Commit 85adbcd5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "This release is mainly a collection of driver specific updates,
  including a few nice cleanups to make drivers use more core features.

   - automatically use the parent device to allocate DMA buffers if
     there wasn't an explicitly configured device.

   - fixes for leaks on allocation.

   - a small piece of the start of SPI slave support, a feature that's
     been on the cards for over a decade!"

* tag 'spi-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (55 commits)
  spi: spi-ti-qspi: Fix error handling
  spi: spi-ti-qspi: Fix error handling
  spi: lantiq-ssc: activate under COMPILE_TEST
  spi: armada-3700: Remove spi_master_put in a3700_spi_remove()
  spi: ti-qspi: revise ti_qspi_probe() failure flow
  spi: spi-ep93xx: simplify GPIO chip selects
  spi: rspi: Replaces "n" by "len" in qspi_transfer_*()
  spi: rspi: Fixes bogus received byte in qspi_transfer_in()
  spi: bcm-qspi: Remove unnecessary platform_set_drvdata()
  spi: bcm-qspi: Fix bcm_qspi_bspi_read() performance
  spi: lantiq-ssc: add support for Lantiq SSC SPI controller
  spi: s3c64xx: fix inconsistency between binding and driver
  spi: armada-3700: Remove .owner field for driver
  spi: bcm-qspi: Added mspi read fallback in bcm_qspi_flash_read()
  spi: fix device-node leaks
  spi: mediatek: Only do dma for 4-byte aligned buffers
  spi: When no dma_chan map buffers with spi_master's parent
  spi: pca2xx-pci: Allow MSI
  spi: pxa2xx: Prepare for edge-triggered interrupts
  spi: pxa2xx: Add support for Intel Gemini Lake
  ...
parents f790bd9c 57f22cd2
Lantiq Synchronous Serial Controller (SSC) SPI master driver
Required properties:
- compatible: "lantiq,ase-spi", "lantiq,falcon-spi", "lantiq,xrx100-spi"
- #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt
- reg: address and length of the spi master registers
- interrupts: should contain the "spi_rx", "spi_tx" and "spi_err" interrupt.
Optional properties:
- clocks: spi clock phandle
- num-cs: see spi-bus.txt, set to 8 if unset
- base-cs: the number of the first chip select, set to 1 if unset.
Example:
spi: spi@E100800 {
compatible = "lantiq,xrx200-spi", "lantiq,xrx100-spi";
reg = <0xE100800 0x100>;
interrupt-parent = <&icu0>;
interrupts = <22 23 24>;
interrupt-names = "spi_rx", "spi_tx", "spi_err";
#address-cells = <1>;
#size-cells = <1>;
num-cs = <6>;
base-cs = <1>;
};
...@@ -31,6 +31,10 @@ Optional Properties: ...@@ -31,6 +31,10 @@ Optional Properties:
- rx-sample-delay-ns: nanoseconds to delay after the SCLK edge before sampling - rx-sample-delay-ns: nanoseconds to delay after the SCLK edge before sampling
Rx data (may need to be fine tuned for high capacitance lines). Rx data (may need to be fine tuned for high capacitance lines).
No delay (0) by default. No delay (0) by default.
- pinctrl-names: Names for the pin configuration(s); may be "default" or
"sleep", where the "sleep" configuration may describe the state
the pins should be in during system suspend. See also
pinctrl/pinctrl-bindings.txt.
Example: Example:
...@@ -46,4 +50,7 @@ Example: ...@@ -46,4 +50,7 @@ Example:
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>; clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
clock-names = "spiclk", "apb_pclk"; clock-names = "spiclk", "apb_pclk";
pinctrl-0 = <&spi1_pins>;
pinctrl-1 = <&spi1_sleep>;
pinctrl-names = "default", "sleep";
}; };
Cirrus EP93xx SPI controller driver HOWTO
=========================================
ep93xx_spi driver brings SPI master support for EP93xx SPI controller. Chip
selects are implemented with GPIO lines.
NOTE: If possible, don't use SFRMOUT (SFRM1) signal as a chip select. It will
not work correctly (it cannot be controlled by software). Use GPIO lines
instead.
Sample configuration
====================
Typically driver configuration is done in platform board files (the files under
arch/arm/mach-ep93xx/*.c). In this example we configure MMC over SPI through
this driver on TS-7260 board. You can adapt the code to suit your needs.
This example uses EGPIO9 as SD/MMC card chip select (this is wired in DIO1
header on the board).
You need to select CONFIG_MMC_SPI to use mmc_spi driver.
arch/arm/mach-ep93xx/ts72xx.c:
...
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/platform_data/spi-ep93xx.h>
/* this is our GPIO line used for chip select */
#define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO9
static int ts72xx_mmc_spi_setup(struct spi_device *spi)
{
int err;
err = gpio_request(MMC_CHIP_SELECT_GPIO, spi->modalias);
if (err)
return err;
gpio_direction_output(MMC_CHIP_SELECT_GPIO, 1);
return 0;
}
static void ts72xx_mmc_spi_cleanup(struct spi_device *spi)
{
gpio_set_value(MMC_CHIP_SELECT_GPIO, 1);
gpio_direction_input(MMC_CHIP_SELECT_GPIO);
gpio_free(MMC_CHIP_SELECT_GPIO);
}
static void ts72xx_mmc_spi_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(MMC_CHIP_SELECT_GPIO, value);
}
static struct ep93xx_spi_chip_ops ts72xx_mmc_spi_ops = {
.setup = ts72xx_mmc_spi_setup,
.cleanup = ts72xx_mmc_spi_cleanup,
.cs_control = ts72xx_mmc_spi_cs_control,
};
static struct spi_board_info ts72xx_spi_devices[] __initdata = {
{
.modalias = "mmc_spi",
.controller_data = &ts72xx_mmc_spi_ops,
/*
* We use 10 MHz even though the maximum is 7.4 MHz. The driver
* will limit it automatically to max. frequency.
*/
.max_speed_hz = 10 * 1000 * 1000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
},
};
static struct ep93xx_spi_info ts72xx_spi_info = {
.num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
};
static void __init ts72xx_init_machine(void)
{
...
ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
ARRAY_SIZE(ts72xx_spi_devices));
}
The driver can use DMA for the transfers also. In this case ts72xx_spi_info
becomes:
static struct ep93xx_spi_info ts72xx_spi_info = {
.num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
.use_dma = true;
};
Note that CONFIG_EP93XX_DMA should be enabled as well.
Thanks to
=========
Martin Guy, H. Hartley Sweeten and others who helped me during development of
the driver. Simplemachines.it donated me a Sim.One board which I used testing
the driver on EP9307.
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -106,33 +105,10 @@ static struct cs4271_platform_data edb93xx_cs4271_data = { ...@@ -106,33 +105,10 @@ static struct cs4271_platform_data edb93xx_cs4271_data = {
.gpio_nreset = -EINVAL, /* filled in later */ .gpio_nreset = -EINVAL, /* filled in later */
}; };
static int edb93xx_cs4271_hw_setup(struct spi_device *spi)
{
return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6,
GPIOF_OUT_INIT_HIGH, spi->modalias);
}
static void edb93xx_cs4271_hw_cleanup(struct spi_device *spi)
{
gpio_free(EP93XX_GPIO_LINE_EGPIO6);
}
static void edb93xx_cs4271_hw_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value);
}
static struct ep93xx_spi_chip_ops edb93xx_cs4271_hw = {
.setup = edb93xx_cs4271_hw_setup,
.cleanup = edb93xx_cs4271_hw_cleanup,
.cs_control = edb93xx_cs4271_hw_cs_control,
};
static struct spi_board_info edb93xx_spi_board_info[] __initdata = { static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
{ {
.modalias = "cs4271", .modalias = "cs4271",
.platform_data = &edb93xx_cs4271_data, .platform_data = &edb93xx_cs4271_data,
.controller_data = &edb93xx_cs4271_hw,
.max_speed_hz = 6000000, .max_speed_hz = 6000000,
.bus_num = 0, .bus_num = 0,
.chip_select = 0, .chip_select = 0,
...@@ -140,8 +116,13 @@ static struct spi_board_info edb93xx_spi_board_info[] __initdata = { ...@@ -140,8 +116,13 @@ static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
}, },
}; };
static int edb93xx_spi_chipselects[] __initdata = {
EP93XX_GPIO_LINE_EGPIO6,
};
static struct ep93xx_spi_info edb93xx_spi_info __initdata = { static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
.num_chipselect = ARRAY_SIZE(edb93xx_spi_board_info), .chipselect = edb93xx_spi_chipselects,
.num_chipselect = ARRAY_SIZE(edb93xx_spi_chipselects),
}; };
static void __init edb93xx_register_spi(void) static void __init edb93xx_register_spi(void)
......
...@@ -48,56 +48,6 @@ static struct ep93xxfb_mach_info __initdata simone_fb_info = { ...@@ -48,56 +48,6 @@ static struct ep93xxfb_mach_info __initdata simone_fb_info = {
*/ */
#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0 #define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0
/*
* Up to v1.3, the Sim.One used SFRMOUT as SD card chip select, but this goes
* low between multi-message command blocks. From v1.4, it uses a GPIO instead.
* v1.3 parts will still work, since the signal on SFRMOUT is automatic.
*/
#define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO1
/*
* MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal,
* you can leave these empty and pass NULL as .controller_data.
*/
static int simone_mmc_spi_setup(struct spi_device *spi)
{
unsigned int gpio = MMC_CHIP_SELECT_GPIO;
int err;
err = gpio_request(gpio, spi->modalias);
if (err)
return err;
err = gpio_direction_output(gpio, 1);
if (err) {
gpio_free(gpio);
return err;
}
return 0;
}
static void simone_mmc_spi_cleanup(struct spi_device *spi)
{
unsigned int gpio = MMC_CHIP_SELECT_GPIO;
gpio_set_value(gpio, 1);
gpio_direction_input(gpio);
gpio_free(gpio);
}
static void simone_mmc_spi_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(MMC_CHIP_SELECT_GPIO, value);
}
static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = {
.setup = simone_mmc_spi_setup,
.cleanup = simone_mmc_spi_cleanup,
.cs_control = simone_mmc_spi_cs_control,
};
/* /*
* MMC card detection GPIO setup. * MMC card detection GPIO setup.
*/ */
...@@ -152,7 +102,6 @@ static struct mmc_spi_platform_data simone_mmc_spi_data = { ...@@ -152,7 +102,6 @@ static struct mmc_spi_platform_data simone_mmc_spi_data = {
static struct spi_board_info simone_spi_devices[] __initdata = { static struct spi_board_info simone_spi_devices[] __initdata = {
{ {
.modalias = "mmc_spi", .modalias = "mmc_spi",
.controller_data = &simone_mmc_spi_ops,
.platform_data = &simone_mmc_spi_data, .platform_data = &simone_mmc_spi_data,
/* /*
* We use 10 MHz even though the maximum is 3.7 MHz. The driver * We use 10 MHz even though the maximum is 3.7 MHz. The driver
...@@ -165,8 +114,18 @@ static struct spi_board_info simone_spi_devices[] __initdata = { ...@@ -165,8 +114,18 @@ static struct spi_board_info simone_spi_devices[] __initdata = {
}, },
}; };
/*
* Up to v1.3, the Sim.One used SFRMOUT as SD card chip select, but this goes
* low between multi-message command blocks. From v1.4, it uses a GPIO instead.
* v1.3 parts will still work, since the signal on SFRMOUT is automatic.
*/
static int simone_spi_chipselects[] __initdata = {
EP93XX_GPIO_LINE_EGPIO1,
};
static struct ep93xx_spi_info simone_spi_info __initdata = { static struct ep93xx_spi_info simone_spi_info __initdata = {
.num_chipselect = ARRAY_SIZE(simone_spi_devices), .chipselect = simone_spi_chipselects,
.num_chipselect = ARRAY_SIZE(simone_spi_chipselects),
.use_dma = 1, .use_dma = 1,
}; };
......
...@@ -175,33 +175,9 @@ static struct cs4271_platform_data vision_cs4271_data = { ...@@ -175,33 +175,9 @@ static struct cs4271_platform_data vision_cs4271_data = {
.gpio_nreset = EP93XX_GPIO_LINE_H(2), .gpio_nreset = EP93XX_GPIO_LINE_H(2),
}; };
static int vision_cs4271_hw_setup(struct spi_device *spi)
{
return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6,
GPIOF_OUT_INIT_HIGH, spi->modalias);
}
static void vision_cs4271_hw_cleanup(struct spi_device *spi)
{
gpio_free(EP93XX_GPIO_LINE_EGPIO6);
}
static void vision_cs4271_hw_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value);
}
static struct ep93xx_spi_chip_ops vision_cs4271_hw = {
.setup = vision_cs4271_hw_setup,
.cleanup = vision_cs4271_hw_cleanup,
.cs_control = vision_cs4271_hw_cs_control,
};
/************************************************************************* /*************************************************************************
* SPI Flash * SPI Flash
*************************************************************************/ *************************************************************************/
#define VISION_SPI_FLASH_CS EP93XX_GPIO_LINE_EGPIO7
static struct mtd_partition vision_spi_flash_partitions[] = { static struct mtd_partition vision_spi_flash_partitions[] = {
{ {
.name = "SPI bootstrap", .name = "SPI bootstrap",
...@@ -224,68 +200,20 @@ static struct flash_platform_data vision_spi_flash_data = { ...@@ -224,68 +200,20 @@ static struct flash_platform_data vision_spi_flash_data = {
.nr_parts = ARRAY_SIZE(vision_spi_flash_partitions), .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
}; };
static int vision_spi_flash_hw_setup(struct spi_device *spi)
{
return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
spi->modalias);
}
static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
{
gpio_free(VISION_SPI_FLASH_CS);
}
static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(VISION_SPI_FLASH_CS, value);
}
static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
.setup = vision_spi_flash_hw_setup,
.cleanup = vision_spi_flash_hw_cleanup,
.cs_control = vision_spi_flash_hw_cs_control,
};
/************************************************************************* /*************************************************************************
* SPI SD/MMC host * SPI SD/MMC host
*************************************************************************/ *************************************************************************/
#define VISION_SPI_MMC_CS EP93XX_GPIO_LINE_G(2)
#define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0)
#define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15
static struct mmc_spi_platform_data vision_spi_mmc_data = { static struct mmc_spi_platform_data vision_spi_mmc_data = {
.detect_delay = 100, .detect_delay = 100,
.powerup_msecs = 100, .powerup_msecs = 100,
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO, .flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
.cd_gpio = VISION_SPI_MMC_CD, .cd_gpio = EP93XX_GPIO_LINE_EGPIO15,
.cd_debounce = 1, .cd_debounce = 1,
.ro_gpio = VISION_SPI_MMC_WP, .ro_gpio = EP93XX_GPIO_LINE_F(0),
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH, .caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
}; };
static int vision_spi_mmc_hw_setup(struct spi_device *spi)
{
return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
spi->modalias);
}
static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
{
gpio_free(VISION_SPI_MMC_CS);
}
static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
{
gpio_set_value(VISION_SPI_MMC_CS, value);
}
static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
.setup = vision_spi_mmc_hw_setup,
.cleanup = vision_spi_mmc_hw_cleanup,
.cs_control = vision_spi_mmc_hw_cs_control,
};
/************************************************************************* /*************************************************************************
* SPI Bus * SPI Bus
*************************************************************************/ *************************************************************************/
...@@ -293,7 +221,6 @@ static struct spi_board_info vision_spi_board_info[] __initdata = { ...@@ -293,7 +221,6 @@ static struct spi_board_info vision_spi_board_info[] __initdata = {
{ {
.modalias = "cs4271", .modalias = "cs4271",
.platform_data = &vision_cs4271_data, .platform_data = &vision_cs4271_data,
.controller_data = &vision_cs4271_hw,
.max_speed_hz = 6000000, .max_speed_hz = 6000000,
.bus_num = 0, .bus_num = 0,
.chip_select = 0, .chip_select = 0,
...@@ -301,7 +228,6 @@ static struct spi_board_info vision_spi_board_info[] __initdata = { ...@@ -301,7 +228,6 @@ static struct spi_board_info vision_spi_board_info[] __initdata = {
}, { }, {
.modalias = "sst25l", .modalias = "sst25l",
.platform_data = &vision_spi_flash_data, .platform_data = &vision_spi_flash_data,
.controller_data = &vision_spi_flash_hw,
.max_speed_hz = 20000000, .max_speed_hz = 20000000,
.bus_num = 0, .bus_num = 0,
.chip_select = 1, .chip_select = 1,
...@@ -309,7 +235,6 @@ static struct spi_board_info vision_spi_board_info[] __initdata = { ...@@ -309,7 +235,6 @@ static struct spi_board_info vision_spi_board_info[] __initdata = {
}, { }, {
.modalias = "mmc_spi", .modalias = "mmc_spi",
.platform_data = &vision_spi_mmc_data, .platform_data = &vision_spi_mmc_data,
.controller_data = &vision_spi_mmc_hw,
.max_speed_hz = 20000000, .max_speed_hz = 20000000,
.bus_num = 0, .bus_num = 0,
.chip_select = 2, .chip_select = 2,
...@@ -317,8 +242,15 @@ static struct spi_board_info vision_spi_board_info[] __initdata = { ...@@ -317,8 +242,15 @@ static struct spi_board_info vision_spi_board_info[] __initdata = {
}, },
}; };
static int vision_spi_chipselects[] __initdata = {
EP93XX_GPIO_LINE_EGPIO6,
EP93XX_GPIO_LINE_EGPIO7,
EP93XX_GPIO_LINE_G(2),
};
static struct ep93xx_spi_info vision_spi_master __initdata = { static struct ep93xx_spi_info vision_spi_master __initdata = {
.num_chipselect = ARRAY_SIZE(vision_spi_board_info), .chipselect = vision_spi_chipselects,
.num_chipselect = ARRAY_SIZE(vision_spi_chipselects),
.use_dma = 1, .use_dma = 1,
}; };
......
...@@ -162,7 +162,8 @@ config SPI_BCM63XX_HSSPI ...@@ -162,7 +162,8 @@ config SPI_BCM63XX_HSSPI
config SPI_BCM_QSPI config SPI_BCM_QSPI
tristate "Broadcom BSPI and MSPI controller support" tristate "Broadcom BSPI and MSPI controller support"
depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || COMPILE_TEST depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || \
BMIPS_GENERIC || COMPILE_TEST
default ARCH_BCM_IPROC default ARCH_BCM_IPROC
help help
Enables support for the Broadcom SPI flash and MSPI controller. Enables support for the Broadcom SPI flash and MSPI controller.
...@@ -263,7 +264,7 @@ config SPI_EP93XX ...@@ -263,7 +264,7 @@ config SPI_EP93XX
mode. mode.
config SPI_FALCON config SPI_FALCON
tristate "Falcon SPI controller support" bool "Falcon SPI controller support"
depends on SOC_FALCON depends on SOC_FALCON
help help
The external bus unit (EBU) found on the FALC-ON SoC has SPI The external bus unit (EBU) found on the FALC-ON SoC has SPI
...@@ -416,6 +417,14 @@ config SPI_NUC900 ...@@ -416,6 +417,14 @@ config SPI_NUC900
help help
SPI driver for Nuvoton NUC900 series ARM SoCs SPI driver for Nuvoton NUC900 series ARM SoCs
config SPI_LANTIQ_SSC
tristate "Lantiq SSC SPI controller"
depends on LANTIQ || COMPILE_TEST
help
This driver supports the Lantiq SSC SPI controller in master
mode. This controller is found on Intel (former Lantiq) SoCs like
the Danube, Falcon, xRX200, xRX300.
config SPI_OC_TINY config SPI_OC_TINY
tristate "OpenCores tiny SPI" tristate "OpenCores tiny SPI"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
......
...@@ -49,6 +49,7 @@ obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o ...@@ -49,6 +49,7 @@ obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
obj-$(CONFIG_SPI_IMX) += spi-imx.o obj-$(CONFIG_SPI_IMX) += spi-imx.o
obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
obj-$(CONFIG_SPI_JCORE) += spi-jcore.o obj-$(CONFIG_SPI_JCORE) += spi-jcore.o
obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
......
...@@ -170,12 +170,12 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, ...@@ -170,12 +170,12 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
val &= ~(A3700_SPI_DATA_PIN0 | A3700_SPI_DATA_PIN1); val &= ~(A3700_SPI_DATA_PIN0 | A3700_SPI_DATA_PIN1);
switch (pin_mode) { switch (pin_mode) {
case 1: case SPI_NBITS_SINGLE:
break; break;
case 2: case SPI_NBITS_DUAL:
val |= A3700_SPI_DATA_PIN0; val |= A3700_SPI_DATA_PIN0;
break; break;
case 4: case SPI_NBITS_QUAD:
val |= A3700_SPI_DATA_PIN1; val |= A3700_SPI_DATA_PIN1;
break; break;
default: default:
...@@ -340,7 +340,6 @@ static irqreturn_t a3700_spi_interrupt(int irq, void *dev_id) ...@@ -340,7 +340,6 @@ static irqreturn_t a3700_spi_interrupt(int irq, void *dev_id)
spireg_write(a3700_spi, A3700_SPI_INT_STAT_REG, cause); spireg_write(a3700_spi, A3700_SPI_INT_STAT_REG, cause);
/* Wake up the transfer */ /* Wake up the transfer */
if (a3700_spi->wait_mask & cause)
complete(&a3700_spi->done); complete(&a3700_spi->done);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -562,6 +561,7 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi) ...@@ -562,6 +561,7 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi)
val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG);
if (a3700_spi->buf_len >= 4) { if (a3700_spi->buf_len >= 4) {
u32 data = le32_to_cpu(val); u32 data = le32_to_cpu(val);
memcpy(a3700_spi->rx_buf, &data, 4); memcpy(a3700_spi->rx_buf, &data, 4);
a3700_spi->buf_len -= 4; a3700_spi->buf_len -= 4;
...@@ -901,7 +901,6 @@ static int a3700_spi_remove(struct platform_device *pdev) ...@@ -901,7 +901,6 @@ static int a3700_spi_remove(struct platform_device *pdev)
struct a3700_spi *spi = spi_master_get_devdata(master); struct a3700_spi *spi = spi_master_get_devdata(master);
clk_unprepare(spi->clk); clk_unprepare(spi->clk);
spi_master_put(master);
return 0; return 0;
} }
...@@ -909,7 +908,6 @@ static int a3700_spi_remove(struct platform_device *pdev) ...@@ -909,7 +908,6 @@ static int a3700_spi_remove(struct platform_device *pdev)
static struct platform_driver a3700_spi_driver = { static struct platform_driver a3700_spi_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(a3700_spi_dt_ids), .of_match_table = of_match_ptr(a3700_spi_dt_ids),
}, },
.probe = a3700_spi_probe, .probe = a3700_spi_probe,
......
...@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) ...@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
if (spi->chip_select) { if (gpio_is_valid(spi->cs_gpio)) {
/* SPI is normally active-low */ /* SPI is normally active-low */
gpio_set_value(spi->cs_gpio, cs_high); gpio_set_value_cansleep(spi->cs_gpio, cs_high);
} else { } else {
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (cs_high) if (cs_high)
sp->ioc_base |= AR71XX_SPI_IOC_CS0; sp->ioc_base |= cs_bit;
else else
sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; sp->ioc_base &= ~cs_bit;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
...@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi *sp = ath79_spidev_to_sp(spi);
int status; int status;
if (spi->chip_select && !gpio_is_valid(spi->cs_gpio))
return -EINVAL;
status = 0; status = 0;
if (spi->chip_select) { if (gpio_is_valid(spi->cs_gpio)) {
unsigned long flags; unsigned long flags;
flags = GPIOF_DIR_OUT; flags = GPIOF_DIR_OUT;
...@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
status = gpio_request_one(spi->cs_gpio, flags, status = gpio_request_one(spi->cs_gpio, flags,
dev_name(&spi->dev)); dev_name(&spi->dev));
} else { } else {
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (spi->mode & SPI_CS_HIGH) if (spi->mode & SPI_CS_HIGH)
sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; sp->ioc_base &= ~cs_bit;
else else
sp->ioc_base |= AR71XX_SPI_IOC_CS0; sp->ioc_base |= cs_bit;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
...@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
static void ath79_spi_cleanup_cs(struct spi_device *spi) static void ath79_spi_cleanup_cs(struct spi_device *spi)
{ {
if (spi->chip_select) { if (gpio_is_valid(spi->cs_gpio)) {
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
} }
} }
......
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
#define BSPI_BPP_MODE_SELECT_MASK BIT(8) #define BSPI_BPP_MODE_SELECT_MASK BIT(8)
#define BSPI_BPP_ADDR_SELECT_MASK BIT(16) #define BSPI_BPP_ADDR_SELECT_MASK BIT(16)
#define BSPI_READ_LENGTH 256 #define BSPI_READ_LENGTH 512
/* MSPI register offsets */ /* MSPI register offsets */
#define MSPI_SPCR0_LSB 0x000 #define MSPI_SPCR0_LSB 0x000
...@@ -192,9 +192,11 @@ struct bcm_qspi_dev_id { ...@@ -192,9 +192,11 @@ struct bcm_qspi_dev_id {
void *dev; void *dev;
}; };
struct qspi_trans { struct qspi_trans {
struct spi_transfer *trans; struct spi_transfer *trans;
int byte; int byte;
bool mspi_last_trans;
}; };
struct bcm_qspi { struct bcm_qspi {
...@@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi) ...@@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi)
return 0; return 0;
} }
static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi,
struct qspi_trans *qt)
{
if (qt->mspi_last_trans &&
spi_transfer_is_last(qspi->master, qt->trans))
return true;
else
return false;
}
static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
struct qspi_trans *qt, int flags) struct qspi_trans *qt, int flags)
{ {
...@@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, ...@@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
if (qt->byte >= qt->trans->len) { if (qt->byte >= qt->trans->len) {
/* we're at the end of the spi_transfer */ /* we're at the end of the spi_transfer */
/* in TX mode, need to pause for a delay or CS change */ /* in TX mode, need to pause for a delay or CS change */
if (qt->trans->delay_usecs && if (qt->trans->delay_usecs &&
(flags & TRANS_STATUS_BREAK_DELAY)) (flags & TRANS_STATUS_BREAK_DELAY))
...@@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, ...@@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
goto done; goto done;
dev_dbg(&qspi->pdev->dev, "advance msg exit\n"); dev_dbg(&qspi->pdev->dev, "advance msg exit\n");
if (spi_transfer_is_last(qspi->master, qt->trans)) if (bcm_qspi_mspi_transfer_is_last(qspi, qt))
ret = TRANS_STATUS_BREAK_EOM; ret = TRANS_STATUS_BREAK_EOM;
else else
ret = TRANS_STATUS_BREAK_NO_BYTES; ret = TRANS_STATUS_BREAK_NO_BYTES;
...@@ -813,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -813,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
struct spi_flash_read_message *msg) struct spi_flash_read_message *msg)
{ {
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
u32 addr = 0, len, len_words; u32 addr = 0, len, rdlen, len_words;
int ret = 0; int ret = 0;
unsigned long timeo = msecs_to_jiffies(100); unsigned long timeo = msecs_to_jiffies(100);
struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
...@@ -826,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -826,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);
/* /*
* when using flex mode mode we need to send * when using flex mode we need to send
* the upper address byte to bspi * the upper address byte to bspi
*/ */
if (bcm_qspi_bspi_ver_three(qspi) == false) { if (bcm_qspi_bspi_ver_three(qspi) == false) {
...@@ -840,27 +851,33 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -840,27 +851,33 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
else else
addr = msg->from & 0x00ffffff; addr = msg->from & 0x00ffffff;
/* set BSPI RAF buffer max read length */
len = msg->len;
if (len > BSPI_READ_LENGTH)
len = BSPI_READ_LENGTH;
if (bcm_qspi_bspi_ver_three(qspi) == true) if (bcm_qspi_bspi_ver_three(qspi) == true)
addr = (addr + 0xc00000) & 0xffffff; addr = (addr + 0xc00000) & 0xffffff;
/*
* read into the entire buffer by breaking the reads
* into RAF buffer read lengths
*/
len = msg->len;
qspi->bspi_rf_msg_idx = 0;
do {
if (len > BSPI_READ_LENGTH)
rdlen = BSPI_READ_LENGTH;
else
rdlen = len;
reinit_completion(&qspi->bspi_done); reinit_completion(&qspi->bspi_done);
bcm_qspi_enable_bspi(qspi); bcm_qspi_enable_bspi(qspi);
len_words = (len + 3) >> 2; len_words = (rdlen + 3) >> 2;
qspi->bspi_rf_msg = msg; qspi->bspi_rf_msg = msg;
qspi->bspi_rf_msg_status = 0; qspi->bspi_rf_msg_status = 0;
qspi->bspi_rf_msg_idx = 0; qspi->bspi_rf_msg_len = rdlen;
qspi->bspi_rf_msg_len = len; dev_dbg(&qspi->pdev->dev,
dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len); "bspi xfr addr 0x%x len 0x%x", addr, rdlen);
bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
if (qspi->soc_intc) { if (qspi->soc_intc) {
/* /*
* clear soc MSPI and BSPI interrupts and enable * clear soc MSPI and BSPI interrupts and enable
...@@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
/* Must flush previous writes before starting BSPI operation */ /* Must flush previous writes before starting BSPI operation */
mb(); mb();
bcm_qspi_bspi_lr_start(qspi); bcm_qspi_bspi_lr_start(qspi);
if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} else { break;
/* set the return length for the caller */
msg->retlen = len;
} }
/* set msg return length */
msg->retlen += rdlen;
addr += rdlen;
len -= rdlen;
} while (len);
return ret;
}
static int bcm_qspi_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *trans)
{
struct bcm_qspi *qspi = spi_master_get_devdata(master);
int slots;
unsigned long timeo = msecs_to_jiffies(100);
bcm_qspi_chip_select(qspi, spi->chip_select);
qspi->trans_pos.trans = trans;
qspi->trans_pos.byte = 0;
while (qspi->trans_pos.byte < trans->len) {
reinit_completion(&qspi->mspi_done);
slots = write_to_hw(qspi, spi);
if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
return -ETIMEDOUT;
}
read_from_hw(qspi, slots);
}
return 0;
}
static int bcm_qspi_mspi_flash_read(struct spi_device *spi,
struct spi_flash_read_message *msg)
{
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
struct spi_transfer t[2];
u8 cmd[6];
int ret;
memset(cmd, 0, sizeof(cmd));
memset(t, 0, sizeof(t));
/* tx */
/* opcode is in cmd[0] */
cmd[0] = msg->read_opcode;
cmd[1] = msg->from >> (msg->addr_width * 8 - 8);
cmd[2] = msg->from >> (msg->addr_width * 8 - 16);
cmd[3] = msg->from >> (msg->addr_width * 8 - 24);
cmd[4] = msg->from >> (msg->addr_width * 8 - 32);
t[0].tx_buf = cmd;
t[0].len = msg->addr_width + msg->dummy_bytes + 1;
t[0].bits_per_word = spi->bits_per_word;
t[0].tx_nbits = msg->opcode_nbits;
/* lets mspi know that this is not last transfer */
qspi->trans_pos.mspi_last_trans = false;
ret = bcm_qspi_transfer_one(spi->master, spi, &t[0]);
/* rx */
qspi->trans_pos.mspi_last_trans = true;
if (!ret) {
/* rx */
t[1].rx_buf = msg->buf;
t[1].len = msg->len;
t[1].rx_nbits = msg->data_nbits;
t[1].bits_per_word = spi->bits_per_word;
ret = bcm_qspi_transfer_one(spi->master, spi, &t[1]);
}
if (!ret)
msg->retlen = msg->len;
return ret; return ret;
} }
...@@ -918,8 +1008,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi, ...@@ -918,8 +1008,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
mspi_read = true; mspi_read = true;
if (mspi_read) if (mspi_read)
/* this will make the m25p80 read to fallback to mspi read */ return bcm_qspi_mspi_flash_read(spi, msg);
return -EAGAIN;
io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
addrlen = msg->addr_width; addrlen = msg->addr_width;
...@@ -931,33 +1020,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi, ...@@ -931,33 +1020,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
return ret; return ret;
} }
static int bcm_qspi_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *trans)
{
struct bcm_qspi *qspi = spi_master_get_devdata(master);
int slots;
unsigned long timeo = msecs_to_jiffies(100);
bcm_qspi_chip_select(qspi, spi->chip_select);
qspi->trans_pos.trans = trans;
qspi->trans_pos.byte = 0;
while (qspi->trans_pos.byte < trans->len) {
reinit_completion(&qspi->mspi_done);
slots = write_to_hw(qspi, spi);
if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
return -ETIMEDOUT;
}
read_from_hw(qspi, slots);
}
return 0;
}
static void bcm_qspi_cleanup(struct spi_device *spi) static void bcm_qspi_cleanup(struct spi_device *spi)
{ {
struct bcm_qspi_parms *xp = spi_get_ctldata(spi); struct bcm_qspi_parms *xp = spi_get_ctldata(spi);
...@@ -1187,6 +1249,7 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1187,6 +1249,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
qspi->pdev = pdev; qspi->pdev = pdev;
qspi->trans_pos.trans = NULL; qspi->trans_pos.trans = NULL;
qspi->trans_pos.byte = 0; qspi->trans_pos.byte = 0;
qspi->trans_pos.mspi_last_trans = true;
qspi->master = master; qspi->master = master;
master->bus_num = -1; master->bus_num = -1;
...@@ -1345,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev) ...@@ -1345,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev)
{ {
struct bcm_qspi *qspi = platform_get_drvdata(pdev); struct bcm_qspi *qspi = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
bcm_qspi_hw_uninit(qspi); bcm_qspi_hw_uninit(qspi);
clk_disable_unprepare(qspi->clk); clk_disable_unprepare(qspi->clk);
kfree(qspi->dev_ids); kfree(qspi->dev_ids);
......
/*
* Copyright (C) 2014-2016 Rafał Miłecki <rafal@milecki.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -275,10 +283,6 @@ static int bcm53xxspi_flash_read(struct spi_device *spi, ...@@ -275,10 +283,6 @@ static int bcm53xxspi_flash_read(struct spi_device *spi,
* BCMA * BCMA
**************************************************/ **************************************************/
static struct spi_board_info bcm53xx_info = {
.modalias = "bcm53xxspiflash",
};
static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS),
{}, {},
...@@ -311,6 +315,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) ...@@ -311,6 +315,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
b53spi->bspi = true; b53spi->bspi = true;
bcm53xxspi_disable_bspi(b53spi); bcm53xxspi_disable_bspi(b53spi);
master->dev.of_node = dev->of_node;
master->transfer_one = bcm53xxspi_transfer_one; master->transfer_one = bcm53xxspi_transfer_one;
if (b53spi->mmio_base) if (b53spi->mmio_base)
master->spi_flash_read = bcm53xxspi_flash_read; master->spi_flash_read = bcm53xxspi_flash_read;
...@@ -324,9 +329,6 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) ...@@ -324,9 +329,6 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
return err; return err;
} }
/* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
spi_new_device(master, &bcm53xx_info);
return 0; return 0;
} }
...@@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit); ...@@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit);
MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver"); MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver");
MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>"); MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -107,9 +107,9 @@ static const struct file_operations dw_spi_regs_ops = { ...@@ -107,9 +107,9 @@ static const struct file_operations dw_spi_regs_ops = {
static int dw_spi_debugfs_init(struct dw_spi *dws) static int dw_spi_debugfs_init(struct dw_spi *dws)
{ {
char name[128]; char name[32];
snprintf(name, 128, "dw_spi-%s", dev_name(&dws->master->dev)); snprintf(name, 32, "dw_spi%d", dws->master->bus_num);
dws->debugfs = debugfs_create_dir(name, NULL); dws->debugfs = debugfs_create_dir(name, NULL);
if (!dws->debugfs) if (!dws->debugfs)
return -ENOMEM; return -ENOMEM;
...@@ -486,9 +486,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -486,9 +486,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
dws->type = SSI_MOTO_SPI; dws->type = SSI_MOTO_SPI;
dws->dma_inited = 0; dws->dma_inited = 0;
dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR); dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, master); ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
master);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "can not get IRQ\n"); dev_err(dev, "can not get IRQ\n");
goto err_free_master; goto err_free_master;
......
...@@ -101,7 +101,6 @@ struct dw_spi_dma_ops { ...@@ -101,7 +101,6 @@ struct dw_spi_dma_ops {
struct dw_spi { struct dw_spi {
struct spi_master *master; struct spi_master *master;
enum dw_ssi_type type; enum dw_ssi_type type;
char name[16];
void __iomem *regs; void __iomem *regs;
unsigned long paddr; unsigned long paddr;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/platform_data/dma-ep93xx.h> #include <linux/platform_data/dma-ep93xx.h>
...@@ -107,16 +108,6 @@ struct ep93xx_spi { ...@@ -107,16 +108,6 @@ struct ep93xx_spi {
void *zeropage; void *zeropage;
}; };
/**
* struct ep93xx_spi_chip - SPI device hardware settings
* @spi: back pointer to the SPI device
* @ops: private chip operations
*/
struct ep93xx_spi_chip {
const struct spi_device *spi;
struct ep93xx_spi_chip_ops *ops;
};
/* converts bits per word to CR0.DSS value */ /* converts bits per word to CR0.DSS value */
#define bits_per_word_to_dss(bpw) ((bpw) - 1) #define bits_per_word_to_dss(bpw) ((bpw) - 1)
...@@ -229,104 +220,36 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, ...@@ -229,104 +220,36 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
return -EINVAL; return -EINVAL;
} }
static void ep93xx_spi_cs_control(struct spi_device *spi, bool control) static void ep93xx_spi_cs_control(struct spi_device *spi, bool enable)
{
struct ep93xx_spi_chip *chip = spi_get_ctldata(spi);
int value = (spi->mode & SPI_CS_HIGH) ? control : !control;
if (chip->ops && chip->ops->cs_control)
chip->ops->cs_control(spi, value);
}
/**
* ep93xx_spi_setup() - setup an SPI device
* @spi: SPI device to setup
*
* This function sets up SPI device mode, speed etc. Can be called multiple
* times for a single device. Returns %0 in case of success, negative error in
* case of failure. When this function returns success, the device is
* deselected.
*/
static int ep93xx_spi_setup(struct spi_device *spi)
{
struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
struct ep93xx_spi_chip *chip;
chip = spi_get_ctldata(spi);
if (!chip) {
dev_dbg(&espi->pdev->dev, "initial setup for %s\n",
spi->modalias);
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
chip->spi = spi;
chip->ops = spi->controller_data;
if (chip->ops && chip->ops->setup) {
int ret = chip->ops->setup(spi);
if (ret) {
kfree(chip);
return ret;
}
}
spi_set_ctldata(spi, chip);
}
ep93xx_spi_cs_control(spi, false);
return 0;
}
/**
* ep93xx_spi_cleanup() - cleans up master controller specific state
* @spi: SPI device to cleanup
*
* This function releases master controller specific state for given @spi
* device.
*/
static void ep93xx_spi_cleanup(struct spi_device *spi)
{ {
struct ep93xx_spi_chip *chip; if (spi->mode & SPI_CS_HIGH)
enable = !enable;
chip = spi_get_ctldata(spi); if (gpio_is_valid(spi->cs_gpio))
if (chip) { gpio_set_value(spi->cs_gpio, !enable);
if (chip->ops && chip->ops->cleanup)
chip->ops->cleanup(spi);
spi_set_ctldata(spi, NULL);
kfree(chip);
}
} }
/**
* ep93xx_spi_chip_setup() - configures hardware according to given @chip
* @espi: ep93xx SPI controller struct
* @chip: chip specific settings
* @speed_hz: transfer speed
* @bits_per_word: transfer bits_per_word
*/
static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
const struct ep93xx_spi_chip *chip, struct spi_device *spi,
u32 speed_hz, u8 bits_per_word) struct spi_transfer *xfer)
{ {
u8 dss = bits_per_word_to_dss(bits_per_word); u8 dss = bits_per_word_to_dss(xfer->bits_per_word);
u8 div_cpsr = 0; u8 div_cpsr = 0;
u8 div_scr = 0; u8 div_scr = 0;
u16 cr0; u16 cr0;
int err; int err;
err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr); err = ep93xx_spi_calc_divisors(espi, xfer->speed_hz,
&div_cpsr, &div_scr);
if (err) if (err)
return err; return err;
cr0 = div_scr << SSPCR0_SCR_SHIFT; cr0 = div_scr << SSPCR0_SCR_SHIFT;
cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; cr0 |= (spi->mode & (SPI_CPHA | SPI_CPOL)) << SSPCR0_MODE_SHIFT;
cr0 |= dss; cr0 |= dss;
dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
chip->spi->mode, div_cpsr, div_scr, dss); spi->mode, div_cpsr, div_scr, dss);
dev_dbg(&espi->pdev->dev, "setup: cr0 %#x\n", cr0); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x\n", cr0);
ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr); ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr);
...@@ -603,12 +526,11 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, ...@@ -603,12 +526,11 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
struct spi_message *msg, struct spi_message *msg,
struct spi_transfer *t) struct spi_transfer *t)
{ {
struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
int err; int err;
msg->state = t; msg->state = t;
err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word); err = ep93xx_spi_chip_setup(espi, msg->spi, t);
if (err) { if (err) {
dev_err(&espi->pdev->dev, dev_err(&espi->pdev->dev,
"failed to setup chip for transfer\n"); "failed to setup chip for transfer\n");
...@@ -863,8 +785,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev) ...@@ -863,8 +785,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int irq; int irq;
int error; int error;
int i;
info = dev_get_platdata(&pdev->dev); info = dev_get_platdata(&pdev->dev);
if (!info) {
dev_err(&pdev->dev, "missing platform data\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
...@@ -882,14 +809,36 @@ static int ep93xx_spi_probe(struct platform_device *pdev) ...@@ -882,14 +809,36 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
master->setup = ep93xx_spi_setup;
master->transfer_one_message = ep93xx_spi_transfer_one_message; master->transfer_one_message = ep93xx_spi_transfer_one_message;
master->cleanup = ep93xx_spi_cleanup;
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = info->num_chipselect;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->num_chipselect = info->num_chipselect;
master->cs_gpios = devm_kzalloc(&master->dev,
sizeof(int) * master->num_chipselect,
GFP_KERNEL);
if (!master->cs_gpios) {
error = -ENOMEM;
goto fail_release_master;
}
for (i = 0; i < master->num_chipselect; i++) {
master->cs_gpios[i] = info->chipselect[i];
if (!gpio_is_valid(master->cs_gpios[i]))
continue;
error = devm_gpio_request_one(&pdev->dev, master->cs_gpios[i],
GPIOF_OUT_INIT_HIGH,
"ep93xx-spi");
if (error) {
dev_err(&pdev->dev, "could not request cs gpio %d\n",
master->cs_gpios[i]);
goto fail_release_master;
}
}
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
espi = spi_master_get_devdata(master); espi = spi_master_get_devdata(master);
......
...@@ -366,7 +366,7 @@ static int fsl_lpspi_transfer_one_msg(struct spi_master *master, ...@@ -366,7 +366,7 @@ static int fsl_lpspi_transfer_one_msg(struct spi_master *master,
struct spi_transfer *xfer; struct spi_transfer *xfer;
bool is_first_xfer = true; bool is_first_xfer = true;
u32 temp; u32 temp;
int ret; int ret = 0;
msg->status = 0; msg->status = 0;
msg->actual_length = 0; msg->actual_length = 0;
......
...@@ -267,10 +267,9 @@ static int fsl_spi_setup_transfer(struct spi_device *spi, ...@@ -267,10 +267,9 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
if ((mpc8xxx_spi->spibrg / hz) > 64) { if ((mpc8xxx_spi->spibrg / hz) > 64) {
cs->hw_mode |= SPMODE_DIV16; cs->hw_mode |= SPMODE_DIV16;
pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1; pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
WARN_ONCE(pm > 16,
WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. " "%s: Requested speed is too low: %d Hz. Will use %d Hz instead.\n",
"Will use %d Hz instead.\n", dev_name(&spi->dev), dev_name(&spi->dev), hz, mpc8xxx_spi->spibrg / 1024);
hz, mpc8xxx_spi->spibrg / 1024);
if (pm > 16) if (pm > 16)
pm = 16; pm = 16;
} else { } else {
...@@ -727,12 +726,13 @@ static int of_fsl_spi_get_chipselects(struct device *dev) ...@@ -727,12 +726,13 @@ static int of_fsl_spi_get_chipselects(struct device *dev)
return 0; return 0;
} }
pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL); pinfo->gpios = kmalloc_array(ngpios, sizeof(*pinfo->gpios),
GFP_KERNEL);
if (!pinfo->gpios) if (!pinfo->gpios)
return -ENOMEM; return -ENOMEM;
memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios)); memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags), pinfo->alow_flags = kcalloc(ngpios, sizeof(*pinfo->alow_flags),
GFP_KERNEL); GFP_KERNEL);
if (!pinfo->alow_flags) { if (!pinfo->alow_flags) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -762,8 +762,9 @@ static int of_fsl_spi_get_chipselects(struct device *dev) ...@@ -762,8 +762,9 @@ static int of_fsl_spi_get_chipselects(struct device *dev)
ret = gpio_direction_output(pinfo->gpios[i], ret = gpio_direction_output(pinfo->gpios[i],
pinfo->alow_flags[i]); pinfo->alow_flags[i]);
if (ret) { if (ret) {
dev_err(dev, "can't set output direction for gpio " dev_err(dev,
"#%d: %d\n", i, ret); "can't set output direction for gpio #%d: %d\n",
i, ret);
goto err_loop; goto err_loop;
} }
} }
......
...@@ -211,7 +211,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -211,7 +211,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *transfer) struct spi_transfer *transfer)
{ {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master); struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
unsigned int bpw; unsigned int bpw, i;
if (!master->dma_rx) if (!master->dma_rx)
return false; return false;
...@@ -228,12 +228,16 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -228,12 +228,16 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
if (bpw != 1 && bpw != 2 && bpw != 4) if (bpw != 1 && bpw != 2 && bpw != 4)
return false; return false;
if (transfer->len < spi_imx->wml * bpw) for (i = spi_imx_get_fifosize(spi_imx) / 2; i > 0; i--) {
return false; if (!(transfer->len % (i * bpw)))
break;
}
if (transfer->len % (spi_imx->wml * bpw)) if (i == 0)
return false; return false;
spi_imx->wml = i;
return true; return true;
} }
...@@ -837,10 +841,6 @@ static int spi_imx_dma_configure(struct spi_master *master, ...@@ -837,10 +841,6 @@ static int spi_imx_dma_configure(struct spi_master *master,
struct dma_slave_config rx = {}, tx = {}; struct dma_slave_config rx = {}, tx = {};
struct spi_imx_data *spi_imx = spi_master_get_devdata(master); struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
if (bytes_per_word == spi_imx->bytes_per_word)
/* Same as last time */
return 0;
switch (bytes_per_word) { switch (bytes_per_word) {
case 4: case 4:
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
......
/*
* Copyright (C) 2011-2015 Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
* Copyright (C) 2016 Hauke Mehrtens <hauke@hauke-m.de>
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#ifdef CONFIG_LANTIQ
#include <lantiq_soc.h>
#endif
#define SPI_RX_IRQ_NAME "spi_rx"
#define SPI_TX_IRQ_NAME "spi_tx"
#define SPI_ERR_IRQ_NAME "spi_err"
#define SPI_FRM_IRQ_NAME "spi_frm"
#define SPI_CLC 0x00
#define SPI_PISEL 0x04
#define SPI_ID 0x08
#define SPI_CON 0x10
#define SPI_STAT 0x14
#define SPI_WHBSTATE 0x18
#define SPI_TB 0x20
#define SPI_RB 0x24
#define SPI_RXFCON 0x30
#define SPI_TXFCON 0x34
#define SPI_FSTAT 0x38
#define SPI_BRT 0x40
#define SPI_BRSTAT 0x44
#define SPI_SFCON 0x60
#define SPI_SFSTAT 0x64
#define SPI_GPOCON 0x70
#define SPI_GPOSTAT 0x74
#define SPI_FPGO 0x78
#define SPI_RXREQ 0x80
#define SPI_RXCNT 0x84
#define SPI_DMACON 0xec
#define SPI_IRNEN 0xf4
#define SPI_IRNICR 0xf8
#define SPI_IRNCR 0xfc
#define SPI_CLC_SMC_S 16 /* Clock divider for sleep mode */
#define SPI_CLC_SMC_M (0xFF << SPI_CLC_SMC_S)
#define SPI_CLC_RMC_S 8 /* Clock divider for normal run mode */
#define SPI_CLC_RMC_M (0xFF << SPI_CLC_RMC_S)
#define SPI_CLC_DISS BIT(1) /* Disable status bit */
#define SPI_CLC_DISR BIT(0) /* Disable request bit */
#define SPI_ID_TXFS_S 24 /* Implemented TX FIFO size */
#define SPI_ID_TXFS_M (0x3F << SPI_ID_TXFS_S)
#define SPI_ID_RXFS_S 16 /* Implemented RX FIFO size */
#define SPI_ID_RXFS_M (0x3F << SPI_ID_RXFS_S)
#define SPI_ID_MOD_S 8 /* Module ID */
#define SPI_ID_MOD_M (0xff << SPI_ID_MOD_S)
#define SPI_ID_CFG_S 5 /* DMA interface support */
#define SPI_ID_CFG_M (1 << SPI_ID_CFG_S)
#define SPI_ID_REV_M 0x1F /* Hardware revision number */
#define SPI_CON_BM_S 16 /* Data width selection */
#define SPI_CON_BM_M (0x1F << SPI_CON_BM_S)
#define SPI_CON_EM BIT(24) /* Echo mode */
#define SPI_CON_IDLE BIT(23) /* Idle bit value */
#define SPI_CON_ENBV BIT(22) /* Enable byte valid control */
#define SPI_CON_RUEN BIT(12) /* Receive underflow error enable */
#define SPI_CON_TUEN BIT(11) /* Transmit underflow error enable */
#define SPI_CON_AEN BIT(10) /* Abort error enable */
#define SPI_CON_REN BIT(9) /* Receive overflow error enable */
#define SPI_CON_TEN BIT(8) /* Transmit overflow error enable */
#define SPI_CON_LB BIT(7) /* Loopback control */
#define SPI_CON_PO BIT(6) /* Clock polarity control */
#define SPI_CON_PH BIT(5) /* Clock phase control */
#define SPI_CON_HB BIT(4) /* Heading control */
#define SPI_CON_RXOFF BIT(1) /* Switch receiver off */
#define SPI_CON_TXOFF BIT(0) /* Switch transmitter off */
#define SPI_STAT_RXBV_S 28
#define SPI_STAT_RXBV_M (0x7 << SPI_STAT_RXBV_S)
#define SPI_STAT_BSY BIT(13) /* Busy flag */
#define SPI_STAT_RUE BIT(12) /* Receive underflow error flag */
#define SPI_STAT_TUE BIT(11) /* Transmit underflow error flag */
#define SPI_STAT_AE BIT(10) /* Abort error flag */
#define SPI_STAT_RE BIT(9) /* Receive error flag */
#define SPI_STAT_TE BIT(8) /* Transmit error flag */
#define SPI_STAT_ME BIT(7) /* Mode error flag */
#define SPI_STAT_MS BIT(1) /* Master/slave select bit */
#define SPI_STAT_EN BIT(0) /* Enable bit */
#define SPI_STAT_ERRORS (SPI_STAT_ME | SPI_STAT_TE | SPI_STAT_RE | \
SPI_STAT_AE | SPI_STAT_TUE | SPI_STAT_RUE)
#define SPI_WHBSTATE_SETTUE BIT(15) /* Set transmit underflow error flag */
#define SPI_WHBSTATE_SETAE BIT(14) /* Set abort error flag */
#define SPI_WHBSTATE_SETRE BIT(13) /* Set receive error flag */
#define SPI_WHBSTATE_SETTE BIT(12) /* Set transmit error flag */
#define SPI_WHBSTATE_CLRTUE BIT(11) /* Clear transmit underflow error flag */
#define SPI_WHBSTATE_CLRAE BIT(10) /* Clear abort error flag */
#define SPI_WHBSTATE_CLRRE BIT(9) /* Clear receive error flag */
#define SPI_WHBSTATE_CLRTE BIT(8) /* Clear transmit error flag */
#define SPI_WHBSTATE_SETME BIT(7) /* Set mode error flag */
#define SPI_WHBSTATE_CLRME BIT(6) /* Clear mode error flag */
#define SPI_WHBSTATE_SETRUE BIT(5) /* Set receive underflow error flag */
#define SPI_WHBSTATE_CLRRUE BIT(4) /* Clear receive underflow error flag */
#define SPI_WHBSTATE_SETMS BIT(3) /* Set master select bit */
#define SPI_WHBSTATE_CLRMS BIT(2) /* Clear master select bit */
#define SPI_WHBSTATE_SETEN BIT(1) /* Set enable bit (operational mode) */
#define SPI_WHBSTATE_CLREN BIT(0) /* Clear enable bit (config mode */
#define SPI_WHBSTATE_CLR_ERRORS (SPI_WHBSTATE_CLRRUE | SPI_WHBSTATE_CLRME | \
SPI_WHBSTATE_CLRTE | SPI_WHBSTATE_CLRRE | \
SPI_WHBSTATE_CLRAE | SPI_WHBSTATE_CLRTUE)
#define SPI_RXFCON_RXFITL_S 8 /* FIFO interrupt trigger level */
#define SPI_RXFCON_RXFITL_M (0x3F << SPI_RXFCON_RXFITL_S)
#define SPI_RXFCON_RXFLU BIT(1) /* FIFO flush */
#define SPI_RXFCON_RXFEN BIT(0) /* FIFO enable */
#define SPI_TXFCON_TXFITL_S 8 /* FIFO interrupt trigger level */
#define SPI_TXFCON_TXFITL_M (0x3F << SPI_TXFCON_TXFITL_S)
#define SPI_TXFCON_TXFLU BIT(1) /* FIFO flush */
#define SPI_TXFCON_TXFEN BIT(0) /* FIFO enable */
#define SPI_FSTAT_RXFFL_S 0
#define SPI_FSTAT_RXFFL_M (0x3f << SPI_FSTAT_RXFFL_S)
#define SPI_FSTAT_TXFFL_S 8
#define SPI_FSTAT_TXFFL_M (0x3f << SPI_FSTAT_TXFFL_S)
#define SPI_GPOCON_ISCSBN_S 8
#define SPI_GPOCON_INVOUTN_S 0
#define SPI_FGPO_SETOUTN_S 8
#define SPI_FGPO_CLROUTN_S 0
#define SPI_RXREQ_RXCNT_M 0xFFFF /* Receive count value */
#define SPI_RXCNT_TODO_M 0xFFFF /* Recevie to-do value */
#define SPI_IRNEN_TFI BIT(4) /* TX finished interrupt */
#define SPI_IRNEN_F BIT(3) /* Frame end interrupt request */
#define SPI_IRNEN_E BIT(2) /* Error end interrupt request */
#define SPI_IRNEN_T_XWAY BIT(1) /* Transmit end interrupt request */
#define SPI_IRNEN_R_XWAY BIT(0) /* Receive end interrupt request */
#define SPI_IRNEN_R_XRX BIT(1) /* Transmit end interrupt request */
#define SPI_IRNEN_T_XRX BIT(0) /* Receive end interrupt request */
#define SPI_IRNEN_ALL 0x1F
struct lantiq_ssc_hwcfg {
unsigned int irnen_r;
unsigned int irnen_t;
};
struct lantiq_ssc_spi {
struct spi_master *master;
struct device *dev;
void __iomem *regbase;
struct clk *spi_clk;
struct clk *fpi_clk;
const struct lantiq_ssc_hwcfg *hwcfg;
spinlock_t lock;
struct workqueue_struct *wq;
struct work_struct work;
const u8 *tx;
u8 *rx;
unsigned int tx_todo;
unsigned int rx_todo;
unsigned int bits_per_word;
unsigned int speed_hz;
unsigned int tx_fifo_size;
unsigned int rx_fifo_size;
unsigned int base_cs;
};
static u32 lantiq_ssc_readl(const struct lantiq_ssc_spi *spi, u32 reg)
{
return __raw_readl(spi->regbase + reg);
}
static void lantiq_ssc_writel(const struct lantiq_ssc_spi *spi, u32 val,
u32 reg)
{
__raw_writel(val, spi->regbase + reg);
}
static void lantiq_ssc_maskl(const struct lantiq_ssc_spi *spi, u32 clr,
u32 set, u32 reg)
{
u32 val = __raw_readl(spi->regbase + reg);
val &= ~clr;
val |= set;
__raw_writel(val, spi->regbase + reg);
}
static unsigned int tx_fifo_level(const struct lantiq_ssc_spi *spi)
{
u32 fstat = lantiq_ssc_readl(spi, SPI_FSTAT);
return (fstat & SPI_FSTAT_TXFFL_M) >> SPI_FSTAT_TXFFL_S;
}
static unsigned int rx_fifo_level(const struct lantiq_ssc_spi *spi)
{
u32 fstat = lantiq_ssc_readl(spi, SPI_FSTAT);
return fstat & SPI_FSTAT_RXFFL_M;
}
static unsigned int tx_fifo_free(const struct lantiq_ssc_spi *spi)
{
return spi->tx_fifo_size - tx_fifo_level(spi);
}
static void rx_fifo_reset(const struct lantiq_ssc_spi *spi)
{
u32 val = spi->rx_fifo_size << SPI_RXFCON_RXFITL_S;
val |= SPI_RXFCON_RXFEN | SPI_RXFCON_RXFLU;
lantiq_ssc_writel(spi, val, SPI_RXFCON);
}
static void tx_fifo_reset(const struct lantiq_ssc_spi *spi)
{
u32 val = 1 << SPI_TXFCON_TXFITL_S;
val |= SPI_TXFCON_TXFEN | SPI_TXFCON_TXFLU;
lantiq_ssc_writel(spi, val, SPI_TXFCON);
}
static void rx_fifo_flush(const struct lantiq_ssc_spi *spi)
{
lantiq_ssc_maskl(spi, 0, SPI_RXFCON_RXFLU, SPI_RXFCON);
}
static void tx_fifo_flush(const struct lantiq_ssc_spi *spi)
{
lantiq_ssc_maskl(spi, 0, SPI_TXFCON_TXFLU, SPI_TXFCON);
}
static void hw_enter_config_mode(const struct lantiq_ssc_spi *spi)
{
lantiq_ssc_writel(spi, SPI_WHBSTATE_CLREN, SPI_WHBSTATE);
}
static void hw_enter_active_mode(const struct lantiq_ssc_spi *spi)
{
lantiq_ssc_writel(spi, SPI_WHBSTATE_SETEN, SPI_WHBSTATE);
}
static void hw_setup_speed_hz(const struct lantiq_ssc_spi *spi,
unsigned int max_speed_hz)
{
u32 spi_clk, brt;
/*
* SPI module clock is derived from FPI bus clock dependent on
* divider value in CLC.RMS which is always set to 1.
*
* f_SPI
* baudrate = --------------
* 2 * (BR + 1)
*/
spi_clk = clk_get_rate(spi->fpi_clk) / 2;
if (max_speed_hz > spi_clk)
brt = 0;
else
brt = spi_clk / max_speed_hz - 1;
if (brt > 0xFFFF)
brt = 0xFFFF;
dev_dbg(spi->dev, "spi_clk %u, max_speed_hz %u, brt %u\n",
spi_clk, max_speed_hz, brt);
lantiq_ssc_writel(spi, brt, SPI_BRT);
}
static void hw_setup_bits_per_word(const struct lantiq_ssc_spi *spi,
unsigned int bits_per_word)
{
u32 bm;
/* CON.BM value = bits_per_word - 1 */
bm = (bits_per_word - 1) << SPI_CON_BM_S;
lantiq_ssc_maskl(spi, SPI_CON_BM_M, bm, SPI_CON);
}
static void hw_setup_clock_mode(const struct lantiq_ssc_spi *spi,
unsigned int mode)
{
u32 con_set = 0, con_clr = 0;
/*
* SPI mode mapping in CON register:
* Mode CPOL CPHA CON.PO CON.PH
* 0 0 0 0 1
* 1 0 1 0 0
* 2 1 0 1 1
* 3 1 1 1 0
*/
if (mode & SPI_CPHA)
con_clr |= SPI_CON_PH;
else
con_set |= SPI_CON_PH;
if (mode & SPI_CPOL)
con_set |= SPI_CON_PO | SPI_CON_IDLE;
else
con_clr |= SPI_CON_PO | SPI_CON_IDLE;
/* Set heading control */
if (mode & SPI_LSB_FIRST)
con_clr |= SPI_CON_HB;
else
con_set |= SPI_CON_HB;
/* Set loopback mode */
if (mode & SPI_LOOP)
con_set |= SPI_CON_LB;
else
con_clr |= SPI_CON_LB;
lantiq_ssc_maskl(spi, con_clr, con_set, SPI_CON);
}
static void lantiq_ssc_hw_init(const struct lantiq_ssc_spi *spi)
{
const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg;
/*
* Set clock divider for run mode to 1 to
* run at same frequency as FPI bus
*/
lantiq_ssc_writel(spi, 1 << SPI_CLC_RMC_S, SPI_CLC);
/* Put controller into config mode */
hw_enter_config_mode(spi);
/* Clear error flags */
lantiq_ssc_maskl(spi, 0, SPI_WHBSTATE_CLR_ERRORS, SPI_WHBSTATE);
/* Enable error checking, disable TX/RX */
lantiq_ssc_writel(spi, SPI_CON_RUEN | SPI_CON_AEN | SPI_CON_TEN |
SPI_CON_REN | SPI_CON_TXOFF | SPI_CON_RXOFF, SPI_CON);
/* Setup default SPI mode */
hw_setup_bits_per_word(spi, spi->bits_per_word);
hw_setup_clock_mode(spi, SPI_MODE_0);
/* Enable master mode and clear error flags */
lantiq_ssc_writel(spi, SPI_WHBSTATE_SETMS | SPI_WHBSTATE_CLR_ERRORS,
SPI_WHBSTATE);
/* Reset GPIO/CS registers */
lantiq_ssc_writel(spi, 0, SPI_GPOCON);
lantiq_ssc_writel(spi, 0xFF00, SPI_FPGO);
/* Enable and flush FIFOs */
rx_fifo_reset(spi);
tx_fifo_reset(spi);
/* Enable interrupts */
lantiq_ssc_writel(spi, hwcfg->irnen_t | hwcfg->irnen_r | SPI_IRNEN_E,
SPI_IRNEN);
}
static int lantiq_ssc_setup(struct spi_device *spidev)
{
struct spi_master *master = spidev->master;
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
unsigned int cs = spidev->chip_select;
u32 gpocon;
/* GPIOs are used for CS */
if (gpio_is_valid(spidev->cs_gpio))
return 0;
dev_dbg(spi->dev, "using internal chipselect %u\n", cs);
if (cs < spi->base_cs) {
dev_err(spi->dev,
"chipselect %i too small (min %i)\n", cs, spi->base_cs);
return -EINVAL;
}
/* set GPO pin to CS mode */
gpocon = 1 << ((cs - spi->base_cs) + SPI_GPOCON_ISCSBN_S);
/* invert GPO pin */
if (spidev->mode & SPI_CS_HIGH)
gpocon |= 1 << (cs - spi->base_cs);
lantiq_ssc_maskl(spi, 0, gpocon, SPI_GPOCON);
return 0;
}
static int lantiq_ssc_prepare_message(struct spi_master *master,
struct spi_message *message)
{
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
hw_enter_config_mode(spi);
hw_setup_clock_mode(spi, message->spi->mode);
hw_enter_active_mode(spi);
return 0;
}
static void hw_setup_transfer(struct lantiq_ssc_spi *spi,
struct spi_device *spidev, struct spi_transfer *t)
{
unsigned int speed_hz = t->speed_hz;
unsigned int bits_per_word = t->bits_per_word;
u32 con;
if (bits_per_word != spi->bits_per_word ||
speed_hz != spi->speed_hz) {
hw_enter_config_mode(spi);
hw_setup_speed_hz(spi, speed_hz);
hw_setup_bits_per_word(spi, bits_per_word);
hw_enter_active_mode(spi);
spi->speed_hz = speed_hz;
spi->bits_per_word = bits_per_word;
}
/* Configure transmitter and receiver */
con = lantiq_ssc_readl(spi, SPI_CON);
if (t->tx_buf)
con &= ~SPI_CON_TXOFF;
else
con |= SPI_CON_TXOFF;
if (t->rx_buf)
con &= ~SPI_CON_RXOFF;
else
con |= SPI_CON_RXOFF;
lantiq_ssc_writel(spi, con, SPI_CON);
}
static int lantiq_ssc_unprepare_message(struct spi_master *master,
struct spi_message *message)
{
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
flush_workqueue(spi->wq);
/* Disable transmitter and receiver while idle */
lantiq_ssc_maskl(spi, 0, SPI_CON_TXOFF | SPI_CON_RXOFF, SPI_CON);
return 0;
}
static void tx_fifo_write(struct lantiq_ssc_spi *spi)
{
const u8 *tx8;
const u16 *tx16;
const u32 *tx32;
u32 data;
unsigned int tx_free = tx_fifo_free(spi);
while (spi->tx_todo && tx_free) {
switch (spi->bits_per_word) {
case 2 ... 8:
tx8 = spi->tx;
data = *tx8;
spi->tx_todo--;
spi->tx++;
break;
case 16:
tx16 = (u16 *) spi->tx;
data = *tx16;
spi->tx_todo -= 2;
spi->tx += 2;
break;
case 32:
tx32 = (u32 *) spi->tx;
data = *tx32;
spi->tx_todo -= 4;
spi->tx += 4;
break;
default:
WARN_ON(1);
data = 0;
break;
}
lantiq_ssc_writel(spi, data, SPI_TB);
tx_free--;
}
}
static void rx_fifo_read_full_duplex(struct lantiq_ssc_spi *spi)
{
u8 *rx8;
u16 *rx16;
u32 *rx32;
u32 data;
unsigned int rx_fill = rx_fifo_level(spi);
while (rx_fill) {
data = lantiq_ssc_readl(spi, SPI_RB);
switch (spi->bits_per_word) {
case 2 ... 8:
rx8 = spi->rx;
*rx8 = data;
spi->rx_todo--;
spi->rx++;
break;
case 16:
rx16 = (u16 *) spi->rx;
*rx16 = data;
spi->rx_todo -= 2;
spi->rx += 2;
break;
case 32:
rx32 = (u32 *) spi->rx;
*rx32 = data;
spi->rx_todo -= 4;
spi->rx += 4;
break;
default:
WARN_ON(1);
break;
}
rx_fill--;
}
}
static void rx_fifo_read_half_duplex(struct lantiq_ssc_spi *spi)
{
u32 data, *rx32;
u8 *rx8;
unsigned int rxbv, shift;
unsigned int rx_fill = rx_fifo_level(spi);
/*
* In RX-only mode the bits per word value is ignored by HW. A value
* of 32 is used instead. Thus all 4 bytes per FIFO must be read.
* If remaining RX bytes are less than 4, the FIFO must be read
* differently. The amount of received and valid bytes is indicated
* by STAT.RXBV register value.
*/
while (rx_fill) {
if (spi->rx_todo < 4) {
rxbv = (lantiq_ssc_readl(spi, SPI_STAT) &
SPI_STAT_RXBV_M) >> SPI_STAT_RXBV_S;
data = lantiq_ssc_readl(spi, SPI_RB);
shift = (rxbv - 1) * 8;
rx8 = spi->rx;
while (rxbv) {
*rx8++ = (data >> shift) & 0xFF;
rxbv--;
shift -= 8;
spi->rx_todo--;
spi->rx++;
}
} else {
data = lantiq_ssc_readl(spi, SPI_RB);
rx32 = (u32 *) spi->rx;
*rx32++ = data;
spi->rx_todo -= 4;
spi->rx += 4;
}
rx_fill--;
}
}
static void rx_request(struct lantiq_ssc_spi *spi)
{
unsigned int rxreq, rxreq_max;
/*
* To avoid receive overflows at high clocks it is better to request
* only the amount of bytes that fits into all FIFOs. This value
* depends on the FIFO size implemented in hardware.
*/
rxreq = spi->rx_todo;
rxreq_max = spi->rx_fifo_size * 4;
if (rxreq > rxreq_max)
rxreq = rxreq_max;
lantiq_ssc_writel(spi, rxreq, SPI_RXREQ);
}
static irqreturn_t lantiq_ssc_xmit_interrupt(int irq, void *data)
{
struct lantiq_ssc_spi *spi = data;
if (spi->tx) {
if (spi->rx && spi->rx_todo)
rx_fifo_read_full_duplex(spi);
if (spi->tx_todo)
tx_fifo_write(spi);
else if (!tx_fifo_level(spi))
goto completed;
} else if (spi->rx) {
if (spi->rx_todo) {
rx_fifo_read_half_duplex(spi);
if (spi->rx_todo)
rx_request(spi);
else
goto completed;
} else {
goto completed;
}
}
return IRQ_HANDLED;
completed:
queue_work(spi->wq, &spi->work);
return IRQ_HANDLED;
}
static irqreturn_t lantiq_ssc_err_interrupt(int irq, void *data)
{
struct lantiq_ssc_spi *spi = data;
u32 stat = lantiq_ssc_readl(spi, SPI_STAT);
if (!(stat & SPI_STAT_ERRORS))
return IRQ_NONE;
if (stat & SPI_STAT_RUE)
dev_err(spi->dev, "receive underflow error\n");
if (stat & SPI_STAT_TUE)
dev_err(spi->dev, "transmit underflow error\n");
if (stat & SPI_STAT_AE)
dev_err(spi->dev, "abort error\n");
if (stat & SPI_STAT_RE)
dev_err(spi->dev, "receive overflow error\n");
if (stat & SPI_STAT_TE)
dev_err(spi->dev, "transmit overflow error\n");
if (stat & SPI_STAT_ME)
dev_err(spi->dev, "mode error\n");
/* Clear error flags */
lantiq_ssc_maskl(spi, 0, SPI_WHBSTATE_CLR_ERRORS, SPI_WHBSTATE);
/* set bad status so it can be retried */
if (spi->master->cur_msg)
spi->master->cur_msg->status = -EIO;
queue_work(spi->wq, &spi->work);
return IRQ_HANDLED;
}
static int transfer_start(struct lantiq_ssc_spi *spi, struct spi_device *spidev,
struct spi_transfer *t)
{
unsigned long flags;
spin_lock_irqsave(&spi->lock, flags);
spi->tx = t->tx_buf;
spi->rx = t->rx_buf;
if (t->tx_buf) {
spi->tx_todo = t->len;
/* initially fill TX FIFO */
tx_fifo_write(spi);
}
if (spi->rx) {
spi->rx_todo = t->len;
/* start shift clock in RX-only mode */
if (!spi->tx)
rx_request(spi);
}
spin_unlock_irqrestore(&spi->lock, flags);
return t->len;
}
/*
* The driver only gets an interrupt when the FIFO is empty, but there
* is an additional shift register from which the data is written to
* the wire. We get the last interrupt when the controller starts to
* write the last word to the wire, not when it is finished. Do busy
* waiting till it finishes.
*/
static void lantiq_ssc_bussy_work(struct work_struct *work)
{
struct lantiq_ssc_spi *spi;
unsigned long long timeout = 8LL * 1000LL;
unsigned long end;
spi = container_of(work, typeof(*spi), work);
do_div(timeout, spi->speed_hz);
timeout += timeout + 100; /* some tolerance */
end = jiffies + msecs_to_jiffies(timeout);
do {
u32 stat = lantiq_ssc_readl(spi, SPI_STAT);
if (!(stat & SPI_STAT_BSY)) {
spi_finalize_current_transfer(spi->master);
return;
}
cond_resched();
} while (!time_after_eq(jiffies, end));
if (spi->master->cur_msg)
spi->master->cur_msg->status = -EIO;
spi_finalize_current_transfer(spi->master);
}
static void lantiq_ssc_handle_err(struct spi_master *master,
struct spi_message *message)
{
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
/* flush FIFOs on timeout */
rx_fifo_flush(spi);
tx_fifo_flush(spi);
}
static void lantiq_ssc_set_cs(struct spi_device *spidev, bool enable)
{
struct lantiq_ssc_spi *spi = spi_master_get_devdata(spidev->master);
unsigned int cs = spidev->chip_select;
u32 fgpo;
if (!!(spidev->mode & SPI_CS_HIGH) == enable)
fgpo = (1 << (cs - spi->base_cs));
else
fgpo = (1 << (cs - spi->base_cs + SPI_FGPO_SETOUTN_S));
lantiq_ssc_writel(spi, fgpo, SPI_FPGO);
}
static int lantiq_ssc_transfer_one(struct spi_master *master,
struct spi_device *spidev,
struct spi_transfer *t)
{
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
hw_setup_transfer(spi, spidev, t);
return transfer_start(spi, spidev, t);
}
static const struct lantiq_ssc_hwcfg lantiq_ssc_xway = {
.irnen_r = SPI_IRNEN_R_XWAY,
.irnen_t = SPI_IRNEN_T_XWAY,
};
static const struct lantiq_ssc_hwcfg lantiq_ssc_xrx = {
.irnen_r = SPI_IRNEN_R_XRX,
.irnen_t = SPI_IRNEN_T_XRX,
};
static const struct of_device_id lantiq_ssc_match[] = {
{ .compatible = "lantiq,ase-spi", .data = &lantiq_ssc_xway, },
{ .compatible = "lantiq,falcon-spi", .data = &lantiq_ssc_xrx, },
{ .compatible = "lantiq,xrx100-spi", .data = &lantiq_ssc_xrx, },
{},
};
MODULE_DEVICE_TABLE(of, lantiq_ssc_match);
static int lantiq_ssc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct spi_master *master;
struct resource *res;
struct lantiq_ssc_spi *spi;
const struct lantiq_ssc_hwcfg *hwcfg;
const struct of_device_id *match;
int err, rx_irq, tx_irq, err_irq;
u32 id, supports_dma, revision;
unsigned int num_cs;
match = of_match_device(lantiq_ssc_match, dev);
if (!match) {
dev_err(dev, "no device match\n");
return -EINVAL;
}
hwcfg = match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "failed to get resources\n");
return -ENXIO;
}
rx_irq = platform_get_irq_byname(pdev, SPI_RX_IRQ_NAME);
if (rx_irq < 0) {
dev_err(dev, "failed to get %s\n", SPI_RX_IRQ_NAME);
return -ENXIO;
}
tx_irq = platform_get_irq_byname(pdev, SPI_TX_IRQ_NAME);
if (tx_irq < 0) {
dev_err(dev, "failed to get %s\n", SPI_TX_IRQ_NAME);
return -ENXIO;
}
err_irq = platform_get_irq_byname(pdev, SPI_ERR_IRQ_NAME);
if (err_irq < 0) {
dev_err(dev, "failed to get %s\n", SPI_ERR_IRQ_NAME);
return -ENXIO;
}
master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi));
if (!master)
return -ENOMEM;
spi = spi_master_get_devdata(master);
spi->master = master;
spi->dev = dev;
spi->hwcfg = hwcfg;
platform_set_drvdata(pdev, spi);
spi->regbase = devm_ioremap_resource(dev, res);
if (IS_ERR(spi->regbase)) {
err = PTR_ERR(spi->regbase);
goto err_master_put;
}
err = devm_request_irq(dev, rx_irq, lantiq_ssc_xmit_interrupt,
0, SPI_RX_IRQ_NAME, spi);
if (err)
goto err_master_put;
err = devm_request_irq(dev, tx_irq, lantiq_ssc_xmit_interrupt,
0, SPI_TX_IRQ_NAME, spi);
if (err)
goto err_master_put;
err = devm_request_irq(dev, err_irq, lantiq_ssc_err_interrupt,
0, SPI_ERR_IRQ_NAME, spi);
if (err)
goto err_master_put;
spi->spi_clk = devm_clk_get(dev, "gate");
if (IS_ERR(spi->spi_clk)) {
err = PTR_ERR(spi->spi_clk);
goto err_master_put;
}
err = clk_prepare_enable(spi->spi_clk);
if (err)
goto err_master_put;
/*
* Use the old clk_get_fpi() function on Lantiq platform, till it
* supports common clk.
*/
#if defined(CONFIG_LANTIQ) && !defined(CONFIG_COMMON_CLK)
spi->fpi_clk = clk_get_fpi();
#else
spi->fpi_clk = clk_get(dev, "freq");
#endif
if (IS_ERR(spi->fpi_clk)) {
err = PTR_ERR(spi->fpi_clk);
goto err_clk_disable;
}
num_cs = 8;
of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
spi->base_cs = 1;
of_property_read_u32(pdev->dev.of_node, "base-cs", &spi->base_cs);
spin_lock_init(&spi->lock);
spi->bits_per_word = 8;
spi->speed_hz = 0;
master->dev.of_node = pdev->dev.of_node;
master->num_chipselect = num_cs;
master->setup = lantiq_ssc_setup;
master->set_cs = lantiq_ssc_set_cs;
master->handle_err = lantiq_ssc_handle_err;
master->prepare_message = lantiq_ssc_prepare_message;
master->unprepare_message = lantiq_ssc_unprepare_message;
master->transfer_one = lantiq_ssc_transfer_one;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH |
SPI_LOOP;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) |
SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
spi->wq = alloc_ordered_workqueue(dev_name(dev), 0);
if (!spi->wq) {
err = -ENOMEM;
goto err_clk_put;
}
INIT_WORK(&spi->work, lantiq_ssc_bussy_work);
id = lantiq_ssc_readl(spi, SPI_ID);
spi->tx_fifo_size = (id & SPI_ID_TXFS_M) >> SPI_ID_TXFS_S;
spi->rx_fifo_size = (id & SPI_ID_RXFS_M) >> SPI_ID_RXFS_S;
supports_dma = (id & SPI_ID_CFG_M) >> SPI_ID_CFG_S;
revision = id & SPI_ID_REV_M;
lantiq_ssc_hw_init(spi);
dev_info(dev,
"Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n",
revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma);
err = devm_spi_register_master(dev, master);
if (err) {
dev_err(dev, "failed to register spi_master\n");
goto err_wq_destroy;
}
return 0;
err_wq_destroy:
destroy_workqueue(spi->wq);
err_clk_put:
clk_put(spi->fpi_clk);
err_clk_disable:
clk_disable_unprepare(spi->spi_clk);
err_master_put:
spi_master_put(master);
return err;
}
static int lantiq_ssc_remove(struct platform_device *pdev)
{
struct lantiq_ssc_spi *spi = platform_get_drvdata(pdev);
lantiq_ssc_writel(spi, 0, SPI_IRNEN);
lantiq_ssc_writel(spi, 0, SPI_CLC);
rx_fifo_flush(spi);
tx_fifo_flush(spi);
hw_enter_config_mode(spi);
destroy_workqueue(spi->wq);
clk_disable_unprepare(spi->spi_clk);
clk_put(spi->fpi_clk);
return 0;
}
static struct platform_driver lantiq_ssc_driver = {
.probe = lantiq_ssc_probe,
.remove = lantiq_ssc_remove,
.driver = {
.name = "spi-lantiq-ssc",
.owner = THIS_MODULE,
.of_match_table = lantiq_ssc_match,
},
};
module_platform_driver(lantiq_ssc_driver);
MODULE_DESCRIPTION("Lantiq SSC SPI controller driver");
MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@gmail.com>");
MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:spi-lantiq-ssc");
...@@ -437,7 +437,8 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -437,7 +437,8 @@ static int mpc52xx_spi_probe(struct platform_device *op)
ms->gpio_cs_count = of_gpio_count(op->dev.of_node); ms->gpio_cs_count = of_gpio_count(op->dev.of_node);
if (ms->gpio_cs_count > 0) { if (ms->gpio_cs_count > 0) {
master->num_chipselect = ms->gpio_cs_count; master->num_chipselect = ms->gpio_cs_count;
ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int), ms->gpio_cs = kmalloc_array(ms->gpio_cs_count,
sizeof(*ms->gpio_cs),
GFP_KERNEL); GFP_KERNEL);
if (!ms->gpio_cs) { if (!ms->gpio_cs) {
rc = -ENOMEM; rc = -ENOMEM;
...@@ -448,8 +449,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -448,8 +449,7 @@ static int mpc52xx_spi_probe(struct platform_device *op)
gpio_cs = of_get_gpio(op->dev.of_node, i); gpio_cs = of_get_gpio(op->dev.of_node, i);
if (gpio_cs < 0) { if (gpio_cs < 0) {
dev_err(&op->dev, dev_err(&op->dev,
"could not parse the gpio field " "could not parse the gpio field in oftree\n");
"in oftree\n");
rc = -ENODEV; rc = -ENODEV;
goto err_gpio; goto err_gpio;
} }
...@@ -457,8 +457,8 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -457,8 +457,8 @@ static int mpc52xx_spi_probe(struct platform_device *op)
rc = gpio_request(gpio_cs, dev_name(&op->dev)); rc = gpio_request(gpio_cs, dev_name(&op->dev));
if (rc) { if (rc) {
dev_err(&op->dev, dev_err(&op->dev,
"can't request spi cs gpio #%d " "can't request spi cs gpio #%d on gpio line %d\n",
"on gpio line %d\n", i, gpio_cs); i, gpio_cs);
goto err_gpio; goto err_gpio;
} }
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
#define MTK_SPI_IDLE 0 #define MTK_SPI_IDLE 0
#define MTK_SPI_PAUSED 1 #define MTK_SPI_PAUSED 1
#define MTK_SPI_MAX_FIFO_SIZE 32 #define MTK_SPI_MAX_FIFO_SIZE 32U
#define MTK_SPI_PACKET_SIZE 1024 #define MTK_SPI_PACKET_SIZE 1024
struct mtk_spi_compatible { struct mtk_spi_compatible {
...@@ -333,7 +333,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, ...@@ -333,7 +333,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
struct mtk_spi *mdata = spi_master_get_devdata(master); struct mtk_spi *mdata = spi_master_get_devdata(master);
mdata->cur_transfer = xfer; mdata->cur_transfer = xfer;
mdata->xfer_len = xfer->len; mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
mtk_spi_prepare_transfer(master, xfer); mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master); mtk_spi_setup_packet(master);
...@@ -410,7 +410,10 @@ static bool mtk_spi_can_dma(struct spi_master *master, ...@@ -410,7 +410,10 @@ static bool mtk_spi_can_dma(struct spi_master *master,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
return xfer->len > MTK_SPI_MAX_FIFO_SIZE; /* Buffers for DMA transactions must be 4-byte aligned */
return (xfer->len > MTK_SPI_MAX_FIFO_SIZE &&
(unsigned long)xfer->tx_buf % 4 == 0 &&
(unsigned long)xfer->rx_buf % 4 == 0);
} }
static int mtk_spi_setup(struct spi_device *spi) static int mtk_spi_setup(struct spi_device *spi)
...@@ -451,10 +454,36 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) ...@@ -451,10 +454,36 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
&reg_val, remainder); &reg_val, remainder);
} }
} }
trans->len -= mdata->xfer_len;
if (!trans->len) {
spi_finalize_current_transfer(master); spi_finalize_current_transfer(master);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (trans->tx_buf)
trans->tx_buf += mdata->xfer_len;
if (trans->rx_buf)
trans->rx_buf += mdata->xfer_len;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
mtk_spi_setup_packet(master);
cnt = trans->len / 4;
iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, cnt);
remainder = trans->len % 4;
if (remainder > 0) {
reg_val = 0;
memcpy(&reg_val, trans->tx_buf + (cnt * 4), remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
mtk_spi_enable_transfer(master);
return IRQ_HANDLED;
}
if (mdata->tx_sgl) if (mdata->tx_sgl)
trans->tx_dma += mdata->xfer_len; trans->tx_dma += mdata->xfer_len;
if (mdata->rx_sgl) if (mdata->rx_sgl)
......
...@@ -411,7 +411,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) ...@@ -411,7 +411,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op)
if (num_gpios > 0) { if (num_gpios > 0) {
int i; int i;
hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL); hw->gpios = kcalloc(num_gpios, sizeof(*hw->gpios), GFP_KERNEL);
if (!hw->gpios) { if (!hw->gpios) {
ret = -ENOMEM; ret = -ENOMEM;
goto free_master; goto free_master;
...@@ -428,8 +428,9 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) ...@@ -428,8 +428,9 @@ static int spi_ppc4xx_of_probe(struct platform_device *op)
/* Real CS - set the initial state. */ /* Real CS - set the initial state. */
ret = gpio_request(gpio, np->name); ret = gpio_request(gpio, np->name);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "can't request gpio " dev_err(dev,
"#%d: %d\n", i, ret); "can't request gpio #%d: %d\n",
i, ret);
goto free_gpios; goto free_gpios;
} }
......
...@@ -41,6 +41,13 @@ struct pxa_spi_info { ...@@ -41,6 +41,13 @@ struct pxa_spi_info {
static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; static struct dw_dma_slave byt_tx_param = { .dst_id = 0 };
static struct dw_dma_slave byt_rx_param = { .src_id = 1 }; static struct dw_dma_slave byt_rx_param = { .src_id = 1 };
static struct dw_dma_slave mrfld3_tx_param = { .dst_id = 15 };
static struct dw_dma_slave mrfld3_rx_param = { .src_id = 14 };
static struct dw_dma_slave mrfld5_tx_param = { .dst_id = 13 };
static struct dw_dma_slave mrfld5_rx_param = { .src_id = 12 };
static struct dw_dma_slave mrfld6_tx_param = { .dst_id = 11 };
static struct dw_dma_slave mrfld6_rx_param = { .src_id = 10 };
static struct dw_dma_slave bsw0_tx_param = { .dst_id = 0 }; static struct dw_dma_slave bsw0_tx_param = { .dst_id = 0 };
static struct dw_dma_slave bsw0_rx_param = { .src_id = 1 }; static struct dw_dma_slave bsw0_rx_param = { .src_id = 1 };
static struct dw_dma_slave bsw1_tx_param = { .dst_id = 6 }; static struct dw_dma_slave bsw1_tx_param = { .dst_id = 6 };
...@@ -93,22 +100,39 @@ static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) ...@@ -93,22 +100,39 @@ static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
{ {
struct pci_dev *dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0));
struct dw_dma_slave *tx, *rx;
switch (PCI_FUNC(dev->devfn)) { switch (PCI_FUNC(dev->devfn)) {
case 0: case 0:
c->port_id = 3; c->port_id = 3;
c->num_chipselect = 1; c->num_chipselect = 1;
c->tx_param = &mrfld3_tx_param;
c->rx_param = &mrfld3_rx_param;
break; break;
case 1: case 1:
c->port_id = 5; c->port_id = 5;
c->num_chipselect = 4; c->num_chipselect = 4;
c->tx_param = &mrfld5_tx_param;
c->rx_param = &mrfld5_rx_param;
break; break;
case 2: case 2:
c->port_id = 6; c->port_id = 6;
c->num_chipselect = 1; c->num_chipselect = 1;
c->tx_param = &mrfld6_tx_param;
c->rx_param = &mrfld6_rx_param;
break; break;
default: default:
return -ENODEV; return -ENODEV;
} }
tx = c->tx_param;
tx->dma_dev = &dma_dev->dev;
rx = c->rx_param;
rx->dma_dev = &dma_dev->dev;
c->dma_filter = lpss_dma_filter;
return 0; return 0;
} }
...@@ -203,10 +227,16 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -203,10 +227,16 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
ssp = &spi_pdata.ssp; ssp = &spi_pdata.ssp;
ssp->phys_base = pci_resource_start(dev, 0); ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = pcim_iomap_table(dev)[0]; ssp->mmio_base = pcim_iomap_table(dev)[0];
ssp->irq = dev->irq;
ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn; ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn;
ssp->type = c->type; ssp->type = c->type;
pci_set_master(dev);
ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
return ret;
ssp->irq = pci_irq_vector(dev, 0);
snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id);
ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, 0, ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, 0,
c->max_clk_rate); c->max_clk_rate);
......
...@@ -732,6 +732,20 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) ...@@ -732,6 +732,20 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void handle_bad_msg(struct driver_data *drv_data)
{
pxa2xx_spi_write(drv_data, SSCR0,
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
pxa2xx_spi_write(drv_data, SSCR1,
pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1);
if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0);
write_SSSR_CS(drv_data, drv_data->clear_sr);
dev_err(&drv_data->pdev->dev,
"bad message state in interrupt handler\n");
}
static irqreturn_t ssp_int(int irq, void *dev_id) static irqreturn_t ssp_int(int irq, void *dev_id)
{ {
struct driver_data *drv_data = dev_id; struct driver_data *drv_data = dev_id;
...@@ -771,21 +785,11 @@ static irqreturn_t ssp_int(int irq, void *dev_id) ...@@ -771,21 +785,11 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
if (!(status & mask)) if (!(status & mask))
return IRQ_NONE; return IRQ_NONE;
if (!drv_data->master->cur_msg) { pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg & ~drv_data->int_cr1);
pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg);
pxa2xx_spi_write(drv_data, SSCR0,
pxa2xx_spi_read(drv_data, SSCR0)
& ~SSCR0_SSE);
pxa2xx_spi_write(drv_data, SSCR1,
pxa2xx_spi_read(drv_data, SSCR1)
& ~drv_data->int_cr1);
if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0);
write_SSSR_CS(drv_data, drv_data->clear_sr);
dev_err(&drv_data->pdev->dev,
"bad message state in interrupt handler\n");
if (!drv_data->master->cur_msg) {
handle_bad_msg(drv_data);
/* Never fail */ /* Never fail */
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1458,6 +1462,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { ...@@ -1458,6 +1462,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
{ PCI_VDEVICE(INTEL, 0x1ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x1ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x1ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x1ac4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x1ac6), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x1ac6), LPSS_BXT_SSP },
/* GLK */
{ PCI_VDEVICE(INTEL, 0x31c2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x31c4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x31c6), LPSS_BXT_SSP },
/* APL */ /* APL */
{ PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -843,6 +844,8 @@ static int rockchip_spi_suspend(struct device *dev) ...@@ -843,6 +844,8 @@ static int rockchip_spi_suspend(struct device *dev)
clk_disable_unprepare(rs->apb_pclk); clk_disable_unprepare(rs->apb_pclk);
} }
pinctrl_pm_select_sleep_state(dev);
return ret; return ret;
} }
...@@ -852,6 +855,8 @@ static int rockchip_spi_resume(struct device *dev) ...@@ -852,6 +855,8 @@ static int rockchip_spi_resume(struct device *dev)
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct rockchip_spi *rs = spi_master_get_devdata(master); struct rockchip_spi *rs = spi_master_get_devdata(master);
pinctrl_pm_select_default_state(dev);
if (!pm_runtime_suspended(dev)) { if (!pm_runtime_suspended(dev)) {
ret = clk_prepare_enable(rs->apb_pclk); ret = clk_prepare_enable(rs->apb_pclk);
if (ret < 0) if (ret < 0)
......
...@@ -808,7 +808,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) ...@@ -808,7 +808,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
rspi_write_data(rspi, *tx++); rspi_write_data(rspi, *tx++);
} else { } else {
ret = rspi_pio_transfer(rspi, tx, NULL, n); ret = rspi_pio_transfer(rspi, tx, NULL, len);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -845,10 +845,9 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) ...@@ -845,10 +845,9 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
*rx++ = rspi_read_data(rspi); *rx++ = rspi_read_data(rspi);
} else { } else {
ret = rspi_pio_transfer(rspi, NULL, rx, n); ret = rspi_pio_transfer(rspi, NULL, rx, len);
if (ret < 0) if (ret < 0)
return ret; return ret;
*rx++ = ret;
} }
n -= len; n -= len;
} }
...@@ -1227,10 +1226,8 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1227,10 +1226,8 @@ static int rspi_probe(struct platform_device *pdev)
const struct spi_ops *ops; const struct spi_ops *ops;
master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
if (master == NULL) { if (master == NULL)
dev_err(&pdev->dev, "spi_alloc_master error.\n");
return -ENOMEM; return -ENOMEM;
}
of_id = of_match_device(rspi_of_match, &pdev->dev); of_id = of_match_device(rspi_of_match, &pdev->dev);
if (of_id) { if (of_id) {
......
...@@ -341,43 +341,16 @@ static void s3c64xx_spi_set_cs(struct spi_device *spi, bool enable) ...@@ -341,43 +341,16 @@ static void s3c64xx_spi_set_cs(struct spi_device *spi, bool enable)
static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
{ {
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
struct device *dev = &sdd->pdev->dev;
if (is_polling(sdd)) if (is_polling(sdd))
return 0; return 0;
/* Acquire DMA channels */
sdd->rx_dma.ch = dma_request_slave_channel(dev, "rx");
if (!sdd->rx_dma.ch) {
dev_err(dev, "Failed to get RX DMA channel\n");
return -EBUSY;
}
spi->dma_rx = sdd->rx_dma.ch; spi->dma_rx = sdd->rx_dma.ch;
sdd->tx_dma.ch = dma_request_slave_channel(dev, "tx");
if (!sdd->tx_dma.ch) {
dev_err(dev, "Failed to get TX DMA channel\n");
dma_release_channel(sdd->rx_dma.ch);
return -EBUSY;
}
spi->dma_tx = sdd->tx_dma.ch; spi->dma_tx = sdd->tx_dma.ch;
return 0; return 0;
} }
static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
{
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
/* Free DMA channels */
if (!is_polling(sdd)) {
dma_release_channel(sdd->rx_dma.ch);
dma_release_channel(sdd->tx_dma.ch);
}
return 0;
}
static bool s3c64xx_spi_can_dma(struct spi_master *master, static bool s3c64xx_spi_can_dma(struct spi_master *master,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
...@@ -996,7 +969,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) ...@@ -996,7 +969,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
sci->num_cs = temp; sci->num_cs = temp;
} }
sci->no_cs = of_property_read_bool(dev->of_node, "broken-cs"); sci->no_cs = of_property_read_bool(dev->of_node, "no-cs-readback");
return sci; return sci;
} }
...@@ -1094,7 +1067,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1094,7 +1067,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
master->prepare_message = s3c64xx_spi_prepare_message; master->prepare_message = s3c64xx_spi_prepare_message;
master->transfer_one = s3c64xx_spi_transfer_one; master->transfer_one = s3c64xx_spi_transfer_one;
master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
master->num_chipselect = sci->num_cs; master->num_chipselect = sci->num_cs;
master->dma_alignment = 8; master->dma_alignment = 8;
master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
...@@ -1161,6 +1133,24 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1161,6 +1133,24 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
} }
} }
if (!is_polling(sdd)) {
/* Acquire DMA channels */
sdd->rx_dma.ch = dma_request_slave_channel_reason(&pdev->dev,
"rx");
if (IS_ERR(sdd->rx_dma.ch)) {
dev_err(&pdev->dev, "Failed to get RX DMA channel\n");
ret = PTR_ERR(sdd->rx_dma.ch);
goto err_disable_io_clk;
}
sdd->tx_dma.ch = dma_request_slave_channel_reason(&pdev->dev,
"tx");
if (IS_ERR(sdd->tx_dma.ch)) {
dev_err(&pdev->dev, "Failed to get TX DMA channel\n");
ret = PTR_ERR(sdd->tx_dma.ch);
goto err_release_rx_dma;
}
}
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT); pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(&pdev->dev);
...@@ -1206,6 +1196,12 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1206,6 +1196,12 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev); pm_runtime_set_suspended(&pdev->dev);
if (!is_polling(sdd))
dma_release_channel(sdd->tx_dma.ch);
err_release_rx_dma:
if (!is_polling(sdd))
dma_release_channel(sdd->rx_dma.ch);
err_disable_io_clk:
clk_disable_unprepare(sdd->ioclk); clk_disable_unprepare(sdd->ioclk);
err_disable_src_clk: err_disable_src_clk:
clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->src_clk);
...@@ -1226,6 +1222,11 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) ...@@ -1226,6 +1222,11 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
writel(0, sdd->regs + S3C64XX_SPI_INT_EN); writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
if (!is_polling(sdd)) {
dma_release_channel(sdd->rx_dma.ch);
dma_release_channel(sdd->tx_dma.ch);
}
clk_disable_unprepare(sdd->ioclk); clk_disable_unprepare(sdd->ioclk);
clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->src_clk);
......
...@@ -1164,10 +1164,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ...@@ -1164,10 +1164,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
int ret; int ret;
master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
if (master == NULL) { if (master == NULL)
dev_err(&pdev->dev, "failed to allocate spi master\n");
return -ENOMEM; return -ENOMEM;
}
p = spi_master_get_devdata(master); p = spi_master_get_devdata(master);
......
...@@ -652,7 +652,8 @@ static int ti_qspi_probe(struct platform_device *pdev) ...@@ -652,7 +652,8 @@ static int ti_qspi_probe(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) { if (r == NULL) {
dev_err(&pdev->dev, "missing platform data\n"); dev_err(&pdev->dev, "missing platform data\n");
return -ENODEV; ret = -ENODEV;
goto free_master;
} }
} }
...@@ -669,7 +670,8 @@ static int ti_qspi_probe(struct platform_device *pdev) ...@@ -669,7 +670,8 @@ static int ti_qspi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n"); dev_err(&pdev->dev, "no irq resource?\n");
return irq; ret = irq;
goto free_master;
} }
mutex_init(&qspi->list_lock); mutex_init(&qspi->list_lock);
...@@ -685,15 +687,17 @@ static int ti_qspi_probe(struct platform_device *pdev) ...@@ -685,15 +687,17 @@ static int ti_qspi_probe(struct platform_device *pdev)
qspi->ctrl_base = qspi->ctrl_base =
syscon_regmap_lookup_by_phandle(np, syscon_regmap_lookup_by_phandle(np,
"syscon-chipselects"); "syscon-chipselects");
if (IS_ERR(qspi->ctrl_base)) if (IS_ERR(qspi->ctrl_base)) {
return PTR_ERR(qspi->ctrl_base); ret = PTR_ERR(qspi->ctrl_base);
goto free_master;
}
ret = of_property_read_u32_index(np, ret = of_property_read_u32_index(np,
"syscon-chipselects", "syscon-chipselects",
1, &qspi->ctrl_reg); 1, &qspi->ctrl_reg);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"couldn't get ctrl_mod reg index\n"); "couldn't get ctrl_mod reg index\n");
return ret; goto free_master;
} }
} }
...@@ -714,9 +718,10 @@ static int ti_qspi_probe(struct platform_device *pdev) ...@@ -714,9 +718,10 @@ static int ti_qspi_probe(struct platform_device *pdev)
dma_cap_set(DMA_MEMCPY, mask); dma_cap_set(DMA_MEMCPY, mask);
qspi->rx_chan = dma_request_chan_by_mask(&mask); qspi->rx_chan = dma_request_chan_by_mask(&mask);
if (!qspi->rx_chan) { if (IS_ERR(qspi->rx_chan)) {
dev_err(qspi->dev, dev_err(qspi->dev,
"No Rx DMA available, trying mmap mode\n"); "No Rx DMA available, trying mmap mode\n");
qspi->rx_chan = NULL;
ret = 0; ret = 0;
goto no_dma; goto no_dma;
} }
...@@ -742,6 +747,7 @@ static int ti_qspi_probe(struct platform_device *pdev) ...@@ -742,6 +747,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
if (!ret) if (!ret)
return 0; return 0;
pm_runtime_disable(&pdev->dev);
free_master: free_master:
spi_master_put(master); spi_master_put(master);
return ret; return ret;
......
...@@ -591,7 +591,6 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw) ...@@ -591,7 +591,6 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
if (!data->pkt_rx_buff) { if (!data->pkt_rx_buff) {
/* flush queue and set status of all transfers to -ENOMEM */ /* flush queue and set status of all transfers to -ENOMEM */
dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) { list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) {
pmsg->status = -ENOMEM; pmsg->status = -ENOMEM;
...@@ -622,8 +621,9 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw) ...@@ -622,8 +621,9 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
if (n_writes > PCH_MAX_FIFO_DEPTH) if (n_writes > PCH_MAX_FIFO_DEPTH)
n_writes = PCH_MAX_FIFO_DEPTH; n_writes = PCH_MAX_FIFO_DEPTH;
dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing " dev_dbg(&data->master->dev,
"0x2 to SSNXCR\n", __func__); "\n%s:Pulling down SSN low - writing 0x2 to SSNXCR\n",
__func__);
pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW); pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
for (j = 0; j < n_writes; j++) for (j = 0; j < n_writes; j++)
...@@ -915,7 +915,6 @@ static void pch_spi_release_dma(struct pch_spi_data *data) ...@@ -915,7 +915,6 @@ static void pch_spi_release_dma(struct pch_spi_data *data)
dma_release_channel(dma->chan_rx); dma_release_channel(dma->chan_rx);
dma->chan_rx = NULL; dma->chan_rx = NULL;
} }
return;
} }
static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
...@@ -1008,7 +1007,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) ...@@ -1008,7 +1007,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
/* RX */ /* RX */
dma->sg_rx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); dma->sg_rx_p = kcalloc(num, sizeof(*dma->sg_rx_p), GFP_ATOMIC);
sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */ sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */
/* offset, length setting */ /* offset, length setting */
sg = dma->sg_rx_p; sg = dma->sg_rx_p;
...@@ -1068,7 +1067,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) ...@@ -1068,7 +1067,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
head = 0; head = 0;
} }
dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); dma->sg_tx_p = kcalloc(num, sizeof(*dma->sg_tx_p), GFP_ATOMIC);
sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
/* offset, length setting */ /* offset, length setting */
sg = dma->sg_tx_p; sg = dma->sg_tx_p;
...@@ -1181,14 +1180,16 @@ static void pch_spi_process_messages(struct work_struct *pwork) ...@@ -1181,14 +1180,16 @@ static void pch_spi_process_messages(struct work_struct *pwork)
data->cur_trans = data->cur_trans =
list_entry(data->current_msg->transfers.next, list_entry(data->current_msg->transfers.next,
struct spi_transfer, transfer_list); struct spi_transfer, transfer_list);
dev_dbg(&data->master->dev, "%s " dev_dbg(&data->master->dev,
":Getting 1st transfer message\n", __func__); "%s :Getting 1st transfer message\n",
__func__);
} else { } else {
data->cur_trans = data->cur_trans =
list_entry(data->cur_trans->transfer_list.next, list_entry(data->cur_trans->transfer_list.next,
struct spi_transfer, transfer_list); struct spi_transfer, transfer_list);
dev_dbg(&data->master->dev, "%s " dev_dbg(&data->master->dev,
":Getting next transfer message\n", __func__); "%s :Getting next transfer message\n",
__func__);
} }
spin_unlock(&data->lock); spin_unlock(&data->lock);
...@@ -1233,9 +1234,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) ...@@ -1233,9 +1234,8 @@ static void pch_spi_process_messages(struct work_struct *pwork)
/* check for delay */ /* check for delay */
if (data->cur_trans->delay_usecs) { if (data->cur_trans->delay_usecs) {
dev_dbg(&data->master->dev, "%s:" dev_dbg(&data->master->dev, "%s:delay in usec=%d\n",
"delay in usec=%d\n", __func__, __func__, data->cur_trans->delay_usecs);
data->cur_trans->delay_usecs);
udelay(data->cur_trans->delay_usecs); udelay(data->cur_trans->delay_usecs);
} }
...@@ -1292,7 +1292,6 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat, ...@@ -1292,7 +1292,6 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
if (dma->rx_buf_dma) if (dma->rx_buf_dma)
dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
dma->rx_buf_virt, dma->rx_buf_dma); dma->rx_buf_virt, dma->rx_buf_dma);
return;
} }
static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
...@@ -1541,11 +1540,11 @@ static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1541,11 +1540,11 @@ static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int i; int i;
struct pch_pd_dev_save *pd_dev_save; struct pch_pd_dev_save *pd_dev_save;
pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL); pd_dev_save = kzalloc(sizeof(*pd_dev_save), GFP_KERNEL);
if (!pd_dev_save) if (!pd_dev_save)
return -ENOMEM; return -ENOMEM;
board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL); board_dat = kzalloc(sizeof(*board_dat), GFP_KERNEL);
if (!board_dat) { if (!board_dat) {
retval = -ENOMEM; retval = -ENOMEM;
goto err_no_mem; goto err_no_mem;
......
...@@ -621,8 +621,10 @@ void spi_unregister_device(struct spi_device *spi) ...@@ -621,8 +621,10 @@ void spi_unregister_device(struct spi_device *spi)
if (!spi) if (!spi)
return; return;
if (spi->dev.of_node) if (spi->dev.of_node) {
of_node_clear_flag(spi->dev.of_node, OF_POPULATED); of_node_clear_flag(spi->dev.of_node, OF_POPULATED);
of_node_put(spi->dev.of_node);
}
if (ACPI_COMPANION(&spi->dev)) if (ACPI_COMPANION(&spi->dev))
acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev)); acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev));
device_unregister(&spi->dev); device_unregister(&spi->dev);
...@@ -672,7 +674,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) ...@@ -672,7 +674,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
if (!n) if (!n)
return -EINVAL; return -EINVAL;
bi = kzalloc(n * sizeof(*bi), GFP_KERNEL); bi = kcalloc(n, sizeof(*bi), GFP_KERNEL);
if (!bi) if (!bi)
return -ENOMEM; return -ENOMEM;
...@@ -805,12 +807,12 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) ...@@ -805,12 +807,12 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
if (master->dma_tx) if (master->dma_tx)
tx_dev = master->dma_tx->device->dev; tx_dev = master->dma_tx->device->dev;
else else
tx_dev = &master->dev; tx_dev = master->dev.parent;
if (master->dma_rx) if (master->dma_rx)
rx_dev = master->dma_rx->device->dev; rx_dev = master->dma_rx->device->dev;
else else
rx_dev = &master->dev; rx_dev = master->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer)) if (!master->can_dma(master, msg->spi, xfer))
...@@ -852,12 +854,12 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg) ...@@ -852,12 +854,12 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
if (master->dma_tx) if (master->dma_tx)
tx_dev = master->dma_tx->device->dev; tx_dev = master->dma_tx->device->dev;
else else
tx_dev = &master->dev; tx_dev = master->dev.parent;
if (master->dma_rx) if (master->dma_rx)
rx_dev = master->dma_rx->device->dev; rx_dev = master->dma_rx->device->dev;
else else
rx_dev = &master->dev; rx_dev = master->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer)) if (!master->can_dma(master, msg->spi, xfer))
...@@ -1502,37 +1504,18 @@ static int spi_master_initialize_queue(struct spi_master *master) ...@@ -1502,37 +1504,18 @@ static int spi_master_initialize_queue(struct spi_master *master)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
static struct spi_device * static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
of_register_spi_device(struct spi_master *master, struct device_node *nc) struct device_node *nc)
{ {
struct spi_device *spi;
int rc;
u32 value; u32 value;
int rc;
/* Alloc an spi_device */
spi = spi_alloc_device(master);
if (!spi) {
dev_err(&master->dev, "spi_device alloc error for %s\n",
nc->full_name);
rc = -ENOMEM;
goto err_out;
}
/* Select device driver */
rc = of_modalias_node(nc, spi->modalias,
sizeof(spi->modalias));
if (rc < 0) {
dev_err(&master->dev, "cannot find modalias for %s\n",
nc->full_name);
goto err_out;
}
/* Device address */ /* Device address */
rc = of_property_read_u32(nc, "reg", &value); rc = of_property_read_u32(nc, "reg", &value);
if (rc) { if (rc) {
dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
nc->full_name, rc); nc->full_name, rc);
goto err_out; return rc;
} }
spi->chip_select = value; spi->chip_select = value;
...@@ -1590,10 +1573,41 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc) ...@@ -1590,10 +1573,41 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc)
if (rc) { if (rc) {
dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
nc->full_name, rc); nc->full_name, rc);
goto err_out; return rc;
} }
spi->max_speed_hz = value; spi->max_speed_hz = value;
return 0;
}
static struct spi_device *
of_register_spi_device(struct spi_master *master, struct device_node *nc)
{
struct spi_device *spi;
int rc;
/* Alloc an spi_device */
spi = spi_alloc_device(master);
if (!spi) {
dev_err(&master->dev, "spi_device alloc error for %s\n",
nc->full_name);
rc = -ENOMEM;
goto err_out;
}
/* Select device driver */
rc = of_modalias_node(nc, spi->modalias,
sizeof(spi->modalias));
if (rc < 0) {
dev_err(&master->dev, "cannot find modalias for %s\n",
nc->full_name);
goto err_out;
}
rc = of_spi_parse_dt(master, spi, nc);
if (rc)
goto err_out;
/* Store a pointer to the node in the device structure */ /* Store a pointer to the node in the device structure */
of_node_get(nc); of_node_get(nc);
spi->dev.of_node = nc; spi->dev.of_node = nc;
...@@ -1603,11 +1617,13 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc) ...@@ -1603,11 +1617,13 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc)
if (rc) { if (rc) {
dev_err(&master->dev, "spi_device register error %s\n", dev_err(&master->dev, "spi_device register error %s\n",
nc->full_name); nc->full_name);
goto err_out; goto err_of_node_put;
} }
return spi; return spi;
err_of_node_put:
of_node_put(nc);
err_out: err_out:
spi_dev_put(spi); spi_dev_put(spi);
return ERR_PTR(rc); return ERR_PTR(rc);
......
...@@ -5,25 +5,14 @@ struct spi_device; ...@@ -5,25 +5,14 @@ struct spi_device;
/** /**
* struct ep93xx_spi_info - EP93xx specific SPI descriptor * struct ep93xx_spi_info - EP93xx specific SPI descriptor
* @num_chipselect: number of chip selects on this board, must be * @chipselect: array of gpio numbers to use as chip selects
* at least one * @num_chipselect: ARRAY_SIZE(chipselect)
* @use_dma: use DMA for the transfers * @use_dma: use DMA for the transfers
*/ */
struct ep93xx_spi_info { struct ep93xx_spi_info {
int *chipselect;
int num_chipselect; int num_chipselect;
bool use_dma; bool use_dma;
}; };
/**
* struct ep93xx_spi_chip_ops - operation callbacks for SPI slave device
* @setup: setup the chip select mechanism
* @cleanup: cleanup the chip select mechanism
* @cs_control: control the device chip select
*/
struct ep93xx_spi_chip_ops {
int (*setup)(struct spi_device *spi);
void (*cleanup)(struct spi_device *spi);
void (*cs_control)(struct spi_device *spi, int value);
};
#endif /* __ASM_MACH_EP93XX_SPI_H */ #endif /* __ASM_MACH_EP93XX_SPI_H */
...@@ -106,7 +106,7 @@ ...@@ -106,7 +106,7 @@
#define CE4100_SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */ #define CE4100_SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
/* QUARK_X1000 SSCR0 bit definition */ /* QUARK_X1000 SSCR0 bit definition */
#define QUARK_X1000_SSCR0_DSS (0x1F) /* Data Size Select (mask) */ #define QUARK_X1000_SSCR0_DSS (0x1F << 0) /* Data Size Select (mask) */
#define QUARK_X1000_SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..32] */ #define QUARK_X1000_SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..32] */
#define QUARK_X1000_SSCR0_FRF (0x3 << 5) /* FRame Format (mask) */ #define QUARK_X1000_SSCR0_FRF (0x3 << 5) /* FRame Format (mask) */
#define QUARK_X1000_SSCR0_Motorola (0x0 << 5) /* Motorola's Serial Peripheral Interface (SPI) */ #define QUARK_X1000_SSCR0_Motorola (0x0 << 5) /* Motorola's Serial Peripheral Interface (SPI) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment