diff options
Diffstat (limited to 'drivers/spi')
| -rw-r--r-- | drivers/spi/Kconfig | 48 | ||||
| -rw-r--r-- | drivers/spi/Makefile | 111 | ||||
| -rw-r--r-- | drivers/spi/atmel_spi.h | 167 | ||||
| -rw-r--r-- | drivers/spi/spi-altera.c (renamed from drivers/spi/spi_altera.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-ath79.c (renamed from drivers/spi/ath79_spi.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-atmel.c (renamed from drivers/spi/atmel_spi.c) | 155 | ||||
| -rw-r--r-- | drivers/spi/spi-au1550.c (renamed from drivers/spi/au1550_spi.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-bfin-sport.c (renamed from drivers/spi/spi_bfin_sport.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-bfin5xx.c (renamed from drivers/spi/spi_bfin5xx.c) | 225 | ||||
| -rw-r--r-- | drivers/spi/spi-bitbang-txrx.h (renamed from drivers/spi/spi_bitbang_txrx.h) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-bitbang.c (renamed from drivers/spi/spi_bitbang.c) | 8 | ||||
| -rw-r--r-- | drivers/spi/spi-butterfly.c (renamed from drivers/spi/spi_butterfly.c) | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-coldfire-qspi.c (renamed from drivers/spi/coldfire_qspi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-davinci.c (renamed from drivers/spi/davinci_spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-dw-mid.c (renamed from drivers/spi/dw_spi_mid.c) | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-dw-mmio.c (renamed from drivers/spi/dw_spi_mmio.c) | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-dw-pci.c (renamed from drivers/spi/dw_spi_pci.c) | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-dw.c (renamed from drivers/spi/dw_spi.c) | 8 | ||||
| -rw-r--r-- | drivers/spi/spi-dw.h (renamed from drivers/spi/dw_spi.h) | 1 | ||||
| -rw-r--r-- | drivers/spi/spi-ep93xx.c (renamed from drivers/spi/ep93xx_spi.c) | 303 | ||||
| -rw-r--r-- | drivers/spi/spi-fsl-espi.c (renamed from drivers/spi/spi_fsl_espi.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-fsl-lib.c (renamed from drivers/spi/spi_fsl_lib.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-fsl-lib.h (renamed from drivers/spi/spi_fsl_lib.h) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-fsl-spi.c (renamed from drivers/spi/spi_fsl_spi.c) | 30 | ||||
| -rw-r--r-- | drivers/spi/spi-gpio.c (renamed from drivers/spi/spi_gpio.c) | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-imx.c (renamed from drivers/spi/spi_imx.c) | 466 | ||||
| -rw-r--r-- | drivers/spi/spi-lm70llp.c (renamed from drivers/spi/spi_lm70llp.c) | 4 | ||||
| -rw-r--r-- | drivers/spi/spi-mpc512x-psc.c (renamed from drivers/spi/mpc512x_psc_spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-mpc52xx-psc.c (renamed from drivers/spi/mpc52xx_psc_spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-mpc52xx.c (renamed from drivers/spi/mpc52xx_spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-nuc900.c (renamed from drivers/spi/spi_nuc900.c) | 5 | ||||
| -rw-r--r-- | drivers/spi/spi-oc-tiny.c (renamed from drivers/spi/spi_oc_tiny.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-omap-100k.c (renamed from drivers/spi/omap_spi_100k.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-omap-uwire.c (renamed from drivers/spi/omap_uwire.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c (renamed from drivers/spi/omap2_mcspi.c) | 12 | ||||
| -rw-r--r-- | drivers/spi/spi-orion.c (renamed from drivers/spi/orion_spi.c) | 8 | ||||
| -rw-r--r-- | drivers/spi/spi-pl022.c (renamed from drivers/spi/amba-pl022.c) | 123 | ||||
| -rw-r--r-- | drivers/spi/spi-ppc4xx.c (renamed from drivers/spi/spi_ppc4xx.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-pxa2xx-pci.c (renamed from drivers/spi/pxa2xx_spi_pci.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-pxa2xx.c (renamed from drivers/spi/pxa2xx_spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-s3c24xx-fiq.S (renamed from drivers/spi/spi_s3c24xx_fiq.S) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-s3c24xx-fiq.h (renamed from drivers/spi/spi_s3c24xx_fiq.h) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-s3c24xx.c (renamed from drivers/spi/spi_s3c24xx.c) | 5 | ||||
| -rw-r--r-- | drivers/spi/spi-s3c64xx.c (renamed from drivers/spi/spi_s3c64xx.c) | 7 | ||||
| -rw-r--r-- | drivers/spi/spi-sh-msiof.c (renamed from drivers/spi/spi_sh_msiof.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-sh-sci.c (renamed from drivers/spi/spi_sh_sci.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-sh.c (renamed from drivers/spi/spi_sh.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-stmp.c (renamed from drivers/spi/spi_stmp.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-tegra.c (renamed from drivers/spi/spi_tegra.c) | 20 | ||||
| -rw-r--r-- | drivers/spi/spi-ti-ssp.c (renamed from drivers/spi/ti-ssp-spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi-tle62x0.c (renamed from drivers/spi/tle62x0.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-topcliff-pch.c (renamed from drivers/spi/spi_topcliff_pch.c) | 1158 | ||||
| -rw-r--r-- | drivers/spi/spi-txx9.c (renamed from drivers/spi/spi_txx9.c) | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-xilinx.c (renamed from drivers/spi/xilinx_spi.c) | 0 | ||||
| -rw-r--r-- | drivers/spi/spi.c | 2 | ||||
| -rw-r--r-- | drivers/spi/spi_s3c24xx_gpio.c | 201 | ||||
| -rw-r--r-- | drivers/spi/spidev.c | 2 | 
57 files changed, 1797 insertions, 1314 deletions
| diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index de35c3ad8a69..52e2900d9d8e 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 @@ -169,21 +154,6 @@ config SPI_GPIO  	  GPIO operations, you should be able to leverage that for better  	  speed with a custom version of this driver; see the source code. -config SPI_IMX_VER_IMX1 -	def_bool y if SOC_IMX1 - -config SPI_IMX_VER_0_0 -	def_bool y if SOC_IMX21 || SOC_IMX27 - -config SPI_IMX_VER_0_4 -	def_bool y if SOC_IMX31 - -config SPI_IMX_VER_0_7 -	def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53 - -config SPI_IMX_VER_2_3 -	def_bool y if SOC_IMX51 || SOC_IMX53 -  config SPI_IMX  	tristate "Freescale i.MX SPI controllers"  	depends on ARCH_MXC @@ -328,16 +298,6 @@ config SPI_S3C24XX_FIQ  	  no free DMA channels, or when doing transfers that required both  	  TX and RX data paths. -config SPI_S3C24XX_GPIO -	tristate "Samsung S3C24XX series SPI by GPIO" -	depends on ARCH_S3C2410 && EXPERIMENTAL -	select SPI_BITBANG -	help -	  SPI driver for Samsung S3C24XX series ARM SoCs using -	  GPIO lines to provide the SPI bus. This can be used where -	  the inbuilt hardware cannot provide the transfer mode, or -	  where the board is using non hardware connected pins. -  config SPI_S3C64XX  	tristate "Samsung S3C64XX series type SPI"  	depends on (ARCH_S3C64XX || ARCH_S5P64X0) @@ -385,16 +345,16 @@ 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" +	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller"  	depends on PCI  	help  	  SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus  	  used in some x86 embedded processors. +	  This driver also supports the ML7213, a companion chip for the +	  Atom E6xx series and compatible with the Intel EG20T PCH. +  config SPI_TXX9  	tristate "Toshiba TXx9 SPI controller"  	depends on GENERIC_GPIO && CPU_TX49XX diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 0f8c69b6b19e..61c3261c388c 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -7,68 +7,55 @@ 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)		+= 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/atmel_spi.h b/drivers/spi/atmel_spi.h deleted file mode 100644 index 6e06b6ad3a45..000000000000 --- a/drivers/spi/atmel_spi.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Register definitions for Atmel Serial Peripheral Interface (SPI) - * - * Copyright (C) 2006 Atmel Corporation - * - * 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. - */ -#ifndef __ATMEL_SPI_H__ -#define __ATMEL_SPI_H__ - -/* SPI register offsets */ -#define SPI_CR					0x0000 -#define SPI_MR					0x0004 -#define SPI_RDR					0x0008 -#define SPI_TDR					0x000c -#define SPI_SR					0x0010 -#define SPI_IER					0x0014 -#define SPI_IDR					0x0018 -#define SPI_IMR					0x001c -#define SPI_CSR0				0x0030 -#define SPI_CSR1				0x0034 -#define SPI_CSR2				0x0038 -#define SPI_CSR3				0x003c -#define SPI_RPR					0x0100 -#define SPI_RCR					0x0104 -#define SPI_TPR					0x0108 -#define SPI_TCR					0x010c -#define SPI_RNPR				0x0110 -#define SPI_RNCR				0x0114 -#define SPI_TNPR				0x0118 -#define SPI_TNCR				0x011c -#define SPI_PTCR				0x0120 -#define SPI_PTSR				0x0124 - -/* Bitfields in CR */ -#define SPI_SPIEN_OFFSET			0 -#define SPI_SPIEN_SIZE				1 -#define SPI_SPIDIS_OFFSET			1 -#define SPI_SPIDIS_SIZE				1 -#define SPI_SWRST_OFFSET			7 -#define SPI_SWRST_SIZE				1 -#define SPI_LASTXFER_OFFSET			24 -#define SPI_LASTXFER_SIZE			1 - -/* Bitfields in MR */ -#define SPI_MSTR_OFFSET				0 -#define SPI_MSTR_SIZE				1 -#define SPI_PS_OFFSET				1 -#define SPI_PS_SIZE				1 -#define SPI_PCSDEC_OFFSET			2 -#define SPI_PCSDEC_SIZE				1 -#define SPI_FDIV_OFFSET				3 -#define SPI_FDIV_SIZE				1 -#define SPI_MODFDIS_OFFSET			4 -#define SPI_MODFDIS_SIZE			1 -#define SPI_LLB_OFFSET				7 -#define SPI_LLB_SIZE				1 -#define SPI_PCS_OFFSET				16 -#define SPI_PCS_SIZE				4 -#define SPI_DLYBCS_OFFSET			24 -#define SPI_DLYBCS_SIZE				8 - -/* Bitfields in RDR */ -#define SPI_RD_OFFSET				0 -#define SPI_RD_SIZE				16 - -/* Bitfields in TDR */ -#define SPI_TD_OFFSET				0 -#define SPI_TD_SIZE				16 - -/* Bitfields in SR */ -#define SPI_RDRF_OFFSET				0 -#define SPI_RDRF_SIZE				1 -#define SPI_TDRE_OFFSET				1 -#define SPI_TDRE_SIZE				1 -#define SPI_MODF_OFFSET				2 -#define SPI_MODF_SIZE				1 -#define SPI_OVRES_OFFSET			3 -#define SPI_OVRES_SIZE				1 -#define SPI_ENDRX_OFFSET			4 -#define SPI_ENDRX_SIZE				1 -#define SPI_ENDTX_OFFSET			5 -#define SPI_ENDTX_SIZE				1 -#define SPI_RXBUFF_OFFSET			6 -#define SPI_RXBUFF_SIZE				1 -#define SPI_TXBUFE_OFFSET			7 -#define SPI_TXBUFE_SIZE				1 -#define SPI_NSSR_OFFSET				8 -#define SPI_NSSR_SIZE				1 -#define SPI_TXEMPTY_OFFSET			9 -#define SPI_TXEMPTY_SIZE			1 -#define SPI_SPIENS_OFFSET			16 -#define SPI_SPIENS_SIZE				1 - -/* Bitfields in CSR0 */ -#define SPI_CPOL_OFFSET				0 -#define SPI_CPOL_SIZE				1 -#define SPI_NCPHA_OFFSET			1 -#define SPI_NCPHA_SIZE				1 -#define SPI_CSAAT_OFFSET			3 -#define SPI_CSAAT_SIZE				1 -#define SPI_BITS_OFFSET				4 -#define SPI_BITS_SIZE				4 -#define SPI_SCBR_OFFSET				8 -#define SPI_SCBR_SIZE				8 -#define SPI_DLYBS_OFFSET			16 -#define SPI_DLYBS_SIZE				8 -#define SPI_DLYBCT_OFFSET			24 -#define SPI_DLYBCT_SIZE				8 - -/* Bitfields in RCR */ -#define SPI_RXCTR_OFFSET			0 -#define SPI_RXCTR_SIZE				16 - -/* Bitfields in TCR */ -#define SPI_TXCTR_OFFSET			0 -#define SPI_TXCTR_SIZE				16 - -/* Bitfields in RNCR */ -#define SPI_RXNCR_OFFSET			0 -#define SPI_RXNCR_SIZE				16 - -/* Bitfields in TNCR */ -#define SPI_TXNCR_OFFSET			0 -#define SPI_TXNCR_SIZE				16 - -/* Bitfields in PTCR */ -#define SPI_RXTEN_OFFSET			0 -#define SPI_RXTEN_SIZE				1 -#define SPI_RXTDIS_OFFSET			1 -#define SPI_RXTDIS_SIZE				1 -#define SPI_TXTEN_OFFSET			8 -#define SPI_TXTEN_SIZE				1 -#define SPI_TXTDIS_OFFSET			9 -#define SPI_TXTDIS_SIZE				1 - -/* Constants for BITS */ -#define SPI_BITS_8_BPT				0 -#define SPI_BITS_9_BPT				1 -#define SPI_BITS_10_BPT				2 -#define SPI_BITS_11_BPT				3 -#define SPI_BITS_12_BPT				4 -#define SPI_BITS_13_BPT				5 -#define SPI_BITS_14_BPT				6 -#define SPI_BITS_15_BPT				7 -#define SPI_BITS_16_BPT				8 - -/* Bit manipulation macros */ -#define SPI_BIT(name) \ -	(1 << SPI_##name##_OFFSET) -#define SPI_BF(name,value) \ -	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET) -#define SPI_BFEXT(name,value) \ -	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1)) -#define SPI_BFINS(name,value,old) \ -	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \ -	  | SPI_BF(name,value)) - -/* Register access macros */ -#define spi_readl(port,reg) \ -	__raw_readl((port)->regs + SPI_##reg) -#define spi_writel(port,reg,value) \ -	__raw_writel((value), (port)->regs + SPI_##reg) - -#endif /* __ATMEL_SPI_H__ */ diff --git a/drivers/spi/spi_altera.c b/drivers/spi/spi-altera.c index 4813a63ce6fb..4813a63ce6fb 100644 --- a/drivers/spi/spi_altera.c +++ b/drivers/spi/spi-altera.c diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/spi-ath79.c index fcff810ea3b0..03019bf5a5e9 100644 --- a/drivers/spi/ath79_spi.c +++ b/drivers/spi/spi-ath79.c @@ -232,7 +232,7 @@ static __devinit int ath79_spi_probe(struct platform_device *pdev)  		goto err_put_master;  	} -	sp->base = ioremap(r->start, r->end - r->start + 1); +	sp->base = ioremap(r->start, resource_size(r));  	if (!sp->base) {  		ret = -ENXIO;  		goto err_put_master; diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/spi-atmel.c index 08711e9202ab..82dee9a6c0de 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/spi-atmel.c @@ -25,7 +25,160 @@  #include <mach/gpio.h>  #include <mach/cpu.h> -#include "atmel_spi.h" +/* SPI register offsets */ +#define SPI_CR					0x0000 +#define SPI_MR					0x0004 +#define SPI_RDR					0x0008 +#define SPI_TDR					0x000c +#define SPI_SR					0x0010 +#define SPI_IER					0x0014 +#define SPI_IDR					0x0018 +#define SPI_IMR					0x001c +#define SPI_CSR0				0x0030 +#define SPI_CSR1				0x0034 +#define SPI_CSR2				0x0038 +#define SPI_CSR3				0x003c +#define SPI_RPR					0x0100 +#define SPI_RCR					0x0104 +#define SPI_TPR					0x0108 +#define SPI_TCR					0x010c +#define SPI_RNPR				0x0110 +#define SPI_RNCR				0x0114 +#define SPI_TNPR				0x0118 +#define SPI_TNCR				0x011c +#define SPI_PTCR				0x0120 +#define SPI_PTSR				0x0124 + +/* Bitfields in CR */ +#define SPI_SPIEN_OFFSET			0 +#define SPI_SPIEN_SIZE				1 +#define SPI_SPIDIS_OFFSET			1 +#define SPI_SPIDIS_SIZE				1 +#define SPI_SWRST_OFFSET			7 +#define SPI_SWRST_SIZE				1 +#define SPI_LASTXFER_OFFSET			24 +#define SPI_LASTXFER_SIZE			1 + +/* Bitfields in MR */ +#define SPI_MSTR_OFFSET				0 +#define SPI_MSTR_SIZE				1 +#define SPI_PS_OFFSET				1 +#define SPI_PS_SIZE				1 +#define SPI_PCSDEC_OFFSET			2 +#define SPI_PCSDEC_SIZE				1 +#define SPI_FDIV_OFFSET				3 +#define SPI_FDIV_SIZE				1 +#define SPI_MODFDIS_OFFSET			4 +#define SPI_MODFDIS_SIZE			1 +#define SPI_LLB_OFFSET				7 +#define SPI_LLB_SIZE				1 +#define SPI_PCS_OFFSET				16 +#define SPI_PCS_SIZE				4 +#define SPI_DLYBCS_OFFSET			24 +#define SPI_DLYBCS_SIZE				8 + +/* Bitfields in RDR */ +#define SPI_RD_OFFSET				0 +#define SPI_RD_SIZE				16 + +/* Bitfields in TDR */ +#define SPI_TD_OFFSET				0 +#define SPI_TD_SIZE				16 + +/* Bitfields in SR */ +#define SPI_RDRF_OFFSET				0 +#define SPI_RDRF_SIZE				1 +#define SPI_TDRE_OFFSET				1 +#define SPI_TDRE_SIZE				1 +#define SPI_MODF_OFFSET				2 +#define SPI_MODF_SIZE				1 +#define SPI_OVRES_OFFSET			3 +#define SPI_OVRES_SIZE				1 +#define SPI_ENDRX_OFFSET			4 +#define SPI_ENDRX_SIZE				1 +#define SPI_ENDTX_OFFSET			5 +#define SPI_ENDTX_SIZE				1 +#define SPI_RXBUFF_OFFSET			6 +#define SPI_RXBUFF_SIZE				1 +#define SPI_TXBUFE_OFFSET			7 +#define SPI_TXBUFE_SIZE				1 +#define SPI_NSSR_OFFSET				8 +#define SPI_NSSR_SIZE				1 +#define SPI_TXEMPTY_OFFSET			9 +#define SPI_TXEMPTY_SIZE			1 +#define SPI_SPIENS_OFFSET			16 +#define SPI_SPIENS_SIZE				1 + +/* Bitfields in CSR0 */ +#define SPI_CPOL_OFFSET				0 +#define SPI_CPOL_SIZE				1 +#define SPI_NCPHA_OFFSET			1 +#define SPI_NCPHA_SIZE				1 +#define SPI_CSAAT_OFFSET			3 +#define SPI_CSAAT_SIZE				1 +#define SPI_BITS_OFFSET				4 +#define SPI_BITS_SIZE				4 +#define SPI_SCBR_OFFSET				8 +#define SPI_SCBR_SIZE				8 +#define SPI_DLYBS_OFFSET			16 +#define SPI_DLYBS_SIZE				8 +#define SPI_DLYBCT_OFFSET			24 +#define SPI_DLYBCT_SIZE				8 + +/* Bitfields in RCR */ +#define SPI_RXCTR_OFFSET			0 +#define SPI_RXCTR_SIZE				16 + +/* Bitfields in TCR */ +#define SPI_TXCTR_OFFSET			0 +#define SPI_TXCTR_SIZE				16 + +/* Bitfields in RNCR */ +#define SPI_RXNCR_OFFSET			0 +#define SPI_RXNCR_SIZE				16 + +/* Bitfields in TNCR */ +#define SPI_TXNCR_OFFSET			0 +#define SPI_TXNCR_SIZE				16 + +/* Bitfields in PTCR */ +#define SPI_RXTEN_OFFSET			0 +#define SPI_RXTEN_SIZE				1 +#define SPI_RXTDIS_OFFSET			1 +#define SPI_RXTDIS_SIZE				1 +#define SPI_TXTEN_OFFSET			8 +#define SPI_TXTEN_SIZE				1 +#define SPI_TXTDIS_OFFSET			9 +#define SPI_TXTDIS_SIZE				1 + +/* Constants for BITS */ +#define SPI_BITS_8_BPT				0 +#define SPI_BITS_9_BPT				1 +#define SPI_BITS_10_BPT				2 +#define SPI_BITS_11_BPT				3 +#define SPI_BITS_12_BPT				4 +#define SPI_BITS_13_BPT				5 +#define SPI_BITS_14_BPT				6 +#define SPI_BITS_15_BPT				7 +#define SPI_BITS_16_BPT				8 + +/* Bit manipulation macros */ +#define SPI_BIT(name) \ +	(1 << SPI_##name##_OFFSET) +#define SPI_BF(name,value) \ +	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET) +#define SPI_BFEXT(name,value) \ +	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1)) +#define SPI_BFINS(name,value,old) \ +	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \ +	  | SPI_BF(name,value)) + +/* Register access macros */ +#define spi_readl(port,reg) \ +	__raw_readl((port)->regs + SPI_##reg) +#define spi_writel(port,reg,value) \ +	__raw_writel((value), (port)->regs + SPI_##reg) +  /*   * The core SPI transfer engine just talks to a register bank to set up diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/spi-au1550.c index b50563d320e1..bddee5f516b2 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/spi-au1550.c @@ -1,5 +1,5 @@  /* - * au1550_spi.c - au1550 psc spi controller driver + * au1550 psc spi controller driver   * may work also with au1200, au1210, au1250   * will not work on au1000, au1100 and au1500 (no full spi controller there)   * diff --git a/drivers/spi/spi_bfin_sport.c b/drivers/spi/spi-bfin-sport.c index e557ff617b11..e557ff617b11 100644 --- a/drivers/spi/spi_bfin_sport.c +++ b/drivers/spi/spi-bfin-sport.c diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi-bfin5xx.c index f706dba165cf..b8d25f2b7038 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -58,7 +58,7 @@ struct bfin_spi_master_data {  	struct spi_master *master;  	/* Regs base of SPI controller */ -	void __iomem *regs_base; +	struct bfin_spi_regs __iomem *regs;  	/* Pin request list */  	u16 *pin_req; @@ -122,34 +122,14 @@ struct bfin_spi_slave_data {  	const struct bfin_spi_transfer_ops *ops;  }; -#define DEFINE_SPI_REG(reg, off) \ -static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \ -	{ return bfin_read16(drv_data->regs_base + off); } \ -static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \ -	{ bfin_write16(drv_data->regs_base + off, v); } - -DEFINE_SPI_REG(CTRL, 0x00) -DEFINE_SPI_REG(FLAG, 0x04) -DEFINE_SPI_REG(STAT, 0x08) -DEFINE_SPI_REG(TDBR, 0x0C) -DEFINE_SPI_REG(RDBR, 0x10) -DEFINE_SPI_REG(BAUD, 0x14) -DEFINE_SPI_REG(SHAW, 0x18) -  static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)  { -	u16 cr; - -	cr = read_CTRL(drv_data); -	write_CTRL(drv_data, (cr | BIT_CTL_ENABLE)); +	bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE);  }  static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)  { -	u16 cr; - -	cr = read_CTRL(drv_data); -	write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE))); +	bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE);  }  /* Caculate the SPI_BAUD register value based on input HZ */ @@ -172,10 +152,10 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)  	unsigned long limit = loops_per_jiffy << 1;  	/* wait for stop and clear stat */ -	while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && --limit) +	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit)  		cpu_relax(); -	write_STAT(drv_data, BIT_STAT_CLR); +	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);  	return limit;  } @@ -183,29 +163,19 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)  /* Chip select operation functions for cs_change flag */  static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)  { -	if (likely(chip->chip_select_num < MAX_CTRL_CS)) { -		u16 flag = read_FLAG(drv_data); - -		flag &= ~chip->flag; - -		write_FLAG(drv_data, flag); -	} else { +	if (likely(chip->chip_select_num < MAX_CTRL_CS)) +		bfin_write_and(&drv_data->regs->flg, ~chip->flag); +	else  		gpio_set_value(chip->cs_gpio, 0); -	}  }  static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,                                   struct bfin_spi_slave_data *chip)  { -	if (likely(chip->chip_select_num < MAX_CTRL_CS)) { -		u16 flag = read_FLAG(drv_data); - -		flag |= chip->flag; - -		write_FLAG(drv_data, flag); -	} else { +	if (likely(chip->chip_select_num < MAX_CTRL_CS)) +		bfin_write_or(&drv_data->regs->flg, chip->flag); +	else  		gpio_set_value(chip->cs_gpio, 1); -	}  	/* Move delay here for consistency */  	if (chip->cs_chg_udelay) @@ -216,25 +186,15 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,  static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,                                        struct bfin_spi_slave_data *chip)  { -	if (chip->chip_select_num < MAX_CTRL_CS) { -		u16 flag = read_FLAG(drv_data); - -		flag |= (chip->flag >> 8); - -		write_FLAG(drv_data, flag); -	} +	if (chip->chip_select_num < MAX_CTRL_CS) +		bfin_write_or(&drv_data->regs->flg, chip->flag >> 8);  }  static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,                                         struct bfin_spi_slave_data *chip)  { -	if (chip->chip_select_num < MAX_CTRL_CS) { -		u16 flag = read_FLAG(drv_data); - -		flag &= ~(chip->flag >> 8); - -		write_FLAG(drv_data, flag); -	} +	if (chip->chip_select_num < MAX_CTRL_CS) +		bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8));  }  /* stop controller and re-config current chip*/ @@ -243,15 +203,15 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)  	struct bfin_spi_slave_data *chip = drv_data->cur_chip;  	/* Clear status and disable clock */ -	write_STAT(drv_data, BIT_STAT_CLR); +	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);  	bfin_spi_disable(drv_data);  	dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");  	SSYNC();  	/* Load the registers */ -	write_CTRL(drv_data, chip->ctl_reg); -	write_BAUD(drv_data, chip->baud); +	bfin_write(&drv_data->regs->ctl, chip->ctl_reg); +	bfin_write(&drv_data->regs->baud, chip->baud);  	bfin_spi_enable(drv_data);  	bfin_spi_cs_active(drv_data, chip); @@ -260,7 +220,7 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)  /* used to kick off transfer in rx mode and read unwanted RX data */  static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)  { -	(void) read_RDBR(drv_data); +	(void) bfin_read(&drv_data->regs->rdbr);  }  static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data) @@ -269,10 +229,10 @@ static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)  	bfin_spi_dummy_read(drv_data);  	while (drv_data->tx < drv_data->tx_end) { -		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++))); +		bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));  		/* wait until transfer finished.  		   checking SPIF or TXS may not guarantee transfer completion */ -		while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  			cpu_relax();  		/* discard RX data and clear RXS */  		bfin_spi_dummy_read(drv_data); @@ -287,10 +247,10 @@ static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)  	bfin_spi_dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		write_TDBR(drv_data, tx_val); -		while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +		bfin_write(&drv_data->regs->tdbr, tx_val); +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  			cpu_relax(); -		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data); +		*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);  	}  } @@ -300,10 +260,10 @@ static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)  	bfin_spi_dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++))); -		while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +		bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++))); +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  			cpu_relax(); -		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data); +		*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);  	}  } @@ -319,11 +279,11 @@ static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)  	bfin_spi_dummy_read(drv_data);  	while (drv_data->tx < drv_data->tx_end) { -		write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); +		bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));  		drv_data->tx += 2;  		/* wait until transfer finished.  		   checking SPIF or TXS may not guarantee transfer completion */ -		while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  			cpu_relax();  		/* discard RX data and clear RXS */  		bfin_spi_dummy_read(drv_data); @@ -338,10 +298,10 @@ static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)  	bfin_spi_dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		write_TDBR(drv_data, tx_val); -		while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +		bfin_write(&drv_data->regs->tdbr, tx_val); +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  			cpu_relax(); -		*(u16 *) (drv_data->rx) = read_RDBR(drv_data); +		*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);  		drv_data->rx += 2;  	}  } @@ -352,11 +312,11 @@ static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)  	bfin_spi_dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); +		bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));  		drv_data->tx += 2; -		while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  			cpu_relax(); -		*(u16 *) (drv_data->rx) = read_RDBR(drv_data); +		*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);  		drv_data->rx += 2;  	}  } @@ -428,7 +388,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)  	int loop = 0;  	/* wait until transfer finished. */ -	while (!(read_STAT(drv_data) & BIT_STAT_RXS)) +	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))  		cpu_relax();  	if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) || @@ -439,11 +399,11 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)  			if (n_bytes % 2) {  				u16 *buf = (u16 *)drv_data->rx;  				for (loop = 0; loop < n_bytes / 2; loop++) -					*buf++ = read_RDBR(drv_data); +					*buf++ = bfin_read(&drv_data->regs->rdbr);  			} else {  				u8 *buf = (u8 *)drv_data->rx;  				for (loop = 0; loop < n_bytes; loop++) -					*buf++ = read_RDBR(drv_data); +					*buf++ = bfin_read(&drv_data->regs->rdbr);  			}  			drv_data->rx += n_bytes;  		} @@ -468,15 +428,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)  			u16 *buf = (u16 *)drv_data->rx;  			u16 *buf2 = (u16 *)drv_data->tx;  			for (loop = 0; loop < n_bytes / 2; loop++) { -				*buf++ = read_RDBR(drv_data); -				write_TDBR(drv_data, *buf2++); +				*buf++ = bfin_read(&drv_data->regs->rdbr); +				bfin_write(&drv_data->regs->tdbr, *buf2++);  			}  		} else {  			u8 *buf = (u8 *)drv_data->rx;  			u8 *buf2 = (u8 *)drv_data->tx;  			for (loop = 0; loop < n_bytes; loop++) { -				*buf++ = read_RDBR(drv_data); -				write_TDBR(drv_data, *buf2++); +				*buf++ = bfin_read(&drv_data->regs->rdbr); +				bfin_write(&drv_data->regs->tdbr, *buf2++);  			}  		}  	} else if (drv_data->rx) { @@ -485,14 +445,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)  		if (n_bytes % 2) {  			u16 *buf = (u16 *)drv_data->rx;  			for (loop = 0; loop < n_bytes / 2; loop++) { -				*buf++ = read_RDBR(drv_data); -				write_TDBR(drv_data, chip->idle_tx_val); +				*buf++ = bfin_read(&drv_data->regs->rdbr); +				bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);  			}  		} else {  			u8 *buf = (u8 *)drv_data->rx;  			for (loop = 0; loop < n_bytes; loop++) { -				*buf++ = read_RDBR(drv_data); -				write_TDBR(drv_data, chip->idle_tx_val); +				*buf++ = bfin_read(&drv_data->regs->rdbr); +				bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);  			}  		}  	} else if (drv_data->tx) { @@ -501,14 +461,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)  		if (n_bytes % 2) {  			u16 *buf = (u16 *)drv_data->tx;  			for (loop = 0; loop < n_bytes / 2; loop++) { -				read_RDBR(drv_data); -				write_TDBR(drv_data, *buf++); +				bfin_read(&drv_data->regs->rdbr); +				bfin_write(&drv_data->regs->tdbr, *buf++);  			}  		} else {  			u8 *buf = (u8 *)drv_data->tx;  			for (loop = 0; loop < n_bytes; loop++) { -				read_RDBR(drv_data); -				write_TDBR(drv_data, *buf++); +				bfin_read(&drv_data->regs->rdbr); +				bfin_write(&drv_data->regs->tdbr, *buf++);  			}  		}  	} @@ -528,19 +488,19 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)  	struct spi_message *msg = drv_data->cur_msg;  	unsigned long timeout;  	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel); -	u16 spistat = read_STAT(drv_data); +	u16 spistat = bfin_read(&drv_data->regs->stat);  	dev_dbg(&drv_data->pdev->dev,  		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",  		dmastat, spistat);  	if (drv_data->rx != NULL) { -		u16 cr = read_CTRL(drv_data); +		u16 cr = bfin_read(&drv_data->regs->ctl);  		/* discard old RX data and clear RXS */  		bfin_spi_dummy_read(drv_data); -		write_CTRL(drv_data, cr & ~BIT_CTL_ENABLE); /* Disable SPI */ -		write_CTRL(drv_data, cr & ~BIT_CTL_TIMOD); /* Restore State */ -		write_STAT(drv_data, BIT_STAT_CLR); /* Clear Status */ +		bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_ENABLE); /* Disable SPI */ +		bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_TIMOD); /* Restore State */ +		bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); /* Clear Status */  	}  	clear_dma_irqstat(drv_data->dma_channel); @@ -552,17 +512,17 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)  	 * register until it goes low for 2 successive reads  	 */  	if (drv_data->tx != NULL) { -		while ((read_STAT(drv_data) & BIT_STAT_TXS) || -		       (read_STAT(drv_data) & BIT_STAT_TXS)) +		while ((bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS) || +		       (bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS))  			cpu_relax();  	}  	dev_dbg(&drv_data->pdev->dev,  		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n", -		dmastat, read_STAT(drv_data)); +		dmastat, bfin_read(&drv_data->regs->stat));  	timeout = jiffies + HZ; -	while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) +	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))  		if (!time_before(jiffies, timeout)) {  			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");  			break; @@ -681,13 +641,14 @@ static void bfin_spi_pump_transfers(unsigned long data)  	drv_data->cs_change = transfer->cs_change;  	/* Bits per word setup */ -	bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; -	if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) { +	bits_per_word = transfer->bits_per_word ? : +		message->spi->bits_per_word ? : 8; +	if (bits_per_word % 16 == 0) {  		drv_data->n_bytes = bits_per_word/8;  		drv_data->len = (transfer->len) >> 1;  		cr_width = BIT_CTL_WORDSIZE;  		drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; -	} else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) { +	} else if (bits_per_word % 8 == 0) {  		drv_data->n_bytes = bits_per_word/8;  		drv_data->len = transfer->len;  		cr_width = 0; @@ -698,9 +659,9 @@ static void bfin_spi_pump_transfers(unsigned long data)  		bfin_spi_giveback(drv_data);  		return;  	} -	cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE); +	cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);  	cr |= cr_width; -	write_CTRL(drv_data, cr); +	bfin_write(&drv_data->regs->ctl, cr);  	dev_dbg(&drv_data->pdev->dev,  		"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n", @@ -711,11 +672,11 @@ static void bfin_spi_pump_transfers(unsigned long data)  	/* Speed setup (surely valid because already checked) */  	if (transfer->speed_hz) -		write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz)); +		bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));  	else -		write_BAUD(drv_data, chip->baud); +		bfin_write(&drv_data->regs->baud, chip->baud); -	write_STAT(drv_data, BIT_STAT_CLR); +	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);  	bfin_spi_cs_active(drv_data, chip);  	dev_dbg(&drv_data->pdev->dev, @@ -748,7 +709,7 @@ static void bfin_spi_pump_transfers(unsigned long data)  		}  		/* poll for SPI completion before start */ -		while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) +		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))  			cpu_relax();  		/* dirty hack for autobuffer DMA mode */ @@ -765,7 +726,7 @@ static void bfin_spi_pump_transfers(unsigned long data)  			enable_dma(drv_data->dma_channel);  			/* start SPI transfer */ -			write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX); +			bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX);  			/* just return here, there can only be one transfer  			 * in this mode @@ -820,7 +781,7 @@ static void bfin_spi_pump_transfers(unsigned long data)  		set_dma_config(drv_data->dma_channel, dma_config);  		local_irq_save(flags);  		SSYNC(); -		write_CTRL(drv_data, cr); +		bfin_write(&drv_data->regs->ctl, cr);  		enable_dma(drv_data->dma_channel);  		dma_enable_irq(drv_data->dma_channel);  		local_irq_restore(flags); @@ -834,7 +795,7 @@ static void bfin_spi_pump_transfers(unsigned long data)  	 * problems with setting up the output value in TDBR prior to the  	 * start of the transfer.  	 */ -	write_CTRL(drv_data, cr | BIT_CTL_TXMOD); +	bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD);  	if (chip->pio_interrupt) {  		/* SPI irq should have been disabled by now */ @@ -844,19 +805,19 @@ static void bfin_spi_pump_transfers(unsigned long data)  		/* start transfer */  		if (drv_data->tx == NULL) -			write_TDBR(drv_data, chip->idle_tx_val); +			bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);  		else {  			int loop;  			if (bits_per_word % 16 == 0) {  				u16 *buf = (u16 *)drv_data->tx;  				for (loop = 0; loop < bits_per_word / 16;  						loop++) { -					write_TDBR(drv_data, *buf++); +					bfin_write(&drv_data->regs->tdbr, *buf++);  				}  			} else if (bits_per_word % 8 == 0) {  				u8 *buf = (u8 *)drv_data->tx;  				for (loop = 0; loop < bits_per_word / 8; loop++) -					write_TDBR(drv_data, *buf++); +					bfin_write(&drv_data->regs->tdbr, *buf++);  			}  			drv_data->tx += drv_data->n_bytes; @@ -1004,7 +965,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)  #define MAX_SPI_SSEL	7 -static u16 ssel[][MAX_SPI_SSEL] = { +static const u16 ssel[][MAX_SPI_SSEL] = {  	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,  	P_SPI0_SSEL4, P_SPI0_SSEL5,  	P_SPI0_SSEL6, P_SPI0_SSEL7}, @@ -1225,7 +1186,7 @@ static void bfin_spi_cleanup(struct spi_device *spi)  	spi_set_ctldata(spi, NULL);  } -static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data) +static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)  {  	INIT_LIST_HEAD(&drv_data->queue);  	spin_lock_init(&drv_data->lock); @@ -1247,7 +1208,7 @@ static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)  	return 0;  } -static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data) +static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)  {  	unsigned long flags; @@ -1269,7 +1230,7 @@ static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)  	return 0;  } -static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data) +static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)  {  	unsigned long flags;  	unsigned limit = 500; @@ -1298,7 +1259,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)  	return status;  } -static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) +static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)  {  	int status; @@ -1352,8 +1313,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)  		goto out_error_get_res;  	} -	drv_data->regs_base = ioremap(res->start, resource_size(res)); -	if (drv_data->regs_base == NULL) { +	drv_data->regs = ioremap(res->start, resource_size(res)); +	if (drv_data->regs == NULL) {  		dev_err(dev, "Cannot map IO\n");  		status = -ENXIO;  		goto out_error_ioremap; @@ -1396,8 +1357,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)  	/* Reset SPI registers. If these registers were used by the boot loader,  	 * the sky may fall on your head if you enable the dma controller.  	 */ -	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER); -	write_FLAG(drv_data, 0xFF00); +	bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER); +	bfin_write(&drv_data->regs->flg, 0xFF00);  	/* Register with the SPI framework */  	platform_set_drvdata(pdev, drv_data); @@ -1407,15 +1368,15 @@ static int __init bfin_spi_probe(struct platform_device *pdev)  		goto out_error_queue_alloc;  	} -	dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n", -		DRV_DESC, DRV_VERSION, drv_data->regs_base, +	dev_info(dev, "%s, Version %s, regs@%p, dma channel@%d\n", +		DRV_DESC, DRV_VERSION, drv_data->regs,  		drv_data->dma_channel);  	return status;  out_error_queue_alloc:  	bfin_spi_destroy_queue(drv_data);  out_error_free_io: -	iounmap((void *) drv_data->regs_base); +	iounmap(drv_data->regs);  out_error_ioremap:  out_error_get_res:  	spi_master_put(master); @@ -1472,14 +1433,14 @@ static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)  	if (status != 0)  		return status; -	drv_data->ctrl_reg = read_CTRL(drv_data); -	drv_data->flag_reg = read_FLAG(drv_data); +	drv_data->ctrl_reg = bfin_read(&drv_data->regs->ctl); +	drv_data->flag_reg = bfin_read(&drv_data->regs->flg);  	/*  	 * reset SPI_CTL and SPI_FLG registers  	 */ -	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER); -	write_FLAG(drv_data, 0xFF00); +	bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER); +	bfin_write(&drv_data->regs->flg, 0xFF00);  	return 0;  } @@ -1489,8 +1450,8 @@ static int bfin_spi_resume(struct platform_device *pdev)  	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);  	int status = 0; -	write_CTRL(drv_data, drv_data->ctrl_reg); -	write_FLAG(drv_data, drv_data->flag_reg); +	bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg); +	bfin_write(&drv_data->regs->flg, drv_data->flag_reg);  	/* Start the queue running */  	status = bfin_spi_start_queue(drv_data); diff --git a/drivers/spi/spi_bitbang_txrx.h b/drivers/spi/spi-bitbang-txrx.h index c16bf853c3eb..c16bf853c3eb 100644 --- a/drivers/spi/spi_bitbang_txrx.h +++ b/drivers/spi/spi-bitbang-txrx.h diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi-bitbang.c index 14a63f6010d1..02d57fbba295 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -1,5 +1,5 @@  /* - * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities + * polling/bitbanging SPI master controller driver utilities   *   * 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 @@ -68,7 +68,7 @@ static unsigned bitbang_txrx_8(  	unsigned		ns,  	struct spi_transfer	*t  ) { -	unsigned		bits = spi->bits_per_word; +	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;  	unsigned		count = t->len;  	const u8		*tx = t->tx_buf;  	u8			*rx = t->rx_buf; @@ -94,7 +94,7 @@ static unsigned bitbang_txrx_16(  	unsigned		ns,  	struct spi_transfer	*t  ) { -	unsigned		bits = spi->bits_per_word; +	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;  	unsigned		count = t->len;  	const u16		*tx = t->tx_buf;  	u16			*rx = t->rx_buf; @@ -120,7 +120,7 @@ static unsigned bitbang_txrx_32(  	unsigned		ns,  	struct spi_transfer	*t  ) { -	unsigned		bits = spi->bits_per_word; +	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;  	unsigned		count = t->len;  	const u32		*tx = t->tx_buf;  	u32			*rx = t->rx_buf; diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi-butterfly.c index 0d4ceba3b590..9f907ec52def 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -1,5 +1,5 @@  /* - * spi_butterfly.c - parport-to-butterfly adapter + * parport-to-butterfly adapter   *   * Copyright (C) 2005 David Brownell   * @@ -149,7 +149,7 @@ static void butterfly_chipselect(struct spi_device *spi, int value)  #define	spidelay(X)	do{}while(0)  //#define	spidelay	ndelay -#include "spi_bitbang_txrx.h" +#include "spi-bitbang-txrx.h"  static u32  butterfly_txrx_word_mode0(struct spi_device *spi, diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/spi-coldfire-qspi.c index ae2cd1c1fda8..ae2cd1c1fda8 100644 --- a/drivers/spi/coldfire_qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/spi-davinci.c index 1f0ed8005c91..1f0ed8005c91 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/spi-davinci.c diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/spi-dw-mid.c index 489178243d88..130e55537db6 100644 --- a/drivers/spi/dw_spi_mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -1,5 +1,5 @@  /* - * dw_spi_mid.c - special handling for DW core on Intel MID platform + * Special handling for DW core on Intel MID platform   *   * Copyright (c) 2009, Intel Corporation.   * @@ -23,7 +23,7 @@  #include <linux/slab.h>  #include <linux/spi/spi.h> -#include "dw_spi.h" +#include "spi-dw.h"  #ifdef CONFIG_SPI_DW_MID_DMA  #include <linux/intel_mid_dma.h> diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/spi-dw-mmio.c index e0e813dad150..34eb66501dbf 100644 --- a/drivers/spi/dw_spi_mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -1,5 +1,5 @@  /* - * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core + * Memory-mapped interface driver for DW SPI Core   *   * Copyright (c) 2010, Octasic semiconductor.   * @@ -16,7 +16,7 @@  #include <linux/spi/spi.h>  #include <linux/scatterlist.h> -#include "dw_spi.h" +#include "spi-dw.h"  #define DRIVER_NAME "dw_spi_mmio" diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/spi-dw-pci.c index ad260aa5e526..c5f37f03ac8b 100644 --- a/drivers/spi/dw_spi_pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -1,5 +1,5 @@  /* - * dw_spi_pci.c - PCI interface driver for DW SPI Core + * PCI interface driver for DW SPI Core   *   * Copyright (c) 2009, Intel Corporation.   * @@ -22,7 +22,7 @@  #include <linux/slab.h>  #include <linux/spi/spi.h> -#include "dw_spi.h" +#include "spi-dw.h"  #define DRIVER_NAME "dw_spi_pci" diff --git a/drivers/spi/dw_spi.c b/drivers/spi/spi-dw.c index 919fa9d9e16b..857cd30b44bb 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/spi-dw.c @@ -1,5 +1,5 @@  /* - * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c) + * Designware SPI core controller driver (refer pxa2xx_spi.c)   *   * Copyright (c) 2009, Intel Corporation.   * @@ -24,7 +24,7 @@  #include <linux/slab.h>  #include <linux/spi/spi.h> -#include "dw_spi.h" +#include "spi-dw.h"  #ifdef CONFIG_DEBUG_FS  #include <linux/debugfs.h> @@ -818,9 +818,11 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)  	dws->prev_chip = NULL;  	dws->dma_inited = 0;  	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); +	snprintf(dws->name, sizeof(dws->name), "dw_spi%d", +			dws->bus_num);  	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, -			"dw_spi", dws); +			dws->name, dws);  	if (ret < 0) {  		dev_err(&master->dev, "can not get IRQ\n");  		goto err_free_master; diff --git a/drivers/spi/dw_spi.h b/drivers/spi/spi-dw.h index 7a5e78d2a5cb..8b7b07bf6c3f 100644 --- a/drivers/spi/dw_spi.h +++ b/drivers/spi/spi-dw.h @@ -96,6 +96,7 @@ struct dw_spi {  	struct spi_device	*cur_dev;  	struct device		*parent_dev;  	enum dw_ssi_type	type; +	char			name[16];  	void __iomem		*regs;  	unsigned long		paddr; diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/spi-ep93xx.c index d3570071e98f..1cf645479bfe 100644 --- a/drivers/spi/ep93xx_spi.c +++ b/drivers/spi/spi-ep93xx.c @@ -1,7 +1,7 @@  /*   * Driver for Cirrus Logic EP93xx SPI controller.   * - * Copyright (c) 2010 Mika Westerberg + * Copyright (C) 2010-2011 Mika Westerberg   *   * Explicit FIFO handling code was inspired by amba-pl022 driver.   * @@ -21,13 +21,16 @@  #include <linux/err.h>  #include <linux/delay.h>  #include <linux/device.h> +#include <linux/dmaengine.h>  #include <linux/bitops.h>  #include <linux/interrupt.h>  #include <linux/platform_device.h>  #include <linux/workqueue.h>  #include <linux/sched.h> +#include <linux/scatterlist.h>  #include <linux/spi/spi.h> +#include <mach/dma.h>  #include <mach/ep93xx_spi.h>  #define SSPCR0			0x0000 @@ -71,6 +74,7 @@   * @pdev: pointer to platform device   * @clk: clock for the controller   * @regs_base: pointer to ioremap()'d registers + * @sspdr_phys: physical address of the SSPDR register   * @irq: IRQ number used by the driver   * @min_rate: minimum clock rate (in Hz) supported by the controller   * @max_rate: maximum clock rate (in Hz) supported by the controller @@ -84,6 +88,14 @@   * @rx: current byte in transfer to receive   * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one   *              frame decreases this level and sending one frame increases it. + * @dma_rx: RX DMA channel + * @dma_tx: TX DMA channel + * @dma_rx_data: RX parameters passed to the DMA engine + * @dma_tx_data: TX parameters passed to the DMA engine + * @rx_sgt: sg table for RX transfers + * @tx_sgt: sg table for TX transfers + * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by + *            the client   *   * This structure holds EP93xx SPI controller specific information. When   * @running is %true, driver accepts transfer requests from protocol drivers. @@ -100,6 +112,7 @@ struct ep93xx_spi {  	const struct platform_device	*pdev;  	struct clk			*clk;  	void __iomem			*regs_base; +	unsigned long			sspdr_phys;  	int				irq;  	unsigned long			min_rate;  	unsigned long			max_rate; @@ -112,6 +125,13 @@ struct ep93xx_spi {  	size_t				tx;  	size_t				rx;  	size_t				fifo_level; +	struct dma_chan			*dma_rx; +	struct dma_chan			*dma_tx; +	struct ep93xx_dma_data		dma_rx_data; +	struct ep93xx_dma_data		dma_tx_data; +	struct sg_table			rx_sgt; +	struct sg_table			tx_sgt; +	void				*zeropage;  };  /** @@ -496,14 +516,195 @@ static int ep93xx_spi_read_write(struct ep93xx_spi *espi)  		espi->fifo_level++;  	} -	if (espi->rx == t->len) { -		msg->actual_length += t->len; +	if (espi->rx == t->len)  		return 0; -	}  	return -EINPROGRESS;  } +static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi) +{ +	/* +	 * Now everything is set up for the current transfer. We prime the TX +	 * FIFO, enable interrupts, and wait for the transfer to complete. +	 */ +	if (ep93xx_spi_read_write(espi)) { +		ep93xx_spi_enable_interrupts(espi); +		wait_for_completion(&espi->wait); +	} +} + +/** + * ep93xx_spi_dma_prepare() - prepares a DMA transfer + * @espi: ep93xx SPI controller struct + * @dir: DMA transfer direction + * + * Function configures the DMA, maps the buffer and prepares the DMA + * descriptor. Returns a valid DMA descriptor in case of success and ERR_PTR + * in case of failure. + */ +static struct dma_async_tx_descriptor * +ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) +{ +	struct spi_transfer *t = espi->current_msg->state; +	struct dma_async_tx_descriptor *txd; +	enum dma_slave_buswidth buswidth; +	struct dma_slave_config conf; +	struct scatterlist *sg; +	struct sg_table *sgt; +	struct dma_chan *chan; +	const void *buf, *pbuf; +	size_t len = t->len; +	int i, ret, nents; + +	if (bits_per_word(espi) > 8) +		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; +	else +		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + +	memset(&conf, 0, sizeof(conf)); +	conf.direction = dir; + +	if (dir == DMA_FROM_DEVICE) { +		chan = espi->dma_rx; +		buf = t->rx_buf; +		sgt = &espi->rx_sgt; + +		conf.src_addr = espi->sspdr_phys; +		conf.src_addr_width = buswidth; +	} else { +		chan = espi->dma_tx; +		buf = t->tx_buf; +		sgt = &espi->tx_sgt; + +		conf.dst_addr = espi->sspdr_phys; +		conf.dst_addr_width = buswidth; +	} + +	ret = dmaengine_slave_config(chan, &conf); +	if (ret) +		return ERR_PTR(ret); + +	/* +	 * We need to split the transfer into PAGE_SIZE'd chunks. This is +	 * because we are using @espi->zeropage to provide a zero RX buffer +	 * for the TX transfers and we have only allocated one page for that. +	 * +	 * For performance reasons we allocate a new sg_table only when +	 * needed. Otherwise we will re-use the current one. Eventually the +	 * last sg_table is released in ep93xx_spi_release_dma(). +	 */ + +	nents = DIV_ROUND_UP(len, PAGE_SIZE); +	if (nents != sgt->nents) { +		sg_free_table(sgt); + +		ret = sg_alloc_table(sgt, nents, GFP_KERNEL); +		if (ret) +			return ERR_PTR(ret); +	} + +	pbuf = buf; +	for_each_sg(sgt->sgl, sg, sgt->nents, i) { +		size_t bytes = min_t(size_t, len, PAGE_SIZE); + +		if (buf) { +			sg_set_page(sg, virt_to_page(pbuf), bytes, +				    offset_in_page(pbuf)); +		} else { +			sg_set_page(sg, virt_to_page(espi->zeropage), +				    bytes, 0); +		} + +		pbuf += bytes; +		len -= bytes; +	} + +	if (WARN_ON(len)) { +		dev_warn(&espi->pdev->dev, "len = %d expected 0!", len); +		return ERR_PTR(-EINVAL); +	} + +	nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); +	if (!nents) +		return ERR_PTR(-ENOMEM); + +	txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents, +						 dir, DMA_CTRL_ACK); +	if (!txd) { +		dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); +		return ERR_PTR(-ENOMEM); +	} +	return txd; +} + +/** + * ep93xx_spi_dma_finish() - finishes with a DMA transfer + * @espi: ep93xx SPI controller struct + * @dir: DMA transfer direction + * + * Function finishes with the DMA transfer. After this, the DMA buffer is + * unmapped. + */ +static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi, +				  enum dma_data_direction dir) +{ +	struct dma_chan *chan; +	struct sg_table *sgt; + +	if (dir == DMA_FROM_DEVICE) { +		chan = espi->dma_rx; +		sgt = &espi->rx_sgt; +	} else { +		chan = espi->dma_tx; +		sgt = &espi->tx_sgt; +	} + +	dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); +} + +static void ep93xx_spi_dma_callback(void *callback_param) +{ +	complete(callback_param); +} + +static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi) +{ +	struct spi_message *msg = espi->current_msg; +	struct dma_async_tx_descriptor *rxd, *txd; + +	rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE); +	if (IS_ERR(rxd)) { +		dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd)); +		msg->status = PTR_ERR(rxd); +		return; +	} + +	txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE); +	if (IS_ERR(txd)) { +		ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE); +		dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd)); +		msg->status = PTR_ERR(txd); +		return; +	} + +	/* We are ready when RX is done */ +	rxd->callback = ep93xx_spi_dma_callback; +	rxd->callback_param = &espi->wait; + +	/* Now submit both descriptors and wait while they finish */ +	dmaengine_submit(rxd); +	dmaengine_submit(txd); + +	dma_async_issue_pending(espi->dma_rx); +	dma_async_issue_pending(espi->dma_tx); + +	wait_for_completion(&espi->wait); + +	ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE); +	ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE); +} +  /**   * ep93xx_spi_process_transfer() - processes one SPI transfer   * @espi: ep93xx SPI controller struct @@ -556,13 +757,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,  	espi->tx = 0;  	/* -	 * Now everything is set up for the current transfer. We prime the TX -	 * FIFO, enable interrupts, and wait for the transfer to complete. +	 * There is no point of setting up DMA for the transfers which will +	 * fit into the FIFO and can be transferred with a single interrupt. +	 * So in these cases we will be using PIO and don't bother for DMA.  	 */ -	if (ep93xx_spi_read_write(espi)) { -		ep93xx_spi_enable_interrupts(espi); -		wait_for_completion(&espi->wait); -	} +	if (espi->dma_rx && t->len > SPI_FIFO_SIZE) +		ep93xx_spi_dma_transfer(espi); +	else +		ep93xx_spi_pio_transfer(espi);  	/*  	 * In case of error during transmit, we bail out from processing @@ -571,6 +773,8 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,  	if (msg->status)  		return; +	msg->actual_length += t->len; +  	/*  	 * After this transfer is finished, perform any possible  	 * post-transfer actions requested by the protocol driver. @@ -752,6 +956,75 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } +static bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param) +{ +	if (ep93xx_dma_chan_is_m2p(chan)) +		return false; + +	chan->private = filter_param; +	return true; +} + +static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) +{ +	dma_cap_mask_t mask; +	int ret; + +	espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL); +	if (!espi->zeropage) +		return -ENOMEM; + +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); + +	espi->dma_rx_data.port = EP93XX_DMA_SSP; +	espi->dma_rx_data.direction = DMA_FROM_DEVICE; +	espi->dma_rx_data.name = "ep93xx-spi-rx"; + +	espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter, +					   &espi->dma_rx_data); +	if (!espi->dma_rx) { +		ret = -ENODEV; +		goto fail_free_page; +	} + +	espi->dma_tx_data.port = EP93XX_DMA_SSP; +	espi->dma_tx_data.direction = DMA_TO_DEVICE; +	espi->dma_tx_data.name = "ep93xx-spi-tx"; + +	espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter, +					   &espi->dma_tx_data); +	if (!espi->dma_tx) { +		ret = -ENODEV; +		goto fail_release_rx; +	} + +	return 0; + +fail_release_rx: +	dma_release_channel(espi->dma_rx); +	espi->dma_rx = NULL; +fail_free_page: +	free_page((unsigned long)espi->zeropage); + +	return ret; +} + +static void ep93xx_spi_release_dma(struct ep93xx_spi *espi) +{ +	if (espi->dma_rx) { +		dma_release_channel(espi->dma_rx); +		sg_free_table(&espi->rx_sgt); +	} +	if (espi->dma_tx) { +		dma_release_channel(espi->dma_tx); +		sg_free_table(&espi->tx_sgt); +	} + +	if (espi->zeropage) +		free_page((unsigned long)espi->zeropage); +} +  static int __init ep93xx_spi_probe(struct platform_device *pdev)  {  	struct spi_master *master; @@ -818,6 +1091,7 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)  		goto fail_put_clock;  	} +	espi->sspdr_phys = res->start + SSPDR;  	espi->regs_base = ioremap(res->start, resource_size(res));  	if (!espi->regs_base) {  		dev_err(&pdev->dev, "failed to map resources\n"); @@ -832,10 +1106,13 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)  		goto fail_unmap_regs;  	} +	if (info->use_dma && ep93xx_spi_setup_dma(espi)) +		dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n"); +  	espi->wq = create_singlethread_workqueue("ep93xx_spid");  	if (!espi->wq) {  		dev_err(&pdev->dev, "unable to create workqueue\n"); -		goto fail_free_irq; +		goto fail_free_dma;  	}  	INIT_WORK(&espi->msg_work, ep93xx_spi_work);  	INIT_LIST_HEAD(&espi->msg_queue); @@ -857,7 +1134,8 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)  fail_free_queue:  	destroy_workqueue(espi->wq); -fail_free_irq: +fail_free_dma: +	ep93xx_spi_release_dma(espi);  	free_irq(espi->irq, espi);  fail_unmap_regs:  	iounmap(espi->regs_base); @@ -901,6 +1179,7 @@ static int __exit ep93xx_spi_remove(struct platform_device *pdev)  	}  	spin_unlock_irq(&espi->lock); +	ep93xx_spi_release_dma(espi);  	free_irq(espi->irq, espi);  	iounmap(espi->regs_base);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi-fsl-espi.c index 496f895a0024..54e499d5f92c 100644 --- a/drivers/spi/spi_fsl_espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -22,7 +22,7 @@  #include <linux/err.h>  #include <sysdev/fsl_soc.h> -#include "spi_fsl_lib.h" +#include "spi-fsl-lib.h"  /* eSPI Controller registers */  struct fsl_espi_reg { diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi-fsl-lib.c index ff59f42ae990..2674fad7f68a 100644 --- a/drivers/spi/spi_fsl_lib.c +++ b/drivers/spi/spi-fsl-lib.c @@ -25,7 +25,7 @@  #include <linux/of_spi.h>  #include <sysdev/fsl_soc.h> -#include "spi_fsl_lib.h" +#include "spi-fsl-lib.h"  #define MPC8XXX_SPI_RX_BUF(type) 					  \  void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \ diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi-fsl-lib.h index cbe881b9ea76..cbe881b9ea76 100644 --- a/drivers/spi/spi_fsl_lib.h +++ b/drivers/spi/spi-fsl-lib.h diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi-fsl-spi.c index 7963c9b49566..d2407558773f 100644 --- a/drivers/spi/spi_fsl_spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -37,7 +37,7 @@  #include <asm/cpm.h>  #include <asm/qe.h> -#include "spi_fsl_lib.h" +#include "spi-fsl-lib.h"  /* CPM1 and CPM2 are mutually exclusive. */  #ifdef CONFIG_CPM1 @@ -684,7 +684,7 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)  	struct device_node *np = dev->of_node;  	const u32 *iprop;  	int size; -	unsigned long spi_base_ofs; +	void __iomem *spi_base;  	unsigned long pram_ofs = -ENOMEM;  	/* Can't use of_address_to_resource(), QE muram isn't at 0. */ @@ -702,33 +702,27 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)  		return pram_ofs;  	} -	/* CPM1 and CPM2 pram must be at a fixed addr. */ -	if (!iprop || size != sizeof(*iprop) * 4) -		return -ENOMEM; - -	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2); -	if (IS_ERR_VALUE(spi_base_ofs)) -		return -ENOMEM; +	spi_base = of_iomap(np, 1); +	if (spi_base == NULL) +		return -EINVAL;  	if (mspi->flags & SPI_CPM2) {  		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); -		if (!IS_ERR_VALUE(pram_ofs)) { -			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs); - -			out_be16(spi_base, pram_ofs); -		} +		out_be16(spi_base, pram_ofs);  	} else { -		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs); +		struct spi_pram __iomem *pram = spi_base;  		u16 rpbase = in_be16(&pram->rpbase);  		/* Microcode relocation patch applied? */  		if (rpbase)  			pram_ofs = rpbase; -		else -			return spi_base_ofs; +		else { +			pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); +			out_be16(spi_base, pram_ofs); +		}  	} -	cpm_muram_free(spi_base_ofs); +	iounmap(spi_base);  	return pram_ofs;  } diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi-gpio.c index 63e51b011d50..0e88ab745490 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi-gpio.c @@ -1,5 +1,5 @@  /* - * spi_gpio.c - SPI master driver using generic bitbanged GPIO + * SPI master driver using generic bitbanged GPIO   *   * Copyright (C) 2006,2008 David Brownell   * @@ -69,7 +69,7 @@ struct spi_gpio {   *		#define	SPI_MOSI_GPIO	120   *		#define	SPI_SCK_GPIO	121   *		#define	SPI_N_CHIPSEL	4 - *		#include "spi_gpio.c" + *		#include "spi-gpio.c"   */  #ifndef DRIVER_NAME @@ -127,7 +127,7 @@ static inline int getmiso(const struct spi_device *spi)   */  #define spidelay(nsecs)	do {} while (0) -#include "spi_bitbang_txrx.h" +#include "spi-bitbang-txrx.h"  /*   * These functions can leverage inline expansion of GPIO calls to shrink diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi-imx.c index 69d6dba67c19..8ac6542aedcd 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi-imx.c @@ -34,6 +34,9 @@  #include <linux/spi/spi.h>  #include <linux/spi/spi_bitbang.h>  #include <linux/types.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h>  #include <mach/spi.h> @@ -45,9 +48,6 @@  #define MXC_CSPIINT		0x0c  #define MXC_RESET		0x1c -#define MX3_CSPISTAT		0x14 -#define MX3_CSPISTAT_RR		(1 << 3) -  /* generic defines to abstract from the different register layouts */  #define MXC_INT_RR	(1 << 0) /* Receive data ready interrupt */  #define MXC_INT_TE	(1 << 1) /* Transmit FIFO empty interrupt */ @@ -60,12 +60,12 @@ struct spi_imx_config {  };  enum spi_imx_devtype { -	SPI_IMX_VER_IMX1, -	SPI_IMX_VER_0_0, -	SPI_IMX_VER_0_4, -	SPI_IMX_VER_0_5, -	SPI_IMX_VER_0_7, -	SPI_IMX_VER_2_3, +	IMX1_CSPI, +	IMX21_CSPI, +	IMX27_CSPI, +	IMX31_CSPI, +	IMX35_CSPI,	/* CSPI on all i.mx except above */ +	IMX51_ECSPI,	/* ECSPI on i.mx51 and later */  };  struct spi_imx_data; @@ -76,7 +76,7 @@ struct spi_imx_devtype_data {  	void (*trigger)(struct spi_imx_data *);  	int (*rx_available)(struct spi_imx_data *);  	void (*reset)(struct spi_imx_data *); -	unsigned int fifosize; +	enum spi_imx_devtype devtype;  };  struct spi_imx_data { @@ -87,7 +87,6 @@ struct spi_imx_data {  	int irq;  	struct clk *clk;  	unsigned long spi_clk; -	int *chipselect;  	unsigned int count;  	void (*tx)(struct spi_imx_data *); @@ -96,9 +95,25 @@ struct spi_imx_data {  	const void *tx_buf;  	unsigned int txfifo; /* number of words pushed in tx FIFO */ -	struct spi_imx_devtype_data devtype_data; +	struct spi_imx_devtype_data *devtype_data; +	int chipselect[0];  }; +static inline int is_imx27_cspi(struct spi_imx_data *d) +{ +	return d->devtype_data->devtype == IMX27_CSPI; +} + +static inline int is_imx35_cspi(struct spi_imx_data *d) +{ +	return d->devtype_data->devtype == IMX35_CSPI; +} + +static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) +{ +	return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8; +} +  #define MXC_SPI_BUF_RX(type)						\  static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx)		\  {									\ @@ -140,14 +155,9 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,  /* MX21, MX27 */  static unsigned int spi_imx_clkdiv_1(unsigned int fin, -		unsigned int fspi) +		unsigned int fspi, unsigned int max)  { -	int i, max; - -	if (cpu_is_mx21()) -		max = 18; -	else -		max = 16; +	int i;  	for (i = 2; i < max; i++)  		if (fspi * mxc_clkdivs[i] >= fin) @@ -171,30 +181,30 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,  	return 7;  } -#define SPI_IMX2_3_CTRL		0x08 -#define SPI_IMX2_3_CTRL_ENABLE		(1 <<  0) -#define SPI_IMX2_3_CTRL_XCH		(1 <<  2) -#define SPI_IMX2_3_CTRL_MODE_MASK	(0xf << 4) -#define SPI_IMX2_3_CTRL_POSTDIV_OFFSET	8 -#define SPI_IMX2_3_CTRL_PREDIV_OFFSET	12 -#define SPI_IMX2_3_CTRL_CS(cs)		((cs) << 18) -#define SPI_IMX2_3_CTRL_BL_OFFSET	20 +#define MX51_ECSPI_CTRL		0x08 +#define MX51_ECSPI_CTRL_ENABLE		(1 <<  0) +#define MX51_ECSPI_CTRL_XCH		(1 <<  2) +#define MX51_ECSPI_CTRL_MODE_MASK	(0xf << 4) +#define MX51_ECSPI_CTRL_POSTDIV_OFFSET	8 +#define MX51_ECSPI_CTRL_PREDIV_OFFSET	12 +#define MX51_ECSPI_CTRL_CS(cs)		((cs) << 18) +#define MX51_ECSPI_CTRL_BL_OFFSET	20 -#define SPI_IMX2_3_CONFIG	0x0c -#define SPI_IMX2_3_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0)) -#define SPI_IMX2_3_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4)) -#define SPI_IMX2_3_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8)) -#define SPI_IMX2_3_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12)) +#define MX51_ECSPI_CONFIG	0x0c +#define MX51_ECSPI_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0)) +#define MX51_ECSPI_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4)) +#define MX51_ECSPI_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8)) +#define MX51_ECSPI_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12)) -#define SPI_IMX2_3_INT		0x10 -#define SPI_IMX2_3_INT_TEEN		(1 <<  0) -#define SPI_IMX2_3_INT_RREN		(1 <<  3) +#define MX51_ECSPI_INT		0x10 +#define MX51_ECSPI_INT_TEEN		(1 <<  0) +#define MX51_ECSPI_INT_RREN		(1 <<  3) -#define SPI_IMX2_3_STAT		0x18 -#define SPI_IMX2_3_STAT_RR		(1 <<  3) +#define MX51_ECSPI_STAT		0x18 +#define MX51_ECSPI_STAT_RR		(1 <<  3)  /* MX51 eCSPI */ -static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi) +static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)  {  	/*  	 * there are two 4-bit dividers, the pre-divider divides by @@ -222,36 +232,36 @@ static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)  	pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",  			__func__, fin, fspi, post, pre); -	return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) | -		(post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET); +	return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) | +		(post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);  } -static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable) +static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)  {  	unsigned val = 0;  	if (enable & MXC_INT_TE) -		val |= SPI_IMX2_3_INT_TEEN; +		val |= MX51_ECSPI_INT_TEEN;  	if (enable & MXC_INT_RR) -		val |= SPI_IMX2_3_INT_RREN; +		val |= MX51_ECSPI_INT_RREN; -	writel(val, spi_imx->base + SPI_IMX2_3_INT); +	writel(val, spi_imx->base + MX51_ECSPI_INT);  } -static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx) +static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)  {  	u32 reg; -	reg = readl(spi_imx->base + SPI_IMX2_3_CTRL); -	reg |= SPI_IMX2_3_CTRL_XCH; -	writel(reg, spi_imx->base + SPI_IMX2_3_CTRL); +	reg = readl(spi_imx->base + MX51_ECSPI_CTRL); +	reg |= MX51_ECSPI_CTRL_XCH; +	writel(reg, spi_imx->base + MX51_ECSPI_CTRL);  } -static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx, +static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,  		struct spi_imx_config *config)  { -	u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0; +	u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;  	/*  	 * The hardware seems to have a race condition when changing modes. The @@ -260,42 +270,42 @@ static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,  	 * the same time.  	 * So set master mode for all channels as we do not support slave mode.  	 */ -	ctrl |= SPI_IMX2_3_CTRL_MODE_MASK; +	ctrl |= MX51_ECSPI_CTRL_MODE_MASK;  	/* set clock speed */ -	ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz); +	ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);  	/* set chip select to use */ -	ctrl |= SPI_IMX2_3_CTRL_CS(config->cs); +	ctrl |= MX51_ECSPI_CTRL_CS(config->cs); -	ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET; +	ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET; -	cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs); +	cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);  	if (config->mode & SPI_CPHA) -		cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs); +		cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);  	if (config->mode & SPI_CPOL) -		cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs); +		cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);  	if (config->mode & SPI_CS_HIGH) -		cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs); +		cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs); -	writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL); -	writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG); +	writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); +	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);  	return 0;  } -static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx) +static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)  { -	return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR; +	return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR;  } -static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx) +static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)  {  	/* drain receive buffer */ -	while (spi_imx2_3_rx_available(spi_imx)) +	while (mx51_ecspi_rx_available(spi_imx))  		readl(spi_imx->base + MXC_CSPIRXDATA);  } @@ -343,32 +353,7 @@ static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)  	writel(reg, spi_imx->base + MXC_CSPICTRL);  } -static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx, -		struct spi_imx_config *config) -{ -	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; -	int cs = spi_imx->chipselect[config->cs]; - -	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) << -		MX31_CSPICTRL_DR_SHIFT; - -	reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; - -	if (config->mode & SPI_CPHA) -		reg |= MX31_CSPICTRL_PHA; -	if (config->mode & SPI_CPOL) -		reg |= MX31_CSPICTRL_POL; -	if (config->mode & SPI_CS_HIGH) -		reg |= MX31_CSPICTRL_SSPOL; -	if (cs < 0) -		reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT; - -	writel(reg, spi_imx->base + MXC_CSPICTRL); - -	return 0; -} - -static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx, +static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,  		struct spi_imx_config *config)  {  	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; @@ -377,8 +362,12 @@ static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,  	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<  		MX31_CSPICTRL_DR_SHIFT; -	reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; -	reg |= MX31_CSPICTRL_SSCTL; +	if (is_imx35_cspi(spi_imx)) { +		reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; +		reg |= MX31_CSPICTRL_SSCTL; +	} else { +		reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; +	}  	if (config->mode & SPI_CPHA)  		reg |= MX31_CSPICTRL_PHA; @@ -387,7 +376,9 @@ static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,  	if (config->mode & SPI_CS_HIGH)  		reg |= MX31_CSPICTRL_SSPOL;  	if (cs < 0) -		reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT; +		reg |= (cs + 32) << +			(is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT : +						  MX31_CSPICTRL_CS_SHIFT);  	writel(reg, spi_imx->base + MXC_CSPICTRL); @@ -399,77 +390,78 @@ static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)  	return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;  } -static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx) +static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx)  {  	/* drain receive buffer */ -	while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR) +	while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR)  		readl(spi_imx->base + MXC_CSPIRXDATA);  } -#define MX27_INTREG_RR		(1 << 4) -#define MX27_INTREG_TEEN	(1 << 9) -#define MX27_INTREG_RREN	(1 << 13) +#define MX21_INTREG_RR		(1 << 4) +#define MX21_INTREG_TEEN	(1 << 9) +#define MX21_INTREG_RREN	(1 << 13) -#define MX27_CSPICTRL_POL	(1 << 5) -#define MX27_CSPICTRL_PHA	(1 << 6) -#define MX27_CSPICTRL_SSPOL	(1 << 8) -#define MX27_CSPICTRL_XCH	(1 << 9) -#define MX27_CSPICTRL_ENABLE	(1 << 10) -#define MX27_CSPICTRL_MASTER	(1 << 11) -#define MX27_CSPICTRL_DR_SHIFT	14 -#define MX27_CSPICTRL_CS_SHIFT	19 +#define MX21_CSPICTRL_POL	(1 << 5) +#define MX21_CSPICTRL_PHA	(1 << 6) +#define MX21_CSPICTRL_SSPOL	(1 << 8) +#define MX21_CSPICTRL_XCH	(1 << 9) +#define MX21_CSPICTRL_ENABLE	(1 << 10) +#define MX21_CSPICTRL_MASTER	(1 << 11) +#define MX21_CSPICTRL_DR_SHIFT	14 +#define MX21_CSPICTRL_CS_SHIFT	19 -static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable) +static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable)  {  	unsigned int val = 0;  	if (enable & MXC_INT_TE) -		val |= MX27_INTREG_TEEN; +		val |= MX21_INTREG_TEEN;  	if (enable & MXC_INT_RR) -		val |= MX27_INTREG_RREN; +		val |= MX21_INTREG_RREN;  	writel(val, spi_imx->base + MXC_CSPIINT);  } -static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx) +static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)  {  	unsigned int reg;  	reg = readl(spi_imx->base + MXC_CSPICTRL); -	reg |= MX27_CSPICTRL_XCH; +	reg |= MX21_CSPICTRL_XCH;  	writel(reg, spi_imx->base + MXC_CSPICTRL);  } -static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx, +static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx,  		struct spi_imx_config *config)  { -	unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER; +	unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;  	int cs = spi_imx->chipselect[config->cs]; +	unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; -	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) << -		MX27_CSPICTRL_DR_SHIFT; +	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) << +		MX21_CSPICTRL_DR_SHIFT;  	reg |= config->bpw - 1;  	if (config->mode & SPI_CPHA) -		reg |= MX27_CSPICTRL_PHA; +		reg |= MX21_CSPICTRL_PHA;  	if (config->mode & SPI_CPOL) -		reg |= MX27_CSPICTRL_POL; +		reg |= MX21_CSPICTRL_POL;  	if (config->mode & SPI_CS_HIGH) -		reg |= MX27_CSPICTRL_SSPOL; +		reg |= MX21_CSPICTRL_SSPOL;  	if (cs < 0) -		reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT; +		reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT;  	writel(reg, spi_imx->base + MXC_CSPICTRL);  	return 0;  } -static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx) +static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx)  { -	return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR; +	return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR;  } -static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx) +static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)  {  	writel(1, spi_imx->base + MXC_RESET);  } @@ -535,61 +527,94 @@ static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)  	writel(1, spi_imx->base + MXC_RESET);  } -/* - * These version numbers are taken from the Freescale driver.  Unfortunately it - * doesn't support i.MX1, so this entry doesn't match the scheme. :-( - */ -static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = { -#ifdef CONFIG_SPI_IMX_VER_IMX1 -	[SPI_IMX_VER_IMX1] = { -		.intctrl = mx1_intctrl, -		.config = mx1_config, -		.trigger = mx1_trigger, -		.rx_available = mx1_rx_available, -		.reset = mx1_reset, -		.fifosize = 8, -	}, -#endif -#ifdef CONFIG_SPI_IMX_VER_0_0 -	[SPI_IMX_VER_0_0] = { -		.intctrl = mx27_intctrl, -		.config = mx27_config, -		.trigger = mx27_trigger, -		.rx_available = mx27_rx_available, -		.reset = spi_imx0_0_reset, -		.fifosize = 8, -	}, -#endif -#ifdef CONFIG_SPI_IMX_VER_0_4 -	[SPI_IMX_VER_0_4] = { -		.intctrl = mx31_intctrl, -		.config = spi_imx0_4_config, -		.trigger = mx31_trigger, -		.rx_available = mx31_rx_available, -		.reset = spi_imx0_4_reset, -		.fifosize = 8, -	}, -#endif -#ifdef CONFIG_SPI_IMX_VER_0_7 -	[SPI_IMX_VER_0_7] = { -		.intctrl = mx31_intctrl, -		.config = spi_imx0_7_config, -		.trigger = mx31_trigger, -		.rx_available = mx31_rx_available, -		.reset = spi_imx0_4_reset, -		.fifosize = 8, -	}, -#endif -#ifdef CONFIG_SPI_IMX_VER_2_3 -	[SPI_IMX_VER_2_3] = { -		.intctrl = spi_imx2_3_intctrl, -		.config = spi_imx2_3_config, -		.trigger = spi_imx2_3_trigger, -		.rx_available = spi_imx2_3_rx_available, -		.reset = spi_imx2_3_reset, -		.fifosize = 64, -	}, -#endif +static struct spi_imx_devtype_data imx1_cspi_devtype_data = { +	.intctrl = mx1_intctrl, +	.config = mx1_config, +	.trigger = mx1_trigger, +	.rx_available = mx1_rx_available, +	.reset = mx1_reset, +	.devtype = IMX1_CSPI, +}; + +static struct spi_imx_devtype_data imx21_cspi_devtype_data = { +	.intctrl = mx21_intctrl, +	.config = mx21_config, +	.trigger = mx21_trigger, +	.rx_available = mx21_rx_available, +	.reset = mx21_reset, +	.devtype = IMX21_CSPI, +}; + +static struct spi_imx_devtype_data imx27_cspi_devtype_data = { +	/* i.mx27 cspi shares the functions with i.mx21 one */ +	.intctrl = mx21_intctrl, +	.config = mx21_config, +	.trigger = mx21_trigger, +	.rx_available = mx21_rx_available, +	.reset = mx21_reset, +	.devtype = IMX27_CSPI, +}; + +static struct spi_imx_devtype_data imx31_cspi_devtype_data = { +	.intctrl = mx31_intctrl, +	.config = mx31_config, +	.trigger = mx31_trigger, +	.rx_available = mx31_rx_available, +	.reset = mx31_reset, +	.devtype = IMX31_CSPI, +}; + +static struct spi_imx_devtype_data imx35_cspi_devtype_data = { +	/* i.mx35 and later cspi shares the functions with i.mx31 one */ +	.intctrl = mx31_intctrl, +	.config = mx31_config, +	.trigger = mx31_trigger, +	.rx_available = mx31_rx_available, +	.reset = mx31_reset, +	.devtype = IMX35_CSPI, +}; + +static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { +	.intctrl = mx51_ecspi_intctrl, +	.config = mx51_ecspi_config, +	.trigger = mx51_ecspi_trigger, +	.rx_available = mx51_ecspi_rx_available, +	.reset = mx51_ecspi_reset, +	.devtype = IMX51_ECSPI, +}; + +static struct platform_device_id spi_imx_devtype[] = { +	{ +		.name = "imx1-cspi", +		.driver_data = (kernel_ulong_t) &imx1_cspi_devtype_data, +	}, { +		.name = "imx21-cspi", +		.driver_data = (kernel_ulong_t) &imx21_cspi_devtype_data, +	}, { +		.name = "imx27-cspi", +		.driver_data = (kernel_ulong_t) &imx27_cspi_devtype_data, +	}, { +		.name = "imx31-cspi", +		.driver_data = (kernel_ulong_t) &imx31_cspi_devtype_data, +	}, { +		.name = "imx35-cspi", +		.driver_data = (kernel_ulong_t) &imx35_cspi_devtype_data, +	}, { +		.name = "imx51-ecspi", +		.driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data, +	}, { +		/* sentinel */ +	} +}; + +static const struct of_device_id spi_imx_dt_ids[] = { +	{ .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, }, +	{ .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, }, +	{ .compatible = "fsl,imx27-cspi", .data = &imx27_cspi_devtype_data, }, +	{ .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, }, +	{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, }, +	{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, }, +	{ /* sentinel */ }  };  static void spi_imx_chipselect(struct spi_device *spi, int is_active) @@ -607,21 +632,21 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active)  static void spi_imx_push(struct spi_imx_data *spi_imx)  { -	while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) { +	while (spi_imx->txfifo < spi_imx_get_fifosize(spi_imx)) {  		if (!spi_imx->count)  			break;  		spi_imx->tx(spi_imx);  		spi_imx->txfifo++;  	} -	spi_imx->devtype_data.trigger(spi_imx); +	spi_imx->devtype_data->trigger(spi_imx);  }  static irqreturn_t spi_imx_isr(int irq, void *dev_id)  {  	struct spi_imx_data *spi_imx = dev_id; -	while (spi_imx->devtype_data.rx_available(spi_imx)) { +	while (spi_imx->devtype_data->rx_available(spi_imx)) {  		spi_imx->rx(spi_imx);  		spi_imx->txfifo--;  	} @@ -635,12 +660,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)  		/* No data left to push, but still waiting for rx data,  		 * enable receive data available interrupt.  		 */ -		spi_imx->devtype_data.intctrl( +		spi_imx->devtype_data->intctrl(  				spi_imx, MXC_INT_RR);  		return IRQ_HANDLED;  	} -	spi_imx->devtype_data.intctrl(spi_imx, 0); +	spi_imx->devtype_data->intctrl(spi_imx, 0);  	complete(&spi_imx->xfer_done);  	return IRQ_HANDLED; @@ -677,7 +702,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,  	} else  		BUG(); -	spi_imx->devtype_data.config(spi_imx, &config); +	spi_imx->devtype_data->config(spi_imx, &config);  	return 0;  } @@ -696,7 +721,7 @@ static int spi_imx_transfer(struct spi_device *spi,  	spi_imx_push(spi_imx); -	spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE); +	spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);  	wait_for_completion(&spi_imx->xfer_done); @@ -723,72 +748,47 @@ static void spi_imx_cleanup(struct spi_device *spi)  {  } -static struct platform_device_id spi_imx_devtype[] = { -	{ -		.name = "imx1-cspi", -		.driver_data = SPI_IMX_VER_IMX1, -	}, { -		.name = "imx21-cspi", -		.driver_data = SPI_IMX_VER_0_0, -	}, { -		.name = "imx25-cspi", -		.driver_data = SPI_IMX_VER_0_7, -	}, { -		.name = "imx27-cspi", -		.driver_data = SPI_IMX_VER_0_0, -	}, { -		.name = "imx31-cspi", -		.driver_data = SPI_IMX_VER_0_4, -	}, { -		.name = "imx35-cspi", -		.driver_data = SPI_IMX_VER_0_7, -	}, { -		.name = "imx51-cspi", -		.driver_data = SPI_IMX_VER_0_7, -	}, { -		.name = "imx51-ecspi", -		.driver_data = SPI_IMX_VER_2_3, -	}, { -		.name = "imx53-cspi", -		.driver_data = SPI_IMX_VER_0_7, -	}, { -		.name = "imx53-ecspi", -		.driver_data = SPI_IMX_VER_2_3, -	}, { -		/* sentinel */ -	} -}; -  static int __devinit spi_imx_probe(struct platform_device *pdev)  { -	struct spi_imx_master *mxc_platform_info; +	struct device_node *np = pdev->dev.of_node; +	const struct of_device_id *of_id = +			of_match_device(spi_imx_dt_ids, &pdev->dev); +	struct spi_imx_master *mxc_platform_info = +			dev_get_platdata(&pdev->dev);  	struct spi_master *master;  	struct spi_imx_data *spi_imx;  	struct resource *res; -	int i, ret; +	int i, ret, num_cs; -	mxc_platform_info = dev_get_platdata(&pdev->dev); -	if (!mxc_platform_info) { +	if (!np && !mxc_platform_info) {  		dev_err(&pdev->dev, "can't get the platform data\n");  		return -EINVAL;  	} -	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data)); +	ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs); +	if (ret < 0) +		num_cs = mxc_platform_info->num_chipselect; + +	master = spi_alloc_master(&pdev->dev, +			sizeof(struct spi_imx_data) + sizeof(int) * num_cs);  	if (!master)  		return -ENOMEM;  	platform_set_drvdata(pdev, master);  	master->bus_num = pdev->id; -	master->num_chipselect = mxc_platform_info->num_chipselect; +	master->num_chipselect = num_cs;  	spi_imx = spi_master_get_devdata(master);  	spi_imx->bitbang.master = spi_master_get(master); -	spi_imx->chipselect = mxc_platform_info->chipselect;  	for (i = 0; i < master->num_chipselect; i++) { -		if (spi_imx->chipselect[i] < 0) +		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); +		if (cs_gpio < 0) +			cs_gpio = mxc_platform_info->chipselect[i]; +		if (cs_gpio < 0)  			continue; +		spi_imx->chipselect[i] = cs_gpio;  		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);  		if (ret) {  			while (i > 0) { @@ -810,8 +810,8 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)  	init_completion(&spi_imx->xfer_done); -	spi_imx->devtype_data = -		spi_imx_devtype_data[pdev->id_entry->driver_data]; +	spi_imx->devtype_data = of_id ? of_id->data : +		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) { @@ -854,10 +854,11 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)  	clk_enable(spi_imx->clk);  	spi_imx->spi_clk = clk_get_rate(spi_imx->clk); -	spi_imx->devtype_data.reset(spi_imx); +	spi_imx->devtype_data->reset(spi_imx); -	spi_imx->devtype_data.intctrl(spi_imx, 0); +	spi_imx->devtype_data->intctrl(spi_imx, 0); +	master->dev.of_node = pdev->dev.of_node;  	ret = spi_bitbang_start(&spi_imx->bitbang);  	if (ret) {  		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); @@ -920,6 +921,7 @@ static struct platform_driver spi_imx_driver = {  	.driver = {  		   .name = DRIVER_NAME,  		   .owner = THIS_MODULE, +		   .of_match_table = spi_imx_dt_ids,  		   },  	.id_table = spi_imx_devtype,  	.probe = spi_imx_probe, diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi-lm70llp.c index 7746a41ab6d6..933eb9d9ddd4 100644 --- a/drivers/spi/spi_lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -1,5 +1,5 @@  /* - * spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor + * Driver for LM70EVAL-LLP board for the LM70 sensor   *   * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>   * @@ -174,7 +174,7 @@ static inline int getmiso(struct spi_device *s)  }  /*--------------------------------------------------------------------*/ -#include "spi_bitbang_txrx.h" +#include "spi-bitbang-txrx.h"  static void lm70_chipselect(struct spi_device *spi, int value)  { diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/spi-mpc512x-psc.c index 6a5b4238fb6b..6a5b4238fb6b 100644 --- a/drivers/spi/mpc512x_psc_spi.c +++ b/drivers/spi/spi-mpc512x-psc.c diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/spi-mpc52xx-psc.c index e30baf0852ac..e30baf0852ac 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/spi-mpc52xx-psc.c diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/spi-mpc52xx.c index 015a974bed72..015a974bed72 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/spi-mpc52xx.c diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi-nuc900.c index 3cd15f690f16..c0a6ce81f9c0 100644 --- a/drivers/spi/spi_nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -1,5 +1,4 @@ -/* linux/drivers/spi/spi_nuc900.c - * +/*   * Copyright (c) 2009 Nuvoton technology.   * Wan ZongShun <mcuos.com@gmail.com>   * @@ -7,7 +6,7 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   * -*/ + */  #include <linux/init.h>  #include <linux/spinlock.h> diff --git a/drivers/spi/spi_oc_tiny.c b/drivers/spi/spi-oc-tiny.c index f1bde66cea19..f1bde66cea19 100644 --- a/drivers/spi/spi_oc_tiny.c +++ b/drivers/spi/spi-oc-tiny.c diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/spi-omap-100k.c index 9bd1c92ad96e..9bd1c92ad96e 100644 --- a/drivers/spi/omap_spi_100k.c +++ b/drivers/spi/spi-omap-100k.c diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/spi-omap-uwire.c index 160d3266205f..00a8e9d7dbe4 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -1,5 +1,5 @@  /* - * omap_uwire.c -- MicroWire interface driver for OMAP + * MicroWire interface driver for OMAP   *   * Copyright 2003 MontaVista Software Inc. <source@mvista.com>   * diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 6f86ba0175ac..fde3a2d4f120 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -298,7 +298,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)  	unsigned int		count, c;  	unsigned long		base, tx_reg, rx_reg;  	int			word_len, data_type, element_count; -	int			elements; +	int			elements = 0;  	u32			l;  	u8			* rx;  	const u8		* tx; @@ -1116,8 +1116,8 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  		status = -ENODEV;  		goto err1;  	} -	if (!request_mem_region(r->start, (r->end - r->start) + 1, -			dev_name(&pdev->dev))) { +	if (!request_mem_region(r->start, resource_size(r), +				dev_name(&pdev->dev))) {  		status = -EBUSY;  		goto err1;  	} @@ -1125,7 +1125,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)  	r->start += pdata->regs_offset;  	r->end += pdata->regs_offset;  	mcspi->phys = r->start; -	mcspi->base = ioremap(r->start, r->end - r->start + 1); +	mcspi->base = ioremap(r->start, resource_size(r));  	if (!mcspi->base) {  		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");  		status = -ENOMEM; @@ -1190,7 +1190,7 @@ err4:  err3:  	kfree(mcspi->dma_channels);  err2: -	release_mem_region(r->start, (r->end - r->start) + 1); +	release_mem_region(r->start, resource_size(r));  	iounmap(mcspi->base);  err1:  	return status; @@ -1210,7 +1210,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)  	omap2_mcspi_disable_clocks(mcspi);  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	release_mem_region(r->start, (r->end - r->start) + 1); +	release_mem_region(r->start, resource_size(r));  	base = mcspi->base;  	spi_unregister_master(master); diff --git a/drivers/spi/orion_spi.c b/drivers/spi/spi-orion.c index 0b677dc041ad..9421a390a5e3 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/spi-orion.c @@ -1,5 +1,5 @@  /* - * orion_spi.c -- Marvell Orion SPI controller driver + * Marvell Orion SPI controller driver   *   * Author: Shadi Ammouri <shadi@marvell.com>   * Copyright (C) 2007-2008 Marvell Ltd. @@ -489,7 +489,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)  		goto out;  	} -	if (!request_mem_region(r->start, (r->end - r->start) + 1, +	if (!request_mem_region(r->start, resource_size(r),  				dev_name(&pdev->dev))) {  		status = -EBUSY;  		goto out; @@ -511,7 +511,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)  	return status;  out_rel_mem: -	release_mem_region(r->start, (r->end - r->start) + 1); +	release_mem_region(r->start, resource_size(r));  out:  	spi_master_put(master); @@ -531,7 +531,7 @@ static int __exit orion_spi_remove(struct platform_device *pdev)  	cancel_work_sync(&spi->work);  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	release_mem_region(r->start, (r->end - r->start) + 1); +	release_mem_region(r->start, resource_size(r));  	spi_unregister_master(master); diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/spi-pl022.c index 6a9e58dd36c7..730b4a37b823 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1,6 +1,4 @@  /* - * drivers/spi/amba-pl022.c - *   * A driver for the ARM PL022 PrimeCell SSP/SPI bus master.   *   * Copyright (C) 2008-2009 ST-Ericsson AB @@ -42,6 +40,7 @@  #include <linux/dmaengine.h>  #include <linux/dma-mapping.h>  #include <linux/scatterlist.h> +#include <linux/pm_runtime.h>  /*   * This macro is used to define some register default values. @@ -383,6 +382,8 @@ struct pl022 {  	enum ssp_reading		read;  	enum ssp_writing		write;  	u32				exp_fifo_level; +	enum ssp_rx_level_trig		rx_lev_trig; +	enum ssp_tx_level_trig		tx_lev_trig;  	/* DMA settings */  #ifdef CONFIG_DMA_ENGINE  	struct dma_chan			*dma_rx_channel; @@ -517,6 +518,7 @@ static void giveback(struct pl022 *pl022)  	clk_disable(pl022->clk);  	amba_pclk_disable(pl022->adev);  	amba_vcore_disable(pl022->adev); +	pm_runtime_put(&pl022->adev->dev);  }  /** @@ -909,12 +911,10 @@ 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; @@ -928,6 +928,54 @@ static int configure_dma(struct pl022 *pl022)  	if (!rxchan || !txchan)  		return -ENODEV; +	/* +	 * If supplied, the DMA burstsize should equal the FIFO trigger level. +	 * Notice that the DMA engine uses one-to-one mapping. Since we can +	 * not trigger on 2 elements this needs explicit mapping rather than +	 * calculation. +	 */ +	switch (pl022->rx_lev_trig) { +	case SSP_RX_1_OR_MORE_ELEM: +		rx_conf.src_maxburst = 1; +		break; +	case SSP_RX_4_OR_MORE_ELEM: +		rx_conf.src_maxburst = 4; +		break; +	case SSP_RX_8_OR_MORE_ELEM: +		rx_conf.src_maxburst = 8; +		break; +	case SSP_RX_16_OR_MORE_ELEM: +		rx_conf.src_maxburst = 16; +		break; +	case SSP_RX_32_OR_MORE_ELEM: +		rx_conf.src_maxburst = 32; +		break; +	default: +		rx_conf.src_maxburst = pl022->vendor->fifodepth >> 1; +		break; +	} + +	switch (pl022->tx_lev_trig) { +	case SSP_TX_1_OR_MORE_EMPTY_LOC: +		tx_conf.dst_maxburst = 1; +		break; +	case SSP_TX_4_OR_MORE_EMPTY_LOC: +		tx_conf.dst_maxburst = 4; +		break; +	case SSP_TX_8_OR_MORE_EMPTY_LOC: +		tx_conf.dst_maxburst = 8; +		break; +	case SSP_TX_16_OR_MORE_EMPTY_LOC: +		tx_conf.dst_maxburst = 16; +		break; +	case SSP_TX_32_OR_MORE_EMPTY_LOC: +		tx_conf.dst_maxburst = 32; +		break; +	default: +		tx_conf.dst_maxburst = pl022->vendor->fifodepth >> 1; +		break; +	} +  	switch (pl022->read) {  	case READING_NULL:  		/* Use the same as for writing */ @@ -1496,6 +1544,7 @@ static void pump_messages(struct work_struct *work)  	 * and core will be disabled when giveback() is called in each method  	 * (poll/interrupt/DMA)  	 */ +	pm_runtime_get_sync(&pl022->adev->dev);  	amba_vcore_enable(pl022->adev);  	amba_pclk_enable(pl022->adev);  	clk_enable(pl022->clk); @@ -1629,17 +1678,57 @@ static int verify_controller_parameters(struct pl022 *pl022,  			"Communication mode is configured incorrectly\n");  		return -EINVAL;  	} -	if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM) -	    || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) { +	switch (chip_info->rx_lev_trig) { +	case SSP_RX_1_OR_MORE_ELEM: +	case SSP_RX_4_OR_MORE_ELEM: +	case SSP_RX_8_OR_MORE_ELEM: +		/* These are always OK, all variants can handle this */ +		break; +	case SSP_RX_16_OR_MORE_ELEM: +		if (pl022->vendor->fifodepth < 16) { +			dev_err(&pl022->adev->dev, +			"RX FIFO Trigger Level is configured incorrectly\n"); +			return -EINVAL; +		} +		break; +	case SSP_RX_32_OR_MORE_ELEM: +		if (pl022->vendor->fifodepth < 32) { +			dev_err(&pl022->adev->dev, +			"RX FIFO Trigger Level is configured incorrectly\n"); +			return -EINVAL; +		} +		break; +	default:  		dev_err(&pl022->adev->dev,  			"RX FIFO Trigger Level is configured incorrectly\n");  		return -EINVAL; +		break;  	} -	if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC) -	    || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) { +	switch (chip_info->tx_lev_trig) { +	case SSP_TX_1_OR_MORE_EMPTY_LOC: +	case SSP_TX_4_OR_MORE_EMPTY_LOC: +	case SSP_TX_8_OR_MORE_EMPTY_LOC: +		/* These are always OK, all variants can handle this */ +		break; +	case SSP_TX_16_OR_MORE_EMPTY_LOC: +		if (pl022->vendor->fifodepth < 16) { +			dev_err(&pl022->adev->dev, +			"TX FIFO Trigger Level is configured incorrectly\n"); +			return -EINVAL; +		} +		break; +	case SSP_TX_32_OR_MORE_EMPTY_LOC: +		if (pl022->vendor->fifodepth < 32) { +			dev_err(&pl022->adev->dev, +			"TX FIFO Trigger Level is configured incorrectly\n"); +			return -EINVAL; +		} +		break; +	default:  		dev_err(&pl022->adev->dev,  			"TX FIFO Trigger Level is configured incorrectly\n");  		return -EINVAL; +		break;  	}  	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {  		if ((chip_info->ctrl_len < SSP_BITS_4) @@ -1861,6 +1950,7 @@ static int pl022_setup(struct spi_device *spi)  	}  	if ((clk_freq.cpsdvsr < CPSDVR_MIN)  	    || (clk_freq.cpsdvsr > CPSDVR_MAX)) { +		status = -EINVAL;  		dev_err(&spi->dev,  			"cpsdvsr is configured incorrectly\n");  		goto err_config_params; @@ -1873,6 +1963,9 @@ static int pl022_setup(struct spi_device *spi)  		goto err_config_params;  	} +	pl022->rx_lev_trig = chip_info->rx_lev_trig; +	pl022->tx_lev_trig = chip_info->tx_lev_trig; +  	/* Now set controller state based on controller data */  	chip->xfer_type = chip_info->com_mode;  	if (!chip_info->cs_control) { @@ -2093,6 +2186,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)  	}  	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",  	       adev->res.start, pl022->virtbase); +	pm_runtime_enable(dev); +	pm_runtime_resume(dev);  	pl022->clk = clk_get(&adev->dev, NULL);  	if (IS_ERR(pl022->clk)) { @@ -2154,6 +2249,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)  	destroy_queue(pl022);  	pl022_dma_remove(pl022);  	free_irq(adev->irq[0], pl022); +	pm_runtime_disable(&adev->dev);   err_no_irq:  	clk_put(pl022->clk);   err_no_clk: @@ -2171,17 +2267,13 @@ static int __devexit  pl022_remove(struct amba_device *adev)  {  	struct pl022 *pl022 = amba_get_drvdata(adev); -	int status = 0; +  	if (!pl022)  		return 0;  	/* Remove the queue */ -	status = destroy_queue(pl022); -	if (status != 0) { -		dev_err(&adev->dev, -			"queue remove failed (%d)\n", status); -		return status; -	} +	if (destroy_queue(pl022) != 0) +		dev_err(&adev->dev, "queue remove failed\n");  	load_ssp_default_config(pl022);  	pl022_dma_remove(pl022);  	free_irq(adev->irq[0], pl022); @@ -2193,7 +2285,6 @@ pl022_remove(struct amba_device *adev)  	spi_unregister_master(pl022->master);  	spi_master_put(pl022->master);  	amba_set_drvdata(adev, NULL); -	dev_dbg(&adev->dev, "remove succeeded\n");  	return 0;  } diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 2a298c029194..b267fd901e54 100644 --- a/drivers/spi/spi_ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -502,7 +502,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)  		goto free_gpios;  	}  	hw->mapbase = resource.start; -	hw->mapsize = resource.end - resource.start + 1; +	hw->mapsize = resource_size(&resource);  	/* Sanity check */  	if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) { diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/spi-pxa2xx-pci.c index 378e504f89eb..378e504f89eb 100644 --- a/drivers/spi/pxa2xx_spi_pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/spi-pxa2xx.c index dc25bee8d33f..dc25bee8d33f 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/spi-pxa2xx.c diff --git a/drivers/spi/spi_s3c24xx_fiq.S b/drivers/spi/spi-s3c24xx-fiq.S index 3793cae361db..059f2dc1fda2 100644 --- a/drivers/spi/spi_s3c24xx_fiq.S +++ b/drivers/spi/spi-s3c24xx-fiq.S @@ -17,7 +17,7 @@  #include <mach/regs-irq.h>  #include <plat/regs-spi.h> -#include "spi_s3c24xx_fiq.h" +#include "spi-s3c24xx-fiq.h"  	.text diff --git a/drivers/spi/spi_s3c24xx_fiq.h b/drivers/spi/spi-s3c24xx-fiq.h index a5950bb25b51..a5950bb25b51 100644 --- a/drivers/spi/spi_s3c24xx_fiq.h +++ b/drivers/spi/spi-s3c24xx-fiq.h diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi-s3c24xx.c index 1a5fcabfd565..1996ac57ef91 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -1,5 +1,4 @@ -/* linux/drivers/spi/spi_s3c24xx.c - * +/*   * Copyright (c) 2006 Ben Dooks   * Copyright 2006-2009 Simtec Electronics   *	Ben Dooks <ben@simtec.co.uk> @@ -32,7 +31,7 @@  #include <plat/fiq.h>  #include <asm/fiq.h> -#include "spi_s3c24xx_fiq.h" +#include "spi-s3c24xx-fiq.h"  /**   * s3c24xx_spi_devstate - per device data diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 795828b90f45..595dacc7645f 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1,5 +1,4 @@ -/* linux/drivers/spi/spi_s3c64xx.c - * +/*   * Copyright (C) 2009 Samsung Electronics Ltd.   *	Jaswinder Singh <jassi.brar@samsung.com>   * @@ -116,9 +115,7 @@  					(((i)->fifo_lvl_mask + 1))) \  					? 1 : 0) -#define S3C64XX_SPI_ST_TX_DONE(v, i) ((((v) >> (i)->rx_lvl_offset) & \ -					(((i)->fifo_lvl_mask + 1) << 1)) \ -					? 1 : 0) +#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0)  #define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)  #define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask) diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi-sh-msiof.c index e00d94b22250..e00d94b22250 100644 --- a/drivers/spi/spi_sh_msiof.c +++ b/drivers/spi/spi-sh-msiof.c diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi-sh-sci.c index 5c6439161199..e7779c09f6ef 100644 --- a/drivers/spi/spi_sh_sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -78,7 +78,7 @@ static inline u32 getmiso(struct spi_device *dev)  #define spidelay(x) ndelay(x) -#include "spi_bitbang_txrx.h" +#include "spi-bitbang-txrx.h"  static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,  				      unsigned nsecs, u32 word, u8 bits) diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi-sh.c index 9eedd71ad898..9eedd71ad898 100644 --- a/drivers/spi/spi_sh.c +++ b/drivers/spi/spi-sh.c diff --git a/drivers/spi/spi_stmp.c b/drivers/spi/spi-stmp.c index fadff76eb7e0..fadff76eb7e0 100644 --- a/drivers/spi/spi_stmp.c +++ b/drivers/spi/spi-stmp.c diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi-tegra.c index 6c3aa6ecaade..a5a6302dc8e0 100644 --- a/drivers/spi/spi_tegra.c +++ b/drivers/spi/spi-tegra.c @@ -498,14 +498,14 @@ static int __init spi_tegra_probe(struct platform_device *pdev)  		goto err0;  	} -	if (!request_mem_region(r->start, (r->end - r->start) + 1, +	if (!request_mem_region(r->start, resource_size(r),  				dev_name(&pdev->dev))) {  		ret = -EBUSY;  		goto err0;  	}  	tspi->phys = r->start; -	tspi->base = ioremap(r->start, r->end - r->start + 1); +	tspi->base = ioremap(r->start, resource_size(r));  	if (!tspi->base) {  		dev_err(&pdev->dev, "can't ioremap iomem\n");  		ret = -ENOMEM; @@ -546,6 +546,7 @@ static int __init spi_tegra_probe(struct platform_device *pdev)  	tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];  	tspi->rx_dma_req.dev = tspi; +	master->dev.of_node = pdev->dev.of_node;  	ret = spi_register_master(master);  	if (ret < 0) @@ -563,7 +564,7 @@ err3:  err2:  	iounmap(tspi->base);  err1: -	release_mem_region(r->start, (r->end - r->start) + 1); +	release_mem_region(r->start, resource_size(r));  err0:  	spi_master_put(master);  	return ret; @@ -588,17 +589,28 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)  	iounmap(tspi->base);  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	release_mem_region(r->start, (r->end - r->start) + 1); +	release_mem_region(r->start, resource_size(r));  	return 0;  }  MODULE_ALIAS("platform:spi_tegra"); +#ifdef CONFIG_OF +static struct of_device_id spi_tegra_of_match_table[] __devinitdata = { +	{ .compatible = "nvidia,tegra20-spi", }, +	{} +}; +MODULE_DEVICE_TABLE(of, spi_tegra_of_match_table); +#else /* CONFIG_OF */ +#define spi_tegra_of_match_table NULL +#endif /* CONFIG_OF */ +  static struct platform_driver spi_tegra_driver = {  	.driver = {  		.name =		"spi_tegra",  		.owner =	THIS_MODULE, +		.of_match_table = spi_tegra_of_match_table,  	},  	.remove =	__devexit_p(spi_tegra_remove),  }; diff --git a/drivers/spi/ti-ssp-spi.c b/drivers/spi/spi-ti-ssp.c index ee22795c7973..ee22795c7973 100644 --- a/drivers/spi/ti-ssp-spi.c +++ b/drivers/spi/spi-ti-ssp.c diff --git a/drivers/spi/tle62x0.c b/drivers/spi/spi-tle62x0.c index 32a40876532f..940e73d1cf09 100644 --- a/drivers/spi/tle62x0.c +++ b/drivers/spi/spi-tle62x0.c @@ -1,5 +1,5 @@  /* - * tle62x0.c -- support Infineon TLE62x0 driver chips + * Support Infineon TLE62x0 driver chips   *   * Copyright (c) 2007 Simtec Electronics   *	Ben Dooks, <ben@simtec.co.uk> diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi-topcliff-pch.c index 79e48d451137..1d23f3831866 100644 --- a/drivers/spi/spi_topcliff_pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -26,6 +26,10 @@  #include <linux/spi/spidev.h>  #include <linux/module.h>  #include <linux/device.h> +#include <linux/platform_device.h> + +#include <linux/dmaengine.h> +#include <linux/pch_dma.h>  /* Register offsets */  #define PCH_SPCR		0x00	/* SPI control register */ @@ -35,6 +39,7 @@  #define PCH_SPDRR		0x10	/* SPI read data register */  #define PCH_SSNXCR		0x18	/* SSN Expand Control Register */  #define PCH_SRST		0x1C	/* SPI reset register */ +#define PCH_ADDRESS_SIZE	0x20  #define PCH_SPSR_TFD		0x000007C0  #define PCH_SPSR_RFD		0x0000F800 @@ -52,8 +57,6 @@  #define STATUS_EXITING		2  #define PCH_SLEEP_TIME		10 -#define PCH_ADDRESS_SIZE	0x20 -  #define SSN_LOW			0x02U  #define SSN_NO_CONTROL		0x00U  #define PCH_MAX_CS		0xFF @@ -73,22 +76,57 @@  #define SPSR_TFI_BIT		(1 << 0)  #define SPSR_RFI_BIT		(1 << 1)  #define SPSR_FI_BIT		(1 << 2) +#define SPSR_ORF_BIT		(1 << 3)  #define SPBRR_SIZE_BIT		(1 << 10) -#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT) +#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|\ +				SPCR_ORIE_BIT|SPCR_MDFIE_BIT)  #define SPCR_RFIC_FIELD		20  #define SPCR_TFIC_FIELD		16 -#define SPSR_INT_BITS		0x1F -#define MASK_SPBRR_SPBR_BITS	(~((1 << 10) - 1)) -#define MASK_RFIC_SPCR_BITS	(~(0xf << 20)) -#define MASK_TFIC_SPCR_BITS	(~(0xf000f << 12)) +#define MASK_SPBRR_SPBR_BITS	((1 << 10) - 1) +#define MASK_RFIC_SPCR_BITS	(0xf << SPCR_RFIC_FIELD) +#define MASK_TFIC_SPCR_BITS	(0xf << SPCR_TFIC_FIELD)  #define PCH_CLOCK_HZ		50000000  #define PCH_MAX_SPBR		1023 +/* Definition for ML7213 by OKI SEMICONDUCTOR */ +#define PCI_VENDOR_ID_ROHM		0x10DB +#define PCI_DEVICE_ID_ML7213_SPI	0x802c +#define PCI_DEVICE_ID_ML7223_SPI	0x800F +/* + * Set the number of SPI instance max + * Intel EG20T PCH :		1ch + * OKI SEMICONDUCTOR ML7213 IOH :	2ch + * OKI SEMICONDUCTOR ML7223 IOH :	1ch +*/ +#define PCH_SPI_MAX_DEV			2 + +#define PCH_BUF_SIZE		4096 +#define PCH_DMA_TRANS_SIZE	12 + +static int use_dma = 1; + +struct pch_spi_dma_ctrl { +	struct dma_async_tx_descriptor	*desc_tx; +	struct dma_async_tx_descriptor	*desc_rx; +	struct pch_dma_slave		param_tx; +	struct pch_dma_slave		param_rx; +	struct dma_chan		*chan_tx; +	struct dma_chan		*chan_rx; +	struct scatterlist		*sg_tx_p; +	struct scatterlist		*sg_rx_p; +	struct scatterlist		sg_tx; +	struct scatterlist		sg_rx; +	int				nent; +	void				*tx_buf_virt; +	void				*rx_buf_virt; +	dma_addr_t			tx_buf_dma; +	dma_addr_t			rx_buf_dma; +};  /**   * struct pch_spi_data - Holds the SPI channel specific details   * @io_remap_addr:		The remapped PCI base address @@ -121,9 +159,13 @@   * @cur_trans:			The current transfer that this SPI driver is   *				handling   * @board_dat:			Reference to the SPI device data structure + * @plat_dev:			platform_device structure + * @ch:				SPI channel number + * @irq_reg_sts:		Status of IRQ registration   */  struct pch_spi_data {  	void __iomem *io_remap_addr; +	unsigned long io_base_addr;  	struct spi_master *master;  	struct work_struct work;  	struct workqueue_struct *wk; @@ -144,27 +186,36 @@ struct pch_spi_data {  	struct spi_message *current_msg;  	struct spi_transfer *cur_trans;  	struct pch_spi_board_data *board_dat; +	struct platform_device	*plat_dev; +	int ch; +	struct pch_spi_dma_ctrl dma; +	int use_dma; +	u8 irq_reg_sts;  };  /**   * struct pch_spi_board_data - Holds the SPI device specific details   * @pdev:		Pointer to the PCI device - * @irq_reg_sts:	Status of IRQ registration - * @pci_req_sts:	Status of pci_request_regions   * @suspend_sts:	Status of suspend - * @data:		Pointer to SPI channel data structure + * @num:		The number of SPI device instance   */  struct pch_spi_board_data {  	struct pci_dev *pdev; -	u8 irq_reg_sts; -	u8 pci_req_sts;  	u8 suspend_sts; -	struct pch_spi_data *data; +	int num; +}; + +struct pch_pd_dev_save { +	int num; +	struct platform_device *pd_save[PCH_SPI_MAX_DEV]; +	struct pch_spi_board_data *board_dat;  };  static struct pci_device_id pch_spi_pcidev_id[] = { -	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)}, -	{0,} +	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI),    1, }, +	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, }, +	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, }, +	{ }  };  /** @@ -251,10 +302,10 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,  			reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */  			/* reset rx threshold */ -			reg_spcr_val &= MASK_RFIC_SPCR_BITS; +			reg_spcr_val &= ~MASK_RFIC_SPCR_BITS;  			reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD); -			iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))), -				 (io_remap_addr + PCH_SPCR)); + +			iowrite32(reg_spcr_val, (io_remap_addr + PCH_SPCR));  		}  		/* update counts */ @@ -265,12 +316,15 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,  	/* if transfer complete interrupt */  	if (reg_spsr_val & SPSR_FI_BIT) { -		/* disable FI & RFI interrupts */ -		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, -				   SPCR_FIE_BIT | SPCR_RFIE_BIT); +		if (tx_index < bpw_len) +			dev_err(&data->master->dev, +				"%s : Transfer is not completed", __func__); +		/* disable interrupts */ +		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);  		/* transfer is completed;inform pch_spi_process_messages */  		data->transfer_complete = true; +		data->transfer_active = false;  		wake_up(&data->wait);  	}  } @@ -283,24 +337,28 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,  static irqreturn_t pch_spi_handler(int irq, void *dev_id)  {  	u32 reg_spsr_val; -	struct pch_spi_data *data;  	void __iomem *spsr;  	void __iomem *io_remap_addr;  	irqreturn_t ret = IRQ_NONE; -	struct pch_spi_board_data *board_dat = dev_id; +	struct pch_spi_data *data = dev_id; +	struct pch_spi_board_data *board_dat = data->board_dat;  	if (board_dat->suspend_sts) {  		dev_dbg(&board_dat->pdev->dev,  			"%s returning due to suspend\n", __func__);  		return IRQ_NONE;  	} +	if (data->use_dma) +		return IRQ_NONE; -	data = board_dat->data;  	io_remap_addr = data->io_remap_addr;  	spsr = io_remap_addr + PCH_SPSR;  	reg_spsr_val = ioread32(spsr); +	if (reg_spsr_val & SPSR_ORF_BIT) +		dev_err(&board_dat->pdev->dev, "%s Over run error", __func__); +  	/* Check if the interrupt is for SPI device */  	if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {  		pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr); @@ -326,7 +384,7 @@ static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)  	if (n_spbr > PCH_MAX_SPBR)  		n_spbr = PCH_MAX_SPBR; -	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS); +	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, MASK_SPBRR_SPBR_BITS);  }  /** @@ -435,26 +493,27 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)  	dev_dbg(&pspi->dev, "%s Transfer List not empty. "  		"Transfer Speed is set.\n", __func__); +	spin_lock_irqsave(&data->lock, flags);  	/* validate Tx/Rx buffers and Transfer length */  	list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {  		if (!transfer->tx_buf && !transfer->rx_buf) {  			dev_err(&pspi->dev,  				"%s Tx and Rx buffer NULL\n", __func__);  			retval = -EINVAL; -			goto err_out; +			goto err_return_spinlock;  		}  		if (!transfer->len) {  			dev_err(&pspi->dev, "%s Transfer length invalid\n",  				__func__);  			retval = -EINVAL; -			goto err_out; +			goto err_return_spinlock;  		}  		dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"  			" valid\n", __func__); -		/* if baud rate hs been specified validate the same */ +		/* if baud rate has been specified validate the same */  		if (transfer->speed_hz > PCH_MAX_BAUDRATE)  			transfer->speed_hz = PCH_MAX_BAUDRATE; @@ -465,25 +524,24 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)  				retval = -EINVAL;  				dev_err(&pspi->dev,  					"%s Invalid bits per word\n", __func__); -				goto err_out; +				goto err_return_spinlock;  			}  		}  	} - -	spin_lock_irqsave(&data->lock, flags); +	spin_unlock_irqrestore(&data->lock, flags);  	/* We won't process any messages if we have been asked to terminate */  	if (data->status == STATUS_EXITING) {  		dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);  		retval = -ESHUTDOWN; -		goto err_return_spinlock; +		goto err_out;  	}  	/* If suspended ,return -EINVAL */  	if (data->board_dat->suspend_sts) {  		dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);  		retval = -EINVAL; -		goto err_return_spinlock; +		goto err_out;  	}  	/* set status of message */ @@ -491,9 +549,11 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)  	dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);  	pmsg->status = -EINPROGRESS; - +	spin_lock_irqsave(&data->lock, flags);  	/* add message to queue */  	list_add_tail(&pmsg->queue, &data->queue); +	spin_unlock_irqrestore(&data->lock, flags); +  	dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);  	/* schedule work queue to run */ @@ -502,11 +562,13 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)  	retval = 0; -err_return_spinlock: -	spin_unlock_irqrestore(&data->lock, flags);  err_out:  	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);  	return retval; +err_return_spinlock: +	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval); +	spin_unlock_irqrestore(&data->lock, flags); +	return retval;  }  static inline void pch_spi_select_chip(struct pch_spi_data *data, @@ -527,8 +589,7 @@ static inline void pch_spi_select_chip(struct pch_spi_data *data,  	pch_spi_setup_transfer(pspi);  } -static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw, -			   struct spi_message **ppmsg) +static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)  {  	int size;  	u32 n_writes; @@ -537,8 +598,6 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,  	const u8 *tx_buf;  	const u16 *tx_sbuf; -	pmsg = *ppmsg; -  	/* set baud rate if needed */  	if (data->cur_trans->speed_hz) {  		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__); @@ -621,10 +680,9 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,  	data->transfer_active = true;  } - -static void pch_spi_nomore_transfer(struct pch_spi_data *data, -						struct spi_message *pmsg) +static void pch_spi_nomore_transfer(struct pch_spi_data *data)  { +	struct spi_message *pmsg;  	dev_dbg(&data->master->dev, "%s called\n", __func__);  	/* Invoke complete callback  	 * [To the spi core..indicating end of transfer] */ @@ -675,29 +733,21 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data,  static void pch_spi_set_ir(struct pch_spi_data *data)  { -	/* enable interrupts */ -	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) { +	/* enable interrupts, set threshold, enable SPI */ +	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH)  		/* set receive threshold to PCH_RX_THOLD */  		pch_spi_setclr_reg(data->master, PCH_SPCR, -				   PCH_RX_THOLD << SPCR_RFIC_FIELD, -				   ~MASK_RFIC_SPCR_BITS); -		/* enable FI and RFI interrupts */ -		pch_spi_setclr_reg(data->master, PCH_SPCR, -				   SPCR_RFIE_BIT | SPCR_FIE_BIT, 0); -	} else { +				   PCH_RX_THOLD << SPCR_RFIC_FIELD | +				   SPCR_FIE_BIT | SPCR_RFIE_BIT | +				   SPCR_ORIE_BIT | SPCR_SPE_BIT, +				   MASK_RFIC_SPCR_BITS | PCH_ALL); +	else  		/* set receive threshold to maximum */  		pch_spi_setclr_reg(data->master, PCH_SPCR, -				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD, -				   ~MASK_TFIC_SPCR_BITS); -		/* enable FI interrupt */ -		pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0); -	} - -	dev_dbg(&data->master->dev, -		"%s:invoking pch_spi_set_enable to enable SPI\n", __func__); - -	/* SPI set enable */ -	pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0); +				   PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD | +				   SPCR_FIE_BIT | SPCR_ORIE_BIT | +				   SPCR_SPE_BIT, +				   MASK_RFIC_SPCR_BITS | PCH_ALL);  	/* Wait until the transfer completes; go to sleep after  				 initiating the transfer. */ @@ -710,15 +760,13 @@ static void pch_spi_set_ir(struct pch_spi_data *data)  	dev_dbg(&data->master->dev,  		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__); -	data->transfer_active = false; -	dev_dbg(&data->master->dev, -		"%s set data->transfer_active = false\n", __func__); -  	/* clear all interrupts */  	pch_spi_writereg(data->master, PCH_SPSR,  			 pch_spi_readreg(data->master, PCH_SPSR)); -	/* disable interrupts */ -	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); +	/* Disable interrupts and SPI transfer */ +	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL | SPCR_SPE_BIT); +	/* clear FIFO */ +	pch_spi_clear_fifo(data->master);  }  static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw) @@ -742,6 +790,327 @@ static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)  	}  } +static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw) +{ +	int j; +	u8 *rx_buf; +	u16 *rx_sbuf; +	const u8 *rx_dma_buf; +	const u16 *rx_dma_sbuf; + +	/* copy Rx Data */ +	if (!data->cur_trans->rx_buf) +		return; + +	if (bpw == 8) { +		rx_buf = data->cur_trans->rx_buf; +		rx_dma_buf = data->dma.rx_buf_virt; +		for (j = 0; j < data->bpw_len; j++) +			*rx_buf++ = *rx_dma_buf++ & 0xFF; +	} else { +		rx_sbuf = data->cur_trans->rx_buf; +		rx_dma_sbuf = data->dma.rx_buf_virt; +		for (j = 0; j < data->bpw_len; j++) +			*rx_sbuf++ = *rx_dma_sbuf++; +	} +} + +static void pch_spi_start_transfer(struct pch_spi_data *data) +{ +	struct pch_spi_dma_ctrl *dma; +	unsigned long flags; + +	dma = &data->dma; + +	spin_lock_irqsave(&data->lock, flags); + +	/* disable interrupts, SPI set enable */ +	pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_SPE_BIT, PCH_ALL); + +	spin_unlock_irqrestore(&data->lock, flags); + +	/* Wait until the transfer completes; go to sleep after +				 initiating the transfer. */ +	dev_dbg(&data->master->dev, +		"%s:waiting for transfer to get over\n", __func__); +	wait_event_interruptible(data->wait, data->transfer_complete); + +	dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent, +			    DMA_FROM_DEVICE); +	async_tx_ack(dma->desc_rx); +	async_tx_ack(dma->desc_tx); +	kfree(dma->sg_tx_p); +	kfree(dma->sg_rx_p); + +	spin_lock_irqsave(&data->lock, flags); +	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); +	dev_dbg(&data->master->dev, +		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__); + +	/* clear fifo threshold, disable interrupts, disable SPI transfer */ +	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, +			   MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS | PCH_ALL | +			   SPCR_SPE_BIT); +	/* clear all interrupts */ +	pch_spi_writereg(data->master, PCH_SPSR, +			 pch_spi_readreg(data->master, PCH_SPSR)); +	/* clear FIFO */ +	pch_spi_clear_fifo(data->master); + +	spin_unlock_irqrestore(&data->lock, flags); +} + +static void pch_dma_rx_complete(void *arg) +{ +	struct pch_spi_data *data = arg; + +	/* transfer is completed;inform pch_spi_process_messages_dma */ +	data->transfer_complete = true; +	wake_up_interruptible(&data->wait); +} + +static bool pch_spi_filter(struct dma_chan *chan, void *slave) +{ +	struct pch_dma_slave *param = slave; + +	if ((chan->chan_id == param->chan_id) && +	    (param->dma_dev == chan->device->dev)) { +		chan->private = param; +		return true; +	} else { +		return false; +	} +} + +static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) +{ +	dma_cap_mask_t mask; +	struct dma_chan *chan; +	struct pci_dev *dma_dev; +	struct pch_dma_slave *param; +	struct pch_spi_dma_ctrl *dma; +	unsigned int width; + +	if (bpw == 8) +		width = PCH_DMA_WIDTH_1_BYTE; +	else +		width = PCH_DMA_WIDTH_2_BYTES; + +	dma = &data->dma; +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); + +	/* Get DMA's dev information */ +	dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(12, 0)); + +	/* Set Tx DMA */ +	param = &dma->param_tx; +	param->dma_dev = &dma_dev->dev; +	param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */ +	param->tx_reg = data->io_base_addr + PCH_SPDWR; +	param->width = width; +	chan = dma_request_channel(mask, pch_spi_filter, param); +	if (!chan) { +		dev_err(&data->master->dev, +			"ERROR: dma_request_channel FAILS(Tx)\n"); +		data->use_dma = 0; +		return; +	} +	dma->chan_tx = chan; + +	/* Set Rx DMA */ +	param = &dma->param_rx; +	param->dma_dev = &dma_dev->dev; +	param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */ +	param->rx_reg = data->io_base_addr + PCH_SPDRR; +	param->width = width; +	chan = dma_request_channel(mask, pch_spi_filter, param); +	if (!chan) { +		dev_err(&data->master->dev, +			"ERROR: dma_request_channel FAILS(Rx)\n"); +		dma_release_channel(dma->chan_tx); +		dma->chan_tx = NULL; +		data->use_dma = 0; +		return; +	} +	dma->chan_rx = chan; +} + +static void pch_spi_release_dma(struct pch_spi_data *data) +{ +	struct pch_spi_dma_ctrl *dma; + +	dma = &data->dma; +	if (dma->chan_tx) { +		dma_release_channel(dma->chan_tx); +		dma->chan_tx = NULL; +	} +	if (dma->chan_rx) { +		dma_release_channel(dma->chan_rx); +		dma->chan_rx = NULL; +	} +	return; +} + +static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) +{ +	const u8 *tx_buf; +	const u16 *tx_sbuf; +	u8 *tx_dma_buf; +	u16 *tx_dma_sbuf; +	struct scatterlist *sg; +	struct dma_async_tx_descriptor *desc_tx; +	struct dma_async_tx_descriptor *desc_rx; +	int num; +	int i; +	int size; +	int rem; +	unsigned long flags; +	struct pch_spi_dma_ctrl *dma; + +	dma = &data->dma; + +	/* set baud rate if needed */ +	if (data->cur_trans->speed_hz) { +		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__); +		spin_lock_irqsave(&data->lock, flags); +		pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz); +		spin_unlock_irqrestore(&data->lock, flags); +	} + +	/* set bits per word if needed */ +	if (data->cur_trans->bits_per_word && +	    (data->current_msg->spi->bits_per_word != +	     data->cur_trans->bits_per_word)) { +		dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__); +		spin_lock_irqsave(&data->lock, flags); +		pch_spi_set_bits_per_word(data->master, +					  data->cur_trans->bits_per_word); +		spin_unlock_irqrestore(&data->lock, flags); +		*bpw = data->cur_trans->bits_per_word; +	} else { +		*bpw = data->current_msg->spi->bits_per_word; +	} +	data->bpw_len = data->cur_trans->len / (*bpw / 8); + +	/* copy Tx Data */ +	if (data->cur_trans->tx_buf != NULL) { +		if (*bpw == 8) { +			tx_buf = data->cur_trans->tx_buf; +			tx_dma_buf = dma->tx_buf_virt; +			for (i = 0; i < data->bpw_len; i++) +				*tx_dma_buf++ = *tx_buf++; +		} else { +			tx_sbuf = data->cur_trans->tx_buf; +			tx_dma_sbuf = dma->tx_buf_virt; +			for (i = 0; i < data->bpw_len; i++) +				*tx_dma_sbuf++ = *tx_sbuf++; +		} +	} +	if (data->bpw_len > PCH_DMA_TRANS_SIZE) { +		num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1; +		size = PCH_DMA_TRANS_SIZE; +		rem = data->bpw_len % PCH_DMA_TRANS_SIZE; +	} else { +		num = 1; +		size = data->bpw_len; +		rem = data->bpw_len; +	} +	dev_dbg(&data->master->dev, "%s num=%d size=%d rem=%d\n", +		__func__, num, size, rem); +	spin_lock_irqsave(&data->lock, flags); + +	/* set receive fifo threshold and transmit fifo threshold */ +	pch_spi_setclr_reg(data->master, PCH_SPCR, +			   ((size - 1) << SPCR_RFIC_FIELD) | +			   ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) << +			    SPCR_TFIC_FIELD), +			   MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS); + +	spin_unlock_irqrestore(&data->lock, flags); + +	/* RX */ +	dma->sg_rx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); +	sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */ +	/* offset, length setting */ +	sg = dma->sg_rx_p; +	for (i = 0; i < num; i++, sg++) { +		if (i == 0) { +			sg->offset = 0; +			sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem, +				    sg->offset); +			sg_dma_len(sg) = rem; +		} else { +			sg->offset = rem + size * (i - 1); +			sg->offset = sg->offset * (*bpw / 8); +			sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size, +				    sg->offset); +			sg_dma_len(sg) = size; +		} +		sg_dma_address(sg) = dma->rx_buf_dma + sg->offset; +	} +	sg = dma->sg_rx_p; +	desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg, +					num, DMA_FROM_DEVICE, +					DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +	if (!desc_rx) { +		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", +			__func__); +		return; +	} +	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE); +	desc_rx->callback = pch_dma_rx_complete; +	desc_rx->callback_param = data; +	dma->nent = num; +	dma->desc_rx = desc_rx; + +	/* TX */ +	dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); +	sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ +	/* offset, length setting */ +	sg = dma->sg_tx_p; +	for (i = 0; i < num; i++, sg++) { +		if (i == 0) { +			sg->offset = 0; +			sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem, +				    sg->offset); +			sg_dma_len(sg) = rem; +		} else { +			sg->offset = rem + size * (i - 1); +			sg->offset = sg->offset * (*bpw / 8); +			sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size, +				    sg->offset); +			sg_dma_len(sg) = size; +		} +		sg_dma_address(sg) = dma->tx_buf_dma + sg->offset; +	} +	sg = dma->sg_tx_p; +	desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx, +					sg, num, DMA_TO_DEVICE, +					DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +	if (!desc_tx) { +		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", +			__func__); +		return; +	} +	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE); +	desc_tx->callback = NULL; +	desc_tx->callback_param = data; +	dma->nent = num; +	dma->desc_tx = desc_tx; + +	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing " +		"0x2 to SSNXCR\n", __func__); + +	spin_lock_irqsave(&data->lock, flags); +	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW); +	desc_rx->tx_submit(desc_rx); +	desc_tx->tx_submit(desc_tx); +	spin_unlock_irqrestore(&data->lock, flags); + +	/* reset transfer complete flag */ +	data->transfer_complete = false; +}  static void pch_spi_process_messages(struct work_struct *pwork)  { @@ -753,13 +1122,10 @@ static void pch_spi_process_messages(struct work_struct *pwork)  	dev_dbg(&data->master->dev, "%s data initialized\n", __func__);  	spin_lock(&data->lock); -  	/* check if suspend has been initiated;if yes flush queue */  	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) { -		dev_dbg(&data->master->dev, -			"%s suspend/remove initiated,flushing queue\n", -			__func__); - +		dev_dbg(&data->master->dev, "%s suspend/remove initiated," +			"flushing queue\n", __func__);  		list_for_each_entry(pmsg, data->queue.next, queue) {  			pmsg->status = -EIO; @@ -793,53 +1159,42 @@ static void pch_spi_process_messages(struct work_struct *pwork)  	spin_unlock(&data->lock); +	if (data->use_dma) +		pch_spi_request_dma(data, +				    data->current_msg->spi->bits_per_word);  	do {  		/* If we are already processing a message get the next  		transfer structure from the message otherwise retrieve  		the 1st transfer request from the message. */  		spin_lock(&data->lock); -  		if (data->cur_trans == NULL) {  			data->cur_trans = -			    list_entry(data->current_msg->transfers. -				       next, struct spi_transfer, -				       transfer_list); -			dev_dbg(&data->master->dev, -				"%s :Getting 1st transfer message\n", __func__); +				list_entry(data->current_msg->transfers.next, +					   struct spi_transfer, transfer_list); +			dev_dbg(&data->master->dev, "%s " +				":Getting 1st transfer message\n", __func__);  		} else {  			data->cur_trans = -			    list_entry(data->cur_trans->transfer_list.next, -				       struct spi_transfer, -				       transfer_list); -			dev_dbg(&data->master->dev, -				"%s :Getting next transfer message\n", -				__func__); +				list_entry(data->cur_trans->transfer_list.next, +					   struct spi_transfer, transfer_list); +			dev_dbg(&data->master->dev, "%s " +				":Getting next transfer message\n", __func__);  		} -  		spin_unlock(&data->lock); -		pch_spi_set_tx(data, &bpw, &pmsg); - -		/* Control interrupt*/ -		pch_spi_set_ir(data); - -		/* Disable SPI transfer */ -		pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0, -				   SPCR_SPE_BIT); - -		/* clear FIFO */ -		pch_spi_clear_fifo(data->master); - -		/* copy Rx Data */ -		pch_spi_copy_rx_data(data, bpw); - -		/* free memory */ -		kfree(data->pkt_rx_buff); -		data->pkt_rx_buff = NULL; - -		kfree(data->pkt_tx_buff); -		data->pkt_tx_buff = NULL; - +		if (data->use_dma) { +			pch_spi_handle_dma(data, &bpw); +			pch_spi_start_transfer(data); +			pch_spi_copy_rx_data_for_dma(data, bpw); +		} else { +			pch_spi_set_tx(data, &bpw); +			pch_spi_set_ir(data); +			pch_spi_copy_rx_data(data, bpw); +			kfree(data->pkt_rx_buff); +			data->pkt_rx_buff = NULL; +			kfree(data->pkt_tx_buff); +			data->pkt_tx_buff = NULL; +		}  		/* increment message count */  		data->current_msg->actual_length += data->cur_trans->len; @@ -860,125 +1215,60 @@ static void pch_spi_process_messages(struct work_struct *pwork)  		/* No more transfer in this message. */  		if ((data->cur_trans->transfer_list.next) ==  		    &(data->current_msg->transfers)) { -			pch_spi_nomore_transfer(data, pmsg); +			pch_spi_nomore_transfer(data);  		}  		spin_unlock(&data->lock);  	} while (data->cur_trans != NULL); + +	if (data->use_dma) +		pch_spi_release_dma(data);  } -static void pch_spi_free_resources(struct pch_spi_board_data *board_dat) +static void pch_spi_free_resources(struct pch_spi_board_data *board_dat, +				   struct pch_spi_data *data)  {  	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);  	/* free workqueue */ -	if (board_dat->data->wk != NULL) { -		destroy_workqueue(board_dat->data->wk); -		board_dat->data->wk = NULL; +	if (data->wk != NULL) { +		destroy_workqueue(data->wk); +		data->wk = NULL;  		dev_dbg(&board_dat->pdev->dev,  			"%s destroy_workqueue invoked successfully\n",  			__func__);  	} - -	/* disable interrupts & free IRQ */ -	if (board_dat->irq_reg_sts) { -		/* disable interrupts */ -		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0, -				   PCH_ALL); - -		/* free IRQ */ -		free_irq(board_dat->pdev->irq, board_dat); - -		dev_dbg(&board_dat->pdev->dev, -			"%s free_irq invoked successfully\n", __func__); - -		board_dat->irq_reg_sts = false; -	} - -	/* unmap PCI base address */ -	if (board_dat->data->io_remap_addr != 0) { -		pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr); - -		board_dat->data->io_remap_addr = 0; - -		dev_dbg(&board_dat->pdev->dev, -			"%s pci_iounmap invoked successfully\n", __func__); -	} - -	/* release PCI region */ -	if (board_dat->pci_req_sts) { -		pci_release_regions(board_dat->pdev); -		dev_dbg(&board_dat->pdev->dev, -			"%s pci_release_regions invoked successfully\n", -			__func__); -		board_dat->pci_req_sts = false; -	}  } -static int pch_spi_get_resources(struct pch_spi_board_data *board_dat) +static int pch_spi_get_resources(struct pch_spi_board_data *board_dat, +				 struct pch_spi_data *data)  { -	void __iomem *io_remap_addr; -	int retval; +	int retval = 0; +  	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);  	/* create workqueue */ -	board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME); -	if (!board_dat->data->wk) { +	data->wk = create_singlethread_workqueue(KBUILD_MODNAME); +	if (!data->wk) {  		dev_err(&board_dat->pdev->dev,  			"%s create_singlet hread_workqueue failed\n", __func__);  		retval = -EBUSY;  		goto err_return;  	} -	dev_dbg(&board_dat->pdev->dev, -		"%s create_singlethread_workqueue success\n", __func__); - -	retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME); -	if (retval != 0) { -		dev_err(&board_dat->pdev->dev, -			"%s request_region failed\n", __func__); -		goto err_return; -	} - -	board_dat->pci_req_sts = true; - -	io_remap_addr = pci_iomap(board_dat->pdev, 1, 0); -	if (io_remap_addr == 0) { -		dev_err(&board_dat->pdev->dev, -			"%s pci_iomap failed\n", __func__); -		retval = -ENOMEM; -		goto err_return; -	} - -	/* calculate base address for all channels */ -	board_dat->data->io_remap_addr = io_remap_addr; -  	/* reset PCH SPI h/w */ -	pch_spi_reset(board_dat->data->master); +	pch_spi_reset(data->master);  	dev_dbg(&board_dat->pdev->dev,  		"%s pch_spi_reset invoked successfully\n", __func__); -	/* register IRQ */ -	retval = request_irq(board_dat->pdev->irq, pch_spi_handler, -			     IRQF_SHARED, KBUILD_MODNAME, board_dat); -	if (retval != 0) { -		dev_err(&board_dat->pdev->dev, -			"%s request_irq failed\n", __func__); -		goto err_return; -	} - -	dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n", -		__func__, retval); - -	board_dat->irq_reg_sts = true;  	dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);  err_return:  	if (retval != 0) {  		dev_err(&board_dat->pdev->dev,  			"%s FAIL:invoking pch_spi_free_resources\n", __func__); -		pch_spi_free_resources(board_dat); +		pch_spi_free_resources(board_dat, data);  	}  	dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval); @@ -986,255 +1276,387 @@ err_return:  	return retval;  } -static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static void pch_free_dma_buf(struct pch_spi_board_data *board_dat, +			     struct pch_spi_data *data)  { +	struct pch_spi_dma_ctrl *dma; + +	dma = &data->dma; +	if (dma->tx_buf_dma) +		dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, +				  dma->tx_buf_virt, dma->tx_buf_dma); +	if (dma->rx_buf_dma) +		dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, +				  dma->rx_buf_virt, dma->rx_buf_dma); +	return; +} -	struct spi_master *master; - -	struct pch_spi_board_data *board_dat; -	int retval; - -	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); - -	/* allocate memory for private data */ -	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL); -	if (board_dat == NULL) { -		dev_err(&pdev->dev, -			" %s memory allocation for private data failed\n", -			__func__); -		retval = -ENOMEM; -		goto err_kmalloc; -	} +static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, +			      struct pch_spi_data *data) +{ +	struct pch_spi_dma_ctrl *dma; + +	dma = &data->dma; +	/* Get Consistent memory for Tx DMA */ +	dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, +				PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL); +	/* Get Consistent memory for Rx DMA */ +	dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, +				PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL); +} -	dev_dbg(&pdev->dev, -		"%s memory allocation for private data success\n", __func__); +static int __devinit pch_spi_pd_probe(struct platform_device *plat_dev) +{ +	int ret; +	struct spi_master *master; +	struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev); +	struct pch_spi_data *data; -	/* enable PCI device */ -	retval = pci_enable_device(pdev); -	if (retval != 0) { -		dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__); +	dev_dbg(&plat_dev->dev, "%s:debug\n", __func__); -		goto err_pci_en_device; +	master = spi_alloc_master(&board_dat->pdev->dev, +				  sizeof(struct pch_spi_data)); +	if (!master) { +		dev_err(&plat_dev->dev, "spi_alloc_master[%d] failed.\n", +			plat_dev->id); +		return -ENOMEM;  	} -	dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n", -		__func__, retval); +	data = spi_master_get_devdata(master); +	data->master = master; -	board_dat->pdev = pdev; +	platform_set_drvdata(plat_dev, data); -	/* alllocate memory for SPI master */ -	master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data)); -	if (master == NULL) { -		retval = -ENOMEM; -		dev_err(&pdev->dev, "%s Fail.\n", __func__); -		goto err_spi_alloc_master; +	/* baseaddress + address offset) */ +	data->io_base_addr = pci_resource_start(board_dat->pdev, 1) + +					 PCH_ADDRESS_SIZE * plat_dev->id; +	data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) + +					 PCH_ADDRESS_SIZE * plat_dev->id; +	if (!data->io_remap_addr) { +		dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__); +		ret = -ENOMEM; +		goto err_pci_iomap;  	} -	dev_dbg(&pdev->dev, -		"%s spi_alloc_master returned non NULL\n", __func__); +	dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n", +		plat_dev->id, data->io_remap_addr);  	/* initialize members of SPI master */  	master->bus_num = -1;  	master->num_chipselect = PCH_MAX_CS;  	master->setup = pch_spi_setup;  	master->transfer = pch_spi_transfer; -	dev_dbg(&pdev->dev, -		"%s transfer member of SPI master initialized\n", __func__); - -	board_dat->data = spi_master_get_devdata(master); - -	board_dat->data->master = master; -	board_dat->data->n_curnt_chip = 255; -	board_dat->data->board_dat = board_dat; -	board_dat->data->status = STATUS_RUNNING; - -	INIT_LIST_HEAD(&board_dat->data->queue); -	spin_lock_init(&board_dat->data->lock); -	INIT_WORK(&board_dat->data->work, pch_spi_process_messages); -	init_waitqueue_head(&board_dat->data->wait); -	/* allocate resources for PCH SPI */ -	retval = pch_spi_get_resources(board_dat); -	if (retval) { -		dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval); +	data->board_dat = board_dat; +	data->plat_dev = plat_dev; +	data->n_curnt_chip = 255; +	data->status = STATUS_RUNNING; +	data->ch = plat_dev->id; +	data->use_dma = use_dma; + +	INIT_LIST_HEAD(&data->queue); +	spin_lock_init(&data->lock); +	INIT_WORK(&data->work, pch_spi_process_messages); +	init_waitqueue_head(&data->wait); + +	ret = pch_spi_get_resources(board_dat, data); +	if (ret) { +		dev_err(&plat_dev->dev, "%s fail(retval=%d)\n", __func__, ret);  		goto err_spi_get_resources;  	} -	dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n", -		__func__, retval); - -	/* save private data in dev */ -	pci_set_drvdata(pdev, board_dat); -	dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__); +	ret = request_irq(board_dat->pdev->irq, pch_spi_handler, +			  IRQF_SHARED, KBUILD_MODNAME, data); +	if (ret) { +		dev_err(&plat_dev->dev, +			"%s request_irq failed\n", __func__); +		goto err_request_irq; +	} +	data->irq_reg_sts = true; -	/* set master mode */  	pch_spi_set_master_mode(master); -	dev_dbg(&pdev->dev, -		"%s invoked pch_spi_set_master_mode\n", __func__); -	/* Register the controller with the SPI core. */ -	retval = spi_register_master(master); -	if (retval != 0) { -		dev_err(&pdev->dev, +	ret = spi_register_master(master); +	if (ret != 0) { +		dev_err(&plat_dev->dev,  			"%s spi_register_master FAILED\n", __func__); -		goto err_spi_reg_master; +		goto err_spi_register_master;  	} -	dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n", -		__func__, retval); - +	if (use_dma) { +		dev_info(&plat_dev->dev, "Use DMA for data transfers\n"); +		pch_alloc_dma_buf(board_dat, data); +	}  	return 0; -err_spi_reg_master: -	spi_unregister_master(master); +err_spi_register_master: +	free_irq(board_dat->pdev->irq, board_dat); +err_request_irq: +	pch_spi_free_resources(board_dat, data);  err_spi_get_resources: -err_spi_alloc_master: +	pci_iounmap(board_dat->pdev, data->io_remap_addr); +err_pci_iomap:  	spi_master_put(master); -	pci_disable_device(pdev); -err_pci_en_device: -	kfree(board_dat); -err_kmalloc: -	return retval; + +	return ret;  } -static void pch_spi_remove(struct pci_dev *pdev) +static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)  { -	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev); +	struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev); +	struct pch_spi_data *data = platform_get_drvdata(plat_dev);  	int count; +	unsigned long flags; -	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); +	dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n", +		__func__, plat_dev->id, board_dat->pdev->irq); -	if (!board_dat) { -		dev_err(&pdev->dev, -			"%s pci_get_drvdata returned NULL\n", __func__); -		return; -	} +	if (use_dma) +		pch_free_dma_buf(board_dat, data);  	/* check for any pending messages; no action is taken if the queue  	 * is still full; but at least we tried.  Unload anyway */  	count = 500; -	spin_lock(&board_dat->data->lock); -	board_dat->data->status = STATUS_EXITING; -	while ((list_empty(&board_dat->data->queue) == 0) && --count) { +	spin_lock_irqsave(&data->lock, flags); +	data->status = STATUS_EXITING; +	while ((list_empty(&data->queue) == 0) && --count) {  		dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",  			__func__); -		spin_unlock(&board_dat->data->lock); +		spin_unlock_irqrestore(&data->lock, flags);  		msleep(PCH_SLEEP_TIME); -		spin_lock(&board_dat->data->lock); +		spin_lock_irqsave(&data->lock, flags);  	} -	spin_unlock(&board_dat->data->lock); - -	/* Free resources allocated for PCH SPI */ -	pch_spi_free_resources(board_dat); - -	spi_unregister_master(board_dat->data->master); - -	/* free memory for private data */ -	kfree(board_dat); +	spin_unlock_irqrestore(&data->lock, flags); -	pci_set_drvdata(pdev, NULL); +	pch_spi_free_resources(board_dat, data); +	/* disable interrupts & free IRQ */ +	if (data->irq_reg_sts) { +		/* disable interrupts */ +		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); +		data->irq_reg_sts = false; +		free_irq(board_dat->pdev->irq, data); +	} -	/* disable PCI device */ -	pci_disable_device(pdev); +	pci_iounmap(board_dat->pdev, data->io_remap_addr); +	spi_unregister_master(data->master); +	spi_master_put(data->master); +	platform_set_drvdata(plat_dev, NULL); -	dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__); +	return 0;  } -  #ifdef CONFIG_PM -static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state) +static int pch_spi_pd_suspend(struct platform_device *pd_dev, +			      pm_message_t state)  {  	u8 count; -	int retval; - -	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev); +	struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev); +	struct pch_spi_data *data = platform_get_drvdata(pd_dev); -	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); +	dev_dbg(&pd_dev->dev, "%s ENTRY\n", __func__);  	if (!board_dat) { -		dev_err(&pdev->dev, +		dev_err(&pd_dev->dev,  			"%s pci_get_drvdata returned NULL\n", __func__);  		return -EFAULT;  	} -	retval = 0; -	board_dat->suspend_sts = true; -  	/* check if the current message is processed:  	   Only after thats done the transfer will be suspended */  	count = 255;  	while ((--count) > 0) { -		if (!(board_dat->data->bcurrent_msg_processing)) { -			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_" -				"msg_processing = false\n", __func__); +		if (!(data->bcurrent_msg_processing))  			break; -		} else { -			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_" -				"processing = true\n", __func__); -		}  		msleep(PCH_SLEEP_TIME);  	}  	/* Free IRQ */ -	if (board_dat->irq_reg_sts) { +	if (data->irq_reg_sts) {  		/* disable all interrupts */ -		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0, -				   PCH_ALL); -		pch_spi_reset(board_dat->data->master); - -		free_irq(board_dat->pdev->irq, board_dat); +		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); +		pch_spi_reset(data->master); +		free_irq(board_dat->pdev->irq, data); -		board_dat->irq_reg_sts = false; -		dev_dbg(&pdev->dev, +		data->irq_reg_sts = false; +		dev_dbg(&pd_dev->dev,  			"%s free_irq invoked successfully.\n", __func__);  	} +	return 0; +} + +static int pch_spi_pd_resume(struct platform_device *pd_dev) +{ +	struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev); +	struct pch_spi_data *data = platform_get_drvdata(pd_dev); +	int retval; + +	if (!board_dat) { +		dev_err(&pd_dev->dev, +			"%s pci_get_drvdata returned NULL\n", __func__); +		return -EFAULT; +	} + +	if (!data->irq_reg_sts) { +		/* register IRQ */ +		retval = request_irq(board_dat->pdev->irq, pch_spi_handler, +				     IRQF_SHARED, KBUILD_MODNAME, data); +		if (retval < 0) { +			dev_err(&pd_dev->dev, +				"%s request_irq failed\n", __func__); +			return retval; +		} + +		/* reset PCH SPI h/w */ +		pch_spi_reset(data->master); +		pch_spi_set_master_mode(data->master); +		data->irq_reg_sts = true; +	} +	return 0; +} +#else +#define pch_spi_pd_suspend NULL +#define pch_spi_pd_resume NULL +#endif + +static struct platform_driver pch_spi_pd_driver = { +	.driver = { +		.name = "pch-spi", +		.owner = THIS_MODULE, +	}, +	.probe = pch_spi_pd_probe, +	.remove = __devexit_p(pch_spi_pd_remove), +	.suspend = pch_spi_pd_suspend, +	.resume = pch_spi_pd_resume +}; + +static int __devinit pch_spi_probe(struct pci_dev *pdev, +				   const struct pci_device_id *id) +{ +	struct pch_spi_board_data *board_dat; +	struct platform_device *pd_dev = NULL; +	int retval; +	int i; +	struct pch_pd_dev_save *pd_dev_save; + +	pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL); +	if (!pd_dev_save) { +		dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__); +		return -ENOMEM; +	} + +	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL); +	if (!board_dat) { +		dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__); +		retval = -ENOMEM; +		goto err_no_mem; +	} + +	retval = pci_request_regions(pdev, KBUILD_MODNAME); +	if (retval) { +		dev_err(&pdev->dev, "%s request_region failed\n", __func__); +		goto pci_request_regions; +	} + +	board_dat->pdev = pdev; +	board_dat->num = id->driver_data; +	pd_dev_save->num = id->driver_data; +	pd_dev_save->board_dat = board_dat; + +	retval = pci_enable_device(pdev); +	if (retval) { +		dev_err(&pdev->dev, "%s pci_enable_device failed\n", __func__); +		goto pci_enable_device; +	} + +	for (i = 0; i < board_dat->num; i++) { +		pd_dev = platform_device_alloc("pch-spi", i); +		if (!pd_dev) { +			dev_err(&pdev->dev, "platform_device_alloc failed\n"); +			goto err_platform_device; +		} +		pd_dev_save->pd_save[i] = pd_dev; +		pd_dev->dev.parent = &pdev->dev; + +		retval = platform_device_add_data(pd_dev, board_dat, +						  sizeof(*board_dat)); +		if (retval) { +			dev_err(&pdev->dev, +				"platform_device_add_data failed\n"); +			platform_device_put(pd_dev); +			goto err_platform_device; +		} + +		retval = platform_device_add(pd_dev); +		if (retval) { +			dev_err(&pdev->dev, "platform_device_add failed\n"); +			platform_device_put(pd_dev); +			goto err_platform_device; +		} +	} + +	pci_set_drvdata(pdev, pd_dev_save); + +	return 0; + +err_platform_device: +	pci_disable_device(pdev); +pci_enable_device: +	pci_release_regions(pdev); +pci_request_regions: +	kfree(board_dat); +err_no_mem: +	kfree(pd_dev_save); + +	return retval; +} + +static void __devexit pch_spi_remove(struct pci_dev *pdev) +{ +	int i; +	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev); + +	dev_dbg(&pdev->dev, "%s ENTRY:pdev=%p\n", __func__, pdev); + +	for (i = 0; i < pd_dev_save->num; i++) +		platform_device_unregister(pd_dev_save->pd_save[i]); + +	pci_disable_device(pdev); +	pci_release_regions(pdev); +	kfree(pd_dev_save->board_dat); +	kfree(pd_dev_save); +} + +#ifdef CONFIG_PM +static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state) +{ +	int retval; +	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev); + +	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); + +	pd_dev_save->board_dat->suspend_sts = true; +  	/* save config space */  	retval = pci_save_state(pdev); -  	if (retval == 0) { -		dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n", -			__func__, retval); -		/* disable PM notifications */  		pci_enable_wake(pdev, PCI_D3hot, 0); -		dev_dbg(&pdev->dev, -			"%s pci_enable_wake invoked successfully\n", __func__); -		/* disable PCI device */  		pci_disable_device(pdev); -		dev_dbg(&pdev->dev, -			"%s pci_disable_device invoked successfully\n", -			__func__); -		/* move device to D3hot  state */  		pci_set_power_state(pdev, PCI_D3hot); -		dev_dbg(&pdev->dev, -			"%s pci_set_power_state invoked successfully\n", -			__func__);  	} else {  		dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);  	} -	dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval); -  	return retval;  }  static int pch_spi_resume(struct pci_dev *pdev)  {  	int retval; - -	struct pch_spi_board_data *board = pci_get_drvdata(pdev); +	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);  	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); -	if (!board) { -		dev_err(&pdev->dev, -			"%s pci_get_drvdata returned NULL\n", __func__); -		return -EFAULT; -	} - -	/* move device to DO power state */  	pci_set_power_state(pdev, PCI_D0); - -	/* restore state */  	pci_restore_state(pdev);  	retval = pci_enable_device(pdev); @@ -1242,34 +1664,12 @@ static int pch_spi_resume(struct pci_dev *pdev)  		dev_err(&pdev->dev,  			"%s pci_enable_device failed\n", __func__);  	} else { -		/* disable PM notifications */  		pci_enable_wake(pdev, PCI_D3hot, 0); -		/* register IRQ handler */ -		if (!board->irq_reg_sts) { -			/* register IRQ */ -			retval = request_irq(board->pdev->irq, pch_spi_handler, -					     IRQF_SHARED, KBUILD_MODNAME, -					     board); -			if (retval < 0) { -				dev_err(&pdev->dev, -					"%s request_irq failed\n", __func__); -				return retval; -			} -			board->irq_reg_sts = true; - -			/* reset PCH SPI h/w */ -			pch_spi_reset(board->data->master); -			pch_spi_set_master_mode(board->data->master); - -			/* set suspend status to false */ -			board->suspend_sts = false; - -		} +		/* set suspend status to false */ +		pd_dev_save->board_dat->suspend_sts = false;  	} -	dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval); -  	return retval;  }  #else @@ -1289,15 +1689,29 @@ static struct pci_driver pch_spi_pcidev = {  static int __init pch_spi_init(void)  { -	return pci_register_driver(&pch_spi_pcidev); +	int ret; +	ret = platform_driver_register(&pch_spi_pd_driver); +	if (ret) +		return ret; + +	ret = pci_register_driver(&pch_spi_pcidev); +	if (ret) +		return ret; + +	return 0;  }  module_init(pch_spi_init);  static void __exit pch_spi_exit(void)  {  	pci_unregister_driver(&pch_spi_pcidev); +	platform_driver_unregister(&pch_spi_pd_driver);  }  module_exit(pch_spi_exit); +module_param(use_dma, int, 0644); +MODULE_PARM_DESC(use_dma, +		 "to use DMA for data transfers pass 1 else 0; default 1"); +  MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver"); +MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7xxx IOH SPI Driver"); diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi-txx9.c index dfa024b633e1..f0a2ab0428a3 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi-txx9.c @@ -1,5 +1,5 @@  /* - * spi_txx9.c - TXx9 SPI controller driver. + * TXx9 SPI controller driver.   *   * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c   * Copyright (C) 2000-2001 Toshiba Corporation diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/spi-xilinx.c index 4d2c75df886c..4d2c75df886c 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/spi-xilinx.c diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2e13a14bba3f..4d1b9f517ce8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1,5 +1,5 @@  /* - * spi.c - SPI init/core code + * SPI init/core code   *   * Copyright (C) 2005 David Brownell   * diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c deleted file mode 100644 index be991359bf92..000000000000 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ /dev/null @@ -1,201 +0,0 @@ -/* linux/drivers/spi/spi_s3c24xx_gpio.c - * - * Copyright (c) 2006 Ben Dooks - * Copyright (c) 2006 Simtec Electronics - * - * S3C24XX GPIO based SPI driver - * - * 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. - * -*/ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/workqueue.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> - -#include <linux/spi/spi.h> -#include <linux/spi/spi_bitbang.h> - -#include <mach/regs-gpio.h> -#include <mach/spi-gpio.h> -#include <mach/hardware.h> - -struct s3c2410_spigpio { -	struct spi_bitbang		 bitbang; - -	struct s3c2410_spigpio_info	*info; -	struct platform_device		*dev; -}; - -static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi) -{ -	return spi_master_get_devdata(spi->master); -} - -static inline void setsck(struct spi_device *dev, int on) -{ -	struct s3c2410_spigpio *sg = spidev_to_sg(dev); -	s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0); -} - -static inline void setmosi(struct spi_device *dev, int on) -{ -	struct s3c2410_spigpio *sg = spidev_to_sg(dev); -	s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0); -} - -static inline u32 getmiso(struct spi_device *dev) -{ -	struct s3c2410_spigpio *sg = spidev_to_sg(dev); -	return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0; -} - -#define spidelay(x) ndelay(x) - -#include "spi_bitbang_txrx.h" - - -static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, -				      unsigned nsecs, u32 word, u8 bits) -{ -	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); -} - -static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi, -				      unsigned nsecs, u32 word, u8 bits) -{ -	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); -} - -static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi, -				      unsigned nsecs, u32 word, u8 bits) -{ -	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); -} - -static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi, -				      unsigned nsecs, u32 word, u8 bits) -{ -	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); -} - - -static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value) -{ -	struct s3c2410_spigpio *sg = spidev_to_sg(dev); - -	if (sg->info && sg->info->chip_select) -		(sg->info->chip_select)(sg->info, value); -} - -static int s3c2410_spigpio_probe(struct platform_device *dev) -{ -	struct s3c2410_spigpio_info *info; -	struct spi_master	*master; -	struct s3c2410_spigpio  *sp; -	int ret; - -	master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); -	if (master == NULL) { -		dev_err(&dev->dev, "failed to allocate spi master\n"); -		ret = -ENOMEM; -		goto err; -	} - -	sp = spi_master_get_devdata(master); - -	platform_set_drvdata(dev, sp); - -	/* copy in the plkatform data */ -	info = sp->info = dev->dev.platform_data; - -	/* setup spi bitbang adaptor */ -	sp->bitbang.master = spi_master_get(master); -	sp->bitbang.master->bus_num = info->bus_num; -	sp->bitbang.master->num_chipselect = info->num_chipselect; -	sp->bitbang.chipselect = s3c2410_spigpio_chipselect; - -	sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; -	sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1; -	sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2; -	sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3; - -	/* set state of spi pins, always assume that the clock is -	 * available, but do check the MOSI and MISO. */ -	s3c2410_gpio_setpin(info->pin_clk, 0); -	s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT); - -	if (info->pin_mosi < S3C2410_GPH10) { -		s3c2410_gpio_setpin(info->pin_mosi, 0); -		s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT); -	} - -	if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10) -		s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT); - -	ret = spi_bitbang_start(&sp->bitbang); -	if (ret) -		goto err_no_bitbang; - -	return 0; - - err_no_bitbang: -	spi_master_put(sp->bitbang.master); - err: -	return ret; - -} - -static int s3c2410_spigpio_remove(struct platform_device *dev) -{ -	struct s3c2410_spigpio *sp = platform_get_drvdata(dev); - -	spi_bitbang_stop(&sp->bitbang); -	spi_master_put(sp->bitbang.master); - -	return 0; -} - -/* all gpio should be held over suspend/resume, so we should - * not need to deal with this -*/ - -#define s3c2410_spigpio_suspend NULL -#define s3c2410_spigpio_resume NULL - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:spi_s3c24xx_gpio"); - -static struct platform_driver s3c2410_spigpio_drv = { -	.probe		= s3c2410_spigpio_probe, -        .remove		= s3c2410_spigpio_remove, -        .suspend	= s3c2410_spigpio_suspend, -        .resume		= s3c2410_spigpio_resume, -        .driver		= { -		.name	= "spi_s3c24xx_gpio", -		.owner	= THIS_MODULE, -        }, -}; - -static int __init s3c2410_spigpio_init(void) -{ -        return platform_driver_register(&s3c2410_spigpio_drv); -} - -static void __exit s3c2410_spigpio_exit(void) -{ -        platform_driver_unregister(&s3c2410_spigpio_drv); -} - -module_init(s3c2410_spigpio_init); -module_exit(s3c2410_spigpio_exit); - -MODULE_DESCRIPTION("S3C24XX SPI Driver"); -MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index d9fd86211365..830adbed1d7a 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -1,5 +1,5 @@  /* - * spidev.c -- simple synchronous userspace interface to SPI devices + * Simple synchronous userspace interface to SPI devices   *   * Copyright (C) 2006 SWAPP   *	Andrea Paterniani <a.paterniani@swapp-eng.it> | 
