From ca632f556697d45d67ed5cada7cedf3ddfe0db4b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 6 Jun 2011 01:16:30 -0600 Subject: spi: reorganize drivers Sort the SPI makefile and enforce the naming convention spi_*.c for spi drivers. This change also rolls the contents of atmel_spi.h into the .c file since there is only one user of that particular include file. v2: - Use 'spi-' prefix instead of 'spi_' to match what seems to be be the predominant pattern for subsystem prefixes. - Clean up filenames in Kconfig and header comment blocks Signed-off-by: Grant Likely Acked-by: Wolfram Sang Acked-by: Linus Walleij --- drivers/spi/Kconfig | 18 - drivers/spi/Makefile | 112 +- drivers/spi/amba-pl022.c | 2344 --------------------------------------- drivers/spi/ath79_spi.c | 292 ----- drivers/spi/atmel_spi.c | 940 ---------------- drivers/spi/atmel_spi.h | 167 --- drivers/spi/au1550_spi.c | 1032 ----------------- drivers/spi/coldfire_qspi.c | 642 ----------- drivers/spi/davinci_spi.c | 1030 ----------------- drivers/spi/dw_spi.c | 936 ---------------- drivers/spi/dw_spi.h | 232 ---- drivers/spi/dw_spi_mid.c | 224 ---- drivers/spi/dw_spi_mmio.c | 151 --- drivers/spi/dw_spi_pci.c | 181 --- drivers/spi/ep93xx_spi.c | 938 ---------------- drivers/spi/mpc512x_psc_spi.c | 577 ---------- drivers/spi/mpc52xx_psc_spi.c | 529 --------- drivers/spi/mpc52xx_spi.c | 579 ---------- drivers/spi/omap2_mcspi.c | 1293 --------------------- drivers/spi/omap_spi_100k.c | 637 ----------- drivers/spi/omap_uwire.c | 593 ---------- drivers/spi/orion_spi.c | 573 ---------- drivers/spi/pxa2xx_spi.c | 1816 ------------------------------ drivers/spi/pxa2xx_spi_pci.c | 180 --- drivers/spi/spi-altera.c | 339 ++++++ drivers/spi/spi-ath79.c | 292 +++++ drivers/spi/spi-atmel.c | 1093 ++++++++++++++++++ drivers/spi/spi-au1550.c | 1032 +++++++++++++++++ drivers/spi/spi-bfin-sport.c | 952 ++++++++++++++++ drivers/spi/spi-bfin5xx.c | 1530 +++++++++++++++++++++++++ drivers/spi/spi-bitbang-txrx.h | 97 ++ drivers/spi/spi-bitbang.c | 505 +++++++++ drivers/spi/spi-butterfly.c | 356 ++++++ drivers/spi/spi-coldfire-qspi.c | 642 +++++++++++ drivers/spi/spi-davinci.c | 1030 +++++++++++++++++ drivers/spi/spi-dw-mid.c | 224 ++++ drivers/spi/spi-dw-mmio.c | 151 +++ drivers/spi/spi-dw-pci.c | 181 +++ drivers/spi/spi-dw.c | 936 ++++++++++++++++ drivers/spi/spi-dw.h | 232 ++++ drivers/spi/spi-ep93xx.c | 938 ++++++++++++++++ drivers/spi/spi-fsl-espi.c | 762 +++++++++++++ drivers/spi/spi-fsl-lib.c | 236 ++++ drivers/spi/spi-fsl-lib.h | 123 ++ drivers/spi/spi-fsl-spi.c | 1192 ++++++++++++++++++++ drivers/spi/spi-gpio.c | 429 +++++++ drivers/spi/spi-imx.c | 944 ++++++++++++++++ drivers/spi/spi-lm70llp.c | 351 ++++++ drivers/spi/spi-mpc512x-psc.c | 577 ++++++++++ drivers/spi/spi-mpc52xx-psc.c | 529 +++++++++ drivers/spi/spi-mpc52xx.c | 579 ++++++++++ drivers/spi/spi-nuc900.c | 504 +++++++++ drivers/spi/spi-oc-tiny.c | 425 +++++++ drivers/spi/spi-omap-100k.c | 637 +++++++++++ drivers/spi/spi-omap-uwire.c | 593 ++++++++++ drivers/spi/spi-omap2-mcspi.c | 1293 +++++++++++++++++++++ drivers/spi/spi-orion.c | 573 ++++++++++ drivers/spi/spi-pl022.c | 2342 ++++++++++++++++++++++++++++++++++++++ drivers/spi/spi-ppc4xx.c | 612 ++++++++++ drivers/spi/spi-pxa2xx-pci.c | 180 +++ drivers/spi/spi-pxa2xx.c | 1816 ++++++++++++++++++++++++++++++ drivers/spi/spi-s3c24xx-fiq.S | 116 ++ drivers/spi/spi-s3c24xx-fiq.h | 26 + drivers/spi/spi-s3c24xx-gpio.c | 200 ++++ drivers/spi/spi-s3c24xx.c | 745 +++++++++++++ drivers/spi/spi-s3c64xx.c | 1247 +++++++++++++++++++++ drivers/spi/spi-sh-msiof.c | 749 +++++++++++++ drivers/spi/spi-sh-sci.c | 205 ++++ drivers/spi/spi-sh.c | 543 +++++++++ drivers/spi/spi-stmp.c | 679 ++++++++++++ drivers/spi/spi-tegra.c | 618 +++++++++++ drivers/spi/spi-ti-ssp.c | 402 +++++++ drivers/spi/spi-tle62x0.c | 334 ++++++ drivers/spi/spi-topcliff-pch.c | 1303 ++++++++++++++++++++++ drivers/spi/spi-txx9.c | 472 ++++++++ drivers/spi/spi-xilinx.c | 556 ++++++++++ drivers/spi/spi.c | 2 +- drivers/spi/spi_altera.c | 339 ------ drivers/spi/spi_bfin5xx.c | 1530 ------------------------- drivers/spi/spi_bfin_sport.c | 952 ---------------- drivers/spi/spi_bitbang.c | 505 --------- drivers/spi/spi_bitbang_txrx.h | 97 -- drivers/spi/spi_butterfly.c | 356 ------ drivers/spi/spi_fsl_espi.c | 762 ------------- drivers/spi/spi_fsl_lib.c | 236 ---- drivers/spi/spi_fsl_lib.h | 123 -- drivers/spi/spi_fsl_spi.c | 1192 -------------------- drivers/spi/spi_gpio.c | 429 ------- drivers/spi/spi_imx.c | 944 ---------------- drivers/spi/spi_lm70llp.c | 351 ------ drivers/spi/spi_nuc900.c | 505 --------- drivers/spi/spi_oc_tiny.c | 425 ------- drivers/spi/spi_ppc4xx.c | 612 ---------- drivers/spi/spi_s3c24xx.c | 746 ------------- drivers/spi/spi_s3c24xx_fiq.S | 116 -- drivers/spi/spi_s3c24xx_fiq.h | 26 - drivers/spi/spi_s3c24xx_gpio.c | 201 ---- drivers/spi/spi_s3c64xx.c | 1248 --------------------- drivers/spi/spi_sh.c | 543 --------- drivers/spi/spi_sh_msiof.c | 749 ------------- drivers/spi/spi_sh_sci.c | 205 ---- drivers/spi/spi_stmp.c | 679 ------------ drivers/spi/spi_tegra.c | 618 ----------- drivers/spi/spi_topcliff_pch.c | 1303 ---------------------- drivers/spi/spi_txx9.c | 472 -------- drivers/spi/spidev.c | 2 +- drivers/spi/ti-ssp-spi.c | 402 ------- drivers/spi/tle62x0.c | 334 ------ drivers/spi/xilinx_spi.c | 556 ---------- 109 files changed, 33474 insertions(+), 33524 deletions(-) delete mode 100644 drivers/spi/amba-pl022.c delete mode 100644 drivers/spi/ath79_spi.c delete mode 100644 drivers/spi/atmel_spi.c delete mode 100644 drivers/spi/atmel_spi.h delete mode 100644 drivers/spi/au1550_spi.c delete mode 100644 drivers/spi/coldfire_qspi.c delete mode 100644 drivers/spi/davinci_spi.c delete mode 100644 drivers/spi/dw_spi.c delete mode 100644 drivers/spi/dw_spi.h delete mode 100644 drivers/spi/dw_spi_mid.c delete mode 100644 drivers/spi/dw_spi_mmio.c delete mode 100644 drivers/spi/dw_spi_pci.c delete mode 100644 drivers/spi/ep93xx_spi.c delete mode 100644 drivers/spi/mpc512x_psc_spi.c delete mode 100644 drivers/spi/mpc52xx_psc_spi.c delete mode 100644 drivers/spi/mpc52xx_spi.c delete mode 100644 drivers/spi/omap2_mcspi.c delete mode 100644 drivers/spi/omap_spi_100k.c delete mode 100644 drivers/spi/omap_uwire.c delete mode 100644 drivers/spi/orion_spi.c delete mode 100644 drivers/spi/pxa2xx_spi.c delete mode 100644 drivers/spi/pxa2xx_spi_pci.c create mode 100644 drivers/spi/spi-altera.c create mode 100644 drivers/spi/spi-ath79.c create mode 100644 drivers/spi/spi-atmel.c create mode 100644 drivers/spi/spi-au1550.c create mode 100644 drivers/spi/spi-bfin-sport.c create mode 100644 drivers/spi/spi-bfin5xx.c create mode 100644 drivers/spi/spi-bitbang-txrx.h create mode 100644 drivers/spi/spi-bitbang.c create mode 100644 drivers/spi/spi-butterfly.c create mode 100644 drivers/spi/spi-coldfire-qspi.c create mode 100644 drivers/spi/spi-davinci.c create mode 100644 drivers/spi/spi-dw-mid.c create mode 100644 drivers/spi/spi-dw-mmio.c create mode 100644 drivers/spi/spi-dw-pci.c create mode 100644 drivers/spi/spi-dw.c create mode 100644 drivers/spi/spi-dw.h create mode 100644 drivers/spi/spi-ep93xx.c create mode 100644 drivers/spi/spi-fsl-espi.c create mode 100644 drivers/spi/spi-fsl-lib.c create mode 100644 drivers/spi/spi-fsl-lib.h create mode 100644 drivers/spi/spi-fsl-spi.c create mode 100644 drivers/spi/spi-gpio.c create mode 100644 drivers/spi/spi-imx.c create mode 100644 drivers/spi/spi-lm70llp.c create mode 100644 drivers/spi/spi-mpc512x-psc.c create mode 100644 drivers/spi/spi-mpc52xx-psc.c create mode 100644 drivers/spi/spi-mpc52xx.c create mode 100644 drivers/spi/spi-nuc900.c create mode 100644 drivers/spi/spi-oc-tiny.c create mode 100644 drivers/spi/spi-omap-100k.c create mode 100644 drivers/spi/spi-omap-uwire.c create mode 100644 drivers/spi/spi-omap2-mcspi.c create mode 100644 drivers/spi/spi-orion.c create mode 100644 drivers/spi/spi-pl022.c create mode 100644 drivers/spi/spi-ppc4xx.c create mode 100644 drivers/spi/spi-pxa2xx-pci.c create mode 100644 drivers/spi/spi-pxa2xx.c create mode 100644 drivers/spi/spi-s3c24xx-fiq.S create mode 100644 drivers/spi/spi-s3c24xx-fiq.h create mode 100644 drivers/spi/spi-s3c24xx-gpio.c create mode 100644 drivers/spi/spi-s3c24xx.c create mode 100644 drivers/spi/spi-s3c64xx.c create mode 100644 drivers/spi/spi-sh-msiof.c create mode 100644 drivers/spi/spi-sh-sci.c create mode 100644 drivers/spi/spi-sh.c create mode 100644 drivers/spi/spi-stmp.c create mode 100644 drivers/spi/spi-tegra.c create mode 100644 drivers/spi/spi-ti-ssp.c create mode 100644 drivers/spi/spi-tle62x0.c create mode 100644 drivers/spi/spi-topcliff-pch.c create mode 100644 drivers/spi/spi-txx9.c create mode 100644 drivers/spi/spi-xilinx.c delete mode 100644 drivers/spi/spi_altera.c delete mode 100644 drivers/spi/spi_bfin5xx.c delete mode 100644 drivers/spi/spi_bfin_sport.c delete mode 100644 drivers/spi/spi_bitbang.c delete mode 100644 drivers/spi/spi_bitbang_txrx.h delete mode 100644 drivers/spi/spi_butterfly.c delete mode 100644 drivers/spi/spi_fsl_espi.c delete mode 100644 drivers/spi/spi_fsl_lib.c delete mode 100644 drivers/spi/spi_fsl_lib.h delete mode 100644 drivers/spi/spi_fsl_spi.c delete mode 100644 drivers/spi/spi_gpio.c delete mode 100644 drivers/spi/spi_imx.c delete mode 100644 drivers/spi/spi_lm70llp.c delete mode 100644 drivers/spi/spi_nuc900.c delete mode 100644 drivers/spi/spi_oc_tiny.c delete mode 100644 drivers/spi/spi_ppc4xx.c delete mode 100644 drivers/spi/spi_s3c24xx.c delete mode 100644 drivers/spi/spi_s3c24xx_fiq.S delete mode 100644 drivers/spi/spi_s3c24xx_fiq.h delete mode 100644 drivers/spi/spi_s3c24xx_gpio.c delete mode 100644 drivers/spi/spi_s3c64xx.c delete mode 100644 drivers/spi/spi_sh.c delete mode 100644 drivers/spi/spi_sh_msiof.c delete mode 100644 drivers/spi/spi_sh_sci.c delete mode 100644 drivers/spi/spi_stmp.c delete mode 100644 drivers/spi/spi_tegra.c delete mode 100644 drivers/spi/spi_topcliff_pch.c delete mode 100644 drivers/spi/spi_txx9.c delete mode 100644 drivers/spi/ti-ssp-spi.c delete mode 100644 drivers/spi/tle62x0.c delete mode 100644 drivers/spi/xilinx_spi.c (limited to 'drivers/spi') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index de35c3ad8a69..9578a8492012 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -86,9 +86,6 @@ config SPI_BFIN_SPORT help Enable support for a SPI bus via the Blackfin SPORT peripheral. - This driver can also be built as a module. If so, the module - will be called spi_bfin_sport. - config SPI_AU1550 tristate "Au1550/Au12x0 SPI Controller" depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL @@ -97,9 +94,6 @@ config SPI_AU1550 If you say yes to this option, support will be included for the Au1550 SPI controller (may also work with Au1200,Au1210,Au1250). - This driver can also be built as a module. If so, the module - will be called au1550_spi. - config SPI_BITBANG tristate "Utilities for Bitbanging SPI masters" help @@ -130,9 +124,6 @@ config SPI_COLDFIRE_QSPI This enables support for the Coldfire QSPI controller in master mode. - This driver can also be built as a module. If so, the module - will be called coldfire_qspi. - config SPI_DAVINCI tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller" depends on SPI_MASTER && ARCH_DAVINCI @@ -140,9 +131,6 @@ config SPI_DAVINCI help SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules. - This driver can also be built as a module. The module will be called - davinci_spi. - config SPI_EP93XX tristate "Cirrus Logic EP93xx SPI controller" depends on ARCH_EP93XX @@ -150,9 +138,6 @@ config SPI_EP93XX This enables using the Cirrus EP93xx SPI controller in master mode. - To compile this driver as a module, choose M here. The module will be - called ep93xx_spi. - config SPI_GPIO tristate "GPIO-based bitbanging SPI Master" depends on GENERIC_GPIO @@ -385,9 +370,6 @@ config SPI_TI_SSP This selects an SPI master implementation using a TI sequencer serial port. - To compile this driver as a module, choose M here: the - module will be called ti-ssp-spi. - config SPI_TOPCLIFF_PCH tristate "Topcliff PCH SPI Controller" depends on PCI diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 0f8c69b6b19e..b60b04befee0 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -7,68 +7,56 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG # small core, mostly translating board-specific # config declarations into driver model code obj-$(CONFIG_SPI_MASTER) += spi.o +obj-$(CONFIG_SPI_SPIDEV) += spidev.o # SPI master controller drivers (bus) -obj-$(CONFIG_SPI_ALTERA) += spi_altera.o -obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o -obj-$(CONFIG_SPI_ATH79) += ath79_spi.o -obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o -obj-$(CONFIG_SPI_BFIN_SPORT) += spi_bfin_sport.o -obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o -obj-$(CONFIG_SPI_AU1550) += au1550_spi.o -obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o -obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o -obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o -obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o -obj-$(CONFIG_SPI_DW_PCI) += dw_spi_midpci.o -dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o -obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o -obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o -obj-$(CONFIG_SPI_GPIO) += spi_gpio.o -obj-$(CONFIG_SPI_IMX) += spi_imx.o -obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o -obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o -obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o -obj-$(CONFIG_SPI_OC_TINY) += spi_oc_tiny.o -obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o -obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o -obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o -obj-$(CONFIG_SPI_ORION) += orion_spi.o -obj-$(CONFIG_SPI_PL022) += amba-pl022.o -obj-$(CONFIG_SPI_MPC512x_PSC) += mpc512x_psc_spi.o -obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o -obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o -obj-$(CONFIG_SPI_FSL_LIB) += spi_fsl_lib.o -obj-$(CONFIG_SPI_FSL_ESPI) += spi_fsl_espi.o -obj-$(CONFIG_SPI_FSL_SPI) += spi_fsl_spi.o -obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o -obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o -obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o -obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o -obj-$(CONFIG_SPI_TEGRA) += spi_tegra.o -obj-$(CONFIG_SPI_TI_SSP) += ti-ssp-spi.o -obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o -obj-$(CONFIG_SPI_TXX9) += spi_txx9.o -obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o -obj-$(CONFIG_SPI_SH) += spi_sh.o -obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o -obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o -obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o -obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o +obj-$(CONFIG_SPI_ALTERA) += spi-altera.o +obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o +obj-$(CONFIG_SPI_ATH79) += spi-ath79.o +obj-$(CONFIG_SPI_AU1550) += spi-au1550.o +obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o +obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o +obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o +obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o +obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o +obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o +obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o +obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o +obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o +spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o +obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o +obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o +obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o +obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o +obj-$(CONFIG_SPI_GPIO) += spi-gpio.o +obj-$(CONFIG_SPI_IMX) += spi-imx.o +obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o +obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o +obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o +obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o +obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o +obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o +obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o +obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o +obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o +obj-$(CONFIG_SPI_ORION) += spi-orion.o +obj-$(CONFIG_SPI_PL022) += spi-pl022.o +obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o +obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o +obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o +obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi-s3c24xx-gpio.o +obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o +spi-s3c24xx-hw-y := spi-s3c24xx.o +spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o +obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o +obj-$(CONFIG_SPI_SH) += spi-sh.o +obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o +obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o +obj-$(CONFIG_SPI_STMP3XXX) += spi-stmp.o +obj-$(CONFIG_SPI_TEGRA) += spi-tegra.o +obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o +obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o +obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o +obj-$(CONFIG_SPI_TXX9) += spi-txx9.o +obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o -# special build for s3c24xx spi driver with fiq support -spi_s3c24xx_hw-y := spi_s3c24xx.o -spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o - -# ... add above this line ... - -# SPI protocol drivers (device/link on bus) -obj-$(CONFIG_SPI_SPIDEV) += spidev.o -obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o -# ... add above this line ... - -# SPI slave controller drivers (upstream link) -# ... add above this line ... - -# SPI slave drivers (protocol for that link) -# ... add above this line ... diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c deleted file mode 100644 index 6a9e58dd36c7..000000000000 --- a/drivers/spi/amba-pl022.c +++ /dev/null @@ -1,2344 +0,0 @@ -/* - * drivers/spi/amba-pl022.c - * - * A driver for the ARM PL022 PrimeCell SSP/SPI bus master. - * - * Copyright (C) 2008-2009 ST-Ericsson AB - * Copyright (C) 2006 STMicroelectronics Pvt. Ltd. - * - * Author: Linus Walleij - * - * Initial version inspired by: - * linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c - * Initial adoption to PL022 by: - * Sachin Verma - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This macro is used to define some register default values. - * reg is masked with mask, the OR:ed with an (again masked) - * val shifted sb steps to the left. - */ -#define SSP_WRITE_BITS(reg, val, mask, sb) \ - ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask)))) - -/* - * This macro is also used to define some default values. - * It will just shift val by sb steps to the left and mask - * the result with mask. - */ -#define GEN_MASK_BITS(val, mask, sb) \ - (((val)<<(sb)) & (mask)) - -#define DRIVE_TX 0 -#define DO_NOT_DRIVE_TX 1 - -#define DO_NOT_QUEUE_DMA 0 -#define QUEUE_DMA 1 - -#define RX_TRANSFER 1 -#define TX_TRANSFER 2 - -/* - * Macros to access SSP Registers with their offsets - */ -#define SSP_CR0(r) (r + 0x000) -#define SSP_CR1(r) (r + 0x004) -#define SSP_DR(r) (r + 0x008) -#define SSP_SR(r) (r + 0x00C) -#define SSP_CPSR(r) (r + 0x010) -#define SSP_IMSC(r) (r + 0x014) -#define SSP_RIS(r) (r + 0x018) -#define SSP_MIS(r) (r + 0x01C) -#define SSP_ICR(r) (r + 0x020) -#define SSP_DMACR(r) (r + 0x024) -#define SSP_ITCR(r) (r + 0x080) -#define SSP_ITIP(r) (r + 0x084) -#define SSP_ITOP(r) (r + 0x088) -#define SSP_TDR(r) (r + 0x08C) - -#define SSP_PID0(r) (r + 0xFE0) -#define SSP_PID1(r) (r + 0xFE4) -#define SSP_PID2(r) (r + 0xFE8) -#define SSP_PID3(r) (r + 0xFEC) - -#define SSP_CID0(r) (r + 0xFF0) -#define SSP_CID1(r) (r + 0xFF4) -#define SSP_CID2(r) (r + 0xFF8) -#define SSP_CID3(r) (r + 0xFFC) - -/* - * SSP Control Register 0 - SSP_CR0 - */ -#define SSP_CR0_MASK_DSS (0x0FUL << 0) -#define SSP_CR0_MASK_FRF (0x3UL << 4) -#define SSP_CR0_MASK_SPO (0x1UL << 6) -#define SSP_CR0_MASK_SPH (0x1UL << 7) -#define SSP_CR0_MASK_SCR (0xFFUL << 8) - -/* - * The ST version of this block moves som bits - * in SSP_CR0 and extends it to 32 bits - */ -#define SSP_CR0_MASK_DSS_ST (0x1FUL << 0) -#define SSP_CR0_MASK_HALFDUP_ST (0x1UL << 5) -#define SSP_CR0_MASK_CSS_ST (0x1FUL << 16) -#define SSP_CR0_MASK_FRF_ST (0x3UL << 21) - - -/* - * SSP Control Register 0 - SSP_CR1 - */ -#define SSP_CR1_MASK_LBM (0x1UL << 0) -#define SSP_CR1_MASK_SSE (0x1UL << 1) -#define SSP_CR1_MASK_MS (0x1UL << 2) -#define SSP_CR1_MASK_SOD (0x1UL << 3) - -/* - * The ST version of this block adds some bits - * in SSP_CR1 - */ -#define SSP_CR1_MASK_RENDN_ST (0x1UL << 4) -#define SSP_CR1_MASK_TENDN_ST (0x1UL << 5) -#define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6) -#define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7) -#define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10) -/* This one is only in the PL023 variant */ -#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13) - -/* - * SSP Status Register - SSP_SR - */ -#define SSP_SR_MASK_TFE (0x1UL << 0) /* Transmit FIFO empty */ -#define SSP_SR_MASK_TNF (0x1UL << 1) /* Transmit FIFO not full */ -#define SSP_SR_MASK_RNE (0x1UL << 2) /* Receive FIFO not empty */ -#define SSP_SR_MASK_RFF (0x1UL << 3) /* Receive FIFO full */ -#define SSP_SR_MASK_BSY (0x1UL << 4) /* Busy Flag */ - -/* - * SSP Clock Prescale Register - SSP_CPSR - */ -#define SSP_CPSR_MASK_CPSDVSR (0xFFUL << 0) - -/* - * SSP Interrupt Mask Set/Clear Register - SSP_IMSC - */ -#define SSP_IMSC_MASK_RORIM (0x1UL << 0) /* Receive Overrun Interrupt mask */ -#define SSP_IMSC_MASK_RTIM (0x1UL << 1) /* Receive timeout Interrupt mask */ -#define SSP_IMSC_MASK_RXIM (0x1UL << 2) /* Receive FIFO Interrupt mask */ -#define SSP_IMSC_MASK_TXIM (0x1UL << 3) /* Transmit FIFO Interrupt mask */ - -/* - * SSP Raw Interrupt Status Register - SSP_RIS - */ -/* Receive Overrun Raw Interrupt status */ -#define SSP_RIS_MASK_RORRIS (0x1UL << 0) -/* Receive Timeout Raw Interrupt status */ -#define SSP_RIS_MASK_RTRIS (0x1UL << 1) -/* Receive FIFO Raw Interrupt status */ -#define SSP_RIS_MASK_RXRIS (0x1UL << 2) -/* Transmit FIFO Raw Interrupt status */ -#define SSP_RIS_MASK_TXRIS (0x1UL << 3) - -/* - * SSP Masked Interrupt Status Register - SSP_MIS - */ -/* Receive Overrun Masked Interrupt status */ -#define SSP_MIS_MASK_RORMIS (0x1UL << 0) -/* Receive Timeout Masked Interrupt status */ -#define SSP_MIS_MASK_RTMIS (0x1UL << 1) -/* Receive FIFO Masked Interrupt status */ -#define SSP_MIS_MASK_RXMIS (0x1UL << 2) -/* Transmit FIFO Masked Interrupt status */ -#define SSP_MIS_MASK_TXMIS (0x1UL << 3) - -/* - * SSP Interrupt Clear Register - SSP_ICR - */ -/* Receive Overrun Raw Clear Interrupt bit */ -#define SSP_ICR_MASK_RORIC (0x1UL << 0) -/* Receive Timeout Clear Interrupt bit */ -#define SSP_ICR_MASK_RTIC (0x1UL << 1) - -/* - * SSP DMA Control Register - SSP_DMACR - */ -/* Receive DMA Enable bit */ -#define SSP_DMACR_MASK_RXDMAE (0x1UL << 0) -/* Transmit DMA Enable bit */ -#define SSP_DMACR_MASK_TXDMAE (0x1UL << 1) - -/* - * SSP Integration Test control Register - SSP_ITCR - */ -#define SSP_ITCR_MASK_ITEN (0x1UL << 0) -#define SSP_ITCR_MASK_TESTFIFO (0x1UL << 1) - -/* - * SSP Integration Test Input Register - SSP_ITIP - */ -#define ITIP_MASK_SSPRXD (0x1UL << 0) -#define ITIP_MASK_SSPFSSIN (0x1UL << 1) -#define ITIP_MASK_SSPCLKIN (0x1UL << 2) -#define ITIP_MASK_RXDMAC (0x1UL << 3) -#define ITIP_MASK_TXDMAC (0x1UL << 4) -#define ITIP_MASK_SSPTXDIN (0x1UL << 5) - -/* - * SSP Integration Test output Register - SSP_ITOP - */ -#define ITOP_MASK_SSPTXD (0x1UL << 0) -#define ITOP_MASK_SSPFSSOUT (0x1UL << 1) -#define ITOP_MASK_SSPCLKOUT (0x1UL << 2) -#define ITOP_MASK_SSPOEn (0x1UL << 3) -#define ITOP_MASK_SSPCTLOEn (0x1UL << 4) -#define ITOP_MASK_RORINTR (0x1UL << 5) -#define ITOP_MASK_RTINTR (0x1UL << 6) -#define ITOP_MASK_RXINTR (0x1UL << 7) -#define ITOP_MASK_TXINTR (0x1UL << 8) -#define ITOP_MASK_INTR (0x1UL << 9) -#define ITOP_MASK_RXDMABREQ (0x1UL << 10) -#define ITOP_MASK_RXDMASREQ (0x1UL << 11) -#define ITOP_MASK_TXDMABREQ (0x1UL << 12) -#define ITOP_MASK_TXDMASREQ (0x1UL << 13) - -/* - * SSP Test Data Register - SSP_TDR - */ -#define TDR_MASK_TESTDATA (0xFFFFFFFF) - -/* - * Message State - * we use the spi_message.state (void *) pointer to - * hold a single state value, that's why all this - * (void *) casting is done here. - */ -#define STATE_START ((void *) 0) -#define STATE_RUNNING ((void *) 1) -#define STATE_DONE ((void *) 2) -#define STATE_ERROR ((void *) -1) - -/* - * SSP State - Whether Enabled or Disabled - */ -#define SSP_DISABLED (0) -#define SSP_ENABLED (1) - -/* - * SSP DMA State - Whether DMA Enabled or Disabled - */ -#define SSP_DMA_DISABLED (0) -#define SSP_DMA_ENABLED (1) - -/* - * SSP Clock Defaults - */ -#define SSP_DEFAULT_CLKRATE 0x2 -#define SSP_DEFAULT_PRESCALE 0x40 - -/* - * SSP Clock Parameter ranges - */ -#define CPSDVR_MIN 0x02 -#define CPSDVR_MAX 0xFE -#define SCR_MIN 0x00 -#define SCR_MAX 0xFF - -/* - * SSP Interrupt related Macros - */ -#define DEFAULT_SSP_REG_IMSC 0x0UL -#define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC -#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC) - -#define CLEAR_ALL_INTERRUPTS 0x3 - -#define SPI_POLLING_TIMEOUT 1000 - - -/* - * The type of reading going on on this chip - */ -enum ssp_reading { - READING_NULL, - READING_U8, - READING_U16, - READING_U32 -}; - -/** - * The type of writing going on on this chip - */ -enum ssp_writing { - WRITING_NULL, - WRITING_U8, - WRITING_U16, - WRITING_U32 -}; - -/** - * struct vendor_data - vendor-specific config parameters - * for PL022 derivates - * @fifodepth: depth of FIFOs (both) - * @max_bpw: maximum number of bits per word - * @unidir: supports unidirection transfers - * @extended_cr: 32 bit wide control register 0 with extra - * features and extra features in CR1 as found in the ST variants - * @pl023: supports a subset of the ST extensions called "PL023" - */ -struct vendor_data { - int fifodepth; - int max_bpw; - bool unidir; - bool extended_cr; - bool pl023; - bool loopback; -}; - -/** - * struct pl022 - This is the private SSP driver data structure - * @adev: AMBA device model hookup - * @vendor: vendor data for the IP block - * @phybase: the physical memory where the SSP device resides - * @virtbase: the virtual memory where the SSP is mapped - * @clk: outgoing clock "SPICLK" for the SPI bus - * @master: SPI framework hookup - * @master_info: controller-specific data from machine setup - * @workqueue: a workqueue on which any spi_message request is queued - * @pump_messages: work struct for scheduling work to the workqueue - * @queue_lock: spinlock to syncronise access to message queue - * @queue: message queue - * @busy: workqueue is busy - * @running: workqueue is running - * @pump_transfers: Tasklet used in Interrupt Transfer mode - * @cur_msg: Pointer to current spi_message being processed - * @cur_transfer: Pointer to current spi_transfer - * @cur_chip: pointer to current clients chip(assigned from controller_state) - * @tx: current position in TX buffer to be read - * @tx_end: end position in TX buffer to be read - * @rx: current position in RX buffer to be written - * @rx_end: end position in RX buffer to be written - * @read: the type of read currently going on - * @write: the type of write currently going on - * @exp_fifo_level: expected FIFO level - * @dma_rx_channel: optional channel for RX DMA - * @dma_tx_channel: optional channel for TX DMA - * @sgt_rx: scattertable for the RX transfer - * @sgt_tx: scattertable for the TX transfer - * @dummypage: a dummy page used for driving data on the bus with DMA - */ -struct pl022 { - struct amba_device *adev; - struct vendor_data *vendor; - resource_size_t phybase; - void __iomem *virtbase; - struct clk *clk; - struct spi_master *master; - struct pl022_ssp_controller *master_info; - /* Driver message queue */ - struct workqueue_struct *workqueue; - struct work_struct pump_messages; - spinlock_t queue_lock; - struct list_head queue; - bool busy; - bool running; - /* Message transfer pump */ - struct tasklet_struct pump_transfers; - struct spi_message *cur_msg; - struct spi_transfer *cur_transfer; - struct chip_data *cur_chip; - void *tx; - void *tx_end; - void *rx; - void *rx_end; - enum ssp_reading read; - enum ssp_writing write; - u32 exp_fifo_level; - /* DMA settings */ -#ifdef CONFIG_DMA_ENGINE - struct dma_chan *dma_rx_channel; - struct dma_chan *dma_tx_channel; - struct sg_table sgt_rx; - struct sg_table sgt_tx; - char *dummypage; -#endif -}; - -/** - * struct chip_data - To maintain runtime state of SSP for each client chip - * @cr0: Value of control register CR0 of SSP - on later ST variants this - * register is 32 bits wide rather than just 16 - * @cr1: Value of control register CR1 of SSP - * @dmacr: Value of DMA control Register of SSP - * @cpsr: Value of Clock prescale register - * @n_bytes: how many bytes(power of 2) reqd for a given data width of client - * @enable_dma: Whether to enable DMA or not - * @read: function ptr to be used to read when doing xfer for this chip - * @write: function ptr to be used to write when doing xfer for this chip - * @cs_control: chip select callback provided by chip - * @xfer_type: polling/interrupt/DMA - * - * Runtime state of the SSP controller, maintained per chip, - * This would be set according to the current message that would be served - */ -struct chip_data { - u32 cr0; - u16 cr1; - u16 dmacr; - u16 cpsr; - u8 n_bytes; - bool enable_dma; - enum ssp_reading read; - enum ssp_writing write; - void (*cs_control) (u32 command); - int xfer_type; -}; - -/** - * null_cs_control - Dummy chip select function - * @command: select/delect the chip - * - * If no chip select function is provided by client this is used as dummy - * chip select - */ -static void null_cs_control(u32 command) -{ - pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); -} - -/** - * giveback - current spi_message is over, schedule next message and call - * callback of this message. Assumes that caller already - * set message->status; dma and pio irqs are blocked - * @pl022: SSP driver private data structure - */ -static void giveback(struct pl022 *pl022) -{ - struct spi_transfer *last_transfer; - unsigned long flags; - struct spi_message *msg; - void (*curr_cs_control) (u32 command); - - /* - * This local reference to the chip select function - * is needed because we set curr_chip to NULL - * as a step toward termininating the message. - */ - curr_cs_control = pl022->cur_chip->cs_control; - spin_lock_irqsave(&pl022->queue_lock, flags); - msg = pl022->cur_msg; - pl022->cur_msg = NULL; - pl022->cur_transfer = NULL; - pl022->cur_chip = NULL; - queue_work(pl022->workqueue, &pl022->pump_messages); - spin_unlock_irqrestore(&pl022->queue_lock, flags); - - last_transfer = list_entry(msg->transfers.prev, - struct spi_transfer, - transfer_list); - - /* Delay if requested before any change in chip select */ - if (last_transfer->delay_usecs) - /* - * FIXME: This runs in interrupt context. - * Is this really smart? - */ - udelay(last_transfer->delay_usecs); - - /* - * Drop chip select UNLESS cs_change is true or we are returning - * a message with an error, or next message is for another chip - */ - if (!last_transfer->cs_change) - curr_cs_control(SSP_CHIP_DESELECT); - else { - struct spi_message *next_msg; - - /* Holding of cs was hinted, but we need to make sure - * the next message is for the same chip. Don't waste - * time with the following tests unless this was hinted. - * - * We cannot postpone this until pump_messages, because - * after calling msg->complete (below) the driver that - * sent the current message could be unloaded, which - * could invalidate the cs_control() callback... - */ - - /* get a pointer to the next message, if any */ - spin_lock_irqsave(&pl022->queue_lock, flags); - if (list_empty(&pl022->queue)) - next_msg = NULL; - else - next_msg = list_entry(pl022->queue.next, - struct spi_message, queue); - spin_unlock_irqrestore(&pl022->queue_lock, flags); - - /* see if the next and current messages point - * to the same chip - */ - if (next_msg && next_msg->spi != msg->spi) - next_msg = NULL; - if (!next_msg || msg->state == STATE_ERROR) - curr_cs_control(SSP_CHIP_DESELECT); - } - msg->state = NULL; - if (msg->complete) - msg->complete(msg->context); - /* This message is completed, so let's turn off the clocks & power */ - clk_disable(pl022->clk); - amba_pclk_disable(pl022->adev); - amba_vcore_disable(pl022->adev); -} - -/** - * flush - flush the FIFO to reach a clean state - * @pl022: SSP driver private data structure - */ -static int flush(struct pl022 *pl022) -{ - unsigned long limit = loops_per_jiffy << 1; - - dev_dbg(&pl022->adev->dev, "flush\n"); - do { - while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) - readw(SSP_DR(pl022->virtbase)); - } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); - - pl022->exp_fifo_level = 0; - - return limit; -} - -/** - * restore_state - Load configuration of current chip - * @pl022: SSP driver private data structure - */ -static void restore_state(struct pl022 *pl022) -{ - struct chip_data *chip = pl022->cur_chip; - - if (pl022->vendor->extended_cr) - writel(chip->cr0, SSP_CR0(pl022->virtbase)); - else - writew(chip->cr0, SSP_CR0(pl022->virtbase)); - writew(chip->cr1, SSP_CR1(pl022->virtbase)); - writew(chip->dmacr, SSP_DMACR(pl022->virtbase)); - writew(chip->cpsr, SSP_CPSR(pl022->virtbase)); - writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); - writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); -} - -/* - * Default SSP Register Values - */ -#define DEFAULT_SSP_REG_CR0 ( \ - GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS, 0) | \ - GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF, 4) | \ - GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \ - GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \ - GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \ -) - -/* ST versions have slightly different bit layout */ -#define DEFAULT_SSP_REG_CR0_ST ( \ - GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0) | \ - GEN_MASK_BITS(SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, SSP_CR0_MASK_HALFDUP_ST, 5) | \ - GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \ - GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \ - GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) | \ - GEN_MASK_BITS(SSP_BITS_8, SSP_CR0_MASK_CSS_ST, 16) | \ - GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \ -) - -/* The PL023 version is slightly different again */ -#define DEFAULT_SSP_REG_CR0_ST_PL023 ( \ - GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0) | \ - GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \ - GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \ - GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \ -) - -#define DEFAULT_SSP_REG_CR1 ( \ - GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \ - GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ - GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \ - GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) \ -) - -/* ST versions extend this register to use all 16 bits */ -#define DEFAULT_SSP_REG_CR1_ST ( \ - DEFAULT_SSP_REG_CR1 | \ - GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \ - GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \ - GEN_MASK_BITS(SSP_MWIRE_WAIT_ZERO, SSP_CR1_MASK_MWAIT_ST, 6) |\ - GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \ - GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \ -) - -/* - * The PL023 variant has further differences: no loopback mode, no microwire - * support, and a new clock feedback delay setting. - */ -#define DEFAULT_SSP_REG_CR1_ST_PL023 ( \ - GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ - GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \ - GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \ - GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \ - GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \ - GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \ - GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) | \ - GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \ -) - -#define DEFAULT_SSP_REG_CPSR ( \ - GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ -) - -#define DEFAULT_SSP_REG_DMACR (\ - GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_RXDMAE, 0) | \ - GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \ -) - -/** - * load_ssp_default_config - Load default configuration for SSP - * @pl022: SSP driver private data structure - */ -static void load_ssp_default_config(struct pl022 *pl022) -{ - if (pl022->vendor->pl023) { - writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase)); - writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase)); - } else if (pl022->vendor->extended_cr) { - writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase)); - writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase)); - } else { - writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); - writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase)); - } - writew(DEFAULT_SSP_REG_DMACR, SSP_DMACR(pl022->virtbase)); - writew(DEFAULT_SSP_REG_CPSR, SSP_CPSR(pl022->virtbase)); - writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); - writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); -} - -/** - * This will write to TX and read from RX according to the parameters - * set in pl022. - */ -static void readwriter(struct pl022 *pl022) -{ - - /* - * The FIFO depth is different between primecell variants. - * I believe filling in too much in the FIFO might cause - * errons in 8bit wide transfers on ARM variants (just 8 words - * FIFO, means only 8x8 = 64 bits in FIFO) at least. - * - * To prevent this issue, the TX FIFO is only filled to the - * unused RX FIFO fill length, regardless of what the TX - * FIFO status flag indicates. - */ - dev_dbg(&pl022->adev->dev, - "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", - __func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end); - - /* Read as much as you can */ - while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) - && (pl022->rx < pl022->rx_end)) { - switch (pl022->read) { - case READING_NULL: - readw(SSP_DR(pl022->virtbase)); - break; - case READING_U8: - *(u8 *) (pl022->rx) = - readw(SSP_DR(pl022->virtbase)) & 0xFFU; - break; - case READING_U16: - *(u16 *) (pl022->rx) = - (u16) readw(SSP_DR(pl022->virtbase)); - break; - case READING_U32: - *(u32 *) (pl022->rx) = - readl(SSP_DR(pl022->virtbase)); - break; - } - pl022->rx += (pl022->cur_chip->n_bytes); - pl022->exp_fifo_level--; - } - /* - * Write as much as possible up to the RX FIFO size - */ - while ((pl022->exp_fifo_level < pl022->vendor->fifodepth) - && (pl022->tx < pl022->tx_end)) { - switch (pl022->write) { - case WRITING_NULL: - writew(0x0, SSP_DR(pl022->virtbase)); - break; - case WRITING_U8: - writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase)); - break; - case WRITING_U16: - writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase)); - break; - case WRITING_U32: - writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase)); - break; - } - pl022->tx += (pl022->cur_chip->n_bytes); - pl022->exp_fifo_level++; - /* - * This inner reader takes care of things appearing in the RX - * FIFO as we're transmitting. This will happen a lot since the - * clock starts running when you put things into the TX FIFO, - * and then things are continuously clocked into the RX FIFO. - */ - while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) - && (pl022->rx < pl022->rx_end)) { - switch (pl022->read) { - case READING_NULL: - readw(SSP_DR(pl022->virtbase)); - break; - case READING_U8: - *(u8 *) (pl022->rx) = - readw(SSP_DR(pl022->virtbase)) & 0xFFU; - break; - case READING_U16: - *(u16 *) (pl022->rx) = - (u16) readw(SSP_DR(pl022->virtbase)); - break; - case READING_U32: - *(u32 *) (pl022->rx) = - readl(SSP_DR(pl022->virtbase)); - break; - } - pl022->rx += (pl022->cur_chip->n_bytes); - pl022->exp_fifo_level--; - } - } - /* - * When we exit here the TX FIFO should be full and the RX FIFO - * should be empty - */ -} - - -/** - * next_transfer - Move to the Next transfer in the current spi message - * @pl022: SSP driver private data structure - * - * This function moves though the linked list of spi transfers in the - * current spi message and returns with the state of current spi - * message i.e whether its last transfer is done(STATE_DONE) or - * Next transfer is ready(STATE_RUNNING) - */ -static void *next_transfer(struct pl022 *pl022) -{ - struct spi_message *msg = pl022->cur_msg; - struct spi_transfer *trans = pl022->cur_transfer; - - /* Move to next transfer */ - if (trans->transfer_list.next != &msg->transfers) { - pl022->cur_transfer = - list_entry(trans->transfer_list.next, - struct spi_transfer, transfer_list); - return STATE_RUNNING; - } - return STATE_DONE; -} - -/* - * This DMA functionality is only compiled in if we have - * access to the generic DMA devices/DMA engine. - */ -#ifdef CONFIG_DMA_ENGINE -static void unmap_free_dma_scatter(struct pl022 *pl022) -{ - /* Unmap and free the SG tables */ - dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl, - pl022->sgt_tx.nents, DMA_TO_DEVICE); - dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl, - pl022->sgt_rx.nents, DMA_FROM_DEVICE); - sg_free_table(&pl022->sgt_rx); - sg_free_table(&pl022->sgt_tx); -} - -static void dma_callback(void *data) -{ - struct pl022 *pl022 = data; - struct spi_message *msg = pl022->cur_msg; - - BUG_ON(!pl022->sgt_rx.sgl); - -#ifdef VERBOSE_DEBUG - /* - * Optionally dump out buffers to inspect contents, this is - * good if you want to convince yourself that the loopback - * read/write contents are the same, when adopting to a new - * DMA engine. - */ - { - struct scatterlist *sg; - unsigned int i; - - dma_sync_sg_for_cpu(&pl022->adev->dev, - pl022->sgt_rx.sgl, - pl022->sgt_rx.nents, - DMA_FROM_DEVICE); - - for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) { - dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i); - print_hex_dump(KERN_ERR, "SPI RX: ", - DUMP_PREFIX_OFFSET, - 16, - 1, - sg_virt(sg), - sg_dma_len(sg), - 1); - } - for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) { - dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i); - print_hex_dump(KERN_ERR, "SPI TX: ", - DUMP_PREFIX_OFFSET, - 16, - 1, - sg_virt(sg), - sg_dma_len(sg), - 1); - } - } -#endif - - unmap_free_dma_scatter(pl022); - - /* Update total bytes transferred */ - msg->actual_length += pl022->cur_transfer->len; - if (pl022->cur_transfer->cs_change) - pl022->cur_chip-> - cs_control(SSP_CHIP_DESELECT); - - /* Move to next transfer */ - msg->state = next_transfer(pl022); - tasklet_schedule(&pl022->pump_transfers); -} - -static void setup_dma_scatter(struct pl022 *pl022, - void *buffer, - unsigned int length, - struct sg_table *sgtab) -{ - struct scatterlist *sg; - int bytesleft = length; - void *bufp = buffer; - int mapbytes; - int i; - - if (buffer) { - for_each_sg(sgtab->sgl, sg, sgtab->nents, i) { - /* - * If there are less bytes left than what fits - * in the current page (plus page alignment offset) - * we just feed in this, else we stuff in as much - * as we can. - */ - if (bytesleft < (PAGE_SIZE - offset_in_page(bufp))) - mapbytes = bytesleft; - else - mapbytes = PAGE_SIZE - offset_in_page(bufp); - sg_set_page(sg, virt_to_page(bufp), - mapbytes, offset_in_page(bufp)); - bufp += mapbytes; - bytesleft -= mapbytes; - dev_dbg(&pl022->adev->dev, - "set RX/TX target page @ %p, %d bytes, %d left\n", - bufp, mapbytes, bytesleft); - } - } else { - /* Map the dummy buffer on every page */ - for_each_sg(sgtab->sgl, sg, sgtab->nents, i) { - if (bytesleft < PAGE_SIZE) - mapbytes = bytesleft; - else - mapbytes = PAGE_SIZE; - sg_set_page(sg, virt_to_page(pl022->dummypage), - mapbytes, 0); - bytesleft -= mapbytes; - dev_dbg(&pl022->adev->dev, - "set RX/TX to dummy page %d bytes, %d left\n", - mapbytes, bytesleft); - - } - } - BUG_ON(bytesleft); -} - -/** - * configure_dma - configures the channels for the next transfer - * @pl022: SSP driver's private data structure - */ -static int configure_dma(struct pl022 *pl022) -{ - struct dma_slave_config rx_conf = { - .src_addr = SSP_DR(pl022->phybase), - .direction = DMA_FROM_DEVICE, - .src_maxburst = pl022->vendor->fifodepth >> 1, - }; - struct dma_slave_config tx_conf = { - .dst_addr = SSP_DR(pl022->phybase), - .direction = DMA_TO_DEVICE, - .dst_maxburst = pl022->vendor->fifodepth >> 1, - }; - unsigned int pages; - int ret; - int rx_sglen, tx_sglen; - struct dma_chan *rxchan = pl022->dma_rx_channel; - struct dma_chan *txchan = pl022->dma_tx_channel; - struct dma_async_tx_descriptor *rxdesc; - struct dma_async_tx_descriptor *txdesc; - - /* Check that the channels are available */ - if (!rxchan || !txchan) - return -ENODEV; - - switch (pl022->read) { - case READING_NULL: - /* Use the same as for writing */ - rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; - break; - case READING_U8: - rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - break; - case READING_U16: - rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - break; - case READING_U32: - rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - break; - } - - switch (pl022->write) { - case WRITING_NULL: - /* Use the same as for reading */ - tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; - break; - case WRITING_U8: - tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - break; - case WRITING_U16: - tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - break; - case WRITING_U32: - tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - break; - } - - /* SPI pecularity: we need to read and write the same width */ - if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) - rx_conf.src_addr_width = tx_conf.dst_addr_width; - if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) - tx_conf.dst_addr_width = rx_conf.src_addr_width; - BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width); - - dmaengine_slave_config(rxchan, &rx_conf); - dmaengine_slave_config(txchan, &tx_conf); - - /* Create sglists for the transfers */ - pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; - dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages); - - ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL); - if (ret) - goto err_alloc_rx_sg; - - ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL); - if (ret) - goto err_alloc_tx_sg; - - /* Fill in the scatterlists for the RX+TX buffers */ - setup_dma_scatter(pl022, pl022->rx, - pl022->cur_transfer->len, &pl022->sgt_rx); - setup_dma_scatter(pl022, pl022->tx, - pl022->cur_transfer->len, &pl022->sgt_tx); - - /* Map DMA buffers */ - rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl, - pl022->sgt_rx.nents, DMA_FROM_DEVICE); - if (!rx_sglen) - goto err_rx_sgmap; - - tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl, - pl022->sgt_tx.nents, DMA_TO_DEVICE); - if (!tx_sglen) - goto err_tx_sgmap; - - /* Send both scatterlists */ - rxdesc = rxchan->device->device_prep_slave_sg(rxchan, - pl022->sgt_rx.sgl, - rx_sglen, - DMA_FROM_DEVICE, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!rxdesc) - goto err_rxdesc; - - txdesc = txchan->device->device_prep_slave_sg(txchan, - pl022->sgt_tx.sgl, - tx_sglen, - DMA_TO_DEVICE, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!txdesc) - goto err_txdesc; - - /* Put the callback on the RX transfer only, that should finish last */ - rxdesc->callback = dma_callback; - rxdesc->callback_param = pl022; - - /* Submit and fire RX and TX with TX last so we're ready to read! */ - dmaengine_submit(rxdesc); - dmaengine_submit(txdesc); - dma_async_issue_pending(rxchan); - dma_async_issue_pending(txchan); - - return 0; - -err_txdesc: - dmaengine_terminate_all(txchan); -err_rxdesc: - dmaengine_terminate_all(rxchan); - dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl, - pl022->sgt_tx.nents, DMA_TO_DEVICE); -err_tx_sgmap: - dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, - pl022->sgt_tx.nents, DMA_FROM_DEVICE); -err_rx_sgmap: - sg_free_table(&pl022->sgt_tx); -err_alloc_tx_sg: - sg_free_table(&pl022->sgt_rx); -err_alloc_rx_sg: - return -ENOMEM; -} - -static int __init pl022_dma_probe(struct pl022 *pl022) -{ - dma_cap_mask_t mask; - - /* Try to acquire a generic DMA engine slave channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - /* - * We need both RX and TX channels to do DMA, else do none - * of them. - */ - pl022->dma_rx_channel = dma_request_channel(mask, - pl022->master_info->dma_filter, - pl022->master_info->dma_rx_param); - if (!pl022->dma_rx_channel) { - dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n"); - goto err_no_rxchan; - } - - pl022->dma_tx_channel = dma_request_channel(mask, - pl022->master_info->dma_filter, - pl022->master_info->dma_tx_param); - if (!pl022->dma_tx_channel) { - dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n"); - goto err_no_txchan; - } - - pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!pl022->dummypage) { - dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n"); - goto err_no_dummypage; - } - - dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n", - dma_chan_name(pl022->dma_rx_channel), - dma_chan_name(pl022->dma_tx_channel)); - - return 0; - -err_no_dummypage: - dma_release_channel(pl022->dma_tx_channel); -err_no_txchan: - dma_release_channel(pl022->dma_rx_channel); - pl022->dma_rx_channel = NULL; -err_no_rxchan: - dev_err(&pl022->adev->dev, - "Failed to work in dma mode, work without dma!\n"); - return -ENODEV; -} - -static void terminate_dma(struct pl022 *pl022) -{ - struct dma_chan *rxchan = pl022->dma_rx_channel; - struct dma_chan *txchan = pl022->dma_tx_channel; - - dmaengine_terminate_all(rxchan); - dmaengine_terminate_all(txchan); - unmap_free_dma_scatter(pl022); -} - -static void pl022_dma_remove(struct pl022 *pl022) -{ - if (pl022->busy) - terminate_dma(pl022); - if (pl022->dma_tx_channel) - dma_release_channel(pl022->dma_tx_channel); - if (pl022->dma_rx_channel) - dma_release_channel(pl022->dma_rx_channel); - kfree(pl022->dummypage); -} - -#else -static inline int configure_dma(struct pl022 *pl022) -{ - return -ENODEV; -} - -static inline int pl022_dma_probe(struct pl022 *pl022) -{ - return 0; -} - -static inline void pl022_dma_remove(struct pl022 *pl022) -{ -} -#endif - -/** - * pl022_interrupt_handler - Interrupt handler for SSP controller - * - * This function handles interrupts generated for an interrupt based transfer. - * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the - * current message's state as STATE_ERROR and schedule the tasklet - * pump_transfers which will do the postprocessing of the current message by - * calling giveback(). Otherwise it reads data from RX FIFO till there is no - * more data, and writes data in TX FIFO till it is not full. If we complete - * the transfer we move to the next transfer and schedule the tasklet. - */ -static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) -{ - struct pl022 *pl022 = dev_id; - struct spi_message *msg = pl022->cur_msg; - u16 irq_status = 0; - u16 flag = 0; - - if (unlikely(!msg)) { - dev_err(&pl022->adev->dev, - "bad message state in interrupt handler"); - /* Never fail */ - return IRQ_HANDLED; - } - - /* Read the Interrupt Status Register */ - irq_status = readw(SSP_MIS(pl022->virtbase)); - - if (unlikely(!irq_status)) - return IRQ_NONE; - - /* - * This handles the FIFO interrupts, the timeout - * interrupts are flatly ignored, they cannot be - * trusted. - */ - if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) { - /* - * Overrun interrupt - bail out since our Data has been - * corrupted - */ - dev_err(&pl022->adev->dev, "FIFO overrun\n"); - if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF) - dev_err(&pl022->adev->dev, - "RXFIFO is full\n"); - if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) - dev_err(&pl022->adev->dev, - "TXFIFO is full\n"); - - /* - * Disable and clear interrupts, disable SSP, - * mark message with bad status so it can be - * retried. - */ - writew(DISABLE_ALL_INTERRUPTS, - SSP_IMSC(pl022->virtbase)); - writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); - writew((readw(SSP_CR1(pl022->virtbase)) & - (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); - msg->state = STATE_ERROR; - - /* Schedule message queue handler */ - tasklet_schedule(&pl022->pump_transfers); - return IRQ_HANDLED; - } - - readwriter(pl022); - - if ((pl022->tx == pl022->tx_end) && (flag == 0)) { - flag = 1; - /* Disable Transmit interrupt */ - writew(readw(SSP_IMSC(pl022->virtbase)) & - (~SSP_IMSC_MASK_TXIM), - SSP_IMSC(pl022->virtbase)); - } - - /* - * Since all transactions must write as much as shall be read, - * we can conclude the entire transaction once RX is complete. - * At this point, all TX will always be finished. - */ - if (pl022->rx >= pl022->rx_end) { - writew(DISABLE_ALL_INTERRUPTS, - SSP_IMSC(pl022->virtbase)); - writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); - if (unlikely(pl022->rx > pl022->rx_end)) { - dev_warn(&pl022->adev->dev, "read %u surplus " - "bytes (did you request an odd " - "number of bytes on a 16bit bus?)\n", - (u32) (pl022->rx - pl022->rx_end)); - } - /* Update total bytes transferred */ - msg->actual_length += pl022->cur_transfer->len; - if (pl022->cur_transfer->cs_change) - pl022->cur_chip-> - cs_control(SSP_CHIP_DESELECT); - /* Move to next transfer */ - msg->state = next_transfer(pl022); - tasklet_schedule(&pl022->pump_transfers); - return IRQ_HANDLED; - } - - return IRQ_HANDLED; -} - -/** - * This sets up the pointers to memory for the next message to - * send out on the SPI bus. - */ -static int set_up_next_transfer(struct pl022 *pl022, - struct spi_transfer *transfer) -{ - int residue; - - /* Sanity check the message for this bus width */ - residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes; - if (unlikely(residue != 0)) { - dev_err(&pl022->adev->dev, - "message of %u bytes to transmit but the current " - "chip bus has a data width of %u bytes!\n", - pl022->cur_transfer->len, - pl022->cur_chip->n_bytes); - dev_err(&pl022->adev->dev, "skipping this message\n"); - return -EIO; - } - pl022->tx = (void *)transfer->tx_buf; - pl022->tx_end = pl022->tx + pl022->cur_transfer->len; - pl022->rx = (void *)transfer->rx_buf; - pl022->rx_end = pl022->rx + pl022->cur_transfer->len; - pl022->write = - pl022->tx ? pl022->cur_chip->write : WRITING_NULL; - pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL; - return 0; -} - -/** - * pump_transfers - Tasklet function which schedules next transfer - * when running in interrupt or DMA transfer mode. - * @data: SSP driver private data structure - * - */ -static void pump_transfers(unsigned long data) -{ - struct pl022 *pl022 = (struct pl022 *) data; - struct spi_message *message = NULL; - struct spi_transfer *transfer = NULL; - struct spi_transfer *previous = NULL; - - /* Get current state information */ - message = pl022->cur_msg; - transfer = pl022->cur_transfer; - - /* Handle for abort */ - if (message->state == STATE_ERROR) { - message->status = -EIO; - giveback(pl022); - return; - } - - /* Handle end of message */ - if (message->state == STATE_DONE) { - message->status = 0; - giveback(pl022); - return; - } - - /* Delay if requested at end of transfer before CS change */ - if (message->state == STATE_RUNNING) { - previous = list_entry(transfer->transfer_list.prev, - struct spi_transfer, - transfer_list); - if (previous->delay_usecs) - /* - * FIXME: This runs in interrupt context. - * Is this really smart? - */ - udelay(previous->delay_usecs); - - /* Drop chip select only if cs_change is requested */ - if (previous->cs_change) - pl022->cur_chip->cs_control(SSP_CHIP_SELECT); - } else { - /* STATE_START */ - message->state = STATE_RUNNING; - } - - if (set_up_next_transfer(pl022, transfer)) { - message->state = STATE_ERROR; - message->status = -EIO; - giveback(pl022); - return; - } - /* Flush the FIFOs and let's go! */ - flush(pl022); - - if (pl022->cur_chip->enable_dma) { - if (configure_dma(pl022)) { - dev_dbg(&pl022->adev->dev, - "configuration of DMA failed, fall back to interrupt mode\n"); - goto err_config_dma; - } - return; - } - -err_config_dma: - writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); -} - -static void do_interrupt_dma_transfer(struct pl022 *pl022) -{ - u32 irqflags = ENABLE_ALL_INTERRUPTS; - - /* Enable target chip */ - pl022->cur_chip->cs_control(SSP_CHIP_SELECT); - if (set_up_next_transfer(pl022, pl022->cur_transfer)) { - /* Error path */ - pl022->cur_msg->state = STATE_ERROR; - pl022->cur_msg->status = -EIO; - giveback(pl022); - return; - } - /* If we're using DMA, set up DMA here */ - if (pl022->cur_chip->enable_dma) { - /* Configure DMA transfer */ - if (configure_dma(pl022)) { - dev_dbg(&pl022->adev->dev, - "configuration of DMA failed, fall back to interrupt mode\n"); - goto err_config_dma; - } - /* Disable interrupts in DMA mode, IRQ from DMA controller */ - irqflags = DISABLE_ALL_INTERRUPTS; - } -err_config_dma: - /* Enable SSP, turn on interrupts */ - writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), - SSP_CR1(pl022->virtbase)); - writew(irqflags, SSP_IMSC(pl022->virtbase)); -} - -static void do_polling_transfer(struct pl022 *pl022) -{ - struct spi_message *message = NULL; - struct spi_transfer *transfer = NULL; - struct spi_transfer *previous = NULL; - struct chip_data *chip; - unsigned long time, timeout; - - chip = pl022->cur_chip; - message = pl022->cur_msg; - - while (message->state != STATE_DONE) { - /* Handle for abort */ - if (message->state == STATE_ERROR) - break; - transfer = pl022->cur_transfer; - - /* Delay if requested at end of transfer */ - if (message->state == STATE_RUNNING) { - previous = - list_entry(transfer->transfer_list.prev, - struct spi_transfer, transfer_list); - if (previous->delay_usecs) - udelay(previous->delay_usecs); - if (previous->cs_change) - pl022->cur_chip->cs_control(SSP_CHIP_SELECT); - } else { - /* STATE_START */ - message->state = STATE_RUNNING; - pl022->cur_chip->cs_control(SSP_CHIP_SELECT); - } - - /* Configuration Changing Per Transfer */ - if (set_up_next_transfer(pl022, transfer)) { - /* Error path */ - message->state = STATE_ERROR; - break; - } - /* Flush FIFOs and enable SSP */ - flush(pl022); - writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), - SSP_CR1(pl022->virtbase)); - - dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); - - timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); - while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { - time = jiffies; - readwriter(pl022); - if (time_after(time, timeout)) { - dev_warn(&pl022->adev->dev, - "%s: timeout!\n", __func__); - message->state = STATE_ERROR; - goto out; - } - cpu_relax(); - } - - /* Update total byte transferred */ - message->actual_length += pl022->cur_transfer->len; - if (pl022->cur_transfer->cs_change) - pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); - /* Move to next transfer */ - message->state = next_transfer(pl022); - } -out: - /* Handle end of message */ - if (message->state == STATE_DONE) - message->status = 0; - else - message->status = -EIO; - - giveback(pl022); - return; -} - -/** - * pump_messages - Workqueue function which processes spi message queue - * @data: pointer to private data of SSP driver - * - * This function checks if there is any spi message in the queue that - * needs processing and delegate control to appropriate function - * do_polling_transfer()/do_interrupt_dma_transfer() - * based on the kind of the transfer - * - */ -static void pump_messages(struct work_struct *work) -{ - struct pl022 *pl022 = - container_of(work, struct pl022, pump_messages); - unsigned long flags; - - /* Lock queue and check for queue work */ - spin_lock_irqsave(&pl022->queue_lock, flags); - if (list_empty(&pl022->queue) || !pl022->running) { - pl022->busy = false; - spin_unlock_irqrestore(&pl022->queue_lock, flags); - return; - } - /* Make sure we are not already running a message */ - if (pl022->cur_msg) { - spin_unlock_irqrestore(&pl022->queue_lock, flags); - return; - } - /* Extract head of queue */ - pl022->cur_msg = - list_entry(pl022->queue.next, struct spi_message, queue); - - list_del_init(&pl022->cur_msg->queue); - pl022->busy = true; - spin_unlock_irqrestore(&pl022->queue_lock, flags); - - /* Initial message state */ - pl022->cur_msg->state = STATE_START; - pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next, - struct spi_transfer, - transfer_list); - - /* Setup the SPI using the per chip configuration */ - pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); - /* - * We enable the core voltage and clocks here, then the clocks - * and core will be disabled when giveback() is called in each method - * (poll/interrupt/DMA) - */ - amba_vcore_enable(pl022->adev); - amba_pclk_enable(pl022->adev); - clk_enable(pl022->clk); - restore_state(pl022); - flush(pl022); - - if (pl022->cur_chip->xfer_type == POLLING_TRANSFER) - do_polling_transfer(pl022); - else - do_interrupt_dma_transfer(pl022); -} - - -static int __init init_queue(struct pl022 *pl022) -{ - INIT_LIST_HEAD(&pl022->queue); - spin_lock_init(&pl022->queue_lock); - - pl022->running = false; - pl022->busy = false; - - tasklet_init(&pl022->pump_transfers, - pump_transfers, (unsigned long)pl022); - - INIT_WORK(&pl022->pump_messages, pump_messages); - pl022->workqueue = create_singlethread_workqueue( - dev_name(pl022->master->dev.parent)); - if (pl022->workqueue == NULL) - return -EBUSY; - - return 0; -} - - -static int start_queue(struct pl022 *pl022) -{ - unsigned long flags; - - spin_lock_irqsave(&pl022->queue_lock, flags); - - if (pl022->running || pl022->busy) { - spin_unlock_irqrestore(&pl022->queue_lock, flags); - return -EBUSY; - } - - pl022->running = true; - pl022->cur_msg = NULL; - pl022->cur_transfer = NULL; - pl022->cur_chip = NULL; - spin_unlock_irqrestore(&pl022->queue_lock, flags); - - queue_work(pl022->workqueue, &pl022->pump_messages); - - return 0; -} - - -static int stop_que