summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/spi
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/spi
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/spi')
-rw-r--r--ANDROID_3.4.5/drivers/spi/Kconfig486
-rw-r--r--ANDROID_3.4.5/drivers/spi/Makefile69
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-altera.c329
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-ath79.c282
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-atmel.c1083
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-au1550.c1033
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-bcm63xx.c507
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-bfin-sport.c942
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-bfin5xx.c1493
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-bitbang-txrx.h97
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-bitbang.c506
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-butterfly.c357
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-coldfire-qspi.c632
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-davinci.c1020
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-dw-mid.c228
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-dw-mmio.c142
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-dw-pci.c182
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-dw.c933
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-dw.h242
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-ep93xx.c1207
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-fsl-espi.c753
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-fsl-lib.c236
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-fsl-lib.h123
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-fsl-spi.c1191
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-gpio.c419
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-imx.c935
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-lm70llp.c351
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-mpc512x-psc.c566
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-mpc52xx-psc.c518
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-mpc52xx.c567
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-nuc900.c491
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-oc-tiny.c415
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-omap-100k.c637
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-omap-uwire.c593
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-omap2-mcspi.c1347
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-orion.c569
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-pl022.c2328
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-ppc4xx.c601
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-pxa2xx-pci.c181
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-pxa2xx.c1816
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-rspi.c521
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.S116
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.h26
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-s3c24xx.c735
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-s3c64xx.c1258
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-sh-hspi.c331
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-sh-msiof.c739
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-sh-sci.c195
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-sh.c553
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-sirf.c687
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-stmp.c668
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-tegra.c621
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-ti-ssp.c392
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-tle62x0.c335
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-topcliff-pch.c1814
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-txx9.c473
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi-xilinx.c545
-rw-r--r--ANDROID_3.4.5/drivers/spi/spi.c1480
-rw-r--r--ANDROID_3.4.5/drivers/spi/spidev.c701
-rwxr-xr-xANDROID_3.4.5/drivers/spi/wmt_spi.c1347
-rwxr-xr-xANDROID_3.4.5/drivers/spi/wmt_spi_1.c1363
61 files changed, 0 insertions, 41307 deletions
diff --git a/ANDROID_3.4.5/drivers/spi/Kconfig b/ANDROID_3.4.5/drivers/spi/Kconfig
deleted file mode 100644
index c578f65c..00000000
--- a/ANDROID_3.4.5/drivers/spi/Kconfig
+++ /dev/null
@@ -1,486 +0,0 @@
-#
-# SPI driver configuration
-#
-# NOTE: the reason this doesn't show SPI slave support is mostly that
-# nobody's needed a slave side API yet. The master-role API is not
-# fully appropriate there, so it'd need some thought to do well.
-#
-menuconfig SPI
- bool "SPI support"
- depends on HAS_IOMEM
- help
- The "Serial Peripheral Interface" is a low level synchronous
- protocol. Chips that support SPI can have data transfer rates
- up to several tens of Mbit/sec. Chips are addressed with a
- controller and a chipselect. Most SPI slaves don't support
- dynamic device discovery; some are even write-only or read-only.
-
- SPI is widely used by microcontrollers to talk with sensors,
- eeprom and flash memory, codecs and various other controller
- chips, analog to digital (and d-to-a) converters, and more.
- MMC and SD cards can be accessed using SPI protocol; and for
- DataFlash cards used in MMC sockets, SPI must always be used.
-
- SPI is one of a family of similar protocols using a four wire
- interface (select, clock, data in, data out) including Microwire
- (half duplex), SSP, SSI, and PSP. This driver framework should
- work with most such devices and controllers.
-
-if SPI
-
-config SPI_DEBUG
- boolean "Debug support for SPI drivers"
- depends on DEBUG_KERNEL
- help
- Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
- sysfs, and debugfs support in SPI controller and protocol drivers.
-
-#
-# MASTER side ... talking to discrete SPI slave chips including microcontrollers
-#
-
-config SPI_MASTER
-# boolean "SPI Master Support"
- boolean
- default SPI
- help
- If your system has an master-capable SPI controller (which
- provides the clock and chipselect), you can enable that
- controller and the protocol drivers for the SPI slave chips
- that are connected.
-
-if SPI_MASTER
-
-comment "SPI Master Controller Drivers"
-
-config SPI_ALTERA
- tristate "Altera SPI Controller"
- select SPI_BITBANG
- help
- This is the driver for the Altera SPI Controller.
-
-config SPI_ATH79
- tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
- depends on ATH79 && GENERIC_GPIO
- select SPI_BITBANG
- help
- This enables support for the SPI controller present on the
- Atheros AR71XX/AR724X/AR913X SoCs.
-
-config SPI_ATMEL
- tristate "Atmel SPI Controller"
- depends on (ARCH_AT91 || AVR32)
- help
- This selects a driver for the Atmel SPI Controller, present on
- many AT32 (AVR32) and AT91 (ARM) chips.
-
-config SPI_BFIN5XX
- tristate "SPI controller driver for ADI Blackfin5xx"
- depends on BLACKFIN
- help
- This is the SPI controller master driver for Blackfin 5xx processor.
-
-config SPI_BFIN_SPORT
- tristate "SPI bus via Blackfin SPORT"
- depends on BLACKFIN
- help
- Enable support for a SPI bus via the Blackfin SPORT peripheral.
-
-config SPI_AU1550
- tristate "Au1550/Au1200/Au1300 SPI Controller"
- depends on MIPS_ALCHEMY && EXPERIMENTAL
- select SPI_BITBANG
- help
- If you say yes to this option, support will be included for the
- PSC SPI controller found on Au1550, Au1200 and Au1300 series.
-
-config SPI_BCM63XX
- tristate "Broadcom BCM63xx SPI controller"
- depends on BCM63XX
- help
- Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
-
-config SPI_BITBANG
- tristate "Utilities for Bitbanging SPI masters"
- help
- With a few GPIO pins, your system can bitbang the SPI protocol.
- Select this to get SPI support through I/O pins (GPIO, parallel
- port, etc). Or, some systems' SPI master controller drivers use
- this code to manage the per-word or per-transfer accesses to the
- hardware shift registers.
-
- This is library code, and is automatically selected by drivers that
- need it. You only need to select this explicitly to support driver
- modules that aren't part of this kernel tree.
-
-config SPI_BUTTERFLY
- tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
- depends on PARPORT
- select SPI_BITBANG
- help
- This uses a custom parallel port cable to connect to an AVR
- Butterfly <http://www.atmel.com/products/avr/butterfly>, an
- inexpensive battery powered microcontroller evaluation board.
- This same cable can be used to flash new firmware.
-
-config SPI_COLDFIRE_QSPI
- tristate "Freescale Coldfire QSPI controller"
- depends on (M520x || M523x || M5249 || M527x || M528x || M532x)
- help
- This enables support for the Coldfire QSPI controller in master
- mode.
-
-config SPI_DAVINCI
- tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
- depends on ARCH_DAVINCI
- select SPI_BITBANG
- help
- SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
-
-config SPI_EP93XX
- tristate "Cirrus Logic EP93xx SPI controller"
- depends on ARCH_EP93XX
- help
- This enables using the Cirrus EP93xx SPI controller in master
- mode.
-
-config SPI_GPIO
- tristate "GPIO-based bitbanging SPI Master"
- depends on GENERIC_GPIO
- select SPI_BITBANG
- help
- This simple GPIO bitbanging SPI master uses the arch-neutral GPIO
- interface to manage MOSI, MISO, SCK, and chipselect signals. SPI
- slaves connected to a bus using this driver are configured as usual,
- except that the spi_board_info.controller_data holds the GPIO number
- for the chipselect used by this controller driver.
-
- Note that this driver often won't achieve even 1 Mbit/sec speeds,
- making it unusually slow for SPI. If your platform can inline
- 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
- tristate "Freescale i.MX SPI controllers"
- depends on ARCH_MXC
- select SPI_BITBANG
- default m if IMX_HAVE_PLATFORM_SPI_IMX
- help
- This enables using the Freescale i.MX SPI controllers in master
- mode.
-
-config SPI_LM70_LLP
- tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
- depends on PARPORT && EXPERIMENTAL
- select SPI_BITBANG
- help
- This driver supports the NS LM70 LLP Evaluation Board,
- which interfaces to an LM70 temperature sensor using
- a parallel port.
-
-config SPI_MPC52xx
- tristate "Freescale MPC52xx SPI (non-PSC) controller support"
- depends on PPC_MPC52xx
- help
- This drivers supports the MPC52xx SPI controller in master SPI
- mode.
-
-config SPI_MPC52xx_PSC
- tristate "Freescale MPC52xx PSC SPI controller"
- depends on PPC_MPC52xx && EXPERIMENTAL
- help
- This enables using the Freescale MPC52xx Programmable Serial
- Controller in master SPI mode.
-
-config SPI_MPC512x_PSC
- tristate "Freescale MPC512x PSC SPI controller"
- depends on PPC_MPC512x
- help
- This enables using the Freescale MPC5121 Programmable Serial
- Controller in SPI master mode.
-
-config SPI_FSL_LIB
- tristate
- depends on FSL_SOC
-
-config SPI_FSL_SPI
- bool "Freescale SPI controller"
- depends on FSL_SOC
- select SPI_FSL_LIB
- help
- This enables using the Freescale SPI controllers in master mode.
- MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
- MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
-
-config SPI_FSL_ESPI
- bool "Freescale eSPI controller"
- depends on FSL_SOC
- select SPI_FSL_LIB
- help
- This enables using the Freescale eSPI controllers in master mode.
- From MPC8536, 85xx platform uses the controller, and all P10xx,
- P20xx, P30xx,P40xx, P50xx uses this controller.
-
-config SPI_OC_TINY
- tristate "OpenCores tiny SPI"
- depends on GENERIC_GPIO
- select SPI_BITBANG
- help
- This is the driver for OpenCores tiny SPI master controller.
-
-config SPI_OMAP_UWIRE
- tristate "OMAP1 MicroWire"
- depends on ARCH_OMAP1
- select SPI_BITBANG
- help
- This hooks up to the MicroWire controller on OMAP1 chips.
-
-config SPI_OMAP24XX
- tristate "McSPI driver for OMAP"
- depends on ARCH_OMAP2PLUS
- help
- SPI master controller for OMAP24XX and later Multichannel SPI
- (McSPI) modules.
-
-config SPI_OMAP_100K
- tristate "OMAP SPI 100K"
- depends on ARCH_OMAP850 || ARCH_OMAP730
- help
- OMAP SPI 100K master controller for omap7xx boards.
-
-config SPI_ORION
- tristate "Orion SPI master (EXPERIMENTAL)"
- depends on PLAT_ORION && EXPERIMENTAL
- help
- This enables using the SPI master controller on the Orion chips.
-
-config SPI_PL022
- tristate "ARM AMBA PL022 SSP controller"
- depends on ARM_AMBA
- default y if MACH_U300
- default y if ARCH_REALVIEW
- default y if INTEGRATOR_IMPD1
- default y if ARCH_VERSATILE
- help
- This selects the ARM(R) AMBA(R) PrimeCell PL022 SSP
- controller. If you have an embedded system with an AMBA(R)
- bus and a PL022 controller, say Y or M here.
-
-config SPI_PPC4xx
- tristate "PPC4xx SPI Controller"
- depends on PPC32 && 4xx
- select SPI_BITBANG
- help
- This selects a driver for the PPC4xx SPI Controller.
-
-config SPI_PXA2XX
- tristate "PXA2xx SSP SPI master"
- depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
- select PXA_SSP if ARCH_PXA
- help
- This enables using a PXA2xx or Sodaville SSP port as a SPI master
- controller. The driver can be configured to use any SSP port and
- additional documentation can be found a Documentation/spi/pxa2xx.
-
-config SPI_PXA2XX_PCI
- def_bool SPI_PXA2XX && X86_32 && PCI
-
-config SPI_RSPI
- tristate "Renesas RSPI controller"
- depends on SUPERH
- help
- SPI driver for Renesas RSPI blocks.
-
-config SPI_S3C24XX
- tristate "Samsung S3C24XX series SPI"
- depends on ARCH_S3C24XX && EXPERIMENTAL
- select SPI_BITBANG
- help
- SPI driver for Samsung S3C24XX series ARM SoCs
-
-config SPI_S3C24XX_FIQ
- bool "S3C24XX driver with FIQ pseudo-DMA"
- depends on SPI_S3C24XX
- select FIQ
- help
- Enable FIQ support for the S3C24XX SPI driver to provide pseudo
- DMA by using the fast-interrupt request framework, This allows
- the driver to get DMA-like performance when there are either
- no free DMA channels, or when doing transfers that required both
- TX and RX data paths.
-
-config SPI_S3C64XX
- tristate "Samsung S3C64XX series type SPI"
- depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
- select S3C64XX_DMA if ARCH_S3C64XX
- help
- SPI driver for Samsung S3C64XX and newer SoCs.
-
-config SPI_SH_MSIOF
- tristate "SuperH MSIOF SPI controller"
- depends on SUPERH && HAVE_CLK
- select SPI_BITBANG
- help
- SPI driver for SuperH MSIOF blocks.
-
-config SPI_SH
- tristate "SuperH SPI controller"
- depends on SUPERH
- help
- SPI driver for SuperH SPI blocks.
-
-config SPI_SH_SCI
- tristate "SuperH SCI SPI controller"
- depends on SUPERH
- select SPI_BITBANG
- help
- SPI driver for SuperH SCI blocks.
-
-config SPI_SH_HSPI
- tristate "SuperH HSPI controller"
- depends on ARCH_SHMOBILE
- help
- SPI driver for SuperH HSPI blocks.
-
-config SPI_SIRF
- tristate "CSR SiRFprimaII SPI controller"
- depends on ARCH_PRIMA2
- select SPI_BITBANG
- help
- SPI driver for CSR SiRFprimaII SoCs
-
-config SPI_STMP3XXX
- tristate "Freescale STMP37xx/378x SPI/SSP controller"
- depends on ARCH_STMP3XXX
- help
- SPI driver for Freescale STMP37xx/378x SoC SSP interface
-
-config SPI_TEGRA
- tristate "Nvidia Tegra SPI controller"
- depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA
- help
- SPI driver for NVidia Tegra SoCs
-
-config SPI_TI_SSP
- tristate "TI Sequencer Serial Port - SPI Support"
- depends on MFD_TI_SSP
- help
- This selects an SPI master implementation using a TI sequencer
- serial port.
-
-config SPI_TOPCLIFF_PCH
- tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI"
- 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/ML7223/ML7831, 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
- help
- SPI driver for Toshiba TXx9 MIPS SoCs
-
-config SPI_XILINX
- tristate "Xilinx SPI controller common module"
- depends on HAS_IOMEM && EXPERIMENTAL
- select SPI_BITBANG
- help
- This exposes the SPI controller IP from the Xilinx EDK.
-
- See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
- Product Specification document (DS464) for hardware details.
-
- Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
-
-# WonderMedia SPI driver
-config WMT_NEWSPI_SUPPORT
- tristate "WonderMedia SPI Bus Support"
- default y
- depends on ARCH_WMT
- help
- If you say yes here you get support for the WMT chip.
- This is proprietary driver for WMT
-
- This driver can also be built as a module. If so, the module
- will be called wmt_spi.ko
-# WonderMedia SPI driver
-config WMT_NEWSPI1_SUPPORT
- tristate "WonderMedia SPI 1 Bus Support"
- default n
- depends on ARCH_WMT
- help
- If you say yes here you get support for the WMT chip.
- This is proprietary driver for WMT
-
- This driver can also be built as a module. If so, the module
- will be called wmt_spi.ko
-
-config WMT_SPISLAVE1_SUPPORT
- tristate "WMT SPI1 SLAVE DRIVER SUPPORT"
- default n
-
-config SPI_NUC900
- tristate "Nuvoton NUC900 series SPI"
- depends on ARCH_W90X900 && EXPERIMENTAL
- select SPI_BITBANG
- help
- SPI driver for Nuvoton NUC900 series ARM SoCs
-
-#
-# Add new SPI master controllers in alphabetical order above this line
-#
-
-config SPI_DESIGNWARE
- tristate "DesignWare SPI controller core support"
- help
- general driver for SPI controller core from DesignWare
-
-config SPI_DW_PCI
- tristate "PCI interface driver for DW SPI core"
- depends on SPI_DESIGNWARE && PCI
-
-config SPI_DW_MID_DMA
- bool "DMA support for DW SPI controller on Intel Moorestown platform"
- depends on SPI_DW_PCI && INTEL_MID_DMAC
-
-config SPI_DW_MMIO
- tristate "Memory-mapped io interface driver for DW SPI core"
- depends on SPI_DESIGNWARE && HAVE_CLK
-
-#
-# There are lots of SPI device types, with sensors and memory
-# being probably the most widely used ones.
-#
-comment "SPI Protocol Masters"
-
-config SPI_SPIDEV
- tristate "User mode SPI device driver support"
- depends on EXPERIMENTAL
- help
- This supports user mode SPI protocol drivers.
-
- Note that this application programming interface is EXPERIMENTAL
- and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
-
-config SPI_TLE62X0
- tristate "Infineon TLE62X0 (for power switching)"
- depends on SYSFS
- help
- SPI driver for Infineon TLE62X0 series line driver chips,
- such as the TLE6220, TLE6230 and TLE6240. This provides a
- sysfs interface, with each line presented as a kind of GPIO
- exposing both switch control and diagnostic feedback.
-
-#
-# Add new SPI protocol masters in alphabetical order above this line
-#
-
-endif # SPI_MASTER
-
-# (slave support would go here)
-
-endif # SPI
diff --git a/ANDROID_3.4.5/drivers/spi/Makefile b/ANDROID_3.4.5/drivers/spi/Makefile
deleted file mode 100644
index 0d3ad65d..00000000
--- a/ANDROID_3.4.5/drivers/spi/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# Makefile for kernel SPI drivers.
-#
-
-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) += spi-atmel.o
-obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
-obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
-obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
-obj-$(CONFIG_SPI_BFIN5XX) += 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_RSPI) += spi-rspi.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_HSPI) += spi-sh-hspi.o
-obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
-obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
-obj-$(CONFIG_SPI_SIRF) += spi-sirf.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
-
-#WMT proprietary SPI driver
-obj-$(CONFIG_WMT_NEWSPI_SUPPORT) += wmt_spi.o
-obj-$(CONFIG_WMT_NEWSPI1_SUPPORT) += wmt_spi_1.o
-obj-$(CONFIG_WMT_SPISLAVE1_SUPPORT) += wmt_spislave.o
diff --git a/ANDROID_3.4.5/drivers/spi/spi-altera.c b/ANDROID_3.4.5/drivers/spi/spi-altera.c
deleted file mode 100644
index c00d00e9..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-altera.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Altera SPI driver
- *
- * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
- *
- * Based on spi_s3c24xx.c, which is:
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/io.h>
-#include <linux/of.h>
-
-#define DRV_NAME "spi_altera"
-
-#define ALTERA_SPI_RXDATA 0
-#define ALTERA_SPI_TXDATA 4
-#define ALTERA_SPI_STATUS 8
-#define ALTERA_SPI_CONTROL 12
-#define ALTERA_SPI_SLAVE_SEL 20
-
-#define ALTERA_SPI_STATUS_ROE_MSK 0x8
-#define ALTERA_SPI_STATUS_TOE_MSK 0x10
-#define ALTERA_SPI_STATUS_TMT_MSK 0x20
-#define ALTERA_SPI_STATUS_TRDY_MSK 0x40
-#define ALTERA_SPI_STATUS_RRDY_MSK 0x80
-#define ALTERA_SPI_STATUS_E_MSK 0x100
-
-#define ALTERA_SPI_CONTROL_IROE_MSK 0x8
-#define ALTERA_SPI_CONTROL_ITOE_MSK 0x10
-#define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40
-#define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80
-#define ALTERA_SPI_CONTROL_IE_MSK 0x100
-#define ALTERA_SPI_CONTROL_SSO_MSK 0x400
-
-struct altera_spi {
- /* bitbang has to be first */
- struct spi_bitbang bitbang;
- struct completion done;
-
- void __iomem *base;
- int irq;
- int len;
- int count;
- int bytes_per_word;
- unsigned long imr;
-
- /* data buffers */
- const unsigned char *tx;
- unsigned char *rx;
-};
-
-static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
-{
- return spi_master_get_devdata(sdev->master);
-}
-
-static void altera_spi_chipsel(struct spi_device *spi, int value)
-{
- struct altera_spi *hw = altera_spi_to_hw(spi);
-
- if (spi->mode & SPI_CS_HIGH) {
- switch (value) {
- case BITBANG_CS_INACTIVE:
- writel(1 << spi->chip_select,
- hw->base + ALTERA_SPI_SLAVE_SEL);
- hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- break;
-
- case BITBANG_CS_ACTIVE:
- hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
- break;
- }
- } else {
- switch (value) {
- case BITBANG_CS_INACTIVE:
- hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- break;
-
- case BITBANG_CS_ACTIVE:
- writel(1 << spi->chip_select,
- hw->base + ALTERA_SPI_SLAVE_SEL);
- hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- break;
- }
- }
-}
-
-static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
- return 0;
-}
-
-static int altera_spi_setup(struct spi_device *spi)
-{
- return 0;
-}
-
-static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
-{
- if (hw->tx) {
- switch (hw->bytes_per_word) {
- case 1:
- return hw->tx[count];
- case 2:
- return (hw->tx[count * 2]
- | (hw->tx[count * 2 + 1] << 8));
- }
- }
- return 0;
-}
-
-static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct altera_spi *hw = altera_spi_to_hw(spi);
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->count = 0;
- hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8;
- hw->len = t->len / hw->bytes_per_word;
-
- if (hw->irq >= 0) {
- /* enable receive interrupt */
- hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-
- /* send the first byte */
- writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
-
- wait_for_completion(&hw->done);
- /* disable receive interrupt */
- hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- } else {
- /* send the first byte */
- writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
-
- while (1) {
- unsigned int rxd;
-
- while (!(readl(hw->base + ALTERA_SPI_STATUS) &
- ALTERA_SPI_STATUS_RRDY_MSK))
- cpu_relax();
-
- rxd = readl(hw->base + ALTERA_SPI_RXDATA);
- if (hw->rx) {
- switch (hw->bytes_per_word) {
- case 1:
- hw->rx[hw->count] = rxd;
- break;
- case 2:
- hw->rx[hw->count * 2] = rxd;
- hw->rx[hw->count * 2 + 1] = rxd >> 8;
- break;
- }
- }
-
- hw->count++;
-
- if (hw->count < hw->len)
- writel(hw_txbyte(hw, hw->count),
- hw->base + ALTERA_SPI_TXDATA);
- else
- break;
- }
-
- }
-
- return hw->count * hw->bytes_per_word;
-}
-
-static irqreturn_t altera_spi_irq(int irq, void *dev)
-{
- struct altera_spi *hw = dev;
- unsigned int rxd;
-
- rxd = readl(hw->base + ALTERA_SPI_RXDATA);
- if (hw->rx) {
- switch (hw->bytes_per_word) {
- case 1:
- hw->rx[hw->count] = rxd;
- break;
- case 2:
- hw->rx[hw->count * 2] = rxd;
- hw->rx[hw->count * 2 + 1] = rxd >> 8;
- break;
- }
- }
-
- hw->count++;
-
- if (hw->count < hw->len)
- writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
- else
- complete(&hw->done);
-
- return IRQ_HANDLED;
-}
-
-static int __devinit altera_spi_probe(struct platform_device *pdev)
-{
- struct altera_spi_platform_data *platp = pdev->dev.platform_data;
- struct altera_spi *hw;
- struct spi_master *master;
- struct resource *res;
- int err = -ENODEV;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
- if (!master)
- return err;
-
- /* setup the master state. */
- master->bus_num = pdev->id;
- master->num_chipselect = 16;
- master->mode_bits = SPI_CS_HIGH;
- master->setup = altera_spi_setup;
-
- hw = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, hw);
-
- /* setup the state for the bitbang driver */
- hw->bitbang.master = spi_master_get(master);
- if (!hw->bitbang.master)
- return err;
- hw->bitbang.setup_transfer = altera_spi_setupxfer;
- hw->bitbang.chipselect = altera_spi_chipsel;
- hw->bitbang.txrx_bufs = altera_spi_txrx;
-
- /* find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- goto exit_busy;
- if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
- pdev->name))
- goto exit_busy;
- hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
- resource_size(res));
- if (!hw->base)
- goto exit_busy;
- /* program defaults into the registers */
- hw->imr = 0; /* disable spi interrupts */
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
- writel(0, hw->base + ALTERA_SPI_STATUS); /* clear status reg */
- if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)
- readl(hw->base + ALTERA_SPI_RXDATA); /* flush rxdata */
- /* irq is optional */
- hw->irq = platform_get_irq(pdev, 0);
- if (hw->irq >= 0) {
- init_completion(&hw->done);
- err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
- pdev->name, hw);
- if (err)
- goto exit;
- }
- /* find platform data */
- if (!platp)
- hw->bitbang.master->dev.of_node = pdev->dev.of_node;
-
- /* register our spi controller */
- err = spi_bitbang_start(&hw->bitbang);
- if (err)
- goto exit;
- dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
-
- return 0;
-
-exit_busy:
- err = -EBUSY;
-exit:
- platform_set_drvdata(pdev, NULL);
- spi_master_put(master);
- return err;
-}
-
-static int __devexit altera_spi_remove(struct platform_device *dev)
-{
- struct altera_spi *hw = platform_get_drvdata(dev);
- struct spi_master *master = hw->bitbang.master;
-
- spi_bitbang_stop(&hw->bitbang);
- platform_set_drvdata(dev, NULL);
- spi_master_put(master);
- return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id altera_spi_match[] = {
- { .compatible = "ALTR,spi-1.0", },
- {},
-};
-MODULE_DEVICE_TABLE(of, altera_spi_match);
-#else /* CONFIG_OF */
-#define altera_spi_match NULL
-#endif /* CONFIG_OF */
-
-static struct platform_driver altera_spi_driver = {
- .probe = altera_spi_probe,
- .remove = __devexit_p(altera_spi_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- .pm = NULL,
- .of_match_table = altera_spi_match,
- },
-};
-module_platform_driver(altera_spi_driver);
-
-MODULE_DESCRIPTION("Altera SPI driver");
-MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-ath79.c b/ANDROID_3.4.5/drivers/spi/spi-ath79.c
deleted file mode 100644
index acc88b4d..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-ath79.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
- *
- * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
- *
- * This driver has been based on the spi-gpio.c:
- * Copyright (C) 2006,2008 David Brownell
- *
- * 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/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/bitops.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ath79_spi_platform.h>
-
-#define DRV_NAME "ath79-spi"
-
-struct ath79_spi {
- struct spi_bitbang bitbang;
- u32 ioc_base;
- u32 reg_ctrl;
- void __iomem *base;
-};
-
-static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
-{
- return ioread32(sp->base + reg);
-}
-
-static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
-{
- iowrite32(val, sp->base + reg);
-}
-
-static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
-{
- return spi_master_get_devdata(spi->master);
-}
-
-static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
-{
- struct ath79_spi *sp = ath79_spidev_to_sp(spi);
- int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
-
- if (is_active) {
- /* set initial clock polarity */
- if (spi->mode & SPI_CPOL)
- sp->ioc_base |= AR71XX_SPI_IOC_CLK;
- else
- sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
-
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
- }
-
- if (spi->chip_select) {
- struct ath79_spi_controller_data *cdata = spi->controller_data;
-
- /* SPI is normally active-low */
- gpio_set_value(cdata->gpio, cs_high);
- } else {
- if (cs_high)
- sp->ioc_base |= AR71XX_SPI_IOC_CS0;
- else
- sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
-
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
- }
-
-}
-
-static int ath79_spi_setup_cs(struct spi_device *spi)
-{
- struct ath79_spi *sp = ath79_spidev_to_sp(spi);
- struct ath79_spi_controller_data *cdata;
-
- cdata = spi->controller_data;
- if (spi->chip_select && !cdata)
- return -EINVAL;
-
- /* enable GPIO mode */
- ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
-
- /* save CTRL register */
- sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
- sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
-
- /* TODO: setup speed? */
- ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
-
- if (spi->chip_select) {
- int status = 0;
-
- status = gpio_request(cdata->gpio, dev_name(&spi->dev));
- if (status)
- return status;
-
- status = gpio_direction_output(cdata->gpio,
- spi->mode & SPI_CS_HIGH);
- if (status) {
- gpio_free(cdata->gpio);
- return status;
- }
- } else {
- if (spi->mode & SPI_CS_HIGH)
- sp->ioc_base |= AR71XX_SPI_IOC_CS0;
- else
- sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
- }
-
- return 0;
-}
-
-static void ath79_spi_cleanup_cs(struct spi_device *spi)
-{
- struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-
- if (spi->chip_select) {
- struct ath79_spi_controller_data *cdata = spi->controller_data;
- gpio_free(cdata->gpio);
- }
-
- /* restore CTRL register */
- ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
- /* disable GPIO mode */
- ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
-}
-
-static int ath79_spi_setup(struct spi_device *spi)
-{
- int status = 0;
-
- if (spi->bits_per_word > 32)
- return -EINVAL;
-
- if (!spi->controller_state) {
- status = ath79_spi_setup_cs(spi);
- if (status)
- return status;
- }
-
- status = spi_bitbang_setup(spi);
- if (status && !spi->controller_state)
- ath79_spi_cleanup_cs(spi);
-
- return status;
-}
-
-static void ath79_spi_cleanup(struct spi_device *spi)
-{
- ath79_spi_cleanup_cs(spi);
- spi_bitbang_cleanup(spi);
-}
-
-static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
- u32 word, u8 bits)
-{
- struct ath79_spi *sp = ath79_spidev_to_sp(spi);
- u32 ioc = sp->ioc_base;
-
- /* clock starts at inactive polarity */
- for (word <<= (32 - bits); likely(bits); bits--) {
- u32 out;
-
- if (word & (1 << 31))
- out = ioc | AR71XX_SPI_IOC_DO;
- else
- out = ioc & ~AR71XX_SPI_IOC_DO;
-
- /* setup MSB (to slave) on trailing edge */
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
- ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
-
- word <<= 1;
- }
-
- return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
-}
-
-static __devinit int ath79_spi_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct ath79_spi *sp;
- struct ath79_spi_platform_data *pdata;
- struct resource *r;
- int ret;
-
- master = spi_alloc_master(&pdev->dev, sizeof(*sp));
- if (master == NULL) {
- dev_err(&pdev->dev, "failed to allocate spi master\n");
- return -ENOMEM;
- }
-
- sp = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, sp);
-
- pdata = pdev->dev.platform_data;
-
- master->setup = ath79_spi_setup;
- master->cleanup = ath79_spi_cleanup;
- if (pdata) {
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->num_chipselect;
- } else {
- master->bus_num = -1;
- master->num_chipselect = 1;
- }
-
- sp->bitbang.master = spi_master_get(master);
- sp->bitbang.chipselect = ath79_spi_chipselect;
- sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
- sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
- sp->bitbang.flags = SPI_CS_HIGH;
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENOENT;
- goto err_put_master;
- }
-
- sp->base = ioremap(r->start, resource_size(r));
- if (!sp->base) {
- ret = -ENXIO;
- goto err_put_master;
- }
-
- ret = spi_bitbang_start(&sp->bitbang);
- if (ret)
- goto err_unmap;
-
- return 0;
-
-err_unmap:
- iounmap(sp->base);
-err_put_master:
- platform_set_drvdata(pdev, NULL);
- spi_master_put(sp->bitbang.master);
-
- return ret;
-}
-
-static __devexit int ath79_spi_remove(struct platform_device *pdev)
-{
- struct ath79_spi *sp = platform_get_drvdata(pdev);
-
- spi_bitbang_stop(&sp->bitbang);
- iounmap(sp->base);
- platform_set_drvdata(pdev, NULL);
- spi_master_put(sp->bitbang.master);
-
- return 0;
-}
-
-static struct platform_driver ath79_spi_driver = {
- .probe = ath79_spi_probe,
- .remove = __devexit_p(ath79_spi_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(ath79_spi_driver);
-
-MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X");
-MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-atmel.c b/ANDROID_3.4.5/drivers/spi/spi-atmel.c
deleted file mode 100644
index 16d6a839..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-atmel.c
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
- * Driver for Atmel AT32 and AT91 SPI Controllers
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <mach/board.h>
-#include <asm/gpio.h>
-#include <mach/cpu.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
- * DMA transfers; transfer queue progress is driven by IRQs. The clock
- * framework provides the base clock, subdivided for each spi_device.
- */
-struct atmel_spi {
- spinlock_t lock;
-
- void __iomem *regs;
- int irq;
- struct clk *clk;
- struct platform_device *pdev;
- struct spi_device *stay;
-
- u8 stopping;
- struct list_head queue;
- struct spi_transfer *current_transfer;
- unsigned long current_remaining_bytes;
- struct spi_transfer *next_transfer;
- unsigned long next_remaining_bytes;
-
- void *buffer;
- dma_addr_t buffer_dma;
-};
-
-/* Controller-specific per-slave state */
-struct atmel_spi_device {
- unsigned int npcs_pin;
- u32 csr;
-};
-
-#define BUFFER_SIZE PAGE_SIZE
-#define INVALID_DMA_ADDRESS 0xffffffff
-
-/*
- * Version 2 of the SPI controller has
- * - CR.LASTXFER
- * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
- * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
- * - SPI_CSRx.CSAAT
- * - SPI_CSRx.SBCR allows faster clocking
- *
- * We can determine the controller version by reading the VERSION
- * register, but I haven't checked that it exists on all chips, and
- * this is cheaper anyway.
- */
-static bool atmel_spi_is_v2(void)
-{
- return !cpu_is_at91rm9200();
-}
-
-/*
- * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
- * they assume that spi slave device state will not change on deselect, so
- * that automagic deselection is OK. ("NPCSx rises if no data is to be
- * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer
- * controllers have CSAAT and friends.
- *
- * Since the CSAAT functionality is a bit weird on newer controllers as
- * well, we use GPIO to control nCSx pins on all controllers, updating
- * MR.PCS to avoid confusing the controller. Using GPIOs also lets us
- * support active-high chipselects despite the controller's belief that
- * only active-low devices/systems exists.
- *
- * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
- * right when driven with GPIO. ("Mode Fault does not allow more than one
- * Master on Chip Select 0.") No workaround exists for that ... so for
- * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
- * and (c) will trigger that first erratum in some cases.
- *
- * TODO: Test if the atmel_spi_is_v2() branch below works on
- * AT91RM9200 if we use some other register than CSR0. However, don't
- * do this unconditionally since AP7000 has an errata where the BITS
- * field in CSR0 overrides all other CSRs.
- */
-
-static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
-{
- struct atmel_spi_device *asd = spi->controller_state;
- unsigned active = spi->mode & SPI_CS_HIGH;
- u32 mr;
-
- if (atmel_spi_is_v2()) {
- /*
- * Always use CSR0. This ensures that the clock
- * switches to the correct idle polarity before we
- * toggle the CS.
- */
- spi_writel(as, CSR0, asd->csr);
- spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
- | SPI_BIT(MSTR));
- mr = spi_readl(as, MR);
- gpio_set_value(asd->npcs_pin, active);
- } else {
- u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
- int i;
- u32 csr;
-
- /* Make sure clock polarity is correct */
- for (i = 0; i < spi->master->num_chipselect; i++) {
- csr = spi_readl(as, CSR0 + 4 * i);
- if ((csr ^ cpol) & SPI_BIT(CPOL))
- spi_writel(as, CSR0 + 4 * i,
- csr ^ SPI_BIT(CPOL));
- }
-
- mr = spi_readl(as, MR);
- mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
- if (spi->chip_select != 0)
- gpio_set_value(asd->npcs_pin, active);
- spi_writel(as, MR, mr);
- }
-
- dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
- asd->npcs_pin, active ? " (high)" : "",
- mr);
-}
-
-static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
-{
- struct atmel_spi_device *asd = spi->controller_state;
- unsigned active = spi->mode & SPI_CS_HIGH;
- u32 mr;
-
- /* only deactivate *this* device; sometimes transfers to
- * another device may be active when this routine is called.
- */
- mr = spi_readl(as, MR);
- if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
- mr = SPI_BFINS(PCS, 0xf, mr);
- spi_writel(as, MR, mr);
- }
-
- dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
- asd->npcs_pin, active ? " (low)" : "",
- mr);
-
- if (atmel_spi_is_v2() || spi->chip_select != 0)
- gpio_set_value(asd->npcs_pin, !active);
-}
-
-static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
- struct spi_transfer *xfer)
-{
- return msg->transfers.prev == &xfer->transfer_list;
-}
-
-static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
-{
- return xfer->delay_usecs == 0 && !xfer->cs_change;
-}
-
-static void atmel_spi_next_xfer_data(struct spi_master *master,
- struct spi_transfer *xfer,
- dma_addr_t *tx_dma,
- dma_addr_t *rx_dma,
- u32 *plen)
-{
- struct atmel_spi *as = spi_master_get_devdata(master);
- u32 len = *plen;
-
- /* use scratch buffer only when rx or tx data is unspecified */
- if (xfer->rx_buf)
- *rx_dma = xfer->rx_dma + xfer->len - *plen;
- else {
- *rx_dma = as->buffer_dma;
- if (len > BUFFER_SIZE)
- len = BUFFER_SIZE;
- }
- if (xfer->tx_buf)
- *tx_dma = xfer->tx_dma + xfer->len - *plen;
- else {
- *tx_dma = as->buffer_dma;
- if (len > BUFFER_SIZE)
- len = BUFFER_SIZE;
- memset(as->buffer, 0, len);
- dma_sync_single_for_device(&as->pdev->dev,
- as->buffer_dma, len, DMA_TO_DEVICE);
- }
-
- *plen = len;
-}
-
-/*
- * Submit next transfer for DMA.
- * lock is held, spi irq is blocked
- */
-static void atmel_spi_next_xfer(struct spi_master *master,
- struct spi_message *msg)
-{
- struct atmel_spi *as = spi_master_get_devdata(master);
- struct spi_transfer *xfer;
- u32 len, remaining;
- u32 ieval;
- dma_addr_t tx_dma, rx_dma;
-
- if (!as->current_transfer)
- xfer = list_entry(msg->transfers.next,
- struct spi_transfer, transfer_list);
- else if (!as->next_transfer)
- xfer = list_entry(as->current_transfer->transfer_list.next,
- struct spi_transfer, transfer_list);
- else
- xfer = NULL;
-
- if (xfer) {
- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-
- len = xfer->len;
- atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
- remaining = xfer->len - len;
-
- spi_writel(as, RPR, rx_dma);
- spi_writel(as, TPR, tx_dma);
-
- if (msg->spi->bits_per_word > 8)
- len >>= 1;
- spi_writel(as, RCR, len);
- spi_writel(as, TCR, len);
-
- dev_dbg(&msg->spi->dev,
- " start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
- xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
- xfer->rx_buf, xfer->rx_dma);
- } else {
- xfer = as->next_transfer;
- remaining = as->next_remaining_bytes;
- }
-
- as->current_transfer = xfer;
- as->current_remaining_bytes = remaining;
-
- if (remaining > 0)
- len = remaining;
- else if (!atmel_spi_xfer_is_last(msg, xfer)
- && atmel_spi_xfer_can_be_chained(xfer)) {
- xfer = list_entry(xfer->transfer_list.next,
- struct spi_transfer, transfer_list);
- len = xfer->len;
- } else
- xfer = NULL;
-
- as->next_transfer = xfer;
-
- if (xfer) {
- u32 total;
-
- total = len;
- atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
- as->next_remaining_bytes = total - len;
-
- spi_writel(as, RNPR, rx_dma);
- spi_writel(as, TNPR, tx_dma);
-
- if (msg->spi->bits_per_word > 8)
- len >>= 1;
- spi_writel(as, RNCR, len);
- spi_writel(as, TNCR, len);
-
- dev_dbg(&msg->spi->dev,
- " next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
- xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
- xfer->rx_buf, xfer->rx_dma);
- ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
- } else {
- spi_writel(as, RNCR, 0);
- spi_writel(as, TNCR, 0);
- ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES);
- }
-
- /* REVISIT: We're waiting for ENDRX before we start the next
- * transfer because we need to handle some difficult timing
- * issues otherwise. If we wait for ENDTX in one transfer and
- * then starts waiting for ENDRX in the next, it's difficult
- * to tell the difference between the ENDRX interrupt we're
- * actually waiting for and the ENDRX interrupt of the
- * previous transfer.
- *
- * It should be doable, though. Just not now...
- */
- spi_writel(as, IER, ieval);
- spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
-}
-
-static void atmel_spi_next_message(struct spi_master *master)
-{
- struct atmel_spi *as = spi_master_get_devdata(master);
- struct spi_message *msg;
- struct spi_device *spi;
-
- BUG_ON(as->current_transfer);
-
- msg = list_entry(as->queue.next, struct spi_message, queue);
- spi = msg->spi;
-
- dev_dbg(master->dev.parent, "start message %p for %s\n",
- msg, dev_name(&spi->dev));
-
- /* select chip if it's not still active */
- if (as->stay) {
- if (as->stay != spi) {
- cs_deactivate(as, as->stay);
- cs_activate(as, spi);
- }
- as->stay = NULL;
- } else
- cs_activate(as, spi);
-
- atmel_spi_next_xfer(master, msg);
-}
-
-/*
- * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
- * - The buffer is either valid for CPU access, else NULL
- * - If the buffer is valid, so is its DMA address
- *
- * This driver manages the dma address unless message->is_dma_mapped.
- */
-static int
-atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
-{
- struct device *dev = &as->pdev->dev;
-
- xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
- if (xfer->tx_buf) {
- /* tx_buf is a const void* where we need a void * for the dma
- * mapping */
- void *nonconst_tx = (void *)xfer->tx_buf;
-
- xfer->tx_dma = dma_map_single(dev,
- nonconst_tx, xfer->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, xfer->tx_dma))
- return -ENOMEM;
- }
- if (xfer->rx_buf) {
- xfer->rx_dma = dma_map_single(dev,
- xfer->rx_buf, xfer->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, xfer->rx_dma)) {
- if (xfer->tx_buf)
- dma_unmap_single(dev,
- xfer->tx_dma, xfer->len,
- DMA_TO_DEVICE);
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
- struct spi_transfer *xfer)
-{
- if (xfer->tx_dma != INVALID_DMA_ADDRESS)
- dma_unmap_single(master->dev.parent, xfer->tx_dma,
- xfer->len, DMA_TO_DEVICE);
- if (xfer->rx_dma != INVALID_DMA_ADDRESS)
- dma_unmap_single(master->dev.parent, xfer->rx_dma,
- xfer->len, DMA_FROM_DEVICE);
-}
-
-static void
-atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
- struct spi_message *msg, int status, int stay)
-{
- if (!stay || status < 0)
- cs_deactivate(as, msg->spi);
- else
- as->stay = msg->spi;
-
- list_del(&msg->queue);
- msg->status = status;
-
- dev_dbg(master->dev.parent,
- "xfer complete: %u bytes transferred\n",
- msg->actual_length);
-
- spin_unlock(&as->lock);
- msg->complete(msg->context);
- spin_lock(&as->lock);
-
- as->current_transfer = NULL;
- as->next_transfer = NULL;
-
- /* continue if needed */
- if (list_empty(&as->queue) || as->stopping)
- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
- else
- atmel_spi_next_message(master);
-}
-
-static irqreturn_t
-atmel_spi_interrupt(int irq, void *dev_id)
-{
- struct spi_master *master = dev_id;
- struct atmel_spi *as = spi_master_get_devdata(master);
- struct spi_message *msg;
- struct spi_transfer *xfer;
- u32 status, pending, imr;
- int ret = IRQ_NONE;
-
- spin_lock(&as->lock);
-
- xfer = as->current_transfer;
- msg = list_entry(as->queue.next, struct spi_message, queue);
-
- imr = spi_readl(as, IMR);
- status = spi_readl(as, SR);
- pending = status & imr;
-
- if (pending & SPI_BIT(OVRES)) {
- int timeout;
-
- ret = IRQ_HANDLED;
-
- spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX)
- | SPI_BIT(OVRES)));
-
- /*
- * When we get an overrun, we disregard the current
- * transfer. Data will not be copied back from any
- * bounce buffer and msg->actual_len will not be
- * updated with the last xfer.
- *
- * We will also not process any remaning transfers in
- * the message.
- *
- * First, stop the transfer and unmap the DMA buffers.
- */
- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
- if (!msg->is_dma_mapped)
- atmel_spi_dma_unmap_xfer(master, xfer);
-
- /* REVISIT: udelay in irq is unfriendly */
- if (xfer->delay_usecs)
- udelay(xfer->delay_usecs);
-
- dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n",
- spi_readl(as, TCR), spi_readl(as, RCR));
-
- /*
- * Clean up DMA registers and make sure the data
- * registers are empty.
- */
- spi_writel(as, RNCR, 0);
- spi_writel(as, TNCR, 0);
- spi_writel(as, RCR, 0);
- spi_writel(as, TCR, 0);
- for (timeout = 1000; timeout; timeout--)
- if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
- break;
- if (!timeout)
- dev_warn(master->dev.parent,
- "timeout waiting for TXEMPTY");
- while (spi_readl(as, SR) & SPI_BIT(RDRF))
- spi_readl(as, RDR);
-
- /* Clear any overrun happening while cleaning up */
- spi_readl(as, SR);
-
- atmel_spi_msg_done(master, as, msg, -EIO, 0);
- } else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
- ret = IRQ_HANDLED;
-
- spi_writel(as, IDR, pending);
-
- if (as->current_remaining_bytes == 0) {
- msg->actual_length += xfer->len;
-
- if (!msg->is_dma_mapped)
- atmel_spi_dma_unmap_xfer(master, xfer);
-
- /* REVISIT: udelay in irq is unfriendly */
- if (xfer->delay_usecs)
- udelay(xfer->delay_usecs);
-
- if (atmel_spi_xfer_is_last(msg, xfer)) {
- /* report completed message */
- atmel_spi_msg_done(master, as, msg, 0,
- xfer->cs_change);
- } else {
- if (xfer->cs_change) {
- cs_deactivate(as, msg->spi);
- udelay(1);
- cs_activate(as, msg->spi);
- }
-
- /*
- * Not done yet. Submit the next transfer.
- *
- * FIXME handle protocol options for xfer
- */
- atmel_spi_next_xfer(master, msg);
- }
- } else {
- /*
- * Keep going, we still have data to send in
- * the current transfer.
- */
- atmel_spi_next_xfer(master, msg);
- }
- }
-
- spin_unlock(&as->lock);
-
- return ret;
-}
-
-static int atmel_spi_setup(struct spi_device *spi)
-{
- struct atmel_spi *as;
- struct atmel_spi_device *asd;
- u32 scbr, csr;
- unsigned int bits = spi->bits_per_word;
- unsigned long bus_hz;
- unsigned int npcs_pin;
- int ret;
-
- as = spi_master_get_devdata(spi->master);
-
- if (as->stopping)
- return -ESHUTDOWN;
-
- if (spi->chip_select > spi->master->num_chipselect) {
- dev_dbg(&spi->dev,
- "setup: invalid chipselect %u (%u defined)\n",
- spi->chip_select, spi->master->num_chipselect);
- return -EINVAL;
- }
-
- if (bits < 8 || bits > 16) {
- dev_dbg(&spi->dev,
- "setup: invalid bits_per_word %u (8 to 16)\n",
- bits);
- return -EINVAL;
- }
-
- /* see notes above re chipselect */
- if (!atmel_spi_is_v2()
- && spi->chip_select == 0
- && (spi->mode & SPI_CS_HIGH)) {
- dev_dbg(&spi->dev, "setup: can't be active-high\n");
- return -EINVAL;
- }
-
- /* v1 chips start out at half the peripheral bus speed. */
- bus_hz = clk_get_rate(as->clk);
- if (!atmel_spi_is_v2())
- bus_hz /= 2;
-
- if (spi->max_speed_hz) {
- /*
- * Calculate the lowest divider that satisfies the
- * constraint, assuming div32/fdiv/mbz == 0.
- */
- scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
-
- /*
- * If the resulting divider doesn't fit into the
- * register bitfield, we can't satisfy the constraint.
- */
- if (scbr >= (1 << SPI_SCBR_SIZE)) {
- dev_dbg(&spi->dev,
- "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
- spi->max_speed_hz, scbr, bus_hz/255);
- return -EINVAL;
- }
- } else
- /* speed zero means "as slow as possible" */
- scbr = 0xff;
-
- csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
- if (spi->mode & SPI_CPOL)
- csr |= SPI_BIT(CPOL);
- if (!(spi->mode & SPI_CPHA))
- csr |= SPI_BIT(NCPHA);
-
- /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
- *
- * DLYBCT would add delays between words, slowing down transfers.
- * It could potentially be useful to cope with DMA bottlenecks, but
- * in those cases it's probably best to just use a lower bitrate.
- */
- csr |= SPI_BF(DLYBS, 0);
- csr |= SPI_BF(DLYBCT, 0);
-
- /* chipselect must have been muxed as GPIO (e.g. in board setup) */
- npcs_pin = (unsigned int)spi->controller_data;
- asd = spi->controller_state;
- if (!asd) {
- asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
- if (!asd)
- return -ENOMEM;
-
- ret = gpio_request(npcs_pin, dev_name(&spi->dev));
- if (ret) {
- kfree(asd);
- return ret;
- }
-
- asd->npcs_pin = npcs_pin;
- spi->controller_state = asd;
- gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
- } else {
- unsigned long flags;
-
- spin_lock_irqsave(&as->lock, flags);
- if (as->stay == spi)
- as->stay = NULL;
- cs_deactivate(as, spi);
- spin_unlock_irqrestore(&as->lock, flags);
- }
-
- asd->csr = csr;
-
- dev_dbg(&spi->dev,
- "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
- bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
-
- if (!atmel_spi_is_v2())
- spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
-
- return 0;
-}
-
-static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct atmel_spi *as;
- struct spi_transfer *xfer;
- unsigned long flags;
- struct device *controller = spi->master->dev.parent;
- u8 bits;
- struct atmel_spi_device *asd;
-
- as = spi_master_get_devdata(spi->master);
-
- dev_dbg(controller, "new message %p submitted for %s\n",
- msg, dev_name(&spi->dev));
-
- if (unlikely(list_empty(&msg->transfers)))
- return -EINVAL;
-
- if (as->stopping)
- return -ESHUTDOWN;
-
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
- dev_dbg(&spi->dev, "missing rx or tx buf\n");
- return -EINVAL;
- }
-
- if (xfer->bits_per_word) {
- asd = spi->controller_state;
- bits = (asd->csr >> 4) & 0xf;
- if (bits != xfer->bits_per_word - 8) {
- dev_dbg(&spi->dev, "you can't yet change "
- "bits_per_word in transfers\n");
- return -ENOPROTOOPT;
- }
- }
-
- /* FIXME implement these protocol options!! */
- if (xfer->speed_hz) {
- dev_dbg(&spi->dev, "no protocol options yet\n");
- return -ENOPROTOOPT;
- }
-
- /*
- * DMA map early, for performance (empties dcache ASAP) and
- * better fault reporting. This is a DMA-only driver.
- *
- * NOTE that if dma_unmap_single() ever starts to do work on
- * platforms supported by this driver, we would need to clean
- * up mappings for previously-mapped transfers.
- */
- if (!msg->is_dma_mapped) {
- if (atmel_spi_dma_map_xfer(as, xfer) < 0)
- return -ENOMEM;
- }
- }
-
-#ifdef VERBOSE
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- dev_dbg(controller,
- " xfer %p: len %u tx %p/%08x rx %p/%08x\n",
- xfer, xfer->len,
- xfer->tx_buf, xfer->tx_dma,
- xfer->rx_buf, xfer->rx_dma);
- }
-#endif
-
- msg->status = -EINPROGRESS;
- msg->actual_length = 0;
-
- spin_lock_irqsave(&as->lock, flags);
- list_add_tail(&msg->queue, &as->queue);
- if (!as->current_transfer)
- atmel_spi_next_message(spi->master);
- spin_unlock_irqrestore(&as->lock, flags);
-
- return 0;
-}
-
-static void atmel_spi_cleanup(struct spi_device *spi)
-{
- struct atmel_spi *as = spi_master_get_devdata(spi->master);
- struct atmel_spi_device *asd = spi->controller_state;
- unsigned gpio = (unsigned) spi->controller_data;
- unsigned long flags;
-
- if (!asd)
- return;
-
- spin_lock_irqsave(&as->lock, flags);
- if (as->stay == spi) {
- as->stay = NULL;
- cs_deactivate(as, spi);
- }
- spin_unlock_irqrestore(&as->lock, flags);
-
- spi->controller_state = NULL;
- gpio_free(gpio);
- kfree(asd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit atmel_spi_probe(struct platform_device *pdev)
-{
- struct resource *regs;
- int irq;
- struct clk *clk;
- int ret;
- struct spi_master *master;
- struct atmel_spi *as;
-
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!regs)
- return -ENXIO;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-
- clk = clk_get(&pdev->dev, "spi_clk");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- /* setup spi core then atmel-specific driver state */
- ret = -ENOMEM;
- master = spi_alloc_master(&pdev->dev, sizeof *as);
- if (!master)
- goto out_free;
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- master->bus_num = pdev->id;
- master->num_chipselect = 4;
- master->setup = atmel_spi_setup;
- master->transfer = atmel_spi_transfer;
- master->cleanup = atmel_spi_cleanup;
- platform_set_drvdata(pdev, master);
-
- as = spi_master_get_devdata(master);
-
- /*
- * Scratch buffer is used for throwaway rx and tx data.
- * It's coherent to minimize dcache pollution.
- */
- as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
- &as->buffer_dma, GFP_KERNEL);
- if (!as->buffer)
- goto out_free;
-
- spin_lock_init(&as->lock);
- INIT_LIST_HEAD(&as->queue);
- as->pdev = pdev;
- as->regs = ioremap(regs->start, resource_size(regs));
- if (!as->regs)
- goto out_free_buffer;
- as->irq = irq;
- as->clk = clk;
-
- ret = request_irq(irq, atmel_spi_interrupt, 0,
- dev_name(&pdev->dev), master);
- if (ret)
- goto out_unmap_regs;
-
- /* Initialize the hardware */
- clk_enable(clk);
- spi_writel(as, CR, SPI_BIT(SWRST));
- spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
- spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
- spi_writel(as, CR, SPI_BIT(SPIEN));
-
- /* go! */
- dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
- (unsigned long)regs->start, irq);
-
- ret = spi_register_master(master);
- if (ret)
- goto out_reset_hw;
-
- return 0;
-
-out_reset_hw:
- spi_writel(as, CR, SPI_BIT(SWRST));
- spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
- clk_disable(clk);
- free_irq(irq, master);
-out_unmap_regs:
- iounmap(as->regs);
-out_free_buffer:
- dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
- as->buffer_dma);
-out_free:
- clk_put(clk);
- spi_master_put(master);
- return ret;
-}
-
-static int __devexit atmel_spi_remove(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct atmel_spi *as = spi_master_get_devdata(master);
- struct spi_message *msg;
-
- /* reset the hardware and block queue progress */
- spin_lock_irq(&as->lock);
- as->stopping = 1;
- spi_writel(as, CR, SPI_BIT(SWRST));
- spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
- spi_readl(as, SR);
- spin_unlock_irq(&as->lock);
-
- /* Terminate remaining queued transfers */
- list_for_each_entry(msg, &as->queue, queue) {
- /* REVISIT unmapping the dma is a NOP on ARM and AVR32
- * but we shouldn't depend on that...
- */
- msg->status = -ESHUTDOWN;
- msg->complete(msg->context);
- }
-
- dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
- as->buffer_dma);
-
- clk_disable(as->clk);
- clk_put(as->clk);
- free_irq(as->irq, master);
- iounmap(as->regs);
-
- spi_unregister_master(master);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct atmel_spi *as = spi_master_get_devdata(master);
-
- clk_disable(as->clk);
- return 0;
-}
-
-static int atmel_spi_resume(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct atmel_spi *as = spi_master_get_devdata(master);
-
- clk_enable(as->clk);
- return 0;
-}
-
-#else
-#define atmel_spi_suspend NULL
-#define atmel_spi_resume NULL
-#endif
-
-
-static struct platform_driver atmel_spi_driver = {
- .driver = {
- .name = "atmel_spi",
- .owner = THIS_MODULE,
- },
- .suspend = atmel_spi_suspend,
- .resume = atmel_spi_resume,
- .probe = atmel_spi_probe,
- .remove = __exit_p(atmel_spi_remove),
-};
-module_platform_driver(atmel_spi_driver);
-
-MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
-MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:atmel_spi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-au1550.c b/ANDROID_3.4.5/drivers/spi/spi-au1550.c
deleted file mode 100644
index 5784c879..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-au1550.c
+++ /dev/null
@@ -1,1033 +0,0 @@
-/*
- * 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)
- *
- * Copyright (c) 2006 ATRON electronic GmbH
- * Author: Jan Nikitenko <jan.nikitenko@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/dma-mapping.h>
-#include <linux/completion.h>
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/au1xxx_psc.h>
-#include <asm/mach-au1x00/au1xxx_dbdma.h>
-
-#include <asm/mach-au1x00/au1550_spi.h>
-
-static unsigned usedma = 1;
-module_param(usedma, uint, 0644);
-
-/*
-#define AU1550_SPI_DEBUG_LOOPBACK
-*/
-
-
-#define AU1550_SPI_DBDMA_DESCRIPTORS 1
-#define AU1550_SPI_DMA_RXTMP_MINSIZE 2048U
-
-struct au1550_spi {
- struct spi_bitbang bitbang;
-
- volatile psc_spi_t __iomem *regs;
- int irq;
- unsigned freq_max;
- unsigned freq_min;
-
- unsigned len;
- unsigned tx_count;
- unsigned rx_count;
- const u8 *tx;
- u8 *rx;
-
- void (*rx_word)(struct au1550_spi *hw);
- void (*tx_word)(struct au1550_spi *hw);
- int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
- irqreturn_t (*irq_callback)(struct au1550_spi *hw);
-
- struct completion master_done;
-
- unsigned usedma;
- u32 dma_tx_id;
- u32 dma_rx_id;
- u32 dma_tx_ch;
- u32 dma_rx_ch;
-
- u8 *dma_rx_tmpbuf;
- unsigned dma_rx_tmpbuf_size;
- u32 dma_rx_tmpbuf_addr;
-
- struct spi_master *master;
- struct device *dev;
- struct au1550_spi_info *pdata;
- struct resource *ioarea;
-};
-
-
-/* we use an 8-bit memory device for dma transfers to/from spi fifo */
-static dbdev_tab_t au1550_spi_mem_dbdev =
-{
- .dev_id = DBDMA_MEM_CHAN,
- .dev_flags = DEV_FLAGS_ANYUSE|DEV_FLAGS_SYNC,
- .dev_tsize = 0,
- .dev_devwidth = 8,
- .dev_physaddr = 0x00000000,
- .dev_intlevel = 0,
- .dev_intpolarity = 0
-};
-
-static int ddma_memid; /* id to above mem dma device */
-
-static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
-
-
-/*
- * compute BRG and DIV bits to setup spi clock based on main input clock rate
- * that was specified in platform data structure
- * according to au1550 datasheet:
- * psc_tempclk = psc_mainclk / (2 << DIV)
- * spiclk = psc_tempclk / (2 * (BRG + 1))
- * BRG valid range is 4..63
- * DIV valid range is 0..3
- */
-static u32 au1550_spi_baudcfg(struct au1550_spi *hw, unsigned speed_hz)
-{
- u32 mainclk_hz = hw->pdata->mainclk_hz;
- u32 div, brg;
-
- for (div = 0; div < 4; div++) {
- brg = mainclk_hz / speed_hz / (4 << div);
- /* now we have BRG+1 in brg, so count with that */
- if (brg < (4 + 1)) {
- brg = (4 + 1); /* speed_hz too big */
- break; /* set lowest brg (div is == 0) */
- }
- if (brg <= (63 + 1))
- break; /* we have valid brg and div */
- }
- if (div == 4) {
- div = 3; /* speed_hz too small */
- brg = (63 + 1); /* set highest brg and div */
- }
- brg--;
- return PSC_SPICFG_SET_BAUD(brg) | PSC_SPICFG_SET_DIV(div);
-}
-
-static inline void au1550_spi_mask_ack_all(struct au1550_spi *hw)
-{
- hw->regs->psc_spimsk =
- PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
- | PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
- | PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
- au_sync();
-
- hw->regs->psc_spievent =
- PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
- | PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
- | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
- au_sync();
-}
-
-static void au1550_spi_reset_fifos(struct au1550_spi *hw)
-{
- u32 pcr;
-
- hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
- au_sync();
- do {
- pcr = hw->regs->psc_spipcr;
- au_sync();
- } while (pcr != 0);
-}
-
-/*
- * dma transfers are used for the most common spi word size of 8-bits
- * we cannot easily change already set up dma channels' width, so if we wanted
- * dma support for more than 8-bit words (up to 24 bits), we would need to
- * setup dma channels from scratch on each spi transfer, based on bits_per_word
- * instead we have pre set up 8 bit dma channels supporting spi 4 to 8 bits
- * transfers, and 9 to 24 bits spi transfers will be done in pio irq based mode
- * callbacks to handle dma or pio are set up in au1550_spi_bits_handlers_set()
- */
-static void au1550_spi_chipsel(struct spi_device *spi, int value)
-{
- struct au1550_spi *hw = spi_master_get_devdata(spi->master);
- unsigned cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
- u32 cfg, stat;
-
- switch (value) {
- case BITBANG_CS_INACTIVE:
- if (hw->pdata->deactivate_cs)
- hw->pdata->deactivate_cs(hw->pdata, spi->chip_select,
- cspol);
- break;
-
- case BITBANG_CS_ACTIVE:
- au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
-
- cfg = hw->regs->psc_spicfg;
- au_sync();
- hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
- au_sync();
-
- if (spi->mode & SPI_CPOL)
- cfg |= PSC_SPICFG_BI;
- else
- cfg &= ~PSC_SPICFG_BI;
- if (spi->mode & SPI_CPHA)
- cfg &= ~PSC_SPICFG_CDE;
- else
- cfg |= PSC_SPICFG_CDE;
-
- if (spi->mode & SPI_LSB_FIRST)
- cfg |= PSC_SPICFG_MLF;
- else
- cfg &= ~PSC_SPICFG_MLF;
-
- if (hw->usedma && spi->bits_per_word <= 8)
- cfg &= ~PSC_SPICFG_DD_DISABLE;
- else
- cfg |= PSC_SPICFG_DD_DISABLE;
- cfg = PSC_SPICFG_CLR_LEN(cfg);
- cfg |= PSC_SPICFG_SET_LEN(spi->bits_per_word);
-
- cfg = PSC_SPICFG_CLR_BAUD(cfg);
- cfg &= ~PSC_SPICFG_SET_DIV(3);
- cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
-
- hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
- au_sync();
- do {
- stat = hw->regs->psc_spistat;
- au_sync();
- } while ((stat & PSC_SPISTAT_DR) == 0);
-
- if (hw->pdata->activate_cs)
- hw->pdata->activate_cs(hw->pdata, spi->chip_select,
- cspol);
- break;
- }
-}
-
-static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct au1550_spi *hw = spi_master_get_devdata(spi->master);
- unsigned bpw, hz;
- u32 cfg, stat;
-
- bpw = spi->bits_per_word;
- hz = spi->max_speed_hz;
- if (t) {
- if (t->bits_per_word)
- bpw = t->bits_per_word;
- if (t->speed_hz)
- hz = t->speed_hz;
- }
-
- if (bpw < 4 || bpw > 24) {
- dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n",
- bpw);
- return -EINVAL;
- }
- if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
- dev_err(&spi->dev, "setupxfer: clock rate=%d out of range\n",
- hz);
- return -EINVAL;
- }
-
- au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
-
- cfg = hw->regs->psc_spicfg;
- au_sync();
- hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
- au_sync();
-
- if (hw->usedma && bpw <= 8)
- cfg &= ~PSC_SPICFG_DD_DISABLE;
- else
- cfg |= PSC_SPICFG_DD_DISABLE;
- cfg = PSC_SPICFG_CLR_LEN(cfg);
- cfg |= PSC_SPICFG_SET_LEN(bpw);
-
- cfg = PSC_SPICFG_CLR_BAUD(cfg);
- cfg &= ~PSC_SPICFG_SET_DIV(3);
- cfg |= au1550_spi_baudcfg(hw, hz);
-
- hw->regs->psc_spicfg = cfg;
- au_sync();
-
- if (cfg & PSC_SPICFG_DE_ENABLE) {
- do {
- stat = hw->regs->psc_spistat;
- au_sync();
- } while ((stat & PSC_SPISTAT_DR) == 0);
- }
-
- au1550_spi_reset_fifos(hw);
- au1550_spi_mask_ack_all(hw);
- return 0;
-}
-
-static int au1550_spi_setup(struct spi_device *spi)
-{
- struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-
- if (spi->bits_per_word < 4 || spi->bits_per_word > 24) {
- dev_err(&spi->dev, "setup: invalid bits_per_word=%d\n",
- spi->bits_per_word);
- return -EINVAL;
- }
-
- if (spi->max_speed_hz == 0)
- spi->max_speed_hz = hw->freq_max;
- if (spi->max_speed_hz > hw->freq_max
- || spi->max_speed_hz < hw->freq_min)
- return -EINVAL;
- /*
- * NOTE: cannot change speed and other hw settings immediately,
- * otherwise sharing of spi bus is not possible,
- * so do not call setupxfer(spi, NULL) here
- */
- return 0;
-}
-
-/*
- * for dma spi transfers, we have to setup rx channel, otherwise there is
- * no reliable way how to recognize that spi transfer is done
- * dma complete callbacks are called before real spi transfer is finished
- * and if only tx dma channel is set up (and rx fifo overflow event masked)
- * spi master done event irq is not generated unless rx fifo is empty (emptied)
- * so we need rx tmp buffer to use for rx dma if user does not provide one
- */
-static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned size)
-{
- hw->dma_rx_tmpbuf = kmalloc(size, GFP_KERNEL);
- if (!hw->dma_rx_tmpbuf)
- return -ENOMEM;
- hw->dma_rx_tmpbuf_size = size;
- hw->dma_rx_tmpbuf_addr = dma_map_single(hw->dev, hw->dma_rx_tmpbuf,
- size, DMA_FROM_DEVICE);
- if (dma_mapping_error(hw->dev, hw->dma_rx_tmpbuf_addr)) {
- kfree(hw->dma_rx_tmpbuf);
- hw->dma_rx_tmpbuf = 0;
- hw->dma_rx_tmpbuf_size = 0;
- return -EFAULT;
- }
- return 0;
-}
-
-static void au1550_spi_dma_rxtmp_free(struct au1550_spi *hw)
-{
- dma_unmap_single(hw->dev, hw->dma_rx_tmpbuf_addr,
- hw->dma_rx_tmpbuf_size, DMA_FROM_DEVICE);
- kfree(hw->dma_rx_tmpbuf);
- hw->dma_rx_tmpbuf = 0;
- hw->dma_rx_tmpbuf_size = 0;
-}
-
-static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
-{
- struct au1550_spi *hw = spi_master_get_devdata(spi->master);
- dma_addr_t dma_tx_addr;
- dma_addr_t dma_rx_addr;
- u32 res;
-
- hw->len = t->len;
- hw->tx_count = 0;
- hw->rx_count = 0;
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- dma_tx_addr = t->tx_dma;
- dma_rx_addr = t->rx_dma;
-
- /*
- * check if buffers are already dma mapped, map them otherwise:
- * - first map the TX buffer, so cache data gets written to memory
- * - then map the RX buffer, so that cache entries (with
- * soon-to-be-stale data) get removed
- * use rx buffer in place of tx if tx buffer was not provided
- * use temp rx buffer (preallocated or realloc to fit) for rx dma
- */
- if (t->tx_buf) {
- if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
- dma_tx_addr = dma_map_single(hw->dev,
- (void *)t->tx_buf,
- t->len, DMA_TO_DEVICE);
- if (dma_mapping_error(hw->dev, dma_tx_addr))
- dev_err(hw->dev, "tx dma map error\n");
- }
- }
-
- if (t->rx_buf) {
- if (t->rx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
- dma_rx_addr = dma_map_single(hw->dev,
- (void *)t->rx_buf,
- t->len, DMA_FROM_DEVICE);
- if (dma_mapping_error(hw->dev, dma_rx_addr))
- dev_err(hw->dev, "rx dma map error\n");
- }
- } else {
- if (t->len > hw->dma_rx_tmpbuf_size) {
- int ret;
-
- au1550_spi_dma_rxtmp_free(hw);
- ret = au1550_spi_dma_rxtmp_alloc(hw, max(t->len,
- AU1550_SPI_DMA_RXTMP_MINSIZE));
- if (ret < 0)
- return ret;
- }
- hw->rx = hw->dma_rx_tmpbuf;
- dma_rx_addr = hw->dma_rx_tmpbuf_addr;
- dma_sync_single_for_device(hw->dev, dma_rx_addr,
- t->len, DMA_FROM_DEVICE);
- }
-
- if (!t->tx_buf) {
- dma_sync_single_for_device(hw->dev, dma_rx_addr,
- t->len, DMA_BIDIRECTIONAL);
- hw->tx = hw->rx;
- }
-
- /* put buffers on the ring */
- res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, virt_to_phys(hw->rx),
- t->len, DDMA_FLAGS_IE);
- if (!res)
- dev_err(hw->dev, "rx dma put dest error\n");
-
- res = au1xxx_dbdma_put_source(hw->dma_tx_ch, virt_to_phys(hw->tx),
- t->len, DDMA_FLAGS_IE);
- if (!res)
- dev_err(hw->dev, "tx dma put source error\n");
-
- au1xxx_dbdma_start(hw->dma_rx_ch);
- au1xxx_dbdma_start(hw->dma_tx_ch);
-
- /* by default enable nearly all events interrupt */
- hw->regs->psc_spimsk = PSC_SPIMSK_SD;
- au_sync();
-
- /* start the transfer */
- hw->regs->psc_spipcr = PSC_SPIPCR_MS;
- au_sync();
-
- wait_for_completion(&hw->master_done);
-
- au1xxx_dbdma_stop(hw->dma_tx_ch);
- au1xxx_dbdma_stop(hw->dma_rx_ch);
-
- if (!t->rx_buf) {
- /* using the temporal preallocated and premapped buffer */
- dma_sync_single_for_cpu(hw->dev, dma_rx_addr, t->len,
- DMA_FROM_DEVICE);
- }
- /* unmap buffers if mapped above */
- if (t->rx_buf && t->rx_dma == 0 )
- dma_unmap_single(hw->dev, dma_rx_addr, t->len,
- DMA_FROM_DEVICE);
- if (t->tx_buf && t->tx_dma == 0 )
- dma_unmap_single(hw->dev, dma_tx_addr, t->len,
- DMA_TO_DEVICE);
-
- return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
-}
-
-static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
-{
- u32 stat, evnt;
-
- stat = hw->regs->psc_spistat;
- evnt = hw->regs->psc_spievent;
- au_sync();
- if ((stat & PSC_SPISTAT_DI) == 0) {
- dev_err(hw->dev, "Unexpected IRQ!\n");
- return IRQ_NONE;
- }
-
- if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
- | PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
- | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
- != 0) {
- /*
- * due to an spi error we consider transfer as done,
- * so mask all events until before next transfer start
- * and stop the possibly running dma immediatelly
- */
- au1550_spi_mask_ack_all(hw);
- au1xxx_dbdma_stop(hw->dma_rx_ch);
- au1xxx_dbdma_stop(hw->dma_tx_ch);
-
- /* get number of transferred bytes */
- hw->rx_count = hw->len - au1xxx_get_dma_residue(hw->dma_rx_ch);
- hw->tx_count = hw->len - au1xxx_get_dma_residue(hw->dma_tx_ch);
-
- au1xxx_dbdma_reset(hw->dma_rx_ch);
- au1xxx_dbdma_reset(hw->dma_tx_ch);
- au1550_spi_reset_fifos(hw);
-
- if (evnt == PSC_SPIEVNT_RO)
- dev_err(hw->dev,
- "dma transfer: receive FIFO overflow!\n");
- else
- dev_err(hw->dev,
- "dma transfer: unexpected SPI error "
- "(event=0x%x stat=0x%x)!\n", evnt, stat);
-
- complete(&hw->master_done);
- return IRQ_HANDLED;
- }
-
- if ((evnt & PSC_SPIEVNT_MD) != 0) {
- /* transfer completed successfully */
- au1550_spi_mask_ack_all(hw);
- hw->rx_count = hw->len;
- hw->tx_count = hw->len;
- complete(&hw->master_done);
- }
- return IRQ_HANDLED;
-}
-
-
-/* routines to handle different word sizes in pio mode */
-#define AU1550_SPI_RX_WORD(size, mask) \
-static void au1550_spi_rx_word_##size(struct au1550_spi *hw) \
-{ \
- u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask); \
- au_sync(); \
- if (hw->rx) { \
- *(u##size *)hw->rx = (u##size)fifoword; \
- hw->rx += (size) / 8; \
- } \
- hw->rx_count += (size) / 8; \
-}
-
-#define AU1550_SPI_TX_WORD(size, mask) \
-static void au1550_spi_tx_word_##size(struct au1550_spi *hw) \
-{ \
- u32 fifoword = 0; \
- if (hw->tx) { \
- fifoword = *(u##size *)hw->tx & (u32)(mask); \
- hw->tx += (size) / 8; \
- } \
- hw->tx_count += (size) / 8; \
- if (hw->tx_count >= hw->len) \
- fifoword |= PSC_SPITXRX_LC; \
- hw->regs->psc_spitxrx = fifoword; \
- au_sync(); \
-}
-
-AU1550_SPI_RX_WORD(8,0xff)
-AU1550_SPI_RX_WORD(16,0xffff)
-AU1550_SPI_RX_WORD(32,0xffffff)
-AU1550_SPI_TX_WORD(8,0xff)
-AU1550_SPI_TX_WORD(16,0xffff)
-AU1550_SPI_TX_WORD(32,0xffffff)
-
-static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
-{
- u32 stat, mask;
- struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->len = t->len;
- hw->tx_count = 0;
- hw->rx_count = 0;
-
- /* by default enable nearly all events after filling tx fifo */
- mask = PSC_SPIMSK_SD;
-
- /* fill the transmit FIFO */
- while (hw->tx_count < hw->len) {
-
- hw->tx_word(hw);
-
- if (hw->tx_count >= hw->len) {
- /* mask tx fifo request interrupt as we are done */
- mask |= PSC_SPIMSK_TR;
- }
-
- stat = hw->regs->psc_spistat;
- au_sync();
- if (stat & PSC_SPISTAT_TF)
- break;
- }
-
- /* enable event interrupts */
- hw->regs->psc_spimsk = mask;
- au_sync();
-
- /* start the transfer */
- hw->regs->psc_spipcr = PSC_SPIPCR_MS;
- au_sync();
-
- wait_for_completion(&hw->master_done);
-
- return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
-}
-
-static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
-{
- int busy;
- u32 stat, evnt;
-
- stat = hw->regs->psc_spistat;
- evnt = hw->regs->psc_spievent;
- au_sync();
- if ((stat & PSC_SPISTAT_DI) == 0) {
- dev_err(hw->dev, "Unexpected IRQ!\n");
- return IRQ_NONE;
- }
-
- if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
- | PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
- | PSC_SPIEVNT_SD))
- != 0) {
- /*
- * due to an error we consider transfer as done,
- * so mask all events until before next transfer start
- */
- au1550_spi_mask_ack_all(hw);
- au1550_spi_reset_fifos(hw);
- dev_err(hw->dev,
- "pio transfer: unexpected SPI error "
- "(event=0x%x stat=0x%x)!\n", evnt, stat);
- complete(&hw->master_done);
- return IRQ_HANDLED;
- }
-
- /*
- * while there is something to read from rx fifo
- * or there is a space to write to tx fifo:
- */
- do {
- busy = 0;
- stat = hw->regs->psc_spistat;
- au_sync();
-
- /*
- * Take care to not let the Rx FIFO overflow.
- *
- * We only write a byte if we have read one at least. Initially,
- * the write fifo is full, so we should read from the read fifo
- * first.
- * In case we miss a word from the read fifo, we should get a
- * RO event and should back out.
- */
- if (!(stat & PSC_SPISTAT_RE) && hw->rx_count < hw->len) {
- hw->rx_word(hw);
- busy = 1;
-
- if (!(stat & PSC_SPISTAT_TF) && hw->tx_count < hw->len)
- hw->tx_word(hw);
- }
- } while (busy);
-
- hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
- au_sync();
-
- /*
- * Restart the SPI transmission in case of a transmit underflow.
- * This seems to work despite the notes in the Au1550 data book
- * of Figure 8-4 with flowchart for SPI master operation:
- *
- * """Note 1: An XFR Error Interrupt occurs, unless masked,
- * for any of the following events: Tx FIFO Underflow,
- * Rx FIFO Overflow, or Multiple-master Error
- * Note 2: In case of a Tx Underflow Error, all zeroes are
- * transmitted."""
- *
- * By simply restarting the spi transfer on Tx Underflow Error,
- * we assume that spi transfer was paused instead of zeroes
- * transmittion mentioned in the Note 2 of Au1550 data book.
- */
- if (evnt & PSC_SPIEVNT_TU) {
- hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
- au_sync();
- hw->regs->psc_spipcr = PSC_SPIPCR_MS;
- au_sync();
- }
-
- if (hw->rx_count >= hw->len) {
- /* transfer completed successfully */
- au1550_spi_mask_ack_all(hw);
- complete(&hw->master_done);
- }
- return IRQ_HANDLED;
-}
-
-static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
- struct au1550_spi *hw = spi_master_get_devdata(spi->master);
- return hw->txrx_bufs(spi, t);
-}
-
-static irqreturn_t au1550_spi_irq(int irq, void *dev)
-{
- struct au1550_spi *hw = dev;
- return hw->irq_callback(hw);
-}
-
-static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw)
-{
- if (bpw <= 8) {
- if (hw->usedma) {
- hw->txrx_bufs = &au1550_spi_dma_txrxb;
- hw->irq_callback = &au1550_spi_dma_irq_callback;
- } else {
- hw->rx_word = &au1550_spi_rx_word_8;
- hw->tx_word = &au1550_spi_tx_word_8;
- hw->txrx_bufs = &au1550_spi_pio_txrxb;
- hw->irq_callback = &au1550_spi_pio_irq_callback;
- }
- } else if (bpw <= 16) {
- hw->rx_word = &au1550_spi_rx_word_16;
- hw->tx_word = &au1550_spi_tx_word_16;
- hw->txrx_bufs = &au1550_spi_pio_txrxb;
- hw->irq_callback = &au1550_spi_pio_irq_callback;
- } else {
- hw->rx_word = &au1550_spi_rx_word_32;
- hw->tx_word = &au1550_spi_tx_word_32;
- hw->txrx_bufs = &au1550_spi_pio_txrxb;
- hw->irq_callback = &au1550_spi_pio_irq_callback;
- }
-}
-
-static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
-{
- u32 stat, cfg;
-
- /* set up the PSC for SPI mode */
- hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
- au_sync();
- hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
- au_sync();
-
- hw->regs->psc_spicfg = 0;
- au_sync();
-
- hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
- au_sync();
-
- do {
- stat = hw->regs->psc_spistat;
- au_sync();
- } while ((stat & PSC_SPISTAT_SR) == 0);
-
-
- cfg = hw->usedma ? 0 : PSC_SPICFG_DD_DISABLE;
- cfg |= PSC_SPICFG_SET_LEN(8);
- cfg |= PSC_SPICFG_RT_FIFO8 | PSC_SPICFG_TT_FIFO8;
- /* use minimal allowed brg and div values as initial setting: */
- cfg |= PSC_SPICFG_SET_BAUD(4) | PSC_SPICFG_SET_DIV(0);
-
-#ifdef AU1550_SPI_DEBUG_LOOPBACK
- cfg |= PSC_SPICFG_LB;
-#endif
-
- hw->regs->psc_spicfg = cfg;
- au_sync();
-
- au1550_spi_mask_ack_all(hw);
-
- hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
- au_sync();
-
- do {
- stat = hw->regs->psc_spistat;
- au_sync();
- } while ((stat & PSC_SPISTAT_DR) == 0);
-
- au1550_spi_reset_fifos(hw);
-}
-
-
-static int __init au1550_spi_probe(struct platform_device *pdev)
-{
- struct au1550_spi *hw;
- struct spi_master *master;
- struct resource *r;
- int err = 0;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
- if (master == NULL) {
- dev_err(&pdev->dev, "No memory for spi_master\n");
- err = -ENOMEM;
- goto err_nomem;
- }
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
-
- hw = spi_master_get_devdata(master);
-
- hw->master = spi_master_get(master);
- hw->pdata = pdev->dev.platform_data;
- hw->dev = &pdev->dev;
-
- if (hw->pdata == NULL) {
- dev_err(&pdev->dev, "No platform data supplied\n");
- err = -ENOENT;
- goto err_no_pdata;
- }
-
- r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!r) {
- dev_err(&pdev->dev, "no IRQ\n");
- err = -ENODEV;
- goto err_no_iores;
- }
- hw->irq = r->start;
-
- hw->usedma = 0;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (r) {
- hw->dma_tx_id = r->start;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (r) {
- hw->dma_rx_id = r->start;
- if (usedma && ddma_memid) {
- if (pdev->dev.dma_mask == NULL)
- dev_warn(&pdev->dev, "no dma mask\n");
- else
- hw->usedma = 1;
- }
- }
- }
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(&pdev->dev, "no mmio resource\n");
- err = -ENODEV;
- goto err_no_iores;
- }
-
- hw->ioarea = request_mem_region(r->start, sizeof(psc_spi_t),
- pdev->name);
- if (!hw->ioarea) {
- dev_err(&pdev->dev, "Cannot reserve iomem region\n");
- err = -ENXIO;
- goto err_no_iores;
- }
-
- hw->regs = (psc_spi_t __iomem *)ioremap(r->start, sizeof(psc_spi_t));
- if (!hw->regs) {
- dev_err(&pdev->dev, "cannot ioremap\n");
- err = -ENXIO;
- goto err_ioremap;
- }
-
- platform_set_drvdata(pdev, hw);
-
- init_completion(&hw->master_done);
-
- hw->bitbang.master = hw->master;
- hw->bitbang.setup_transfer = au1550_spi_setupxfer;
- hw->bitbang.chipselect = au1550_spi_chipsel;
- hw->bitbang.master->setup = au1550_spi_setup;
- hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
-
- if (hw->usedma) {
- hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(ddma_memid,
- hw->dma_tx_id, NULL, (void *)hw);
- if (hw->dma_tx_ch == 0) {
- dev_err(&pdev->dev,
- "Cannot allocate tx dma channel\n");
- err = -ENXIO;
- goto err_no_txdma;
- }
- au1xxx_dbdma_set_devwidth(hw->dma_tx_ch, 8);
- if (au1xxx_dbdma_ring_alloc(hw->dma_tx_ch,
- AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
- dev_err(&pdev->dev,
- "Cannot allocate tx dma descriptors\n");
- err = -ENXIO;
- goto err_no_txdma_descr;
- }
-
-
- hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
- ddma_memid, NULL, (void *)hw);
- if (hw->dma_rx_ch == 0) {
- dev_err(&pdev->dev,
- "Cannot allocate rx dma channel\n");
- err = -ENXIO;
- goto err_no_rxdma;
- }
- au1xxx_dbdma_set_devwidth(hw->dma_rx_ch, 8);
- if (au1xxx_dbdma_ring_alloc(hw->dma_rx_ch,
- AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
- dev_err(&pdev->dev,
- "Cannot allocate rx dma descriptors\n");
- err = -ENXIO;
- goto err_no_rxdma_descr;
- }
-
- err = au1550_spi_dma_rxtmp_alloc(hw,
- AU1550_SPI_DMA_RXTMP_MINSIZE);
- if (err < 0) {
- dev_err(&pdev->dev,
- "Cannot allocate initial rx dma tmp buffer\n");
- goto err_dma_rxtmp_alloc;
- }
- }
-
- au1550_spi_bits_handlers_set(hw, 8);
-
- err = request_irq(hw->irq, au1550_spi_irq, 0, pdev->name, hw);
- if (err) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_no_irq;
- }
-
- master->bus_num = pdev->id;
- master->num_chipselect = hw->pdata->num_chipselect;
-
- /*
- * precompute valid range for spi freq - from au1550 datasheet:
- * psc_tempclk = psc_mainclk / (2 << DIV)
- * spiclk = psc_tempclk / (2 * (BRG + 1))
- * BRG valid range is 4..63
- * DIV valid range is 0..3
- * round the min and max frequencies to values that would still
- * produce valid brg and div
- */
- {
- int min_div = (2 << 0) * (2 * (4 + 1));
- int max_div = (2 << 3) * (2 * (63 + 1));
- hw->freq_max = hw->pdata->mainclk_hz / min_div;
- hw->freq_min = hw->pdata->mainclk_hz / (max_div + 1) + 1;
- }
-
- au1550_spi_setup_psc_as_spi(hw);
-
- err = spi_bitbang_start(&hw->bitbang);
- if (err) {
- dev_err(&pdev->dev, "Failed to register SPI master\n");
- goto err_register;
- }
-
- dev_info(&pdev->dev,
- "spi master registered: bus_num=%d num_chipselect=%d\n",
- master->bus_num, master->num_chipselect);
-
- return 0;
-
-err_register:
- free_irq(hw->irq, hw);
-
-err_no_irq:
- au1550_spi_dma_rxtmp_free(hw);
-
-err_dma_rxtmp_alloc:
-err_no_rxdma_descr:
- if (hw->usedma)
- au1xxx_dbdma_chan_free(hw->dma_rx_ch);
-
-err_no_rxdma:
-err_no_txdma_descr:
- if (hw->usedma)
- au1xxx_dbdma_chan_free(hw->dma_tx_ch);
-
-err_no_txdma:
- iounmap((void __iomem *)hw->regs);
-
-err_ioremap:
- release_resource(hw->ioarea);
- kfree(hw->ioarea);
-
-err_no_iores:
-err_no_pdata:
- spi_master_put(hw->master);
-
-err_nomem:
- return err;
-}
-
-static int __exit au1550_spi_remove(struct platform_device *pdev)
-{
- struct au1550_spi *hw = platform_get_drvdata(pdev);
-
- dev_info(&pdev->dev, "spi master remove: bus_num=%d\n",
- hw->master->bus_num);
-
- spi_bitbang_stop(&hw->bitbang);
- free_irq(hw->irq, hw);
- iounmap((void __iomem *)hw->regs);
- release_resource(hw->ioarea);
- kfree(hw->ioarea);
-
- if (hw->usedma) {
- au1550_spi_dma_rxtmp_free(hw);
- au1xxx_dbdma_chan_free(hw->dma_rx_ch);
- au1xxx_dbdma_chan_free(hw->dma_tx_ch);
- }
-
- platform_set_drvdata(pdev, NULL);
-
- spi_master_put(hw->master);
- return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:au1550-spi");
-
-static struct platform_driver au1550_spi_drv = {
- .remove = __exit_p(au1550_spi_remove),
- .driver = {
- .name = "au1550-spi",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init au1550_spi_init(void)
-{
- /*
- * create memory device with 8 bits dev_devwidth
- * needed for proper byte ordering to spi fifo
- */
- if (usedma) {
- ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
- if (!ddma_memid)
- printk(KERN_ERR "au1550-spi: cannot add memory"
- "dbdma device\n");
- }
- return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
-}
-module_init(au1550_spi_init);
-
-static void __exit au1550_spi_exit(void)
-{
- if (usedma && ddma_memid)
- au1xxx_ddma_del_device(ddma_memid);
- platform_driver_unregister(&au1550_spi_drv);
-}
-module_exit(au1550_spi_exit);
-
-MODULE_DESCRIPTION("Au1550 PSC SPI Driver");
-MODULE_AUTHOR("Jan Nikitenko <jan.nikitenko@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-bcm63xx.c b/ANDROID_3.4.5/drivers/spi/spi-bcm63xx.c
deleted file mode 100644
index 74919711..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-bcm63xx.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Broadcom BCM63xx SPI controller support
- *
- * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
- * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/completion.h>
-#include <linux/err.h>
-#include <linux/workqueue.h>
-#include <linux/pm_runtime.h>
-
-#include <bcm63xx_dev_spi.h>
-
-#define PFX KBUILD_MODNAME
-#define DRV_VER "0.1.2"
-
-struct bcm63xx_spi {
- struct completion done;
-
- void __iomem *regs;
- int irq;
-
- /* Platform data */
- u32 speed_hz;
- unsigned fifo_size;
-
- /* Data buffers */
- const unsigned char *tx_ptr;
- unsigned char *rx_ptr;
-
- /* data iomem */
- u8 __iomem *tx_io;
- const u8 __iomem *rx_io;
-
- int remaining_bytes;
-
- struct clk *clk;
- struct platform_device *pdev;
-};
-
-static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
- unsigned int offset)
-{
- return bcm_readb(bs->regs + bcm63xx_spireg(offset));
-}
-
-static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
- unsigned int offset)
-{
- return bcm_readw(bs->regs + bcm63xx_spireg(offset));
-}
-
-static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
- u8 value, unsigned int offset)
-{
- bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
-}
-
-static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
- u16 value, unsigned int offset)
-{
- bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
-}
-
-static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
- { 20000000, SPI_CLK_20MHZ },
- { 12500000, SPI_CLK_12_50MHZ },
- { 6250000, SPI_CLK_6_250MHZ },
- { 3125000, SPI_CLK_3_125MHZ },
- { 1563000, SPI_CLK_1_563MHZ },
- { 781000, SPI_CLK_0_781MHZ },
- { 391000, SPI_CLK_0_391MHZ }
-};
-
-static int bcm63xx_spi_check_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- u8 bits_per_word;
-
- bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
- if (bits_per_word != 8) {
- dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
- __func__, bits_per_word);
- return -EINVAL;
- }
-
- if (spi->chip_select > spi->master->num_chipselect) {
- dev_err(&spi->dev, "%s, unsupported slave %d\n",
- __func__, spi->chip_select);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
- u32 hz;
- u8 clk_cfg, reg;
- int i;
-
- hz = (t) ? t->speed_hz : spi->max_speed_hz;
-
- /* Find the closest clock configuration */
- for (i = 0; i < SPI_CLK_MASK; i++) {
- if (hz <= bcm63xx_spi_freq_table[i][0]) {
- clk_cfg = bcm63xx_spi_freq_table[i][1];
- break;
- }
- }
-
- /* No matching configuration found, default to lowest */
- if (i == SPI_CLK_MASK)
- clk_cfg = SPI_CLK_0_391MHZ;
-
- /* clear existing clock configuration bits of the register */
- reg = bcm_spi_readb(bs, SPI_CLK_CFG);
- reg &= ~SPI_CLK_MASK;
- reg |= clk_cfg;
-
- bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
- dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
- clk_cfg, hz);
-}
-
-/* the spi->mode bits understood by this driver: */
-#define MODEBITS (SPI_CPOL | SPI_CPHA)
-
-static int bcm63xx_spi_setup(struct spi_device *spi)
-{
- struct bcm63xx_spi *bs;
- int ret;
-
- bs = spi_master_get_devdata(spi->master);
-
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
-
- if (spi->mode & ~MODEBITS) {
- dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
- __func__, spi->mode & ~MODEBITS);
- return -EINVAL;
- }
-
- ret = bcm63xx_spi_check_transfer(spi, NULL);
- if (ret < 0) {
- dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
- spi->mode & ~MODEBITS);
- return ret;
- }
-
- dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
- __func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
-
- return 0;
-}
-
-/* Fill the TX FIFO with as many bytes as possible */
-static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
-{
- u8 size;
-
- /* Fill the Tx FIFO with as many bytes as possible */
- size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes :
- bs->fifo_size;
- memcpy_toio(bs->tx_io, bs->tx_ptr, size);
- bs->remaining_bytes -= size;
-}
-
-static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
- u16 msg_ctl;
- u16 cmd;
-
- /* Disable the CMD_DONE interrupt */
- bcm_spi_writeb(bs, 0, SPI_INT_MASK);
-
- dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
- t->tx_buf, t->rx_buf, t->len);
-
- /* Transmitter is inhibited */
- bs->tx_ptr = t->tx_buf;
- bs->rx_ptr = t->rx_buf;
-
- if (t->tx_buf) {
- bs->remaining_bytes = t->len;
- bcm63xx_spi_fill_tx_fifo(bs);
- }
-
- init_completion(&bs->done);
-
- /* Fill in the Message control register */
- msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
-
- if (t->rx_buf && t->tx_buf)
- msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT);
- else if (t->rx_buf)
- msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT);
- else if (t->tx_buf)
- msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT);
-
- bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
-
- /* Issue the transfer */
- cmd = SPI_CMD_START_IMMEDIATE;
- cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
- cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
- bcm_spi_writew(bs, cmd, SPI_CMD);
-
- /* Enable the CMD_DONE interrupt */
- bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
-
- return t->len - bs->remaining_bytes;
-}
-
-static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
-{
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- pm_runtime_get_sync(&bs->pdev->dev);
-
- return 0;
-}
-
-static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
-{
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- pm_runtime_put(&bs->pdev->dev);
-
- return 0;
-}
-
-static int bcm63xx_spi_transfer_one(struct spi_master *master,
- struct spi_message *m)
-{
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
- struct spi_transfer *t;
- struct spi_device *spi = m->spi;
- int status = 0;
- unsigned int timeout = 0;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- unsigned int len = t->len;
- u8 rx_tail;
-
- status = bcm63xx_spi_check_transfer(spi, t);
- if (status < 0)
- goto exit;
-
- /* configure adapter for a new transfer */
- bcm63xx_spi_setup_transfer(spi, t);
-
- while (len) {
- /* send the data */
- len -= bcm63xx_txrx_bufs(spi, t);
-
- timeout = wait_for_completion_timeout(&bs->done, HZ);
- if (!timeout) {
- status = -ETIMEDOUT;
- goto exit;
- }
-
- /* read out all data */
- rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
-
- /* Read out all the data */
- if (rx_tail)
- memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
- }
-
- m->actual_length += t->len;
- }
-exit:
- m->status = status;
- spi_finalize_current_message(master);
-
- return 0;
-}
-
-/* This driver supports single master mode only. Hence
- * CMD_DONE is the only interrupt we care about
- */
-static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
-{
- struct spi_master *master = (struct spi_master *)dev_id;
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
- u8 intr;
-
- /* Read interupts and clear them immediately */
- intr = bcm_spi_readb(bs, SPI_INT_STATUS);
- bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
- bcm_spi_writeb(bs, 0, SPI_INT_MASK);
-
- /* A transfer completed */
- if (intr & SPI_INTR_CMD_DONE)
- complete(&bs->done);
-
- return IRQ_HANDLED;
-}
-
-
-static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
-{
- struct resource *r;
- struct device *dev = &pdev->dev;
- struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
- int irq;
- struct spi_master *master;
- struct clk *clk;
- struct bcm63xx_spi *bs;
- int ret;
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(dev, "no iomem\n");
- ret = -ENXIO;
- goto out;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "no irq\n");
- ret = -ENXIO;
- goto out;
- }
-
- clk = clk_get(dev, "spi");
- if (IS_ERR(clk)) {
- dev_err(dev, "no clock for device\n");
- ret = PTR_ERR(clk);
- goto out;
- }
-
- master = spi_alloc_master(dev, sizeof(*bs));
- if (!master) {
- dev_err(dev, "out of memory\n");
- ret = -ENOMEM;
- goto out_clk;
- }
-
- bs = spi_master_get_devdata(master);
-
- platform_set_drvdata(pdev, master);
- bs->pdev = pdev;
-
- if (!devm_request_mem_region(&pdev->dev, r->start,
- resource_size(r), PFX)) {
- dev_err(dev, "iomem request failed\n");
- ret = -ENXIO;
- goto out_err;
- }
-
- bs->regs = devm_ioremap_nocache(&pdev->dev, r->start,
- resource_size(r));
- if (!bs->regs) {
- dev_err(dev, "unable to ioremap regs\n");
- ret = -ENOMEM;
- goto out_err;
- }
-
- bs->irq = irq;
- bs->clk = clk;
- bs->fifo_size = pdata->fifo_size;
-
- ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
- pdev->name, master);
- if (ret) {
- dev_err(dev, "unable to request irq\n");
- goto out_err;
- }
-
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->num_chipselect;
- master->setup = bcm63xx_spi_setup;
- master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
- master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
- master->transfer_one_message = bcm63xx_spi_transfer_one;
- master->mode_bits = MODEBITS;
- bs->speed_hz = pdata->speed_hz;
- bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
- bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
-
- /* Initialize hardware */
- clk_enable(bs->clk);
- bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
-
- /* register and we are done */
- ret = spi_register_master(master);
- if (ret) {
- dev_err(dev, "spi register failed\n");
- goto out_clk_disable;
- }
-
- dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n",
- r->start, irq, bs->fifo_size, DRV_VER);
-
- return 0;
-
-out_clk_disable:
- clk_disable(clk);
-out_err:
- platform_set_drvdata(pdev, NULL);
- spi_master_put(master);
-out_clk:
- clk_put(clk);
-out:
- return ret;
-}
-
-static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- spi_unregister_master(master);
-
- /* reset spi block */
- bcm_spi_writeb(bs, 0, SPI_INT_MASK);
-
- /* HW shutdown */
- clk_disable(bs->clk);
- clk_put(bs->clk);
-
- platform_set_drvdata(pdev, 0);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int bcm63xx_spi_suspend(struct device *dev)
-{
- struct spi_master *master =
- platform_get_drvdata(to_platform_device(dev));
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- clk_disable(bs->clk);
-
- return 0;
-}
-
-static int bcm63xx_spi_resume(struct device *dev)
-{
- struct spi_master *master =
- platform_get_drvdata(to_platform_device(dev));
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- clk_enable(bs->clk);
-
- return 0;
-}
-
-static const struct dev_pm_ops bcm63xx_spi_pm_ops = {
- .suspend = bcm63xx_spi_suspend,
- .resume = bcm63xx_spi_resume,
-};
-
-#define BCM63XX_SPI_PM_OPS (&bcm63xx_spi_pm_ops)
-#else
-#define BCM63XX_SPI_PM_OPS NULL
-#endif
-
-static struct platform_driver bcm63xx_spi_driver = {
- .driver = {
- .name = "bcm63xx-spi",
- .owner = THIS_MODULE,
- .pm = BCM63XX_SPI_PM_OPS,
- },
- .probe = bcm63xx_spi_probe,
- .remove = __devexit_p(bcm63xx_spi_remove),
-};
-
-module_platform_driver(bcm63xx_spi_driver);
-
-MODULE_ALIAS("platform:bcm63xx_spi");
-MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
-MODULE_AUTHOR("Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>");
-MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-bfin-sport.c b/ANDROID_3.4.5/drivers/spi/spi-bfin-sport.c
deleted file mode 100644
index 1fe51198..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-bfin-sport.c
+++ /dev/null
@@ -1,942 +0,0 @@
-/*
- * SPI bus via the Blackfin SPORT peripheral
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-
-#include <asm/portmux.h>
-#include <asm/bfin5xx_spi.h>
-#include <asm/blackfin.h>
-#include <asm/bfin_sport.h>
-#include <asm/cacheflush.h>
-
-#define DRV_NAME "bfin-sport-spi"
-#define DRV_DESC "SPI bus via the Blackfin SPORT"
-
-MODULE_AUTHOR("Cliff Cai");
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:bfin-sport-spi");
-
-enum bfin_sport_spi_state {
- START_STATE,
- RUNNING_STATE,
- DONE_STATE,
- ERROR_STATE,
-};
-
-struct bfin_sport_spi_master_data;
-
-struct bfin_sport_transfer_ops {
- void (*write) (struct bfin_sport_spi_master_data *);
- void (*read) (struct bfin_sport_spi_master_data *);
- void (*duplex) (struct bfin_sport_spi_master_data *);
-};
-
-struct bfin_sport_spi_master_data {
- /* Driver model hookup */
- struct device *dev;
-
- /* SPI framework hookup */
- struct spi_master *master;
-
- /* Regs base of SPI controller */
- struct sport_register __iomem *regs;
- int err_irq;
-
- /* Pin request list */
- u16 *pin_req;
-
- /* Driver message queue */
- struct workqueue_struct *workqueue;
- struct work_struct pump_messages;
- spinlock_t lock;
- struct list_head queue;
- int busy;
- bool run;
-
- /* Message Transfer pump */
- struct tasklet_struct pump_transfers;
-
- /* Current message transfer state info */
- enum bfin_sport_spi_state state;
- struct spi_message *cur_msg;
- struct spi_transfer *cur_transfer;
- struct bfin_sport_spi_slave_data *cur_chip;
- union {
- void *tx;
- u8 *tx8;
- u16 *tx16;
- };
- void *tx_end;
- union {
- void *rx;
- u8 *rx8;
- u16 *rx16;
- };
- void *rx_end;
-
- int cs_change;
- struct bfin_sport_transfer_ops *ops;
-};
-
-struct bfin_sport_spi_slave_data {
- u16 ctl_reg;
- u16 baud;
- u16 cs_chg_udelay; /* Some devices require > 255usec delay */
- u32 cs_gpio;
- u16 idle_tx_val;
- struct bfin_sport_transfer_ops *ops;
-};
-
-static void
-bfin_sport_spi_enable(struct bfin_sport_spi_master_data *drv_data)
-{
- bfin_write_or(&drv_data->regs->tcr1, TSPEN);
- bfin_write_or(&drv_data->regs->rcr1, TSPEN);
- SSYNC();
-}
-
-static void
-bfin_sport_spi_disable(struct bfin_sport_spi_master_data *drv_data)
-{
- bfin_write_and(&drv_data->regs->tcr1, ~TSPEN);
- bfin_write_and(&drv_data->regs->rcr1, ~TSPEN);
- SSYNC();
-}
-
-/* Caculate the SPI_BAUD register value based on input HZ */
-static u16
-bfin_sport_hz_to_spi_baud(u32 speed_hz)
-{
- u_long clk, sclk = get_sclk();
- int div = (sclk / (2 * speed_hz)) - 1;
-
- if (div < 0)
- div = 0;
-
- clk = sclk / (2 * (div + 1));
-
- if (clk > speed_hz)
- div++;
-
- return div;
-}
-
-/* Chip select operation functions for cs_change flag */
-static void
-bfin_sport_spi_cs_active(struct bfin_sport_spi_slave_data *chip)
-{
- gpio_direction_output(chip->cs_gpio, 0);
-}
-
-static void
-bfin_sport_spi_cs_deactive(struct bfin_sport_spi_slave_data *chip)
-{
- gpio_direction_output(chip->cs_gpio, 1);
- /* Move delay here for consistency */
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
-}
-
-static void
-bfin_sport_spi_stat_poll_complete(struct bfin_sport_spi_master_data *drv_data)
-{
- unsigned long timeout = jiffies + HZ;
- while (!(bfin_read(&drv_data->regs->stat) & RXNE)) {
- if (!time_before(jiffies, timeout))
- break;
- }
-}
-
-static void
-bfin_sport_spi_u8_writer(struct bfin_sport_spi_master_data *drv_data)
-{
- u16 dummy;
-
- while (drv_data->tx < drv_data->tx_end) {
- bfin_write(&drv_data->regs->tx16, *drv_data->tx8++);
- bfin_sport_spi_stat_poll_complete(drv_data);
- dummy = bfin_read(&drv_data->regs->rx16);
- }
-}
-
-static void
-bfin_sport_spi_u8_reader(struct bfin_sport_spi_master_data *drv_data)
-{
- u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tx16, tx_val);
- bfin_sport_spi_stat_poll_complete(drv_data);
- *drv_data->rx8++ = bfin_read(&drv_data->regs->rx16);
- }
-}
-
-static void
-bfin_sport_spi_u8_duplex(struct bfin_sport_spi_master_data *drv_data)
-{
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tx16, *drv_data->tx8++);
- bfin_sport_spi_stat_poll_complete(drv_data);
- *drv_data->rx8++ = bfin_read(&drv_data->regs->rx16);
- }
-}
-
-static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u8 = {
- .write = bfin_sport_spi_u8_writer,
- .read = bfin_sport_spi_u8_reader,
- .duplex = bfin_sport_spi_u8_duplex,
-};
-
-static void
-bfin_sport_spi_u16_writer(struct bfin_sport_spi_master_data *drv_data)
-{
- u16 dummy;
-
- while (drv_data->tx < drv_data->tx_end) {
- bfin_write(&drv_data->regs->tx16, *drv_data->tx16++);
- bfin_sport_spi_stat_poll_complete(drv_data);
- dummy = bfin_read(&drv_data->regs->rx16);
- }
-}
-
-static void
-bfin_sport_spi_u16_reader(struct bfin_sport_spi_master_data *drv_data)
-{
- u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tx16, tx_val);
- bfin_sport_spi_stat_poll_complete(drv_data);
- *drv_data->rx16++ = bfin_read(&drv_data->regs->rx16);
- }
-}
-
-static void
-bfin_sport_spi_u16_duplex(struct bfin_sport_spi_master_data *drv_data)
-{
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tx16, *drv_data->tx16++);
- bfin_sport_spi_stat_poll_complete(drv_data);
- *drv_data->rx16++ = bfin_read(&drv_data->regs->rx16);
- }
-}
-
-static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u16 = {
- .write = bfin_sport_spi_u16_writer,
- .read = bfin_sport_spi_u16_reader,
- .duplex = bfin_sport_spi_u16_duplex,
-};
-
-/* stop controller and re-config current chip */
-static void
-bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
-{
- struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
-
- bfin_sport_spi_disable(drv_data);
- dev_dbg(drv_data->dev, "restoring spi ctl state\n");
-
- bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
- bfin_write(&drv_data->regs->tclkdiv, chip->baud);
- SSYNC();
-
- bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
- SSYNC();
-
- bfin_sport_spi_cs_active(chip);
-}
-
-/* test if there is more transfer to be done */
-static enum bfin_sport_spi_state
-bfin_sport_spi_next_transfer(struct bfin_sport_spi_master_data *drv_data)
-{
- struct spi_message *msg = drv_data->cur_msg;
- struct spi_transfer *trans = drv_data->cur_transfer;
-
- /* Move to next transfer */
- if (trans->transfer_list.next != &msg->transfers) {
- drv_data->cur_transfer =
- list_entry(trans->transfer_list.next,
- struct spi_transfer, transfer_list);
- return RUNNING_STATE;
- }
-
- return DONE_STATE;
-}
-
-/*
- * caller already set message->status;
- * dma and pio irqs are blocked give finished message back
- */
-static void
-bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data)
-{
- struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
- unsigned long flags;
- struct spi_message *msg;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- msg = drv_data->cur_msg;
- drv_data->state = START_STATE;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- drv_data->cur_chip = NULL;
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- if (!drv_data->cs_change)
- bfin_sport_spi_cs_deactive(chip);
-
- if (msg->complete)
- msg->complete(msg->context);
-}
-
-static irqreturn_t
-sport_err_handler(int irq, void *dev_id)
-{
- struct bfin_sport_spi_master_data *drv_data = dev_id;
- u16 status;
-
- dev_dbg(drv_data->dev, "%s enter\n", __func__);
- status = bfin_read(&drv_data->regs->stat) & (TOVF | TUVF | ROVF | RUVF);
-
- if (status) {
- bfin_write(&drv_data->regs->stat, status);
- SSYNC();
-
- bfin_sport_spi_disable(drv_data);
- dev_err(drv_data->dev, "status error:%s%s%s%s\n",
- status & TOVF ? " TOVF" : "",
- status & TUVF ? " TUVF" : "",
- status & ROVF ? " ROVF" : "",
- status & RUVF ? " RUVF" : "");
- }
-
- return IRQ_HANDLED;
-}
-
-static void
-bfin_sport_spi_pump_transfers(unsigned long data)
-{
- struct bfin_sport_spi_master_data *drv_data = (void *)data;
- struct spi_message *message = NULL;
- struct spi_transfer *transfer = NULL;
- struct spi_transfer *previous = NULL;
- struct bfin_sport_spi_slave_data *chip = NULL;
- unsigned int bits_per_word;
- u32 tranf_success = 1;
- u32 transfer_speed;
- u8 full_duplex = 0;
-
- /* Get current state information */
- message = drv_data->cur_msg;
- transfer = drv_data->cur_transfer;
- chip = drv_data->cur_chip;
-
- if (transfer->speed_hz)
- transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
- else
- transfer_speed = chip->baud;
- bfin_write(&drv_data->regs->tclkdiv, transfer_speed);
- SSYNC();
-
- /*
- * if msg is error or done, report it back using complete() callback
- */
-
- /* Handle for abort */
- if (drv_data->state == ERROR_STATE) {
- dev_dbg(drv_data->dev, "transfer: we've hit an error\n");
- message->status = -EIO;
- bfin_sport_spi_giveback(drv_data);
- return;
- }
-
- /* Handle end of message */
- if (drv_data->state == DONE_STATE) {
- dev_dbg(drv_data->dev, "transfer: all done!\n");
- message->status = 0;
- bfin_sport_spi_giveback(drv_data);
- return;
- }
-
- /* Delay if requested at end of transfer */
- if (drv_data->state == RUNNING_STATE) {
- dev_dbg(drv_data->dev, "transfer: still running ...\n");
- previous = list_entry(transfer->transfer_list.prev,
- struct spi_transfer, transfer_list);
- if (previous->delay_usecs)
- udelay(previous->delay_usecs);
- }
-
- if (transfer->len == 0) {
- /* Move to next transfer of this msg */
- drv_data->state = bfin_sport_spi_next_transfer(drv_data);
- /* Schedule next transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
- }
-
- if (transfer->tx_buf != NULL) {
- drv_data->tx = (void *)transfer->tx_buf;
- drv_data->tx_end = drv_data->tx + transfer->len;
- dev_dbg(drv_data->dev, "tx_buf is %p, tx_end is %p\n",
- transfer->tx_buf, drv_data->tx_end);
- } else
- drv_data->tx = NULL;
-
- if (transfer->rx_buf != NULL) {
- full_duplex = transfer->tx_buf != NULL;
- drv_data->rx = transfer->rx_buf;
- drv_data->rx_end = drv_data->rx + transfer->len;
- dev_dbg(drv_data->dev, "rx_buf is %p, rx_end is %p\n",
- transfer->rx_buf, drv_data->rx_end);
- } else
- drv_data->rx = NULL;
-
- drv_data->cs_change = transfer->cs_change;
-
- /* Bits per word setup */
- bits_per_word = transfer->bits_per_word ? :
- message->spi->bits_per_word ? : 8;
- if (bits_per_word % 16 == 0)
- drv_data->ops = &bfin_sport_transfer_ops_u16;
- else
- drv_data->ops = &bfin_sport_transfer_ops_u8;
- bfin_write(&drv_data->regs->tcr2, bits_per_word - 1);
- bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1);
- bfin_write(&drv_data->regs->rcr2, bits_per_word - 1);
-
- drv_data->state = RUNNING_STATE;
-
- if (drv_data->cs_change)
- bfin_sport_spi_cs_active(chip);
-
- dev_dbg(drv_data->dev,
- "now pumping a transfer: width is %d, len is %d\n",
- bits_per_word, transfer->len);
-
- /* PIO mode write then read */
- dev_dbg(drv_data->dev, "doing IO transfer\n");
-
- bfin_sport_spi_enable(drv_data);
- if (full_duplex) {
- /* full duplex mode */
- BUG_ON((drv_data->tx_end - drv_data->tx) !=
- (drv_data->rx_end - drv_data->rx));
- drv_data->ops->duplex(drv_data);
-
- if (drv_data->tx != drv_data->tx_end)
- tranf_success = 0;
- } else if (drv_data->tx != NULL) {
- /* write only half duplex */
-
- drv_data->ops->write(drv_data);
-
- if (drv_data->tx != drv_data->tx_end)
- tranf_success = 0;
- } else if (drv_data->rx != NULL) {
- /* read only half duplex */
-
- drv_data->ops->read(drv_data);
- if (drv_data->rx != drv_data->rx_end)
- tranf_success = 0;
- }
- bfin_sport_spi_disable(drv_data);
-
- if (!tranf_success) {
- dev_dbg(drv_data->dev, "IO write error!\n");
- drv_data->state = ERROR_STATE;
- } else {
- /* Update total byte transfered */
- message->actual_length += transfer->len;
- /* Move to next transfer of this msg */
- drv_data->state = bfin_sport_spi_next_transfer(drv_data);
- if (drv_data->cs_change)
- bfin_sport_spi_cs_deactive(chip);
- }
-
- /* Schedule next transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
-}
-
-/* pop a msg from queue and kick off real transfer */
-static void
-bfin_sport_spi_pump_messages(struct work_struct *work)
-{
- struct bfin_sport_spi_master_data *drv_data;
- unsigned long flags;
- struct spi_message *next_msg;
-
- drv_data = container_of(work, struct bfin_sport_spi_master_data, pump_messages);
-
- /* Lock queue and check for queue work */
- spin_lock_irqsave(&drv_data->lock, flags);
- if (list_empty(&drv_data->queue) || !drv_data->run) {
- /* pumper kicked off but no work to do */
- drv_data->busy = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Make sure we are not already running a message */
- if (drv_data->cur_msg) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Extract head of queue */
- next_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
-
- drv_data->cur_msg = next_msg;
-
- /* Setup the SSP using the per chip configuration */
- drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-
- list_del_init(&drv_data->cur_msg->queue);
-
- /* Initialize message state */
- drv_data->cur_msg->state = START_STATE;
- drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
- struct spi_transfer, transfer_list);
- bfin_sport_spi_restore_state(drv_data);
- dev_dbg(drv_data->dev, "got a message to pump, "
- "state is set to: baud %d, cs_gpio %i, ctl 0x%x\n",
- drv_data->cur_chip->baud, drv_data->cur_chip->cs_gpio,
- drv_data->cur_chip->ctl_reg);
-
- dev_dbg(drv_data->dev,
- "the first transfer len is %d\n",
- drv_data->cur_transfer->len);
-
- /* Mark as busy and launch transfers */
- tasklet_schedule(&drv_data->pump_transfers);
-
- drv_data->busy = 1;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-/*
- * got a msg to transfer, queue it in drv_data->queue.
- * And kick off message pumper
- */
-static int
-bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct bfin_sport_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (!drv_data->run) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -ESHUTDOWN;
- }
-
- msg->actual_length = 0;
- msg->status = -EINPROGRESS;
- msg->state = START_STATE;
-
- dev_dbg(&spi->dev, "adding an msg in transfer()\n");
- list_add_tail(&msg->queue, &drv_data->queue);
-
- if (drv_data->run && !drv_data->busy)
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return 0;
-}
-
-/* Called every time common spi devices change state */
-static int
-bfin_sport_spi_setup(struct spi_device *spi)
-{
- struct bfin_sport_spi_slave_data *chip, *first = NULL;
- int ret;
-
- /* Only alloc (or use chip_info) on first setup */
- chip = spi_get_ctldata(spi);
- if (chip == NULL) {
- struct bfin5xx_spi_chip *chip_info;
-
- chip = first = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- /* platform chip_info isn't required */
- chip_info = spi->controller_data;
- if (chip_info) {
- /*
- * DITFS and TDTYPE are only thing we don't set, but
- * they probably shouldn't be changed by people.
- */
- if (chip_info->ctl_reg || chip_info->enable_dma) {
- ret = -EINVAL;
- dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields");
- goto error;
- }
- chip->cs_chg_udelay = chip_info->cs_chg_udelay;
- chip->idle_tx_val = chip_info->idle_tx_val;
- }
- }
-
- if (spi->bits_per_word % 8) {
- dev_err(&spi->dev, "%d bits_per_word is not supported\n",
- spi->bits_per_word);
- ret = -EINVAL;
- goto error;
- }
-
- /* translate common spi framework into our register
- * following configure contents are same for tx and rx.
- */
-
- if (spi->mode & SPI_CPHA)
- chip->ctl_reg &= ~TCKFE;
- else
- chip->ctl_reg |= TCKFE;
-
- if (spi->mode & SPI_LSB_FIRST)
- chip->ctl_reg |= TLSBIT;
- else
- chip->ctl_reg &= ~TLSBIT;
-
- /* Sport in master mode */
- chip->ctl_reg |= ITCLK | ITFS | TFSR | LATFS | LTFS;
-
- chip->baud = bfin_sport_hz_to_spi_baud(spi->max_speed_hz);
-
- chip->cs_gpio = spi->chip_select;
- ret = gpio_request(chip->cs_gpio, spi->modalias);
- if (ret)
- goto error;
-
- dev_dbg(&spi->dev, "setup spi chip %s, width is %d\n",
- spi->modalias, spi->bits_per_word);
- dev_dbg(&spi->dev, "ctl_reg is 0x%x, GPIO is %i\n",
- chip->ctl_reg, spi->chip_select);
-
- spi_set_ctldata(spi, chip);
-
- bfin_sport_spi_cs_deactive(chip);
-
- return ret;
-
- error:
- kfree(first);
- return ret;
-}
-
-/*
- * callback for spi framework.
- * clean driver specific data
- */
-static void
-bfin_sport_spi_cleanup(struct spi_device *spi)
-{
- struct bfin_sport_spi_slave_data *chip = spi_get_ctldata(spi);
-
- if (!chip)
- return;
-
- gpio_free(chip->cs_gpio);
-
- kfree(chip);
-}
-
-static int
-bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data)
-{
- INIT_LIST_HEAD(&drv_data->queue);
- spin_lock_init(&drv_data->lock);
-
- drv_data->run = false;
- drv_data->busy = 0;
-
- /* init transfer tasklet */
- tasklet_init(&drv_data->pump_transfers,
- bfin_sport_spi_pump_transfers, (unsigned long)drv_data);
-
- /* init messages workqueue */
- INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages);
- drv_data->workqueue =
- create_singlethread_workqueue(dev_name(drv_data->master->dev.parent));
- if (drv_data->workqueue == NULL)
- return -EBUSY;
-
- return 0;
-}
-
-static int
-bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (drv_data->run || drv_data->busy) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -EBUSY;
- }
-
- drv_data->run = true;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- drv_data->cur_chip = NULL;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- return 0;
-}
-
-static inline int
-bfin_sport_spi_stop_queue(struct bfin_sport_spi_master_data *drv_data)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- /*
- * This is a bit lame, but is optimized for the common execution path.
- * A wait_queue on the drv_data->busy could be used, but then the common
- * execution path (pump_messages) would be required to call wake_up or
- * friends on every SPI message. Do this instead
- */
- drv_data->run = false;
- while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- msleep(10);
- spin_lock_irqsave(&drv_data->lock, flags);
- }
-
- if (!list_empty(&drv_data->queue) || drv_data->busy)
- status = -EBUSY;
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return status;
-}
-
-static inline int
-bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data)
-{
- int status;
-
- status = bfin_sport_spi_stop_queue(drv_data);
- if (status)
- return status;
-
- destroy_workqueue(drv_data->workqueue);
-
- return 0;
-}
-
-static int __devinit
-bfin_sport_spi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct bfin5xx_spi_master *platform_info;
- struct spi_master *master;
- struct resource *res, *ires;
- struct bfin_sport_spi_master_data *drv_data;
- int status;
-
- platform_info = dev->platform_data;
-
- /* Allocate master with space for drv_data */
- master = spi_alloc_master(dev, sizeof(*master) + 16);
- if (!master) {
- dev_err(dev, "cannot alloc spi_master\n");
- return -ENOMEM;
- }
-
- drv_data = spi_master_get_devdata(master);
- drv_data->master = master;
- drv_data->dev = dev;
- drv_data->pin_req = platform_info->pin_req;
-
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
- master->bus_num = pdev->id;
- master->num_chipselect = platform_info->num_chipselect;
- master->cleanup = bfin_sport_spi_cleanup;
- master->setup = bfin_sport_spi_setup;
- master->transfer = bfin_sport_spi_transfer;
-
- /* Find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(dev, "cannot get IORESOURCE_MEM\n");
- status = -ENOENT;
- goto out_error_get_res;
- }
-
- drv_data->regs = ioremap(res->start, resource_size(res));
- if (drv_data->regs == NULL) {
- dev_err(dev, "cannot map registers\n");
- status = -ENXIO;
- goto out_error_ioremap;
- }
-
- ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!ires) {
- dev_err(dev, "cannot get IORESOURCE_IRQ\n");
- status = -ENODEV;
- goto out_error_get_ires;
- }
- drv_data->err_irq = ires->start;
-
- /* Initial and start queue */
- status = bfin_sport_spi_init_queue(drv_data);
- if (status) {
- dev_err(dev, "problem initializing queue\n");
- goto out_error_queue_alloc;
- }
-
- status = bfin_sport_spi_start_queue(drv_data);
- if (status) {
- dev_err(dev, "problem starting queue\n");
- goto out_error_queue_alloc;
- }
-
- status = request_irq(drv_data->err_irq, sport_err_handler,
- 0, "sport_spi_err", drv_data);
- if (status) {
- dev_err(dev, "unable to request sport err irq\n");
- goto out_error_irq;
- }
-
- status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
- if (status) {
- dev_err(dev, "requesting peripherals failed\n");
- goto out_error_peripheral;
- }
-
- /* Register with the SPI framework */
- platform_set_drvdata(pdev, drv_data);
- status = spi_register_master(master);
- if (status) {
- dev_err(dev, "problem registering spi master\n");
- goto out_error_master;
- }
-
- dev_info(dev, "%s, regs_base@%p\n", DRV_DESC, drv_data->regs);
- return 0;
-
- out_error_master:
- peripheral_free_list(drv_data->pin_req);
- out_error_peripheral:
- free_irq(drv_data->err_irq, drv_data);
- out_error_irq:
- out_error_queue_alloc:
- bfin_sport_spi_destroy_queue(drv_data);
- out_error_get_ires:
- iounmap(drv_data->regs);
- out_error_ioremap:
- out_error_get_res:
- spi_master_put(master);
-
- return status;
-}
-
-/* stop hardware and remove the driver */
-static int __devexit
-bfin_sport_spi_remove(struct platform_device *pdev)
-{
- struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
- int status = 0;
-
- if (!drv_data)
- return 0;
-
- /* Remove the queue */
- status = bfin_sport_spi_destroy_queue(drv_data);
- if (status)
- return status;
-
- /* Disable the SSP at the peripheral and SOC level */
- bfin_sport_spi_disable(drv_data);
-
- /* Disconnect from the SPI framework */
- spi_unregister_master(drv_data->master);
-
- peripheral_free_list(drv_data->pin_req);
-
- /* Prevent double remove */
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
- int status;
-
- status = bfin_sport_spi_stop_queue(drv_data);
- if (status)
- return status;
-
- /* stop hardware */
- bfin_sport_spi_disable(drv_data);
-
- return status;
-}
-
-static int
-bfin_sport_spi_resume(struct platform_device *pdev)
-{
- struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
- int status;
-
- /* Enable the SPI interface */
- bfin_sport_spi_enable(drv_data);
-
- /* Start the queue running */
- status = bfin_sport_spi_start_queue(drv_data);
- if (status)
- dev_err(drv_data->dev, "problem resuming queue\n");
-
- return status;
-}
-#else
-# define bfin_sport_spi_suspend NULL
-# define bfin_sport_spi_resume NULL
-#endif
-
-static struct platform_driver bfin_sport_spi_driver = {
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
- .probe = bfin_sport_spi_probe,
- .remove = __devexit_p(bfin_sport_spi_remove),
- .suspend = bfin_sport_spi_suspend,
- .resume = bfin_sport_spi_resume,
-};
-module_platform_driver(bfin_sport_spi_driver);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-bfin5xx.c b/ANDROID_3.4.5/drivers/spi/spi-bfin5xx.c
deleted file mode 100644
index 9bb4d4af..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-bfin5xx.c
+++ /dev/null
@@ -1,1493 +0,0 @@
-/*
- * Blackfin On-Chip SPI Driver
- *
- * Copyright 2004-2010 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-
-#include <asm/dma.h>
-#include <asm/portmux.h>
-#include <asm/bfin5xx_spi.h>
-#include <asm/cacheflush.h>
-
-#define DRV_NAME "bfin-spi"
-#define DRV_AUTHOR "Bryan Wu, Luke Yang"
-#define DRV_DESC "Blackfin on-chip SPI Controller Driver"
-#define DRV_VERSION "1.0"
-
-MODULE_AUTHOR(DRV_AUTHOR);
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_LICENSE("GPL");
-
-#define START_STATE ((void *)0)
-#define RUNNING_STATE ((void *)1)
-#define DONE_STATE ((void *)2)
-#define ERROR_STATE ((void *)-1)
-
-struct bfin_spi_master_data;
-
-struct bfin_spi_transfer_ops {
- void (*write) (struct bfin_spi_master_data *);
- void (*read) (struct bfin_spi_master_data *);
- void (*duplex) (struct bfin_spi_master_data *);
-};
-
-struct bfin_spi_master_data {
- /* Driver model hookup */
- struct platform_device *pdev;
-
- /* SPI framework hookup */
- struct spi_master *master;
-
- /* Regs base of SPI controller */
- struct bfin_spi_regs __iomem *regs;
-
- /* Pin request list */
- u16 *pin_req;
-
- /* BFIN hookup */
- struct bfin5xx_spi_master *master_info;
-
- /* Driver message queue */
- struct workqueue_struct *workqueue;
- struct work_struct pump_messages;
- spinlock_t lock;
- struct list_head queue;
- int busy;
- bool running;
-
- /* Message Transfer pump */
- struct tasklet_struct pump_transfers;
-
- /* Current message transfer state info */
- struct spi_message *cur_msg;
- struct spi_transfer *cur_transfer;
- struct bfin_spi_slave_data *cur_chip;
- size_t len_in_bytes;
- size_t len;
- void *tx;
- void *tx_end;
- void *rx;
- void *rx_end;
-
- /* DMA stuffs */
- int dma_channel;
- int dma_mapped;
- int dma_requested;
- dma_addr_t rx_dma;
- dma_addr_t tx_dma;
-
- int irq_requested;
- int spi_irq;
-
- size_t rx_map_len;
- size_t tx_map_len;
- u8 n_bytes;
- u16 ctrl_reg;
- u16 flag_reg;
-
- int cs_change;
- const struct bfin_spi_transfer_ops *ops;
-};
-
-struct bfin_spi_slave_data {
- u16 ctl_reg;
- u16 baud;
- u16 flag;
-
- u8 chip_select_num;
- u8 enable_dma;
- u16 cs_chg_udelay; /* Some devices require > 255usec delay */
- u32 cs_gpio;
- u16 idle_tx_val;
- u8 pio_interrupt; /* use spi data irq */
- const struct bfin_spi_transfer_ops *ops;
-};
-
-static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
-{
- bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE);
-}
-
-static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
-{
- bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE);
-}
-
-/* Caculate the SPI_BAUD register value based on input HZ */
-static u16 hz_to_spi_baud(u32 speed_hz)
-{
- u_long sclk = get_sclk();
- u16 spi_baud = (sclk / (2 * speed_hz));
-
- if ((sclk % (2 * speed_hz)) > 0)
- spi_baud++;
-
- if (spi_baud < MIN_SPI_BAUD_VAL)
- spi_baud = MIN_SPI_BAUD_VAL;
-
- return spi_baud;
-}
-
-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 (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit)
- cpu_relax();
-
- bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
-
- return limit;
-}
-
-/* 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))
- 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))
- 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)
- udelay(chip->cs_chg_udelay);
-}
-
-/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
-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)
- 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)
- bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8));
-}
-
-/* stop controller and re-config current chip*/
-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 */
- 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 */
- 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);
-}
-
-/* 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) bfin_read(&drv_data->regs->rdbr);
-}
-
-static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
-{
- /* clear RXS (we check for RXS inside the loop) */
- bfin_spi_dummy_read(drv_data);
-
- while (drv_data->tx < drv_data->tx_end) {
- bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
- /* wait until transfer finished.
- checking SPIF or TXS may not guarantee transfer completion */
- while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
- cpu_relax();
- /* discard RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
- }
-}
-
-static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
-{
- u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
- /* discard old RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
-
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tdbr, tx_val);
- while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
- cpu_relax();
- *(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
- }
-}
-
-static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
-{
- /* discard old RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
-
- while (drv_data->rx < drv_data->rx_end) {
- 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++) = bfin_read(&drv_data->regs->rdbr);
- }
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
- .write = bfin_spi_u8_writer,
- .read = bfin_spi_u8_reader,
- .duplex = bfin_spi_u8_duplex,
-};
-
-static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
-{
- /* clear RXS (we check for RXS inside the loop) */
- bfin_spi_dummy_read(drv_data);
-
- while (drv_data->tx < drv_data->tx_end) {
- 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 (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
- cpu_relax();
- /* discard RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
- }
-}
-
-static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
-{
- u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
- /* discard old RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
-
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tdbr, tx_val);
- while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
- cpu_relax();
- *(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
- drv_data->rx += 2;
- }
-}
-
-static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
-{
- /* discard old RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
-
- while (drv_data->rx < drv_data->rx_end) {
- bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
- drv_data->tx += 2;
- while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
- cpu_relax();
- *(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
- drv_data->rx += 2;
- }
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
- .write = bfin_spi_u16_writer,
- .read = bfin_spi_u16_reader,
- .duplex = bfin_spi_u16_duplex,
-};
-
-/* test if there is more transfer to be done */
-static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data)
-{
- struct spi_message *msg = drv_data->cur_msg;
- struct spi_transfer *trans = drv_data->cur_transfer;
-
- /* Move to next transfer */
- if (trans->transfer_list.next != &msg->transfers) {
- drv_data->cur_transfer =
- list_entry(trans->transfer_list.next,
- struct spi_transfer, transfer_list);
- return RUNNING_STATE;
- } else
- return DONE_STATE;
-}
-
-/*
- * caller already set message->status;
- * dma and pio irqs are blocked give finished message back
- */
-static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
-{
- struct bfin_spi_slave_data *chip = drv_data->cur_chip;
- struct spi_transfer *last_transfer;
- unsigned long flags;
- struct spi_message *msg;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- msg = drv_data->cur_msg;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- drv_data->cur_chip = NULL;
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- last_transfer = list_entry(msg->transfers.prev,
- struct spi_transfer, transfer_list);
-
- msg->state = NULL;
-
- if (!drv_data->cs_change)
- bfin_spi_cs_deactive(drv_data, chip);
-
- /* Not stop spi in autobuffer mode */
- if (drv_data->tx_dma != 0xFFFF)
- bfin_spi_disable(drv_data);
-
- if (msg->complete)
- msg->complete(msg->context);
-}
-
-/* spi data irq handler */
-static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
-{
- struct bfin_spi_master_data *drv_data = dev_id;
- struct bfin_spi_slave_data *chip = drv_data->cur_chip;
- struct spi_message *msg = drv_data->cur_msg;
- int n_bytes = drv_data->n_bytes;
- int loop = 0;
-
- /* wait until transfer finished. */
- while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
- cpu_relax();
-
- if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
- (drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) {
- /* last read */
- if (drv_data->rx) {
- dev_dbg(&drv_data->pdev->dev, "last read\n");
- if (!(n_bytes % 2)) {
- u16 *buf = (u16 *)drv_data->rx;
- for (loop = 0; loop < n_bytes / 2; loop++)
- *buf++ = bfin_read(&drv_data->regs->rdbr);
- } else {
- u8 *buf = (u8 *)drv_data->rx;
- for (loop = 0; loop < n_bytes; loop++)
- *buf++ = bfin_read(&drv_data->regs->rdbr);
- }
- drv_data->rx += n_bytes;
- }
-
- msg->actual_length += drv_data->len_in_bytes;
- if (drv_data->cs_change)
- bfin_spi_cs_deactive(drv_data, chip);
- /* Move to next transfer */
- msg->state = bfin_spi_next_transfer(drv_data);
-
- disable_irq_nosync(drv_data->spi_irq);
-
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
- return IRQ_HANDLED;
- }
-
- if (drv_data->rx && drv_data->tx) {
- /* duplex */
- dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
- if (!(n_bytes % 2)) {
- u16 *buf = (u16 *)drv_data->rx;
- u16 *buf2 = (u16 *)drv_data->tx;
- for (loop = 0; loop < n_bytes / 2; loop++) {
- *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++ = bfin_read(&drv_data->regs->rdbr);
- bfin_write(&drv_data->regs->tdbr, *buf2++);
- }
- }
- } else if (drv_data->rx) {
- /* read */
- dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
- if (!(n_bytes % 2)) {
- u16 *buf = (u16 *)drv_data->rx;
- for (loop = 0; loop < n_bytes / 2; loop++) {
- *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++ = bfin_read(&drv_data->regs->rdbr);
- bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
- }
- }
- } else if (drv_data->tx) {
- /* write */
- dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
- if (!(n_bytes % 2)) {
- u16 *buf = (u16 *)drv_data->tx;
- for (loop = 0; loop < n_bytes / 2; loop++) {
- 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++) {
- bfin_read(&drv_data->regs->rdbr);
- bfin_write(&drv_data->regs->tdbr, *buf++);
- }
- }
- }
-
- if (drv_data->tx)
- drv_data->tx += n_bytes;
- if (drv_data->rx)
- drv_data->rx += n_bytes;
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
-{
- struct bfin_spi_master_data *drv_data = dev_id;
- struct bfin_spi_slave_data *chip = drv_data->cur_chip;
- struct spi_message *msg = drv_data->cur_msg;
- unsigned long timeout;
- unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
- 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 = bfin_read(&drv_data->regs->ctl);
- /* discard old RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
- 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);
-
- /*
- * wait for the last transaction shifted out. HRM states:
- * at this point there may still be data in the SPI DMA FIFO waiting
- * to be transmitted ... software needs to poll TXS in the SPI_STAT
- * register until it goes low for 2 successive reads
- */
- if (drv_data->tx != NULL) {
- 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, bfin_read(&drv_data->regs->stat));
-
- timeout = jiffies + HZ;
- 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;
- } else
- cpu_relax();
-
- if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) {
- msg->state = ERROR_STATE;
- dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
- } else {
- msg->actual_length += drv_data->len_in_bytes;
-
- if (drv_data->cs_change)
- bfin_spi_cs_deactive(drv_data, chip);
-
- /* Move to next transfer */
- msg->state = bfin_spi_next_transfer(drv_data);
- }
-
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
-
- /* free the irq handler before next transfer */
- dev_dbg(&drv_data->pdev->dev,
- "disable dma channel irq%d\n",
- drv_data->dma_channel);
- dma_disable_irq_nosync(drv_data->dma_channel);
-
- return IRQ_HANDLED;
-}
-
-static void bfin_spi_pump_transfers(unsigned long data)
-{
- struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data;
- struct spi_message *message = NULL;
- struct spi_transfer *transfer = NULL;
- struct spi_transfer *previous = NULL;
- struct bfin_spi_slave_data *chip = NULL;
- unsigned int bits_per_word;
- u16 cr, cr_width, dma_width, dma_config;
- u32 tranf_success = 1;
- u8 full_duplex = 0;
-
- /* Get current state information */
- message = drv_data->cur_msg;
- transfer = drv_data->cur_transfer;
- chip = drv_data->cur_chip;
-
- /*
- * if msg is error or done, report it back using complete() callback
- */
-
- /* Handle for abort */
- if (message->state == ERROR_STATE) {
- dev_dbg(&drv_data->pdev->dev, "transfer: we've hit an error\n");
- message->status = -EIO;
- bfin_spi_giveback(drv_data);
- return;
- }
-
- /* Handle end of message */
- if (message->state == DONE_STATE) {
- dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
- message->status = 0;
- bfin_spi_flush(drv_data);
- bfin_spi_giveback(drv_data);
- return;
- }
-
- /* Delay if requested at end of transfer */
- if (message->state == RUNNING_STATE) {
- dev_dbg(&drv_data->pdev->dev, "transfer: still running ...\n");
- previous = list_entry(transfer->transfer_list.prev,
- struct spi_transfer, transfer_list);
- if (previous->delay_usecs)
- udelay(previous->delay_usecs);
- }
-
- /* Flush any existing transfers that may be sitting in the hardware */
- if (bfin_spi_flush(drv_data) == 0) {
- dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
- message->status = -EIO;
- bfin_spi_giveback(drv_data);
- return;
- }
-
- if (transfer->len == 0) {
- /* Move to next transfer of this msg */
- message->state = bfin_spi_next_transfer(drv_data);
- /* Schedule next transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
- return;
- }
-
- if (transfer->tx_buf != NULL) {
- drv_data->tx = (void *)transfer->tx_buf;
- drv_data->tx_end = drv_data->tx + transfer->len;
- dev_dbg(&drv_data->pdev->dev, "tx_buf is %p, tx_end is %p\n",
- transfer->tx_buf, drv_data->tx_end);
- } else {
- drv_data->tx = NULL;
- }
-
- if (transfer->rx_buf != NULL) {
- full_duplex = transfer->tx_buf != NULL;
- drv_data->rx = transfer->rx_buf;
- drv_data->rx_end = drv_data->rx + transfer->len;
- dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n",
- transfer->rx_buf, drv_data->rx_end);
- } else {
- drv_data->rx = NULL;
- }
-
- drv_data->rx_dma = transfer->rx_dma;
- drv_data->tx_dma = transfer->tx_dma;
- drv_data->len_in_bytes = transfer->len;
- drv_data->cs_change = transfer->cs_change;
-
- /* Bits per word setup */
- 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 % 8 == 0) {
- drv_data->n_bytes = bits_per_word/8;
- drv_data->len = transfer->len;
- cr_width = 0;
- drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
- } else {
- dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
- message->status = -EINVAL;
- bfin_spi_giveback(drv_data);
- return;
- }
- cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
- cr |= cr_width;
- 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",
- drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8);
-
- message->state = RUNNING_STATE;
- dma_config = 0;
-
- /* Speed setup (surely valid because already checked) */
- if (transfer->speed_hz)
- bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
- else
- bfin_write(&drv_data->regs->baud, chip->baud);
-
- bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
- bfin_spi_cs_active(drv_data, chip);
-
- dev_dbg(&drv_data->pdev->dev,
- "now pumping a transfer: width is %d, len is %d\n",
- cr_width, transfer->len);
-
- /*
- * Try to map dma buffer and do a dma transfer. If successful use,
- * different way to r/w according to the enable_dma settings and if
- * we are not doing a full duplex transfer (since the hardware does
- * not support full duplex DMA transfers).
- */
- if (!full_duplex && drv_data->cur_chip->enable_dma
- && drv_data->len > 6) {
-
- unsigned long dma_start_addr, flags;
-
- disable_dma(drv_data->dma_channel);
- clear_dma_irqstat(drv_data->dma_channel);
-
- /* config dma channel */
- dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
- set_dma_x_count(drv_data->dma_channel, drv_data->len);
- if (cr_width == BIT_CTL_WORDSIZE) {
- set_dma_x_modify(drv_data->dma_channel, 2);
- dma_width = WDSIZE_16;
- } else {
- set_dma_x_modify(drv_data->dma_channel, 1);
- dma_width = WDSIZE_8;
- }
-
- /* poll for SPI completion before start */
- while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
- cpu_relax();
-
- /* dirty hack for autobuffer DMA mode */
- if (drv_data->tx_dma == 0xFFFF) {
- dev_dbg(&drv_data->pdev->dev,
- "doing autobuffer DMA out.\n");
-
- /* no irq in autobuffer mode */
- dma_config =
- (DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
- set_dma_config(drv_data->dma_channel, dma_config);
- set_dma_start_addr(drv_data->dma_channel,
- (unsigned long)drv_data->tx);
- enable_dma(drv_data->dma_channel);
-
- /* start SPI transfer */
- bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX);
-
- /* just return here, there can only be one transfer
- * in this mode
- */
- message->status = 0;
- bfin_spi_giveback(drv_data);
- return;
- }
-
- /* In dma mode, rx or tx must be NULL in one transfer */
- dma_config = (RESTART | dma_width | DI_EN);
- if (drv_data->rx != NULL) {
- /* set transfer mode, and enable SPI */
- dev_dbg(&drv_data->pdev->dev, "doing DMA in to %p (size %zx)\n",
- drv_data->rx, drv_data->len_in_bytes);
-
- /* invalidate caches, if needed */
- if (bfin_addr_dcacheable((unsigned long) drv_data->rx))
- invalidate_dcache_range((unsigned long) drv_data->rx,
- (unsigned long) (drv_data->rx +
- drv_data->len_in_bytes));
-
- dma_config |= WNR;
- dma_start_addr = (unsigned long)drv_data->rx;
- cr |= BIT_CTL_TIMOD_DMA_RX | BIT_CTL_SENDOPT;
-
- } else if (drv_data->tx != NULL) {
- dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
-
- /* flush caches, if needed */
- if (bfin_addr_dcacheable((unsigned long) drv_data->tx))
- flush_dcache_range((unsigned long) drv_data->tx,
- (unsigned long) (drv_data->tx +
- drv_data->len_in_bytes));
-
- dma_start_addr = (unsigned long)drv_data->tx;
- cr |= BIT_CTL_TIMOD_DMA_TX;
-
- } else
- BUG();
-
- /* oh man, here there be monsters ... and i dont mean the
- * fluffy cute ones from pixar, i mean the kind that'll eat
- * your data, kick your dog, and love it all. do *not* try
- * and change these lines unless you (1) heavily test DMA
- * with SPI flashes on a loaded system (e.g. ping floods),
- * (2) know just how broken the DMA engine interaction with
- * the SPI peripheral is, and (3) have someone else to blame
- * when you screw it all up anyways.
- */
- set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
- set_dma_config(drv_data->dma_channel, dma_config);
- local_irq_save(flags);
- SSYNC();
- bfin_write(&drv_data->regs->ctl, cr);
- enable_dma(drv_data->dma_channel);
- dma_enable_irq(drv_data->dma_channel);
- local_irq_restore(flags);
-
- return;
- }
-
- /*
- * We always use SPI_WRITE mode (transfer starts with TDBR write).
- * SPI_READ mode (transfer starts with RDBR read) seems to have
- * problems with setting up the output value in TDBR prior to the
- * start of the transfer.
- */
- bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD);
-
- if (chip->pio_interrupt) {
- /* SPI irq should have been disabled by now */
-
- /* discard old RX data and clear RXS */
- bfin_spi_dummy_read(drv_data);
-
- /* start transfer */
- if (drv_data->tx == NULL)
- 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++) {
- 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++)
- bfin_write(&drv_data->regs->tdbr, *buf++);
- }
-
- drv_data->tx += drv_data->n_bytes;
- }
-
- /* once TDBR is empty, interrupt is triggered */
- enable_irq(drv_data->spi_irq);
- return;
- }
-
- /* IO mode */
- dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
-
- if (full_duplex) {
- /* full duplex mode */
- BUG_ON((drv_data->tx_end - drv_data->tx) !=
- (drv_data->rx_end - drv_data->rx));
- dev_dbg(&drv_data->pdev->dev,
- "IO duplex: cr is 0x%x\n", cr);
-
- drv_data->ops->duplex(drv_data);
-
- if (drv_data->tx != drv_data->tx_end)
- tranf_success = 0;
- } else if (drv_data->tx != NULL) {
- /* write only half duplex */
- dev_dbg(&drv_data->pdev->dev,
- "IO write: cr is 0x%x\n", cr);
-
- drv_data->ops->write(drv_data);
-
- if (drv_data->tx != drv_data->tx_end)
- tranf_success = 0;
- } else if (drv_data->rx != NULL) {
- /* read only half duplex */
- dev_dbg(&drv_data->pdev->dev,
- "IO read: cr is 0x%x\n", cr);
-
- drv_data->ops->read(drv_data);
- if (drv_data->rx != drv_data->rx_end)
- tranf_success = 0;
- }
-
- if (!tranf_success) {
- dev_dbg(&drv_data->pdev->dev,
- "IO write error!\n");
- message->state = ERROR_STATE;
- } else {
- /* Update total byte transferred */
- message->actual_length += drv_data->len_in_bytes;
- /* Move to next transfer of this msg */
- message->state = bfin_spi_next_transfer(drv_data);
- if (drv_data->cs_change && message->state != DONE_STATE) {
- bfin_spi_flush(drv_data);
- bfin_spi_cs_deactive(drv_data, chip);
- }
- }
-
- /* Schedule next transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
-}
-
-/* pop a msg from queue and kick off real transfer */
-static void bfin_spi_pump_messages(struct work_struct *work)
-{
- struct bfin_spi_master_data *drv_data;
- unsigned long flags;
-
- drv_data = container_of(work, struct bfin_spi_master_data, pump_messages);
-
- /* Lock queue and check for queue work */
- spin_lock_irqsave(&drv_data->lock, flags);
- if (list_empty(&drv_data->queue) || !drv_data->running) {
- /* pumper kicked off but no work to do */
- drv_data->busy = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Make sure we are not already running a message */
- if (drv_data->cur_msg) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Extract head of queue */
- drv_data->cur_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
-
- /* Setup the SSP using the per chip configuration */
- drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
- bfin_spi_restore_state(drv_data);
-
- list_del_init(&drv_data->cur_msg->queue);
-
- /* Initial message state */
- drv_data->cur_msg->state = START_STATE;
- drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
- struct spi_transfer, transfer_list);
-
- dev_dbg(&drv_data->pdev->dev, "got a message to pump, "
- "state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
- drv_data->cur_chip->baud, drv_data->cur_chip->flag,
- drv_data->cur_chip->ctl_reg);
-
- dev_dbg(&drv_data->pdev->dev,
- "the first transfer len is %d\n",
- drv_data->cur_transfer->len);
-
- /* Mark as busy and launch transfers */
- tasklet_schedule(&drv_data->pump_transfers);
-
- drv_data->busy = 1;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-/*
- * got a msg to transfer, queue it in drv_data->queue.
- * And kick off message pumper
- */
-static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (!drv_data->running) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -ESHUTDOWN;
- }
-
- msg->actual_length = 0;
- msg->status = -EINPROGRESS;
- msg->state = START_STATE;
-
- dev_dbg(&spi->dev, "adding an msg in transfer() \n");
- list_add_tail(&msg->queue, &drv_data->queue);
-
- if (drv_data->running && !drv_data->busy)
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return 0;
-}
-
-#define MAX_SPI_SSEL 7
-
-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},
-
- {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
- P_SPI1_SSEL4, P_SPI1_SSEL5,
- P_SPI1_SSEL6, P_SPI1_SSEL7},
-
- {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
- P_SPI2_SSEL4, P_SPI2_SSEL5,
- P_SPI2_SSEL6, P_SPI2_SSEL7},
-};
-
-/* setup for devices (may be called multiple times -- not just first setup) */
-static int bfin_spi_setup(struct spi_device *spi)
-{
- struct bfin5xx_spi_chip *chip_info;
- struct bfin_spi_slave_data *chip = NULL;
- struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
- u16 bfin_ctl_reg;
- int ret = -EINVAL;
-
- /* Only alloc (or use chip_info) on first setup */
- chip_info = NULL;
- chip = spi_get_ctldata(spi);
- if (chip == NULL) {
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- dev_err(&spi->dev, "cannot allocate chip data\n");
- ret = -ENOMEM;
- goto error;
- }
-
- chip->enable_dma = 0;
- chip_info = spi->controller_data;
- }
-
- /* Let people set non-standard bits directly */
- bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO |
- BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ;
-
- /* chip_info isn't always needed */
- if (chip_info) {
- /* Make sure people stop trying to set fields via ctl_reg
- * when they should actually be using common SPI framework.
- * Currently we let through: WOM EMISO PSSE GM SZ.
- * Not sure if a user actually needs/uses any of these,
- * but let's assume (for now) they do.
- */
- if (chip_info->ctl_reg & ~bfin_ctl_reg) {
- dev_err(&spi->dev, "do not set bits in ctl_reg "
- "that the SPI framework manages\n");
- goto error;
- }
- chip->enable_dma = chip_info->enable_dma != 0
- && drv_data->master_info->enable_dma;
- chip->ctl_reg = chip_info->ctl_reg;
- chip->cs_chg_udelay = chip_info->cs_chg_udelay;
- chip->idle_tx_val = chip_info->idle_tx_val;
- chip->pio_interrupt = chip_info->pio_interrupt;
- } else {
- /* force a default base state */
- chip->ctl_reg &= bfin_ctl_reg;
- }
-
- if (spi->bits_per_word % 8) {
- dev_err(&spi->dev, "%d bits_per_word is not supported\n",
- spi->bits_per_word);
- goto error;
- }
-
- /* translate common spi framework into our register */
- if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
- dev_err(&spi->dev, "unsupported spi modes detected\n");
- goto error;
- }
- if (spi->mode & SPI_CPOL)
- chip->ctl_reg |= BIT_CTL_CPOL;
- if (spi->mode & SPI_CPHA)
- chip->ctl_reg |= BIT_CTL_CPHA;
- if (spi->mode & SPI_LSB_FIRST)
- chip->ctl_reg |= BIT_CTL_LSBF;
- /* we dont support running in slave mode (yet?) */
- chip->ctl_reg |= BIT_CTL_MASTER;
-
- /*
- * Notice: for blackfin, the speed_hz is the value of register
- * SPI_BAUD, not the real baudrate
- */
- chip->baud = hz_to_spi_baud(spi->max_speed_hz);
- chip->chip_select_num = spi->chip_select;
- if (chip->chip_select_num < MAX_CTRL_CS) {
- if (!(spi->mode & SPI_CPHA))
- dev_warn(&spi->dev, "Warning: SPI CPHA not set:"
- " Slave Select not under software control!\n"
- " See Documentation/blackfin/bfin-spi-notes.txt");
-
- chip->flag = (1 << spi->chip_select) << 8;
- } else
- chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
-
- if (chip->enable_dma && chip->pio_interrupt) {
- dev_err(&spi->dev, "enable_dma is set, "
- "do not set pio_interrupt\n");
- goto error;
- }
- /*
- * if any one SPI chip is registered and wants DMA, request the
- * DMA channel for it
- */
- if (chip->enable_dma && !drv_data->dma_requested) {
- /* register dma irq handler */
- ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA");
- if (ret) {
- dev_err(&spi->dev,
- "Unable to request BlackFin SPI DMA channel\n");
- goto error;
- }
- drv_data->dma_requested = 1;
-
- ret = set_dma_callback(drv_data->dma_channel,
- bfin_spi_dma_irq_handler, drv_data);
- if (ret) {
- dev_err(&spi->dev, "Unable to set dma callback\n");
- goto error;
- }
- dma_disable_irq(drv_data->dma_channel);
- }
-
- if (chip->pio_interrupt && !drv_data->irq_requested) {
- ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
- 0, "BFIN_SPI", drv_data);
- if (ret) {
- dev_err(&spi->dev, "Unable to register spi IRQ\n");
- goto error;
- }
- drv_data->irq_requested = 1;
- /* we use write mode, spi irq has to be disabled here */
- disable_irq(drv_data->spi_irq);
- }
-
- if (chip->chip_select_num >= MAX_CTRL_CS) {
- /* Only request on first setup */
- if (spi_get_ctldata(spi) == NULL) {
- ret = gpio_request(chip->cs_gpio, spi->modalias);
- if (ret) {
- dev_err(&spi->dev, "gpio_request() error\n");
- goto pin_error;
- }
- gpio_direction_output(chip->cs_gpio, 1);
- }
- }
-
- dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
- spi->modalias, spi->bits_per_word, chip->enable_dma);
- dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
- chip->ctl_reg, chip->flag);
-
- spi_set_ctldata(spi, chip);
-
- dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
- if (chip->chip_select_num < MAX_CTRL_CS) {
- ret = peripheral_request(ssel[spi->master->bus_num]
- [chip->chip_select_num-1], spi->modalias);
- if (ret) {
- dev_err(&spi->dev, "peripheral_request() error\n");
- goto pin_error;
- }
- }
-
- bfin_spi_cs_enable(drv_data, chip);
- bfin_spi_cs_deactive(drv_data, chip);
-
- return 0;
-
- pin_error:
- if (chip->chip_select_num >= MAX_CTRL_CS)
- gpio_free(chip->cs_gpio);
- else
- peripheral_free(ssel[spi->master->bus_num]
- [chip->chip_select_num - 1]);
- error:
- if (chip) {
- if (drv_data->dma_requested)
- free_dma(drv_data->dma_channel);
- drv_data->dma_requested = 0;
-
- kfree(chip);
- /* prevent free 'chip' twice */
- spi_set_ctldata(spi, NULL);
- }
-
- return ret;
-}
-
-/*
- * callback for spi framework.
- * clean driver specific data
- */
-static void bfin_spi_cleanup(struct spi_device *spi)
-{
- struct bfin_spi_slave_data *chip = spi_get_ctldata(spi);
- struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
-
- if (!chip)
- return;
-
- if (chip->chip_select_num < MAX_CTRL_CS) {
- peripheral_free(ssel[spi->master->bus_num]
- [chip->chip_select_num-1]);
- bfin_spi_cs_disable(drv_data, chip);
- } else
- gpio_free(chip->cs_gpio);
-
- kfree(chip);
- /* prevent free 'chip' twice */
- spi_set_ctldata(spi, NULL);
-}
-
-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);
-
- drv_data->running = false;
- drv_data->busy = 0;
-
- /* init transfer tasklet */
- tasklet_init(&drv_data->pump_transfers,
- bfin_spi_pump_transfers, (unsigned long)drv_data);
-
- /* init messages workqueue */
- INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages);
- drv_data->workqueue = create_singlethread_workqueue(
- dev_name(drv_data->master->dev.parent));
- if (drv_data->workqueue == NULL)
- return -EBUSY;
-
- return 0;
-}
-
-static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (drv_data->running || drv_data->busy) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -EBUSY;
- }
-
- drv_data->running = true;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- drv_data->cur_chip = NULL;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- return 0;
-}
-
-static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- /*
- * This is a bit lame, but is optimized for the common execution path.
- * A wait_queue on the drv_data->busy could be used, but then the common
- * execution path (pump_messages) would be required to call wake_up or
- * friends on every SPI message. Do this instead
- */
- drv_data->running = false;
- while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- msleep(10);
- spin_lock_irqsave(&drv_data->lock, flags);
- }
-
- if (!list_empty(&drv_data->queue) || drv_data->busy)
- status = -EBUSY;
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return status;
-}
-
-static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
-{
- int status;
-
- status = bfin_spi_stop_queue(drv_data);
- if (status != 0)
- return status;
-
- destroy_workqueue(drv_data->workqueue);
-
- return 0;
-}
-
-static int __init bfin_spi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct bfin5xx_spi_master *platform_info;
- struct spi_master *master;
- struct bfin_spi_master_data *drv_data;
- struct resource *res;
- int status = 0;
-
- platform_info = dev->platform_data;
-
- /* Allocate master with space for drv_data */
- master = spi_alloc_master(dev, sizeof(*drv_data));
- if (!master) {
- dev_err(&pdev->dev, "can not alloc spi_master\n");
- return -ENOMEM;
- }
-
- drv_data = spi_master_get_devdata(master);
- drv_data->master = master;
- drv_data->master_info = platform_info;
- drv_data->pdev = pdev;
- drv_data->pin_req = platform_info->pin_req;
-
- /* the spi->mode bits supported by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
-
- master->bus_num = pdev->id;
- master->num_chipselect = platform_info->num_chipselect;
- master->cleanup = bfin_spi_cleanup;
- master->setup = bfin_spi_setup;
- master->transfer = bfin_spi_transfer;
-
- /* Find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(dev, "Cannot get IORESOURCE_MEM\n");
- status = -ENOENT;
- goto out_error_get_res;
- }
-
- 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;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (res == NULL) {
- dev_err(dev, "No DMA channel specified\n");
- status = -ENOENT;
- goto out_error_free_io;
- }
- drv_data->dma_channel = res->start;
-
- drv_data->spi_irq = platform_get_irq(pdev, 0);
- if (drv_data->spi_irq < 0) {
- dev_err(dev, "No spi pio irq specified\n");
- status = -ENOENT;
- goto out_error_free_io;
- }
-
- /* Initial and start queue */
- status = bfin_spi_init_queue(drv_data);
- if (status != 0) {
- dev_err(dev, "problem initializing queue\n");
- goto out_error_queue_alloc;
- }
-
- status = bfin_spi_start_queue(drv_data);
- if (status != 0) {
- dev_err(dev, "problem starting queue\n");
- goto out_error_queue_alloc;
- }
-
- status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
- if (status != 0) {
- dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
- goto out_error_queue_alloc;
- }
-
- /* 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.
- */
- 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);
- status = spi_register_master(master);
- if (status != 0) {
- dev_err(dev, "problem registering spi master\n");
- goto out_error_queue_alloc;
- }
-
- 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(drv_data->regs);
-out_error_ioremap:
-out_error_get_res:
- spi_master_put(master);
-
- return status;
-}
-
-/* stop hardware and remove the driver */
-static int __devexit bfin_spi_remove(struct platform_device *pdev)
-{
- struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
- int status = 0;
-
- if (!drv_data)
- return 0;
-
- /* Remove the queue */
- status = bfin_spi_destroy_queue(drv_data);
- if (status != 0)
- return status;
-
- /* Disable the SSP at the peripheral and SOC level */
- bfin_spi_disable(drv_data);
-
- /* Release DMA */
- if (drv_data->master_info->enable_dma) {
- if (dma_channel_active(drv_data->dma_channel))
- free_dma(drv_data->dma_channel);
- }
-
- if (drv_data->irq_requested) {
- free_irq(drv_data->spi_irq, drv_data);
- drv_data->irq_requested = 0;
- }
-
- /* Disconnect from the SPI framework */
- spi_unregister_master(drv_data->master);
-
- peripheral_free_list(drv_data->pin_req);
-
- /* Prevent double remove */
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
- int status = 0;
-
- status = bfin_spi_stop_queue(drv_data);
- if (status != 0)
- return status;
-
- 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
- */
- bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
- bfin_write(&drv_data->regs->flg, 0xFF00);
-
- return 0;
-}
-
-static int bfin_spi_resume(struct platform_device *pdev)
-{
- struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
- int status = 0;
-
- 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);
- if (status != 0) {
- dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
- return status;
- }
-
- return 0;
-}
-#else
-#define bfin_spi_suspend NULL
-#define bfin_spi_resume NULL
-#endif /* CONFIG_PM */
-
-MODULE_ALIAS("platform:bfin-spi");
-static struct platform_driver bfin_spi_driver = {
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
- .suspend = bfin_spi_suspend,
- .resume = bfin_spi_resume,
- .remove = __devexit_p(bfin_spi_remove),
-};
-
-static int __init bfin_spi_init(void)
-{
- return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
-}
-subsys_initcall(bfin_spi_init);
-
-static void __exit bfin_spi_exit(void)
-{
- platform_driver_unregister(&bfin_spi_driver);
-}
-module_exit(bfin_spi_exit);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-bitbang-txrx.h b/ANDROID_3.4.5/drivers/spi/spi-bitbang-txrx.h
deleted file mode 100644
index c16bf853..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-bitbang-txrx.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Mix this utility code with some glue code to get one of several types of
- * simple SPI master driver. Two do polled word-at-a-time I/O:
- *
- * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
- * expanding the per-word routines from the inline templates below.
- *
- * - Drivers for controllers resembling bare shift registers. Provide
- * chipselect() and txrx_word[](), with custom setup()/cleanup() methods
- * that use your controller's clock and chipselect registers.
- *
- * Some hardware works well with requests at spi_transfer scope:
- *
- * - Drivers leveraging smarter hardware, with fifos or DMA; or for half
- * duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(),
- * and custom setup()/cleanup() methods.
- */
-
-/*
- * The code that knows what GPIO pins do what should have declared four
- * functions, ideally as inlines, before including this header:
- *
- * void setsck(struct spi_device *, int is_on);
- * void setmosi(struct spi_device *, int is_on);
- * int getmiso(struct spi_device *);
- * void spidelay(unsigned);
- *
- * setsck()'s is_on parameter is a zero/nonzero boolean.
- *
- * setmosi()'s is_on parameter is a zero/nonzero boolean.
- *
- * getmiso() is required to return 0 or 1 only. Any other value is invalid
- * and will result in improper operation.
- *
- * A non-inlined routine would call bitbang_txrx_*() routines. The
- * main loop could easily compile down to a handful of instructions,
- * especially if the delay is a NOP (to run at peak speed).
- *
- * Since this is software, the timings may not be exactly what your board's
- * chips need ... there may be several reasons you'd need to tweak timings
- * in these routines, not just make to make it faster or slower to match a
- * particular CPU clock rate.
- */
-
-static inline u32
-bitbang_txrx_be_cpha0(struct spi_device *spi,
- unsigned nsecs, unsigned cpol, unsigned flags,
- u32 word, u8 bits)
-{
- /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
-
- /* clock starts at inactive polarity */
- for (word <<= (32 - bits); likely(bits); bits--) {
-
- /* setup MSB (to slave) on trailing edge */
- if ((flags & SPI_MASTER_NO_TX) == 0)
- setmosi(spi, word & (1 << 31));
- spidelay(nsecs); /* T(setup) */
-
- setsck(spi, !cpol);
- spidelay(nsecs);
-
- /* sample MSB (from slave) on leading edge */
- word <<= 1;
- if ((flags & SPI_MASTER_NO_RX) == 0)
- word |= getmiso(spi);
- setsck(spi, cpol);
- }
- return word;
-}
-
-static inline u32
-bitbang_txrx_be_cpha1(struct spi_device *spi,
- unsigned nsecs, unsigned cpol, unsigned flags,
- u32 word, u8 bits)
-{
- /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
-
- /* clock starts at inactive polarity */
- for (word <<= (32 - bits); likely(bits); bits--) {
-
- /* setup MSB (to slave) on leading edge */
- setsck(spi, !cpol);
- if ((flags & SPI_MASTER_NO_TX) == 0)
- setmosi(spi, word & (1 << 31));
- spidelay(nsecs); /* T(setup) */
-
- setsck(spi, cpol);
- spidelay(nsecs);
-
- /* sample MSB (from slave) on trailing edge */
- word <<= 1;
- if ((flags & SPI_MASTER_NO_RX) == 0)
- word |= getmiso(spi);
- }
- return word;
-}
diff --git a/ANDROID_3.4.5/drivers/spi/spi-bitbang.c b/ANDROID_3.4.5/drivers/spi/spi-bitbang.c
deleted file mode 100644
index aef59b1a..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-bitbang.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-
-/*----------------------------------------------------------------------*/
-
-/*
- * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support.
- * Use this for GPIO or shift-register level hardware APIs.
- *
- * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
- * to glue code. These bitbang setup() and cleanup() routines are always
- * used, though maybe they're called from controller-aware code.
- *
- * chipselect() and friends may use use spi_device->controller_data and
- * controller registers as appropriate.
- *
- *
- * NOTE: SPI controller pins can often be used as GPIO pins instead,
- * which means you could use a bitbang driver either to get hardware
- * working quickly, or testing for differences that aren't speed related.
- */
-
-struct spi_bitbang_cs {
- unsigned nsecs; /* (clock cycle time)/2 */
- u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
- u32 word, u8 bits);
- unsigned (*txrx_bufs)(struct spi_device *,
- u32 (*txrx_word)(
- struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits),
- unsigned, struct spi_transfer *);
-};
-
-static unsigned bitbang_txrx_8(
- struct spi_device *spi,
- u32 (*txrx_word)(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits),
- unsigned ns,
- struct spi_transfer *t
-) {
- 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;
-
- while (likely(count > 0)) {
- u8 word = 0;
-
- if (tx)
- word = *tx++;
- word = txrx_word(spi, ns, word, bits);
- if (rx)
- *rx++ = word;
- count -= 1;
- }
- return t->len - count;
-}
-
-static unsigned bitbang_txrx_16(
- struct spi_device *spi,
- u32 (*txrx_word)(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits),
- unsigned ns,
- struct spi_transfer *t
-) {
- 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;
-
- while (likely(count > 1)) {
- u16 word = 0;
-
- if (tx)
- word = *tx++;
- word = txrx_word(spi, ns, word, bits);
- if (rx)
- *rx++ = word;
- count -= 2;
- }
- return t->len - count;
-}
-
-static unsigned bitbang_txrx_32(
- struct spi_device *spi,
- u32 (*txrx_word)(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits),
- unsigned ns,
- struct spi_transfer *t
-) {
- 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;
-
- while (likely(count > 3)) {
- u32 word = 0;
-
- if (tx)
- word = *tx++;
- word = txrx_word(spi, ns, word, bits);
- if (rx)
- *rx++ = word;
- count -= 4;
- }
- return t->len - count;
-}
-
-int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct spi_bitbang_cs *cs = spi->controller_state;
- u8 bits_per_word;
- u32 hz;
-
- if (t) {
- bits_per_word = t->bits_per_word;
- hz = t->speed_hz;
- } else {
- bits_per_word = 0;
- hz = 0;
- }
-
- /* spi_transfer level calls that work per-word */
- if (!bits_per_word)
- bits_per_word = spi->bits_per_word;
- if (bits_per_word <= 8)
- cs->txrx_bufs = bitbang_txrx_8;
- else if (bits_per_word <= 16)
- cs->txrx_bufs = bitbang_txrx_16;
- else if (bits_per_word <= 32)
- cs->txrx_bufs = bitbang_txrx_32;
- else
- return -EINVAL;
-
- /* nsecs = (clock period)/2 */
- if (!hz)
- hz = spi->max_speed_hz;
- if (hz) {
- cs->nsecs = (1000000000/2) / hz;
- if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
- return -EINVAL;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
-
-/**
- * spi_bitbang_setup - default setup for per-word I/O loops
- */
-int spi_bitbang_setup(struct spi_device *spi)
-{
- struct spi_bitbang_cs *cs = spi->controller_state;
- struct spi_bitbang *bitbang;
- int retval;
- unsigned long flags;
-
- bitbang = spi_master_get_devdata(spi->master);
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- spi->controller_state = cs;
- }
-
- /* per-word shift register access, in hardware or bitbanging */
- cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
- if (!cs->txrx_word)
- return -EINVAL;
-
- retval = bitbang->setup_transfer(spi, NULL);
- if (retval < 0)
- return retval;
-
- dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
-
- /* NOTE we _need_ to call chipselect() early, ideally with adapter
- * setup, unless the hardware defaults cooperate to avoid confusion
- * between normal (active low) and inverted chipselects.
- */
-
- /* deselect chip (low or high) */
- spin_lock_irqsave(&bitbang->lock, flags);
- if (!bitbang->busy) {
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(cs->nsecs);
- }
- spin_unlock_irqrestore(&bitbang->lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_setup);
-
-/**
- * spi_bitbang_cleanup - default cleanup for per-word I/O loops
- */
-void spi_bitbang_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
-
-static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
- struct spi_bitbang_cs *cs = spi->controller_state;
- unsigned nsecs = cs->nsecs;
-
- return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * SECOND PART ... simple transfer queue runner.
- *
- * This costs a task context per controller, running the queue by
- * performing each transfer in sequence. Smarter hardware can queue
- * several DMA transfers at once, and process several controller queues
- * in parallel; this driver doesn't match such hardware very well.
- *
- * Drivers can provide word-at-a-time i/o primitives, or provide
- * transfer-at-a-time ones to leverage dma or fifo hardware.
- */
-static void bitbang_work(struct work_struct *work)
-{
- struct spi_bitbang *bitbang =
- container_of(work, struct spi_bitbang, work);
- unsigned long flags;
-
- spin_lock_irqsave(&bitbang->lock, flags);
- bitbang->busy = 1;
- while (!list_empty(&bitbang->queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- unsigned nsecs;
- struct spi_transfer *t = NULL;
- unsigned tmp;
- unsigned cs_change;
- int status;
- int do_setup = -1;
-
- m = container_of(bitbang->queue.next, struct spi_message,
- queue);
- list_del_init(&m->queue);
- spin_unlock_irqrestore(&bitbang->lock, flags);
-
- /* FIXME this is made-up ... the correct value is known to
- * word-at-a-time bitbang code, and presumably chipselect()
- * should enforce these requirements too?
- */
- nsecs = 100;
-
- spi = m->spi;
- tmp = 0;
- cs_change = 1;
- status = 0;
-
- list_for_each_entry (t, &m->transfers, transfer_list) {
-
- /* override speed or wordsize? */
- if (t->speed_hz || t->bits_per_word)
- do_setup = 1;
-
- /* init (-1) or override (1) transfer params */
- if (do_setup != 0) {
- status = bitbang->setup_transfer(spi, t);
- if (status < 0)
- break;
- if (do_setup == -1)
- do_setup = 0;
- }
-
- /* set up default clock polarity, and activate chip;
- * this implicitly updates clock and spi modes as
- * previously recorded for this device via setup().
- * (and also deselects any other chip that might be
- * selected ...)
- */
- if (cs_change) {
- bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
- ndelay(nsecs);
- }
- cs_change = t->cs_change;
- if (!t->tx_buf && !t->rx_buf && t->len) {
- status = -EINVAL;
- break;
- }
-
- /* transfer data. the lower level code handles any
- * new dma mappings it needs. our caller always gave
- * us dma-safe buffers.
- */
- if (t->len) {
- /* REVISIT dma API still needs a designated
- * DMA_ADDR_INVALID; ~0 might be better.
- */
- if (!m->is_dma_mapped)
- t->rx_dma = t->tx_dma = 0;
- status = bitbang->txrx_bufs(spi, t);
- }
- if (status > 0)
- m->actual_length += status;
- if (status != t->len) {
- /* always report some kind of error */
- if (status >= 0)
- status = -EREMOTEIO;
- break;
- }
- status = 0;
-
- /* protocol tweaks before next transfer */
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (!cs_change)
- continue;
- if (t->transfer_list.next == &m->transfers)
- break;
-
- /* sometimes a short mid-message deselect of the chip
- * may be needed to terminate a mode or command
- */
- ndelay(nsecs);
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
-
- m->status = status;
- m->complete(m->context);
-
- /* normally deactivate chipselect ... unless no error and
- * cs_change has hinted that the next message will probably
- * be for this chip too.
- */
- if (!(status == 0 && cs_change)) {
- ndelay(nsecs);
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
-
- spin_lock_irqsave(&bitbang->lock, flags);
- }
- bitbang->busy = 0;
- spin_unlock_irqrestore(&bitbang->lock, flags);
-}
-
-/**
- * spi_bitbang_transfer - default submit to transfer queue
- */
-int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct spi_bitbang *bitbang;
- unsigned long flags;
- int status = 0;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- bitbang = spi_master_get_devdata(spi->master);
-
- spin_lock_irqsave(&bitbang->lock, flags);
- if (!spi->max_speed_hz)
- status = -ENETDOWN;
- else {
- list_add_tail(&m->queue, &bitbang->queue);
- queue_work(bitbang->workqueue, &bitbang->work);
- }
- spin_unlock_irqrestore(&bitbang->lock, flags);
-
- return status;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
-
-/*----------------------------------------------------------------------*/
-
-/**
- * spi_bitbang_start - start up a polled/bitbanging SPI master driver
- * @bitbang: driver handle
- *
- * Caller should have zero-initialized all parts of the structure, and then
- * provided callbacks for chip selection and I/O loops. If the master has
- * a transfer method, its final step should call spi_bitbang_transfer; or,
- * that's the default if the transfer routine is not initialized. It should
- * also set up the bus number and number of chipselects.
- *
- * For i/o loops, provide callbacks either per-word (for bitbanging, or for
- * hardware that basically exposes a shift register) or per-spi_transfer
- * (which takes better advantage of hardware like fifos or DMA engines).
- *
- * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
- * spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
- * master methods. Those methods are the defaults if the bitbang->txrx_bufs
- * routine isn't initialized.
- *
- * This routine registers the spi_master, which will process requests in a
- * dedicated task, keeping IRQs unblocked most of the time. To stop
- * processing those requests, call spi_bitbang_stop().
- */
-int spi_bitbang_start(struct spi_bitbang *bitbang)
-{
- int status;
-
- if (!bitbang->master || !bitbang->chipselect)
- return -EINVAL;
-
- INIT_WORK(&bitbang->work, bitbang_work);
- spin_lock_init(&bitbang->lock);
- INIT_LIST_HEAD(&bitbang->queue);
-
- if (!bitbang->master->mode_bits)
- bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
-
- if (!bitbang->master->transfer)
- bitbang->master->transfer = spi_bitbang_transfer;
- if (!bitbang->txrx_bufs) {
- bitbang->use_dma = 0;
- bitbang->txrx_bufs = spi_bitbang_bufs;
- if (!bitbang->master->setup) {
- if (!bitbang->setup_transfer)
- bitbang->setup_transfer =
- spi_bitbang_setup_transfer;
- bitbang->master->setup = spi_bitbang_setup;
- bitbang->master->cleanup = spi_bitbang_cleanup;
- }
- } else if (!bitbang->master->setup)
- return -EINVAL;
- if (bitbang->master->transfer == spi_bitbang_transfer &&
- !bitbang->setup_transfer)
- return -EINVAL;
-
- /* this task is the only thing to touch the SPI bits */
- bitbang->busy = 0;
- bitbang->workqueue = create_singlethread_workqueue(
- dev_name(bitbang->master->dev.parent));
- if (bitbang->workqueue == NULL) {
- status = -EBUSY;
- goto err1;
- }
-
- /* driver may get busy before register() returns, especially
- * if someone registered boardinfo for devices
- */
- status = spi_register_master(bitbang->master);
- if (status < 0)
- goto err2;
-
- return status;
-
-err2:
- destroy_workqueue(bitbang->workqueue);
-err1:
- return status;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_start);
-
-/**
- * spi_bitbang_stop - stops the task providing spi communication
- */
-int spi_bitbang_stop(struct spi_bitbang *bitbang)
-{
- spi_unregister_master(bitbang->master);
-
- WARN_ON(!list_empty(&bitbang->queue));
-
- destroy_workqueue(bitbang->workqueue);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_stop);
-
-MODULE_LICENSE("GPL");
-
diff --git a/ANDROID_3.4.5/drivers/spi/spi-butterfly.c b/ANDROID_3.4.5/drivers/spi/spi-butterfly.c
deleted file mode 100644
index 5ed08e53..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-butterfly.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * parport-to-butterfly adapter
- *
- * Copyright (C) 2005 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/parport.h>
-
-#include <linux/sched.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/flash.h>
-
-#include <linux/mtd/partitions.h>
-
-
-/*
- * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
- * with a battery powered AVR microcontroller and lots of goodies. You
- * can use GCC to develop firmware for this.
- *
- * See Documentation/spi/butterfly for information about how to build
- * and use this custom parallel port cable.
- */
-
-
-/* DATA output bits (pins 2..9 == D0..D7) */
-#define butterfly_nreset (1 << 1) /* pin 3 */
-
-#define spi_sck_bit (1 << 0) /* pin 2 */
-#define spi_mosi_bit (1 << 7) /* pin 9 */
-
-#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */
-
-/* STATUS input bits */
-#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */
-
-/* CONTROL output bits */
-#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */
-
-
-
-static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
-{
- return spi->controller_data;
-}
-
-
-struct butterfly {
- /* REVISIT ... for now, this must be first */
- struct spi_bitbang bitbang;
-
- struct parport *port;
- struct pardevice *pd;
-
- u8 lastbyte;
-
- struct spi_device *dataflash;
- struct spi_device *butterfly;
- struct spi_board_info info[2];
-
-};
-
-/*----------------------------------------------------------------------*/
-
-static inline void
-setsck(struct spi_device *spi, int is_on)
-{
- struct butterfly *pp = spidev_to_pp(spi);
- u8 bit, byte = pp->lastbyte;
-
- bit = spi_sck_bit;
-
- if (is_on)
- byte |= bit;
- else
- byte &= ~bit;
- parport_write_data(pp->port, byte);
- pp->lastbyte = byte;
-}
-
-static inline void
-setmosi(struct spi_device *spi, int is_on)
-{
- struct butterfly *pp = spidev_to_pp(spi);
- u8 bit, byte = pp->lastbyte;
-
- bit = spi_mosi_bit;
-
- if (is_on)
- byte |= bit;
- else
- byte &= ~bit;
- parport_write_data(pp->port, byte);
- pp->lastbyte = byte;
-}
-
-static inline int getmiso(struct spi_device *spi)
-{
- struct butterfly *pp = spidev_to_pp(spi);
- int value;
- u8 bit;
-
- bit = spi_miso_bit;
-
- /* only STATUS_BUSY is NOT negated */
- value = !(parport_read_status(pp->port) & bit);
- return (bit == PARPORT_STATUS_BUSY) ? value : !value;
-}
-
-static void butterfly_chipselect(struct spi_device *spi, int value)
-{
- struct butterfly *pp = spidev_to_pp(spi);
-
- /* set default clock polarity */
- if (value != BITBANG_CS_INACTIVE)
- setsck(spi, spi->mode & SPI_CPOL);
-
- /* here, value == "activate or not";
- * most PARPORT_CONTROL_* bits are negated, so we must
- * morph it to value == "bit value to write in control register"
- */
- if (spi_cs_bit == PARPORT_CONTROL_INIT)
- value = !value;
-
- parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
-}
-
-
-/* we only needed to implement one mode here, and choose SPI_MODE_0 */
-
-#define spidelay(X) do{}while(0)
-//#define spidelay ndelay
-
-#include "spi-bitbang-txrx.h"
-
-static u32
-butterfly_txrx_word_mode0(struct spi_device *spi,
- unsigned nsecs,
- u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-/*----------------------------------------------------------------------*/
-
-/* override default partitioning with cmdlinepart */
-static struct mtd_partition partitions[] = { {
- /* JFFS2 wants partitions of 4*N blocks for this device,
- * so sectors 0 and 1 can't be partitions by themselves.
- */
-
- /* sector 0 = 8 pages * 264 bytes/page (1 block)
- * sector 1 = 248 pages * 264 bytes/page
- */
- .name = "bookkeeping", // 66 KB
- .offset = 0,
- .size = (8 + 248) * 264,
-// .mask_flags = MTD_WRITEABLE,
-}, {
- /* sector 2 = 256 pages * 264 bytes/page
- * sectors 3-5 = 512 pages * 264 bytes/page
- */
- .name = "filesystem", // 462 KB
- .offset = MTDPART_OFS_APPEND,
- .size = MTDPART_SIZ_FULL,
-} };
-
-static struct flash_platform_data flash = {
- .name = "butterflash",
- .parts = partitions,
- .nr_parts = ARRAY_SIZE(partitions),
-};
-
-
-/* REVISIT remove this ugly global and its "only one" limitation */
-static struct butterfly *butterfly;
-
-static void butterfly_attach(struct parport *p)
-{
- struct pardevice *pd;
- int status;
- struct butterfly *pp;
- struct spi_master *master;
- struct device *dev = p->physport->dev;
-
- if (butterfly || !dev)
- return;
-
- /* REVISIT: this just _assumes_ a butterfly is there ... no probe,
- * and no way to be selective about what it binds to.
- */
-
- master = spi_alloc_master(dev, sizeof *pp);
- if (!master) {
- status = -ENOMEM;
- goto done;
- }
- pp = spi_master_get_devdata(master);
-
- /*
- * SPI and bitbang hookup
- *
- * use default setup(), cleanup(), and transfer() methods; and
- * only bother implementing mode 0. Start it later.
- */
- master->bus_num = 42;
- master->num_chipselect = 2;
-
- pp->bitbang.master = spi_master_get(master);
- pp->bitbang.chipselect = butterfly_chipselect;
- pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
-
- /*
- * parport hookup
- */
- pp->port = p;
- pd = parport_register_device(p, "spi_butterfly",
- NULL, NULL, NULL,
- 0 /* FLAGS */, pp);
- if (!pd) {
- status = -ENOMEM;
- goto clean0;
- }
- pp->pd = pd;
-
- status = parport_claim(pd);
- if (status < 0)
- goto clean1;
-
- /*
- * Butterfly reset, powerup, run firmware
- */
- pr_debug("%s: powerup/reset Butterfly\n", p->name);
-
- /* nCS for dataflash (this bit is inverted on output) */
- parport_frob_control(pp->port, spi_cs_bit, 0);
-
- /* stabilize power with chip in reset (nRESET), and
- * spi_sck_bit clear (CPOL=0)
- */
- pp->lastbyte |= vcc_bits;
- parport_write_data(pp->port, pp->lastbyte);
- msleep(5);
-
- /* take it out of reset; assume long reset delay */
- pp->lastbyte |= butterfly_nreset;
- parport_write_data(pp->port, pp->lastbyte);
- msleep(100);
-
-
- /*
- * Start SPI ... for now, hide that we're two physical busses.
- */
- status = spi_bitbang_start(&pp->bitbang);
- if (status < 0)
- goto clean2;
-
- /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
- * (firmware resets at45, acts as spi slave) or neither (we ignore
- * both, AVR uses AT45). Here we expect firmware for the first option.
- */
-
- pp->info[0].max_speed_hz = 15 * 1000 * 1000;
- strcpy(pp->info[0].modalias, "mtd_dataflash");
- pp->info[0].platform_data = &flash;
- pp->info[0].chip_select = 1;
- pp->info[0].controller_data = pp;
- pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
- if (pp->dataflash)
- pr_debug("%s: dataflash at %s\n", p->name,
- dev_name(&pp->dataflash->dev));
-
- // dev_info(_what?_, ...)
- pr_info("%s: AVR Butterfly\n", p->name);
- butterfly = pp;
- return;
-
-clean2:
- /* turn off VCC */
- parport_write_data(pp->port, 0);
-
- parport_release(pp->pd);
-clean1:
- parport_unregister_device(pd);
-clean0:
- (void) spi_master_put(pp->bitbang.master);
-done:
- pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
-}
-
-static void butterfly_detach(struct parport *p)
-{
- struct butterfly *pp;
- int status;
-
- /* FIXME this global is ugly ... but, how to quickly get from
- * the parport to the "struct butterfly" associated with it?
- * "old school" driver-internal device lists?
- */
- if (!butterfly || butterfly->port != p)
- return;
- pp = butterfly;
- butterfly = NULL;
-
- /* stop() unregisters child devices too */
- status = spi_bitbang_stop(&pp->bitbang);
-
- /* turn off VCC */
- parport_write_data(pp->port, 0);
- msleep(10);
-
- parport_release(pp->pd);
- parport_unregister_device(pp->pd);
-
- (void) spi_master_put(pp->bitbang.master);
-}
-
-static struct parport_driver butterfly_driver = {
- .name = "spi_butterfly",
- .attach = butterfly_attach,
- .detach = butterfly_detach,
-};
-
-
-static int __init butterfly_init(void)
-{
- return parport_register_driver(&butterfly_driver);
-}
-device_initcall(butterfly_init);
-
-static void __exit butterfly_exit(void)
-{
- parport_unregister_driver(&butterfly_driver);
-}
-module_exit(butterfly_exit);
-
-MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-coldfire-qspi.c b/ANDROID_3.4.5/drivers/spi/spi-coldfire-qspi.c
deleted file mode 100644
index 6eee64a5..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-coldfire-qspi.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Freescale/Motorola Coldfire Queued SPI driver
- *
- * Copyright 2010 Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/spi/spi.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfqspi.h>
-
-#define DRIVER_NAME "mcfqspi"
-
-#define MCFQSPI_BUSCLK (MCF_BUSCLK / 2)
-
-#define MCFQSPI_QMR 0x00
-#define MCFQSPI_QMR_MSTR 0x8000
-#define MCFQSPI_QMR_CPOL 0x0200
-#define MCFQSPI_QMR_CPHA 0x0100
-#define MCFQSPI_QDLYR 0x04
-#define MCFQSPI_QDLYR_SPE 0x8000
-#define MCFQSPI_QWR 0x08
-#define MCFQSPI_QWR_HALT 0x8000
-#define MCFQSPI_QWR_WREN 0x4000
-#define MCFQSPI_QWR_CSIV 0x1000
-#define MCFQSPI_QIR 0x0C
-#define MCFQSPI_QIR_WCEFB 0x8000
-#define MCFQSPI_QIR_ABRTB 0x4000
-#define MCFQSPI_QIR_ABRTL 0x1000
-#define MCFQSPI_QIR_WCEFE 0x0800
-#define MCFQSPI_QIR_ABRTE 0x0400
-#define MCFQSPI_QIR_SPIFE 0x0100
-#define MCFQSPI_QIR_WCEF 0x0008
-#define MCFQSPI_QIR_ABRT 0x0004
-#define MCFQSPI_QIR_SPIF 0x0001
-#define MCFQSPI_QAR 0x010
-#define MCFQSPI_QAR_TXBUF 0x00
-#define MCFQSPI_QAR_RXBUF 0x10
-#define MCFQSPI_QAR_CMDBUF 0x20
-#define MCFQSPI_QDR 0x014
-#define MCFQSPI_QCR 0x014
-#define MCFQSPI_QCR_CONT 0x8000
-#define MCFQSPI_QCR_BITSE 0x4000
-#define MCFQSPI_QCR_DT 0x2000
-
-struct mcfqspi {
- void __iomem *iobase;
- int irq;
- struct clk *clk;
- struct mcfqspi_cs_control *cs_control;
-
- wait_queue_head_t waitq;
-
- struct work_struct work;
- struct workqueue_struct *workq;
- spinlock_t lock;
- struct list_head msgq;
-};
-
-static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
-{
- writew(val, mcfqspi->iobase + MCFQSPI_QMR);
-}
-
-static void mcfqspi_wr_qdlyr(struct mcfqspi *mcfqspi, u16 val)
-{
- writew(val, mcfqspi->iobase + MCFQSPI_QDLYR);
-}
-
-static u16 mcfqspi_rd_qdlyr(struct mcfqspi *mcfqspi)
-{
- return readw(mcfqspi->iobase + MCFQSPI_QDLYR);
-}
-
-static void mcfqspi_wr_qwr(struct mcfqspi *mcfqspi, u16 val)
-{
- writew(val, mcfqspi->iobase + MCFQSPI_QWR);
-}
-
-static void mcfqspi_wr_qir(struct mcfqspi *mcfqspi, u16 val)
-{
- writew(val, mcfqspi->iobase + MCFQSPI_QIR);
-}
-
-static void mcfqspi_wr_qar(struct mcfqspi *mcfqspi, u16 val)
-{
- writew(val, mcfqspi->iobase + MCFQSPI_QAR);
-}
-
-static void mcfqspi_wr_qdr(struct mcfqspi *mcfqspi, u16 val)
-{
- writew(val, mcfqspi->iobase + MCFQSPI_QDR);
-}
-
-static u16 mcfqspi_rd_qdr(struct mcfqspi *mcfqspi)
-{
- return readw(mcfqspi->iobase + MCFQSPI_QDR);
-}
-
-static void mcfqspi_cs_select(struct mcfqspi *mcfqspi, u8 chip_select,
- bool cs_high)
-{
- mcfqspi->cs_control->select(mcfqspi->cs_control, chip_select, cs_high);
-}
-
-static void mcfqspi_cs_deselect(struct mcfqspi *mcfqspi, u8 chip_select,
- bool cs_high)
-{
- mcfqspi->cs_control->deselect(mcfqspi->cs_control, chip_select, cs_high);
-}
-
-static int mcfqspi_cs_setup(struct mcfqspi *mcfqspi)
-{
- return (mcfqspi->cs_control && mcfqspi->cs_control->setup) ?
- mcfqspi->cs_control->setup(mcfqspi->cs_control) : 0;
-}
-
-static void mcfqspi_cs_teardown(struct mcfqspi *mcfqspi)
-{
- if (mcfqspi->cs_control && mcfqspi->cs_control->teardown)
- mcfqspi->cs_control->teardown(mcfqspi->cs_control);
-}
-
-static u8 mcfqspi_qmr_baud(u32 speed_hz)
-{
- return clamp((MCFQSPI_BUSCLK + speed_hz - 1) / speed_hz, 2u, 255u);
-}
-
-static bool mcfqspi_qdlyr_spe(struct mcfqspi *mcfqspi)
-{
- return mcfqspi_rd_qdlyr(mcfqspi) & MCFQSPI_QDLYR_SPE;
-}
-
-static irqreturn_t mcfqspi_irq_handler(int this_irq, void *dev_id)
-{
- struct mcfqspi *mcfqspi = dev_id;
-
- /* clear interrupt */
- mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE | MCFQSPI_QIR_SPIF);
- wake_up(&mcfqspi->waitq);
-
- return IRQ_HANDLED;
-}
-
-static void mcfqspi_transfer_msg8(struct mcfqspi *mcfqspi, unsigned count,
- const u8 *txbuf, u8 *rxbuf)
-{
- unsigned i, n, offset = 0;
-
- n = min(count, 16u);
-
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
- for (i = 0; i < n; ++i)
- mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
-
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
- if (txbuf)
- for (i = 0; i < n; ++i)
- mcfqspi_wr_qdr(mcfqspi, *txbuf++);
- else
- for (i = 0; i < count; ++i)
- mcfqspi_wr_qdr(mcfqspi, 0);
-
- count -= n;
- if (count) {
- u16 qwr = 0xf08;
- mcfqspi_wr_qwr(mcfqspi, 0x700);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-
- do {
- wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
- mcfqspi_wr_qwr(mcfqspi, qwr);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
- if (rxbuf) {
- mcfqspi_wr_qar(mcfqspi,
- MCFQSPI_QAR_RXBUF + offset);
- for (i = 0; i < 8; ++i)
- *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
- }
- n = min(count, 8u);
- if (txbuf) {
- mcfqspi_wr_qar(mcfqspi,
- MCFQSPI_QAR_TXBUF + offset);
- for (i = 0; i < n; ++i)
- mcfqspi_wr_qdr(mcfqspi, *txbuf++);
- }
- qwr = (offset ? 0x808 : 0) + ((n - 1) << 8);
- offset ^= 8;
- count -= n;
- } while (count);
- wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
- mcfqspi_wr_qwr(mcfqspi, qwr);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
- if (rxbuf) {
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
- for (i = 0; i < 8; ++i)
- *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
- offset ^= 8;
- }
- } else {
- mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
- }
- wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
- if (rxbuf) {
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
- for (i = 0; i < n; ++i)
- *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
- }
-}
-
-static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
- const u16 *txbuf, u16 *rxbuf)
-{
- unsigned i, n, offset = 0;
-
- n = min(count, 16u);
-
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
- for (i = 0; i < n; ++i)
- mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
-
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
- if (txbuf)
- for (i = 0; i < n; ++i)
- mcfqspi_wr_qdr(mcfqspi, *txbuf++);
- else
- for (i = 0; i < count; ++i)
- mcfqspi_wr_qdr(mcfqspi, 0);
-
- count -= n;
- if (count) {
- u16 qwr = 0xf08;
- mcfqspi_wr_qwr(mcfqspi, 0x700);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-
- do {
- wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
- mcfqspi_wr_qwr(mcfqspi, qwr);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
- if (rxbuf) {
- mcfqspi_wr_qar(mcfqspi,
- MCFQSPI_QAR_RXBUF + offset);
- for (i = 0; i < 8; ++i)
- *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
- }
- n = min(count, 8u);
- if (txbuf) {
- mcfqspi_wr_qar(mcfqspi,
- MCFQSPI_QAR_TXBUF + offset);
- for (i = 0; i < n; ++i)
- mcfqspi_wr_qdr(mcfqspi, *txbuf++);
- }
- qwr = (offset ? 0x808 : 0x000) + ((n - 1) << 8);
- offset ^= 8;
- count -= n;
- } while (count);
- wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
- mcfqspi_wr_qwr(mcfqspi, qwr);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
- if (rxbuf) {
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
- for (i = 0; i < 8; ++i)
- *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
- offset ^= 8;
- }
- } else {
- mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
- mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
- }
- wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
- if (rxbuf) {
- mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
- for (i = 0; i < n; ++i)
- *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
- }
-}
-
-static void mcfqspi_work(struct work_struct *work)
-{
- struct mcfqspi *mcfqspi = container_of(work, struct mcfqspi, work);
- unsigned long flags;
-
- spin_lock_irqsave(&mcfqspi->lock, flags);
- while (!list_empty(&mcfqspi->msgq)) {
- struct spi_message *msg;
- struct spi_device *spi;
- struct spi_transfer *xfer;
- int status = 0;
-
- msg = container_of(mcfqspi->msgq.next, struct spi_message,
- queue);
-
- list_del_init(&msg->queue);
- spin_unlock_irqrestore(&mcfqspi->lock, flags);
-
- spi = msg->spi;
-
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- bool cs_high = spi->mode & SPI_CS_HIGH;
- u16 qmr = MCFQSPI_QMR_MSTR;
-
- if (xfer->bits_per_word)
- qmr |= xfer->bits_per_word << 10;
- else
- qmr |= spi->bits_per_word << 10;
- if (spi->mode & SPI_CPHA)
- qmr |= MCFQSPI_QMR_CPHA;
- if (spi->mode & SPI_CPOL)
- qmr |= MCFQSPI_QMR_CPOL;
- if (xfer->speed_hz)
- qmr |= mcfqspi_qmr_baud(xfer->speed_hz);
- else
- qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
- mcfqspi_wr_qmr(mcfqspi, qmr);
-
- mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
-
- mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
- if ((xfer->bits_per_word ? xfer->bits_per_word :
- spi->bits_per_word) == 8)
- mcfqspi_transfer_msg8(mcfqspi, xfer->len,
- xfer->tx_buf,
- xfer->rx_buf);
- else
- mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2,
- xfer->tx_buf,
- xfer->rx_buf);
- mcfqspi_wr_qir(mcfqspi, 0);
-
- if (xfer->delay_usecs)
- udelay(xfer->delay_usecs);
- if (xfer->cs_change) {
- if (!list_is_last(&xfer->transfer_list,
- &msg->transfers))
- mcfqspi_cs_deselect(mcfqspi,
- spi->chip_select,
- cs_high);
- } else {
- if (list_is_last(&xfer->transfer_list,
- &msg->transfers))
- mcfqspi_cs_deselect(mcfqspi,
- spi->chip_select,
- cs_high);
- }
- msg->actual_length += xfer->len;
- }
- msg->status = status;
- msg->complete(msg->context);
-
- spin_lock_irqsave(&mcfqspi->lock, flags);
- }
- spin_unlock_irqrestore(&mcfqspi->lock, flags);
-}
-
-static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct mcfqspi *mcfqspi;
- struct spi_transfer *xfer;
- unsigned long flags;
-
- mcfqspi = spi_master_get_devdata(spi->master);
-
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if (xfer->bits_per_word && ((xfer->bits_per_word < 8)
- || (xfer->bits_per_word > 16))) {
- dev_dbg(&spi->dev,
- "%d bits per word is not supported\n",
- xfer->bits_per_word);
- goto fail;
- }
- if (xfer->speed_hz) {
- u32 real_speed = MCFQSPI_BUSCLK /
- mcfqspi_qmr_baud(xfer->speed_hz);
- if (real_speed != xfer->speed_hz)
- dev_dbg(&spi->dev,
- "using speed %d instead of %d\n",
- real_speed, xfer->speed_hz);
- }
- }
- msg->status = -EINPROGRESS;
- msg->actual_length = 0;
-
- spin_lock_irqsave(&mcfqspi->lock, flags);
- list_add_tail(&msg->queue, &mcfqspi->msgq);
- queue_work(mcfqspi->workq, &mcfqspi->work);
- spin_unlock_irqrestore(&mcfqspi->lock, flags);
-
- return 0;
-fail:
- msg->status = -EINVAL;
- return -EINVAL;
-}
-
-static int mcfqspi_setup(struct spi_device *spi)
-{
- if ((spi->bits_per_word < 8) || (spi->bits_per_word > 16)) {
- dev_dbg(&spi->dev, "%d bits per word is not supported\n",
- spi->bits_per_word);
- return -EINVAL;
- }
- if (spi->chip_select >= spi->master->num_chipselect) {
- dev_dbg(&spi->dev, "%d chip select is out of range\n",
- spi->chip_select);
- return -EINVAL;
- }
-
- mcfqspi_cs_deselect(spi_master_get_devdata(spi->master),
- spi->chip_select, spi->mode & SPI_CS_HIGH);
-
- dev_dbg(&spi->dev,
- "bits per word %d, chip select %d, speed %d KHz\n",
- spi->bits_per_word, spi->chip_select,
- (MCFQSPI_BUSCLK / mcfqspi_qmr_baud(spi->max_speed_hz))
- / 1000);
-
- return 0;
-}
-
-static int __devinit mcfqspi_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct mcfqspi *mcfqspi;
- struct resource *res;
- struct mcfqspi_platform_data *pdata;
- int status;
-
- master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi));
- if (master == NULL) {
- dev_dbg(&pdev->dev, "spi_alloc_master failed\n");
- return -ENOMEM;
- }
-
- mcfqspi = spi_master_get_devdata(master);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_dbg(&pdev->dev, "platform_get_resource failed\n");
- status = -ENXIO;
- goto fail0;
- }
-
- if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
- dev_dbg(&pdev->dev, "request_mem_region failed\n");
- status = -EBUSY;
- goto fail0;
- }
-
- mcfqspi->iobase = ioremap(res->start, resource_size(res));
- if (!mcfqspi->iobase) {
- dev_dbg(&pdev->dev, "ioremap failed\n");
- status = -ENOMEM;
- goto fail1;
- }
-
- mcfqspi->irq = platform_get_irq(pdev, 0);
- if (mcfqspi->irq < 0) {
- dev_dbg(&pdev->dev, "platform_get_irq failed\n");
- status = -ENXIO;
- goto fail2;
- }
-
- status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
- pdev->name, mcfqspi);
- if (status) {
- dev_dbg(&pdev->dev, "request_irq failed\n");
- goto fail2;
- }
-
- mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
- if (IS_ERR(mcfqspi->clk)) {
- dev_dbg(&pdev->dev, "clk_get failed\n");
- status = PTR_ERR(mcfqspi->clk);
- goto fail3;
- }
- clk_enable(mcfqspi->clk);
-
- mcfqspi->workq = create_singlethread_workqueue(dev_name(master->dev.parent));
- if (!mcfqspi->workq) {
- dev_dbg(&pdev->dev, "create_workqueue failed\n");
- status = -ENOMEM;
- goto fail4;
- }
- INIT_WORK(&mcfqspi->work, mcfqspi_work);
- spin_lock_init(&mcfqspi->lock);
- INIT_LIST_HEAD(&mcfqspi->msgq);
- init_waitqueue_head(&mcfqspi->waitq);
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_dbg(&pdev->dev, "platform data is missing\n");
- goto fail5;
- }
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->num_chipselect;
-
- mcfqspi->cs_control = pdata->cs_control;
- status = mcfqspi_cs_setup(mcfqspi);
- if (status) {
- dev_dbg(&pdev->dev, "error initializing cs_control\n");
- goto fail5;
- }
-
- master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
- master->setup = mcfqspi_setup;
- master->transfer = mcfqspi_transfer;
-
- platform_set_drvdata(pdev, master);
-
- status = spi_register_master(master);
- if (status) {
- dev_dbg(&pdev->dev, "spi_register_master failed\n");
- goto fail6;
- }
- dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
-
- return 0;
-
-fail6:
- mcfqspi_cs_teardown(mcfqspi);
-fail5:
- destroy_workqueue(mcfqspi->workq);
-fail4:
- clk_disable(mcfqspi->clk);
- clk_put(mcfqspi->clk);
-fail3:
- free_irq(mcfqspi->irq, mcfqspi);
-fail2:
- iounmap(mcfqspi->iobase);
-fail1:
- release_mem_region(res->start, resource_size(res));
-fail0:
- spi_master_put(master);
-
- dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n");
-
- return status;
-}
-
-static int __devexit mcfqspi_remove(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- /* disable the hardware (set the baud rate to 0) */
- mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
-
- platform_set_drvdata(pdev, NULL);
- mcfqspi_cs_teardown(mcfqspi);
- destroy_workqueue(mcfqspi->workq);
- clk_disable(mcfqspi->clk);
- clk_put(mcfqspi->clk);
- free_irq(mcfqspi->irq, mcfqspi);
- iounmap(mcfqspi->iobase);
- release_mem_region(res->start, resource_size(res));
- spi_unregister_master(master);
- spi_master_put(master);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int mcfqspi_suspend(struct device *dev)
-{
- struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
-
- clk_disable(mcfqspi->clk);
-
- return 0;
-}
-
-static int mcfqspi_resume(struct device *dev)
-{
- struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
-
- clk_enable(mcfqspi->clk);
-
- return 0;
-}
-
-static struct dev_pm_ops mcfqspi_dev_pm_ops = {
- .suspend = mcfqspi_suspend,
- .resume = mcfqspi_resume,
-};
-
-#define MCFQSPI_DEV_PM_OPS (&mcfqspi_dev_pm_ops)
-#else
-#define MCFQSPI_DEV_PM_OPS NULL
-#endif
-
-static struct platform_driver mcfqspi_driver = {
- .driver.name = DRIVER_NAME,
- .driver.owner = THIS_MODULE,
- .driver.pm = MCFQSPI_DEV_PM_OPS,
- .probe = mcfqspi_probe,
- .remove = __devexit_p(mcfqspi_remove),
-};
-module_platform_driver(mcfqspi_driver);
-
-MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
-MODULE_DESCRIPTION("Coldfire QSPI Controller Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-davinci.c b/ANDROID_3.4.5/drivers/spi/spi-davinci.c
deleted file mode 100644
index 9b2901fe..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-davinci.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments.
- * Copyright (C) 2010 EF Johnson Technologies
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/slab.h>
-
-#include <mach/spi.h>
-#include <mach/edma.h>
-
-#define SPI_NO_RESOURCE ((resource_size_t)-1)
-
-#define SPI_MAX_CHIPSELECT 2
-
-#define CS_DEFAULT 0xFF
-
-#define SPIFMT_PHASE_MASK BIT(16)
-#define SPIFMT_POLARITY_MASK BIT(17)
-#define SPIFMT_DISTIMER_MASK BIT(18)
-#define SPIFMT_SHIFTDIR_MASK BIT(20)
-#define SPIFMT_WAITENA_MASK BIT(21)
-#define SPIFMT_PARITYENA_MASK BIT(22)
-#define SPIFMT_ODD_PARITY_MASK BIT(23)
-#define SPIFMT_WDELAY_MASK 0x3f000000u
-#define SPIFMT_WDELAY_SHIFT 24
-#define SPIFMT_PRESCALE_SHIFT 8
-
-/* SPIPC0 */
-#define SPIPC0_DIFUN_MASK BIT(11) /* MISO */
-#define SPIPC0_DOFUN_MASK BIT(10) /* MOSI */
-#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */
-#define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */
-
-#define SPIINT_MASKALL 0x0101035F
-#define SPIINT_MASKINT 0x0000015F
-#define SPI_INTLVL_1 0x000001FF
-#define SPI_INTLVL_0 0x00000000
-
-/* SPIDAT1 (upper 16 bit defines) */
-#define SPIDAT1_CSHOLD_MASK BIT(12)
-
-/* SPIGCR1 */
-#define SPIGCR1_CLKMOD_MASK BIT(1)
-#define SPIGCR1_MASTER_MASK BIT(0)
-#define SPIGCR1_POWERDOWN_MASK BIT(8)
-#define SPIGCR1_LOOPBACK_MASK BIT(16)
-#define SPIGCR1_SPIENA_MASK BIT(24)
-
-/* SPIBUF */
-#define SPIBUF_TXFULL_MASK BIT(29)
-#define SPIBUF_RXEMPTY_MASK BIT(31)
-
-/* SPIDELAY */
-#define SPIDELAY_C2TDELAY_SHIFT 24
-#define SPIDELAY_C2TDELAY_MASK (0xFF << SPIDELAY_C2TDELAY_SHIFT)
-#define SPIDELAY_T2CDELAY_SHIFT 16
-#define SPIDELAY_T2CDELAY_MASK (0xFF << SPIDELAY_T2CDELAY_SHIFT)
-#define SPIDELAY_T2EDELAY_SHIFT 8
-#define SPIDELAY_T2EDELAY_MASK (0xFF << SPIDELAY_T2EDELAY_SHIFT)
-#define SPIDELAY_C2EDELAY_SHIFT 0
-#define SPIDELAY_C2EDELAY_MASK 0xFF
-
-/* Error Masks */
-#define SPIFLG_DLEN_ERR_MASK BIT(0)
-#define SPIFLG_TIMEOUT_MASK BIT(1)
-#define SPIFLG_PARERR_MASK BIT(2)
-#define SPIFLG_DESYNC_MASK BIT(3)
-#define SPIFLG_BITERR_MASK BIT(4)
-#define SPIFLG_OVRRUN_MASK BIT(6)
-#define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24)
-#define SPIFLG_ERROR_MASK (SPIFLG_DLEN_ERR_MASK \
- | SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
- | SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
- | SPIFLG_OVRRUN_MASK)
-
-#define SPIINT_DMA_REQ_EN BIT(16)
-
-/* SPI Controller registers */
-#define SPIGCR0 0x00
-#define SPIGCR1 0x04
-#define SPIINT 0x08
-#define SPILVL 0x0c
-#define SPIFLG 0x10
-#define SPIPC0 0x14
-#define SPIDAT1 0x3c
-#define SPIBUF 0x40
-#define SPIDELAY 0x48
-#define SPIDEF 0x4c
-#define SPIFMT0 0x50
-
-/* We have 2 DMA channels per CS, one for RX and one for TX */
-struct davinci_spi_dma {
- int tx_channel;
- int rx_channel;
- int dummy_param_slot;
- enum dma_event_q eventq;
-};
-
-/* SPI Controller driver's private data. */
-struct davinci_spi {
- struct spi_bitbang bitbang;
- struct clk *clk;
-
- u8 version;
- resource_size_t pbase;
- void __iomem *base;
- u32 irq;
- struct completion done;
-
- const void *tx;
- void *rx;
-#define SPI_TMP_BUFSZ (SMP_CACHE_BYTES + 1)
- u8 rx_tmp_buf[SPI_TMP_BUFSZ];
- int rcount;
- int wcount;
- struct davinci_spi_dma dma;
- struct davinci_spi_platform_data *pdata;
-
- void (*get_rx)(u32 rx_data, struct davinci_spi *);
- u32 (*get_tx)(struct davinci_spi *);
-
- u8 bytes_per_word[SPI_MAX_CHIPSELECT];
-};
-
-static struct davinci_spi_config davinci_spi_default_cfg;
-
-static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *dspi)
-{
- if (dspi->rx) {
- u8 *rx = dspi->rx;
- *rx++ = (u8)data;
- dspi->rx = rx;
- }
-}
-
-static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi)
-{
- if (dspi->rx) {
- u16 *rx = dspi->rx;
- *rx++ = (u16)data;
- dspi->rx = rx;
- }
-}
-
-static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
-{
- u32 data = 0;
- if (dspi->tx) {
- const u8 *tx = dspi->tx;
- data = *tx++;
- dspi->tx = tx;
- }
- return data;
-}
-
-static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi)
-{
- u32 data = 0;
- if (dspi->tx) {
- const u16 *tx = dspi->tx;
- data = *tx++;
- dspi->tx = tx;
- }
- return data;
-}
-
-static inline void set_io_bits(void __iomem *addr, u32 bits)
-{
- u32 v = ioread32(addr);
-
- v |= bits;
- iowrite32(v, addr);
-}
-
-static inline void clear_io_bits(void __iomem *addr, u32 bits)
-{
- u32 v = ioread32(addr);
-
- v &= ~bits;
- iowrite32(v, addr);
-}
-
-/*
- * Interface to control the chip select signal
- */
-static void davinci_spi_chipselect(struct spi_device *spi, int value)
-{
- struct davinci_spi *dspi;
- struct davinci_spi_platform_data *pdata;
- u8 chip_sel = spi->chip_select;
- u16 spidat1 = CS_DEFAULT;
- bool gpio_chipsel = false;
-
- dspi = spi_master_get_devdata(spi->master);
- pdata = dspi->pdata;
-
- if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
- pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
- gpio_chipsel = true;
-
- /*
- * Board specific chip select logic decides the polarity and cs
- * line for the controller
- */
- if (gpio_chipsel) {
- if (value == BITBANG_CS_ACTIVE)
- gpio_set_value(pdata->chip_sel[chip_sel], 0);
- else
- gpio_set_value(pdata->chip_sel[chip_sel], 1);
- } else {
- if (value == BITBANG_CS_ACTIVE) {
- spidat1 |= SPIDAT1_CSHOLD_MASK;
- spidat1 &= ~(0x1 << chip_sel);
- }
-
- iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
- }
-}
-
-/**
- * davinci_spi_get_prescale - Calculates the correct prescale value
- * @maxspeed_hz: the maximum rate the SPI clock can run at
- *
- * This function calculates the prescale value that generates a clock rate
- * less than or equal to the specified maximum.
- *
- * Returns: calculated prescale - 1 for easy programming into SPI registers
- * or negative error number if valid prescalar cannot be updated.
- */
-static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
- u32 max_speed_hz)
-{
- int ret;
-
- ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
-
- if (ret < 3 || ret > 256)
- return -EINVAL;
-
- return ret - 1;
-}
-
-/**
- * davinci_spi_setup_transfer - This functions will determine transfer method
- * @spi: spi device on which data transfer to be done
- * @t: spi transfer in which transfer info is filled
- *
- * This function determines data transfer method (8/16/32 bit transfer).
- * It will also set the SPI Clock Control register according to
- * SPI slave device freq.
- */
-static int davinci_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
-
- struct davinci_spi *dspi;
- struct davinci_spi_config *spicfg;
- u8 bits_per_word = 0;
- u32 hz = 0, spifmt = 0, prescale = 0;
-
- dspi = spi_master_get_devdata(spi->master);
- spicfg = (struct davinci_spi_config *)spi->controller_data;
- if (!spicfg)
- spicfg = &davinci_spi_default_cfg;
-
- if (t) {
- bits_per_word = t->bits_per_word;
- hz = t->speed_hz;
- }
-
- /* if bits_per_word is not set then set it default */
- if (!bits_per_word)
- bits_per_word = spi->bits_per_word;
-
- /*
- * Assign function pointer to appropriate transfer method
- * 8bit, 16bit or 32bit transfer
- */
- if (bits_per_word <= 8 && bits_per_word >= 2) {
- dspi->get_rx = davinci_spi_rx_buf_u8;
- dspi->get_tx = davinci_spi_tx_buf_u8;
- dspi->bytes_per_word[spi->chip_select] = 1;
- } else if (bits_per_word <= 16 && bits_per_word >= 2) {
- dspi->get_rx = davinci_spi_rx_buf_u16;
- dspi->get_tx = davinci_spi_tx_buf_u16;
- dspi->bytes_per_word[spi->chip_select] = 2;
- } else
- return -EINVAL;
-
- if (!hz)
- hz = spi->max_speed_hz;
-
- /* Set up SPIFMTn register, unique to this chipselect. */
-
- prescale = davinci_spi_get_prescale(dspi, hz);
- if (prescale < 0)
- return prescale;
-
- spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f);
-
- if (spi->mode & SPI_LSB_FIRST)
- spifmt |= SPIFMT_SHIFTDIR_MASK;
-
- if (spi->mode & SPI_CPOL)
- spifmt |= SPIFMT_POLARITY_MASK;
-
- if (!(spi->mode & SPI_CPHA))
- spifmt |= SPIFMT_PHASE_MASK;
-
- /*
- * Version 1 hardware supports two basic SPI modes:
- * - Standard SPI mode uses 4 pins, with chipselect
- * - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
- * (distinct from SPI_3WIRE, with just one data wire;
- * or similar variants without MOSI or without MISO)
- *
- * Version 2 hardware supports an optional handshaking signal,
- * so it can support two more modes:
- * - 5 pin SPI variant is standard SPI plus SPI_READY
- * - 4 pin with enable is (SPI_READY | SPI_NO_CS)
- */
-
- if (dspi->version == SPI_VERSION_2) {
-
- u32 delay = 0;
-
- spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
- & SPIFMT_WDELAY_MASK);
-
- if (spicfg->odd_parity)
- spifmt |= SPIFMT_ODD_PARITY_MASK;
-
- if (spicfg->parity_enable)
- spifmt |= SPIFMT_PARITYENA_MASK;
-
- if (spicfg->timer_disable) {
- spifmt |= SPIFMT_DISTIMER_MASK;
- } else {
- delay |= (spicfg->c2tdelay << SPIDELAY_C2TDELAY_SHIFT)
- & SPIDELAY_C2TDELAY_MASK;
- delay |= (spicfg->t2cdelay << SPIDELAY_T2CDELAY_SHIFT)
- & SPIDELAY_T2CDELAY_MASK;
- }
-
- if (spi->mode & SPI_READY) {
- spifmt |= SPIFMT_WAITENA_MASK;
- delay |= (spicfg->t2edelay << SPIDELAY_T2EDELAY_SHIFT)
- & SPIDELAY_T2EDELAY_MASK;
- delay |= (spicfg->c2edelay << SPIDELAY_C2EDELAY_SHIFT)
- & SPIDELAY_C2EDELAY_MASK;
- }
-
- iowrite32(delay, dspi->base + SPIDELAY);
- }
-
- iowrite32(spifmt, dspi->base + SPIFMT0);
-
- return 0;
-}
-
-/**
- * davinci_spi_setup - This functions will set default transfer method
- * @spi: spi device on which data transfer to be done
- *
- * This functions sets the default transfer method.
- */
-static int davinci_spi_setup(struct spi_device *spi)
-{
- int retval = 0;
- struct davinci_spi *dspi;
- struct davinci_spi_platform_data *pdata;
-
- dspi = spi_master_get_devdata(spi->master);
- pdata = dspi->pdata;
-
- /* if bits per word length is zero then set it default 8 */
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
-
- if (!(spi->mode & SPI_NO_CS)) {
- if ((pdata->chip_sel == NULL) ||
- (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
- set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
-
- }
-
- if (spi->mode & SPI_READY)
- set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
-
- if (spi->mode & SPI_LOOP)
- set_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
- else
- clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
-
- return retval;
-}
-
-static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
-{
- struct device *sdev = dspi->bitbang.master->dev.parent;
-
- if (int_status & SPIFLG_TIMEOUT_MASK) {
- dev_dbg(sdev, "SPI Time-out Error\n");
- return -ETIMEDOUT;
- }
- if (int_status & SPIFLG_DESYNC_MASK) {
- dev_dbg(sdev, "SPI Desynchronization Error\n");
- return -EIO;
- }
- if (int_status & SPIFLG_BITERR_MASK) {
- dev_dbg(sdev, "SPI Bit error\n");
- return -EIO;
- }
-
- if (dspi->version == SPI_VERSION_2) {
- if (int_status & SPIFLG_DLEN_ERR_MASK) {
- dev_dbg(sdev, "SPI Data Length Error\n");
- return -EIO;
- }
- if (int_status & SPIFLG_PARERR_MASK) {
- dev_dbg(sdev, "SPI Parity Error\n");
- return -EIO;
- }
- if (int_status & SPIFLG_OVRRUN_MASK) {
- dev_dbg(sdev, "SPI Data Overrun error\n");
- return -EIO;
- }
- if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) {
- dev_dbg(sdev, "SPI Buffer Init Active\n");
- return -EBUSY;
- }
- }
-
- return 0;
-}
-
-/**
- * davinci_spi_process_events - check for and handle any SPI controller events
- * @dspi: the controller data
- *
- * This function will check the SPIFLG register and handle any events that are
- * detected there
- */
-static int davinci_spi_process_events(struct davinci_spi *dspi)
-{
- u32 buf, status, errors = 0, spidat1;
-
- buf = ioread32(dspi->base + SPIBUF);
-
- if (dspi->rcount > 0 && !(buf & SPIBUF_RXEMPTY_MASK)) {
- dspi->get_rx(buf & 0xFFFF, dspi);
- dspi->rcount--;
- }
-
- status = ioread32(dspi->base + SPIFLG);
-
- if (unlikely(status & SPIFLG_ERROR_MASK)) {
- errors = status & SPIFLG_ERROR_MASK;
- goto out;
- }
-
- if (dspi->wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) {
- spidat1 = ioread32(dspi->base + SPIDAT1);
- dspi->wcount--;
- spidat1 &= ~0xFFFF;
- spidat1 |= 0xFFFF & dspi->get_tx(dspi);
- iowrite32(spidat1, dspi->base + SPIDAT1);
- }
-
-out:
- return errors;
-}
-
-static void davinci_spi_dma_callback(unsigned lch, u16 status, void *data)
-{
- struct davinci_spi *dspi = data;
- struct davinci_spi_dma *dma = &dspi->dma;
-
- edma_stop(lch);
-
- if (status == DMA_COMPLETE) {
- if (lch == dma->rx_channel)
- dspi->rcount = 0;
- if (lch == dma->tx_channel)
- dspi->wcount = 0;
- }
-
- if ((!dspi->wcount && !dspi->rcount) || (status != DMA_COMPLETE))
- complete(&dspi->done);
-}
-
-/**
- * davinci_spi_bufs - functions which will handle transfer data
- * @spi: spi device on which data transfer to be done
- * @t: spi transfer in which transfer info is filled
- *
- * This function will put data to be transferred into data register
- * of SPI controller and then wait until the completion will be marked
- * by the IRQ Handler.
- */
-static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
- struct davinci_spi *dspi;
- int data_type, ret;
- u32 tx_data, spidat1;
- u32 errors = 0;
- struct davinci_spi_config *spicfg;
- struct davinci_spi_platform_data *pdata;
- unsigned uninitialized_var(rx_buf_count);
- struct device *sdev;
-
- dspi = spi_master_get_devdata(spi->master);
- pdata = dspi->pdata;
- spicfg = (struct davinci_spi_config *)spi->controller_data;
- if (!spicfg)
- spicfg = &davinci_spi_default_cfg;
- sdev = dspi->bitbang.master->dev.parent;
-
- /* convert len to words based on bits_per_word */
- data_type = dspi->bytes_per_word[spi->chip_select];
-
- dspi->tx = t->tx_buf;
- dspi->rx = t->rx_buf;
- dspi->wcount = t->len / data_type;
- dspi->rcount = dspi->wcount;
-
- spidat1 = ioread32(dspi->base + SPIDAT1);
-
- clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
- set_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
-
- INIT_COMPLETION(dspi->done);
-
- if (spicfg->io_type == SPI_IO_TYPE_INTR)
- set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
-
- if (spicfg->io_type != SPI_IO_TYPE_DMA) {
- /* start the transfer */
- dspi->wcount--;
- tx_data = dspi->get_tx(dspi);
- spidat1 &= 0xFFFF0000;
- spidat1 |= tx_data & 0xFFFF;
- iowrite32(spidat1, dspi->base + SPIDAT1);
- } else {
- struct davinci_spi_dma *dma;
- unsigned long tx_reg, rx_reg;
- struct edmacc_param param;
- void *rx_buf;
- int b, c;
-
- dma = &dspi->dma;
-
- tx_reg = (unsigned long)dspi->pbase + SPIDAT1;
- rx_reg = (unsigned long)dspi->pbase + SPIBUF;
-
- /*
- * Transmit DMA setup
- *
- * If there is transmit data, map the transmit buffer, set it
- * as the source of data and set the source B index to data
- * size. If there is no transmit data, set the transmit register
- * as the source of data, and set the source B index to zero.
- *
- * The destination is always the transmit register itself. And
- * the destination never increments.
- */
-
- if (t->tx_buf) {
- t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
- t->len, DMA_TO_DEVICE);
- if (dma_mapping_error(&spi->dev, t->tx_dma)) {
- dev_dbg(sdev, "Unable to DMA map %d bytes"
- "TX buffer\n", t->len);
- return -ENOMEM;
- }
- }
-
- /*
- * If number of words is greater than 65535, then we need
- * to configure a 3 dimension transfer. Use the BCNTRLD
- * feature to allow for transfers that aren't even multiples
- * of 65535 (or any other possible b size) by first transferring
- * the remainder amount then grabbing the next N blocks of
- * 65535 words.
- */
-
- c = dspi->wcount / (SZ_64K - 1); /* N 65535 Blocks */
- b = dspi->wcount - c * (SZ_64K - 1); /* Remainder */
- if (b)
- c++;
- else
- b = SZ_64K - 1;
-
- param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
- param.src = t->tx_buf ? t->tx_dma : tx_reg;
- param.a_b_cnt = b << 16 | data_type;
- param.dst = tx_reg;
- param.src_dst_bidx = t->tx_buf ? data_type : 0;
- param.link_bcntrld = 0xffffffff;
- param.src_dst_cidx = t->tx_buf ? data_type : 0;
- param.ccnt = c;
- edma_write_slot(dma->tx_channel, &param);
- edma_link(dma->tx_channel, dma->dummy_param_slot);
-
- /*
- * Receive DMA setup
- *
- * If there is receive buffer, use it to receive data. If there
- * is none provided, use a temporary receive buffer. Set the
- * destination B index to 0 so effectively only one byte is used
- * in the temporary buffer (address does not increment).
- *
- * The source of receive data is the receive data register. The
- * source address never increments.
- */
-
- if (t->rx_buf) {
- rx_buf = t->rx_buf;
- rx_buf_count = t->len;
- } else {
- rx_buf = dspi->rx_tmp_buf;
- rx_buf_count = sizeof(dspi->rx_tmp_buf);
- }
-
- t->rx_dma = dma_map_single(&spi->dev, rx_buf, rx_buf_count,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(&spi->dev, t->rx_dma)) {
- dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
- rx_buf_count);
- if (t->tx_buf)
- dma_unmap_single(&spi->dev, t->tx_dma, t->len,
- DMA_TO_DEVICE);
- return -ENOMEM;
- }
-
- param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
- param.src = rx_reg;
- param.a_b_cnt = b << 16 | data_type;
- param.dst = t->rx_dma;
- param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
- param.link_bcntrld = 0xffffffff;
- param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
- param.ccnt = c;
- edma_write_slot(dma->rx_channel, &param);
-
- if (pdata->cshold_bug)
- iowrite16(spidat1 >> 16, dspi->base + SPIDAT1 + 2);
-
- edma_start(dma->rx_channel);
- edma_start(dma->tx_channel);
- set_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
- }
-
- /* Wait for the transfer to complete */
- if (spicfg->io_type != SPI_IO_TYPE_POLL) {
- wait_for_completion_interruptible(&(dspi->done));
- } else {
- while (dspi->rcount > 0 || dspi->wcount > 0) {
- errors = davinci_spi_process_events(dspi);
- if (errors)
- break;
- cpu_relax();
- }
- }
-
- clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
- if (spicfg->io_type == SPI_IO_TYPE_DMA) {
-
- if (t->tx_buf)
- dma_unmap_single(&spi->dev, t->tx_dma, t->len,
- DMA_TO_DEVICE);
-
- dma_unmap_single(&spi->dev, t->rx_dma, rx_buf_count,
- DMA_FROM_DEVICE);
-
- clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
- }
-
- clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
- set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
-
- /*
- * Check for bit error, desync error,parity error,timeout error and
- * receive overflow errors
- */
- if (errors) {
- ret = davinci_spi_check_error(dspi, errors);
- WARN(!ret, "%s: error reported but no error found!\n",
- dev_name(&spi->dev));
- return ret;
- }
-
- if (dspi->rcount != 0 || dspi->wcount != 0) {
- dev_err(sdev, "SPI data transfer error\n");
- return -EIO;
- }
-
- return t->len;
-}
-
-/**
- * davinci_spi_irq - Interrupt handler for SPI Master Controller
- * @irq: IRQ number for this SPI Master
- * @context_data: structure for SPI Master controller davinci_spi
- *
- * ISR will determine that interrupt arrives either for READ or WRITE command.
- * According to command it will do the appropriate action. It will check
- * transfer length and if it is not zero then dispatch transfer command again.
- * If transfer length is zero then it will indicate the COMPLETION so that
- * davinci_spi_bufs function can go ahead.
- */
-static irqreturn_t davinci_spi_irq(s32 irq, void *data)
-{
- struct davinci_spi *dspi = data;
- int status;
-
- status = davinci_spi_process_events(dspi);
- if (unlikely(status != 0))
- clear_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
-
- if ((!dspi->rcount && !dspi->wcount) || status)
- complete(&dspi->done);
-
- return IRQ_HANDLED;
-}
-
-static int davinci_spi_request_dma(struct davinci_spi *dspi)
-{
- int r;
- struct davinci_spi_dma *dma = &dspi->dma;
-
- r = edma_alloc_channel(dma->rx_channel, davinci_spi_dma_callback, dspi,
- dma->eventq);
- if (r < 0) {
- pr_err("Unable to request DMA channel for SPI RX\n");
- r = -EAGAIN;
- goto rx_dma_failed;
- }
-
- r = edma_alloc_channel(dma->tx_channel, davinci_spi_dma_callback, dspi,
- dma->eventq);
- if (r < 0) {
- pr_err("Unable to request DMA channel for SPI TX\n");
- r = -EAGAIN;
- goto tx_dma_failed;
- }
-
- r = edma_alloc_slot(EDMA_CTLR(dma->tx_channel), EDMA_SLOT_ANY);
- if (r < 0) {
- pr_err("Unable to request SPI TX DMA param slot\n");
- r = -EAGAIN;
- goto param_failed;
- }
- dma->dummy_param_slot = r;
- edma_link(dma->dummy_param_slot, dma->dummy_param_slot);
-
- return 0;
-param_failed:
- edma_free_channel(dma->tx_channel);
-tx_dma_failed:
- edma_free_channel(dma->rx_channel);
-rx_dma_failed:
- return r;
-}
-
-/**
- * davinci_spi_probe - probe function for SPI Master Controller
- * @pdev: platform_device structure which contains plateform specific data
- *
- * According to Linux Device Model this function will be invoked by Linux
- * with platform_device struct which contains the device specific info.
- * This function will map the SPI controller's memory, register IRQ,
- * Reset SPI controller and setting its registers to default value.
- * It will invoke spi_bitbang_start to create work queue so that client driver
- * can register transfer method to work queue.
- */
-static int __devinit davinci_spi_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct davinci_spi *dspi;
- struct davinci_spi_platform_data *pdata;
- struct resource *r, *mem;
- resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
- resource_size_t dma_tx_chan = SPI_NO_RESOURCE;
- int i = 0, ret = 0;
- u32 spipc0;
-
- pdata = pdev->dev.platform_data;
- if (pdata == NULL) {
- ret = -ENODEV;
- goto err;
- }
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
- if (master == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- dev_set_drvdata(&pdev->dev, master);
-
- dspi = spi_master_get_devdata(master);
- if (dspi == NULL) {
- ret = -ENOENT;
- goto free_master;
- }
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENOENT;
- goto free_master;
- }
-
- dspi->pbase = r->start;
- dspi->pdata = pdata;
-
- mem = request_mem_region(r->start, resource_size(r), pdev->name);
- if (mem == NULL) {
- ret = -EBUSY;
- goto free_master;
- }
-
- dspi->base = ioremap(r->start, resource_size(r));
- if (dspi->base == NULL) {
- ret = -ENOMEM;
- goto release_region;
- }
-
- dspi->irq = platform_get_irq(pdev, 0);
- if (dspi->irq <= 0) {
- ret = -EINVAL;
- goto unmap_io;
- }
-
- ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev),
- dspi);
- if (ret)
- goto unmap_io;
-
- dspi->bitbang.master = spi_master_get(master);
- if (dspi->bitbang.master == NULL) {
- ret = -ENODEV;
- goto irq_free;
- }
-
- dspi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dspi->clk)) {
- ret = -ENODEV;
- goto put_master;
- }
- clk_enable(dspi->clk);
-
- master->bus_num = pdev->id;
- master->num_chipselect = pdata->num_chipselect;
- master->setup = davinci_spi_setup;
-
- dspi->bitbang.chipselect = davinci_spi_chipselect;
- dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
-
- dspi->version = pdata->version;
-
- dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
- if (dspi->version == SPI_VERSION_2)
- dspi->bitbang.flags |= SPI_READY;
-
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (r)
- dma_rx_chan = r->start;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (r)
- dma_tx_chan = r->start;
-
- dspi->bitbang.txrx_bufs = davinci_spi_bufs;
- if (dma_rx_chan != SPI_NO_RESOURCE &&
- dma_tx_chan != SPI_NO_RESOURCE) {
- dspi->dma.rx_channel = dma_rx_chan;
- dspi->dma.tx_channel = dma_tx_chan;
- dspi->dma.eventq = pdata->dma_event_q;
-
- ret = davinci_spi_request_dma(dspi);
- if (ret)
- goto free_clk;
-
- dev_info(&pdev->dev, "DMA: supported\n");
- dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
- "event queue: %d\n", dma_rx_chan, dma_tx_chan,
- pdata->dma_event_q);
- }
-
- dspi->get_rx = davinci_spi_rx_buf_u8;
- dspi->get_tx = davinci_spi_tx_buf_u8;
-
- init_completion(&dspi->done);
-
- /* Reset In/OUT SPI module */
- iowrite32(0, dspi->base + SPIGCR0);
- udelay(100);
- iowrite32(1, dspi->base + SPIGCR0);
-
- /* Set up SPIPC0. CS and ENA init is done in davinci_spi_setup */
- spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
- iowrite32(spipc0, dspi->base + SPIPC0);
-
- /* initialize chip selects */
- if (pdata->chip_sel) {
- for (i = 0; i < pdata->num_chipselect; i++) {
- if (pdata->chip_sel[i] != SPI_INTERN_CS)
- gpio_direction_output(pdata->chip_sel[i], 1);
- }
- }
-
- if (pdata->intr_line)
- iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);
- else
- iowrite32(SPI_INTLVL_0, dspi->base + SPILVL);
-
- iowrite32(CS_DEFAULT, dspi->base + SPIDEF);
-
- /* master mode default */
- set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
- set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
- set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
-
- ret = spi_bitbang_start(&dspi->bitbang);
- if (ret)
- goto free_dma;
-
- dev_info(&pdev->dev, "Controller at 0x%p\n", dspi->base);
-
- return ret;
-
-free_dma:
- edma_free_channel(dspi->dma.tx_channel);
- edma_free_channel(dspi->dma.rx_channel);
- edma_free_slot(dspi->dma.dummy_param_slot);
-free_clk:
- clk_disable(dspi->clk);
- clk_put(dspi->clk);
-put_master:
- spi_master_put(master);
-irq_free:
- free_irq(dspi->irq, dspi);
-unmap_io:
- iounmap(dspi->base);
-release_region:
- release_mem_region(dspi->pbase, resource_size(r));
-free_master:
- kfree(master);
-err:
- return ret;
-}
-
-/**
- * davinci_spi_remove - remove function for SPI Master Controller
- * @pdev: platform_device structure which contains plateform specific data
- *
- * This function will do the reverse action of davinci_spi_probe function
- * It will free the IRQ and SPI controller's memory region.
- * It will also call spi_bitbang_stop to destroy the work queue which was
- * created by spi_bitbang_start.
- */
-static int __devexit davinci_spi_remove(struct platform_device *pdev)
-{
- struct davinci_spi *dspi;
- struct spi_master *master;
- struct resource *r;
-
- master = dev_get_drvdata(&pdev->dev);
- dspi = spi_master_get_devdata(master);
-
- spi_bitbang_stop(&dspi->bitbang);
-
- clk_disable(dspi->clk);
- clk_put(dspi->clk);
- spi_master_put(master);
- free_irq(dspi->irq, dspi);
- iounmap(dspi->base);
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(dspi->pbase, resource_size(r));
-
- return 0;
-}
-
-static struct platform_driver davinci_spi_driver = {
- .driver = {
- .name = "spi_davinci",
- .owner = THIS_MODULE,
- },
- .probe = davinci_spi_probe,
- .remove = __devexit_p(davinci_spi_remove),
-};
-module_platform_driver(davinci_spi_driver);
-
-MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-dw-mid.c b/ANDROID_3.4.5/drivers/spi/spi-dw-mid.c
deleted file mode 100644
index b9f01927..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-dw-mid.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Special handling for DW core on Intel MID platform
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/types.h>
-
-#include "spi-dw.h"
-
-#ifdef CONFIG_SPI_DW_MID_DMA
-#include <linux/intel_mid_dma.h>
-#include <linux/pci.h>
-
-struct mid_dma {
- struct intel_mid_dma_slave dmas_tx;
- struct intel_mid_dma_slave dmas_rx;
-};
-
-static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
-{
- struct dw_spi *dws = param;
-
- return dws->dmac && (&dws->dmac->dev == chan->device->dev);
-}
-
-static int mid_spi_dma_init(struct dw_spi *dws)
-{
- struct mid_dma *dw_dma = dws->dma_priv;
- struct intel_mid_dma_slave *rxs, *txs;
- dma_cap_mask_t mask;
-
- /*
- * Get pci device for DMA controller, currently it could only
- * be the DMA controller of either Moorestown or Medfield
- */
- dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
- if (!dws->dmac)
- dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- /* 1. Init rx channel */
- dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
- if (!dws->rxchan)
- goto err_exit;
- rxs = &dw_dma->dmas_rx;
- rxs->hs_mode = LNW_DMA_HW_HS;
- rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
- dws->rxchan->private = rxs;
-
- /* 2. Init tx channel */
- dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
- if (!dws->txchan)
- goto free_rxchan;
- txs = &dw_dma->dmas_tx;
- txs->hs_mode = LNW_DMA_HW_HS;
- txs->cfg_mode = LNW_DMA_MEM_TO_PER;
- dws->txchan->private = txs;
-
- dws->dma_inited = 1;
- return 0;
-
-free_rxchan:
- dma_release_channel(dws->rxchan);
-err_exit:
- return -1;
-
-}
-
-static void mid_spi_dma_exit(struct dw_spi *dws)
-{
- dma_release_channel(dws->txchan);
- dma_release_channel(dws->rxchan);
-}
-
-/*
- * dws->dma_chan_done is cleared before the dma transfer starts,
- * callback for rx/tx channel will each increment it by 1.
- * Reaching 2 means the whole spi transaction is done.
- */
-static void dw_spi_dma_done(void *arg)
-{
- struct dw_spi *dws = arg;
-
- if (++dws->dma_chan_done != 2)
- return;
- dw_spi_xfer_done(dws);
-}
-
-static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
-{
- struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
- struct dma_chan *txchan, *rxchan;
- struct dma_slave_config txconf, rxconf;
- u16 dma_ctrl = 0;
-
- /* 1. setup DMA related registers */
- if (cs_change) {
- spi_enable_chip(dws, 0);
- dw_writew(dws, DW_SPI_DMARDLR, 0xf);
- dw_writew(dws, DW_SPI_DMATDLR, 0x10);
- if (dws->tx_dma)
- dma_ctrl |= 0x2;
- if (dws->rx_dma)
- dma_ctrl |= 0x1;
- dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
- spi_enable_chip(dws, 1);
- }
-
- dws->dma_chan_done = 0;
- txchan = dws->txchan;
- rxchan = dws->rxchan;
-
- /* 2. Prepare the TX dma transfer */
- txconf.direction = DMA_MEM_TO_DEV;
- txconf.dst_addr = dws->dma_addr;
- txconf.dst_maxburst = LNW_DMA_MSIZE_16;
- txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- txconf.device_fc = false;
-
- txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
- (unsigned long) &txconf);
-
- memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
- dws->tx_sgl.dma_address = dws->tx_dma;
- dws->tx_sgl.length = dws->len;
-
- txdesc = dmaengine_prep_slave_sg(txchan,
- &dws->tx_sgl,
- 1,
- DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
- txdesc->callback = dw_spi_dma_done;
- txdesc->callback_param = dws;
-
- /* 3. Prepare the RX dma transfer */
- rxconf.direction = DMA_DEV_TO_MEM;
- rxconf.src_addr = dws->dma_addr;
- rxconf.src_maxburst = LNW_DMA_MSIZE_16;
- rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- rxconf.device_fc = false;
-
- rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
- (unsigned long) &rxconf);
-
- memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
- dws->rx_sgl.dma_address = dws->rx_dma;
- dws->rx_sgl.length = dws->len;
-
- rxdesc = dmaengine_prep_slave_sg(rxchan,
- &dws->rx_sgl,
- 1,
- DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
- rxdesc->callback = dw_spi_dma_done;
- rxdesc->callback_param = dws;
-
- /* rx must be started before tx due to spi instinct */
- rxdesc->tx_submit(rxdesc);
- txdesc->tx_submit(txdesc);
- return 0;
-}
-
-static struct dw_spi_dma_ops mid_dma_ops = {
- .dma_init = mid_spi_dma_init,
- .dma_exit = mid_spi_dma_exit,
- .dma_transfer = mid_spi_dma_transfer,
-};
-#endif
-
-/* Some specific info for SPI0 controller on Moorestown */
-
-/* HW info for MRST CLk Control Unit, one 32b reg */
-#define MRST_SPI_CLK_BASE 100000000 /* 100m */
-#define MRST_CLK_SPI0_REG 0xff11d86c
-#define CLK_SPI_BDIV_OFFSET 0
-#define CLK_SPI_BDIV_MASK 0x00000007
-#define CLK_SPI_CDIV_OFFSET 9
-#define CLK_SPI_CDIV_MASK 0x00000e00
-#define CLK_SPI_DISABLE_OFFSET 8
-
-int dw_spi_mid_init(struct dw_spi *dws)
-{
- void __iomem *clk_reg;
- u32 clk_cdiv;
-
- clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
- if (!clk_reg)
- return -ENOMEM;
-
- /* get SPI controller operating freq info */
- clk_cdiv = (readl(clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
- dws->max_freq = MRST_SPI_CLK_BASE / (clk_cdiv + 1);
- iounmap(clk_reg);
-
- dws->num_cs = 16;
- dws->fifo_len = 40; /* FIFO has 40 words buffer */
-
-#ifdef CONFIG_SPI_DW_MID_DMA
- dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
- if (!dws->dma_priv)
- return -ENOMEM;
- dws->dma_ops = &mid_dma_ops;
-#endif
- return 0;
-}
diff --git a/ANDROID_3.4.5/drivers/spi/spi-dw-mmio.c b/ANDROID_3.4.5/drivers/spi/spi-dw-mmio.c
deleted file mode 100644
index db2f1ba0..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-dw-mmio.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Memory-mapped interface driver for DW SPI Core
- *
- * Copyright (c) 2010, Octasic semiconductor.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/scatterlist.h>
-#include <linux/module.h>
-
-#include "spi-dw.h"
-
-#define DRIVER_NAME "dw_spi_mmio"
-
-struct dw_spi_mmio {
- struct dw_spi dws;
- struct clk *clk;
-};
-
-static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
-{
- struct dw_spi_mmio *dwsmmio;
- struct dw_spi *dws;
- struct resource *mem, *ioarea;
- int ret;
-
- dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
- if (!dwsmmio) {
- ret = -ENOMEM;
- goto err_end;
- }
-
- dws = &dwsmmio->dws;
-
- /* Get basic io resource and map it */
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no mem resource?\n");
- ret = -EINVAL;
- goto err_kfree;
- }
-
- ioarea = request_mem_region(mem->start, resource_size(mem),
- pdev->name);
- if (!ioarea) {
- dev_err(&pdev->dev, "SPI region already claimed\n");
- ret = -EBUSY;
- goto err_kfree;
- }
-
- dws->regs = ioremap_nocache(mem->start, resource_size(mem));
- if (!dws->regs) {
- dev_err(&pdev->dev, "SPI region already mapped\n");
- ret = -ENOMEM;
- goto err_release_reg;
- }
-
- dws->irq = platform_get_irq(pdev, 0);
- if (dws->irq < 0) {
- dev_err(&pdev->dev, "no irq resource?\n");
- ret = dws->irq; /* -ENXIO */
- goto err_unmap;
- }
-
- dwsmmio->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dwsmmio->clk)) {
- ret = PTR_ERR(dwsmmio->clk);
- goto err_irq;
- }
- clk_enable(dwsmmio->clk);
-
- dws->parent_dev = &pdev->dev;
- dws->bus_num = 0;
- dws->num_cs = 4;
- dws->max_freq = clk_get_rate(dwsmmio->clk);
-
- ret = dw_spi_add_host(dws);
- if (ret)
- goto err_clk;
-
- platform_set_drvdata(pdev, dwsmmio);
- return 0;
-
-err_clk:
- clk_disable(dwsmmio->clk);
- clk_put(dwsmmio->clk);
- dwsmmio->clk = NULL;
-err_irq:
- free_irq(dws->irq, dws);
-err_unmap:
- iounmap(dws->regs);
-err_release_reg:
- release_mem_region(mem->start, resource_size(mem));
-err_kfree:
- kfree(dwsmmio);
-err_end:
- return ret;
-}
-
-static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
-{
- struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
- struct resource *mem;
-
- platform_set_drvdata(pdev, NULL);
-
- clk_disable(dwsmmio->clk);
- clk_put(dwsmmio->clk);
- dwsmmio->clk = NULL;
-
- free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
- dw_spi_remove_host(&dwsmmio->dws);
- iounmap(dwsmmio->dws.regs);
- kfree(dwsmmio);
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- return 0;
-}
-
-static struct platform_driver dw_spi_mmio_driver = {
- .probe = dw_spi_mmio_probe,
- .remove = __devexit_p(dw_spi_mmio_remove),
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(dw_spi_mmio_driver);
-
-MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
-MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-dw-pci.c b/ANDROID_3.4.5/drivers/spi/spi-dw-pci.c
deleted file mode 100644
index 14f7cc95..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-dw-pci.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * PCI interface driver for DW SPI Core
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/module.h>
-
-#include "spi-dw.h"
-
-#define DRIVER_NAME "dw_spi_pci"
-
-struct dw_spi_pci {
- struct pci_dev *pdev;
- struct dw_spi dws;
-};
-
-static int __devinit spi_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct dw_spi_pci *dwpci;
- struct dw_spi *dws;
- int pci_bar = 0;
- int ret;
-
- printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n",
- pdev->vendor, pdev->device);
-
- ret = pci_enable_device(pdev);
- if (ret)
- return ret;
-
- dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
- if (!dwpci) {
- ret = -ENOMEM;
- goto err_disable;
- }
-
- dwpci->pdev = pdev;
- dws = &dwpci->dws;
-
- /* Get basic io resource and map it */
- dws->paddr = pci_resource_start(pdev, pci_bar);
- dws->iolen = pci_resource_len(pdev, pci_bar);
-
- ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
- if (ret)
- goto err_kfree;
-
- dws->regs = ioremap_nocache((unsigned long)dws->paddr,
- pci_resource_len(pdev, pci_bar));
- if (!dws->regs) {
- ret = -ENOMEM;
- goto err_release_reg;
- }
-
- dws->parent_dev = &pdev->dev;
- dws->bus_num = 0;
- dws->num_cs = 4;
- dws->irq = pdev->irq;
-
- /*
- * Specific handling for Intel MID paltforms, like dma setup,
- * clock rate, FIFO depth.
- */
- if (pdev->device == 0x0800) {
- ret = dw_spi_mid_init(dws);
- if (ret)
- goto err_unmap;
- }
-
- ret = dw_spi_add_host(dws);
- if (ret)
- goto err_unmap;
-
- /* PCI hook and SPI hook use the same drv data */
- pci_set_drvdata(pdev, dwpci);
- return 0;
-
-err_unmap:
- iounmap(dws->regs);
-err_release_reg:
- pci_release_region(pdev, pci_bar);
-err_kfree:
- kfree(dwpci);
-err_disable:
- pci_disable_device(pdev);
- return ret;
-}
-
-static void __devexit spi_pci_remove(struct pci_dev *pdev)
-{
- struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
-
- pci_set_drvdata(pdev, NULL);
- dw_spi_remove_host(&dwpci->dws);
- iounmap(dwpci->dws.regs);
- pci_release_region(pdev, 0);
- kfree(dwpci);
- pci_disable_device(pdev);
-}
-
-#ifdef CONFIG_PM
-static int spi_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
- int ret;
-
- ret = dw_spi_suspend_host(&dwpci->dws);
- if (ret)
- return ret;
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- return ret;
-}
-
-static int spi_resume(struct pci_dev *pdev)
-{
- struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
- int ret;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- ret = pci_enable_device(pdev);
- if (ret)
- return ret;
- return dw_spi_resume_host(&dwpci->dws);
-}
-#else
-#define spi_suspend NULL
-#define spi_resume NULL
-#endif
-
-static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
- /* Intel MID platform SPI controller 0 */
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
- {},
-};
-
-static struct pci_driver dw_spi_driver = {
- .name = DRIVER_NAME,
- .id_table = pci_ids,
- .probe = spi_pci_probe,
- .remove = __devexit_p(spi_pci_remove),
- .suspend = spi_suspend,
- .resume = spi_resume,
-};
-
-static int __init mrst_spi_init(void)
-{
- return pci_register_driver(&dw_spi_driver);
-}
-
-static void __exit mrst_spi_exit(void)
-{
- pci_unregister_driver(&dw_spi_driver);
-}
-
-module_init(mrst_spi_init);
-module_exit(mrst_spi_exit);
-
-MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
-MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-dw.c b/ANDROID_3.4.5/drivers/spi/spi-dw.c
deleted file mode 100644
index d1a495f6..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-dw.c
+++ /dev/null
@@ -1,933 +0,0 @@
-/*
- * Designware SPI core controller driver (refer pxa2xx_spi.c)
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/highmem.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include "spi-dw.h"
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#endif
-
-#define START_STATE ((void *)0)
-#define RUNNING_STATE ((void *)1)
-#define DONE_STATE ((void *)2)
-#define ERROR_STATE ((void *)-1)
-
-#define QUEUE_RUNNING 0
-#define QUEUE_STOPPED 1
-
-#define MRST_SPI_DEASSERT 0
-#define MRST_SPI_ASSERT 1
-
-/* Slave spi_dev related */
-struct chip_data {
- u16 cr0;
- u8 cs; /* chip select pin */
- u8 n_bytes; /* current is a 1/2/4 byte op */
- u8 tmode; /* TR/TO/RO/EEPROM */
- u8 type; /* SPI/SSP/MicroWire */
-
- u8 poll_mode; /* 1 means use poll mode */
-
- u32 dma_width;
- u32 rx_threshold;
- u32 tx_threshold;
- u8 enable_dma;
- u8 bits_per_word;
- u16 clk_div; /* baud rate divider */
- u32 speed_hz; /* baud rate */
- void (*cs_control)(u32 command);
-};
-
-#ifdef CONFIG_DEBUG_FS
-#define SPI_REGS_BUFSIZE 1024
-static ssize_t spi_show_regs(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct dw_spi *dws;
- char *buf;
- u32 len = 0;
- ssize_t ret;
-
- dws = file->private_data;
-
- buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
- if (!buf)
- return 0;
-
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "MRST SPI0 registers:\n");
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "=================================\n");
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
- len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "=================================\n");
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
- return ret;
-}
-
-static const struct file_operations mrst_spi_regs_ops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = spi_show_regs,
- .llseek = default_llseek,
-};
-
-static int mrst_spi_debugfs_init(struct dw_spi *dws)
-{
- dws->debugfs = debugfs_create_dir("mrst_spi", NULL);
- if (!dws->debugfs)
- return -ENOMEM;
-
- debugfs_create_file("registers", S_IFREG | S_IRUGO,
- dws->debugfs, (void *)dws, &mrst_spi_regs_ops);
- return 0;
-}
-
-static void mrst_spi_debugfs_remove(struct dw_spi *dws)
-{
- if (dws->debugfs)
- debugfs_remove_recursive(dws->debugfs);
-}
-
-#else
-static inline int mrst_spi_debugfs_init(struct dw_spi *dws)
-{
- return 0;
-}
-
-static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
-/* Return the max entries we can fill into tx fifo */
-static inline u32 tx_max(struct dw_spi *dws)
-{
- u32 tx_left, tx_room, rxtx_gap;
-
- tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
- tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR);
-
- /*
- * Another concern is about the tx/rx mismatch, we
- * though to use (dws->fifo_len - rxflr - txflr) as
- * one maximum value for tx, but it doesn't cover the
- * data which is out of tx/rx fifo and inside the
- * shift registers. So a control from sw point of
- * view is taken.
- */
- rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx))
- / dws->n_bytes;
-
- return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap));
-}
-
-/* Return the max entries we should read out of rx fifo */
-static inline u32 rx_max(struct dw_spi *dws)
-{
- u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
-
- return min(rx_left, (u32)dw_readw(dws, DW_SPI_RXFLR));
-}
-
-static void dw_writer(struct dw_spi *dws)
-{
- u32 max = tx_max(dws);
- u16 txw = 0;
-
- while (max--) {
- /* Set the tx word if the transfer's original "tx" is not null */
- if (dws->tx_end - dws->len) {
- if (dws->n_bytes == 1)
- txw = *(u8 *)(dws->tx);
- else
- txw = *(u16 *)(dws->tx);
- }
- dw_writew(dws, DW_SPI_DR, txw);
- dws->tx += dws->n_bytes;
- }
-}
-
-static void dw_reader(struct dw_spi *dws)
-{
- u32 max = rx_max(dws);
- u16 rxw;
-
- while (max--) {
- rxw = dw_readw(dws, DW_SPI_DR);
- /* Care rx only if the transfer's original "rx" is not null */
- if (dws->rx_end - dws->len) {
- if (dws->n_bytes == 1)
- *(u8 *)(dws->rx) = rxw;
- else
- *(u16 *)(dws->rx) = rxw;
- }
- dws->rx += dws->n_bytes;
- }
-}
-
-static void *next_transfer(struct dw_spi *dws)
-{
- struct spi_message *msg = dws->cur_msg;
- struct spi_transfer *trans = dws->cur_transfer;
-
- /* Move to next transfer */
- if (trans->transfer_list.next != &msg->transfers) {
- dws->cur_transfer =
- list_entry(trans->transfer_list.next,
- struct spi_transfer,
- transfer_list);
- return RUNNING_STATE;
- } else
- return DONE_STATE;
-}
-
-/*
- * Note: first step is the protocol driver prepares
- * a dma-capable memory, and this func just need translate
- * the virt addr to physical
- */
-static int map_dma_buffers(struct dw_spi *dws)
-{
- if (!dws->cur_msg->is_dma_mapped
- || !dws->dma_inited
- || !dws->cur_chip->enable_dma
- || !dws->dma_ops)
- return 0;
-
- if (dws->cur_transfer->tx_dma)
- dws->tx_dma = dws->cur_transfer->tx_dma;
-
- if (dws->cur_transfer->rx_dma)
- dws->rx_dma = dws->cur_transfer->rx_dma;
-
- return 1;
-}
-
-/* Caller already set message->status; dma and pio irqs are blocked */
-static void giveback(struct dw_spi *dws)
-{
- struct spi_transfer *last_transfer;
- unsigned long flags;
- struct spi_message *msg;
-
- spin_lock_irqsave(&dws->lock, flags);
- msg = dws->cur_msg;
- dws->cur_msg = NULL;
- dws->cur_transfer = NULL;
- dws->prev_chip = dws->cur_chip;
- dws->cur_chip = NULL;
- dws->dma_mapped = 0;
- queue_work(dws->workqueue, &dws->pump_messages);
- spin_unlock_irqrestore(&dws->lock, flags);
-
- last_transfer = list_entry(msg->transfers.prev,
- struct spi_transfer,
- transfer_list);
-
- if (!last_transfer->cs_change && dws->cs_control)
- dws->cs_control(MRST_SPI_DEASSERT);
-
- msg->state = NULL;
- if (msg->complete)
- msg->complete(msg->context);
-}
-
-static void int_error_stop(struct dw_spi *dws, const char *msg)
-{
- /* Stop the hw */
- spi_enable_chip(dws, 0);
-
- dev_err(&dws->master->dev, "%s\n", msg);
- dws->cur_msg->state = ERROR_STATE;
- tasklet_schedule(&dws->pump_transfers);
-}
-
-void dw_spi_xfer_done(struct dw_spi *dws)
-{
- /* Update total byte transferred return count actual bytes read */
- dws->cur_msg->actual_length += dws->len;
-
- /* Move to next transfer */
- dws->cur_msg->state = next_transfer(dws);
-
- /* Handle end of message */
- if (dws->cur_msg->state == DONE_STATE) {
- dws->cur_msg->status = 0;
- giveback(dws);
- } else
- tasklet_schedule(&dws->pump_transfers);
-}
-EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
-
-static irqreturn_t interrupt_transfer(struct dw_spi *dws)
-{
- u16 irq_status = dw_readw(dws, DW_SPI_ISR);
-
- /* Error handling */
- if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
- dw_readw(dws, DW_SPI_TXOICR);
- dw_readw(dws, DW_SPI_RXOICR);
- dw_readw(dws, DW_SPI_RXUICR);
- int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
- return IRQ_HANDLED;
- }
-
- dw_reader(dws);
- if (dws->rx_end == dws->rx) {
- spi_mask_intr(dws, SPI_INT_TXEI);
- dw_spi_xfer_done(dws);
- return IRQ_HANDLED;
- }
- if (irq_status & SPI_INT_TXEI) {
- spi_mask_intr(dws, SPI_INT_TXEI);
- dw_writer(dws);
- /* Enable TX irq always, it will be disabled when RX finished */
- spi_umask_intr(dws, SPI_INT_TXEI);
- }
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t dw_spi_irq(int irq, void *dev_id)
-{
- struct dw_spi *dws = dev_id;
- u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f;
-
- if (!irq_status)
- return IRQ_NONE;
-
- if (!dws->cur_msg) {
- spi_mask_intr(dws, SPI_INT_TXEI);
- return IRQ_HANDLED;
- }
-
- return dws->transfer_handler(dws);
-}
-
-/* Must be called inside pump_transfers() */
-static void poll_transfer(struct dw_spi *dws)
-{
- do {
- dw_writer(dws);
- dw_reader(dws);
- cpu_relax();
- } while (dws->rx_end > dws->rx);
-
- dw_spi_xfer_done(dws);
-}
-
-static void pump_transfers(unsigned long data)
-{
- struct dw_spi *dws = (struct dw_spi *)data;
- struct spi_message *message = NULL;
- struct spi_transfer *transfer = NULL;
- struct spi_transfer *previous = NULL;
- struct spi_device *spi = NULL;
- struct chip_data *chip = NULL;
- u8 bits = 0;
- u8 imask = 0;
- u8 cs_change = 0;
- u16 txint_level = 0;
- u16 clk_div = 0;
- u32 speed = 0;
- u32 cr0 = 0;
-
- /* Get current state information */
- message = dws->cur_msg;
- transfer = dws->cur_transfer;
- chip = dws->cur_chip;
- spi = message->spi;
-
- if (unlikely(!chip->clk_div))
- chip->clk_div = dws->max_freq / chip->speed_hz;
-
- if (message->state == ERROR_STATE) {
- message->status = -EIO;
- goto early_exit;
- }
-
- /* Handle end of message */
- if (message->state == DONE_STATE) {
- message->status = 0;
- goto early_exit;
- }
-
- /* Delay if requested at end of transfer*/
- if (message->state == RUNNING_STATE) {
- previous = list_entry(transfer->transfer_list.prev,
- struct spi_transfer,
- transfer_list);
- if (previous->delay_usecs)
- udelay(previous->delay_usecs);
- }
-
- dws->n_bytes = chip->n_bytes;
- dws->dma_width = chip->dma_width;
- dws->cs_control = chip->cs_control;
-
- dws->rx_dma = transfer->rx_dma;
- dws->tx_dma = transfer->tx_dma;
- dws->tx = (void *)transfer->tx_buf;
- dws->tx_end = dws->tx + transfer->len;
- dws->rx = transfer->rx_buf;
- dws->rx_end = dws->rx + transfer->len;
- dws->cs_change = transfer->cs_change;
- dws->len = dws->cur_transfer->len;
- if (chip != dws->prev_chip)
- cs_change = 1;
-
- cr0 = chip->cr0;
-
- /* Handle per transfer options for bpw and speed */
- if (transfer->speed_hz) {
- speed = chip->speed_hz;
-
- if (transfer->speed_hz != speed) {
- speed = transfer->speed_hz;
- if (speed > dws->max_freq) {
- printk(KERN_ERR "MRST SPI0: unsupported"
- "freq: %dHz\n", speed);
- message->status = -EIO;
- goto early_exit;
- }
-
- /* clk_div doesn't support odd number */
- clk_div = dws->max_freq / speed;
- clk_div = (clk_div + 1) & 0xfffe;
-
- chip->speed_hz = speed;
- chip->clk_div = clk_div;
- }
- }
- if (transfer->bits_per_word) {
- bits = transfer->bits_per_word;
-
- switch (bits) {
- case 8:
- case 16:
- dws->n_bytes = dws->dma_width = bits >> 3;
- break;
- default:
- printk(KERN_ERR "MRST SPI0: unsupported bits:"
- "%db\n", bits);
- message->status = -EIO;
- goto early_exit;
- }
-
- cr0 = (bits - 1)
- | (chip->type << SPI_FRF_OFFSET)
- | (spi->mode << SPI_MODE_OFFSET)
- | (chip->tmode << SPI_TMOD_OFFSET);
- }
- message->state = RUNNING_STATE;
-
- /*
- * Adjust transfer mode if necessary. Requires platform dependent
- * chipselect mechanism.
- */
- if (dws->cs_control) {
- if (dws->rx && dws->tx)
- chip->tmode = SPI_TMOD_TR;
- else if (dws->rx)
- chip->tmode = SPI_TMOD_RO;
- else
- chip->tmode = SPI_TMOD_TO;
-
- cr0 &= ~SPI_TMOD_MASK;
- cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
- }
-
- /* Check if current transfer is a DMA transaction */
- dws->dma_mapped = map_dma_buffers(dws);
-
- /*
- * Interrupt mode
- * we only need set the TXEI IRQ, as TX/RX always happen syncronizely
- */
- if (!dws->dma_mapped && !chip->poll_mode) {
- int templen = dws->len / dws->n_bytes;
- txint_level = dws->fifo_len / 2;
- txint_level = (templen > txint_level) ? txint_level : templen;
-
- imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI;
- dws->transfer_handler = interrupt_transfer;
- }
-
- /*
- * Reprogram registers only if
- * 1. chip select changes
- * 2. clk_div is changed
- * 3. control value changes
- */
- if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) {
- spi_enable_chip(dws, 0);
-
- if (dw_readw(dws, DW_SPI_CTRL0) != cr0)
- dw_writew(dws, DW_SPI_CTRL0, cr0);
-
- spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
- spi_chip_sel(dws, spi->chip_select);
-
- /* Set the interrupt mask, for poll mode just disable all int */
- spi_mask_intr(dws, 0xff);
- if (imask)
- spi_umask_intr(dws, imask);
- if (txint_level)
- dw_writew(dws, DW_SPI_TXFLTR, txint_level);
-
- spi_enable_chip(dws, 1);
- if (cs_change)
- dws->prev_chip = chip;
- }
-
- if (dws->dma_mapped)
- dws->dma_ops->dma_transfer(dws, cs_change);
-
- if (chip->poll_mode)
- poll_transfer(dws);
-
- return;
-
-early_exit:
- giveback(dws);
- return;
-}
-
-static void pump_messages(struct work_struct *work)
-{
- struct dw_spi *dws =
- container_of(work, struct dw_spi, pump_messages);
- unsigned long flags;
-
- /* Lock queue and check for queue work */
- spin_lock_irqsave(&dws->lock, flags);
- if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {
- dws->busy = 0;
- spin_unlock_irqrestore(&dws->lock, flags);
- return;
- }
-
- /* Make sure we are not already running a message */
- if (dws->cur_msg) {
- spin_unlock_irqrestore(&dws->lock, flags);
- return;
- }
-
- /* Extract head of queue */
- dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);
- list_del_init(&dws->cur_msg->queue);
-
- /* Initial message state*/
- dws->cur_msg->state = START_STATE;
- dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
- struct spi_transfer,
- transfer_list);
- dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
-
- /* Mark as busy and launch transfers */
- tasklet_schedule(&dws->pump_transfers);
-
- dws->busy = 1;
- spin_unlock_irqrestore(&dws->lock, flags);
-}
-
-/* spi_device use this to queue in their spi_msg */
-static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct dw_spi *dws = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&dws->lock, flags);
-
- if (dws->run == QUEUE_STOPPED) {
- spin_unlock_irqrestore(&dws->lock, flags);
- return -ESHUTDOWN;
- }
-
- msg->actual_length = 0;
- msg->status = -EINPROGRESS;
- msg->state = START_STATE;
-
- list_add_tail(&msg->queue, &dws->queue);
-
- if (dws->run == QUEUE_RUNNING && !dws->busy) {
-
- if (dws->cur_transfer || dws->cur_msg)
- queue_work(dws->workqueue,
- &dws->pump_messages);
- else {
- /* If no other data transaction in air, just go */
- spin_unlock_irqrestore(&dws->lock, flags);
- pump_messages(&dws->pump_messages);
- return 0;
- }
- }
-
- spin_unlock_irqrestore(&dws->lock, flags);
- return 0;
-}
-
-/* This may be called twice for each spi dev */
-static int dw_spi_setup(struct spi_device *spi)
-{
- struct dw_spi_chip *chip_info = NULL;
- struct chip_data *chip;
-
- if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
- return -EINVAL;
-
- /* Only alloc on first setup */
- chip = spi_get_ctldata(spi);
- if (!chip) {
- chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
- }
-
- /*
- * Protocol drivers may change the chip settings, so...
- * if chip_info exists, use it
- */
- chip_info = spi->controller_data;
-
- /* chip_info doesn't always exist */
- if (chip_info) {
- if (chip_info->cs_control)
- chip->cs_control = chip_info->cs_control;
-
- chip->poll_mode = chip_info->poll_mode;
- chip->type = chip_info->type;
-
- chip->rx_threshold = 0;
- chip->tx_threshold = 0;
-
- chip->enable_dma = chip_info->enable_dma;
- }
-
- if (spi->bits_per_word <= 8) {
- chip->n_bytes = 1;
- chip->dma_width = 1;
- } else if (spi->bits_per_word <= 16) {
- chip->n_bytes = 2;
- chip->dma_width = 2;
- } else {
- /* Never take >16b case for MRST SPIC */
- dev_err(&spi->dev, "invalid wordsize\n");
- return -EINVAL;
- }
- chip->bits_per_word = spi->bits_per_word;
-
- if (!spi->max_speed_hz) {
- dev_err(&spi->dev, "No max speed HZ parameter\n");
- return -EINVAL;
- }
- chip->speed_hz = spi->max_speed_hz;
-
- chip->tmode = 0; /* Tx & Rx */
- /* Default SPI mode is SCPOL = 0, SCPH = 0 */
- chip->cr0 = (chip->bits_per_word - 1)
- | (chip->type << SPI_FRF_OFFSET)
- | (spi->mode << SPI_MODE_OFFSET)
- | (chip->tmode << SPI_TMOD_OFFSET);
-
- spi_set_ctldata(spi, chip);
- return 0;
-}
-
-static void dw_spi_cleanup(struct spi_device *spi)
-{
- struct chip_data *chip = spi_get_ctldata(spi);
- kfree(chip);
-}
-
-static int __devinit init_queue(struct dw_spi *dws)
-{
- INIT_LIST_HEAD(&dws->queue);
- spin_lock_init(&dws->lock);
-
- dws->run = QUEUE_STOPPED;
- dws->busy = 0;
-
- tasklet_init(&dws->pump_transfers,
- pump_transfers, (unsigned long)dws);
-
- INIT_WORK(&dws->pump_messages, pump_messages);
- dws->workqueue = create_singlethread_workqueue(
- dev_name(dws->master->dev.parent));
- if (dws->workqueue == NULL)
- return -EBUSY;
-
- return 0;
-}
-
-static int start_queue(struct dw_spi *dws)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dws->lock, flags);
-
- if (dws->run == QUEUE_RUNNING || dws->busy) {
- spin_unlock_irqrestore(&dws->lock, flags);
- return -EBUSY;
- }
-
- dws->run = QUEUE_RUNNING;
- dws->cur_msg = NULL;
- dws->cur_transfer = NULL;
- dws->cur_chip = NULL;
- dws->prev_chip = NULL;
- spin_unlock_irqrestore(&dws->lock, flags);
-
- queue_work(dws->workqueue, &dws->pump_messages);
-
- return 0;
-}
-
-static int stop_queue(struct dw_spi *dws)
-{
- unsigned long flags;
- unsigned limit = 50;
- int status = 0;
-
- spin_lock_irqsave(&dws->lock, flags);
- dws->run = QUEUE_STOPPED;
- while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
- spin_unlock_irqrestore(&dws->lock, flags);
- msleep(10);
- spin_lock_irqsave(&dws->lock, flags);
- }
-
- if (!list_empty(&dws->queue) || dws->busy)
- status = -EBUSY;
- spin_unlock_irqrestore(&dws->lock, flags);
-
- return status;
-}
-
-static int destroy_queue(struct dw_spi *dws)
-{
- int status;
-
- status = stop_queue(dws);
- if (status != 0)
- return status;
- destroy_workqueue(dws->workqueue);
- return 0;
-}
-
-/* Restart the controller, disable all interrupts, clean rx fifo */
-static void spi_hw_init(struct dw_spi *dws)
-{
- spi_enable_chip(dws, 0);
- spi_mask_intr(dws, 0xff);
- spi_enable_chip(dws, 1);
-
- /*
- * Try to detect the FIFO depth if not set by interface driver,
- * the depth could be from 2 to 256 from HW spec
- */
- if (!dws->fifo_len) {
- u32 fifo;
- for (fifo = 2; fifo <= 257; fifo++) {
- dw_writew(dws, DW_SPI_TXFLTR, fifo);
- if (fifo != dw_readw(dws, DW_SPI_TXFLTR))
- break;
- }
-
- dws->fifo_len = (fifo == 257) ? 0 : fifo;
- dw_writew(dws, DW_SPI_TXFLTR, 0);
- }
-}
-
-int __devinit dw_spi_add_host(struct dw_spi *dws)
-{
- struct spi_master *master;
- int ret;
-
- BUG_ON(dws == NULL);
-
- master = spi_alloc_master(dws->parent_dev, 0);
- if (!master) {
- ret = -ENOMEM;
- goto exit;
- }
-
- dws->master = master;
- dws->type = SSI_MOTO_SPI;
- 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,
- dws->name, dws);
- if (ret < 0) {
- dev_err(&master->dev, "can not get IRQ\n");
- goto err_free_master;
- }
-
- master->mode_bits = SPI_CPOL | SPI_CPHA;
- master->bus_num = dws->bus_num;
- master->num_chipselect = dws->num_cs;
- master->cleanup = dw_spi_cleanup;
- master->setup = dw_spi_setup;
- master->transfer = dw_spi_transfer;
-
- /* Basic HW init */
- spi_hw_init(dws);
-
- if (dws->dma_ops && dws->dma_ops->dma_init) {
- ret = dws->dma_ops->dma_init(dws);
- if (ret) {
- dev_warn(&master->dev, "DMA init failed\n");
- dws->dma_inited = 0;
- }
- }
-
- /* Initial and start queue */
- ret = init_queue(dws);
- if (ret) {
- dev_err(&master->dev, "problem initializing queue\n");
- goto err_diable_hw;
- }
- ret = start_queue(dws);
- if (ret) {
- dev_err(&master->dev, "problem starting queue\n");
- goto err_diable_hw;
- }
-
- spi_master_set_devdata(master, dws);
- ret = spi_register_master(master);
- if (ret) {
- dev_err(&master->dev, "problem registering spi master\n");
- goto err_queue_alloc;
- }
-
- mrst_spi_debugfs_init(dws);
- return 0;
-
-err_queue_alloc:
- destroy_queue(dws);
- if (dws->dma_ops && dws->dma_ops->dma_exit)
- dws->dma_ops->dma_exit(dws);
-err_diable_hw:
- spi_enable_chip(dws, 0);
- free_irq(dws->irq, dws);
-err_free_master:
- spi_master_put(master);
-exit:
- return ret;
-}
-EXPORT_SYMBOL_GPL(dw_spi_add_host);
-
-void __devexit dw_spi_remove_host(struct dw_spi *dws)
-{
- int status = 0;
-
- if (!dws)
- return;
- mrst_spi_debugfs_remove(dws);
-
- /* Remove the queue */
- status = destroy_queue(dws);
- if (status != 0)
- dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
- "complete, message memory not freed\n");
-
- if (dws->dma_ops && dws->dma_ops->dma_exit)
- dws->dma_ops->dma_exit(dws);
- spi_enable_chip(dws, 0);
- /* Disable clk */
- spi_set_clk(dws, 0);
- free_irq(dws->irq, dws);
-
- /* Disconnect from the SPI framework */
- spi_unregister_master(dws->master);
-}
-EXPORT_SYMBOL_GPL(dw_spi_remove_host);
-
-int dw_spi_suspend_host(struct dw_spi *dws)
-{
- int ret = 0;
-
- ret = stop_queue(dws);
- if (ret)
- return ret;
- spi_enable_chip(dws, 0);
- spi_set_clk(dws, 0);
- return ret;
-}
-EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
-
-int dw_spi_resume_host(struct dw_spi *dws)
-{
- int ret;
-
- spi_hw_init(dws);
- ret = start_queue(dws);
- if (ret)
- dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
- return ret;
-}
-EXPORT_SYMBOL_GPL(dw_spi_resume_host);
-
-MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
-MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-dw.h b/ANDROID_3.4.5/drivers/spi/spi-dw.h
deleted file mode 100644
index 9c57c078..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-dw.h
+++ /dev/null
@@ -1,242 +0,0 @@
-#ifndef DW_SPI_HEADER_H
-#define DW_SPI_HEADER_H
-
-#include <linux/io.h>
-#include <linux/scatterlist.h>
-
-/* Register offsets */
-#define DW_SPI_CTRL0 0x00
-#define DW_SPI_CTRL1 0x04
-#define DW_SPI_SSIENR 0x08
-#define DW_SPI_MWCR 0x0c
-#define DW_SPI_SER 0x10
-#define DW_SPI_BAUDR 0x14
-#define DW_SPI_TXFLTR 0x18
-#define DW_SPI_RXFLTR 0x1c
-#define DW_SPI_TXFLR 0x20
-#define DW_SPI_RXFLR 0x24
-#define DW_SPI_SR 0x28
-#define DW_SPI_IMR 0x2c
-#define DW_SPI_ISR 0x30
-#define DW_SPI_RISR 0x34
-#define DW_SPI_TXOICR 0x38
-#define DW_SPI_RXOICR 0x3c
-#define DW_SPI_RXUICR 0x40
-#define DW_SPI_MSTICR 0x44
-#define DW_SPI_ICR 0x48
-#define DW_SPI_DMACR 0x4c
-#define DW_SPI_DMATDLR 0x50
-#define DW_SPI_DMARDLR 0x54
-#define DW_SPI_IDR 0x58
-#define DW_SPI_VERSION 0x5c
-#define DW_SPI_DR 0x60
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET 0
-
-#define SPI_FRF_OFFSET 4
-#define SPI_FRF_SPI 0x0
-#define SPI_FRF_SSP 0x1
-#define SPI_FRF_MICROWIRE 0x2
-#define SPI_FRF_RESV 0x3
-
-#define SPI_MODE_OFFSET 6
-#define SPI_SCPH_OFFSET 6
-#define SPI_SCOL_OFFSET 7
-
-#define SPI_TMOD_OFFSET 8
-#define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET)
-#define SPI_TMOD_TR 0x0 /* xmit & recv */
-#define SPI_TMOD_TO 0x1 /* xmit only */
-#define SPI_TMOD_RO 0x2 /* recv only */
-#define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET 10
-#define SPI_SRL_OFFSET 11
-#define SPI_CFS_OFFSET 12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK 0x7f /* cover 7 bits */
-#define SR_BUSY (1 << 0)
-#define SR_TF_NOT_FULL (1 << 1)
-#define SR_TF_EMPT (1 << 2)
-#define SR_RF_NOT_EMPT (1 << 3)
-#define SR_RF_FULL (1 << 4)
-#define SR_TX_ERR (1 << 5)
-#define SR_DCOL (1 << 6)
-
-/* Bit fields in ISR, IMR, RISR, 7 bits */
-#define SPI_INT_TXEI (1 << 0)
-#define SPI_INT_TXOI (1 << 1)
-#define SPI_INT_RXUI (1 << 2)
-#define SPI_INT_RXOI (1 << 3)
-#define SPI_INT_RXFI (1 << 4)
-#define SPI_INT_MSTI (1 << 5)
-
-/* TX RX interrupt level threshold, max can be 256 */
-#define SPI_INT_THRESHOLD 32
-
-enum dw_ssi_type {
- SSI_MOTO_SPI = 0,
- SSI_TI_SSP,
- SSI_NS_MICROWIRE,
-};
-
-struct dw_spi;
-struct dw_spi_dma_ops {
- int (*dma_init)(struct dw_spi *dws);
- void (*dma_exit)(struct dw_spi *dws);
- int (*dma_transfer)(struct dw_spi *dws, int cs_change);
-};
-
-struct dw_spi {
- struct spi_master *master;
- struct spi_device *cur_dev;
- struct device *parent_dev;
- enum dw_ssi_type type;
- char name[16];
-
- void __iomem *regs;
- unsigned long paddr;
- u32 iolen;
- int irq;
- u32 fifo_len; /* depth of the FIFO buffer */
- u32 max_freq; /* max bus freq supported */
-
- u16 bus_num;
- u16 num_cs; /* supported slave numbers */
-
- /* Driver message queue */
- struct workqueue_struct *workqueue;
- struct work_struct pump_messages;
- spinlock_t lock;
- struct list_head queue;
- int busy;
- int run;
-
- /* Message Transfer pump */
- struct tasklet_struct pump_transfers;
-
- /* Current message transfer state info */
- struct spi_message *cur_msg;
- struct spi_transfer *cur_transfer;
- struct chip_data *cur_chip;
- struct chip_data *prev_chip;
- size_t len;
- void *tx;
- void *tx_end;
- void *rx;
- void *rx_end;
- int dma_mapped;
- dma_addr_t rx_dma;
- dma_addr_t tx_dma;
- size_t rx_map_len;
- size_t tx_map_len;
- u8 n_bytes; /* current is a 1/2 bytes op */
- u8 max_bits_per_word; /* maxim is 16b */
- u32 dma_width;
- int cs_change;
- irqreturn_t (*transfer_handler)(struct dw_spi *dws);
- void (*cs_control)(u32 command);
-
- /* Dma info */
- int dma_inited;
- struct dma_chan *txchan;
- struct scatterlist tx_sgl;
- struct dma_chan *rxchan;
- struct scatterlist rx_sgl;
- int dma_chan_done;
- struct device *dma_dev;
- dma_addr_t dma_addr; /* phy address of the Data register */
- struct dw_spi_dma_ops *dma_ops;
- void *dma_priv; /* platform relate info */
- struct pci_dev *dmac;
-
- /* Bus interface info */
- void *priv;
-#ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs;
-#endif
-};
-
-static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
-{
- return __raw_readl(dws->regs + offset);
-}
-
-static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
-{
- __raw_writel(val, dws->regs + offset);
-}
-
-static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
-{
- return __raw_readw(dws->regs + offset);
-}
-
-static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
-{
- __raw_writew(val, dws->regs + offset);
-}
-
-static inline void spi_enable_chip(struct dw_spi *dws, int enable)
-{
- dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
-}
-
-static inline void spi_set_clk(struct dw_spi *dws, u16 div)
-{
- dw_writel(dws, DW_SPI_BAUDR, div);
-}
-
-static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
-{
- if (cs > dws->num_cs)
- return;
-
- if (dws->cs_control)
- dws->cs_control(1);
-
- dw_writel(dws, DW_SPI_SER, 1 << cs);
-}
-
-/* Disable IRQ bits */
-static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
-{
- u32 new_mask;
-
- new_mask = dw_readl(dws, DW_SPI_IMR) & ~mask;
- dw_writel(dws, DW_SPI_IMR, new_mask);
-}
-
-/* Enable IRQ bits */
-static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
-{
- u32 new_mask;
-
- new_mask = dw_readl(dws, DW_SPI_IMR) | mask;
- dw_writel(dws, DW_SPI_IMR, new_mask);
-}
-
-/*
- * Each SPI slave device to work with dw_api controller should
- * has such a structure claiming its working mode (PIO/DMA etc),
- * which can be save in the "controller_data" member of the
- * struct spi_device
- */
-struct dw_spi_chip {
- u8 poll_mode; /* 0 for contoller polling mode */
- u8 type; /* SPI/SSP/Micrwire */
- u8 enable_dma;
- void (*cs_control)(u32 command);
-};
-
-extern int dw_spi_add_host(struct dw_spi *dws);
-extern void dw_spi_remove_host(struct dw_spi *dws);
-extern int dw_spi_suspend_host(struct dw_spi *dws);
-extern int dw_spi_resume_host(struct dw_spi *dws);
-extern void dw_spi_xfer_done(struct dw_spi *dws);
-
-/* platform related setup */
-extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
-#endif /* DW_SPI_HEADER_H */
diff --git a/ANDROID_3.4.5/drivers/spi/spi-ep93xx.c b/ANDROID_3.4.5/drivers/spi/spi-ep93xx.c
deleted file mode 100644
index e8055073..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-ep93xx.c
+++ /dev/null
@@ -1,1207 +0,0 @@
-/*
- * Driver for Cirrus Logic EP93xx SPI controller.
- *
- * Copyright (C) 2010-2011 Mika Westerberg
- *
- * Explicit FIFO handling code was inspired by amba-pl022 driver.
- *
- * Chip select support using other than built-in GPIOs by H. Hartley Sweeten.
- *
- * For more information about the SPI controller see documentation on Cirrus
- * Logic web site:
- * http://www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf
- *
- * 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/io.h>
-#include <linux/clk.h>
-#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/module.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
-#define SSPCR0_MODE_SHIFT 6
-#define SSPCR0_SCR_SHIFT 8
-
-#define SSPCR1 0x0004
-#define SSPCR1_RIE BIT(0)
-#define SSPCR1_TIE BIT(1)
-#define SSPCR1_RORIE BIT(2)
-#define SSPCR1_LBM BIT(3)
-#define SSPCR1_SSE BIT(4)
-#define SSPCR1_MS BIT(5)
-#define SSPCR1_SOD BIT(6)
-
-#define SSPDR 0x0008
-
-#define SSPSR 0x000c
-#define SSPSR_TFE BIT(0)
-#define SSPSR_TNF BIT(1)
-#define SSPSR_RNE BIT(2)
-#define SSPSR_RFF BIT(3)
-#define SSPSR_BSY BIT(4)
-#define SSPCPSR 0x0010
-
-#define SSPIIR 0x0014
-#define SSPIIR_RIS BIT(0)
-#define SSPIIR_TIS BIT(1)
-#define SSPIIR_RORIS BIT(2)
-#define SSPICR SSPIIR
-
-/* timeout in milliseconds */
-#define SPI_TIMEOUT 5
-/* maximum depth of RX/TX FIFO */
-#define SPI_FIFO_SIZE 8
-
-/**
- * struct ep93xx_spi - EP93xx SPI controller structure
- * @lock: spinlock that protects concurrent accesses to fields @running,
- * @current_msg and @msg_queue
- * @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
- * @running: is the queue running
- * @wq: workqueue used by the driver
- * @msg_work: work that is queued for the driver
- * @wait: wait here until given transfer is completed
- * @msg_queue: queue for the messages
- * @current_msg: message that is currently processed (or %NULL if none)
- * @tx: current byte in transfer to transmit
- * @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.
- * @current_msg is used to hold pointer to the message that is currently
- * processed. If @current_msg is %NULL, it means that no processing is going
- * on.
- *
- * Most of the fields are only written once and they can be accessed without
- * taking the @lock. Fields that are accessed concurrently are: @current_msg,
- * @running, and @msg_queue.
- */
-struct ep93xx_spi {
- spinlock_t lock;
- 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;
- bool running;
- struct workqueue_struct *wq;
- struct work_struct msg_work;
- struct completion wait;
- struct list_head msg_queue;
- struct spi_message *current_msg;
- 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;
-};
-
-/**
- * struct ep93xx_spi_chip - SPI device hardware settings
- * @spi: back pointer to the SPI device
- * @rate: max rate in hz this chip supports
- * @div_cpsr: cpsr (pre-scaler) divider
- * @div_scr: scr divider
- * @dss: bits per word (4 - 16 bits)
- * @ops: private chip operations
- *
- * This structure is used to store hardware register specific settings for each
- * SPI device. Settings are written to hardware by function
- * ep93xx_spi_chip_setup().
- */
-struct ep93xx_spi_chip {
- const struct spi_device *spi;
- unsigned long rate;
- u8 div_cpsr;
- u8 div_scr;
- u8 dss;
- struct ep93xx_spi_chip_ops *ops;
-};
-
-/* converts bits per word to CR0.DSS value */
-#define bits_per_word_to_dss(bpw) ((bpw) - 1)
-
-static inline void
-ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value)
-{
- __raw_writeb(value, espi->regs_base + reg);
-}
-
-static inline u8
-ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
-{
- return __raw_readb(spi->regs_base + reg);
-}
-
-static inline void
-ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value)
-{
- __raw_writew(value, espi->regs_base + reg);
-}
-
-static inline u16
-ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
-{
- return __raw_readw(spi->regs_base + reg);
-}
-
-static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
-{
- u8 regval;
- int err;
-
- err = clk_enable(espi->clk);
- if (err)
- return err;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval |= SSPCR1_SSE;
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-
- return 0;
-}
-
-static void ep93xx_spi_disable(const struct ep93xx_spi *espi)
-{
- u8 regval;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval &= ~SSPCR1_SSE;
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-
- clk_disable(espi->clk);
-}
-
-static void ep93xx_spi_enable_interrupts(const struct ep93xx_spi *espi)
-{
- u8 regval;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-}
-
-static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
-{
- u8 regval;
-
- regval = ep93xx_spi_read_u8(espi, SSPCR1);
- regval &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
- ep93xx_spi_write_u8(espi, SSPCR1, regval);
-}
-
-/**
- * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
- * @espi: ep93xx SPI controller struct
- * @chip: divisors are calculated for this chip
- * @rate: desired SPI output clock rate
- *
- * Function calculates cpsr (clock pre-scaler) and scr divisors based on
- * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
- * for some reason, divisors cannot be calculated nothing is stored and
- * %-EINVAL is returned.
- */
-static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
- struct ep93xx_spi_chip *chip,
- unsigned long rate)
-{
- unsigned long spi_clk_rate = clk_get_rate(espi->clk);
- int cpsr, scr;
-
- /*
- * Make sure that max value is between values supported by the
- * controller. Note that minimum value is already checked in
- * ep93xx_spi_transfer().
- */
- rate = clamp(rate, espi->min_rate, espi->max_rate);
-
- /*
- * Calculate divisors so that we can get speed according the
- * following formula:
- * rate = spi_clock_rate / (cpsr * (1 + scr))
- *
- * cpsr must be even number and starts from 2, scr can be any number
- * between 0 and 255.
- */
- for (cpsr = 2; cpsr <= 254; cpsr += 2) {
- for (scr = 0; scr <= 255; scr++) {
- if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
- chip->div_scr = (u8)scr;
- chip->div_cpsr = (u8)cpsr;
- return 0;
- }
- }
- }
-
- return -EINVAL;
-}
-
-static void ep93xx_spi_cs_control(struct spi_device *spi, bool control)
-{
- struct ep93xx_spi_chip *chip = spi_get_ctldata(spi);
- int value = (spi->mode & SPI_CS_HIGH) ? control : !control;
-
- if (chip->ops && chip->ops->cs_control)
- chip->ops->cs_control(spi, value);
-}
-
-/**
- * ep93xx_spi_setup() - setup an SPI device
- * @spi: SPI device to setup
- *
- * This function sets up SPI device mode, speed etc. Can be called multiple
- * times for a single device. Returns %0 in case of success, negative error in
- * case of failure. When this function returns success, the device is
- * deselected.
- */
-static int ep93xx_spi_setup(struct spi_device *spi)
-{
- struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
- struct ep93xx_spi_chip *chip;
-
- if (spi->bits_per_word < 4 || spi->bits_per_word > 16) {
- dev_err(&espi->pdev->dev, "invalid bits per word %d\n",
- spi->bits_per_word);
- return -EINVAL;
- }
-
- chip = spi_get_ctldata(spi);
- if (!chip) {
- dev_dbg(&espi->pdev->dev, "initial setup for %s\n",
- spi->modalias);
-
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- chip->spi = spi;
- chip->ops = spi->controller_data;
-
- if (chip->ops && chip->ops->setup) {
- int ret = chip->ops->setup(spi);
- if (ret) {
- kfree(chip);
- return ret;
- }
- }
-
- spi_set_ctldata(spi, chip);
- }
-
- if (spi->max_speed_hz != chip->rate) {
- int err;
-
- err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz);
- if (err != 0) {
- spi_set_ctldata(spi, NULL);
- kfree(chip);
- return err;
- }
- chip->rate = spi->max_speed_hz;
- }
-
- chip->dss = bits_per_word_to_dss(spi->bits_per_word);
-
- ep93xx_spi_cs_control(spi, false);
- return 0;
-}
-
-/**
- * ep93xx_spi_transfer() - queue message to be transferred
- * @spi: target SPI device
- * @msg: message to be transferred
- *
- * This function is called by SPI device drivers when they are going to transfer
- * a new message. It simply puts the message in the queue and schedules
- * workqueue to perform the actual transfer later on.
- *
- * Returns %0 on success and negative error in case of failure.
- */
-static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
- struct spi_transfer *t;
- unsigned long flags;
-
- if (!msg || !msg->complete)
- return -EINVAL;
-
- /* first validate each transfer */
- list_for_each_entry(t, &msg->transfers, transfer_list) {
- if (t->bits_per_word) {
- if (t->bits_per_word < 4 || t->bits_per_word > 16)
- return -EINVAL;
- }
- if (t->speed_hz && t->speed_hz < espi->min_rate)
- return -EINVAL;
- }
-
- /*
- * Now that we own the message, let's initialize it so that it is
- * suitable for us. We use @msg->status to signal whether there was
- * error in transfer and @msg->state is used to hold pointer to the
- * current transfer (or %NULL if no active current transfer).
- */
- msg->state = NULL;
- msg->status = 0;
- msg->actual_length = 0;
-
- spin_lock_irqsave(&espi->lock, flags);
- if (!espi->running) {
- spin_unlock_irqrestore(&espi->lock, flags);
- return -ESHUTDOWN;
- }
- list_add_tail(&msg->queue, &espi->msg_queue);
- queue_work(espi->wq, &espi->msg_work);
- spin_unlock_irqrestore(&espi->lock, flags);
-
- return 0;
-}
-
-/**
- * ep93xx_spi_cleanup() - cleans up master controller specific state
- * @spi: SPI device to cleanup
- *
- * This function releases master controller specific state for given @spi
- * device.
- */
-static void ep93xx_spi_cleanup(struct spi_device *spi)
-{
- struct ep93xx_spi_chip *chip;
-
- chip = spi_get_ctldata(spi);
- if (chip) {
- if (chip->ops && chip->ops->cleanup)
- chip->ops->cleanup(spi);
- spi_set_ctldata(spi, NULL);
- kfree(chip);
- }
-}
-
-/**
- * ep93xx_spi_chip_setup() - configures hardware according to given @chip
- * @espi: ep93xx SPI controller struct
- * @chip: chip specific settings
- *
- * This function sets up the actual hardware registers with settings given in
- * @chip. Note that no validation is done so make sure that callers validate
- * settings before calling this.
- */
-static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
- const struct ep93xx_spi_chip *chip)
-{
- u16 cr0;
-
- cr0 = chip->div_scr << SSPCR0_SCR_SHIFT;
- cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT;
- cr0 |= chip->dss;
-
- dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
- chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss);
- dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
-
- ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr);
- ep93xx_spi_write_u16(espi, SSPCR0, cr0);
-}
-
-static inline int bits_per_word(const struct ep93xx_spi *espi)
-{
- struct spi_message *msg = espi->current_msg;
- struct spi_transfer *t = msg->state;
-
- return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word;
-}
-
-static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
-{
- if (bits_per_word(espi) > 8) {
- u16 tx_val = 0;
-
- if (t->tx_buf)
- tx_val = ((u16 *)t->tx_buf)[espi->tx];
- ep93xx_spi_write_u16(espi, SSPDR, tx_val);
- espi->tx += sizeof(tx_val);
- } else {
- u8 tx_val = 0;
-
- if (t->tx_buf)
- tx_val = ((u8 *)t->tx_buf)[espi->tx];
- ep93xx_spi_write_u8(espi, SSPDR, tx_val);
- espi->tx += sizeof(tx_val);
- }
-}
-
-static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
-{
- if (bits_per_word(espi) > 8) {
- u16 rx_val;
-
- rx_val = ep93xx_spi_read_u16(espi, SSPDR);
- if (t->rx_buf)
- ((u16 *)t->rx_buf)[espi->rx] = rx_val;
- espi->rx += sizeof(rx_val);
- } else {
- u8 rx_val;
-
- rx_val = ep93xx_spi_read_u8(espi, SSPDR);
- if (t->rx_buf)
- ((u8 *)t->rx_buf)[espi->rx] = rx_val;
- espi->rx += sizeof(rx_val);
- }
-}
-
-/**
- * ep93xx_spi_read_write() - perform next RX/TX transfer
- * @espi: ep93xx SPI controller struct
- *
- * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If
- * called several times, the whole transfer will be completed. Returns
- * %-EINPROGRESS when current transfer was not yet completed otherwise %0.
- *
- * When this function is finished, RX FIFO should be empty and TX FIFO should be
- * full.
- */
-static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
-{
- struct spi_message *msg = espi->current_msg;
- struct spi_transfer *t = msg->state;
-
- /* read as long as RX FIFO has frames in it */
- while ((ep93xx_spi_read_u8(espi, SSPSR) & SSPSR_RNE)) {
- ep93xx_do_read(espi, t);
- espi->fifo_level--;
- }
-
- /* write as long as TX FIFO has room */
- while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < t->len) {
- ep93xx_do_write(espi, t);
- espi->fifo_level++;
- }
-
- 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_transfer_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_DEV_TO_MEM) {
- 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 = dmaengine_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_transfer_direction dir)
-{
- struct dma_chan *chan;
- struct sg_table *sgt;
-
- if (dir == DMA_DEV_TO_MEM) {
- 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_DEV_TO_MEM);
- 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_MEM_TO_DEV);
- if (IS_ERR(txd)) {
- ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
- 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_MEM_TO_DEV);
- ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
-}
-
-/**
- * ep93xx_spi_process_transfer() - processes one SPI transfer
- * @espi: ep93xx SPI controller struct
- * @msg: current message
- * @t: transfer to process
- *
- * This function processes one SPI transfer given in @t. Function waits until
- * transfer is complete (may sleep) and updates @msg->status based on whether
- * transfer was successfully processed or not.
- */
-static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
- struct spi_message *msg,
- struct spi_transfer *t)
-{
- struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
-
- msg->state = t;
-
- /*
- * Handle any transfer specific settings if needed. We use
- * temporary chip settings here and restore original later when
- * the transfer is finished.
- */
- if (t->speed_hz || t->bits_per_word) {
- struct ep93xx_spi_chip tmp_chip = *chip;
-
- if (t->speed_hz) {
- int err;
-
- err = ep93xx_spi_calc_divisors(espi, &tmp_chip,
- t->speed_hz);
- if (err) {
- dev_err(&espi->pdev->dev,
- "failed to adjust speed\n");
- msg->status = err;
- return;
- }
- }
-
- if (t->bits_per_word)
- tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word);
-
- /*
- * Set up temporary new hw settings for this transfer.
- */
- ep93xx_spi_chip_setup(espi, &tmp_chip);
- }
-
- espi->rx = 0;
- espi->tx = 0;
-
- /*
- * 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 (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
- * the message.
- */
- 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.
- */
- if (t->delay_usecs) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(usecs_to_jiffies(t->delay_usecs));
- }
- if (t->cs_change) {
- if (!list_is_last(&t->transfer_list, &msg->transfers)) {
- /*
- * In case protocol driver is asking us to drop the
- * chipselect briefly, we let the scheduler to handle
- * any "delay" here.
- */
- ep93xx_spi_cs_control(msg->spi, false);
- cond_resched();
- ep93xx_spi_cs_control(msg->spi, true);
- }
- }
-
- if (t->speed_hz || t->bits_per_word)
- ep93xx_spi_chip_setup(espi, chip);
-}
-
-/*
- * ep93xx_spi_process_message() - process one SPI message
- * @espi: ep93xx SPI controller struct
- * @msg: message to process
- *
- * This function processes a single SPI message. We go through all transfers in
- * the message and pass them to ep93xx_spi_process_transfer(). Chipselect is
- * asserted during the whole message (unless per transfer cs_change is set).
- *
- * @msg->status contains %0 in case of success or negative error code in case of
- * failure.
- */
-static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
- struct spi_message *msg)
-{
- unsigned long timeout;
- struct spi_transfer *t;
- int err;
-
- /*
- * Enable the SPI controller and its clock.
- */
- err = ep93xx_spi_enable(espi);
- if (err) {
- dev_err(&espi->pdev->dev, "failed to enable SPI controller\n");
- msg->status = err;
- return;
- }
-
- /*
- * Just to be sure: flush any data from RX FIFO.
- */
- timeout = jiffies + msecs_to_jiffies(SPI_TIMEOUT);
- while (ep93xx_spi_read_u16(espi, SSPSR) & SSPSR_RNE) {
- if (time_after(jiffies, timeout)) {
- dev_warn(&espi->pdev->dev,
- "timeout while flushing RX FIFO\n");
- msg->status = -ETIMEDOUT;
- return;
- }
- ep93xx_spi_read_u16(espi, SSPDR);
- }
-
- /*
- * We explicitly handle FIFO level. This way we don't have to check TX
- * FIFO status using %SSPSR_TNF bit which may cause RX FIFO overruns.
- */
- espi->fifo_level = 0;
-
- /*
- * Update SPI controller registers according to spi device and assert
- * the chipselect.
- */
- ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
- ep93xx_spi_cs_control(msg->spi, true);
-
- list_for_each_entry(t, &msg->transfers, transfer_list) {
- ep93xx_spi_process_transfer(espi, msg, t);
- if (msg->status)
- break;
- }
-
- /*
- * Now the whole message is transferred (or failed for some reason). We
- * deselect the device and disable the SPI controller.
- */
- ep93xx_spi_cs_control(msg->spi, false);
- ep93xx_spi_disable(espi);
-}
-
-#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work))
-
-/**
- * ep93xx_spi_work() - EP93xx SPI workqueue worker function
- * @work: work struct
- *
- * Workqueue worker function. This function is called when there are new
- * SPI messages to be processed. Message is taken out from the queue and then
- * passed to ep93xx_spi_process_message().
- *
- * After message is transferred, protocol driver is notified by calling
- * @msg->complete(). In case of error, @msg->status is set to negative error
- * number, otherwise it contains zero (and @msg->actual_length is updated).
- */
-static void ep93xx_spi_work(struct work_struct *work)
-{
- struct ep93xx_spi *espi = work_to_espi(work);
- struct spi_message *msg;
-
- spin_lock_irq(&espi->lock);
- if (!espi->running || espi->current_msg ||
- list_empty(&espi->msg_queue)) {
- spin_unlock_irq(&espi->lock);
- return;
- }
- msg = list_first_entry(&espi->msg_queue, struct spi_message, queue);
- list_del_init(&msg->queue);
- espi->current_msg = msg;
- spin_unlock_irq(&espi->lock);
-
- ep93xx_spi_process_message(espi, msg);
-
- /*
- * Update the current message and re-schedule ourselves if there are
- * more messages in the queue.
- */
- spin_lock_irq(&espi->lock);
- espi->current_msg = NULL;
- if (espi->running && !list_empty(&espi->msg_queue))
- queue_work(espi->wq, &espi->msg_work);
- spin_unlock_irq(&espi->lock);
-
- /* notify the protocol driver that we are done with this message */
- msg->complete(msg->context);
-}
-
-static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
-{
- struct ep93xx_spi *espi = dev_id;
- u8 irq_status = ep93xx_spi_read_u8(espi, SSPIIR);
-
- /*
- * If we got ROR (receive overrun) interrupt we know that something is
- * wrong. Just abort the message.
- */
- if (unlikely(irq_status & SSPIIR_RORIS)) {
- /* clear the overrun interrupt */
- ep93xx_spi_write_u8(espi, SSPICR, 0);
- dev_warn(&espi->pdev->dev,
- "receive overrun, aborting the message\n");
- espi->current_msg->status = -EIO;
- } else {
- /*
- * Interrupt is either RX (RIS) or TX (TIS). For both cases we
- * simply execute next data transfer.
- */
- if (ep93xx_spi_read_write(espi)) {
- /*
- * In normal case, there still is some processing left
- * for current transfer. Let's wait for the next
- * interrupt then.
- */
- return IRQ_HANDLED;
- }
- }
-
- /*
- * Current transfer is finished, either with error or with success. In
- * any case we disable interrupts and notify the worker to handle
- * any post-processing of the message.
- */
- ep93xx_spi_disable_interrupts(espi);
- complete(&espi->wait);
- 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_DEV_TO_MEM;
- 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_MEM_TO_DEV;
- 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 __devinit ep93xx_spi_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct ep93xx_spi_info *info;
- struct ep93xx_spi *espi;
- struct resource *res;
- int error;
-
- info = pdev->dev.platform_data;
-
- master = spi_alloc_master(&pdev->dev, sizeof(*espi));
- if (!master) {
- dev_err(&pdev->dev, "failed to allocate spi master\n");
- return -ENOMEM;
- }
-
- master->setup = ep93xx_spi_setup;
- master->transfer = ep93xx_spi_transfer;
- master->cleanup = ep93xx_spi_cleanup;
- master->bus_num = pdev->id;
- master->num_chipselect = info->num_chipselect;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- platform_set_drvdata(pdev, master);
-
- espi = spi_master_get_devdata(master);
-
- espi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(espi->clk)) {
- dev_err(&pdev->dev, "unable to get spi clock\n");
- error = PTR_ERR(espi->clk);
- goto fail_release_master;
- }
-
- spin_lock_init(&espi->lock);
- init_completion(&espi->wait);
-
- /*
- * Calculate maximum and minimum supported clock rates
- * for the controller.
- */
- espi->max_rate = clk_get_rate(espi->clk) / 2;
- espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
- espi->pdev = pdev;
-
- espi->irq = platform_get_irq(pdev, 0);
- if (espi->irq < 0) {
- error = -EBUSY;
- dev_err(&pdev->dev, "failed to get irq resources\n");
- goto fail_put_clock;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "unable to get iomem resource\n");
- error = -ENODEV;
- goto fail_put_clock;
- }
-
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (!res) {
- dev_err(&pdev->dev, "unable to request iomem resources\n");
- error = -EBUSY;
- 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");
- error = -ENODEV;
- goto fail_free_mem;
- }
-
- error = request_irq(espi->irq, ep93xx_spi_interrupt, 0,
- "ep93xx-spi", espi);
- if (error) {
- dev_err(&pdev->dev, "failed to request irq\n");
- 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_dma;
- }
- INIT_WORK(&espi->msg_work, ep93xx_spi_work);
- INIT_LIST_HEAD(&espi->msg_queue);
- espi->running = true;
-
- /* make sure that the hardware is disabled */
- ep93xx_spi_write_u8(espi, SSPCR1, 0);
-
- error = spi_register_master(master);
- if (error) {
- dev_err(&pdev->dev, "failed to register SPI master\n");
- goto fail_free_queue;
- }
-
- dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
- (unsigned long)res->start, espi->irq);
-
- return 0;
-
-fail_free_queue:
- destroy_workqueue(espi->wq);
-fail_free_dma:
- ep93xx_spi_release_dma(espi);
- free_irq(espi->irq, espi);
-fail_unmap_regs:
- iounmap(espi->regs_base);
-fail_free_mem:
- release_mem_region(res->start, resource_size(res));
-fail_put_clock:
- clk_put(espi->clk);
-fail_release_master:
- spi_master_put(master);
- platform_set_drvdata(pdev, NULL);
-
- return error;
-}
-
-static int __devexit ep93xx_spi_remove(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct ep93xx_spi *espi = spi_master_get_devdata(master);
- struct resource *res;
-
- spin_lock_irq(&espi->lock);
- espi->running = false;
- spin_unlock_irq(&espi->lock);
-
- destroy_workqueue(espi->wq);
-
- /*
- * Complete remaining messages with %-ESHUTDOWN status.
- */
- spin_lock_irq(&espi->lock);
- while (!list_empty(&espi->msg_queue)) {
- struct spi_message *msg;
-
- msg = list_first_entry(&espi->msg_queue,
- struct spi_message, queue);
- list_del_init(&msg->queue);
- msg->status = -ESHUTDOWN;
- spin_unlock_irq(&espi->lock);
- msg->complete(msg->context);
- spin_lock_irq(&espi->lock);
- }
- 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);
- release_mem_region(res->start, resource_size(res));
- clk_put(espi->clk);
- platform_set_drvdata(pdev, NULL);
-
- spi_unregister_master(master);
- return 0;
-}
-
-static struct platform_driver ep93xx_spi_driver = {
- .driver = {
- .name = "ep93xx-spi",
- .owner = THIS_MODULE,
- },
- .probe = ep93xx_spi_probe,
- .remove = __devexit_p(ep93xx_spi_remove),
-};
-module_platform_driver(ep93xx_spi_driver);
-
-MODULE_DESCRIPTION("EP93xx SPI Controller driver");
-MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ep93xx-spi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-fsl-espi.c b/ANDROID_3.4.5/drivers/spi/spi-fsl-espi.c
deleted file mode 100644
index 7523a242..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-fsl-espi.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Freescale eSPI controller driver.
- *
- * Copyright 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/spi/spi.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/mm.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_spi.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <sysdev/fsl_soc.h>
-
-#include "spi-fsl-lib.h"
-
-/* eSPI Controller registers */
-struct fsl_espi_reg {
- __be32 mode; /* 0x000 - eSPI mode register */
- __be32 event; /* 0x004 - eSPI event register */
- __be32 mask; /* 0x008 - eSPI mask register */
- __be32 command; /* 0x00c - eSPI command register */
- __be32 transmit; /* 0x010 - eSPI transmit FIFO access register*/
- __be32 receive; /* 0x014 - eSPI receive FIFO access register*/
- u8 res[8]; /* 0x018 - 0x01c reserved */
- __be32 csmode[4]; /* 0x020 - 0x02c eSPI cs mode register */
-};
-
-struct fsl_espi_transfer {
- const void *tx_buf;
- void *rx_buf;
- unsigned len;
- unsigned n_tx;
- unsigned n_rx;
- unsigned actual_length;
- int status;
-};
-
-/* eSPI Controller mode register definitions */
-#define SPMODE_ENABLE (1 << 31)
-#define SPMODE_LOOP (1 << 30)
-#define SPMODE_TXTHR(x) ((x) << 8)
-#define SPMODE_RXTHR(x) ((x) << 0)
-
-/* eSPI Controller CS mode register definitions */
-#define CSMODE_CI_INACTIVEHIGH (1 << 31)
-#define CSMODE_CP_BEGIN_EDGECLK (1 << 30)
-#define CSMODE_REV (1 << 29)
-#define CSMODE_DIV16 (1 << 28)
-#define CSMODE_PM(x) ((x) << 24)
-#define CSMODE_POL_1 (1 << 20)
-#define CSMODE_LEN(x) ((x) << 16)
-#define CSMODE_BEF(x) ((x) << 12)
-#define CSMODE_AFT(x) ((x) << 8)
-#define CSMODE_CG(x) ((x) << 3)
-
-/* Default mode/csmode for eSPI controller */
-#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
-#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
- | CSMODE_AFT(0) | CSMODE_CG(1))
-
-/* SPIE register values */
-#define SPIE_NE 0x00000200 /* Not empty */
-#define SPIE_NF 0x00000100 /* Not full */
-
-/* SPIM register values */
-#define SPIM_NE 0x00000200 /* Not empty */
-#define SPIM_NF 0x00000100 /* Not full */
-#define SPIE_RXCNT(reg) ((reg >> 24) & 0x3F)
-#define SPIE_TXCNT(reg) ((reg >> 16) & 0x3F)
-
-/* SPCOM register values */
-#define SPCOM_CS(x) ((x) << 30)
-#define SPCOM_TRANLEN(x) ((x) << 0)
-#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */
-
-static void fsl_espi_change_mode(struct spi_device *spi)
-{
- struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
- struct fsl_espi_reg *reg_base = mspi->reg_base;
- __be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
- __be32 __iomem *espi_mode = &reg_base->mode;
- u32 tmp;
- unsigned long flags;
-
- /* Turn off IRQs locally to minimize time that SPI is disabled. */
- local_irq_save(flags);
-
- /* Turn off SPI unit prior changing mode */
- tmp = mpc8xxx_spi_read_reg(espi_mode);
- mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
- mpc8xxx_spi_write_reg(mode, cs->hw_mode);
- mpc8xxx_spi_write_reg(espi_mode, tmp);
-
- local_irq_restore(flags);
-}
-
-static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
-{
- u32 data;
- u16 data_h;
- u16 data_l;
- const u32 *tx = mpc8xxx_spi->tx;
-
- if (!tx)
- return 0;
-
- data = *tx++ << mpc8xxx_spi->tx_shift;
- data_l = data & 0xffff;
- data_h = (data >> 16) & 0xffff;
- swab16s(&data_l);
- swab16s(&data_h);
- data = data_h | data_l;
-
- mpc8xxx_spi->tx = tx;
- return data;
-}
-
-static int fsl_espi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- int bits_per_word = 0;
- u8 pm;
- u32 hz = 0;
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
- if (t) {
- bits_per_word = t->bits_per_word;
- hz = t->speed_hz;
- }
-
- /* spi_transfer level calls that work per-word */
- if (!bits_per_word)
- bits_per_word = spi->bits_per_word;
-
- /* Make sure its a bit width we support [4..16] */
- if ((bits_per_word < 4) || (bits_per_word > 16))
- return -EINVAL;
-
- if (!hz)
- hz = spi->max_speed_hz;
-
- cs->rx_shift = 0;
- cs->tx_shift = 0;
- cs->get_rx = mpc8xxx_spi_rx_buf_u32;
- cs->get_tx = mpc8xxx_spi_tx_buf_u32;
- if (bits_per_word <= 8) {
- cs->rx_shift = 8 - bits_per_word;
- } else if (bits_per_word <= 16) {
- cs->rx_shift = 16 - bits_per_word;
- if (spi->mode & SPI_LSB_FIRST)
- cs->get_tx = fsl_espi_tx_buf_lsb;
- } else {
- return -EINVAL;
- }
-
- mpc8xxx_spi->rx_shift = cs->rx_shift;
- mpc8xxx_spi->tx_shift = cs->tx_shift;
- mpc8xxx_spi->get_rx = cs->get_rx;
- mpc8xxx_spi->get_tx = cs->get_tx;
-
- bits_per_word = bits_per_word - 1;
-
- /* mask out bits we are going to set */
- cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
-
- cs->hw_mode |= CSMODE_LEN(bits_per_word);
-
- if ((mpc8xxx_spi->spibrg / hz) > 64) {
- cs->hw_mode |= CSMODE_DIV16;
- pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 16 * 4);
-
- WARN_ONCE(pm > 33, "%s: Requested speed is too low: %d Hz. "
- "Will use %d Hz instead.\n", dev_name(&spi->dev),
- hz, mpc8xxx_spi->spibrg / (4 * 16 * (32 + 1)));
- if (pm > 33)
- pm = 33;
- } else {
- pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 4);
- }
- if (pm)
- pm--;
- if (pm < 2)
- pm = 2;
-
- cs->hw_mode |= CSMODE_PM(pm);
-
- fsl_espi_change_mode(spi);
- return 0;
-}
-
-static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
- unsigned int len)
-{
- u32 word;
- struct fsl_espi_reg *reg_base = mspi->reg_base;
-
- mspi->count = len;
-
- /* enable rx ints */
- mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
-
- /* transmit word */
- word = mspi->get_tx(mspi);
- mpc8xxx_spi_write_reg(&reg_base->transmit, word);
-
- return 0;
-}
-
-static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
- unsigned int len = t->len;
- u8 bits_per_word;
- int ret;
-
- bits_per_word = spi->bits_per_word;
- if (t->bits_per_word)
- bits_per_word = t->bits_per_word;
-
- mpc8xxx_spi->len = t->len;
- len = roundup(len, 4) / 4;
-
- mpc8xxx_spi->tx = t->tx_buf;
- mpc8xxx_spi->rx = t->rx_buf;
-
- INIT_COMPLETION(mpc8xxx_spi->done);
-
- /* Set SPCOM[CS] and SPCOM[TRANLEN] field */
- if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
- dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
- " beyond the SPCOM[TRANLEN] field\n", t->len);
- return -EINVAL;
- }
- mpc8xxx_spi_write_reg(&reg_base->command,
- (SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
-
- ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
- if (ret)
- return ret;
-
- wait_for_completion(&mpc8xxx_spi->done);
-
- /* disable rx ints */
- mpc8xxx_spi_write_reg(&reg_base->mask, 0);
-
- return mpc8xxx_spi->count;
-}
-
-static inline void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
-{
- if (cmd) {
- cmd[1] = (u8)(addr >> 16);
- cmd[2] = (u8)(addr >> 8);
- cmd[3] = (u8)(addr >> 0);
- }
-}
-
-static inline unsigned int fsl_espi_cmd2addr(u8 *cmd)
-{
- if (cmd)
- return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
-
- return 0;
-}
-
-static void fsl_espi_do_trans(struct spi_message *m,
- struct fsl_espi_transfer *tr)
-{
- struct spi_device *spi = m->spi;
- struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
- struct fsl_espi_transfer *espi_trans = tr;
- struct spi_message message;
- struct spi_transfer *t, *first, trans;
- int status = 0;
-
- spi_message_init(&message);
- memset(&trans, 0, sizeof(trans));
-
- first = list_first_entry(&m->transfers, struct spi_transfer,
- transfer_list);
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if ((first->bits_per_word != t->bits_per_word) ||
- (first->speed_hz != t->speed_hz)) {
- espi_trans->status = -EINVAL;
- dev_err(mspi->dev, "bits_per_word/speed_hz should be"
- " same for the same SPI transfer\n");
- return;
- }
-
- trans.speed_hz = t->speed_hz;
- trans.bits_per_word = t->bits_per_word;
- trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
- }
-
- trans.len = espi_trans->len;
- trans.tx_buf = espi_trans->tx_buf;
- trans.rx_buf = espi_trans->rx_buf;
- spi_message_add_tail(&trans, &message);
-
- list_for_each_entry(t, &message.transfers, transfer_list) {
- if (t->bits_per_word || t->speed_hz) {
- status = -EINVAL;
-
- status = fsl_espi_setup_transfer(spi, t);
- if (status < 0)
- break;
- }
-
- if (t->len)
- status = fsl_espi_bufs(spi, t);
-
- if (status) {
- status = -EMSGSIZE;
- break;
- }
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
- }
-
- espi_trans->status = status;
- fsl_espi_setup_transfer(spi, NULL);
-}
-
-static void fsl_espi_cmd_trans(struct spi_message *m,
- struct fsl_espi_transfer *trans, u8 *rx_buff)
-{
- struct spi_transfer *t;
- u8 *local_buf;
- int i = 0;
- struct fsl_espi_transfer *espi_trans = trans;
-
- local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
- if (!local_buf) {
- espi_trans->status = -ENOMEM;
- return;
- }
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->tx_buf) {
- memcpy(local_buf + i, t->tx_buf, t->len);
- i += t->len;
- }
- }
-
- espi_trans->tx_buf = local_buf;
- espi_trans->rx_buf = local_buf + espi_trans->n_tx;
- fsl_espi_do_trans(m, espi_trans);
-
- espi_trans->actual_length = espi_trans->len;
- kfree(local_buf);
-}
-
-static void fsl_espi_rw_trans(struct spi_message *m,
- struct fsl_espi_transfer *trans, u8 *rx_buff)
-{
- struct fsl_espi_transfer *espi_trans = trans;
- unsigned int n_tx = espi_trans->n_tx;
- unsigned int n_rx = espi_trans->n_rx;
- struct spi_transfer *t;
- u8 *local_buf;
- u8 *rx_buf = rx_buff;
- unsigned int trans_len;
- unsigned int addr;
- int i, pos, loop;
-
- local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
- if (!local_buf) {
- espi_trans->status = -ENOMEM;
- return;
- }
-
- for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
- trans_len = n_rx - pos;
- if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
- trans_len = SPCOM_TRANLEN_MAX - n_tx;
-
- i = 0;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->tx_buf) {
- memcpy(local_buf + i, t->tx_buf, t->len);
- i += t->len;
- }
- }
-
- if (pos > 0) {
- addr = fsl_espi_cmd2addr(local_buf);
- addr += pos;
- fsl_espi_addr2cmd(addr, local_buf);
- }
-
- espi_trans->n_tx = n_tx;
- espi_trans->n_rx = trans_len;
- espi_trans->len = trans_len + n_tx;
- espi_trans->tx_buf = local_buf;
- espi_trans->rx_buf = local_buf + n_tx;
- fsl_espi_do_trans(m, espi_trans);
-
- memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
-
- if (loop > 0)
- espi_trans->actual_length += espi_trans->len - n_tx;
- else
- espi_trans->actual_length += espi_trans->len;
- }
-
- kfree(local_buf);
-}
-
-static void fsl_espi_do_one_msg(struct spi_message *m)
-{
- struct spi_transfer *t;
- u8 *rx_buf = NULL;
- unsigned int n_tx = 0;
- unsigned int n_rx = 0;
- struct fsl_espi_transfer espi_trans;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->tx_buf)
- n_tx += t->len;
- if (t->rx_buf) {
- n_rx += t->len;
- rx_buf = t->rx_buf;
- }
- }
-
- espi_trans.n_tx = n_tx;
- espi_trans.n_rx = n_rx;
- espi_trans.len = n_tx + n_rx;
- espi_trans.actual_length = 0;
- espi_trans.status = 0;
-
- if (!rx_buf)
- fsl_espi_cmd_trans(m, &espi_trans, NULL);
- else
- fsl_espi_rw_trans(m, &espi_trans, rx_buf);
-
- m->actual_length = espi_trans.actual_length;
- m->status = espi_trans.status;
- m->complete(m->context);
-}
-
-static int fsl_espi_setup(struct spi_device *spi)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_espi_reg *reg_base;
- int retval;
- u32 hw_mode;
- u32 loop_mode;
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
- if (!spi->max_speed_hz)
- return -EINVAL;
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- spi->controller_state = cs;
- }
-
- mpc8xxx_spi = spi_master_get_devdata(spi->master);
- reg_base = mpc8xxx_spi->reg_base;
-
- hw_mode = cs->hw_mode; /* Save original settings */
- cs->hw_mode = mpc8xxx_spi_read_reg(
- &reg_base->csmode[spi->chip_select]);
- /* mask out bits we are going to set */
- cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
- | CSMODE_REV);
-
- if (spi->mode & SPI_CPHA)
- cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
- if (spi->mode & SPI_CPOL)
- cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
- if (!(spi->mode & SPI_LSB_FIRST))
- cs->hw_mode |= CSMODE_REV;
-
- /* Handle the loop mode */
- loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
- loop_mode &= ~SPMODE_LOOP;
- if (spi->mode & SPI_LOOP)
- loop_mode |= SPMODE_LOOP;
- mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
-
- retval = fsl_espi_setup_transfer(spi, NULL);
- if (retval < 0) {
- cs->hw_mode = hw_mode; /* Restore settings */
- return retval;
- }
- return 0;
-}
-
-void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
- struct fsl_espi_reg *reg_base = mspi->reg_base;
-
- /* We need handle RX first */
- if (events & SPIE_NE) {
- u32 rx_data, tmp;
- u8 rx_data_8;
-
- /* Spin until RX is done */
- while (SPIE_RXCNT(events) < min(4, mspi->len)) {
- cpu_relax();
- events = mpc8xxx_spi_read_reg(&reg_base->event);
- }
-
- if (mspi->len >= 4) {
- rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
- } else {
- tmp = mspi->len;
- rx_data = 0;
- while (tmp--) {
- rx_data_8 = in_8((u8 *)&reg_base->receive);
- rx_data |= (rx_data_8 << (tmp * 8));
- }
-
- rx_data <<= (4 - mspi->len) * 8;
- }
-
- mspi->len -= 4;
-
- if (mspi->rx)
- mspi->get_rx(rx_data, mspi);
- }
-
- if (!(events & SPIE_NF)) {
- int ret;
-
- /* spin until TX is done */
- ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
- &reg_base->event)) & SPIE_NF) == 0, 1000, 0);
- if (!ret) {
- dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
- return;
- }
- }
-
- /* Clear the events */
- mpc8xxx_spi_write_reg(&reg_base->event, events);
-
- mspi->count -= 1;
- if (mspi->count) {
- u32 word = mspi->get_tx(mspi);
-
- mpc8xxx_spi_write_reg(&reg_base->transmit, word);
- } else {
- complete(&mspi->done);
- }
-}
-
-static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
-{
- struct mpc8xxx_spi *mspi = context_data;
- struct fsl_espi_reg *reg_base = mspi->reg_base;
- irqreturn_t ret = IRQ_NONE;
- u32 events;
-
- /* Get interrupt events(tx/rx) */
- events = mpc8xxx_spi_read_reg(&reg_base->event);
- if (events)
- ret = IRQ_HANDLED;
-
- dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
-
- fsl_espi_cpu_irq(mspi, events);
-
- return ret;
-}
-
-static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
-{
- iounmap(mspi->reg_base);
-}
-
-static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
- struct resource *mem, unsigned int irq)
-{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct spi_master *master;
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_espi_reg *reg_base;
- u32 regval;
- int i, ret = 0;
-
- master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
- if (!master) {
- ret = -ENOMEM;
- goto err;
- }
-
- dev_set_drvdata(dev, master);
-
- ret = mpc8xxx_spi_probe(dev, mem, irq);
- if (ret)
- goto err_probe;
-
- master->setup = fsl_espi_setup;
-
- mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
- mpc8xxx_spi->spi_remove = fsl_espi_remove;
-
- mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
- if (!mpc8xxx_spi->reg_base) {
- ret = -ENOMEM;
- goto err_probe;
- }
-
- reg_base = mpc8xxx_spi->reg_base;
-
- /* Register for SPI Interrupt */
- ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
- 0, "fsl_espi", mpc8xxx_spi);
- if (ret)
- goto free_irq;
-
- if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
- mpc8xxx_spi->rx_shift = 16;
- mpc8xxx_spi->tx_shift = 24;
- }
-
- /* SPI controller initializations */
- mpc8xxx_spi_write_reg(&reg_base->mode, 0);
- mpc8xxx_spi_write_reg(&reg_base->mask, 0);
- mpc8xxx_spi_write_reg(&reg_base->command, 0);
- mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
-
- /* Init eSPI CS mode register */
- for (i = 0; i < pdata->max_chipselect; i++)
- mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
-
- /* Enable SPI interface */
- regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
-
- mpc8xxx_spi_write_reg(&reg_base->mode, regval);
-
- ret = spi_register_master(master);
- if (ret < 0)
- goto unreg_master;
-
- dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
-
- return master;
-
-unreg_master:
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
- iounmap(mpc8xxx_spi->reg_base);
-err_probe:
- spi_master_put(master);
-err:
- return ERR_PTR(ret);
-}
-
-static int of_fsl_espi_get_chipselects(struct device *dev)
-{
- struct device_node *np = dev->of_node;
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- const u32 *prop;
- int len;
-
- prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
- if (!prop || len < sizeof(*prop)) {
- dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
- return -EINVAL;
- }
-
- pdata->max_chipselect = *prop;
- pdata->cs_control = NULL;
-
- return 0;
-}
-
-static int __devinit of_fsl_espi_probe(struct platform_device *ofdev)
-{
- struct device *dev = &ofdev->dev;
- struct device_node *np = ofdev->dev.of_node;
- struct spi_master *master;
- struct resource mem;
- struct resource irq;
- int ret = -ENOMEM;
-
- ret = of_mpc8xxx_spi_probe(ofdev);
- if (ret)
- return ret;
-
- ret = of_fsl_espi_get_chipselects(dev);
- if (ret)
- goto err;
-
- ret = of_address_to_resource(np, 0, &mem);
- if (ret)
- goto err;
-
- ret = of_irq_to_resource(np, 0, &irq);
- if (!ret) {
- ret = -EINVAL;
- goto err;
- }
-
- master = fsl_espi_probe(dev, &mem, irq.start);
- if (IS_ERR(master)) {
- ret = PTR_ERR(master);
- goto err;
- }
-
- return 0;
-
-err:
- return ret;
-}
-
-static int __devexit of_fsl_espi_remove(struct platform_device *dev)
-{
- return mpc8xxx_spi_remove(&dev->dev);
-}
-
-static const struct of_device_id of_fsl_espi_match[] = {
- { .compatible = "fsl,mpc8536-espi" },
- {}
-};
-MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
-
-static struct platform_driver fsl_espi_driver = {
- .driver = {
- .name = "fsl_espi",
- .owner = THIS_MODULE,
- .of_match_table = of_fsl_espi_match,
- },
- .probe = of_fsl_espi_probe,
- .remove = __devexit_p(of_fsl_espi_remove),
-};
-module_platform_driver(fsl_espi_driver);
-
-MODULE_AUTHOR("Mingkai Hu");
-MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-fsl-lib.c b/ANDROID_3.4.5/drivers/spi/spi-fsl-lib.c
deleted file mode 100644
index 2674fad7..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-fsl-lib.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Freescale SPI/eSPI controller driver library.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright (C) 2006 Polycom, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009 MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * Copyright 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/of_platform.h>
-#include <linux/of_spi.h>
-#include <sysdev/fsl_soc.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) \
-{ \
- type *rx = mpc8xxx_spi->rx; \
- *rx++ = (type)(data >> mpc8xxx_spi->rx_shift); \
- mpc8xxx_spi->rx = rx; \
-}
-
-#define MPC8XXX_SPI_TX_BUF(type) \
-u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi) \
-{ \
- u32 data; \
- const type *tx = mpc8xxx_spi->tx; \
- if (!tx) \
- return 0; \
- data = *tx++ << mpc8xxx_spi->tx_shift; \
- mpc8xxx_spi->tx = tx; \
- return data; \
-}
-
-MPC8XXX_SPI_RX_BUF(u8)
-MPC8XXX_SPI_RX_BUF(u16)
-MPC8XXX_SPI_RX_BUF(u32)
-MPC8XXX_SPI_TX_BUF(u8)
-MPC8XXX_SPI_TX_BUF(u16)
-MPC8XXX_SPI_TX_BUF(u32)
-
-struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
-{
- return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
-}
-
-void mpc8xxx_spi_work(struct work_struct *work)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
- work);
-
- spin_lock_irq(&mpc8xxx_spi->lock);
- while (!list_empty(&mpc8xxx_spi->queue)) {
- struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
- struct spi_message, queue);
-
- list_del_init(&m->queue);
- spin_unlock_irq(&mpc8xxx_spi->lock);
-
- if (mpc8xxx_spi->spi_do_one_msg)
- mpc8xxx_spi->spi_do_one_msg(m);
-
- spin_lock_irq(&mpc8xxx_spi->lock);
- }
- spin_unlock_irq(&mpc8xxx_spi->lock);
-}
-
-int mpc8xxx_spi_transfer(struct spi_device *spi,
- struct spi_message *m)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
- list_add_tail(&m->queue, &mpc8xxx_spi->queue);
- queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
- spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
-
- return 0;
-}
-
-void mpc8xxx_spi_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-
-const char *mpc8xxx_spi_strmode(unsigned int flags)
-{
- if (flags & SPI_QE_CPU_MODE) {
- return "QE CPU";
- } else if (flags & SPI_CPM_MODE) {
- if (flags & SPI_QE)
- return "QE";
- else if (flags & SPI_CPM2)
- return "CPM2";
- else
- return "CPM1";
- }
- return "CPU";
-}
-
-int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
- unsigned int irq)
-{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct spi_master *master;
- struct mpc8xxx_spi *mpc8xxx_spi;
- int ret = 0;
-
- master = dev_get_drvdata(dev);
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
- | SPI_LSB_FIRST | SPI_LOOP;
-
- master->transfer = mpc8xxx_spi_transfer;
- master->cleanup = mpc8xxx_spi_cleanup;
- master->dev.of_node = dev->of_node;
-
- mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->dev = dev;
- mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
- mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
- mpc8xxx_spi->flags = pdata->flags;
- mpc8xxx_spi->spibrg = pdata->sysclk;
- mpc8xxx_spi->irq = irq;
-
- mpc8xxx_spi->rx_shift = 0;
- mpc8xxx_spi->tx_shift = 0;
-
- init_completion(&mpc8xxx_spi->done);
-
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->max_chipselect;
-
- spin_lock_init(&mpc8xxx_spi->lock);
- init_completion(&mpc8xxx_spi->done);
- INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
- INIT_LIST_HEAD(&mpc8xxx_spi->queue);
-
- mpc8xxx_spi->workqueue = create_singlethread_workqueue(
- dev_name(master->dev.parent));
- if (mpc8xxx_spi->workqueue == NULL) {
- ret = -EBUSY;
- goto err;
- }
-
- return 0;
-
-err:
- return ret;
-}
-
-int __devexit mpc8xxx_spi_remove(struct device *dev)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct spi_master *master;
-
- master = dev_get_drvdata(dev);
- mpc8xxx_spi = spi_master_get_devdata(master);
-
- flush_workqueue(mpc8xxx_spi->workqueue);
- destroy_workqueue(mpc8xxx_spi->workqueue);
- spi_unregister_master(master);
-
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-
- if (mpc8xxx_spi->spi_remove)
- mpc8xxx_spi->spi_remove(mpc8xxx_spi);
-
- return 0;
-}
-
-int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
-{
- struct device *dev = &ofdev->dev;
- struct device_node *np = ofdev->dev.of_node;
- struct mpc8xxx_spi_probe_info *pinfo;
- struct fsl_spi_platform_data *pdata;
- const void *prop;
- int ret = -ENOMEM;
-
- pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
- if (!pinfo)
- return -ENOMEM;
-
- pdata = &pinfo->pdata;
- dev->platform_data = pdata;
-
- /* Allocate bus num dynamically. */
- pdata->bus_num = -1;
-
- /* SPI controller is either clocked from QE or SoC clock. */
- pdata->sysclk = get_brgfreq();
- if (pdata->sysclk == -1) {
- pdata->sysclk = fsl_get_sys_freq();
- if (pdata->sysclk == -1) {
- ret = -ENODEV;
- goto err;
- }
- }
-
- prop = of_get_property(np, "mode", NULL);
- if (prop && !strcmp(prop, "cpu-qe"))
- pdata->flags = SPI_QE_CPU_MODE;
- else if (prop && !strcmp(prop, "qe"))
- pdata->flags = SPI_CPM_MODE | SPI_QE;
- else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
- pdata->flags = SPI_CPM_MODE | SPI_CPM2;
- else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
- pdata->flags = SPI_CPM_MODE | SPI_CPM1;
-
- return 0;
-
-err:
- kfree(pinfo);
- return ret;
-}
diff --git a/ANDROID_3.4.5/drivers/spi/spi-fsl-lib.h b/ANDROID_3.4.5/drivers/spi/spi-fsl-lib.h
deleted file mode 100644
index cbe881b9..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-fsl-lib.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Freescale SPI/eSPI controller driver library.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright 2010 Freescale Semiconductor, Inc.
- * Copyright (C) 2006 Polycom, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009 MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef __SPI_FSL_LIB_H__
-#define __SPI_FSL_LIB_H__
-
-#include <asm/io.h>
-
-/* SPI/eSPI Controller driver's private data. */
-struct mpc8xxx_spi {
- struct device *dev;
- void *reg_base;
-
- /* rx & tx bufs from the spi_transfer */
- const void *tx;
- void *rx;
-#ifdef CONFIG_SPI_FSL_ESPI
- int len;
-#endif
-
- int subblock;
- struct spi_pram __iomem *pram;
- struct cpm_buf_desc __iomem *tx_bd;
- struct cpm_buf_desc __iomem *rx_bd;
-
- struct spi_transfer *xfer_in_progress;
-
- /* dma addresses for CPM transfers */
- dma_addr_t tx_dma;
- dma_addr_t rx_dma;
- bool map_tx_dma;
- bool map_rx_dma;
-
- dma_addr_t dma_dummy_tx;
- dma_addr_t dma_dummy_rx;
-
- /* functions to deal with different sized buffers */
- void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
- u32(*get_tx) (struct mpc8xxx_spi *);
-
- /* hooks for different controller driver */
- void (*spi_do_one_msg) (struct spi_message *m);
- void (*spi_remove) (struct mpc8xxx_spi *mspi);
-
- unsigned int count;
- unsigned int irq;
-
- unsigned nsecs; /* (clock cycle time)/2 */
-
- u32 spibrg; /* SPIBRG input clock */
- u32 rx_shift; /* RX data reg shift when in qe mode */
- u32 tx_shift; /* TX data reg shift when in qe mode */
-
- unsigned int flags;
-
- struct workqueue_struct *workqueue;
- struct work_struct work;
-
- struct list_head queue;
- spinlock_t lock;
-
- struct completion done;
-};
-
-struct spi_mpc8xxx_cs {
- /* functions to deal with different sized buffers */
- void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
- u32 (*get_tx) (struct mpc8xxx_spi *);
- u32 rx_shift; /* RX data reg shift when in qe mode */
- u32 tx_shift; /* TX data reg shift when in qe mode */
- u32 hw_mode; /* Holds HW mode register settings */
-};
-
-static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
-{
- out_be32(reg, val);
-}
-
-static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
-{
- return in_be32(reg);
-}
-
-struct mpc8xxx_spi_probe_info {
- struct fsl_spi_platform_data pdata;
- int *gpios;
- bool *alow_flags;
-};
-
-extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
-extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
-extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
-extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
-extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
-extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
-
-extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
- struct fsl_spi_platform_data *pdata);
-extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
- struct spi_transfer *t, unsigned int len);
-extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
-extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
-extern const char *mpc8xxx_spi_strmode(unsigned int flags);
-extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
- unsigned int irq);
-extern int mpc8xxx_spi_remove(struct device *dev);
-extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
-
-#endif /* __SPI_FSL_LIB_H__ */
diff --git a/ANDROID_3.4.5/drivers/spi/spi-fsl-spi.c b/ANDROID_3.4.5/drivers/spi/spi-fsl-spi.c
deleted file mode 100644
index 6a62934c..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-fsl-spi.c
+++ /dev/null
@@ -1,1191 +0,0 @@
-/*
- * Freescale SPI controller driver.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright (C) 2006 Polycom, Inc.
- * Copyright 2010 Freescale Semiconductor, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009 MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-
-#include <sysdev/fsl_soc.h>
-#include <asm/cpm.h>
-#include <asm/qe.h>
-
-#include "spi-fsl-lib.h"
-
-/* CPM1 and CPM2 are mutually exclusive. */
-#ifdef CONFIG_CPM1
-#include <asm/cpm1.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
-#else
-#include <asm/cpm2.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
-#endif
-
-/* SPI Controller registers */
-struct fsl_spi_reg {
- u8 res1[0x20];
- __be32 mode;
- __be32 event;
- __be32 mask;
- __be32 command;
- __be32 transmit;
- __be32 receive;
-};
-
-/* SPI Controller mode register definitions */
-#define SPMODE_LOOP (1 << 30)
-#define SPMODE_CI_INACTIVEHIGH (1 << 29)
-#define SPMODE_CP_BEGIN_EDGECLK (1 << 28)
-#define SPMODE_DIV16 (1 << 27)
-#define SPMODE_REV (1 << 26)
-#define SPMODE_MS (1 << 25)
-#define SPMODE_ENABLE (1 << 24)
-#define SPMODE_LEN(x) ((x) << 20)
-#define SPMODE_PM(x) ((x) << 16)
-#define SPMODE_OP (1 << 14)
-#define SPMODE_CG(x) ((x) << 7)
-
-/*
- * Default for SPI Mode:
- * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
- */
-#define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
- SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
-
-/* SPIE register values */
-#define SPIE_NE 0x00000200 /* Not empty */
-#define SPIE_NF 0x00000100 /* Not full */
-
-/* SPIM register values */
-#define SPIM_NE 0x00000200 /* Not empty */
-#define SPIM_NF 0x00000100 /* Not full */
-
-#define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */
-#define SPIE_RXB 0x00000100 /* Last char is written to rx buf */
-
-/* SPCOM register values */
-#define SPCOM_STR (1 << 23) /* Start transmit */
-
-#define SPI_PRAM_SIZE 0x100
-#define SPI_MRBLR ((unsigned int)PAGE_SIZE)
-
-static void *fsl_dummy_rx;
-static DEFINE_MUTEX(fsl_dummy_rx_lock);
-static int fsl_dummy_rx_refcnt;
-
-static void fsl_spi_change_mode(struct spi_device *spi)
-{
- struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
- struct fsl_spi_reg *reg_base = mspi->reg_base;
- __be32 __iomem *mode = &reg_base->mode;
- unsigned long flags;
-
- if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
- return;
-
- /* Turn off IRQs locally to minimize time that SPI is disabled. */
- local_irq_save(flags);
-
- /* Turn off SPI unit prior changing mode */
- mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
-
- /* When in CPM mode, we need to reinit tx and rx. */
- if (mspi->flags & SPI_CPM_MODE) {
- if (mspi->flags & SPI_QE) {
- qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
- QE_CR_PROTOCOL_UNSPECIFIED, 0);
- } else {
- cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
- if (mspi->flags & SPI_CPM1) {
- out_be16(&mspi->pram->rbptr,
- in_be16(&mspi->pram->rbase));
- out_be16(&mspi->pram->tbptr,
- in_be16(&mspi->pram->tbase));
- }
- }
- }
- mpc8xxx_spi_write_reg(mode, cs->hw_mode);
- local_irq_restore(flags);
-}
-
-static void fsl_spi_chipselect(struct spi_device *spi, int value)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- struct fsl_spi_platform_data *pdata;
- bool pol = spi->mode & SPI_CS_HIGH;
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
- pdata = spi->dev.parent->parent->platform_data;
-
- if (value == BITBANG_CS_INACTIVE) {
- if (pdata->cs_control)
- pdata->cs_control(spi, !pol);
- }
-
- if (value == BITBANG_CS_ACTIVE) {
- mpc8xxx_spi->rx_shift = cs->rx_shift;
- mpc8xxx_spi->tx_shift = cs->tx_shift;
- mpc8xxx_spi->get_rx = cs->get_rx;
- mpc8xxx_spi->get_tx = cs->get_tx;
-
- fsl_spi_change_mode(spi);
-
- if (pdata->cs_control)
- pdata->cs_control(spi, pol);
- }
-}
-
-static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
- struct spi_device *spi,
- struct mpc8xxx_spi *mpc8xxx_spi,
- int bits_per_word)
-{
- cs->rx_shift = 0;
- cs->tx_shift = 0;
- if (bits_per_word <= 8) {
- cs->get_rx = mpc8xxx_spi_rx_buf_u8;
- cs->get_tx = mpc8xxx_spi_tx_buf_u8;
- if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
- cs->rx_shift = 16;
- cs->tx_shift = 24;
- }
- } else if (bits_per_word <= 16) {
- cs->get_rx = mpc8xxx_spi_rx_buf_u16;
- cs->get_tx = mpc8xxx_spi_tx_buf_u16;
- if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
- cs->rx_shift = 16;
- cs->tx_shift = 16;
- }
- } else if (bits_per_word <= 32) {
- cs->get_rx = mpc8xxx_spi_rx_buf_u32;
- cs->get_tx = mpc8xxx_spi_tx_buf_u32;
- } else
- return -EINVAL;
-
- if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
- spi->mode & SPI_LSB_FIRST) {
- cs->tx_shift = 0;
- if (bits_per_word <= 8)
- cs->rx_shift = 8;
- else
- cs->rx_shift = 0;
- }
- mpc8xxx_spi->rx_shift = cs->rx_shift;
- mpc8xxx_spi->tx_shift = cs->tx_shift;
- mpc8xxx_spi->get_rx = cs->get_rx;
- mpc8xxx_spi->get_tx = cs->get_tx;
-
- return bits_per_word;
-}
-
-static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
- struct spi_device *spi,
- int bits_per_word)
-{
- /* QE uses Little Endian for words > 8
- * so transform all words > 8 into 8 bits
- * Unfortnatly that doesn't work for LSB so
- * reject these for now */
- /* Note: 32 bits word, LSB works iff
- * tfcr/rfcr is set to CPMFCR_GBL */
- if (spi->mode & SPI_LSB_FIRST &&
- bits_per_word > 8)
- return -EINVAL;
- if (bits_per_word > 8)
- return 8; /* pretend its 8 bits */
- return bits_per_word;
-}
-
-static int fsl_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- int bits_per_word = 0;
- u8 pm;
- u32 hz = 0;
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
- mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
- if (t) {
- bits_per_word = t->bits_per_word;
- hz = t->speed_hz;
- }
-
- /* spi_transfer level calls that work per-word */
- if (!bits_per_word)
- bits_per_word = spi->bits_per_word;
-
- /* Make sure its a bit width we support [4..16, 32] */
- if ((bits_per_word < 4)
- || ((bits_per_word > 16) && (bits_per_word != 32)))
- return -EINVAL;
-
- if (!hz)
- hz = spi->max_speed_hz;
-
- if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
- bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
- mpc8xxx_spi,
- bits_per_word);
- else if (mpc8xxx_spi->flags & SPI_QE)
- bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
- bits_per_word);
-
- if (bits_per_word < 0)
- return bits_per_word;
-
- if (bits_per_word == 32)
- bits_per_word = 0;
- else
- bits_per_word = bits_per_word - 1;
-
- /* mask out bits we are going to set */
- cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
- | SPMODE_PM(0xF));
-
- cs->hw_mode |= SPMODE_LEN(bits_per_word);
-
- if ((mpc8xxx_spi->spibrg / hz) > 64) {
- cs->hw_mode |= SPMODE_DIV16;
- pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
-
- WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
- "Will use %d Hz instead.\n", dev_name(&spi->dev),
- hz, mpc8xxx_spi->spibrg / 1024);
- if (pm > 16)
- pm = 16;
- } else {
- pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
- }
- if (pm)
- pm--;
-
- cs->hw_mode |= SPMODE_PM(pm);
-
- fsl_spi_change_mode(spi);
- return 0;
-}
-
-static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
-{
- struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
- struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
- unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
- unsigned int xfer_ofs;
- struct fsl_spi_reg *reg_base = mspi->reg_base;
-
- xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
-
- if (mspi->rx_dma == mspi->dma_dummy_rx)
- out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
- else
- out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
- out_be16(&rx_bd->cbd_datlen, 0);
- out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
-
- if (mspi->tx_dma == mspi->dma_dummy_tx)
- out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
- else
- out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
- out_be16(&tx_bd->cbd_datlen, xfer_len);
- out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
- BD_SC_LAST);
-
- /* start transfer */
- mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
-}
-
-static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
- struct spi_transfer *t, bool is_dma_mapped)
-{
- struct device *dev = mspi->dev;
- struct fsl_spi_reg *reg_base = mspi->reg_base;
-
- if (is_dma_mapped) {
- mspi->map_tx_dma = 0;
- mspi->map_rx_dma = 0;
- } else {
- mspi->map_tx_dma = 1;
- mspi->map_rx_dma = 1;
- }
-
- if (!t->tx_buf) {
- mspi->tx_dma = mspi->dma_dummy_tx;
- mspi->map_tx_dma = 0;
- }
-
- if (!t->rx_buf) {
- mspi->rx_dma = mspi->dma_dummy_rx;
- mspi->map_rx_dma = 0;
- }
-
- if (mspi->map_tx_dma) {
- void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
-
- mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, mspi->tx_dma)) {
- dev_err(dev, "unable to map tx dma\n");
- return -ENOMEM;
- }
- } else if (t->tx_buf) {
- mspi->tx_dma = t->tx_dma;
- }
-
- if (mspi->map_rx_dma) {
- mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, mspi->rx_dma)) {
- dev_err(dev, "unable to map rx dma\n");
- goto err_rx_dma;
- }
- } else if (t->rx_buf) {
- mspi->rx_dma = t->rx_dma;
- }
-
- /* enable rx ints */
- mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
-
- mspi->xfer_in_progress = t;
- mspi->count = t->len;
-
- /* start CPM transfers */
- fsl_spi_cpm_bufs_start(mspi);
-
- return 0;
-
-err_rx_dma:
- if (mspi->map_tx_dma)
- dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
- return -ENOMEM;
-}
-
-static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
-{
- struct device *dev = mspi->dev;
- struct spi_transfer *t = mspi->xfer_in_progress;
-
- if (mspi->map_tx_dma)
- dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
- if (mspi->map_rx_dma)
- dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
- mspi->xfer_in_progress = NULL;
-}
-
-static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
- struct spi_transfer *t, unsigned int len)
-{
- u32 word;
- struct fsl_spi_reg *reg_base = mspi->reg_base;
-
- mspi->count = len;
-
- /* enable rx ints */
- mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
-
- /* transmit word */
- word = mspi->get_tx(mspi);
- mpc8xxx_spi_write_reg(&reg_base->transmit, word);
-
- return 0;
-}
-
-static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
- bool is_dma_mapped)
-{
- struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- struct fsl_spi_reg *reg_base;
- unsigned int len = t->len;
- u8 bits_per_word;
- int ret;
-
- reg_base = mpc8xxx_spi->reg_base;
- bits_per_word = spi->bits_per_word;
- if (t->bits_per_word)
- bits_per_word = t->bits_per_word;
-
- if (bits_per_word > 8) {
- /* invalid length? */
- if (len & 1)
- return -EINVAL;
- len /= 2;
- }
- if (bits_per_word > 16) {
- /* invalid length? */
- if (len & 1)
- return -EINVAL;
- len /= 2;
- }
-
- mpc8xxx_spi->tx = t->tx_buf;
- mpc8xxx_spi->rx = t->rx_buf;
-
- INIT_COMPLETION(mpc8xxx_spi->done);
-
- if (mpc8xxx_spi->flags & SPI_CPM_MODE)
- ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
- else
- ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
- if (ret)
- return ret;
-
- wait_for_completion(&mpc8xxx_spi->done);
-
- /* disable rx ints */
- mpc8xxx_spi_write_reg(&reg_base->mask, 0);
-
- if (mpc8xxx_spi->flags & SPI_CPM_MODE)
- fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
-
- return mpc8xxx_spi->count;
-}
-
-static void fsl_spi_do_one_msg(struct spi_message *m)
-{
- struct spi_device *spi = m->spi;
- struct spi_transfer *t;
- unsigned int cs_change;
- const int nsecs = 50;
- int status;
-
- cs_change = 1;
- status = 0;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->bits_per_word || t->speed_hz) {
- /* Don't allow changes if CS is active */
- status = -EINVAL;
-
- if (cs_change)
- status = fsl_spi_setup_transfer(spi, t);
- if (status < 0)
- break;
- }
-
- if (cs_change) {
- fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
- ndelay(nsecs);
- }
- cs_change = t->cs_change;
- if (t->len)
- status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
- if (status) {
- status = -EMSGSIZE;
- break;
- }
- m->actual_length += t->len;
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (cs_change) {
- ndelay(nsecs);
- fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
- }
-
- m->status = status;
- m->complete(m->context);
-
- if (status || !cs_change) {
- ndelay(nsecs);
- fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
- }
-
- fsl_spi_setup_transfer(spi, NULL);
-}
-
-static int fsl_spi_setup(struct spi_device *spi)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_spi_reg *reg_base;
- int retval;
- u32 hw_mode;
- struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
- if (!spi->max_speed_hz)
- return -EINVAL;
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- spi->controller_state = cs;
- }
- mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
- reg_base = mpc8xxx_spi->reg_base;
-
- hw_mode = cs->hw_mode; /* Save original settings */
- cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
- /* mask out bits we are going to set */
- cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
- | SPMODE_REV | SPMODE_LOOP);
-
- if (spi->mode & SPI_CPHA)
- cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
- if (spi->mode & SPI_CPOL)
- cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
- if (!(spi->mode & SPI_LSB_FIRST))
- cs->hw_mode |= SPMODE_REV;
- if (spi->mode & SPI_LOOP)
- cs->hw_mode |= SPMODE_LOOP;
-
- retval = fsl_spi_setup_transfer(spi, NULL);
- if (retval < 0) {
- cs->hw_mode = hw_mode; /* Restore settings */
- return retval;
- }
- return 0;
-}
-
-static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
- u16 len;
- struct fsl_spi_reg *reg_base = mspi->reg_base;
-
- dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
- in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
-
- len = in_be16(&mspi->rx_bd->cbd_datlen);
- if (len > mspi->count) {
- WARN_ON(1);
- len = mspi->count;
- }
-
- /* Clear the events */
- mpc8xxx_spi_write_reg(&reg_base->event, events);
-
- mspi->count -= len;
- if (mspi->count)
- fsl_spi_cpm_bufs_start(mspi);
- else
- complete(&mspi->done);
-}
-
-static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
- struct fsl_spi_reg *reg_base = mspi->reg_base;
-
- /* We need handle RX first */
- if (events & SPIE_NE) {
- u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
-
- if (mspi->rx)
- mspi->get_rx(rx_data, mspi);
- }
-
- if ((events & SPIE_NF) == 0)
- /* spin until TX is done */
- while (((events =
- mpc8xxx_spi_read_reg(&reg_base->event)) &
- SPIE_NF) == 0)
- cpu_relax();
-
- /* Clear the events */
- mpc8xxx_spi_write_reg(&reg_base->event, events);
-
- mspi->count -= 1;
- if (mspi->count) {
- u32 word = mspi->get_tx(mspi);
-
- mpc8xxx_spi_write_reg(&reg_base->transmit, word);
- } else {
- complete(&mspi->done);
- }
-}
-
-static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
-{
- struct mpc8xxx_spi *mspi = context_data;
- irqreturn_t ret = IRQ_NONE;
- u32 events;
- struct fsl_spi_reg *reg_base = mspi->reg_base;
-
- /* Get interrupt events(tx/rx) */
- events = mpc8xxx_spi_read_reg(&reg_base->event);
- if (events)
- ret = IRQ_HANDLED;
-
- dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
-
- if (mspi->flags & SPI_CPM_MODE)
- fsl_spi_cpm_irq(mspi, events);
- else
- fsl_spi_cpu_irq(mspi, events);
-
- return ret;
-}
-
-static void *fsl_spi_alloc_dummy_rx(void)
-{
- mutex_lock(&fsl_dummy_rx_lock);
-
- if (!fsl_dummy_rx)
- fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
- if (fsl_dummy_rx)
- fsl_dummy_rx_refcnt++;
-
- mutex_unlock(&fsl_dummy_rx_lock);
-
- return fsl_dummy_rx;
-}
-
-static void fsl_spi_free_dummy_rx(void)
-{
- mutex_lock(&fsl_dummy_rx_lock);
-
- switch (fsl_dummy_rx_refcnt) {
- case 0:
- WARN_ON(1);
- break;
- case 1:
- kfree(fsl_dummy_rx);
- fsl_dummy_rx = NULL;
- /* fall through */
- default:
- fsl_dummy_rx_refcnt--;
- break;
- }
-
- mutex_unlock(&fsl_dummy_rx_lock);
-}
-
-static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
-{
- struct device *dev = mspi->dev;
- struct device_node *np = dev->of_node;
- const u32 *iprop;
- int size;
- void __iomem *spi_base;
- unsigned long pram_ofs = -ENOMEM;
-
- /* Can't use of_address_to_resource(), QE muram isn't at 0. */
- iprop = of_get_property(np, "reg", &size);
-
- /* QE with a fixed pram location? */
- if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
- return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
-
- /* QE but with a dynamic pram location? */
- if (mspi->flags & SPI_QE) {
- pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
- qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
- QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
- return pram_ofs;
- }
-
- 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);
- out_be16(spi_base, pram_ofs);
- } else {
- struct spi_pram __iomem *pram = spi_base;
- u16 rpbase = in_be16(&pram->rpbase);
-
- /* Microcode relocation patch applied? */
- if (rpbase)
- pram_ofs = rpbase;
- else {
- pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
- out_be16(spi_base, pram_ofs);
- }
- }
-
- iounmap(spi_base);
- return pram_ofs;
-}
-
-static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
-{
- struct device *dev = mspi->dev;
- struct device_node *np = dev->of_node;
- const u32 *iprop;
- int size;
- unsigned long pram_ofs;
- unsigned long bds_ofs;
-
- if (!(mspi->flags & SPI_CPM_MODE))
- return 0;
-
- if (!fsl_spi_alloc_dummy_rx())
- return -ENOMEM;
-
- if (mspi->flags & SPI_QE) {
- iprop = of_get_property(np, "cell-index", &size);
- if (iprop && size == sizeof(*iprop))
- mspi->subblock = *iprop;
-
- switch (mspi->subblock) {
- default:
- dev_warn(dev, "cell-index unspecified, assuming SPI1");
- /* fall through */
- case 0:
- mspi->subblock = QE_CR_SUBBLOCK_SPI1;
- break;
- case 1:
- mspi->subblock = QE_CR_SUBBLOCK_SPI2;
- break;
- }
- }
-
- pram_ofs = fsl_spi_cpm_get_pram(mspi);
- if (IS_ERR_VALUE(pram_ofs)) {
- dev_err(dev, "can't allocate spi parameter ram\n");
- goto err_pram;
- }
-
- bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
- sizeof(*mspi->rx_bd), 8);
- if (IS_ERR_VALUE(bds_ofs)) {
- dev_err(dev, "can't allocate bds\n");
- goto err_bds;
- }
-
- mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
- dev_err(dev, "unable to map dummy tx buffer\n");
- goto err_dummy_tx;
- }
-
- mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
- dev_err(dev, "unable to map dummy rx buffer\n");
- goto err_dummy_rx;
- }
-
- mspi->pram = cpm_muram_addr(pram_ofs);
-
- mspi->tx_bd = cpm_muram_addr(bds_ofs);
- mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
-
- /* Initialize parameter ram. */
- out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
- out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
- out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
- out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
- out_be16(&mspi->pram->mrblr, SPI_MRBLR);
- out_be32(&mspi->pram->rstate, 0);
- out_be32(&mspi->pram->rdp, 0);
- out_be16(&mspi->pram->rbptr, 0);
- out_be16(&mspi->pram->rbc, 0);
- out_be32(&mspi->pram->rxtmp, 0);
- out_be32(&mspi->pram->tstate, 0);
- out_be32(&mspi->pram->tdp, 0);
- out_be16(&mspi->pram->tbptr, 0);
- out_be16(&mspi->pram->tbc, 0);
- out_be32(&mspi->pram->txtmp, 0);
-
- return 0;
-
-err_dummy_rx:
- dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-err_dummy_tx:
- cpm_muram_free(bds_ofs);
-err_bds:
- cpm_muram_free(pram_ofs);
-err_pram:
- fsl_spi_free_dummy_rx();
- return -ENOMEM;
-}
-
-static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
-{
- struct device *dev = mspi->dev;
-
- if (!(mspi->flags & SPI_CPM_MODE))
- return;
-
- dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
- dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
- cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
- cpm_muram_free(cpm_muram_offset(mspi->pram));
- fsl_spi_free_dummy_rx();
-}
-
-static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
-{
- iounmap(mspi->reg_base);
- fsl_spi_cpm_free(mspi);
-}
-
-static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
- struct resource *mem, unsigned int irq)
-{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct spi_master *master;
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_spi_reg *reg_base;
- u32 regval;
- int ret = 0;
-
- master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
- if (master == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- dev_set_drvdata(dev, master);
-
- ret = mpc8xxx_spi_probe(dev, mem, irq);
- if (ret)
- goto err_probe;
-
- master->setup = fsl_spi_setup;
-
- mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
- mpc8xxx_spi->spi_remove = fsl_spi_remove;
-
-
- ret = fsl_spi_cpm_init(mpc8xxx_spi);
- if (ret)
- goto err_cpm_init;
-
- if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
- mpc8xxx_spi->rx_shift = 16;
- mpc8xxx_spi->tx_shift = 24;
- }
-
- mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
- if (mpc8xxx_spi->reg_base == NULL) {
- ret = -ENOMEM;
- goto err_ioremap;
- }
-
- /* Register for SPI Interrupt */
- ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
- 0, "fsl_spi", mpc8xxx_spi);
-
- if (ret != 0)
- goto free_irq;
-
- reg_base = mpc8xxx_spi->reg_base;
-
- /* SPI controller initializations */
- mpc8xxx_spi_write_reg(&reg_base->mode, 0);
- mpc8xxx_spi_write_reg(&reg_base->mask, 0);
- mpc8xxx_spi_write_reg(&reg_base->command, 0);
- mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
-
- /* Enable SPI interface */
- regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
- if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
- regval |= SPMODE_OP;
-
- mpc8xxx_spi_write_reg(&reg_base->mode, regval);
-
- ret = spi_register_master(master);
- if (ret < 0)
- goto unreg_master;
-
- dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
- mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
-
- return master;
-
-unreg_master:
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
- iounmap(mpc8xxx_spi->reg_base);
-err_ioremap:
- fsl_spi_cpm_free(mpc8xxx_spi);
-err_cpm_init:
-err_probe:
- spi_master_put(master);
-err:
- return ERR_PTR(ret);
-}
-
-static void fsl_spi_cs_control(struct spi_device *spi, bool on)
-{
- struct device *dev = spi->dev.parent->parent;
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
- u16 cs = spi->chip_select;
- int gpio = pinfo->gpios[cs];
- bool alow = pinfo->alow_flags[cs];
-
- gpio_set_value(gpio, on ^ alow);
-}
-
-static int of_fsl_spi_get_chipselects(struct device *dev)
-{
- struct device_node *np = dev->of_node;
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
- unsigned int ngpios;
- int i = 0;
- int ret;
-
- ngpios = of_gpio_count(np);
- if (!ngpios) {
- /*
- * SPI w/o chip-select line. One SPI device is still permitted
- * though.
- */
- pdata->max_chipselect = 1;
- return 0;
- }
-
- pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
- if (!pinfo->gpios)
- return -ENOMEM;
- memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
-
- pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
- GFP_KERNEL);
- if (!pinfo->alow_flags) {
- ret = -ENOMEM;
- goto err_alloc_flags;
- }
-
- for (; i < ngpios; i++) {
- int gpio;
- enum of_gpio_flags flags;
-
- gpio = of_get_gpio_flags(np, i, &flags);
- if (!gpio_is_valid(gpio)) {
- dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
- ret = gpio;
- goto err_loop;
- }
-
- ret = gpio_request(gpio, dev_name(dev));
- if (ret) {
- dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
- goto err_loop;
- }
-
- pinfo->gpios[i] = gpio;
- pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
-
- ret = gpio_direction_output(pinfo->gpios[i],
- pinfo->alow_flags[i]);
- if (ret) {
- dev_err(dev, "can't set output direction for gpio "
- "#%d: %d\n", i, ret);
- goto err_loop;
- }
- }
-
- pdata->max_chipselect = ngpios;
- pdata->cs_control = fsl_spi_cs_control;
-
- return 0;
-
-err_loop:
- while (i >= 0) {
- if (gpio_is_valid(pinfo->gpios[i]))
- gpio_free(pinfo->gpios[i]);
- i--;
- }
-
- kfree(pinfo->alow_flags);
- pinfo->alow_flags = NULL;
-err_alloc_flags:
- kfree(pinfo->gpios);
- pinfo->gpios = NULL;
- return ret;
-}
-
-static int of_fsl_spi_free_chipselects(struct device *dev)
-{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
- int i;
-
- if (!pinfo->gpios)
- return 0;
-
- for (i = 0; i < pdata->max_chipselect; i++) {
- if (gpio_is_valid(pinfo->gpios[i]))
- gpio_free(pinfo->gpios[i]);
- }
-
- kfree(pinfo->gpios);
- kfree(pinfo->alow_flags);
- return 0;
-}
-
-static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
-{
- struct device *dev = &ofdev->dev;
- struct device_node *np = ofdev->dev.of_node;
- struct spi_master *master;
- struct resource mem;
- struct resource irq;
- int ret = -ENOMEM;
-
- ret = of_mpc8xxx_spi_probe(ofdev);
- if (ret)
- return ret;
-
- ret = of_fsl_spi_get_chipselects(dev);
- if (ret)
- goto err;
-
- ret = of_address_to_resource(np, 0, &mem);
- if (ret)
- goto err;
-
- ret = of_irq_to_resource(np, 0, &irq);
- if (!ret) {
- ret = -EINVAL;
- goto err;
- }
-
- master = fsl_spi_probe(dev, &mem, irq.start);
- if (IS_ERR(master)) {
- ret = PTR_ERR(master);
- goto err;
- }
-
- return 0;
-
-err:
- of_fsl_spi_free_chipselects(dev);
- return ret;
-}
-
-static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
-{
- int ret;
-
- ret = mpc8xxx_spi_remove(&ofdev->dev);
- if (ret)
- return ret;
- of_fsl_spi_free_chipselects(&ofdev->dev);
- return 0;
-}
-
-static const struct of_device_id of_fsl_spi_match[] = {
- { .compatible = "fsl,spi" },
- {}
-};
-MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
-
-static struct platform_driver of_fsl_spi_driver = {
- .driver = {
- .name = "fsl_spi",
- .owner = THIS_MODULE,
- .of_match_table = of_fsl_spi_match,
- },
- .probe = of_fsl_spi_probe,
- .remove = __devexit_p(of_fsl_spi_remove),
-};
-
-#ifdef CONFIG_MPC832x_RDB
-/*
- * XXX XXX XXX
- * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
- * only. The driver should go away soon, since newer MPC8323E-RDB's device
- * tree can work with OpenFirmware driver. But for now we support old trees
- * as well.
- */
-static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
-{
- struct resource *mem;
- int irq;
- struct spi_master *master;
-
- if (!pdev->dev.platform_data)
- return -EINVAL;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem)
- return -EINVAL;
-
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0)
- return -EINVAL;
-
- master = fsl_spi_probe(&pdev->dev, mem, irq);
- if (IS_ERR(master))
- return PTR_ERR(master);
- return 0;
-}
-
-static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
-{
- return mpc8xxx_spi_remove(&pdev->dev);
-}
-
-MODULE_ALIAS("platform:mpc8xxx_spi");
-static struct platform_driver mpc8xxx_spi_driver = {
- .probe = plat_mpc8xxx_spi_probe,
- .remove = __devexit_p(plat_mpc8xxx_spi_remove),
- .driver = {
- .name = "mpc8xxx_spi",
- .owner = THIS_MODULE,
- },
-};
-
-static bool legacy_driver_failed;
-
-static void __init legacy_driver_register(void)
-{
- legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
-}
-
-static void __exit legacy_driver_unregister(void)
-{
- if (legacy_driver_failed)
- return;
- platform_driver_unregister(&mpc8xxx_spi_driver);
-}
-#else
-static void __init legacy_driver_register(void) {}
-static void __exit legacy_driver_unregister(void) {}
-#endif /* CONFIG_MPC832x_RDB */
-
-static int __init fsl_spi_init(void)
-{
- legacy_driver_register();
- return platform_driver_register(&of_fsl_spi_driver);
-}
-module_init(fsl_spi_init);
-
-static void __exit fsl_spi_exit(void)
-{
- platform_driver_unregister(&of_fsl_spi_driver);
- legacy_driver_unregister();
-}
-module_exit(fsl_spi_exit);
-
-MODULE_AUTHOR("Kumar Gala");
-MODULE_DESCRIPTION("Simple Freescale SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-gpio.c b/ANDROID_3.4.5/drivers/spi/spi-gpio.c
deleted file mode 100644
index 0094c645..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-gpio.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * SPI master driver using generic bitbanged GPIO
- *
- * Copyright (C) 2006,2008 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/spi_gpio.h>
-
-
-/*
- * This bitbanging SPI master driver should help make systems usable
- * when a native hardware SPI engine is not available, perhaps because
- * its driver isn't yet working or because the I/O pins it requires
- * are used for other purposes.
- *
- * platform_device->driver_data ... points to spi_gpio
- *
- * spi->controller_state ... reserved for bitbang framework code
- * spi->controller_data ... holds chipselect GPIO
- *
- * spi->master->dev.driver_data ... points to spi_gpio->bitbang
- */
-
-struct spi_gpio {
- struct spi_bitbang bitbang;
- struct spi_gpio_platform_data pdata;
- struct platform_device *pdev;
-};
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Because the overhead of going through four GPIO procedure calls
- * per transferred bit can make performance a problem, this code
- * is set up so that you can use it in either of two ways:
- *
- * - The slow generic way: set up platform_data to hold the GPIO
- * numbers used for MISO/MOSI/SCK, and issue procedure calls for
- * each of them. This driver can handle several such busses.
- *
- * - The quicker inlined way: only helps with platform GPIO code
- * that inlines operations for constant GPIOs. This can give
- * you tight (fast!) inner loops, but each such bus needs a
- * new driver. You'll define a new C file, with Makefile and
- * Kconfig support; the C code can be a total of six lines:
- *
- * #define DRIVER_NAME "myboard_spi2"
- * #define SPI_MISO_GPIO 119
- * #define SPI_MOSI_GPIO 120
- * #define SPI_SCK_GPIO 121
- * #define SPI_N_CHIPSEL 4
- * #include "spi-gpio.c"
- */
-
-#ifndef DRIVER_NAME
-#define DRIVER_NAME "spi_gpio"
-
-#define GENERIC_BITBANG /* vs tight inlines */
-
-/* all functions referencing these symbols must define pdata */
-#define SPI_MISO_GPIO ((pdata)->miso)
-#define SPI_MOSI_GPIO ((pdata)->mosi)
-#define SPI_SCK_GPIO ((pdata)->sck)
-
-#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
-
-#endif
-
-/*----------------------------------------------------------------------*/
-
-static inline const struct spi_gpio_platform_data * __pure
-spi_to_pdata(const struct spi_device *spi)
-{
- const struct spi_bitbang *bang;
- const struct spi_gpio *spi_gpio;
-
- bang = spi_master_get_devdata(spi->master);
- spi_gpio = container_of(bang, struct spi_gpio, bitbang);
- return &spi_gpio->pdata;
-}
-
-/* this is #defined to avoid unused-variable warnings when inlining */
-#define pdata spi_to_pdata(spi)
-
-static inline void setsck(const struct spi_device *spi, int is_on)
-{
- gpio_set_value(SPI_SCK_GPIO, is_on);
-}
-
-static inline void setmosi(const struct spi_device *spi, int is_on)
-{
- gpio_set_value(SPI_MOSI_GPIO, is_on);
-}
-
-static inline int getmiso(const struct spi_device *spi)
-{
- return !!gpio_get_value(SPI_MISO_GPIO);
-}
-
-#undef pdata
-
-/*
- * NOTE: this clocks "as fast as we can". It "should" be a function of the
- * requested device clock. Software overhead means we usually have trouble
- * reaching even one Mbit/sec (except when we can inline bitops), so for now
- * we'll just assume we never need additional per-bit slowdowns.
- */
-#define spidelay(nsecs) do {} while (0)
-
-#include "spi-bitbang-txrx.h"
-
-/*
- * These functions can leverage inline expansion of GPIO calls to shrink
- * costs for a txrx bit, often by factors of around ten (by instruction
- * count). That is particularly visible for larger word sizes, but helps
- * even with default 8-bit words.
- *
- * REVISIT overheads calling these functions for each word also have
- * significant performance costs. Having txrx_bufs() calls that inline
- * the txrx_word() logic would help performance, e.g. on larger blocks
- * used with flash storage or MMC/SD. There should also be ways to make
- * GCC be less stupid about reloading registers inside the I/O loops,
- * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3?
- */
-
-static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
-}
-
-static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
-}
-
-/*
- * These functions do not call setmosi or getmiso if respective flag
- * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
- * call when such pin is not present or defined in the controller.
- * A separate set of callbacks is defined to get highest possible
- * speed in the generic case (when both MISO and MOSI lines are
- * available), as optimiser will remove the checks when argument is
- * constant.
- */
-
-static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- unsigned flags = spi->master->flags;
- return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
-}
-
-static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- unsigned flags = spi->master->flags;
- return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
-}
-
-static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- unsigned flags = spi->master->flags;
- return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
-}
-
-static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
- unsigned nsecs, u32 word, u8 bits)
-{
- unsigned flags = spi->master->flags;
- return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
-}
-
-/*----------------------------------------------------------------------*/
-
-static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
-{
- unsigned long cs = (unsigned long) spi->controller_data;
-
- /* set initial clock polarity */
- if (is_active)
- setsck(spi, spi->mode & SPI_CPOL);
-
- if (cs != SPI_GPIO_NO_CHIPSELECT) {
- /* SPI is normally active-low */
- gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
- }
-}
-
-static int spi_gpio_setup(struct spi_device *spi)
-{
- unsigned long cs = (unsigned long) spi->controller_data;
- int status = 0;
-
- if (spi->bits_per_word > 32)
- return -EINVAL;
-
- if (!spi->controller_state) {
- if (cs != SPI_GPIO_NO_CHIPSELECT) {
- status = gpio_request(cs, dev_name(&spi->dev));
- if (status)
- return status;
- status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
- }
- }
- if (!status)
- status = spi_bitbang_setup(spi);
- if (status) {
- if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
- gpio_free(cs);
- }
- return status;
-}
-
-static void spi_gpio_cleanup(struct spi_device *spi)
-{
- unsigned long cs = (unsigned long) spi->controller_data;
-
- if (cs != SPI_GPIO_NO_CHIPSELECT)
- gpio_free(cs);
- spi_bitbang_cleanup(spi);
-}
-
-static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
-{
- int value;
-
- value = gpio_request(pin, label);
- if (value == 0) {
- if (is_in)
- value = gpio_direction_input(pin);
- else
- value = gpio_direction_output(pin, 0);
- }
- return value;
-}
-
-static int __devinit
-spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
- u16 *res_flags)
-{
- int value;
-
- /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
-
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
- value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
- if (value)
- goto done;
- } else {
- /* HW configuration without MOSI pin */
- *res_flags |= SPI_MASTER_NO_TX;
- }
-
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
- value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
- if (value)
- goto free_mosi;
- } else {
- /* HW configuration without MISO pin */
- *res_flags |= SPI_MASTER_NO_RX;
- }
-
- value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
- if (value)
- goto free_miso;
-
- goto done;
-
-free_miso:
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
- gpio_free(SPI_MISO_GPIO);
-free_mosi:
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
- gpio_free(SPI_MOSI_GPIO);
-done:
- return value;
-}
-
-static int __devinit spi_gpio_probe(struct platform_device *pdev)
-{
- int status;
- struct spi_master *master;
- struct spi_gpio *spi_gpio;
- struct spi_gpio_platform_data *pdata;
- u16 master_flags = 0;
-
- pdata = pdev->dev.platform_data;
-#ifdef GENERIC_BITBANG
- if (!pdata || !pdata->num_chipselect)
- return -ENODEV;
-#endif
-
- status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
- if (status < 0)
- return status;
-
- master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
- if (!master) {
- status = -ENOMEM;
- goto gpio_free;
- }
- spi_gpio = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, spi_gpio);
-
- spi_gpio->pdev = pdev;
- if (pdata)
- spi_gpio->pdata = *pdata;
-
- master->flags = master_flags;
- master->bus_num = pdev->id;
- master->num_chipselect = SPI_N_CHIPSEL;
- master->setup = spi_gpio_setup;
- master->cleanup = spi_gpio_cleanup;
-
- spi_gpio->bitbang.master = spi_master_get(master);
- spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
-
- if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
- spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
- spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
- spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
- spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
- } else {
- spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
- spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
- spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
- spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
- }
- spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
- spi_gpio->bitbang.flags = SPI_CS_HIGH;
-
- status = spi_bitbang_start(&spi_gpio->bitbang);
- if (status < 0) {
- spi_master_put(spi_gpio->bitbang.master);
-gpio_free:
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
- gpio_free(SPI_MISO_GPIO);
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
- gpio_free(SPI_MOSI_GPIO);
- gpio_free(SPI_SCK_GPIO);
- spi_master_put(master);
- }
-
- return status;
-}
-
-static int __devexit spi_gpio_remove(struct platform_device *pdev)
-{
- struct spi_gpio *spi_gpio;
- struct spi_gpio_platform_data *pdata;
- int status;
-
- spi_gpio = platform_get_drvdata(pdev);
- pdata = pdev->dev.platform_data;
-
- /* stop() unregisters child devices too */
- status = spi_bitbang_stop(&spi_gpio->bitbang);
- spi_master_put(spi_gpio->bitbang.master);
-
- platform_set_drvdata(pdev, NULL);
-
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
- gpio_free(SPI_MISO_GPIO);
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
- gpio_free(SPI_MOSI_GPIO);
- gpio_free(SPI_SCK_GPIO);
-
- return status;
-}
-
-MODULE_ALIAS("platform:" DRIVER_NAME);
-
-static struct platform_driver spi_gpio_driver = {
- .driver.name = DRIVER_NAME,
- .driver.owner = THIS_MODULE,
- .probe = spi_gpio_probe,
- .remove = __devexit_p(spi_gpio_remove),
-};
-module_platform_driver(spi_gpio_driver);
-
-MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
-MODULE_AUTHOR("David Brownell");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-imx.c b/ANDROID_3.4.5/drivers/spi/spi-imx.c
deleted file mode 100644
index 570f2205..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-imx.c
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 Juergen Beisert
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301, USA.
- */
-
-#include <linux/clk.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#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>
-
-#define DRIVER_NAME "spi_imx"
-
-#define MXC_CSPIRXDATA 0x00
-#define MXC_CSPITXDATA 0x04
-#define MXC_CSPICTRL 0x08
-#define MXC_CSPIINT 0x0c
-#define MXC_RESET 0x1c
-
-/* 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 */
-
-struct spi_imx_config {
- unsigned int speed_hz;
- unsigned int bpw;
- unsigned int mode;
- u8 cs;
-};
-
-enum spi_imx_devtype {
- 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;
-
-struct spi_imx_devtype_data {
- void (*intctrl)(struct spi_imx_data *, int);
- int (*config)(struct spi_imx_data *, struct spi_imx_config *);
- void (*trigger)(struct spi_imx_data *);
- int (*rx_available)(struct spi_imx_data *);
- void (*reset)(struct spi_imx_data *);
- enum spi_imx_devtype devtype;
-};
-
-struct spi_imx_data {
- struct spi_bitbang bitbang;
-
- struct completion xfer_done;
- void __iomem *base;
- int irq;
- struct clk *clk;
- unsigned long spi_clk;
-
- unsigned int count;
- void (*tx)(struct spi_imx_data *);
- void (*rx)(struct spi_imx_data *);
- void *rx_buf;
- const void *tx_buf;
- unsigned int txfifo; /* number of words pushed in tx FIFO */
-
- 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) \
-{ \
- unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA); \
- \
- if (spi_imx->rx_buf) { \
- *(type *)spi_imx->rx_buf = val; \
- spi_imx->rx_buf += sizeof(type); \
- } \
-}
-
-#define MXC_SPI_BUF_TX(type) \
-static void spi_imx_buf_tx_##type(struct spi_imx_data *spi_imx) \
-{ \
- type val = 0; \
- \
- if (spi_imx->tx_buf) { \
- val = *(type *)spi_imx->tx_buf; \
- spi_imx->tx_buf += sizeof(type); \
- } \
- \
- spi_imx->count -= sizeof(type); \
- \
- writel(val, spi_imx->base + MXC_CSPITXDATA); \
-}
-
-MXC_SPI_BUF_RX(u8)
-MXC_SPI_BUF_TX(u8)
-MXC_SPI_BUF_RX(u16)
-MXC_SPI_BUF_TX(u16)
-MXC_SPI_BUF_RX(u32)
-MXC_SPI_BUF_TX(u32)
-
-/* First entry is reserved, second entry is valid only if SDHC_SPIEN is set
- * (which is currently not the case in this driver)
- */
-static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
- 256, 384, 512, 768, 1024};
-
-/* MX21, MX27 */
-static unsigned int spi_imx_clkdiv_1(unsigned int fin,
- unsigned int fspi, unsigned int max)
-{
- int i;
-
- for (i = 2; i < max; i++)
- if (fspi * mxc_clkdivs[i] >= fin)
- return i;
-
- return max;
-}
-
-/* MX1, MX31, MX35, MX51 CSPI */
-static unsigned int spi_imx_clkdiv_2(unsigned int fin,
- unsigned int fspi)
-{
- int i, div = 4;
-
- for (i = 0; i < 7; i++) {
- if (fspi * div >= fin)
- return i;
- div <<= 1;
- }
-
- return 7;
-}
-
-#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 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 MX51_ECSPI_INT 0x10
-#define MX51_ECSPI_INT_TEEN (1 << 0)
-#define MX51_ECSPI_INT_RREN (1 << 3)
-
-#define MX51_ECSPI_STAT 0x18
-#define MX51_ECSPI_STAT_RR (1 << 3)
-
-/* MX51 eCSPI */
-static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
-{
- /*
- * there are two 4-bit dividers, the pre-divider divides by
- * $pre, the post-divider by 2^$post
- */
- unsigned int pre, post;
-
- if (unlikely(fspi > fin))
- return 0;
-
- post = fls(fin) - fls(fspi);
- if (fin > fspi << post)
- post++;
-
- /* now we have: (fin <= fspi << post) with post being minimal */
-
- post = max(4U, post) - 4;
- if (unlikely(post > 0xf)) {
- pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
- __func__, fspi, fin);
- return 0xff;
- }
-
- pre = DIV_ROUND_UP(fin, fspi << post) - 1;
-
- pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
- __func__, fin, fspi, post, pre);
- return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
- (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
-}
-
-static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
- unsigned val = 0;
-
- if (enable & MXC_INT_TE)
- val |= MX51_ECSPI_INT_TEEN;
-
- if (enable & MXC_INT_RR)
- val |= MX51_ECSPI_INT_RREN;
-
- writel(val, spi_imx->base + MX51_ECSPI_INT);
-}
-
-static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
-{
- u32 reg;
-
- 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 mx51_ecspi_config(struct spi_imx_data *spi_imx,
- struct spi_imx_config *config)
-{
- u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
-
- /*
- * The hardware seems to have a race condition when changing modes. The
- * current assumption is that the selection of the channel arrives
- * earlier in the hardware than the mode bits when they are written at
- * the same time.
- * So set master mode for all channels as we do not support slave mode.
- */
- ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
-
- /* set clock speed */
- ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
-
- /* set chip select to use */
- ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
-
- ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
-
- cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);
-
- if (config->mode & SPI_CPHA)
- cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
-
- if (config->mode & SPI_CPOL)
- cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
-
- if (config->mode & SPI_CS_HIGH)
- cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
-
- writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
- writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
-
- return 0;
-}
-
-static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
-{
- return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR;
-}
-
-static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)
-{
- /* drain receive buffer */
- while (mx51_ecspi_rx_available(spi_imx))
- readl(spi_imx->base + MXC_CSPIRXDATA);
-}
-
-#define MX31_INTREG_TEEN (1 << 0)
-#define MX31_INTREG_RREN (1 << 3)
-
-#define MX31_CSPICTRL_ENABLE (1 << 0)
-#define MX31_CSPICTRL_MASTER (1 << 1)
-#define MX31_CSPICTRL_XCH (1 << 2)
-#define MX31_CSPICTRL_POL (1 << 4)
-#define MX31_CSPICTRL_PHA (1 << 5)
-#define MX31_CSPICTRL_SSCTL (1 << 6)
-#define MX31_CSPICTRL_SSPOL (1 << 7)
-#define MX31_CSPICTRL_BC_SHIFT 8
-#define MX35_CSPICTRL_BL_SHIFT 20
-#define MX31_CSPICTRL_CS_SHIFT 24
-#define MX35_CSPICTRL_CS_SHIFT 12
-#define MX31_CSPICTRL_DR_SHIFT 16
-
-#define MX31_CSPISTATUS 0x14
-#define MX31_STATUS_RR (1 << 3)
-
-/* These functions also work for the i.MX35, but be aware that
- * the i.MX35 has a slightly different register layout for bits
- * we do not use here.
- */
-static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
- unsigned int val = 0;
-
- if (enable & MXC_INT_TE)
- val |= MX31_INTREG_TEEN;
- if (enable & MXC_INT_RR)
- val |= MX31_INTREG_RREN;
-
- writel(val, spi_imx->base + MXC_CSPIINT);
-}
-
-static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
-{
- unsigned int reg;
-
- reg = readl(spi_imx->base + MXC_CSPICTRL);
- reg |= MX31_CSPICTRL_XCH;
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-}
-
-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;
- int cs = spi_imx->chipselect[config->cs];
-
- reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
- MX31_CSPICTRL_DR_SHIFT;
-
- 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;
- 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) <<
- (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT :
- MX31_CSPICTRL_CS_SHIFT);
-
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-
- return 0;
-}
-
-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 mx31_reset(struct spi_imx_data *spi_imx)
-{
- /* drain receive buffer */
- while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR)
- readl(spi_imx->base + MXC_CSPIRXDATA);
-}
-
-#define MX21_INTREG_RR (1 << 4)
-#define MX21_INTREG_TEEN (1 << 9)
-#define MX21_INTREG_RREN (1 << 13)
-
-#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 mx21_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
- unsigned int val = 0;
-
- if (enable & MXC_INT_TE)
- val |= MX21_INTREG_TEEN;
- if (enable & MXC_INT_RR)
- val |= MX21_INTREG_RREN;
-
- writel(val, spi_imx->base + MXC_CSPIINT);
-}
-
-static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)
-{
- unsigned int reg;
-
- reg = readl(spi_imx->base + MXC_CSPICTRL);
- reg |= MX21_CSPICTRL_XCH;
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-}
-
-static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx,
- struct spi_imx_config *config)
-{
- 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, max) <<
- MX21_CSPICTRL_DR_SHIFT;
- reg |= config->bpw - 1;
-
- if (config->mode & SPI_CPHA)
- reg |= MX21_CSPICTRL_PHA;
- if (config->mode & SPI_CPOL)
- reg |= MX21_CSPICTRL_POL;
- if (config->mode & SPI_CS_HIGH)
- reg |= MX21_CSPICTRL_SSPOL;
- if (cs < 0)
- reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT;
-
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-
- return 0;
-}
-
-static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx)
-{
- return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR;
-}
-
-static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)
-{
- writel(1, spi_imx->base + MXC_RESET);
-}
-
-#define MX1_INTREG_RR (1 << 3)
-#define MX1_INTREG_TEEN (1 << 8)
-#define MX1_INTREG_RREN (1 << 11)
-
-#define MX1_CSPICTRL_POL (1 << 4)
-#define MX1_CSPICTRL_PHA (1 << 5)
-#define MX1_CSPICTRL_XCH (1 << 8)
-#define MX1_CSPICTRL_ENABLE (1 << 9)
-#define MX1_CSPICTRL_MASTER (1 << 10)
-#define MX1_CSPICTRL_DR_SHIFT 13
-
-static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
- unsigned int val = 0;
-
- if (enable & MXC_INT_TE)
- val |= MX1_INTREG_TEEN;
- if (enable & MXC_INT_RR)
- val |= MX1_INTREG_RREN;
-
- writel(val, spi_imx->base + MXC_CSPIINT);
-}
-
-static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
-{
- unsigned int reg;
-
- reg = readl(spi_imx->base + MXC_CSPICTRL);
- reg |= MX1_CSPICTRL_XCH;
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-}
-
-static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
- struct spi_imx_config *config)
-{
- unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
-
- reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
- MX1_CSPICTRL_DR_SHIFT;
- reg |= config->bpw - 1;
-
- if (config->mode & SPI_CPHA)
- reg |= MX1_CSPICTRL_PHA;
- if (config->mode & SPI_CPOL)
- reg |= MX1_CSPICTRL_POL;
-
- writel(reg, spi_imx->base + MXC_CSPICTRL);
-
- return 0;
-}
-
-static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
-{
- return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
-}
-
-static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
-{
- writel(1, spi_imx->base + MXC_RESET);
-}
-
-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)
-{
- struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
- int gpio = spi_imx->chipselect[spi->chip_select];
- int active = is_active != BITBANG_CS_INACTIVE;
- int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
-
- if (gpio < 0)
- return;
-
- gpio_set_value(gpio, dev_is_lowactive ^ active);
-}
-
-static void spi_imx_push(struct spi_imx_data *spi_imx)
-{
- 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);
-}
-
-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)) {
- spi_imx->rx(spi_imx);
- spi_imx->txfifo--;
- }
-
- if (spi_imx->count) {
- spi_imx_push(spi_imx);
- return IRQ_HANDLED;
- }
-
- if (spi_imx->txfifo) {
- /* No data left to push, but still waiting for rx data,
- * enable receive data available interrupt.
- */
- spi_imx->devtype_data->intctrl(
- spi_imx, MXC_INT_RR);
- return IRQ_HANDLED;
- }
-
- spi_imx->devtype_data->intctrl(spi_imx, 0);
- complete(&spi_imx->xfer_done);
-
- return IRQ_HANDLED;
-}
-
-static int spi_imx_setupxfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
- struct spi_imx_config config;
-
- config.bpw = t ? t->bits_per_word : spi->bits_per_word;
- config.speed_hz = t ? t->speed_hz : spi->max_speed_hz;
- config.mode = spi->mode;
- config.cs = spi->chip_select;
-
- if (!config.speed_hz)
- config.speed_hz = spi->max_speed_hz;
- if (!config.bpw)
- config.bpw = spi->bits_per_word;
- if (!config.speed_hz)
- config.speed_hz = spi->max_speed_hz;
-
- /* Initialize the functions for transfer */
- if (config.bpw <= 8) {
- spi_imx->rx = spi_imx_buf_rx_u8;
- spi_imx->tx = spi_imx_buf_tx_u8;
- } else if (config.bpw <= 16) {
- spi_imx->rx = spi_imx_buf_rx_u16;
- spi_imx->tx = spi_imx_buf_tx_u16;
- } else if (config.bpw <= 32) {
- spi_imx->rx = spi_imx_buf_rx_u32;
- spi_imx->tx = spi_imx_buf_tx_u32;
- } else
- BUG();
-
- spi_imx->devtype_data->config(spi_imx, &config);
-
- return 0;
-}
-
-static int spi_imx_transfer(struct spi_device *spi,
- struct spi_transfer *transfer)
-{
- struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-
- spi_imx->tx_buf = transfer->tx_buf;
- spi_imx->rx_buf = transfer->rx_buf;
- spi_imx->count = transfer->len;
- spi_imx->txfifo = 0;
-
- init_completion(&spi_imx->xfer_done);
-
- spi_imx_push(spi_imx);
-
- spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);
-
- wait_for_completion(&spi_imx->xfer_done);
-
- return transfer->len;
-}
-
-static int spi_imx_setup(struct spi_device *spi)
-{
- struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
- int gpio = spi_imx->chipselect[spi->chip_select];
-
- dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
- spi->mode, spi->bits_per_word, spi->max_speed_hz);
-
- if (gpio >= 0)
- gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
-
- spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
-
- return 0;
-}
-
-static void spi_imx_cleanup(struct spi_device *spi)
-{
-}
-
-static int __devinit spi_imx_probe(struct platform_device *pdev)
-{
- 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, num_cs;
-
- if (!np && !mxc_platform_info) {
- dev_err(&pdev->dev, "can't get the platform data\n");
- return -EINVAL;
- }
-
- ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
- if (ret < 0) {
- if (mxc_platform_info)
- num_cs = mxc_platform_info->num_chipselect;
- else
- return ret;
- }
-
- 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 = num_cs;
-
- spi_imx = spi_master_get_devdata(master);
- spi_imx->bitbang.master = spi_master_get(master);
-
- for (i = 0; i < master->num_chipselect; i++) {
- int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
- if (cs_gpio < 0 && mxc_platform_info)
- cs_gpio = mxc_platform_info->chipselect[i];
-
- spi_imx->chipselect[i] = cs_gpio;
- if (cs_gpio < 0)
- continue;
-
- ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
- if (ret) {
- dev_err(&pdev->dev, "can't get cs gpios\n");
- goto out_gpio_free;
- }
- }
-
- spi_imx->bitbang.chipselect = spi_imx_chipselect;
- spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
- spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
- spi_imx->bitbang.master->setup = spi_imx_setup;
- spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
- spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- init_completion(&spi_imx->xfer_done);
-
- 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) {
- dev_err(&pdev->dev, "can't get platform resource\n");
- ret = -ENOMEM;
- goto out_gpio_free;
- }
-
- if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
- dev_err(&pdev->dev, "request_mem_region failed\n");
- ret = -EBUSY;
- goto out_gpio_free;
- }
-
- spi_imx->base = ioremap(res->start, resource_size(res));
- if (!spi_imx->base) {
- ret = -EINVAL;
- goto out_release_mem;
- }
-
- spi_imx->irq = platform_get_irq(pdev, 0);
- if (spi_imx->irq < 0) {
- ret = -EINVAL;
- goto out_iounmap;
- }
-
- ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
- if (ret) {
- dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
- goto out_iounmap;
- }
-
- spi_imx->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(spi_imx->clk)) {
- dev_err(&pdev->dev, "unable to get clock\n");
- ret = PTR_ERR(spi_imx->clk);
- goto out_free_irq;
- }
-
- 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->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);
- goto out_clk_put;
- }
-
- dev_info(&pdev->dev, "probed\n");
-
- return ret;
-
-out_clk_put:
- clk_disable(spi_imx->clk);
- clk_put(spi_imx->clk);
-out_free_irq:
- free_irq(spi_imx->irq, spi_imx);
-out_iounmap:
- iounmap(spi_imx->base);
-out_release_mem:
- release_mem_region(res->start, resource_size(res));
-out_gpio_free:
- while (--i >= 0) {
- if (spi_imx->chipselect[i] >= 0)
- gpio_free(spi_imx->chipselect[i]);
- }
- spi_master_put(master);
- kfree(master);
- platform_set_drvdata(pdev, NULL);
- return ret;
-}
-
-static int __devexit spi_imx_remove(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
- int i;
-
- spi_bitbang_stop(&spi_imx->bitbang);
-
- writel(0, spi_imx->base + MXC_CSPICTRL);
- clk_disable(spi_imx->clk);
- clk_put(spi_imx->clk);
- free_irq(spi_imx->irq, spi_imx);
- iounmap(spi_imx->base);
-
- for (i = 0; i < master->num_chipselect; i++)
- if (spi_imx->chipselect[i] >= 0)
- gpio_free(spi_imx->chipselect[i]);
-
- spi_master_put(master);
-
- release_mem_region(res->start, resource_size(res));
-
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-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,
- .remove = __devexit_p(spi_imx_remove),
-};
-module_platform_driver(spi_imx_driver);
-
-MODULE_DESCRIPTION("SPI Master Controller driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-lm70llp.c b/ANDROID_3.4.5/drivers/spi/spi-lm70llp.c
deleted file mode 100644
index 933eb9d9..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-lm70llp.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Driver for LM70EVAL-LLP board for the LM70 sensor
- *
- * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/parport.h>
-#include <linux/sysfs.h>
-#include <linux/workqueue.h>
-
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-
-/*
- * The LM70 communicates with a host processor using a 3-wire variant of
- * the SPI/Microwire bus interface. This driver specifically supports an
- * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
- * port to bitbang an SPI-parport bridge. Accordingly, this is an SPI
- * master controller driver. The hwmon/lm70 driver is a "SPI protocol
- * driver", layered on top of this one and usable without the lm70llp.
- *
- * Datasheet and Schematic:
- * The LM70 is a temperature sensor chip from National Semiconductor; its
- * datasheet is available at http://www.national.com/pf/LM/LM70.html
- * The schematic for this particular board (the LM70EVAL-LLP) is
- * available (on page 4) here:
- * http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf
- *
- * Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is
- * (heavily) based on spi-butterfly by David Brownell.
- *
- * The LM70 LLP connects to the PC parallel port in the following manner:
- *
- * Parallel LM70 LLP
- * Port Direction JP2 Header
- * ----------- --------- ------------
- * D0 2 - -
- * D1 3 --> V+ 5
- * D2 4 --> V+ 5
- * D3 5 --> V+ 5
- * D4 6 --> V+ 5
- * D5 7 --> nCS 8
- * D6 8 --> SCLK 3
- * D7 9 --> SI/O 5
- * GND 25 - GND 7
- * Select 13 <-- SI/O 1
- *
- * Note that parport pin 13 actually gets inverted by the transistor
- * arrangement which lets either the parport or the LM70 drive the
- * SI/SO signal (see the schematic for details).
- */
-
-#define DRVNAME "spi-lm70llp"
-
-#define lm70_INIT 0xBE
-#define SIO 0x10
-#define nCS 0x20
-#define SCLK 0x40
-
-/*-------------------------------------------------------------------------*/
-
-struct spi_lm70llp {
- struct spi_bitbang bitbang;
- struct parport *port;
- struct pardevice *pd;
- struct spi_device *spidev_lm70;
- struct spi_board_info info;
- //struct device *dev;
-};
-
-/* REVISIT : ugly global ; provides "exclusive open" facility */
-static struct spi_lm70llp *lm70llp;
-
-
-/*-------------------------------------------------------------------*/
-
-static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
-{
- return spi->controller_data;
-}
-
-/*---------------------- LM70 LLP eval board-specific inlines follow */
-
-/* NOTE: we don't actually need to reread the output values, since they'll
- * still be what we wrote before. Plus, going through parport builds in
- * a ~1ms/operation delay; these SPI transfers could easily be faster.
- */
-
-static inline void deassertCS(struct spi_lm70llp *pp)
-{
- u8 data = parport_read_data(pp->port);
-
- data &= ~0x80; /* pull D7/SI-out low while de-asserted */
- parport_write_data(pp->port, data | nCS);
-}
-
-static inline void assertCS(struct spi_lm70llp *pp)
-{
- u8 data = parport_read_data(pp->port);
-
- data |= 0x80; /* pull D7/SI-out high so lm70 drives SO-in */
- parport_write_data(pp->port, data & ~nCS);
-}
-
-static inline void clkHigh(struct spi_lm70llp *pp)
-{
- u8 data = parport_read_data(pp->port);
- parport_write_data(pp->port, data | SCLK);
-}
-
-static inline void clkLow(struct spi_lm70llp *pp)
-{
- u8 data = parport_read_data(pp->port);
- parport_write_data(pp->port, data & ~SCLK);
-}
-
-/*------------------------- SPI-LM70-specific inlines ----------------------*/
-
-static inline void spidelay(unsigned d)
-{
- udelay(d);
-}
-
-static inline void setsck(struct spi_device *s, int is_on)
-{
- struct spi_lm70llp *pp = spidev_to_pp(s);
-
- if (is_on)
- clkHigh(pp);
- else
- clkLow(pp);
-}
-
-static inline void setmosi(struct spi_device *s, int is_on)
-{
- /* FIXME update D7 ... this way we can put the chip
- * into shutdown mode and read the manufacturer ID,
- * but we can't put it back into operational mode.
- */
-}
-
-/*
- * getmiso:
- * Why do we return 0 when the SIO line is high and vice-versa?
- * The fact is, the lm70 eval board from NS (which this driver drives),
- * is wired in just such a way : when the lm70's SIO goes high, a transistor
- * switches it to low reflecting this on the parport (pin 13), and vice-versa.
- */
-static inline int getmiso(struct spi_device *s)
-{
- struct spi_lm70llp *pp = spidev_to_pp(s);
- return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 );
-}
-/*--------------------------------------------------------------------*/
-
-#include "spi-bitbang-txrx.h"
-
-static void lm70_chipselect(struct spi_device *spi, int value)
-{
- struct spi_lm70llp *pp = spidev_to_pp(spi);
-
- if (value)
- assertCS(pp);
- else
- deassertCS(pp);
-}
-
-/*
- * Our actual bitbanger routine.
- */
-static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
-{
- return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static void spi_lm70llp_attach(struct parport *p)
-{
- struct pardevice *pd;
- struct spi_lm70llp *pp;
- struct spi_master *master;
- int status;
-
- if (lm70llp) {
- printk(KERN_WARNING
- "%s: spi_lm70llp instance already loaded. Aborting.\n",
- DRVNAME);
- return;
- }
-
- /* TODO: this just _assumes_ a lm70 is there ... no probe;
- * the lm70 driver could verify it, reading the manf ID.
- */
-
- master = spi_alloc_master(p->physport->dev, sizeof *pp);
- if (!master) {
- status = -ENOMEM;
- goto out_fail;
- }
- pp = spi_master_get_devdata(master);
-
- master->bus_num = -1; /* dynamic alloc of a bus number */
- master->num_chipselect = 1;
-
- /*
- * SPI and bitbang hookup.
- */
- pp->bitbang.master = spi_master_get(master);
- pp->bitbang.chipselect = lm70_chipselect;
- pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
- pp->bitbang.flags = SPI_3WIRE;
-
- /*
- * Parport hookup
- */
- pp->port = p;
- pd = parport_register_device(p, DRVNAME,
- NULL, NULL, NULL,
- PARPORT_FLAG_EXCL, pp);
- if (!pd) {
- status = -ENOMEM;
- goto out_free_master;
- }
- pp->pd = pd;
-
- status = parport_claim(pd);
- if (status < 0)
- goto out_parport_unreg;
-
- /*
- * Start SPI ...
- */
- status = spi_bitbang_start(&pp->bitbang);
- if (status < 0) {
- printk(KERN_WARNING
- "%s: spi_bitbang_start failed with status %d\n",
- DRVNAME, status);
- goto out_off_and_release;
- }
-
- /*
- * The modalias name MUST match the device_driver name
- * for the bus glue code to match and subsequently bind them.
- * We are binding to the generic drivers/hwmon/lm70.c device
- * driver.
- */
- strcpy(pp->info.modalias, "lm70");
- pp->info.max_speed_hz = 6 * 1000 * 1000;
- pp->info.chip_select = 0;
- pp->info.mode = SPI_3WIRE | SPI_MODE_0;
-
- /* power up the chip, and let the LM70 control SI/SO */
- parport_write_data(pp->port, lm70_INIT);
-
- /* Enable access to our primary data structure via
- * the board info's (void *)controller_data.
- */
- pp->info.controller_data = pp;
- pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
- if (pp->spidev_lm70)
- dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
- dev_name(&pp->spidev_lm70->dev));
- else {
- printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
- status = -ENODEV;
- goto out_bitbang_stop;
- }
- pp->spidev_lm70->bits_per_word = 8;
-
- lm70llp = pp;
- return;
-
-out_bitbang_stop:
- spi_bitbang_stop(&pp->bitbang);
-out_off_and_release:
- /* power down */
- parport_write_data(pp->port, 0);
- mdelay(10);
- parport_release(pp->pd);
-out_parport_unreg:
- parport_unregister_device(pd);
-out_free_master:
- (void) spi_master_put(master);
-out_fail:
- pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status);
-}
-
-static void spi_lm70llp_detach(struct parport *p)
-{
- struct spi_lm70llp *pp;
-
- if (!lm70llp || lm70llp->port != p)
- return;
-
- pp = lm70llp;
- spi_bitbang_stop(&pp->bitbang);
-
- /* power down */
- parport_write_data(pp->port, 0);
-
- parport_release(pp->pd);
- parport_unregister_device(pp->pd);
-
- (void) spi_master_put(pp->bitbang.master);
-
- lm70llp = NULL;
-}
-
-
-static struct parport_driver spi_lm70llp_drv = {
- .name = DRVNAME,
- .attach = spi_lm70llp_attach,
- .detach = spi_lm70llp_detach,
-};
-
-static int __init init_spi_lm70llp(void)
-{
- return parport_register_driver(&spi_lm70llp_drv);
-}
-module_init(init_spi_lm70llp);
-
-static void __exit cleanup_spi_lm70llp(void)
-{
- parport_unregister_driver(&spi_lm70llp_drv);
-}
-module_exit(cleanup_spi_lm70llp);
-
-MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
-MODULE_DESCRIPTION(
- "Parport adapter for the National Semiconductor LM70 LLP eval board");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-mpc512x-psc.c b/ANDROID_3.4.5/drivers/spi/spi-mpc512x-psc.c
deleted file mode 100644
index 4c63f772..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-mpc512x-psc.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * MPC512x PSC in SPI mode driver.
- *
- * Copyright (C) 2007,2008 Freescale Semiconductor Inc.
- * Original port from 52xx driver:
- * Hongjun Chen <hong-jun.chen@freescale.com>
- *
- * Fork of mpc52xx_psc_spi.c:
- * Copyright (C) 2006 TOPTICA Photonics AG., Dragos Carp
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/spi/spi.h>
-#include <linux/fsl_devices.h>
-#include <asm/mpc52xx_psc.h>
-
-struct mpc512x_psc_spi {
- void (*cs_control)(struct spi_device *spi, bool on);
- u32 sysclk;
-
- /* driver internal data */
- struct mpc52xx_psc __iomem *psc;
- struct mpc512x_psc_fifo __iomem *fifo;
- unsigned int irq;
- u8 bits_per_word;
- u8 busy;
- u32 mclk;
- u8 eofbyte;
-
- struct workqueue_struct *workqueue;
- struct work_struct work;
-
- struct list_head queue;
- spinlock_t lock; /* Message queue lock */
-
- struct completion done;
-};
-
-/* controller state */
-struct mpc512x_psc_spi_cs {
- int bits_per_word;
- int speed_hz;
-};
-
-/* set clock freq, clock ramp, bits per work
- * if t is NULL then reset the values to the default values
- */
-static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct mpc512x_psc_spi_cs *cs = spi->controller_state;
-
- cs->speed_hz = (t && t->speed_hz)
- ? t->speed_hz : spi->max_speed_hz;
- cs->bits_per_word = (t && t->bits_per_word)
- ? t->bits_per_word : spi->bits_per_word;
- cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
- return 0;
-}
-
-static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
-{
- struct mpc512x_psc_spi_cs *cs = spi->controller_state;
- struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
- u32 sicr;
- u32 ccr;
- u16 bclkdiv;
-
- sicr = in_be32(&psc->sicr);
-
- /* Set clock phase and polarity */
- if (spi->mode & SPI_CPHA)
- sicr |= 0x00001000;
- else
- sicr &= ~0x00001000;
-
- if (spi->mode & SPI_CPOL)
- sicr |= 0x00002000;
- else
- sicr &= ~0x00002000;
-
- if (spi->mode & SPI_LSB_FIRST)
- sicr |= 0x10000000;
- else
- sicr &= ~0x10000000;
- out_be32(&psc->sicr, sicr);
-
- ccr = in_be32(&psc->ccr);
- ccr &= 0xFF000000;
- if (cs->speed_hz)
- bclkdiv = (mps->mclk / cs->speed_hz) - 1;
- else
- bclkdiv = (mps->mclk / 1000000) - 1; /* default 1MHz */
-
- ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
- out_be32(&psc->ccr, ccr);
- mps->bits_per_word = cs->bits_per_word;
-
- if (mps->cs_control)
- mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
-}
-
-static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
-{
- struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-
- if (mps->cs_control)
- mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-
-}
-
-/* extract and scale size field in txsz or rxsz */
-#define MPC512x_PSC_FIFO_SZ(sz) ((sz & 0x7ff) << 2);
-
-#define EOFBYTE 1
-
-static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
- struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
- size_t len = t->len;
- u8 *tx_buf = (u8 *)t->tx_buf;
- u8 *rx_buf = (u8 *)t->rx_buf;
-
- if (!tx_buf && !rx_buf && t->len)
- return -EINVAL;
-
- /* Zero MR2 */
- in_8(&psc->mode);
- out_8(&psc->mode, 0x0);
-
- while (len) {
- int count;
- int i;
- u8 data;
- size_t fifosz;
- int rxcount;
-
- /*
- * The number of bytes that can be sent at a time
- * depends on the fifo size.
- */
- fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
- count = min(fifosz, len);
-
- for (i = count; i > 0; i--) {
- data = tx_buf ? *tx_buf++ : 0;
- if (len == EOFBYTE)
- setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
- out_8(&fifo->txdata_8, data);
- len--;
- }
-
- INIT_COMPLETION(mps->done);
-
- /* interrupt on tx fifo empty */
- out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
- out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
-
- /* enable transmiter/receiver */
- out_8(&psc->command,
- MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
-
- wait_for_completion(&mps->done);
-
- mdelay(1);
-
- /* rx fifo should have count bytes in it */
- rxcount = in_be32(&fifo->rxcnt);
- if (rxcount != count)
- mdelay(1);
-
- rxcount = in_be32(&fifo->rxcnt);
- if (rxcount != count) {
- dev_warn(&spi->dev, "expected %d bytes in rx fifo "
- "but got %d\n", count, rxcount);
- }
-
- rxcount = min(rxcount, count);
- for (i = rxcount; i > 0; i--) {
- data = in_8(&fifo->rxdata_8);
- if (rx_buf)
- *rx_buf++ = data;
- }
- while (in_be32(&fifo->rxcnt)) {
- in_8(&fifo->rxdata_8);
- }
-
- out_8(&psc->command,
- MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
- }
- /* disable transmiter/receiver and fifo interrupt */
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
- out_be32(&fifo->tximr, 0);
- return 0;
-}
-
-static void mpc512x_psc_spi_work(struct work_struct *work)
-{
- struct mpc512x_psc_spi *mps = container_of(work,
- struct mpc512x_psc_spi,
- work);
-
- spin_lock_irq(&mps->lock);
- mps->busy = 1;
- while (!list_empty(&mps->queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
- unsigned cs_change;
- int status;
-
- m = container_of(mps->queue.next, struct spi_message, queue);
- list_del_init(&m->queue);
- spin_unlock_irq(&mps->lock);
-
- spi = m->spi;
- cs_change = 1;
- status = 0;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->bits_per_word || t->speed_hz) {
- status = mpc512x_psc_spi_transfer_setup(spi, t);
- if (status < 0)
- break;
- }
-
- if (cs_change)
- mpc512x_psc_spi_activate_cs(spi);
- cs_change = t->cs_change;
-
- status = mpc512x_psc_spi_transfer_rxtx(spi, t);
- if (status)
- break;
- m->actual_length += t->len;
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (cs_change)
- mpc512x_psc_spi_deactivate_cs(spi);
- }
-
- m->status = status;
- m->complete(m->context);
-
- if (status || !cs_change)
- mpc512x_psc_spi_deactivate_cs(spi);
-
- mpc512x_psc_spi_transfer_setup(spi, NULL);
-
- spin_lock_irq(&mps->lock);
- }
- mps->busy = 0;
- spin_unlock_irq(&mps->lock);
-}
-
-static int mpc512x_psc_spi_setup(struct spi_device *spi)
-{
- struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc512x_psc_spi_cs *cs = spi->controller_state;
- unsigned long flags;
-
- if (spi->bits_per_word % 8)
- return -EINVAL;
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- spi->controller_state = cs;
- }
-
- cs->bits_per_word = spi->bits_per_word;
- cs->speed_hz = spi->max_speed_hz;
-
- spin_lock_irqsave(&mps->lock, flags);
- if (!mps->busy)
- mpc512x_psc_spi_deactivate_cs(spi);
- spin_unlock_irqrestore(&mps->lock, flags);
-
- return 0;
-}
-
-static int mpc512x_psc_spi_transfer(struct spi_device *spi,
- struct spi_message *m)
-{
- struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- spin_lock_irqsave(&mps->lock, flags);
- list_add_tail(&m->queue, &mps->queue);
- queue_work(mps->workqueue, &mps->work);
- spin_unlock_irqrestore(&mps->lock, flags);
-
- return 0;
-}
-
-static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-
-static int mpc512x_psc_spi_port_config(struct spi_master *master,
- struct mpc512x_psc_spi *mps)
-{
- struct mpc52xx_psc __iomem *psc = mps->psc;
- struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
- struct clk *spiclk;
- int ret = 0;
- char name[32];
- u32 sicr;
- u32 ccr;
- u16 bclkdiv;
-
- sprintf(name, "psc%d_mclk", master->bus_num);
- spiclk = clk_get(&master->dev, name);
- clk_enable(spiclk);
- mps->mclk = clk_get_rate(spiclk);
- clk_put(spiclk);
-
- /* Reset the PSC into a known state */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-
- /* Disable psc interrupts all useful interrupts are in fifo */
- out_be16(&psc->isr_imr.imr, 0);
-
- /* Disable fifo interrupts, will be enabled later */
- out_be32(&fifo->tximr, 0);
- out_be32(&fifo->rximr, 0);
-
- /* Setup fifo slice address and size */
- /*out_be32(&fifo->txsz, 0x0fe00004);*/
- /*out_be32(&fifo->rxsz, 0x0ff00004);*/
-
- sicr = 0x01000000 | /* SIM = 0001 -- 8 bit */
- 0x00800000 | /* GenClk = 1 -- internal clk */
- 0x00008000 | /* SPI = 1 */
- 0x00004000 | /* MSTR = 1 -- SPI master */
- 0x00000800; /* UseEOF = 1 -- SS low until EOF */
-
- out_be32(&psc->sicr, sicr);
-
- ccr = in_be32(&psc->ccr);
- ccr &= 0xFF000000;
- bclkdiv = (mps->mclk / 1000000) - 1; /* default 1MHz */
- ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
- out_be32(&psc->ccr, ccr);
-
- /* Set 2ms DTL delay */
- out_8(&psc->ctur, 0x00);
- out_8(&psc->ctlr, 0x82);
-
- /* we don't use the alarms */
- out_be32(&fifo->rxalarm, 0xfff);
- out_be32(&fifo->txalarm, 0);
-
- /* Enable FIFO slices for Rx/Tx */
- out_be32(&fifo->rxcmd,
- MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
- out_be32(&fifo->txcmd,
- MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
-
- mps->bits_per_word = 8;
-
- return ret;
-}
-
-static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
-{
- struct mpc512x_psc_spi *mps = (struct mpc512x_psc_spi *)dev_id;
- struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-
- /* clear interrupt and wake up the work queue */
- if (in_be32(&fifo->txisr) &
- in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) {
- out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
- out_be32(&fifo->tximr, 0);
- complete(&mps->done);
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
-}
-
-/* bus_num is used only for the case dev->platform_data == NULL */
-static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
- u32 size, unsigned int irq,
- s16 bus_num)
-{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct mpc512x_psc_spi *mps;
- struct spi_master *master;
- int ret;
- void *tempp;
-
- master = spi_alloc_master(dev, sizeof *mps);
- if (master == NULL)
- return -ENOMEM;
-
- dev_set_drvdata(dev, master);
- mps = spi_master_get_devdata(master);
- mps->irq = irq;
-
- if (pdata == NULL) {
- dev_err(dev, "probe called without platform data, no "
- "cs_control function will be called\n");
- mps->cs_control = NULL;
- mps->sysclk = 0;
- master->bus_num = bus_num;
- master->num_chipselect = 255;
- } else {
- mps->cs_control = pdata->cs_control;
- mps->sysclk = pdata->sysclk;
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->max_chipselect;
- }
-
- master->setup = mpc512x_psc_spi_setup;
- master->transfer = mpc512x_psc_spi_transfer;
- master->cleanup = mpc512x_psc_spi_cleanup;
- master->dev.of_node = dev->of_node;
-
- tempp = ioremap(regaddr, size);
- if (!tempp) {
- dev_err(dev, "could not ioremap I/O port range\n");
- ret = -EFAULT;
- goto free_master;
- }
- mps->psc = tempp;
- mps->fifo =
- (struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
-
- ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
- "mpc512x-psc-spi", mps);
- if (ret)
- goto free_master;
-
- ret = mpc512x_psc_spi_port_config(master, mps);
- if (ret < 0)
- goto free_irq;
-
- spin_lock_init(&mps->lock);
- init_completion(&mps->done);
- INIT_WORK(&mps->work, mpc512x_psc_spi_work);
- INIT_LIST_HEAD(&mps->queue);
-
- mps->workqueue =
- create_singlethread_workqueue(dev_name(master->dev.parent));
- if (mps->workqueue == NULL) {
- ret = -EBUSY;
- goto free_irq;
- }
-
- ret = spi_register_master(master);
- if (ret < 0)
- goto unreg_master;
-
- return ret;
-
-unreg_master:
- destroy_workqueue(mps->workqueue);
-free_irq:
- free_irq(mps->irq, mps);
-free_master:
- if (mps->psc)
- iounmap(mps->psc);
- spi_master_put(master);
-
- return ret;
-}
-
-static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
-{
- struct spi_master *master = dev_get_drvdata(dev);
- struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
-
- flush_workqueue(mps->workqueue);
- destroy_workqueue(mps->workqueue);
- spi_unregister_master(master);
- free_irq(mps->irq, mps);
- if (mps->psc)
- iounmap(mps->psc);
-
- return 0;
-}
-
-static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
-{
- const u32 *regaddr_p;
- u64 regaddr64, size64;
- s16 id = -1;
-
- regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
- if (!regaddr_p) {
- dev_err(&op->dev, "Invalid PSC address\n");
- return -EINVAL;
- }
- regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
-
- /* get PSC id (0..11, used by port_config) */
- if (op->dev.platform_data == NULL) {
- const u32 *psc_nump;
-
- psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
- if (!psc_nump || *psc_nump > 11) {
- dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
- "has invalid cell-index property\n",
- op->dev.of_node->full_name);
- return -EINVAL;
- }
- id = *psc_nump;
- }
-
- return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
- irq_of_parse_and_map(op->dev.of_node, 0), id);
-}
-
-static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op)
-{
- return mpc512x_psc_spi_do_remove(&op->dev);
-}
-
-static struct of_device_id mpc512x_psc_spi_of_match[] = {
- { .compatible = "fsl,mpc5121-psc-spi", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
-
-static struct platform_driver mpc512x_psc_spi_of_driver = {
- .probe = mpc512x_psc_spi_of_probe,
- .remove = __devexit_p(mpc512x_psc_spi_of_remove),
- .driver = {
- .name = "mpc512x-psc-spi",
- .owner = THIS_MODULE,
- .of_match_table = mpc512x_psc_spi_of_match,
- },
-};
-module_platform_driver(mpc512x_psc_spi_of_driver);
-
-MODULE_AUTHOR("John Rigby");
-MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-mpc52xx-psc.c b/ANDROID_3.4.5/drivers/spi/spi-mpc52xx-psc.c
deleted file mode 100644
index 66047156..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-mpc52xx-psc.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * MPC52xx PSC in SPI mode driver.
- *
- * Maintainer: Dragos Carp
- *
- * Copyright (C) 2006 TOPTICA Photonics AG.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/fsl_devices.h>
-#include <linux/slab.h>
-
-#include <asm/mpc52xx.h>
-#include <asm/mpc52xx_psc.h>
-
-#define MCLK 20000000 /* PSC port MClk in hz */
-
-struct mpc52xx_psc_spi {
- /* fsl_spi_platform data */
- void (*cs_control)(struct spi_device *spi, bool on);
- u32 sysclk;
-
- /* driver internal data */
- struct mpc52xx_psc __iomem *psc;
- struct mpc52xx_psc_fifo __iomem *fifo;
- unsigned int irq;
- u8 bits_per_word;
- u8 busy;
-
- struct workqueue_struct *workqueue;
- struct work_struct work;
-
- struct list_head queue;
- spinlock_t lock;
-
- struct completion done;
-};
-
-/* controller state */
-struct mpc52xx_psc_spi_cs {
- int bits_per_word;
- int speed_hz;
-};
-
-/* set clock freq, clock ramp, bits per work
- * if t is NULL then reset the values to the default values
- */
-static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
-
- cs->speed_hz = (t && t->speed_hz)
- ? t->speed_hz : spi->max_speed_hz;
- cs->bits_per_word = (t && t->bits_per_word)
- ? t->bits_per_word : spi->bits_per_word;
- cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
- return 0;
-}
-
-static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
-{
- struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
- struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
- u32 sicr;
- u16 ccr;
-
- sicr = in_be32(&psc->sicr);
-
- /* Set clock phase and polarity */
- if (spi->mode & SPI_CPHA)
- sicr |= 0x00001000;
- else
- sicr &= ~0x00001000;
- if (spi->mode & SPI_CPOL)
- sicr |= 0x00002000;
- else
- sicr &= ~0x00002000;
-
- if (spi->mode & SPI_LSB_FIRST)
- sicr |= 0x10000000;
- else
- sicr &= ~0x10000000;
- out_be32(&psc->sicr, sicr);
-
- /* Set clock frequency and bits per word
- * Because psc->ccr is defined as 16bit register instead of 32bit
- * just set the lower byte of BitClkDiv
- */
- ccr = in_be16((u16 __iomem *)&psc->ccr);
- ccr &= 0xFF00;
- if (cs->speed_hz)
- ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
- else /* by default SPI Clk 1MHz */
- ccr |= (MCLK / 1000000 - 1) & 0xFF;
- out_be16((u16 __iomem *)&psc->ccr, ccr);
- mps->bits_per_word = cs->bits_per_word;
-
- if (mps->cs_control)
- mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
-}
-
-static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
-{
- struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
-
- if (mps->cs_control)
- mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-}
-
-#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
-/* wake up when 80% fifo full */
-#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
-
-static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
- struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
- unsigned rb = 0; /* number of bytes receieved */
- unsigned sb = 0; /* number of bytes sent */
- unsigned char *rx_buf = (unsigned char *)t->rx_buf;
- unsigned char *tx_buf = (unsigned char *)t->tx_buf;
- unsigned rfalarm;
- unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
- unsigned recv_at_once;
- int last_block = 0;
-
- if (!t->tx_buf && !t->rx_buf && t->len)
- return -EINVAL;
-
- /* enable transmiter/receiver */
- out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
- while (rb < t->len) {
- if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
- rfalarm = MPC52xx_PSC_RFALARM;
- last_block = 0;
- } else {
- send_at_once = t->len - sb;
- rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
- last_block = 1;
- }
-
- dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
- for (; send_at_once; sb++, send_at_once--) {
- /* set EOF flag before the last word is sent */
- if (send_at_once == 1 && last_block)
- out_8(&psc->ircr2, 0x01);
-
- if (tx_buf)
- out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
- else
- out_8(&psc->mpc52xx_psc_buffer_8, 0);
- }
-
-
- /* enable interrupts and wait for wake up
- * if just one byte is expected the Rx FIFO genererates no
- * FFULL interrupt, so activate the RxRDY interrupt
- */
- out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
- if (t->len - rb == 1) {
- out_8(&psc->mode, 0);
- } else {
- out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
- out_be16(&fifo->rfalarm, rfalarm);
- }
- out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
- wait_for_completion(&mps->done);
- recv_at_once = in_be16(&fifo->rfnum);
- dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
-
- send_at_once = recv_at_once;
- if (rx_buf) {
- for (; recv_at_once; rb++, recv_at_once--)
- rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8);
- } else {
- for (; recv_at_once; rb++, recv_at_once--)
- in_8(&psc->mpc52xx_psc_buffer_8);
- }
- }
- /* disable transmiter/receiver */
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-
- return 0;
-}
-
-static void mpc52xx_psc_spi_work(struct work_struct *work)
-{
- struct mpc52xx_psc_spi *mps =
- container_of(work, struct mpc52xx_psc_spi, work);
-
- spin_lock_irq(&mps->lock);
- mps->busy = 1;
- while (!list_empty(&mps->queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
- unsigned cs_change;
- int status;
-
- m = container_of(mps->queue.next, struct spi_message, queue);
- list_del_init(&m->queue);
- spin_unlock_irq(&mps->lock);
-
- spi = m->spi;
- cs_change = 1;
- status = 0;
- list_for_each_entry (t, &m->transfers, transfer_list) {
- if (t->bits_per_word || t->speed_hz) {
- status = mpc52xx_psc_spi_transfer_setup(spi, t);
- if (status < 0)
- break;
- }
-
- if (cs_change)
- mpc52xx_psc_spi_activate_cs(spi);
- cs_change = t->cs_change;
-
- status = mpc52xx_psc_spi_transfer_rxtx(spi, t);
- if (status)
- break;
- m->actual_length += t->len;
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (cs_change)
- mpc52xx_psc_spi_deactivate_cs(spi);
- }
-
- m->status = status;
- m->complete(m->context);
-
- if (status || !cs_change)
- mpc52xx_psc_spi_deactivate_cs(spi);
-
- mpc52xx_psc_spi_transfer_setup(spi, NULL);
-
- spin_lock_irq(&mps->lock);
- }
- mps->busy = 0;
- spin_unlock_irq(&mps->lock);
-}
-
-static int mpc52xx_psc_spi_setup(struct spi_device *spi)
-{
- struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
- unsigned long flags;
-
- if (spi->bits_per_word%8)
- return -EINVAL;
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- spi->controller_state = cs;
- }
-
- cs->bits_per_word = spi->bits_per_word;
- cs->speed_hz = spi->max_speed_hz;
-
- spin_lock_irqsave(&mps->lock, flags);
- if (!mps->busy)
- mpc52xx_psc_spi_deactivate_cs(spi);
- spin_unlock_irqrestore(&mps->lock, flags);
-
- return 0;
-}
-
-static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
- struct spi_message *m)
-{
- struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- spin_lock_irqsave(&mps->lock, flags);
- list_add_tail(&m->queue, &mps->queue);
- queue_work(mps->workqueue, &mps->work);
- spin_unlock_irqrestore(&mps->lock, flags);
-
- return 0;
-}
-
-static void mpc52xx_psc_spi_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-
-static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
-{
- struct mpc52xx_psc __iomem *psc = mps->psc;
- struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
- u32 mclken_div;
- int ret;
-
- /* default sysclk is 512MHz */
- mclken_div = (mps->sysclk ? mps->sysclk : 512000000) / MCLK;
- ret = mpc52xx_set_psc_clkdiv(psc_id, mclken_div);
- if (ret)
- return ret;
-
- /* Reset the PSC into a known state */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-
- /* Disable interrupts, interrupts are based on alarm level */
- out_be16(&psc->mpc52xx_psc_imr, 0);
- out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
- out_8(&fifo->rfcntl, 0);
- out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
-
- /* Configure 8bit codec mode as a SPI master and use EOF flags */
- /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
- out_be32(&psc->sicr, 0x0180C800);
- out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
-
- /* Set 2ms DTL delay */
- out_8(&psc->ctur, 0x00);
- out_8(&psc->ctlr, 0x84);
-
- mps->bits_per_word = 8;
-
- return 0;
-}
-
-static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
-{
- struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id;
- struct mpc52xx_psc __iomem *psc = mps->psc;
-
- /* disable interrupt and wake up the work queue */
- if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
- out_be16(&psc->mpc52xx_psc_imr, 0);
- complete(&mps->done);
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
-}
-
-/* bus_num is used only for the case dev->platform_data == NULL */
-static int __devinit mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
- u32 size, unsigned int irq, s16 bus_num)
-{
- struct fsl_spi_platform_data *pdata = dev->platform_data;
- struct mpc52xx_psc_spi *mps;
- struct spi_master *master;
- int ret;
-
- master = spi_alloc_master(dev, sizeof *mps);
- if (master == NULL)
- return -ENOMEM;
-
- dev_set_drvdata(dev, master);
- mps = spi_master_get_devdata(master);
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
-
- mps->irq = irq;
- if (pdata == NULL) {
- dev_warn(dev, "probe called without platform data, no "
- "cs_control function will be called\n");
- mps->cs_control = NULL;
- mps->sysclk = 0;
- master->bus_num = bus_num;
- master->num_chipselect = 255;
- } else {
- mps->cs_control = pdata->cs_control;
- mps->sysclk = pdata->sysclk;
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->max_chipselect;
- }
- master->setup = mpc52xx_psc_spi_setup;
- master->transfer = mpc52xx_psc_spi_transfer;
- master->cleanup = mpc52xx_psc_spi_cleanup;
- master->dev.of_node = dev->of_node;
-
- mps->psc = ioremap(regaddr, size);
- if (!mps->psc) {
- dev_err(dev, "could not ioremap I/O port range\n");
- ret = -EFAULT;
- goto free_master;
- }
- /* On the 5200, fifo regs are immediately ajacent to the psc regs */
- mps->fifo = ((void __iomem *)mps->psc) + sizeof(struct mpc52xx_psc);
-
- ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
- mps);
- if (ret)
- goto free_master;
-
- ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
- if (ret < 0) {
- dev_err(dev, "can't configure PSC! Is it capable of SPI?\n");
- goto free_irq;
- }
-
- spin_lock_init(&mps->lock);
- init_completion(&mps->done);
- INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
- INIT_LIST_HEAD(&mps->queue);
-
- mps->workqueue = create_singlethread_workqueue(
- dev_name(master->dev.parent));
- if (mps->workqueue == NULL) {
- ret = -EBUSY;
- goto free_irq;
- }
-
- ret = spi_register_master(master);
- if (ret < 0)
- goto unreg_master;
-
- return ret;
-
-unreg_master:
- destroy_workqueue(mps->workqueue);
-free_irq:
- free_irq(mps->irq, mps);
-free_master:
- if (mps->psc)
- iounmap(mps->psc);
- spi_master_put(master);
-
- return ret;
-}
-
-static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
-{
- const u32 *regaddr_p;
- u64 regaddr64, size64;
- s16 id = -1;
-
- regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
- if (!regaddr_p) {
- dev_err(&op->dev, "Invalid PSC address\n");
- return -EINVAL;
- }
- regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
-
- /* get PSC id (1..6, used by port_config) */
- if (op->dev.platform_data == NULL) {
- const u32 *psc_nump;
-
- psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
- if (!psc_nump || *psc_nump > 5) {
- dev_err(&op->dev, "Invalid cell-index property\n");
- return -EINVAL;
- }
- id = *psc_nump + 1;
- }
-
- return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
- irq_of_parse_and_map(op->dev.of_node, 0), id);
-}
-
-static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
-{
- struct spi_master *master = dev_get_drvdata(&op->dev);
- struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
-
- flush_workqueue(mps->workqueue);
- destroy_workqueue(mps->workqueue);
- spi_unregister_master(master);
- free_irq(mps->irq, mps);
- if (mps->psc)
- iounmap(mps->psc);
-
- return 0;
-}
-
-static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
- { .compatible = "fsl,mpc5200-psc-spi", },
- { .compatible = "mpc5200-psc-spi", }, /* old */
- {}
-};
-
-MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
-
-static struct platform_driver mpc52xx_psc_spi_of_driver = {
- .probe = mpc52xx_psc_spi_of_probe,
- .remove = __devexit_p(mpc52xx_psc_spi_of_remove),
- .driver = {
- .name = "mpc52xx-psc-spi",
- .owner = THIS_MODULE,
- .of_match_table = mpc52xx_psc_spi_of_match,
- },
-};
-module_platform_driver(mpc52xx_psc_spi_of_driver);
-
-MODULE_AUTHOR("Dragos Carp");
-MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-mpc52xx.c b/ANDROID_3.4.5/drivers/spi/spi-mpc52xx.c
deleted file mode 100644
index 57633d96..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-mpc52xx.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * MPC52xx SPI bus driver.
- *
- * Copyright (C) 2008 Secret Lab Technologies Ltd.
- *
- * This file is released under the GPLv2
- *
- * This is the driver for the MPC5200's dedicated SPI controller.
- *
- * Note: this driver does not support the MPC5200 PSC in SPI mode. For
- * that driver see drivers/spi/mpc52xx_psc_spi.c
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/of_platform.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/io.h>
-#include <linux/of_gpio.h>
-#include <linux/slab.h>
-#include <asm/time.h>
-#include <asm/mpc52xx.h>
-
-MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
-MODULE_DESCRIPTION("MPC52xx SPI (non-PSC) Driver");
-MODULE_LICENSE("GPL");
-
-/* Register offsets */
-#define SPI_CTRL1 0x00
-#define SPI_CTRL1_SPIE (1 << 7)
-#define SPI_CTRL1_SPE (1 << 6)
-#define SPI_CTRL1_MSTR (1 << 4)
-#define SPI_CTRL1_CPOL (1 << 3)
-#define SPI_CTRL1_CPHA (1 << 2)
-#define SPI_CTRL1_SSOE (1 << 1)
-#define SPI_CTRL1_LSBFE (1 << 0)
-
-#define SPI_CTRL2 0x01
-#define SPI_BRR 0x04
-
-#define SPI_STATUS 0x05
-#define SPI_STATUS_SPIF (1 << 7)
-#define SPI_STATUS_WCOL (1 << 6)
-#define SPI_STATUS_MODF (1 << 4)
-
-#define SPI_DATA 0x09
-#define SPI_PORTDATA 0x0d
-#define SPI_DATADIR 0x10
-
-/* FSM state return values */
-#define FSM_STOP 0 /* Nothing more for the state machine to */
- /* do. If something interesting happens */
- /* then an IRQ will be received */
-#define FSM_POLL 1 /* need to poll for completion, an IRQ is */
- /* not expected */
-#define FSM_CONTINUE 2 /* Keep iterating the state machine */
-
-/* Driver internal data */
-struct mpc52xx_spi {
- struct spi_master *master;
- void __iomem *regs;
- int irq0; /* MODF irq */
- int irq1; /* SPIF irq */
- unsigned int ipb_freq;
-
- /* Statistics; not used now, but will be reintroduced for debugfs */
- int msg_count;
- int wcol_count;
- int wcol_ticks;
- u32 wcol_tx_timestamp;
- int modf_count;
- int byte_count;
-
- struct list_head queue; /* queue of pending messages */
- spinlock_t lock;
- struct work_struct work;
-
- /* Details of current transfer (length, and buffer pointers) */
- struct spi_message *message; /* current message */
- struct spi_transfer *transfer; /* current transfer */
- int (*state)(int irq, struct mpc52xx_spi *ms, u8 status, u8 data);
- int len;
- int timestamp;
- u8 *rx_buf;
- const u8 *tx_buf;
- int cs_change;
- int gpio_cs_count;
- unsigned int *gpio_cs;
-};
-
-/*
- * CS control function
- */
-static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
-{
- int cs;
-
- if (ms->gpio_cs_count > 0) {
- cs = ms->message->spi->chip_select;
- gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1);
- } else
- out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
-}
-
-/*
- * Start a new transfer. This is called both by the idle state
- * for the first transfer in a message, and by the wait state when the
- * previous transfer in a message is complete.
- */
-static void mpc52xx_spi_start_transfer(struct mpc52xx_spi *ms)
-{
- ms->rx_buf = ms->transfer->rx_buf;
- ms->tx_buf = ms->transfer->tx_buf;
- ms->len = ms->transfer->len;
-
- /* Activate the chip select */
- if (ms->cs_change)
- mpc52xx_spi_chipsel(ms, 1);
- ms->cs_change = ms->transfer->cs_change;
-
- /* Write out the first byte */
- ms->wcol_tx_timestamp = get_tbl();
- if (ms->tx_buf)
- out_8(ms->regs + SPI_DATA, *ms->tx_buf++);
- else
- out_8(ms->regs + SPI_DATA, 0);
-}
-
-/* Forward declaration of state handlers */
-static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
- u8 status, u8 data);
-static int mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms,
- u8 status, u8 data);
-
-/*
- * IDLE state
- *
- * No transfers are in progress; if another transfer is pending then retrieve
- * it and kick it off. Otherwise, stop processing the state machine
- */
-static int
-mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
-{
- struct spi_device *spi;
- int spr, sppr;
- u8 ctrl1;
-
- if (status && (irq != NO_IRQ))
- dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
- status);
-
- /* Check if there is another transfer waiting. */
- if (list_empty(&ms->queue))
- return FSM_STOP;
-
- /* get the head of the queue */
- ms->message = list_first_entry(&ms->queue, struct spi_message, queue);
- list_del_init(&ms->message->queue);
-
- /* Setup the controller parameters */
- ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
- spi = ms->message->spi;
- if (spi->mode & SPI_CPHA)
- ctrl1 |= SPI_CTRL1_CPHA;
- if (spi->mode & SPI_CPOL)
- ctrl1 |= SPI_CTRL1_CPOL;
- if (spi->mode & SPI_LSB_FIRST)
- ctrl1 |= SPI_CTRL1_LSBFE;
- out_8(ms->regs + SPI_CTRL1, ctrl1);
-
- /* Setup the controller speed */
- /* minimum divider is '2'. Also, add '1' to force rounding the
- * divider up. */
- sppr = ((ms->ipb_freq / ms->message->spi->max_speed_hz) + 1) >> 1;
- spr = 0;
- if (sppr < 1)
- sppr = 1;
- while (((sppr - 1) & ~0x7) != 0) {
- sppr = (sppr + 1) >> 1; /* add '1' to force rounding up */
- spr++;
- }
- sppr--; /* sppr quantity in register is offset by 1 */
- if (spr > 7) {
- /* Don't overrun limits of SPI baudrate register */
- spr = 7;
- sppr = 7;
- }
- out_8(ms->regs + SPI_BRR, sppr << 4 | spr); /* Set speed */
-
- ms->cs_change = 1;
- ms->transfer = container_of(ms->message->transfers.next,
- struct spi_transfer, transfer_list);
-
- mpc52xx_spi_start_transfer(ms);
- ms->state = mpc52xx_spi_fsmstate_transfer;
-
- return FSM_CONTINUE;
-}
-
-/*
- * TRANSFER state
- *
- * In the middle of a transfer. If the SPI core has completed processing
- * a byte, then read out the received data and write out the next byte
- * (unless this transfer is finished; in which case go on to the wait
- * state)
- */
-static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
- u8 status, u8 data)
-{
- if (!status)
- return ms->irq0 ? FSM_STOP : FSM_POLL;
-
- if (status & SPI_STATUS_WCOL) {
- /* The SPI controller is stoopid. At slower speeds, it may
- * raise the SPIF flag before the state machine is actually
- * finished, which causes a collision (internal to the state
- * machine only). The manual recommends inserting a delay
- * between receiving the interrupt and sending the next byte,
- * but it can also be worked around simply by retrying the
- * transfer which is what we do here. */
- ms->wcol_count++;
- ms->wcol_ticks += get_tbl() - ms->wcol_tx_timestamp;
- ms->wcol_tx_timestamp = get_tbl();
- data = 0;
- if (ms->tx_buf)
- data = *(ms->tx_buf - 1);
- out_8(ms->regs + SPI_DATA, data); /* try again */
- return FSM_CONTINUE;
- } else if (status & SPI_STATUS_MODF) {
- ms->modf_count++;
- dev_err(&ms->master->dev, "mode fault\n");
- mpc52xx_spi_chipsel(ms, 0);
- ms->message->status = -EIO;
- ms->message->complete(ms->message->context);
- ms->state = mpc52xx_spi_fsmstate_idle;
- return FSM_CONTINUE;
- }
-
- /* Read data out of the spi device */
- ms->byte_count++;
- if (ms->rx_buf)
- *ms->rx_buf++ = data;
-
- /* Is the transfer complete? */
- ms->len--;
- if (ms->len == 0) {
- ms->timestamp = get_tbl();
- ms->timestamp += ms->transfer->delay_usecs * tb_ticks_per_usec;
- ms->state = mpc52xx_spi_fsmstate_wait;
- return FSM_CONTINUE;
- }
-
- /* Write out the next byte */
- ms->wcol_tx_timestamp = get_tbl();
- if (ms->tx_buf)
- out_8(ms->regs + SPI_DATA, *ms->tx_buf++);
- else
- out_8(ms->regs + SPI_DATA, 0);
-
- return FSM_CONTINUE;
-}
-
-/*
- * WAIT state
- *
- * A transfer has completed; need to wait for the delay period to complete
- * before starting the next transfer
- */
-static int
-mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
-{
- if (status && irq)
- dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
- status);
-
- if (((int)get_tbl()) - ms->timestamp < 0)
- return FSM_POLL;
-
- ms->message->actual_length += ms->transfer->len;
-
- /* Check if there is another transfer in this message. If there
- * aren't then deactivate CS, notify sender, and drop back to idle
- * to start the next message. */
- if (ms->transfer->transfer_list.next == &ms->message->transfers) {
- ms->msg_count++;
- mpc52xx_spi_chipsel(ms, 0);
- ms->message->status = 0;
- ms->message->complete(ms->message->context);
- ms->state = mpc52xx_spi_fsmstate_idle;
- return FSM_CONTINUE;
- }
-
- /* There is another transfer; kick it off */
-
- if (ms->cs_change)
- mpc52xx_spi_chipsel(ms, 0);
-
- ms->transfer = container_of(ms->transfer->transfer_list.next,
- struct spi_transfer, transfer_list);
- mpc52xx_spi_start_transfer(ms);
- ms->state = mpc52xx_spi_fsmstate_transfer;
- return FSM_CONTINUE;
-}
-
-/**
- * mpc52xx_spi_fsm_process - Finite State Machine iteration function
- * @irq: irq number that triggered the FSM or 0 for polling
- * @ms: pointer to mpc52xx_spi driver data
- */
-static void mpc52xx_spi_fsm_process(int irq, struct mpc52xx_spi *ms)
-{
- int rc = FSM_CONTINUE;
- u8 status, data;
-
- while (rc == FSM_CONTINUE) {
- /* Interrupt cleared by read of STATUS followed by
- * read of DATA registers */
- status = in_8(ms->regs + SPI_STATUS);
- data = in_8(ms->regs + SPI_DATA);
- rc = ms->state(irq, ms, status, data);
- }
-
- if (rc == FSM_POLL)
- schedule_work(&ms->work);
-}
-
-/**
- * mpc52xx_spi_irq - IRQ handler
- */
-static irqreturn_t mpc52xx_spi_irq(int irq, void *_ms)
-{
- struct mpc52xx_spi *ms = _ms;
- spin_lock(&ms->lock);
- mpc52xx_spi_fsm_process(irq, ms);
- spin_unlock(&ms->lock);
- return IRQ_HANDLED;
-}
-
-/**
- * mpc52xx_spi_wq - Workqueue function for polling the state machine
- */
-static void mpc52xx_spi_wq(struct work_struct *work)
-{
- struct mpc52xx_spi *ms = container_of(work, struct mpc52xx_spi, work);
- unsigned long flags;
-
- spin_lock_irqsave(&ms->lock, flags);
- mpc52xx_spi_fsm_process(0, ms);
- spin_unlock_irqrestore(&ms->lock, flags);
-}
-
-/*
- * spi_master ops
- */
-
-static int mpc52xx_spi_setup(struct spi_device *spi)
-{
- if (spi->bits_per_word % 8)
- return -EINVAL;
-
- if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST))
- return -EINVAL;
-
- if (spi->chip_select >= spi->master->num_chipselect)
- return -EINVAL;
-
- return 0;
-}
-
-static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- spin_lock_irqsave(&ms->lock, flags);
- list_add_tail(&m->queue, &ms->queue);
- spin_unlock_irqrestore(&ms->lock, flags);
- schedule_work(&ms->work);
-
- return 0;
-}
-
-/*
- * OF Platform Bus Binding
- */
-static int __devinit mpc52xx_spi_probe(struct platform_device *op)
-{
- struct spi_master *master;
- struct mpc52xx_spi *ms;
- void __iomem *regs;
- u8 ctrl1;
- int rc, i = 0;
- int gpio_cs;
-
- /* MMIO registers */
- dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
- regs = of_iomap(op->dev.of_node, 0);
- if (!regs)
- return -ENODEV;
-
- /* initialize the device */
- ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
- out_8(regs + SPI_CTRL1, ctrl1);
- out_8(regs + SPI_CTRL2, 0x0);
- out_8(regs + SPI_DATADIR, 0xe); /* Set output pins */
- out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */
-
- /* Clear the status register and re-read it to check for a MODF
- * failure. This driver cannot currently handle multiple masters
- * on the SPI bus. This fault will also occur if the SPI signals
- * are not connected to any pins (port_config setting) */
- in_8(regs + SPI_STATUS);
- out_8(regs + SPI_CTRL1, ctrl1);
-
- in_8(regs + SPI_DATA);
- if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) {
- dev_err(&op->dev, "mode fault; is port_config correct?\n");
- rc = -EIO;
- goto err_init;
- }
-
- dev_dbg(&op->dev, "allocating spi_master struct\n");
- master = spi_alloc_master(&op->dev, sizeof *ms);
- if (!master) {
- rc = -ENOMEM;
- goto err_alloc;
- }
-
- master->bus_num = -1;
- master->setup = mpc52xx_spi_setup;
- master->transfer = mpc52xx_spi_transfer;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
- master->dev.of_node = op->dev.of_node;
-
- dev_set_drvdata(&op->dev, master);
-
- ms = spi_master_get_devdata(master);
- ms->master = master;
- ms->regs = regs;
- ms->irq0 = irq_of_parse_and_map(op->dev.of_node, 0);
- ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1);
- ms->state = mpc52xx_spi_fsmstate_idle;
- ms->ipb_freq = mpc5xxx_get_bus_frequency(op->dev.of_node);
- ms->gpio_cs_count = of_gpio_count(op->dev.of_node);
- if (ms->gpio_cs_count > 0) {
- master->num_chipselect = ms->gpio_cs_count;
- ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int),
- GFP_KERNEL);
- if (!ms->gpio_cs) {
- rc = -ENOMEM;
- goto err_alloc;
- }
-
- for (i = 0; i < ms->gpio_cs_count; i++) {
- gpio_cs = of_get_gpio(op->dev.of_node, i);
- if (gpio_cs < 0) {
- dev_err(&op->dev,
- "could not parse the gpio field "
- "in oftree\n");
- rc = -ENODEV;
- goto err_gpio;
- }
-
- rc = gpio_request(gpio_cs, dev_name(&op->dev));
- if (rc) {
- dev_err(&op->dev,
- "can't request spi cs gpio #%d "
- "on gpio line %d\n", i, gpio_cs);
- goto err_gpio;
- }
-
- gpio_direction_output(gpio_cs, 1);
- ms->gpio_cs[i] = gpio_cs;
- }
- } else {
- master->num_chipselect = 1;
- }
-
- spin_lock_init(&ms->lock);
- INIT_LIST_HEAD(&ms->queue);
- INIT_WORK(&ms->work, mpc52xx_spi_wq);
-
- /* Decide if interrupts can be used */
- if (ms->irq0 && ms->irq1) {
- rc = request_irq(ms->irq0, mpc52xx_spi_irq, 0,
- "mpc5200-spi-modf", ms);
- rc |= request_irq(ms->irq1, mpc52xx_spi_irq, 0,
- "mpc5200-spi-spif", ms);
- if (rc) {
- free_irq(ms->irq0, ms);
- free_irq(ms->irq1, ms);
- ms->irq0 = ms->irq1 = 0;
- }
- } else {
- /* operate in polled mode */
- ms->irq0 = ms->irq1 = 0;
- }
-
- if (!ms->irq0)
- dev_info(&op->dev, "using polled mode\n");
-
- dev_dbg(&op->dev, "registering spi_master struct\n");
- rc = spi_register_master(master);
- if (rc)
- goto err_register;
-
- dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n");
-
- return rc;
-
- err_register:
- dev_err(&ms->master->dev, "initialization failed\n");
- spi_master_put(master);
- err_gpio:
- while (i-- > 0)
- gpio_free(ms->gpio_cs[i]);
-
- kfree(ms->gpio_cs);
- err_alloc:
- err_init:
- iounmap(regs);
- return rc;
-}
-
-static int __devexit mpc52xx_spi_remove(struct platform_device *op)
-{
- struct spi_master *master = dev_get_drvdata(&op->dev);
- struct mpc52xx_spi *ms = spi_master_get_devdata(master);
- int i;
-
- free_irq(ms->irq0, ms);
- free_irq(ms->irq1, ms);
-
- for (i = 0; i < ms->gpio_cs_count; i++)
- gpio_free(ms->gpio_cs[i]);
-
- kfree(ms->gpio_cs);
- spi_unregister_master(master);
- spi_master_put(master);
- iounmap(ms->regs);
-
- return 0;
-}
-
-static const struct of_device_id mpc52xx_spi_match[] __devinitconst = {
- { .compatible = "fsl,mpc5200-spi", },
- {}
-};
-MODULE_DEVICE_TABLE(of, mpc52xx_spi_match);
-
-static struct platform_driver mpc52xx_spi_of_driver = {
- .driver = {
- .name = "mpc52xx-spi",
- .owner = THIS_MODULE,
- .of_match_table = mpc52xx_spi_match,
- },
- .probe = mpc52xx_spi_probe,
- .remove = __devexit_p(mpc52xx_spi_remove),
-};
-module_platform_driver(mpc52xx_spi_of_driver);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-nuc900.c b/ANDROID_3.4.5/drivers/spi/spi-nuc900.c
deleted file mode 100644
index dae8be22..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-nuc900.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 2009 Nuvoton technology.
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * 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/module.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <mach/nuc900_spi.h>
-
-/* usi registers offset */
-#define USI_CNT 0x00
-#define USI_DIV 0x04
-#define USI_SSR 0x08
-#define USI_RX0 0x10
-#define USI_TX0 0x10
-
-/* usi register bit */
-#define ENINT (0x01 << 17)
-#define ENFLG (0x01 << 16)
-#define TXNUM (0x03 << 8)
-#define TXNEG (0x01 << 2)
-#define RXNEG (0x01 << 1)
-#define LSB (0x01 << 10)
-#define SELECTLEV (0x01 << 2)
-#define SELECTPOL (0x01 << 31)
-#define SELECTSLAVE 0x01
-#define GOBUSY 0x01
-
-struct nuc900_spi {
- struct spi_bitbang bitbang;
- struct completion done;
- void __iomem *regs;
- int irq;
- int len;
- int count;
- const unsigned char *tx;
- unsigned char *rx;
- struct clk *clk;
- struct resource *ioarea;
- struct spi_master *master;
- struct spi_device *curdev;
- struct device *dev;
- struct nuc900_spi_info *pdata;
- spinlock_t lock;
- struct resource *res;
-};
-
-static inline struct nuc900_spi *to_hw(struct spi_device *sdev)
-{
- return spi_master_get_devdata(sdev->master);
-}
-
-static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr)
-{
- struct nuc900_spi *hw = to_hw(spi);
- unsigned int val;
- unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
- unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_SSR);
-
- if (!cs)
- val &= ~SELECTLEV;
- else
- val |= SELECTLEV;
-
- if (!ssr)
- val &= ~SELECTSLAVE;
- else
- val |= SELECTSLAVE;
-
- __raw_writel(val, hw->regs + USI_SSR);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (!cpol)
- val &= ~SELECTPOL;
- else
- val |= SELECTPOL;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_spi_chipsel(struct spi_device *spi, int value)
-{
- switch (value) {
- case BITBANG_CS_INACTIVE:
- nuc900_slave_select(spi, 0);
- break;
-
- case BITBANG_CS_ACTIVE:
- nuc900_slave_select(spi, 1);
- break;
- }
-}
-
-static void nuc900_spi_setup_txnum(struct nuc900_spi *hw,
- unsigned int txnum)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (!txnum)
- val &= ~TXNUM;
- else
- val |= txnum << 0x08;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-
-}
-
-static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw,
- unsigned int txbitlen)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- val |= (txbitlen << 0x03);
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_spi_gobusy(struct nuc900_spi *hw)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- val |= GOBUSY;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static int nuc900_spi_setupxfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- return 0;
-}
-
-static int nuc900_spi_setup(struct spi_device *spi)
-{
- return 0;
-}
-
-static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
-{
- return hw->tx ? hw->tx[count] : 0;
-}
-
-static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct nuc900_spi *hw = to_hw(spi);
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->len = t->len;
- hw->count = 0;
-
- __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0);
-
- nuc900_spi_gobusy(hw);
-
- wait_for_completion(&hw->done);
-
- return hw->count;
-}
-
-static irqreturn_t nuc900_spi_irq(int irq, void *dev)
-{
- struct nuc900_spi *hw = dev;
- unsigned int status;
- unsigned int count = hw->count;
-
- status = __raw_readl(hw->regs + USI_CNT);
- __raw_writel(status, hw->regs + USI_CNT);
-
- if (status & ENFLG) {
- hw->count++;
-
- if (hw->rx)
- hw->rx[count] = __raw_readl(hw->regs + USI_RX0);
- count++;
-
- if (count < hw->len) {
- __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0);
- nuc900_spi_gobusy(hw);
- } else {
- complete(&hw->done);
- }
-
- return IRQ_HANDLED;
- }
-
- complete(&hw->done);
- return IRQ_HANDLED;
-}
-
-static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (edge)
- val |= TXNEG;
- else
- val &= ~TXNEG;
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (edge)
- val |= RXNEG;
- else
- val &= ~RXNEG;
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (lsb)
- val |= LSB;
- else
- val &= ~LSB;
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- if (sleep)
- val |= (sleep << 12);
- else
- val &= ~(0x0f << 12);
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_enable_int(struct nuc900_spi *hw)
-{
- unsigned int val;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->lock, flags);
-
- val = __raw_readl(hw->regs + USI_CNT);
-
- val |= ENINT;
-
- __raw_writel(val, hw->regs + USI_CNT);
-
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_set_divider(struct nuc900_spi *hw)
-{
- __raw_writel(hw->pdata->divider, hw->regs + USI_DIV);
-}
-
-static void nuc900_init_spi(struct nuc900_spi *hw)
-{
- clk_enable(hw->clk);
- spin_lock_init(&hw->lock);
-
- nuc900_tx_edge(hw, hw->pdata->txneg);
- nuc900_rx_edge(hw, hw->pdata->rxneg);
- nuc900_send_first(hw, hw->pdata->lsb);
- nuc900_set_sleep(hw, hw->pdata->sleep);
- nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen);
- nuc900_spi_setup_txnum(hw, hw->pdata->txnum);
- nuc900_set_divider(hw);
- nuc900_enable_int(hw);
-}
-
-static int __devinit nuc900_spi_probe(struct platform_device *pdev)
-{
- struct nuc900_spi *hw;
- struct spi_master *master;
- int err = 0;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
- if (master == NULL) {
- dev_err(&pdev->dev, "No memory for spi_master\n");
- err = -ENOMEM;
- goto err_nomem;
- }
-
- hw = spi_master_get_devdata(master);
- hw->master = spi_master_get(master);
- hw->pdata = pdev->dev.platform_data;
- hw->dev = &pdev->dev;
-
- if (hw->pdata == NULL) {
- dev_err(&pdev->dev, "No platform data supplied\n");
- err = -ENOENT;
- goto err_pdata;
- }
-
- platform_set_drvdata(pdev, hw);
- init_completion(&hw->done);
-
- master->mode_bits = SPI_MODE_0;
- master->num_chipselect = hw->pdata->num_cs;
- master->bus_num = hw->pdata->bus_num;
- hw->bitbang.master = hw->master;
- hw->bitbang.setup_transfer = nuc900_spi_setupxfer;
- hw->bitbang.chipselect = nuc900_spi_chipsel;
- hw->bitbang.txrx_bufs = nuc900_spi_txrx;
- hw->bitbang.master->setup = nuc900_spi_setup;
-
- hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (hw->res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- err = -ENOENT;
- goto err_pdata;
- }
-
- hw->ioarea = request_mem_region(hw->res->start,
- resource_size(hw->res), pdev->name);
-
- if (hw->ioarea == NULL) {
- dev_err(&pdev->dev, "Cannot reserve region\n");
- err = -ENXIO;
- goto err_pdata;
- }
-
- hw->regs = ioremap(hw->res->start, resource_size(hw->res));
- if (hw->regs == NULL) {
- dev_err(&pdev->dev, "Cannot map IO\n");
- err = -ENXIO;
- goto err_iomap;
- }
-
- hw->irq = platform_get_irq(pdev, 0);
- if (hw->irq < 0) {
- dev_err(&pdev->dev, "No IRQ specified\n");
- err = -ENOENT;
- goto err_irq;
- }
-
- err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw);
- if (err) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_irq;
- }
-
- hw->clk = clk_get(&pdev->dev, "spi");
- if (IS_ERR(hw->clk)) {
- dev_err(&pdev->dev, "No clock for device\n");
- err = PTR_ERR(hw->clk);
- goto err_clk;
- }
-
- mfp_set_groupg(&pdev->dev, NULL);
- nuc900_init_spi(hw);
-
- err = spi_bitbang_start(&hw->bitbang);
- if (err) {
- dev_err(&pdev->dev, "Failed to register SPI master\n");
- goto err_register;
- }
-
- return 0;
-
-err_register:
- clk_disable(hw->clk);
- clk_put(hw->clk);
-err_clk:
- free_irq(hw->irq, hw);
-err_irq:
- iounmap(hw->regs);
-err_iomap:
- release_mem_region(hw->res->start, resource_size(hw->res));
- kfree(hw->ioarea);
-err_pdata:
- spi_master_put(hw->master);
-
-err_nomem:
- return err;
-}
-
-static int __devexit nuc900_spi_remove(struct platform_device *dev)
-{
- struct nuc900_spi *hw = platform_get_drvdata(dev);
-
- free_irq(hw->irq, hw);
-
- platform_set_drvdata(dev, NULL);
-
- spi_bitbang_stop(&hw->bitbang);
-
- clk_disable(hw->clk);
- clk_put(hw->clk);
-
- iounmap(hw->regs);
-
- release_mem_region(hw->res->start, resource_size(hw->res));
- kfree(hw->ioarea);
-
- spi_master_put(hw->master);
- return 0;
-}
-
-static struct platform_driver nuc900_spi_driver = {
- .probe = nuc900_spi_probe,
- .remove = __devexit_p(nuc900_spi_remove),
- .driver = {
- .name = "nuc900-spi",
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(nuc900_spi_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("nuc900 spi driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-spi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-oc-tiny.c b/ANDROID_3.4.5/drivers/spi/spi-oc-tiny.c
deleted file mode 100644
index 698018fd..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-oc-tiny.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * OpenCores tiny SPI master driver
- *
- * http://opencores.org/project,tiny_spi
- *
- * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
- *
- * Based on spi_s3c24xx.c, which is:
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/spi_oc_tiny.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-
-#define DRV_NAME "spi_oc_tiny"
-
-#define TINY_SPI_RXDATA 0
-#define TINY_SPI_TXDATA 4
-#define TINY_SPI_STATUS 8
-#define TINY_SPI_CONTROL 12
-#define TINY_SPI_BAUD 16
-
-#define TINY_SPI_STATUS_TXE 0x1
-#define TINY_SPI_STATUS_TXR 0x2
-
-struct tiny_spi {
- /* bitbang has to be first */
- struct spi_bitbang bitbang;
- struct completion done;
-
- void __iomem *base;
- int irq;
- unsigned int freq;
- unsigned int baudwidth;
- unsigned int baud;
- unsigned int speed_hz;
- unsigned int mode;
- unsigned int len;
- unsigned int txc, rxc;
- const u8 *txp;
- u8 *rxp;
- unsigned int gpio_cs_count;
- int *gpio_cs;
-};
-
-static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev)
-{
- return spi_master_get_devdata(sdev->master);
-}
-
-static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz)
-{
- struct tiny_spi *hw = tiny_spi_to_hw(spi);
-
- return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1;
-}
-
-static void tiny_spi_chipselect(struct spi_device *spi, int is_active)
-{
- struct tiny_spi *hw = tiny_spi_to_hw(spi);
-
- if (hw->gpio_cs_count) {
- gpio_set_value(hw->gpio_cs[spi->chip_select],
- (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
- }
-}
-
-static int tiny_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct tiny_spi *hw = tiny_spi_to_hw(spi);
- unsigned int baud = hw->baud;
-
- if (t) {
- if (t->speed_hz && t->speed_hz != hw->speed_hz)
- baud = tiny_spi_baud(spi, t->speed_hz);
- }
- writel(baud, hw->base + TINY_SPI_BAUD);
- writel(hw->mode, hw->base + TINY_SPI_CONTROL);
- return 0;
-}
-
-static int tiny_spi_setup(struct spi_device *spi)
-{
- struct tiny_spi *hw = tiny_spi_to_hw(spi);
-
- if (spi->max_speed_hz != hw->speed_hz) {
- hw->speed_hz = spi->max_speed_hz;
- hw->baud = tiny_spi_baud(spi, hw->speed_hz);
- }
- hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA);
- return 0;
-}
-
-static inline void tiny_spi_wait_txr(struct tiny_spi *hw)
-{
- while (!(readb(hw->base + TINY_SPI_STATUS) &
- TINY_SPI_STATUS_TXR))
- cpu_relax();
-}
-
-static inline void tiny_spi_wait_txe(struct tiny_spi *hw)
-{
- while (!(readb(hw->base + TINY_SPI_STATUS) &
- TINY_SPI_STATUS_TXE))
- cpu_relax();
-}
-
-static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
- struct tiny_spi *hw = tiny_spi_to_hw(spi);
- const u8 *txp = t->tx_buf;
- u8 *rxp = t->rx_buf;
- unsigned int i;
-
- if (hw->irq >= 0) {
- /* use intrrupt driven data transfer */
- hw->len = t->len;
- hw->txp = t->tx_buf;
- hw->rxp = t->rx_buf;
- hw->txc = 0;
- hw->rxc = 0;
-
- /* send the first byte */
- if (t->len > 1) {
- writeb(hw->txp ? *hw->txp++ : 0,
- hw->base + TINY_SPI_TXDATA);
- hw->txc++;
- writeb(hw->txp ? *hw->txp++ : 0,
- hw->base + TINY_SPI_TXDATA);
- hw->txc++;
- writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
- } else {
- writeb(hw->txp ? *hw->txp++ : 0,
- hw->base + TINY_SPI_TXDATA);
- hw->txc++;
- writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
- }
-
- wait_for_completion(&hw->done);
- } else if (txp && rxp) {
- /* we need to tighten the transfer loop */
- writeb(*txp++, hw->base + TINY_SPI_TXDATA);
- if (t->len > 1) {
- writeb(*txp++, hw->base + TINY_SPI_TXDATA);
- for (i = 2; i < t->len; i++) {
- u8 rx, tx = *txp++;
- tiny_spi_wait_txr(hw);
- rx = readb(hw->base + TINY_SPI_TXDATA);
- writeb(tx, hw->base + TINY_SPI_TXDATA);
- *rxp++ = rx;
- }
- tiny_spi_wait_txr(hw);
- *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
- }
- tiny_spi_wait_txe(hw);
- *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
- } else if (rxp) {
- writeb(0, hw->base + TINY_SPI_TXDATA);
- if (t->len > 1) {
- writeb(0,
- hw->base + TINY_SPI_TXDATA);
- for (i = 2; i < t->len; i++) {
- u8 rx;
- tiny_spi_wait_txr(hw);
- rx = readb(hw->base + TINY_SPI_TXDATA);
- writeb(0, hw->base + TINY_SPI_TXDATA);
- *rxp++ = rx;
- }
- tiny_spi_wait_txr(hw);
- *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
- }
- tiny_spi_wait_txe(hw);
- *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
- } else if (txp) {
- writeb(*txp++, hw->base + TINY_SPI_TXDATA);
- if (t->len > 1) {
- writeb(*txp++, hw->base + TINY_SPI_TXDATA);
- for (i = 2; i < t->len; i++) {
- u8 tx = *txp++;
- tiny_spi_wait_txr(hw);
- writeb(tx, hw->base + TINY_SPI_TXDATA);
- }
- }
- tiny_spi_wait_txe(hw);
- } else {
- writeb(0, hw->base + TINY_SPI_TXDATA);
- if (t->len > 1) {
- writeb(0, hw->base + TINY_SPI_TXDATA);
- for (i = 2; i < t->len; i++) {
- tiny_spi_wait_txr(hw);
- writeb(0, hw->base + TINY_SPI_TXDATA);
- }
- }
- tiny_spi_wait_txe(hw);
- }
- return t->len;
-}
-
-static irqreturn_t tiny_spi_irq(int irq, void *dev)
-{
- struct tiny_spi *hw = dev;
-
- writeb(0, hw->base + TINY_SPI_STATUS);
- if (hw->rxc + 1 == hw->len) {
- if (hw->rxp)
- *hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA);
- hw->rxc++;
- complete(&hw->done);
- } else {
- if (hw->rxp)
- *hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA);
- hw->rxc++;
- if (hw->txc < hw->len) {
- writeb(hw->txp ? *hw->txp++ : 0,
- hw->base + TINY_SPI_TXDATA);
- hw->txc++;
- writeb(TINY_SPI_STATUS_TXR,
- hw->base + TINY_SPI_STATUS);
- } else {
- writeb(TINY_SPI_STATUS_TXE,
- hw->base + TINY_SPI_STATUS);
- }
- }
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_OF
-#include <linux/of_gpio.h>
-
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
-{
- struct tiny_spi *hw = platform_get_drvdata(pdev);
- struct device_node *np = pdev->dev.of_node;
- unsigned int i;
- const __be32 *val;
- int len;
-
- if (!np)
- return 0;
- hw->gpio_cs_count = of_gpio_count(np);
- if (hw->gpio_cs_count) {
- hw->gpio_cs = devm_kzalloc(&pdev->dev,
- hw->gpio_cs_count * sizeof(unsigned int),
- GFP_KERNEL);
- if (!hw->gpio_cs)
- return -ENOMEM;
- }
- for (i = 0; i < hw->gpio_cs_count; i++) {
- hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL);
- if (hw->gpio_cs[i] < 0)
- return -ENODEV;
- }
- hw->bitbang.master->dev.of_node = pdev->dev.of_node;
- val = of_get_property(pdev->dev.of_node,
- "clock-frequency", &len);
- if (val && len >= sizeof(__be32))
- hw->freq = be32_to_cpup(val);
- val = of_get_property(pdev->dev.of_node, "baud-width", &len);
- if (val && len >= sizeof(__be32))
- hw->baudwidth = be32_to_cpup(val);
- return 0;
-}
-#else /* !CONFIG_OF */
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
-{
- return 0;
-}
-#endif /* CONFIG_OF */
-
-static int __devinit tiny_spi_probe(struct platform_device *pdev)
-{
- struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
- struct tiny_spi *hw;
- struct spi_master *master;
- struct resource *res;
- unsigned int i;
- int err = -ENODEV;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
- if (!master)
- return err;
-
- /* setup the master state. */
- master->bus_num = pdev->id;
- master->num_chipselect = 255;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- master->setup = tiny_spi_setup;
-
- hw = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, hw);
-
- /* setup the state for the bitbang driver */
- hw->bitbang.master = spi_master_get(master);
- if (!hw->bitbang.master)
- return err;
- hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
- hw->bitbang.chipselect = tiny_spi_chipselect;
- hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
-
- /* find and map our resources */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- goto exit_busy;
- if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
- pdev->name))
- goto exit_busy;
- hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
- resource_size(res));
- if (!hw->base)
- goto exit_busy;
- /* irq is optional */
- hw->irq = platform_get_irq(pdev, 0);
- if (hw->irq >= 0) {
- init_completion(&hw->done);
- err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0,
- pdev->name, hw);
- if (err)
- goto exit;
- }
- /* find platform data */
- if (platp) {
- hw->gpio_cs_count = platp->gpio_cs_count;
- hw->gpio_cs = platp->gpio_cs;
- if (platp->gpio_cs_count && !platp->gpio_cs)
- goto exit_busy;
- hw->freq = platp->freq;
- hw->baudwidth = platp->baudwidth;
- } else {
- err = tiny_spi_of_probe(pdev);
- if (err)
- goto exit;
- }
- for (i = 0; i < hw->gpio_cs_count; i++) {
- err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev));
- if (err)
- goto exit_gpio;
- gpio_direction_output(hw->gpio_cs[i], 1);
- }
- hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count);
-
- /* register our spi controller */
- err = spi_bitbang_start(&hw->bitbang);
- if (err)
- goto exit;
- dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
-
- return 0;
-
-exit_gpio:
- while (i-- > 0)
- gpio_free(hw->gpio_cs[i]);
-exit_busy:
- err = -EBUSY;
-exit:
- platform_set_drvdata(pdev, NULL);
- spi_master_put(master);
- return err;
-}
-
-static int __devexit tiny_spi_remove(struct platform_device *pdev)
-{
- struct tiny_spi *hw = platform_get_drvdata(pdev);
- struct spi_master *master = hw->bitbang.master;
- unsigned int i;
-
- spi_bitbang_stop(&hw->bitbang);
- for (i = 0; i < hw->gpio_cs_count; i++)
- gpio_free(hw->gpio_cs[i]);
- platform_set_drvdata(pdev, NULL);
- spi_master_put(master);
- return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id tiny_spi_match[] = {
- { .compatible = "opencores,tiny-spi-rtlsvn2", },
- {},
-};
-MODULE_DEVICE_TABLE(of, tiny_spi_match);
-#else /* CONFIG_OF */
-#define tiny_spi_match NULL
-#endif /* CONFIG_OF */
-
-static struct platform_driver tiny_spi_driver = {
- .probe = tiny_spi_probe,
- .remove = __devexit_p(tiny_spi_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- .pm = NULL,
- .of_match_table = tiny_spi_match,
- },
-};
-module_platform_driver(tiny_spi_driver);
-
-MODULE_DESCRIPTION("OpenCores tiny SPI driver");
-MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-omap-100k.c b/ANDROID_3.4.5/drivers/spi/spi-omap-100k.c
deleted file mode 100644
index 9bd1c92a..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-omap-100k.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * OMAP7xx SPI 100k controller driver
- * Author: Fabrice Crohas <fcrohas@gmail.com>
- * from original omap1_mcspi driver
- *
- * Copyright (C) 2005, 2006 Nokia Corporation
- * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and
- * Juha Yrj�l� <juha.yrjola@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-
-#include <plat/clock.h>
-
-#define OMAP1_SPI100K_MAX_FREQ 48000000
-
-#define ICR_SPITAS (OMAP7XX_ICR_BASE + 0x12)
-
-#define SPI_SETUP1 0x00
-#define SPI_SETUP2 0x02
-#define SPI_CTRL 0x04
-#define SPI_STATUS 0x06
-#define SPI_TX_LSB 0x08
-#define SPI_TX_MSB 0x0a
-#define SPI_RX_LSB 0x0c
-#define SPI_RX_MSB 0x0e
-
-#define SPI_SETUP1_INT_READ_ENABLE (1UL << 5)
-#define SPI_SETUP1_INT_WRITE_ENABLE (1UL << 4)
-#define SPI_SETUP1_CLOCK_DIVISOR(x) ((x) << 1)
-#define SPI_SETUP1_CLOCK_ENABLE (1UL << 0)
-
-#define SPI_SETUP2_ACTIVE_EDGE_FALLING (0UL << 0)
-#define SPI_SETUP2_ACTIVE_EDGE_RISING (1UL << 0)
-#define SPI_SETUP2_NEGATIVE_LEVEL (0UL << 5)
-#define SPI_SETUP2_POSITIVE_LEVEL (1UL << 5)
-#define SPI_SETUP2_LEVEL_TRIGGER (0UL << 10)
-#define SPI_SETUP2_EDGE_TRIGGER (1UL << 10)
-
-#define SPI_CTRL_SEN(x) ((x) << 7)
-#define SPI_CTRL_WORD_SIZE(x) (((x) - 1) << 2)
-#define SPI_CTRL_WR (1UL << 1)
-#define SPI_CTRL_RD (1UL << 0)
-
-#define SPI_STATUS_WE (1UL << 1)
-#define SPI_STATUS_RD (1UL << 0)
-
-#define WRITE 0
-#define READ 1
-
-
-/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
- * cache operations; better heuristics consider wordsize and bitrate.
- */
-#define DMA_MIN_BYTES 8
-
-#define SPI_RUNNING 0
-#define SPI_SHUTDOWN 1
-
-struct omap1_spi100k {
- struct work_struct work;
-
- /* lock protects queue and registers */
- spinlock_t lock;
- struct list_head msg_queue;
- struct spi_master *master;
- struct clk *ick;
- struct clk *fck;
-
- /* Virtual base address of the controller */
- void __iomem *base;
-
- /* State of the SPI */
- unsigned int state;
-};
-
-struct omap1_spi100k_cs {
- void __iomem *base;
- int word_len;
-};
-
-static struct workqueue_struct *omap1_spi100k_wq;
-
-#define MOD_REG_BIT(val, mask, set) do { \
- if (set) \
- val |= mask; \
- else \
- val &= ~mask; \
-} while (0)
-
-static void spi100k_enable_clock(struct spi_master *master)
-{
- unsigned int val;
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
- /* enable SPI */
- val = readw(spi100k->base + SPI_SETUP1);
- val |= SPI_SETUP1_CLOCK_ENABLE;
- writew(val, spi100k->base + SPI_SETUP1);
-}
-
-static void spi100k_disable_clock(struct spi_master *master)
-{
- unsigned int val;
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
- /* disable SPI */
- val = readw(spi100k->base + SPI_SETUP1);
- val &= ~SPI_SETUP1_CLOCK_ENABLE;
- writew(val, spi100k->base + SPI_SETUP1);
-}
-
-static void spi100k_write_data(struct spi_master *master, int len, int data)
-{
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
- /* write 16-bit word, shifting 8-bit data if necessary */
- if (len <= 8) {
- data <<= 8;
- len = 16;
- }
-
- spi100k_enable_clock(master);
- writew( data , spi100k->base + SPI_TX_MSB);
-
- writew(SPI_CTRL_SEN(0) |
- SPI_CTRL_WORD_SIZE(len) |
- SPI_CTRL_WR,
- spi100k->base + SPI_CTRL);
-
- /* Wait for bit ack send change */
- while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE);
- udelay(1000);
-
- spi100k_disable_clock(master);
-}
-
-static int spi100k_read_data(struct spi_master *master, int len)
-{
- int dataH,dataL;
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
- /* Always do at least 16 bits */
- if (len <= 8)
- len = 16;
-
- spi100k_enable_clock(master);
- writew(SPI_CTRL_SEN(0) |
- SPI_CTRL_WORD_SIZE(len) |
- SPI_CTRL_RD,
- spi100k->base + SPI_CTRL);
-
- while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD);
- udelay(1000);
-
- dataL = readw(spi100k->base + SPI_RX_LSB);
- dataH = readw(spi100k->base + SPI_RX_MSB);
- spi100k_disable_clock(master);
-
- return dataL;
-}
-
-static void spi100k_open(struct spi_master *master)
-{
- /* get control of SPI */
- struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
- writew(SPI_SETUP1_INT_READ_ENABLE |
- SPI_SETUP1_INT_WRITE_ENABLE |
- SPI_SETUP1_CLOCK_DIVISOR(0), spi100k->base + SPI_SETUP1);
-
- /* configure clock and interrupts */
- writew(SPI_SETUP2_ACTIVE_EDGE_FALLING |
- SPI_SETUP2_NEGATIVE_LEVEL |
- SPI_SETUP2_LEVEL_TRIGGER, spi100k->base + SPI_SETUP2);
-}
-
-static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable)
-{
- if (enable)
- writew(0x05fc, spi100k->base + SPI_CTRL);
- else
- writew(0x05fd, spi100k->base + SPI_CTRL);
-}
-
-static unsigned
-omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
-{
- struct omap1_spi100k *spi100k;
- struct omap1_spi100k_cs *cs = spi->controller_state;
- unsigned int count, c;
- int word_len;
-
- spi100k = spi_master_get_devdata(spi->master);
- count = xfer->len;
- c = count;
- word_len = cs->word_len;
-
- if (word_len <= 8) {
- u8 *rx;
- const u8 *tx;
-
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
- do {
- c-=1;
- if (xfer->tx_buf != NULL)
- spi100k_write_data(spi->master, word_len, *tx++);
- if (xfer->rx_buf != NULL)
- *rx++ = spi100k_read_data(spi->master, word_len);
- } while(c);
- } else if (word_len <= 16) {
- u16 *rx;
- const u16 *tx;
-
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
- do {
- c-=2;
- if (xfer->tx_buf != NULL)
- spi100k_write_data(spi->master,word_len, *tx++);
- if (xfer->rx_buf != NULL)
- *rx++ = spi100k_read_data(spi->master,word_len);
- } while(c);
- } else if (word_len <= 32) {
- u32 *rx;
- const u32 *tx;
-
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
- do {
- c-=4;
- if (xfer->tx_buf != NULL)
- spi100k_write_data(spi->master,word_len, *tx);
- if (xfer->rx_buf != NULL)
- *rx = spi100k_read_data(spi->master,word_len);
- } while(c);
- }
- return count - c;
-}
-
-/* called only when no transfer is active to this device */
-static int omap1_spi100k_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master);
- struct omap1_spi100k_cs *cs = spi->controller_state;
- u8 word_len = spi->bits_per_word;
-
- if (t != NULL && t->bits_per_word)
- word_len = t->bits_per_word;
- if (!word_len)
- word_len = 8;
-
- if (spi->bits_per_word > 32)
- return -EINVAL;
- cs->word_len = word_len;
-
- /* SPI init before transfer */
- writew(0x3e , spi100k->base + SPI_SETUP1);
- writew(0x00 , spi100k->base + SPI_STATUS);
- writew(0x3e , spi100k->base + SPI_CTRL);
-
- return 0;
-}
-
-/* the spi->mode bits understood by this driver: */
-#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
-
-static int omap1_spi100k_setup(struct spi_device *spi)
-{
- int ret;
- struct omap1_spi100k *spi100k;
- struct omap1_spi100k_cs *cs = spi->controller_state;
-
- if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
- dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
- spi->bits_per_word);
- return -EINVAL;
- }
-
- spi100k = spi_master_get_devdata(spi->master);
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- cs->base = spi100k->base + spi->chip_select * 0x14;
- spi->controller_state = cs;
- }
-
- spi100k_open(spi->master);
-
- clk_enable(spi100k->ick);
- clk_enable(spi100k->fck);
-
- ret = omap1_spi100k_setup_transfer(spi, NULL);
-
- clk_disable(spi100k->ick);
- clk_disable(spi100k->fck);
-
- return ret;
-}
-
-static void omap1_spi100k_work(struct work_struct *work)
-{
- struct omap1_spi100k *spi100k;
- int status = 0;
-
- spi100k = container_of(work, struct omap1_spi100k, work);
- spin_lock_irq(&spi100k->lock);
-
- clk_enable(spi100k->ick);
- clk_enable(spi100k->fck);
-
- /* We only enable one channel at a time -- the one whose message is
- * at the head of the queue -- although this controller would gladly
- * arbitrate among multiple channels. This corresponds to "single
- * channel" master mode. As a side effect, we need to manage the
- * chipselect with the FORCE bit ... CS != channel enable.
- */
- while (!list_empty(&spi100k->msg_queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
- int cs_active = 0;
- struct omap1_spi100k_cs *cs;
- int par_override = 0;
-
- m = container_of(spi100k->msg_queue.next, struct spi_message,
- queue);
-
- list_del_init(&m->queue);
- spin_unlock_irq(&spi100k->lock);
-
- spi = m->spi;
- cs = spi->controller_state;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
- status = -EINVAL;
- break;
- }
- if (par_override || t->speed_hz || t->bits_per_word) {
- par_override = 1;
- status = omap1_spi100k_setup_transfer(spi, t);
- if (status < 0)
- break;
- if (!t->speed_hz && !t->bits_per_word)
- par_override = 0;
- }
-
- if (!cs_active) {
- omap1_spi100k_force_cs(spi100k, 1);
- cs_active = 1;
- }
-
- if (t->len) {
- unsigned count;
-
- count = omap1_spi100k_txrx_pio(spi, t);
- m->actual_length += count;
-
- if (count != t->len) {
- status = -EIO;
- break;
- }
- }
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- /* ignore the "leave it on after last xfer" hint */
-
- if (t->cs_change) {
- omap1_spi100k_force_cs(spi100k, 0);
- cs_active = 0;
- }
- }
-
- /* Restore defaults if they were overriden */
- if (par_override) {
- par_override = 0;
- status = omap1_spi100k_setup_transfer(spi, NULL);
- }
-
- if (cs_active)
- omap1_spi100k_force_cs(spi100k, 0);
-
- m->status = status;
- m->complete(m->context);
-
- spin_lock_irq(&spi100k->lock);
- }
-
- clk_disable(spi100k->ick);
- clk_disable(spi100k->fck);
- spin_unlock_irq(&spi100k->lock);
-
- if (status < 0)
- printk(KERN_WARNING "spi transfer failed with %d\n", status);
-}
-
-static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct omap1_spi100k *spi100k;
- unsigned long flags;
- struct spi_transfer *t;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- spi100k = spi_master_get_devdata(spi->master);
-
- /* Don't accept new work if we're shutting down */
- if (spi100k->state == SPI_SHUTDOWN)
- return -ESHUTDOWN;
-
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers) || !m->complete)
- return -EINVAL;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- const void *tx_buf = t->tx_buf;
- void *rx_buf = t->rx_buf;
- unsigned len = t->len;
-
- if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
- || (len && !(rx_buf || tx_buf))
- || (t->bits_per_word &&
- ( t->bits_per_word < 4
- || t->bits_per_word > 32))) {
- dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
- t->speed_hz,
- len,
- tx_buf ? "tx" : "",
- rx_buf ? "rx" : "",
- t->bits_per_word);
- return -EINVAL;
- }
-
- if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
- dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
- t->speed_hz,
- OMAP1_SPI100K_MAX_FREQ/(1<<16));
- return -EINVAL;
- }
-
- }
-
- spin_lock_irqsave(&spi100k->lock, flags);
- list_add_tail(&m->queue, &spi100k->msg_queue);
- queue_work(omap1_spi100k_wq, &spi100k->work);
- spin_unlock_irqrestore(&spi100k->lock, flags);
-
- return 0;
-}
-
-static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k)
-{
- return 0;
-}
-
-static int __devinit omap1_spi100k_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct omap1_spi100k *spi100k;
- int status = 0;
-
- if (!pdev->id)
- return -EINVAL;
-
- master = spi_alloc_master(&pdev->dev, sizeof *spi100k);
- if (master == NULL) {
- dev_dbg(&pdev->dev, "master allocation failed\n");
- return -ENOMEM;
- }
-
- if (pdev->id != -1)
- master->bus_num = pdev->id;
-
- master->setup = omap1_spi100k_setup;
- master->transfer = omap1_spi100k_transfer;
- master->cleanup = NULL;
- master->num_chipselect = 2;
- master->mode_bits = MODEBITS;
-
- dev_set_drvdata(&pdev->dev, master);
-
- spi100k = spi_master_get_devdata(master);
- spi100k->master = master;
-
- /*
- * The memory region base address is taken as the platform_data.
- * You should allocate this with ioremap() before initializing
- * the SPI.
- */
- spi100k->base = (void __iomem *) pdev->dev.platform_data;
-
- INIT_WORK(&spi100k->work, omap1_spi100k_work);
-
- spin_lock_init(&spi100k->lock);
- INIT_LIST_HEAD(&spi100k->msg_queue);
- spi100k->ick = clk_get(&pdev->dev, "ick");
- if (IS_ERR(spi100k->ick)) {
- dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
- status = PTR_ERR(spi100k->ick);
- goto err1;
- }
-
- spi100k->fck = clk_get(&pdev->dev, "fck");
- if (IS_ERR(spi100k->fck)) {
- dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
- status = PTR_ERR(spi100k->fck);
- goto err2;
- }
-
- if (omap1_spi100k_reset(spi100k) < 0)
- goto err3;
-
- status = spi_register_master(master);
- if (status < 0)
- goto err3;
-
- spi100k->state = SPI_RUNNING;
-
- return status;
-
-err3:
- clk_put(spi100k->fck);
-err2:
- clk_put(spi100k->ick);
-err1:
- spi_master_put(master);
- return status;
-}
-
-static int __exit omap1_spi100k_remove(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct omap1_spi100k *spi100k;
- struct resource *r;
- unsigned limit = 500;
- unsigned long flags;
- int status = 0;
-
- master = dev_get_drvdata(&pdev->dev);
- spi100k = spi_master_get_devdata(master);
-
- spin_lock_irqsave(&spi100k->lock, flags);
-
- spi100k->state = SPI_SHUTDOWN;
- while (!list_empty(&spi100k->msg_queue) && limit--) {
- spin_unlock_irqrestore(&spi100k->lock, flags);
- msleep(10);
- spin_lock_irqsave(&spi100k->lock, flags);
- }
-
- if (!list_empty(&spi100k->msg_queue))
- status = -EBUSY;
-
- spin_unlock_irqrestore(&spi100k->lock, flags);
-
- if (status != 0)
- return status;
-
- clk_put(spi100k->fck);
- clk_put(spi100k->ick);
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- spi_unregister_master(master);
-
- return 0;
-}
-
-static struct platform_driver omap1_spi100k_driver = {
- .driver = {
- .name = "omap1_spi100k",
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(omap1_spi100k_remove),
-};
-
-
-static int __init omap1_spi100k_init(void)
-{
- omap1_spi100k_wq = create_singlethread_workqueue(
- omap1_spi100k_driver.driver.name);
-
- if (omap1_spi100k_wq == NULL)
- return -1;
-
- return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
-}
-
-static void __exit omap1_spi100k_exit(void)
-{
- platform_driver_unregister(&omap1_spi100k_driver);
-
- destroy_workqueue(omap1_spi100k_wq);
-}
-
-module_init(omap1_spi100k_init);
-module_exit(omap1_spi100k_exit);
-
-MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
-MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
-MODULE_LICENSE("GPL");
-
diff --git a/ANDROID_3.4.5/drivers/spi/spi-omap-uwire.c b/ANDROID_3.4.5/drivers/spi/spi-omap-uwire.c
deleted file mode 100644
index 9b0d7169..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-omap-uwire.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * MicroWire interface driver for OMAP
- *
- * Copyright 2003 MontaVista Software Inc. <source@mvista.com>
- *
- * Ported to 2.6 OMAP uwire interface.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Generalization patches by Juha Yrjola <juha.yrjola@nokia.com>
- *
- * Copyright (C) 2005 David Brownell (ported to 2.6 SPI interface)
- * Copyright (C) 2006 Nokia
- *
- * Many updates by Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/module.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/mach-types.h>
-
-#include <plat/mux.h>
-#include <plat/omap7xx.h> /* OMAP7XX_IO_CONF registers */
-
-
-/* FIXME address is now a platform device resource,
- * and irqs should show there too...
- */
-#define UWIRE_BASE_PHYS 0xFFFB3000
-
-/* uWire Registers: */
-#define UWIRE_IO_SIZE 0x20
-#define UWIRE_TDR 0x00
-#define UWIRE_RDR 0x00
-#define UWIRE_CSR 0x01
-#define UWIRE_SR1 0x02
-#define UWIRE_SR2 0x03
-#define UWIRE_SR3 0x04
-#define UWIRE_SR4 0x05
-#define UWIRE_SR5 0x06
-
-/* CSR bits */
-#define RDRB (1 << 15)
-#define CSRB (1 << 14)
-#define START (1 << 13)
-#define CS_CMD (1 << 12)
-
-/* SR1 or SR2 bits */
-#define UWIRE_READ_FALLING_EDGE 0x0001
-#define UWIRE_READ_RISING_EDGE 0x0000
-#define UWIRE_WRITE_FALLING_EDGE 0x0000
-#define UWIRE_WRITE_RISING_EDGE 0x0002
-#define UWIRE_CS_ACTIVE_LOW 0x0000
-#define UWIRE_CS_ACTIVE_HIGH 0x0004
-#define UWIRE_FREQ_DIV_2 0x0000
-#define UWIRE_FREQ_DIV_4 0x0008
-#define UWIRE_FREQ_DIV_8 0x0010
-#define UWIRE_CHK_READY 0x0020
-#define UWIRE_CLK_INVERTED 0x0040
-
-
-struct uwire_spi {
- struct spi_bitbang bitbang;
- struct clk *ck;
-};
-
-struct uwire_state {
- unsigned bits_per_word;
- unsigned div1_idx;
-};
-
-/* REVISIT compile time constant for idx_shift? */
-/*
- * Or, put it in a structure which is used throughout the driver;
- * that avoids having to issue two loads for each bit of static data.
- */
-static unsigned int uwire_idx_shift;
-static void __iomem *uwire_base;
-
-static inline void uwire_write_reg(int idx, u16 val)
-{
- __raw_writew(val, uwire_base + (idx << uwire_idx_shift));
-}
-
-static inline u16 uwire_read_reg(int idx)
-{
- return __raw_readw(uwire_base + (idx << uwire_idx_shift));
-}
-
-static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
-{
- u16 w, val = 0;
- int shift, reg;
-
- if (flags & UWIRE_CLK_INVERTED)
- val ^= 0x03;
- val = flags & 0x3f;
- if (cs & 1)
- shift = 6;
- else
- shift = 0;
- if (cs <= 1)
- reg = UWIRE_SR1;
- else
- reg = UWIRE_SR2;
-
- w = uwire_read_reg(reg);
- w &= ~(0x3f << shift);
- w |= val << shift;
- uwire_write_reg(reg, w);
-}
-
-static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
-{
- u16 w;
- int c = 0;
- unsigned long max_jiffies = jiffies + HZ;
-
- for (;;) {
- w = uwire_read_reg(UWIRE_CSR);
- if ((w & mask) == val)
- break;
- if (time_after(jiffies, max_jiffies)) {
- printk(KERN_ERR "%s: timeout. reg=%#06x "
- "mask=%#06x val=%#06x\n",
- __func__, w, mask, val);
- return -1;
- }
- c++;
- if (might_not_catch && c > 64)
- break;
- }
- return 0;
-}
-
-static void uwire_set_clk1_div(int div1_idx)
-{
- u16 w;
-
- w = uwire_read_reg(UWIRE_SR3);
- w &= ~(0x03 << 1);
- w |= div1_idx << 1;
- uwire_write_reg(UWIRE_SR3, w);
-}
-
-static void uwire_chipselect(struct spi_device *spi, int value)
-{
- struct uwire_state *ust = spi->controller_state;
- u16 w;
- int old_cs;
-
-
- BUG_ON(wait_uwire_csr_flag(CSRB, 0, 0));
-
- w = uwire_read_reg(UWIRE_CSR);
- old_cs = (w >> 10) & 0x03;
- if (value == BITBANG_CS_INACTIVE || old_cs != spi->chip_select) {
- /* Deselect this CS, or the previous CS */
- w &= ~CS_CMD;
- uwire_write_reg(UWIRE_CSR, w);
- }
- /* activate specfied chipselect */
- if (value == BITBANG_CS_ACTIVE) {
- uwire_set_clk1_div(ust->div1_idx);
- /* invert clock? */
- if (spi->mode & SPI_CPOL)
- uwire_write_reg(UWIRE_SR4, 1);
- else
- uwire_write_reg(UWIRE_SR4, 0);
-
- w = spi->chip_select << 10;
- w |= CS_CMD;
- uwire_write_reg(UWIRE_CSR, w);
- }
-}
-
-static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct uwire_state *ust = spi->controller_state;
- unsigned len = t->len;
- unsigned bits = ust->bits_per_word;
- unsigned bytes;
- u16 val, w;
- int status = 0;
-
- if (!t->tx_buf && !t->rx_buf)
- return 0;
-
- /* Microwire doesn't read and write concurrently */
- if (t->tx_buf && t->rx_buf)
- return -EPERM;
-
- w = spi->chip_select << 10;
- w |= CS_CMD;
-
- if (t->tx_buf) {
- const u8 *buf = t->tx_buf;
-
- /* NOTE: DMA could be used for TX transfers */
-
- /* write one or two bytes at a time */
- while (len >= 1) {
- /* tx bit 15 is first sent; we byteswap multibyte words
- * (msb-first) on the way out from memory.
- */
- val = *buf++;
- if (bits > 8) {
- bytes = 2;
- val |= *buf++ << 8;
- } else
- bytes = 1;
- val <<= 16 - bits;
-
-#ifdef VERBOSE
- pr_debug("%s: write-%d =%04x\n",
- dev_name(&spi->dev), bits, val);
-#endif
- if (wait_uwire_csr_flag(CSRB, 0, 0))
- goto eio;
-
- uwire_write_reg(UWIRE_TDR, val);
-
- /* start write */
- val = START | w | (bits << 5);
-
- uwire_write_reg(UWIRE_CSR, val);
- len -= bytes;
-
- /* Wait till write actually starts.
- * This is needed with MPU clock 60+ MHz.
- * REVISIT: we may not have time to catch it...
- */
- if (wait_uwire_csr_flag(CSRB, CSRB, 1))
- goto eio;
-
- status += bytes;
- }
-
- /* REVISIT: save this for later to get more i/o overlap */
- if (wait_uwire_csr_flag(CSRB, 0, 0))
- goto eio;
-
- } else if (t->rx_buf) {
- u8 *buf = t->rx_buf;
-
- /* read one or two bytes at a time */
- while (len) {
- if (bits > 8) {
- bytes = 2;
- } else
- bytes = 1;
-
- /* start read */
- val = START | w | (bits << 0);
- uwire_write_reg(UWIRE_CSR, val);
- len -= bytes;
-
- /* Wait till read actually starts */
- (void) wait_uwire_csr_flag(CSRB, CSRB, 1);
-
- if (wait_uwire_csr_flag(RDRB | CSRB,
- RDRB, 0))
- goto eio;
-
- /* rx bit 0 is last received; multibyte words will
- * be properly byteswapped on the way to memory.
- */
- val = uwire_read_reg(UWIRE_RDR);
- val &= (1 << bits) - 1;
- *buf++ = (u8) val;
- if (bytes == 2)
- *buf++ = val >> 8;
- status += bytes;
-#ifdef VERBOSE
- pr_debug("%s: read-%d =%04x\n",
- dev_name(&spi->dev), bits, val);
-#endif
-
- }
- }
- return status;
-eio:
- return -EIO;
-}
-
-static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct uwire_state *ust = spi->controller_state;
- struct uwire_spi *uwire;
- unsigned flags = 0;
- unsigned bits;
- unsigned hz;
- unsigned long rate;
- int div1_idx;
- int div1;
- int div2;
- int status;
-
- uwire = spi_master_get_devdata(spi->master);
-
- if (spi->chip_select > 3) {
- pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select);
- status = -ENODEV;
- goto done;
- }
-
- bits = spi->bits_per_word;
- if (t != NULL && t->bits_per_word)
- bits = t->bits_per_word;
-
- if (bits > 16) {
- pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
- status = -ENODEV;
- goto done;
- }
- ust->bits_per_word = bits;
-
- /* mode 0..3, clock inverted separately;
- * standard nCS signaling;
- * don't treat DI=high as "not ready"
- */
- if (spi->mode & SPI_CS_HIGH)
- flags |= UWIRE_CS_ACTIVE_HIGH;
-
- if (spi->mode & SPI_CPOL)
- flags |= UWIRE_CLK_INVERTED;
-
- switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
- case SPI_MODE_0:
- case SPI_MODE_3:
- flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
- break;
- case SPI_MODE_1:
- case SPI_MODE_2:
- flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
- break;
- }
-
- /* assume it's already enabled */
- rate = clk_get_rate(uwire->ck);
-
- hz = spi->max_speed_hz;
- if (t != NULL && t->speed_hz)
- hz = t->speed_hz;
-
- if (!hz) {
- pr_debug("%s: zero speed?\n", dev_name(&spi->dev));
- status = -EINVAL;
- goto done;
- }
-
- /* F_INT = mpu_xor_clk / DIV1 */
- for (div1_idx = 0; div1_idx < 4; div1_idx++) {
- switch (div1_idx) {
- case 0:
- div1 = 2;
- break;
- case 1:
- div1 = 4;
- break;
- case 2:
- div1 = 7;
- break;
- default:
- case 3:
- div1 = 10;
- break;
- }
- div2 = (rate / div1 + hz - 1) / hz;
- if (div2 <= 8)
- break;
- }
- if (div1_idx == 4) {
- pr_debug("%s: lowest clock %ld, need %d\n",
- dev_name(&spi->dev), rate / 10 / 8, hz);
- status = -EDOM;
- goto done;
- }
-
- /* we have to cache this and reset in uwire_chipselect as this is a
- * global parameter and another uwire device can change it under
- * us */
- ust->div1_idx = div1_idx;
- uwire_set_clk1_div(div1_idx);
-
- rate /= div1;
-
- switch (div2) {
- case 0:
- case 1:
- case 2:
- flags |= UWIRE_FREQ_DIV_2;
- rate /= 2;
- break;
- case 3:
- case 4:
- flags |= UWIRE_FREQ_DIV_4;
- rate /= 4;
- break;
- case 5:
- case 6:
- case 7:
- case 8:
- flags |= UWIRE_FREQ_DIV_8;
- rate /= 8;
- break;
- }
- omap_uwire_configure_mode(spi->chip_select, flags);
- pr_debug("%s: uwire flags %02x, armxor %lu KHz, SCK %lu KHz\n",
- __func__, flags,
- clk_get_rate(uwire->ck) / 1000,
- rate / 1000);
- status = 0;
-done:
- return status;
-}
-
-static int uwire_setup(struct spi_device *spi)
-{
- struct uwire_state *ust = spi->controller_state;
-
- if (ust == NULL) {
- ust = kzalloc(sizeof(*ust), GFP_KERNEL);
- if (ust == NULL)
- return -ENOMEM;
- spi->controller_state = ust;
- }
-
- return uwire_setup_transfer(spi, NULL);
-}
-
-static void uwire_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-
-static void uwire_off(struct uwire_spi *uwire)
-{
- uwire_write_reg(UWIRE_SR3, 0);
- clk_disable(uwire->ck);
- clk_put(uwire->ck);
- spi_master_put(uwire->bitbang.master);
-}
-
-static int __init uwire_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct uwire_spi *uwire;
- int status;
-
- master = spi_alloc_master(&pdev->dev, sizeof *uwire);
- if (!master)
- return -ENODEV;
-
- uwire = spi_master_get_devdata(master);
-
- uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
- if (!uwire_base) {
- dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
- spi_master_put(master);
- return -ENOMEM;
- }
-
- dev_set_drvdata(&pdev->dev, uwire);
-
- uwire->ck = clk_get(&pdev->dev, "fck");
- if (IS_ERR(uwire->ck)) {
- status = PTR_ERR(uwire->ck);
- dev_dbg(&pdev->dev, "no functional clock?\n");
- spi_master_put(master);
- return status;
- }
- clk_enable(uwire->ck);
-
- if (cpu_is_omap7xx())
- uwire_idx_shift = 1;
- else
- uwire_idx_shift = 2;
-
- uwire_write_reg(UWIRE_SR3, 1);
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- master->flags = SPI_MASTER_HALF_DUPLEX;
-
- master->bus_num = 2; /* "official" */
- master->num_chipselect = 4;
- master->setup = uwire_setup;
- master->cleanup = uwire_cleanup;
-
- uwire->bitbang.master = master;
- uwire->bitbang.chipselect = uwire_chipselect;
- uwire->bitbang.setup_transfer = uwire_setup_transfer;
- uwire->bitbang.txrx_bufs = uwire_txrx;
-
- status = spi_bitbang_start(&uwire->bitbang);
- if (status < 0) {
- uwire_off(uwire);
- iounmap(uwire_base);
- }
- return status;
-}
-
-static int __exit uwire_remove(struct platform_device *pdev)
-{
- struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev);
- int status;
-
- // FIXME remove all child devices, somewhere ...
-
- status = spi_bitbang_stop(&uwire->bitbang);
- uwire_off(uwire);
- iounmap(uwire_base);
- return status;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:omap_uwire");
-
-static struct platform_driver uwire_driver = {
- .driver = {
- .name = "omap_uwire",
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(uwire_remove),
- // suspend ... unuse ck
- // resume ... use ck
-};
-
-static int __init omap_uwire_init(void)
-{
- /* FIXME move these into the relevant board init code. also, include
- * H3 support; it uses tsc2101 like H2 (on a different chipselect).
- */
-
- if (machine_is_omap_h2()) {
- /* defaults: W21 SDO, U18 SDI, V19 SCL */
- omap_cfg_reg(N14_1610_UWIRE_CS0);
- omap_cfg_reg(N15_1610_UWIRE_CS1);
- }
- if (machine_is_omap_perseus2()) {
- /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
- int val = omap_readl(OMAP7XX_IO_CONF_9) & ~0x00EEE000;
- omap_writel(val | 0x00AAA000, OMAP7XX_IO_CONF_9);
- }
-
- return platform_driver_probe(&uwire_driver, uwire_probe);
-}
-
-static void __exit omap_uwire_exit(void)
-{
- platform_driver_unregister(&uwire_driver);
-}
-
-subsys_initcall(omap_uwire_init);
-module_exit(omap_uwire_exit);
-
-MODULE_LICENSE("GPL");
-
diff --git a/ANDROID_3.4.5/drivers/spi/spi-omap2-mcspi.c b/ANDROID_3.4.5/drivers/spi/spi-omap2-mcspi.c
deleted file mode 100644
index bb9274c2..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-omap2-mcspi.c
+++ /dev/null
@@ -1,1347 +0,0 @@
-/*
- * OMAP2 McSPI controller driver
- *
- * Copyright (C) 2005, 2006 Nokia Corporation
- * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and
- * Juha Yrj�l� <juha.yrjola@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#include <linux/spi/spi.h>
-
-#include <plat/dma.h>
-#include <plat/clock.h>
-#include <plat/mcspi.h>
-
-#define OMAP2_MCSPI_MAX_FREQ 48000000
-
-/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
-#define OMAP2_MCSPI_MAX_CTRL 4
-
-#define OMAP2_MCSPI_REVISION 0x00
-#define OMAP2_MCSPI_SYSSTATUS 0x14
-#define OMAP2_MCSPI_IRQSTATUS 0x18
-#define OMAP2_MCSPI_IRQENABLE 0x1c
-#define OMAP2_MCSPI_WAKEUPENABLE 0x20
-#define OMAP2_MCSPI_SYST 0x24
-#define OMAP2_MCSPI_MODULCTRL 0x28
-
-/* per-channel banks, 0x14 bytes each, first is: */
-#define OMAP2_MCSPI_CHCONF0 0x2c
-#define OMAP2_MCSPI_CHSTAT0 0x30
-#define OMAP2_MCSPI_CHCTRL0 0x34
-#define OMAP2_MCSPI_TX0 0x38
-#define OMAP2_MCSPI_RX0 0x3c
-
-/* per-register bitmasks: */
-
-#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0)
-#define OMAP2_MCSPI_MODULCTRL_MS BIT(2)
-#define OMAP2_MCSPI_MODULCTRL_STEST BIT(3)
-
-#define OMAP2_MCSPI_CHCONF_PHA BIT(0)
-#define OMAP2_MCSPI_CHCONF_POL BIT(1)
-#define OMAP2_MCSPI_CHCONF_CLKD_MASK (0x0f << 2)
-#define OMAP2_MCSPI_CHCONF_EPOL BIT(6)
-#define OMAP2_MCSPI_CHCONF_WL_MASK (0x1f << 7)
-#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY BIT(12)
-#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY BIT(13)
-#define OMAP2_MCSPI_CHCONF_TRM_MASK (0x03 << 12)
-#define OMAP2_MCSPI_CHCONF_DMAW BIT(14)
-#define OMAP2_MCSPI_CHCONF_DMAR BIT(15)
-#define OMAP2_MCSPI_CHCONF_DPE0 BIT(16)
-#define OMAP2_MCSPI_CHCONF_DPE1 BIT(17)
-#define OMAP2_MCSPI_CHCONF_IS BIT(18)
-#define OMAP2_MCSPI_CHCONF_TURBO BIT(19)
-#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
-
-#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
-#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
-#define OMAP2_MCSPI_CHSTAT_EOT BIT(2)
-
-#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
-
-#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
-
-/* We have 2 DMA channels per CS, one for RX and one for TX */
-struct omap2_mcspi_dma {
- int dma_tx_channel;
- int dma_rx_channel;
-
- int dma_tx_sync_dev;
- int dma_rx_sync_dev;
-
- struct completion dma_tx_completion;
- struct completion dma_rx_completion;
-};
-
-/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
- * cache operations; better heuristics consider wordsize and bitrate.
- */
-#define DMA_MIN_BYTES 160
-
-
-struct omap2_mcspi {
- struct work_struct work;
- /* lock protects queue and registers */
- spinlock_t lock;
- struct list_head msg_queue;
- struct spi_master *master;
- /* Virtual base address of the controller */
- void __iomem *base;
- unsigned long phys;
- /* SPI1 has 4 channels, while SPI2 has 2 */
- struct omap2_mcspi_dma *dma_channels;
- struct device *dev;
- struct workqueue_struct *wq;
-};
-
-struct omap2_mcspi_cs {
- void __iomem *base;
- unsigned long phys;
- int word_len;
- struct list_head node;
- /* Context save and restore shadow register */
- u32 chconf0;
-};
-
-/* used for context save and restore, structure members to be updated whenever
- * corresponding registers are modified.
- */
-struct omap2_mcspi_regs {
- u32 modulctrl;
- u32 wakeupenable;
- struct list_head cs;
-};
-
-static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
-
-#define MOD_REG_BIT(val, mask, set) do { \
- if (set) \
- val |= mask; \
- else \
- val &= ~mask; \
-} while (0)
-
-static inline void mcspi_write_reg(struct spi_master *master,
- int idx, u32 val)
-{
- struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
- __raw_writel(val, mcspi->base + idx);
-}
-
-static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
-{
- struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
- return __raw_readl(mcspi->base + idx);
-}
-
-static inline void mcspi_write_cs_reg(const struct spi_device *spi,
- int idx, u32 val)
-{
- struct omap2_mcspi_cs *cs = spi->controller_state;
-
- __raw_writel(val, cs->base + idx);
-}
-
-static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
-{
- struct omap2_mcspi_cs *cs = spi->controller_state;
-
- return __raw_readl(cs->base + idx);
-}
-
-static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
-{
- struct omap2_mcspi_cs *cs = spi->controller_state;
-
- return cs->chconf0;
-}
-
-static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
-{
- struct omap2_mcspi_cs *cs = spi->controller_state;
-
- cs->chconf0 = val;
- mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
- mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
-}
-
-static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
- int is_read, int enable)
-{
- u32 l, rw;
-
- l = mcspi_cached_chconf0(spi);
-
- if (is_read) /* 1 is read, 0 write */
- rw = OMAP2_MCSPI_CHCONF_DMAR;
- else
- rw = OMAP2_MCSPI_CHCONF_DMAW;
-
- MOD_REG_BIT(l, rw, enable);
- mcspi_write_chconf0(spi, l);
-}
-
-static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
-{
- u32 l;
-
- l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
- mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
- /* Flash post-writes */
- mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
-}
-
-static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
-{
- u32 l;
-
- l = mcspi_cached_chconf0(spi);
- MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
- mcspi_write_chconf0(spi, l);
-}
-
-static void omap2_mcspi_set_master_mode(struct spi_master *master)
-{
- u32 l;
-
- /* setup when switching from (reset default) slave mode
- * to single-channel master mode
- */
- l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
- MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
- MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
- MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
- mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
-
- omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
-}
-
-static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
-{
- struct spi_master *spi_cntrl;
- struct omap2_mcspi_cs *cs;
- spi_cntrl = mcspi->master;
-
- /* McSPI: context restore */
- mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
- omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
-
- mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
- omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
-
- list_for_each_entry(cs, &omap2_mcspi_ctx[spi_cntrl->bus_num - 1].cs,
- node)
- __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
-}
-static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
-{
- pm_runtime_put_sync(mcspi->dev);
-}
-
-static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
-{
- return pm_runtime_get_sync(mcspi->dev);
-}
-
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
- unsigned long timeout;
-
- timeout = jiffies + msecs_to_jiffies(1000);
- while (!(__raw_readl(reg) & bit)) {
- if (time_after(jiffies, timeout))
- return -1;
- cpu_relax();
- }
- return 0;
-}
-
-static unsigned
-omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
-{
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_cs *cs = spi->controller_state;
- struct omap2_mcspi_dma *mcspi_dma;
- unsigned int count, c;
- unsigned long base, tx_reg, rx_reg;
- int word_len, data_type, element_count;
- int elements = 0;
- u32 l;
- u8 * rx;
- const u8 * tx;
- void __iomem *chstat_reg;
-
- mcspi = spi_master_get_devdata(spi->master);
- mcspi_dma = &mcspi->dma_channels[spi->chip_select];
- l = mcspi_cached_chconf0(spi);
-
- chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
-
- count = xfer->len;
- c = count;
- word_len = cs->word_len;
-
- base = cs->phys;
- tx_reg = base + OMAP2_MCSPI_TX0;
- rx_reg = base + OMAP2_MCSPI_RX0;
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
-
- if (word_len <= 8) {
- data_type = OMAP_DMA_DATA_TYPE_S8;
- element_count = count;
- } else if (word_len <= 16) {
- data_type = OMAP_DMA_DATA_TYPE_S16;
- element_count = count >> 1;
- } else /* word_len <= 32 */ {
- data_type = OMAP_DMA_DATA_TYPE_S32;
- element_count = count >> 2;
- }
-
- if (tx != NULL) {
- omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
- data_type, element_count, 1,
- OMAP_DMA_SYNC_ELEMENT,
- mcspi_dma->dma_tx_sync_dev, 0);
-
- omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- tx_reg, 0, 0);
-
- omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
- OMAP_DMA_AMODE_POST_INC,
- xfer->tx_dma, 0, 0);
- }
-
- if (rx != NULL) {
- elements = element_count - 1;
- if (l & OMAP2_MCSPI_CHCONF_TURBO)
- elements--;
-
- omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
- data_type, elements, 1,
- OMAP_DMA_SYNC_ELEMENT,
- mcspi_dma->dma_rx_sync_dev, 1);
-
- omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- rx_reg, 0, 0);
-
- omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
- OMAP_DMA_AMODE_POST_INC,
- xfer->rx_dma, 0, 0);
- }
-
- if (tx != NULL) {
- omap_start_dma(mcspi_dma->dma_tx_channel);
- omap2_mcspi_set_dma_req(spi, 0, 1);
- }
-
- if (rx != NULL) {
- omap_start_dma(mcspi_dma->dma_rx_channel);
- omap2_mcspi_set_dma_req(spi, 1, 1);
- }
-
- if (tx != NULL) {
- wait_for_completion(&mcspi_dma->dma_tx_completion);
- dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE);
-
- /* for TX_ONLY mode, be sure all words have shifted out */
- if (rx == NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_TXS) < 0)
- dev_err(&spi->dev, "TXS timed out\n");
- else if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_EOT) < 0)
- dev_err(&spi->dev, "EOT timed out\n");
- }
- }
-
- if (rx != NULL) {
- wait_for_completion(&mcspi_dma->dma_rx_completion);
- dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE);
- omap2_mcspi_set_enable(spi, 0);
-
- if (l & OMAP2_MCSPI_CHCONF_TURBO) {
-
- if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
- & OMAP2_MCSPI_CHSTAT_RXS)) {
- u32 w;
-
- w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
- if (word_len <= 8)
- ((u8 *)xfer->rx_buf)[elements++] = w;
- else if (word_len <= 16)
- ((u16 *)xfer->rx_buf)[elements++] = w;
- else /* word_len <= 32 */
- ((u32 *)xfer->rx_buf)[elements++] = w;
- } else {
- dev_err(&spi->dev,
- "DMA RX penultimate word empty");
- count -= (word_len <= 8) ? 2 :
- (word_len <= 16) ? 4 :
- /* word_len <= 32 */ 8;
- omap2_mcspi_set_enable(spi, 1);
- return count;
- }
- }
-
- if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
- & OMAP2_MCSPI_CHSTAT_RXS)) {
- u32 w;
-
- w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
- if (word_len <= 8)
- ((u8 *)xfer->rx_buf)[elements] = w;
- else if (word_len <= 16)
- ((u16 *)xfer->rx_buf)[elements] = w;
- else /* word_len <= 32 */
- ((u32 *)xfer->rx_buf)[elements] = w;
- } else {
- dev_err(&spi->dev, "DMA RX last word empty");
- count -= (word_len <= 8) ? 1 :
- (word_len <= 16) ? 2 :
- /* word_len <= 32 */ 4;
- }
- omap2_mcspi_set_enable(spi, 1);
- }
- return count;
-}
-
-static unsigned
-omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
-{
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_cs *cs = spi->controller_state;
- unsigned int count, c;
- u32 l;
- void __iomem *base = cs->base;
- void __iomem *tx_reg;
- void __iomem *rx_reg;
- void __iomem *chstat_reg;
- int word_len;
-
- mcspi = spi_master_get_devdata(spi->master);
- count = xfer->len;
- c = count;
- word_len = cs->word_len;
-
- l = mcspi_cached_chconf0(spi);
-
- /* We store the pre-calculated register addresses on stack to speed
- * up the transfer loop. */
- tx_reg = base + OMAP2_MCSPI_TX0;
- rx_reg = base + OMAP2_MCSPI_RX0;
- chstat_reg = base + OMAP2_MCSPI_CHSTAT0;
-
- if (c < (word_len>>3))
- return 0;
-
- if (word_len <= 8) {
- u8 *rx;
- const u8 *tx;
-
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
-
- do {
- c -= 1;
- if (tx != NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_TXS) < 0) {
- dev_err(&spi->dev, "TXS timed out\n");
- goto out;
- }
- dev_vdbg(&spi->dev, "write-%d %02x\n",
- word_len, *tx);
- __raw_writel(*tx++, tx_reg);
- }
- if (rx != NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_RXS) < 0) {
- dev_err(&spi->dev, "RXS timed out\n");
- goto out;
- }
-
- if (c == 1 && tx == NULL &&
- (l & OMAP2_MCSPI_CHCONF_TURBO)) {
- omap2_mcspi_set_enable(spi, 0);
- *rx++ = __raw_readl(rx_reg);
- dev_vdbg(&spi->dev, "read-%d %02x\n",
- word_len, *(rx - 1));
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_RXS) < 0) {
- dev_err(&spi->dev,
- "RXS timed out\n");
- goto out;
- }
- c = 0;
- } else if (c == 0 && tx == NULL) {
- omap2_mcspi_set_enable(spi, 0);
- }
-
- *rx++ = __raw_readl(rx_reg);
- dev_vdbg(&spi->dev, "read-%d %02x\n",
- word_len, *(rx - 1));
- }
- } while (c);
- } else if (word_len <= 16) {
- u16 *rx;
- const u16 *tx;
-
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
- do {
- c -= 2;
- if (tx != NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_TXS) < 0) {
- dev_err(&spi->dev, "TXS timed out\n");
- goto out;
- }
- dev_vdbg(&spi->dev, "write-%d %04x\n",
- word_len, *tx);
- __raw_writel(*tx++, tx_reg);
- }
- if (rx != NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_RXS) < 0) {
- dev_err(&spi->dev, "RXS timed out\n");
- goto out;
- }
-
- if (c == 2 && tx == NULL &&
- (l & OMAP2_MCSPI_CHCONF_TURBO)) {
- omap2_mcspi_set_enable(spi, 0);
- *rx++ = __raw_readl(rx_reg);
- dev_vdbg(&spi->dev, "read-%d %04x\n",
- word_len, *(rx - 1));
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_RXS) < 0) {
- dev_err(&spi->dev,
- "RXS timed out\n");
- goto out;
- }
- c = 0;
- } else if (c == 0 && tx == NULL) {
- omap2_mcspi_set_enable(spi, 0);
- }
-
- *rx++ = __raw_readl(rx_reg);
- dev_vdbg(&spi->dev, "read-%d %04x\n",
- word_len, *(rx - 1));
- }
- } while (c >= 2);
- } else if (word_len <= 32) {
- u32 *rx;
- const u32 *tx;
-
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
- do {
- c -= 4;
- if (tx != NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_TXS) < 0) {
- dev_err(&spi->dev, "TXS timed out\n");
- goto out;
- }
- dev_vdbg(&spi->dev, "write-%d %08x\n",
- word_len, *tx);
- __raw_writel(*tx++, tx_reg);
- }
- if (rx != NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_RXS) < 0) {
- dev_err(&spi->dev, "RXS timed out\n");
- goto out;
- }
-
- if (c == 4 && tx == NULL &&
- (l & OMAP2_MCSPI_CHCONF_TURBO)) {
- omap2_mcspi_set_enable(spi, 0);
- *rx++ = __raw_readl(rx_reg);
- dev_vdbg(&spi->dev, "read-%d %08x\n",
- word_len, *(rx - 1));
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_RXS) < 0) {
- dev_err(&spi->dev,
- "RXS timed out\n");
- goto out;
- }
- c = 0;
- } else if (c == 0 && tx == NULL) {
- omap2_mcspi_set_enable(spi, 0);
- }
-
- *rx++ = __raw_readl(rx_reg);
- dev_vdbg(&spi->dev, "read-%d %08x\n",
- word_len, *(rx - 1));
- }
- } while (c >= 4);
- }
-
- /* for TX_ONLY mode, be sure all words have shifted out */
- if (xfer->rx_buf == NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_TXS) < 0) {
- dev_err(&spi->dev, "TXS timed out\n");
- } else if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_EOT) < 0)
- dev_err(&spi->dev, "EOT timed out\n");
-
- /* disable chan to purge rx datas received in TX_ONLY transfer,
- * otherwise these rx datas will affect the direct following
- * RX_ONLY transfer.
- */
- omap2_mcspi_set_enable(spi, 0);
- }
-out:
- omap2_mcspi_set_enable(spi, 1);
- return count - c;
-}
-
-static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
-{
- u32 div;
-
- for (div = 0; div < 15; div++)
- if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
- return div;
-
- return 15;
-}
-
-/* called only when no transfer is active to this device */
-static int omap2_mcspi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct omap2_mcspi_cs *cs = spi->controller_state;
- struct omap2_mcspi *mcspi;
- struct spi_master *spi_cntrl;
- u32 l = 0, div = 0;
- u8 word_len = spi->bits_per_word;
- u32 speed_hz = spi->max_speed_hz;
-
- mcspi = spi_master_get_devdata(spi->master);
- spi_cntrl = mcspi->master;
-
- if (t != NULL && t->bits_per_word)
- word_len = t->bits_per_word;
-
- cs->word_len = word_len;
-
- if (t && t->speed_hz)
- speed_hz = t->speed_hz;
-
- speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
- div = omap2_mcspi_calc_divisor(speed_hz);
-
- l = mcspi_cached_chconf0(spi);
-
- /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
- * REVISIT: this controller could support SPI_3WIRE mode.
- */
- l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
- l |= OMAP2_MCSPI_CHCONF_DPE0;
-
- /* wordlength */
- l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
- l |= (word_len - 1) << 7;
-
- /* set chipselect polarity; manage with FORCE */
- if (!(spi->mode & SPI_CS_HIGH))
- l |= OMAP2_MCSPI_CHCONF_EPOL; /* active-low; normal */
- else
- l &= ~OMAP2_MCSPI_CHCONF_EPOL;
-
- /* set clock divisor */
- l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
- l |= div << 2;
-
- /* set SPI mode 0..3 */
- if (spi->mode & SPI_CPOL)
- l |= OMAP2_MCSPI_CHCONF_POL;
- else
- l &= ~OMAP2_MCSPI_CHCONF_POL;
- if (spi->mode & SPI_CPHA)
- l |= OMAP2_MCSPI_CHCONF_PHA;
- else
- l &= ~OMAP2_MCSPI_CHCONF_PHA;
-
- mcspi_write_chconf0(spi, l);
-
- dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
- OMAP2_MCSPI_MAX_FREQ >> div,
- (spi->mode & SPI_CPHA) ? "trailing" : "leading",
- (spi->mode & SPI_CPOL) ? "inverted" : "normal");
-
- return 0;
-}
-
-static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
-{
- struct spi_device *spi = data;
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_dma *mcspi_dma;
-
- mcspi = spi_master_get_devdata(spi->master);
- mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
-
- complete(&mcspi_dma->dma_rx_completion);
-
- /* We must disable the DMA RX request */
- omap2_mcspi_set_dma_req(spi, 1, 0);
-}
-
-static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
-{
- struct spi_device *spi = data;
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_dma *mcspi_dma;
-
- mcspi = spi_master_get_devdata(spi->master);
- mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
-
- complete(&mcspi_dma->dma_tx_completion);
-
- /* We must disable the DMA TX request */
- omap2_mcspi_set_dma_req(spi, 0, 0);
-}
-
-static int omap2_mcspi_request_dma(struct spi_device *spi)
-{
- struct spi_master *master = spi->master;
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_dma *mcspi_dma;
-
- mcspi = spi_master_get_devdata(master);
- mcspi_dma = mcspi->dma_channels + spi->chip_select;
-
- if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX",
- omap2_mcspi_dma_rx_callback, spi,
- &mcspi_dma->dma_rx_channel)) {
- dev_err(&spi->dev, "no RX DMA channel for McSPI\n");
- return -EAGAIN;
- }
-
- if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX",
- omap2_mcspi_dma_tx_callback, spi,
- &mcspi_dma->dma_tx_channel)) {
- omap_free_dma(mcspi_dma->dma_rx_channel);
- mcspi_dma->dma_rx_channel = -1;
- dev_err(&spi->dev, "no TX DMA channel for McSPI\n");
- return -EAGAIN;
- }
-
- init_completion(&mcspi_dma->dma_rx_completion);
- init_completion(&mcspi_dma->dma_tx_completion);
-
- return 0;
-}
-
-static int omap2_mcspi_setup(struct spi_device *spi)
-{
- int ret;
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_dma *mcspi_dma;
- struct omap2_mcspi_cs *cs = spi->controller_state;
-
- if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
- dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
- spi->bits_per_word);
- return -EINVAL;
- }
-
- mcspi = spi_master_get_devdata(spi->master);
- mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
- if (!cs) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- cs->base = mcspi->base + spi->chip_select * 0x14;
- cs->phys = mcspi->phys + spi->chip_select * 0x14;
- cs->chconf0 = 0;
- spi->controller_state = cs;
- /* Link this to context save list */
- list_add_tail(&cs->node,
- &omap2_mcspi_ctx[mcspi->master->bus_num - 1].cs);
- }
-
- if (mcspi_dma->dma_rx_channel == -1
- || mcspi_dma->dma_tx_channel == -1) {
- ret = omap2_mcspi_request_dma(spi);
- if (ret < 0)
- return ret;
- }
-
- ret = omap2_mcspi_enable_clocks(mcspi);
- if (ret < 0)
- return ret;
-
- ret = omap2_mcspi_setup_transfer(spi, NULL);
- omap2_mcspi_disable_clocks(mcspi);
-
- return ret;
-}
-
-static void omap2_mcspi_cleanup(struct spi_device *spi)
-{
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_dma *mcspi_dma;
- struct omap2_mcspi_cs *cs;
-
- mcspi = spi_master_get_devdata(spi->master);
-
- if (spi->controller_state) {
- /* Unlink controller state from context save list */
- cs = spi->controller_state;
- list_del(&cs->node);
-
- kfree(spi->controller_state);
- }
-
- if (spi->chip_select < spi->master->num_chipselect) {
- mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
- if (mcspi_dma->dma_rx_channel != -1) {
- omap_free_dma(mcspi_dma->dma_rx_channel);
- mcspi_dma->dma_rx_channel = -1;
- }
- if (mcspi_dma->dma_tx_channel != -1) {
- omap_free_dma(mcspi_dma->dma_tx_channel);
- mcspi_dma->dma_tx_channel = -1;
- }
- }
-}
-
-static void omap2_mcspi_work(struct work_struct *work)
-{
- struct omap2_mcspi *mcspi;
-
- mcspi = container_of(work, struct omap2_mcspi, work);
-
- if (omap2_mcspi_enable_clocks(mcspi) < 0)
- return;
-
- spin_lock_irq(&mcspi->lock);
-
- /* We only enable one channel at a time -- the one whose message is
- * at the head of the queue -- although this controller would gladly
- * arbitrate among multiple channels. This corresponds to "single
- * channel" master mode. As a side effect, we need to manage the
- * chipselect with the FORCE bit ... CS != channel enable.
- */
- while (!list_empty(&mcspi->msg_queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
- int cs_active = 0;
- struct omap2_mcspi_cs *cs;
- struct omap2_mcspi_device_config *cd;
- int par_override = 0;
- int status = 0;
- u32 chconf;
-
- m = container_of(mcspi->msg_queue.next, struct spi_message,
- queue);
-
- list_del_init(&m->queue);
- spin_unlock_irq(&mcspi->lock);
-
- spi = m->spi;
- cs = spi->controller_state;
- cd = spi->controller_data;
-
- omap2_mcspi_set_enable(spi, 1);
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
- status = -EINVAL;
- break;
- }
- if (par_override || t->speed_hz || t->bits_per_word) {
- par_override = 1;
- status = omap2_mcspi_setup_transfer(spi, t);
- if (status < 0)
- break;
- if (!t->speed_hz && !t->bits_per_word)
- par_override = 0;
- }
-
- if (!cs_active) {
- omap2_mcspi_force_cs(spi, 1);
- cs_active = 1;
- }
-
- chconf = mcspi_cached_chconf0(spi);
- chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
- chconf &= ~OMAP2_MCSPI_CHCONF_TURBO;
-
- if (t->tx_buf == NULL)
- chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
- else if (t->rx_buf == NULL)
- chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
-
- if (cd && cd->turbo_mode && t->tx_buf == NULL) {
- /* Turbo mode is for more than one word */
- if (t->len > ((cs->word_len + 7) >> 3))
- chconf |= OMAP2_MCSPI_CHCONF_TURBO;
- }
-
- mcspi_write_chconf0(spi, chconf);
-
- if (t->len) {
- unsigned count;
-
- /* RX_ONLY mode needs dummy data in TX reg */
- if (t->tx_buf == NULL)
- __raw_writel(0, cs->base
- + OMAP2_MCSPI_TX0);
-
- if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
- count = omap2_mcspi_txrx_dma(spi, t);
- else
- count = omap2_mcspi_txrx_pio(spi, t);
- m->actual_length += count;
-
- if (count != t->len) {
- status = -EIO;
- break;
- }
- }
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- /* ignore the "leave it on after last xfer" hint */
- if (t->cs_change) {
- omap2_mcspi_force_cs(spi, 0);
- cs_active = 0;
- }
- }
-
- /* Restore defaults if they were overriden */
- if (par_override) {
- par_override = 0;
- status = omap2_mcspi_setup_transfer(spi, NULL);
- }
-
- if (cs_active)
- omap2_mcspi_force_cs(spi, 0);
-
- omap2_mcspi_set_enable(spi, 0);
-
- m->status = status;
- m->complete(m->context);
-
- spin_lock_irq(&mcspi->lock);
- }
-
- spin_unlock_irq(&mcspi->lock);
-
- omap2_mcspi_disable_clocks(mcspi);
-}
-
-static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct omap2_mcspi *mcspi;
- unsigned long flags;
- struct spi_transfer *t;
-
- m->actual_length = 0;
- m->status = 0;
-
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers) || !m->complete)
- return -EINVAL;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- const void *tx_buf = t->tx_buf;
- void *rx_buf = t->rx_buf;
- unsigned len = t->len;
-
- if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
- || (len && !(rx_buf || tx_buf))
- || (t->bits_per_word &&
- ( t->bits_per_word < 4
- || t->bits_per_word > 32))) {
- dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
- t->speed_hz,
- len,
- tx_buf ? "tx" : "",
- rx_buf ? "rx" : "",
- t->bits_per_word);
- return -EINVAL;
- }
- if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
- dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n",
- t->speed_hz,
- OMAP2_MCSPI_MAX_FREQ >> 15);
- return -EINVAL;
- }
-
- if (m->is_dma_mapped || len < DMA_MIN_BYTES)
- continue;
-
- if (tx_buf != NULL) {
- t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
- len, DMA_TO_DEVICE);
- if (dma_mapping_error(&spi->dev, t->tx_dma)) {
- dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
- 'T', len);
- return -EINVAL;
- }
- }
- if (rx_buf != NULL) {
- t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(&spi->dev, t->rx_dma)) {
- dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
- 'R', len);
- if (tx_buf != NULL)
- dma_unmap_single(&spi->dev, t->tx_dma,
- len, DMA_TO_DEVICE);
- return -EINVAL;
- }
- }
- }
-
- mcspi = spi_master_get_devdata(spi->master);
-
- spin_lock_irqsave(&mcspi->lock, flags);
- list_add_tail(&m->queue, &mcspi->msg_queue);
- queue_work(mcspi->wq, &mcspi->work);
- spin_unlock_irqrestore(&mcspi->lock, flags);
-
- return 0;
-}
-
-static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
-{
- struct spi_master *master = mcspi->master;
- u32 tmp;
- int ret = 0;
-
- ret = omap2_mcspi_enable_clocks(mcspi);
- if (ret < 0)
- return ret;
-
- tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
- mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
- omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp;
-
- omap2_mcspi_set_master_mode(master);
- omap2_mcspi_disable_clocks(mcspi);
- return 0;
-}
-
-static int omap_mcspi_runtime_resume(struct device *dev)
-{
- struct omap2_mcspi *mcspi;
- struct spi_master *master;
-
- master = dev_get_drvdata(dev);
- mcspi = spi_master_get_devdata(master);
- omap2_mcspi_restore_ctx(mcspi);
-
- return 0;
-}
-
-static struct omap2_mcspi_platform_config omap2_pdata = {
- .regs_offset = 0,
-};
-
-static struct omap2_mcspi_platform_config omap4_pdata = {
- .regs_offset = OMAP4_MCSPI_REG_OFFSET,
-};
-
-static const struct of_device_id omap_mcspi_of_match[] = {
- {
- .compatible = "ti,omap2-mcspi",
- .data = &omap2_pdata,
- },
- {
- .compatible = "ti,omap4-mcspi",
- .data = &omap4_pdata,
- },
- { },
-};
-MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
-
-static int __init omap2_mcspi_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct omap2_mcspi_platform_config *pdata;
- struct omap2_mcspi *mcspi;
- struct resource *r;
- int status = 0, i;
- char wq_name[20];
- u32 regs_offset = 0;
- static int bus_num = 1;
- struct device_node *node = pdev->dev.of_node;
- const struct of_device_id *match;
-
- master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
- if (master == NULL) {
- dev_dbg(&pdev->dev, "master allocation failed\n");
- return -ENOMEM;
- }
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- master->setup = omap2_mcspi_setup;
- master->transfer = omap2_mcspi_transfer;
- master->cleanup = omap2_mcspi_cleanup;
- master->dev.of_node = node;
-
- match = of_match_device(omap_mcspi_of_match, &pdev->dev);
- if (match) {
- u32 num_cs = 1; /* default number of chipselect */
- pdata = match->data;
-
- of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
- master->num_chipselect = num_cs;
- master->bus_num = bus_num++;
- } else {
- pdata = pdev->dev.platform_data;
- master->num_chipselect = pdata->num_cs;
- if (pdev->id != -1)
- master->bus_num = pdev->id;
- }
- regs_offset = pdata->regs_offset;
-
- dev_set_drvdata(&pdev->dev, master);
-
- mcspi = spi_master_get_devdata(master);
- mcspi->master = master;
-
- sprintf(wq_name, "omap2_mcspi/%d", master->bus_num);
- mcspi->wq = alloc_workqueue(wq_name, WQ_MEM_RECLAIM, 1);
- if (mcspi->wq == NULL) {
- status = -ENOMEM;
- goto free_master;
- }
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- status = -ENODEV;
- goto free_master;
- }
-
- r->start += regs_offset;
- r->end += regs_offset;
- mcspi->phys = r->start;
- if (!request_mem_region(r->start, resource_size(r),
- dev_name(&pdev->dev))) {
- status = -EBUSY;
- goto free_master;
- }
-
- mcspi->base = ioremap(r->start, resource_size(r));
- if (!mcspi->base) {
- dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
- status = -ENOMEM;
- goto release_region;
- }
-
- mcspi->dev = &pdev->dev;
- INIT_WORK(&mcspi->work, omap2_mcspi_work);
-
- spin_lock_init(&mcspi->lock);
- INIT_LIST_HEAD(&mcspi->msg_queue);
- INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs);
-
- mcspi->dma_channels = kcalloc(master->num_chipselect,
- sizeof(struct omap2_mcspi_dma),
- GFP_KERNEL);
-
- if (mcspi->dma_channels == NULL)
- goto unmap_io;
-
- for (i = 0; i < master->num_chipselect; i++) {
- char dma_ch_name[14];
- struct resource *dma_res;
-
- sprintf(dma_ch_name, "rx%d", i);
- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
- dma_ch_name);
- if (!dma_res) {
- dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
- status = -ENODEV;
- break;
- }
-
- mcspi->dma_channels[i].dma_rx_channel = -1;
- mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
- sprintf(dma_ch_name, "tx%d", i);
- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
- dma_ch_name);
- if (!dma_res) {
- dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
- status = -ENODEV;
- break;
- }
-
- mcspi->dma_channels[i].dma_tx_channel = -1;
- mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
- }
-
- if (status < 0)
- goto dma_chnl_free;
-
- pm_runtime_enable(&pdev->dev);
-
- if (status || omap2_mcspi_master_setup(mcspi) < 0)
- goto disable_pm;
-
- status = spi_register_master(master);
- if (status < 0)
- goto err_spi_register;
-
- return status;
-
-err_spi_register:
- spi_master_put(master);
-disable_pm:
- pm_runtime_disable(&pdev->dev);
-dma_chnl_free:
- kfree(mcspi->dma_channels);
-unmap_io:
- iounmap(mcspi->base);
-release_region:
- release_mem_region(r->start, resource_size(r));
-free_master:
- kfree(master);
- platform_set_drvdata(pdev, NULL);
- return status;
-}
-
-static int __exit omap2_mcspi_remove(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct omap2_mcspi *mcspi;
- struct omap2_mcspi_dma *dma_channels;
- struct resource *r;
- void __iomem *base;
-
- master = dev_get_drvdata(&pdev->dev);
- mcspi = spi_master_get_devdata(master);
- dma_channels = mcspi->dma_channels;
-
- omap2_mcspi_disable_clocks(mcspi);
- pm_runtime_disable(&pdev->dev);
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, resource_size(r));
-
- base = mcspi->base;
- spi_unregister_master(master);
- iounmap(base);
- kfree(dma_channels);
- destroy_workqueue(mcspi->wq);
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:omap2_mcspi");
-
-#ifdef CONFIG_SUSPEND
-/*
- * When SPI wake up from off-mode, CS is in activate state. If it was in
- * unactive state when driver was suspend, then force it to unactive state at
- * wake up.
- */
-static int omap2_mcspi_resume(struct device *dev)
-{
- struct spi_master *master = dev_get_drvdata(dev);
- struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
- struct omap2_mcspi_cs *cs;
-
- omap2_mcspi_enable_clocks(mcspi);
- list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
- node) {
- if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
-
- /*
- * We need to toggle CS state for OMAP take this
- * change in account.
- */
- MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
- __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
- MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
- __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
- }
- }
- omap2_mcspi_disable_clocks(mcspi);
- return 0;
-}
-#else
-#define omap2_mcspi_resume NULL
-#endif
-
-static const struct dev_pm_ops omap2_mcspi_pm_ops = {
- .resume = omap2_mcspi_resume,
- .runtime_resume = omap_mcspi_runtime_resume,
-};
-
-static struct platform_driver omap2_mcspi_driver = {
- .driver = {
- .name = "omap2_mcspi",
- .owner = THIS_MODULE,
- .pm = &omap2_mcspi_pm_ops,
- .of_match_table = omap_mcspi_of_match,
- },
- .remove = __exit_p(omap2_mcspi_remove),
-};
-
-
-static int __init omap2_mcspi_init(void)
-{
- return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
-}
-subsys_initcall(omap2_mcspi_init);
-
-static void __exit omap2_mcspi_exit(void)
-{
- platform_driver_unregister(&omap2_mcspi_driver);
-
-}
-module_exit(omap2_mcspi_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-orion.c b/ANDROID_3.4.5/drivers/spi/spi-orion.c
deleted file mode 100644
index e496f799..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-orion.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * Marvell Orion SPI controller driver
- *
- * Author: Shadi Ammouri <shadi@marvell.com>
- * Copyright (C) 2007-2008 Marvell Ltd.
- *
- * 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/orion_spi.h>
-#include <linux/module.h>
-#include <asm/unaligned.h>
-
-#define DRIVER_NAME "orion_spi"
-
-#define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/
-#define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
-
-#define ORION_SPI_IF_CTRL_REG 0x00
-#define ORION_SPI_IF_CONFIG_REG 0x04
-#define ORION_SPI_DATA_OUT_REG 0x08
-#define ORION_SPI_DATA_IN_REG 0x0c
-#define ORION_SPI_INT_CAUSE_REG 0x10
-
-#define ORION_SPI_IF_8_16_BIT_MODE (1 << 5)
-#define ORION_SPI_CLK_PRESCALE_MASK 0x1F
-
-struct orion_spi {
- struct work_struct work;
-
- /* Lock access to transfer list. */
- spinlock_t lock;
-
- struct list_head msg_queue;
- struct spi_master *master;
- void __iomem *base;
- unsigned int max_speed;
- unsigned int min_speed;
- struct orion_spi_info *spi_info;
-};
-
-static struct workqueue_struct *orion_spi_wq;
-
-static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
-{
- return orion_spi->base + reg;
-}
-
-static inline void
-orion_spi_setbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
-{
- void __iomem *reg_addr = spi_reg(orion_spi, reg);
- u32 val;
-
- val = readl(reg_addr);
- val |= mask;
- writel(val, reg_addr);
-}
-
-static inline void
-orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
-{
- void __iomem *reg_addr = spi_reg(orion_spi, reg);
- u32 val;
-
- val = readl(reg_addr);
- val &= ~mask;
- writel(val, reg_addr);
-}
-
-static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
-{
- if (size == 16) {
- orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
- ORION_SPI_IF_8_16_BIT_MODE);
- } else if (size == 8) {
- orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
- ORION_SPI_IF_8_16_BIT_MODE);
- } else {
- pr_debug("Bad bits per word value %d (only 8 or 16 are "
- "allowed).\n", size);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
-{
- u32 tclk_hz;
- u32 rate;
- u32 prescale;
- u32 reg;
- struct orion_spi *orion_spi;
-
- orion_spi = spi_master_get_devdata(spi->master);
-
- tclk_hz = orion_spi->spi_info->tclk;
-
- /*
- * the supported rates are: 4,6,8...30
- * round up as we look for equal or less speed
- */
- rate = DIV_ROUND_UP(tclk_hz, speed);
- rate = roundup(rate, 2);
-
- /* check if requested speed is too small */
- if (rate > 30)
- return -EINVAL;
-
- if (rate < 4)
- rate = 4;
-
- /* Convert the rate to SPI clock divisor value. */
- prescale = 0x10 + rate/2;
-
- reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
- reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale);
- writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
-
- return 0;
-}
-
-/*
- * called only when no transfer is active on the bus
- */
-static int
-orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct orion_spi *orion_spi;
- unsigned int speed = spi->max_speed_hz;
- unsigned int bits_per_word = spi->bits_per_word;
- int rc;
-
- orion_spi = spi_master_get_devdata(spi->master);
-
- if ((t != NULL) && t->speed_hz)
- speed = t->speed_hz;
-
- if ((t != NULL) && t->bits_per_word)
- bits_per_word = t->bits_per_word;
-
- rc = orion_spi_baudrate_set(spi, speed);
- if (rc)
- return rc;
-
- return orion_spi_set_transfer_size(orion_spi, bits_per_word);
-}
-
-static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
-{
- if (enable)
- orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
- else
- orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
-}
-
-static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
-{
- int i;
-
- for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) {
- if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)))
- return 1;
- else
- udelay(1);
- }
-
- return -1;
-}
-
-static inline int
-orion_spi_write_read_8bit(struct spi_device *spi,
- const u8 **tx_buf, u8 **rx_buf)
-{
- void __iomem *tx_reg, *rx_reg, *int_reg;
- struct orion_spi *orion_spi;
-
- orion_spi = spi_master_get_devdata(spi->master);
- tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
- rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
- int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
-
- /* clear the interrupt cause register */
- writel(0x0, int_reg);
-
- if (tx_buf && *tx_buf)
- writel(*(*tx_buf)++, tx_reg);
- else
- writel(0, tx_reg);
-
- if (orion_spi_wait_till_ready(orion_spi) < 0) {
- dev_err(&spi->dev, "TXS timed out\n");
- return -1;
- }
-
- if (rx_buf && *rx_buf)
- *(*rx_buf)++ = readl(rx_reg);
-
- return 1;
-}
-
-static inline int
-orion_spi_write_read_16bit(struct spi_device *spi,
- const u16 **tx_buf, u16 **rx_buf)
-{
- void __iomem *tx_reg, *rx_reg, *int_reg;
- struct orion_spi *orion_spi;
-
- orion_spi = spi_master_get_devdata(spi->master);
- tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
- rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
- int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
-
- /* clear the interrupt cause register */
- writel(0x0, int_reg);
-
- if (tx_buf && *tx_buf)
- writel(__cpu_to_le16(get_unaligned((*tx_buf)++)), tx_reg);
- else
- writel(0, tx_reg);
-
- if (orion_spi_wait_till_ready(orion_spi) < 0) {
- dev_err(&spi->dev, "TXS timed out\n");
- return -1;
- }
-
- if (rx_buf && *rx_buf)
- put_unaligned(__le16_to_cpu(readl(rx_reg)), (*rx_buf)++);
-
- return 1;
-}
-
-static unsigned int
-orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
-{
- struct orion_spi *orion_spi;
- unsigned int count;
- int word_len;
-
- orion_spi = spi_master_get_devdata(spi->master);
- word_len = spi->bits_per_word;
- count = xfer->len;
-
- if (word_len == 8) {
- const u8 *tx = xfer->tx_buf;
- u8 *rx = xfer->rx_buf;
-
- do {
- if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0)
- goto out;
- count--;
- } while (count);
- } else if (word_len == 16) {
- const u16 *tx = xfer->tx_buf;
- u16 *rx = xfer->rx_buf;
-
- do {
- if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0)
- goto out;
- count -= 2;
- } while (count);
- }
-
-out:
- return xfer->len - count;
-}
-
-
-static void orion_spi_work(struct work_struct *work)
-{
- struct orion_spi *orion_spi =
- container_of(work, struct orion_spi, work);
-
- spin_lock_irq(&orion_spi->lock);
- while (!list_empty(&orion_spi->msg_queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
- int par_override = 0;
- int status = 0;
- int cs_active = 0;
-
- m = container_of(orion_spi->msg_queue.next, struct spi_message,
- queue);
-
- list_del_init(&m->queue);
- spin_unlock_irq(&orion_spi->lock);
-
- spi = m->spi;
-
- /* Load defaults */
- status = orion_spi_setup_transfer(spi, NULL);
-
- if (status < 0)
- goto msg_done;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (par_override || t->speed_hz || t->bits_per_word) {
- par_override = 1;
- status = orion_spi_setup_transfer(spi, t);
- if (status < 0)
- break;
- if (!t->speed_hz && !t->bits_per_word)
- par_override = 0;
- }
-
- if (!cs_active) {
- orion_spi_set_cs(orion_spi, 1);
- cs_active = 1;
- }
-
- if (t->len)
- m->actual_length +=
- orion_spi_write_read(spi, t);
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (t->cs_change) {
- orion_spi_set_cs(orion_spi, 0);
- cs_active = 0;
- }
- }
-
-msg_done:
- if (cs_active)
- orion_spi_set_cs(orion_spi, 0);
-
- m->status = status;
- m->complete(m->context);
-
- spin_lock_irq(&orion_spi->lock);
- }
-
- spin_unlock_irq(&orion_spi->lock);
-}
-
-static int __init orion_spi_reset(struct orion_spi *orion_spi)
-{
- /* Verify that the CS is deasserted */
- orion_spi_set_cs(orion_spi, 0);
-
- return 0;
-}
-
-static int orion_spi_setup(struct spi_device *spi)
-{
- struct orion_spi *orion_spi;
-
- orion_spi = spi_master_get_devdata(spi->master);
-
- if ((spi->max_speed_hz == 0)
- || (spi->max_speed_hz > orion_spi->max_speed))
- spi->max_speed_hz = orion_spi->max_speed;
-
- if (spi->max_speed_hz < orion_spi->min_speed) {
- dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
- spi->max_speed_hz);
- return -EINVAL;
- }
-
- /*
- * baudrate & width will be set orion_spi_setup_transfer
- */
- return 0;
-}
-
-static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct orion_spi *orion_spi;
- struct spi_transfer *t = NULL;
- unsigned long flags;
-
- m->actual_length = 0;
- m->status = 0;
-
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers) || !m->complete)
- return -EINVAL;
-
- orion_spi = spi_master_get_devdata(spi->master);
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- unsigned int bits_per_word = spi->bits_per_word;
-
- if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
- dev_err(&spi->dev,
- "message rejected : "
- "invalid transfer data buffers\n");
- goto msg_rejected;
- }
-
- if (t->bits_per_word)
- bits_per_word = t->bits_per_word;
-
- if ((bits_per_word != 8) && (bits_per_word != 16)) {
- dev_err(&spi->dev,
- "message rejected : "
- "invalid transfer bits_per_word (%d bits)\n",
- bits_per_word);
- goto msg_rejected;
- }
- /*make sure buffer length is even when working in 16 bit mode*/
- if ((t->bits_per_word == 16) && (t->len & 1)) {
- dev_err(&spi->dev,
- "message rejected : "
- "odd data length (%d) while in 16 bit mode\n",
- t->len);
- goto msg_rejected;
- }
-
- if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
- dev_err(&spi->dev,
- "message rejected : "
- "device min speed (%d Hz) exceeds "
- "required transfer speed (%d Hz)\n",
- orion_spi->min_speed, t->speed_hz);
- goto msg_rejected;
- }
- }
-
-
- spin_lock_irqsave(&orion_spi->lock, flags);
- list_add_tail(&m->queue, &orion_spi->msg_queue);
- queue_work(orion_spi_wq, &orion_spi->work);
- spin_unlock_irqrestore(&orion_spi->lock, flags);
-
- return 0;
-msg_rejected:
- /* Message rejected and not queued */
- m->status = -EINVAL;
- if (m->complete)
- m->complete(m->context);
- return -EINVAL;
-}
-
-static int __init orion_spi_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct orion_spi *spi;
- struct resource *r;
- struct orion_spi_info *spi_info;
- int status = 0;
-
- spi_info = pdev->dev.platform_data;
-
- master = spi_alloc_master(&pdev->dev, sizeof *spi);
- if (master == NULL) {
- dev_dbg(&pdev->dev, "master allocation failed\n");
- return -ENOMEM;
- }
-
- if (pdev->id != -1)
- master->bus_num = pdev->id;
-
- /* we support only mode 0, and no options */
- master->mode_bits = 0;
-
- master->setup = orion_spi_setup;
- master->transfer = orion_spi_transfer;
- master->num_chipselect = ORION_NUM_CHIPSELECTS;
-
- dev_set_drvdata(&pdev->dev, master);
-
- spi = spi_master_get_devdata(master);
- spi->master = master;
- spi->spi_info = spi_info;
-
- spi->max_speed = DIV_ROUND_UP(spi_info->tclk, 4);
- spi->min_speed = DIV_ROUND_UP(spi_info->tclk, 30);
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- status = -ENODEV;
- goto out;
- }
-
- if (!request_mem_region(r->start, resource_size(r),
- dev_name(&pdev->dev))) {
- status = -EBUSY;
- goto out;
- }
- spi->base = ioremap(r->start, SZ_1K);
-
- INIT_WORK(&spi->work, orion_spi_work);
-
- spin_lock_init(&spi->lock);
- INIT_LIST_HEAD(&spi->msg_queue);
-
- if (orion_spi_reset(spi) < 0)
- goto out_rel_mem;
-
- status = spi_register_master(master);
- if (status < 0)
- goto out_rel_mem;
-
- return status;
-
-out_rel_mem:
- release_mem_region(r->start, resource_size(r));
-
-out:
- spi_master_put(master);
- return status;
-}
-
-
-static int __exit orion_spi_remove(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct orion_spi *spi;
- struct resource *r;
-
- master = dev_get_drvdata(&pdev->dev);
- spi = spi_master_get_devdata(master);
-
- cancel_work_sync(&spi->work);
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, resource_size(r));
-
- spi_unregister_master(master);
-
- return 0;
-}
-
-MODULE_ALIAS("platform:" DRIVER_NAME);
-
-static struct platform_driver orion_spi_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(orion_spi_remove),
-};
-
-static int __init orion_spi_init(void)
-{
- orion_spi_wq = create_singlethread_workqueue(
- orion_spi_driver.driver.name);
- if (orion_spi_wq == NULL)
- return -ENOMEM;
-
- return platform_driver_probe(&orion_spi_driver, orion_spi_probe);
-}
-module_init(orion_spi_init);
-
-static void __exit orion_spi_exit(void)
-{
- flush_workqueue(orion_spi_wq);
- platform_driver_unregister(&orion_spi_driver);
-
- destroy_workqueue(orion_spi_wq);
-}
-module_exit(orion_spi_exit);
-
-MODULE_DESCRIPTION("Orion SPI driver");
-MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-pl022.c b/ANDROID_3.4.5/drivers/spi/spi-pl022.c
deleted file mode 100644
index 400ae212..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-pl022.c
+++ /dev/null
@@ -1,2328 +0,0 @@
-/*
- * A driver for the ARM PL022 PrimeCell SSP/SPI bus master.
- *
- * Copyright (C) 2008-2009 ST-Ericsson AB
- * Copyright (C) 2006 STMicroelectronics Pvt. Ltd.
- *
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- *
- * Initial version inspired by:
- * linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c
- * Initial adoption to PL022 by:
- * Sachin Verma <sachin.verma@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl022.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#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.
- * reg is masked with mask, the OR:ed with an (again masked)
- * val shifted sb steps to the left.
- */
-#define SSP_WRITE_BITS(reg, val, mask, sb) \
- ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask))))
-
-/*
- * This macro is also used to define some default values.
- * It will just shift val by sb steps to the left and mask
- * the result with mask.
- */
-#define GEN_MASK_BITS(val, mask, sb) \
- (((val)<<(sb)) & (mask))
-
-#define DRIVE_TX 0
-#define DO_NOT_DRIVE_TX 1
-
-#define DO_NOT_QUEUE_DMA 0
-#define QUEUE_DMA 1
-
-#define RX_TRANSFER 1
-#define TX_TRANSFER 2
-
-/*
- * Macros to access SSP Registers with their offsets
- */
-#define SSP_CR0(r) (r + 0x000)
-#define SSP_CR1(r) (r + 0x004)
-#define SSP_DR(r) (r + 0x008)
-#define SSP_SR(r) (r + 0x00C)
-#define SSP_CPSR(r) (r + 0x010)
-#define SSP_IMSC(r) (r + 0x014)
-#define SSP_RIS(r) (r + 0x018)
-#define SSP_MIS(r) (r + 0x01C)
-#define SSP_ICR(r) (r + 0x020)
-#define SSP_DMACR(r) (r + 0x024)
-#define SSP_ITCR(r) (r + 0x080)
-#define SSP_ITIP(r) (r + 0x084)
-#define SSP_ITOP(r) (r + 0x088)
-#define SSP_TDR(r) (r + 0x08C)
-
-#define SSP_PID0(r) (r + 0xFE0)
-#define SSP_PID1(r) (r + 0xFE4)
-#define SSP_PID2(r) (r + 0xFE8)
-#define SSP_PID3(r) (r + 0xFEC)
-
-#define SSP_CID0(r) (r + 0xFF0)
-#define SSP_CID1(r) (r + 0xFF4)
-#define SSP_CID2(r) (r + 0xFF8)
-#define SSP_CID3(r) (r + 0xFFC)
-
-/*
- * SSP Control Register 0 - SSP_CR0
- */
-#define SSP_CR0_MASK_DSS (0x0FUL << 0)
-#define SSP_CR0_MASK_FRF (0x3UL << 4)
-#define SSP_CR0_MASK_SPO (0x1UL << 6)
-#define SSP_CR0_MASK_SPH (0x1UL << 7)
-#define SSP_CR0_MASK_SCR (0xFFUL << 8)
-
-/*
- * The ST version of this block moves som bits
- * in SSP_CR0 and extends it to 32 bits
- */
-#define SSP_CR0_MASK_DSS_ST (0x1FUL << 0)
-#define SSP_CR0_MASK_HALFDUP_ST (0x1UL << 5)
-#define SSP_CR0_MASK_CSS_ST (0x1FUL << 16)
-#define SSP_CR0_MASK_FRF_ST (0x3UL << 21)
-
-/*
- * SSP Control Register 0 - SSP_CR1
- */
-#define SSP_CR1_MASK_LBM (0x1UL << 0)
-#define SSP_CR1_MASK_SSE (0x1UL << 1)
-#define SSP_CR1_MASK_MS (0x1UL << 2)
-#define SSP_CR1_MASK_SOD (0x1UL << 3)
-
-/*
- * The ST version of this block adds some bits
- * in SSP_CR1
- */
-#define SSP_CR1_MASK_RENDN_ST (0x1UL << 4)
-#define SSP_CR1_MASK_TENDN_ST (0x1UL << 5)
-#define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6)
-#define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7)
-#define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10)
-/* This one is only in the PL023 variant */
-#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
-
-/*
- * SSP Status Register - SSP_SR
- */
-#define SSP_SR_MASK_TFE (0x1UL << 0) /* Transmit FIFO empty */
-#define SSP_SR_MASK_TNF (0x1UL << 1) /* Transmit FIFO not full */
-#define SSP_SR_MASK_RNE (0x1UL << 2) /* Receive FIFO not empty */
-#define SSP_SR_MASK_RFF (0x1UL << 3) /* Receive FIFO full */
-#define SSP_SR_MASK_BSY (0x1UL << 4) /* Busy Flag */
-
-/*
- * SSP Clock Prescale Register - SSP_CPSR
- */
-#define SSP_CPSR_MASK_CPSDVSR (0xFFUL << 0)
-
-/*
- * SSP Interrupt Mask Set/Clear Register - SSP_IMSC
- */
-#define SSP_IMSC_MASK_RORIM (0x1UL << 0) /* Receive Overrun Interrupt mask */
-#define SSP_IMSC_MASK_RTIM (0x1UL << 1) /* Receive timeout Interrupt mask */
-#define SSP_IMSC_MASK_RXIM (0x1UL << 2) /* Receive FIFO Interrupt mask */
-#define SSP_IMSC_MASK_TXIM (0x1UL << 3) /* Transmit FIFO Interrupt mask */
-
-/*
- * SSP Raw Interrupt Status Register - SSP_RIS
- */
-/* Receive Overrun Raw Interrupt status */
-#define SSP_RIS_MASK_RORRIS (0x1UL << 0)
-/* Receive Timeout Raw Interrupt status */
-#define SSP_RIS_MASK_RTRIS (0x1UL << 1)
-/* Receive FIFO Raw Interrupt status */
-#define SSP_RIS_MASK_RXRIS (0x1UL << 2)
-/* Transmit FIFO Raw Interrupt status */
-#define SSP_RIS_MASK_TXRIS (0x1UL << 3)
-
-/*
- * SSP Masked Interrupt Status Register - SSP_MIS
- */
-/* Receive Overrun Masked Interrupt status */
-#define SSP_MIS_MASK_RORMIS (0x1UL << 0)
-/* Receive Timeout Masked Interrupt status */
-#define SSP_MIS_MASK_RTMIS (0x1UL << 1)
-/* Receive FIFO Masked Interrupt status */
-#define SSP_MIS_MASK_RXMIS (0x1UL << 2)
-/* Transmit FIFO Masked Interrupt status */
-#define SSP_MIS_MASK_TXMIS (0x1UL << 3)
-
-/*
- * SSP Interrupt Clear Register - SSP_ICR
- */
-/* Receive Overrun Raw Clear Interrupt bit */
-#define SSP_ICR_MASK_RORIC (0x1UL << 0)
-/* Receive Timeout Clear Interrupt bit */
-#define SSP_ICR_MASK_RTIC (0x1UL << 1)
-
-/*
- * SSP DMA Control Register - SSP_DMACR
- */
-/* Receive DMA Enable bit */
-#define SSP_DMACR_MASK_RXDMAE (0x1UL << 0)
-/* Transmit DMA Enable bit */
-#define SSP_DMACR_MASK_TXDMAE (0x1UL << 1)
-
-/*
- * SSP Integration Test control Register - SSP_ITCR
- */
-#define SSP_ITCR_MASK_ITEN (0x1UL << 0)
-#define SSP_ITCR_MASK_TESTFIFO (0x1UL << 1)
-
-/*
- * SSP Integration Test Input Register - SSP_ITIP
- */
-#define ITIP_MASK_SSPRXD (0x1UL << 0)
-#define ITIP_MASK_SSPFSSIN (0x1UL << 1)
-#define ITIP_MASK_SSPCLKIN (0x1UL << 2)
-#define ITIP_MASK_RXDMAC (0x1UL << 3)
-#define ITIP_MASK_TXDMAC (0x1UL << 4)
-#define ITIP_MASK_SSPTXDIN (0x1UL << 5)
-
-/*
- * SSP Integration Test output Register - SSP_ITOP
- */
-#define ITOP_MASK_SSPTXD (0x1UL << 0)
-#define ITOP_MASK_SSPFSSOUT (0x1UL << 1)
-#define ITOP_MASK_SSPCLKOUT (0x1UL << 2)
-#define ITOP_MASK_SSPOEn (0x1UL << 3)
-#define ITOP_MASK_SSPCTLOEn (0x1UL << 4)
-#define ITOP_MASK_RORINTR (0x1UL << 5)
-#define ITOP_MASK_RTINTR (0x1UL << 6)
-#define ITOP_MASK_RXINTR (0x1UL << 7)
-#define ITOP_MASK_TXINTR (0x1UL << 8)
-#define ITOP_MASK_INTR (0x1UL << 9)
-#define ITOP_MASK_RXDMABREQ (0x1UL << 10)
-#define ITOP_MASK_RXDMASREQ (0x1UL << 11)
-#define ITOP_MASK_TXDMABREQ (0x1UL << 12)
-#define ITOP_MASK_TXDMASREQ (0x1UL << 13)
-
-/*
- * SSP Test Data Register - SSP_TDR
- */
-#define TDR_MASK_TESTDATA (0xFFFFFFFF)
-
-/*
- * Message State
- * we use the spi_message.state (void *) pointer to
- * hold a single state value, that's why all this
- * (void *) casting is done here.
- */
-#define STATE_START ((void *) 0)
-#define STATE_RUNNING ((void *) 1)
-#define STATE_DONE ((void *) 2)
-#define STATE_ERROR ((void *) -1)
-
-/*
- * SSP State - Whether Enabled or Disabled
- */
-#define SSP_DISABLED (0)
-#define SSP_ENABLED (1)
-
-/*
- * SSP DMA State - Whether DMA Enabled or Disabled
- */
-#define SSP_DMA_DISABLED (0)
-#define SSP_DMA_ENABLED (1)
-
-/*
- * SSP Clock Defaults
- */
-#define SSP_DEFAULT_CLKRATE 0x2
-#define SSP_DEFAULT_PRESCALE 0x40
-
-/*
- * SSP Clock Parameter ranges
- */
-#define CPSDVR_MIN 0x02
-#define CPSDVR_MAX 0xFE
-#define SCR_MIN 0x00
-#define SCR_MAX 0xFF
-
-/*
- * SSP Interrupt related Macros
- */
-#define DEFAULT_SSP_REG_IMSC 0x0UL
-#define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC
-#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC)
-
-#define CLEAR_ALL_INTERRUPTS 0x3
-
-#define SPI_POLLING_TIMEOUT 1000
-
-/*
- * The type of reading going on on this chip
- */
-enum ssp_reading {
- READING_NULL,
- READING_U8,
- READING_U16,
- READING_U32
-};
-
-/**
- * The type of writing going on on this chip
- */
-enum ssp_writing {
- WRITING_NULL,
- WRITING_U8,
- WRITING_U16,
- WRITING_U32
-};
-
-/**
- * struct vendor_data - vendor-specific config parameters
- * for PL022 derivates
- * @fifodepth: depth of FIFOs (both)
- * @max_bpw: maximum number of bits per word
- * @unidir: supports unidirection transfers
- * @extended_cr: 32 bit wide control register 0 with extra
- * features and extra features in CR1 as found in the ST variants
- * @pl023: supports a subset of the ST extensions called "PL023"
- */
-struct vendor_data {
- int fifodepth;
- int max_bpw;
- bool unidir;
- bool extended_cr;
- bool pl023;
- bool loopback;
-};
-
-/**
- * struct pl022 - This is the private SSP driver data structure
- * @adev: AMBA device model hookup
- * @vendor: vendor data for the IP block
- * @phybase: the physical memory where the SSP device resides
- * @virtbase: the virtual memory where the SSP is mapped
- * @clk: outgoing clock "SPICLK" for the SPI bus
- * @master: SPI framework hookup
- * @master_info: controller-specific data from machine setup
- * @kworker: thread struct for message pump
- * @kworker_task: pointer to task for message pump kworker thread
- * @pump_messages: work struct for scheduling work to the message pump
- * @queue_lock: spinlock to syncronise access to message queue
- * @queue: message queue
- * @busy: message pump is busy
- * @running: message pump is running
- * @pump_transfers: Tasklet used in Interrupt Transfer mode
- * @cur_msg: Pointer to current spi_message being processed
- * @cur_transfer: Pointer to current spi_transfer
- * @cur_chip: pointer to current clients chip(assigned from controller_state)
- * @next_msg_cs_active: the next message in the queue has been examined
- * and it was found that it uses the same chip select as the previous
- * message, so we left it active after the previous transfer, and it's
- * active already.
- * @tx: current position in TX buffer to be read
- * @tx_end: end position in TX buffer to be read
- * @rx: current position in RX buffer to be written
- * @rx_end: end position in RX buffer to be written
- * @read: the type of read currently going on
- * @write: the type of write currently going on
- * @exp_fifo_level: expected FIFO level
- * @dma_rx_channel: optional channel for RX DMA
- * @dma_tx_channel: optional channel for TX DMA
- * @sgt_rx: scattertable for the RX transfer
- * @sgt_tx: scattertable for the TX transfer
- * @dummypage: a dummy page used for driving data on the bus with DMA
- */
-struct pl022 {
- struct amba_device *adev;
- struct vendor_data *vendor;
- resource_size_t phybase;
- void __iomem *virtbase;
- struct clk *clk;
- struct spi_master *master;
- struct pl022_ssp_controller *master_info;
- /* Message per-transfer pump */
- struct tasklet_struct pump_transfers;
- struct spi_message *cur_msg;
- struct spi_transfer *cur_transfer;
- struct chip_data *cur_chip;
- bool next_msg_cs_active;
- void *tx;
- void *tx_end;
- void *rx;
- void *rx_end;
- 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;
- struct dma_chan *dma_tx_channel;
- struct sg_table sgt_rx;
- struct sg_table sgt_tx;
- char *dummypage;
- bool dma_running;
-#endif
-};
-
-/**
- * struct chip_data - To maintain runtime state of SSP for each client chip
- * @cr0: Value of control register CR0 of SSP - on later ST variants this
- * register is 32 bits wide rather than just 16
- * @cr1: Value of control register CR1 of SSP
- * @dmacr: Value of DMA control Register of SSP
- * @cpsr: Value of Clock prescale register
- * @n_bytes: how many bytes(power of 2) reqd for a given data width of client
- * @enable_dma: Whether to enable DMA or not
- * @read: function ptr to be used to read when doing xfer for this chip
- * @write: function ptr to be used to write when doing xfer for this chip
- * @cs_control: chip select callback provided by chip
- * @xfer_type: polling/interrupt/DMA
- *
- * Runtime state of the SSP controller, maintained per chip,
- * This would be set according to the current message that would be served
- */
-struct chip_data {
- u32 cr0;
- u16 cr1;
- u16 dmacr;
- u16 cpsr;
- u8 n_bytes;
- bool enable_dma;
- enum ssp_reading read;
- enum ssp_writing write;
- void (*cs_control) (u32 command);
- int xfer_type;
-};
-
-/**
- * null_cs_control - Dummy chip select function
- * @command: select/delect the chip
- *
- * If no chip select function is provided by client this is used as dummy
- * chip select
- */
-static void null_cs_control(u32 command)
-{
- pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
-}
-
-/**
- * giveback - current spi_message is over, schedule next message and call
- * callback of this message. Assumes that caller already
- * set message->status; dma and pio irqs are blocked
- * @pl022: SSP driver private data structure
- */
-static void giveback(struct pl022 *pl022)
-{
- struct spi_transfer *last_transfer;
- pl022->next_msg_cs_active = false;
-
- last_transfer = list_entry(pl022->cur_msg->transfers.prev,
- struct spi_transfer,
- transfer_list);
-
- /* Delay if requested before any change in chip select */
- if (last_transfer->delay_usecs)
- /*
- * FIXME: This runs in interrupt context.
- * Is this really smart?
- */
- udelay(last_transfer->delay_usecs);
-
- if (!last_transfer->cs_change) {
- struct spi_message *next_msg;
-
- /*
- * cs_change was not set. We can keep the chip select
- * enabled if there is message in the queue and it is
- * for the same spi device.
- *
- * We cannot postpone this until pump_messages, because
- * after calling msg->complete (below) the driver that
- * sent the current message could be unloaded, which
- * could invalidate the cs_control() callback...
- */
- /* get a pointer to the next message, if any */
- next_msg = spi_get_next_queued_message(pl022->master);
-
- /*
- * see if the next and current messages point
- * to the same spi device.
- */
- if (next_msg && next_msg->spi != pl022->cur_msg->spi)
- next_msg = NULL;
- if (!next_msg || pl022->cur_msg->state == STATE_ERROR)
- pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
- else
- pl022->next_msg_cs_active = true;
-
- }
-
- pl022->cur_msg = NULL;
- pl022->cur_transfer = NULL;
- pl022->cur_chip = NULL;
- spi_finalize_current_message(pl022->master);
-}
-
-/**
- * flush - flush the FIFO to reach a clean state
- * @pl022: SSP driver private data structure
- */
-static int flush(struct pl022 *pl022)
-{
- unsigned long limit = loops_per_jiffy << 1;
-
- dev_dbg(&pl022->adev->dev, "flush\n");
- do {
- while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
- readw(SSP_DR(pl022->virtbase));
- } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--);
-
- pl022->exp_fifo_level = 0;
-
- return limit;
-}
-
-/**
- * restore_state - Load configuration of current chip
- * @pl022: SSP driver private data structure
- */
-static void restore_state(struct pl022 *pl022)
-{
- struct chip_data *chip = pl022->cur_chip;
-
- if (pl022->vendor->extended_cr)
- writel(chip->cr0, SSP_CR0(pl022->virtbase));
- else
- writew(chip->cr0, SSP_CR0(pl022->virtbase));
- writew(chip->cr1, SSP_CR1(pl022->virtbase));
- writew(chip->dmacr, SSP_DMACR(pl022->virtbase));
- writew(chip->cpsr, SSP_CPSR(pl022->virtbase));
- writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
- writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
-}
-
-/*
- * Default SSP Register Values
- */
-#define DEFAULT_SSP_REG_CR0 ( \
- GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS, 0) | \
- GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF, 4) | \
- GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
- GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
- GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
-)
-
-/* ST versions have slightly different bit layout */
-#define DEFAULT_SSP_REG_CR0_ST ( \
- GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0) | \
- GEN_MASK_BITS(SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, SSP_CR0_MASK_HALFDUP_ST, 5) | \
- GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
- GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
- GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) | \
- GEN_MASK_BITS(SSP_BITS_8, SSP_CR0_MASK_CSS_ST, 16) | \
- GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \
-)
-
-/* The PL023 version is slightly different again */
-#define DEFAULT_SSP_REG_CR0_ST_PL023 ( \
- GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0) | \
- GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
- GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
- GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
-)
-
-#define DEFAULT_SSP_REG_CR1 ( \
- GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \
- GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
- GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
- GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) \
-)
-
-/* ST versions extend this register to use all 16 bits */
-#define DEFAULT_SSP_REG_CR1_ST ( \
- DEFAULT_SSP_REG_CR1 | \
- GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
- GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
- GEN_MASK_BITS(SSP_MWIRE_WAIT_ZERO, SSP_CR1_MASK_MWAIT_ST, 6) |\
- GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
- GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \
-)
-
-/*
- * The PL023 variant has further differences: no loopback mode, no microwire
- * support, and a new clock feedback delay setting.
- */
-#define DEFAULT_SSP_REG_CR1_ST_PL023 ( \
- GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
- GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
- GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \
- GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
- GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
- GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
- GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) | \
- GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \
-)
-
-#define DEFAULT_SSP_REG_CPSR ( \
- GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
-)
-
-#define DEFAULT_SSP_REG_DMACR (\
- GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_RXDMAE, 0) | \
- GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \
-)
-
-/**
- * load_ssp_default_config - Load default configuration for SSP
- * @pl022: SSP driver private data structure
- */
-static void load_ssp_default_config(struct pl022 *pl022)
-{
- if (pl022->vendor->pl023) {
- writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase));
- writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase));
- } else if (pl022->vendor->extended_cr) {
- writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
- writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
- } else {
- writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
- writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase));
- }
- writew(DEFAULT_SSP_REG_DMACR, SSP_DMACR(pl022->virtbase));
- writew(DEFAULT_SSP_REG_CPSR, SSP_CPSR(pl022->virtbase));
- writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
- writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
-}
-
-/**
- * This will write to TX and read from RX according to the parameters
- * set in pl022.
- */
-static void readwriter(struct pl022 *pl022)
-{
-
- /*
- * The FIFO depth is different between primecell variants.
- * I believe filling in too much in the FIFO might cause
- * errons in 8bit wide transfers on ARM variants (just 8 words
- * FIFO, means only 8x8 = 64 bits in FIFO) at least.
- *
- * To prevent this issue, the TX FIFO is only filled to the
- * unused RX FIFO fill length, regardless of what the TX
- * FIFO status flag indicates.
- */
- dev_dbg(&pl022->adev->dev,
- "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n",
- __func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end);
-
- /* Read as much as you can */
- while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
- && (pl022->rx < pl022->rx_end)) {
- switch (pl022->read) {
- case READING_NULL:
- readw(SSP_DR(pl022->virtbase));
- break;
- case READING_U8:
- *(u8 *) (pl022->rx) =
- readw(SSP_DR(pl022->virtbase)) & 0xFFU;
- break;
- case READING_U16:
- *(u16 *) (pl022->rx) =
- (u16) readw(SSP_DR(pl022->virtbase));
- break;
- case READING_U32:
- *(u32 *) (pl022->rx) =
- readl(SSP_DR(pl022->virtbase));
- break;
- }
- pl022->rx += (pl022->cur_chip->n_bytes);
- pl022->exp_fifo_level--;
- }
- /*
- * Write as much as possible up to the RX FIFO size
- */
- while ((pl022->exp_fifo_level < pl022->vendor->fifodepth)
- && (pl022->tx < pl022->tx_end)) {
- switch (pl022->write) {
- case WRITING_NULL:
- writew(0x0, SSP_DR(pl022->virtbase));
- break;
- case WRITING_U8:
- writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase));
- break;
- case WRITING_U16:
- writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase));
- break;
- case WRITING_U32:
- writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase));
- break;
- }
- pl022->tx += (pl022->cur_chip->n_bytes);
- pl022->exp_fifo_level++;
- /*
- * This inner reader takes care of things appearing in the RX
- * FIFO as we're transmitting. This will happen a lot since the
- * clock starts running when you put things into the TX FIFO,
- * and then things are continuously clocked into the RX FIFO.
- */
- while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
- && (pl022->rx < pl022->rx_end)) {
- switch (pl022->read) {
- case READING_NULL:
- readw(SSP_DR(pl022->virtbase));
- break;
- case READING_U8:
- *(u8 *) (pl022->rx) =
- readw(SSP_DR(pl022->virtbase)) & 0xFFU;
- break;
- case READING_U16:
- *(u16 *) (pl022->rx) =
- (u16) readw(SSP_DR(pl022->virtbase));
- break;
- case READING_U32:
- *(u32 *) (pl022->rx) =
- readl(SSP_DR(pl022->virtbase));
- break;
- }
- pl022->rx += (pl022->cur_chip->n_bytes);
- pl022->exp_fifo_level--;
- }
- }
- /*
- * When we exit here the TX FIFO should be full and the RX FIFO
- * should be empty
- */
-}
-
-/**
- * next_transfer - Move to the Next transfer in the current spi message
- * @pl022: SSP driver private data structure
- *
- * This function moves though the linked list of spi transfers in the
- * current spi message and returns with the state of current spi
- * message i.e whether its last transfer is done(STATE_DONE) or
- * Next transfer is ready(STATE_RUNNING)
- */
-static void *next_transfer(struct pl022 *pl022)
-{
- struct spi_message *msg = pl022->cur_msg;
- struct spi_transfer *trans = pl022->cur_transfer;
-
- /* Move to next transfer */
- if (trans->transfer_list.next != &msg->transfers) {
- pl022->cur_transfer =
- list_entry(trans->transfer_list.next,
- struct spi_transfer, transfer_list);
- return STATE_RUNNING;
- }
- return STATE_DONE;
-}
-
-/*
- * This DMA functionality is only compiled in if we have
- * access to the generic DMA devices/DMA engine.
- */
-#ifdef CONFIG_DMA_ENGINE
-static void unmap_free_dma_scatter(struct pl022 *pl022)
-{
- /* Unmap and free the SG tables */
- dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
- pl022->sgt_tx.nents, DMA_TO_DEVICE);
- dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
- pl022->sgt_rx.nents, DMA_FROM_DEVICE);
- sg_free_table(&pl022->sgt_rx);
- sg_free_table(&pl022->sgt_tx);
-}
-
-static void dma_callback(void *data)
-{
- struct pl022 *pl022 = data;
- struct spi_message *msg = pl022->cur_msg;
-
- BUG_ON(!pl022->sgt_rx.sgl);
-
-#ifdef VERBOSE_DEBUG
- /*
- * Optionally dump out buffers to inspect contents, this is
- * good if you want to convince yourself that the loopback
- * read/write contents are the same, when adopting to a new
- * DMA engine.
- */
- {
- struct scatterlist *sg;
- unsigned int i;
-
- dma_sync_sg_for_cpu(&pl022->adev->dev,
- pl022->sgt_rx.sgl,
- pl022->sgt_rx.nents,
- DMA_FROM_DEVICE);
-
- for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
- dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
- print_hex_dump(KERN_ERR, "SPI RX: ",
- DUMP_PREFIX_OFFSET,
- 16,
- 1,
- sg_virt(sg),
- sg_dma_len(sg),
- 1);
- }
- for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
- dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
- print_hex_dump(KERN_ERR, "SPI TX: ",
- DUMP_PREFIX_OFFSET,
- 16,
- 1,
- sg_virt(sg),
- sg_dma_len(sg),
- 1);
- }
- }
-#endif
-
- unmap_free_dma_scatter(pl022);
-
- /* Update total bytes transferred */
- msg->actual_length += pl022->cur_transfer->len;
- if (pl022->cur_transfer->cs_change)
- pl022->cur_chip->
- cs_control(SSP_CHIP_DESELECT);
-
- /* Move to next transfer */
- msg->state = next_transfer(pl022);
- tasklet_schedule(&pl022->pump_transfers);
-}
-
-static void setup_dma_scatter(struct pl022 *pl022,
- void *buffer,
- unsigned int length,
- struct sg_table *sgtab)
-{
- struct scatterlist *sg;
- int bytesleft = length;
- void *bufp = buffer;
- int mapbytes;
- int i;
-
- if (buffer) {
- for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
- /*
- * If there are less bytes left than what fits
- * in the current page (plus page alignment offset)
- * we just feed in this, else we stuff in as much
- * as we can.
- */
- if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
- mapbytes = bytesleft;
- else
- mapbytes = PAGE_SIZE - offset_in_page(bufp);
- sg_set_page(sg, virt_to_page(bufp),
- mapbytes, offset_in_page(bufp));
- bufp += mapbytes;
- bytesleft -= mapbytes;
- dev_dbg(&pl022->adev->dev,
- "set RX/TX target page @ %p, %d bytes, %d left\n",
- bufp, mapbytes, bytesleft);
- }
- } else {
- /* Map the dummy buffer on every page */
- for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
- if (bytesleft < PAGE_SIZE)
- mapbytes = bytesleft;
- else
- mapbytes = PAGE_SIZE;
- sg_set_page(sg, virt_to_page(pl022->dummypage),
- mapbytes, 0);
- bytesleft -= mapbytes;
- dev_dbg(&pl022->adev->dev,
- "set RX/TX to dummy page %d bytes, %d left\n",
- mapbytes, bytesleft);
-
- }
- }
- BUG_ON(bytesleft);
-}
-
-/**
- * configure_dma - configures the channels for the next transfer
- * @pl022: SSP driver's private data structure
- */
-static int configure_dma(struct pl022 *pl022)
-{
- struct dma_slave_config rx_conf = {
- .src_addr = SSP_DR(pl022->phybase),
- .direction = DMA_DEV_TO_MEM,
- .device_fc = false,
- };
- struct dma_slave_config tx_conf = {
- .dst_addr = SSP_DR(pl022->phybase),
- .direction = DMA_MEM_TO_DEV,
- .device_fc = false,
- };
- unsigned int pages;
- int ret;
- int rx_sglen, tx_sglen;
- struct dma_chan *rxchan = pl022->dma_rx_channel;
- struct dma_chan *txchan = pl022->dma_tx_channel;
- struct dma_async_tx_descriptor *rxdesc;
- struct dma_async_tx_descriptor *txdesc;
-
- /* Check that the channels are available */
- if (!rxchan || !txchan)
- return -ENODEV;
-
- /*
- * 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 */
- rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
- break;
- case READING_U8:
- rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- break;
- case READING_U16:
- rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case READING_U32:
- rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- }
-
- switch (pl022->write) {
- case WRITING_NULL:
- /* Use the same as for reading */
- tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
- break;
- case WRITING_U8:
- tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
- break;
- case WRITING_U16:
- tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case WRITING_U32:
- tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- }
-
- /* SPI pecularity: we need to read and write the same width */
- if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
- rx_conf.src_addr_width = tx_conf.dst_addr_width;
- if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
- tx_conf.dst_addr_width = rx_conf.src_addr_width;
- BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
-
- dmaengine_slave_config(rxchan, &rx_conf);
- dmaengine_slave_config(txchan, &tx_conf);
-
- /* Create sglists for the transfers */
- pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
- dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
-
- ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC);
- if (ret)
- goto err_alloc_rx_sg;
-
- ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_ATOMIC);
- if (ret)
- goto err_alloc_tx_sg;
-
- /* Fill in the scatterlists for the RX+TX buffers */
- setup_dma_scatter(pl022, pl022->rx,
- pl022->cur_transfer->len, &pl022->sgt_rx);
- setup_dma_scatter(pl022, pl022->tx,
- pl022->cur_transfer->len, &pl022->sgt_tx);
-
- /* Map DMA buffers */
- rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
- pl022->sgt_rx.nents, DMA_FROM_DEVICE);
- if (!rx_sglen)
- goto err_rx_sgmap;
-
- tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl,
- pl022->sgt_tx.nents, DMA_TO_DEVICE);
- if (!tx_sglen)
- goto err_tx_sgmap;
-
- /* Send both scatterlists */
- rxdesc = dmaengine_prep_slave_sg(rxchan,
- pl022->sgt_rx.sgl,
- rx_sglen,
- DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!rxdesc)
- goto err_rxdesc;
-
- txdesc = dmaengine_prep_slave_sg(txchan,
- pl022->sgt_tx.sgl,
- tx_sglen,
- DMA_MEM_TO_DEV,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!txdesc)
- goto err_txdesc;
-
- /* Put the callback on the RX transfer only, that should finish last */
- rxdesc->callback = dma_callback;
- rxdesc->callback_param = pl022;
-
- /* Submit and fire RX and TX with TX last so we're ready to read! */
- dmaengine_submit(rxdesc);
- dmaengine_submit(txdesc);
- dma_async_issue_pending(rxchan);
- dma_async_issue_pending(txchan);
- pl022->dma_running = true;
-
- return 0;
-
-err_txdesc:
- dmaengine_terminate_all(txchan);
-err_rxdesc:
- dmaengine_terminate_all(rxchan);
- dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
- pl022->sgt_tx.nents, DMA_TO_DEVICE);
-err_tx_sgmap:
- dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
- pl022->sgt_tx.nents, DMA_FROM_DEVICE);
-err_rx_sgmap:
- sg_free_table(&pl022->sgt_tx);
-err_alloc_tx_sg:
- sg_free_table(&pl022->sgt_rx);
-err_alloc_rx_sg:
- return -ENOMEM;
-}
-
-static int __devinit pl022_dma_probe(struct pl022 *pl022)
-{
- dma_cap_mask_t mask;
-
- /* Try to acquire a generic DMA engine slave channel */
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- /*
- * We need both RX and TX channels to do DMA, else do none
- * of them.
- */
- pl022->dma_rx_channel = dma_request_channel(mask,
- pl022->master_info->dma_filter,
- pl022->master_info->dma_rx_param);
- if (!pl022->dma_rx_channel) {
- dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n");
- goto err_no_rxchan;
- }
-
- pl022->dma_tx_channel = dma_request_channel(mask,
- pl022->master_info->dma_filter,
- pl022->master_info->dma_tx_param);
- if (!pl022->dma_tx_channel) {
- dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n");
- goto err_no_txchan;
- }
-
- pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!pl022->dummypage) {
- dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n");
- goto err_no_dummypage;
- }
-
- dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
- dma_chan_name(pl022->dma_rx_channel),
- dma_chan_name(pl022->dma_tx_channel));
-
- return 0;
-
-err_no_dummypage:
- dma_release_channel(pl022->dma_tx_channel);
-err_no_txchan:
- dma_release_channel(pl022->dma_rx_channel);
- pl022->dma_rx_channel = NULL;
-err_no_rxchan:
- dev_err(&pl022->adev->dev,
- "Failed to work in dma mode, work without dma!\n");
- return -ENODEV;
-}
-
-static void terminate_dma(struct pl022 *pl022)
-{
- struct dma_chan *rxchan = pl022->dma_rx_channel;
- struct dma_chan *txchan = pl022->dma_tx_channel;
-
- dmaengine_terminate_all(rxchan);
- dmaengine_terminate_all(txchan);
- unmap_free_dma_scatter(pl022);
- pl022->dma_running = false;
-}
-
-static void pl022_dma_remove(struct pl022 *pl022)
-{
- if (pl022->dma_running)
- terminate_dma(pl022);
- if (pl022->dma_tx_channel)
- dma_release_channel(pl022->dma_tx_channel);
- if (pl022->dma_rx_channel)
- dma_release_channel(pl022->dma_rx_channel);
- kfree(pl022->dummypage);
-}
-
-#else
-static inline int configure_dma(struct pl022 *pl022)
-{
- return -ENODEV;
-}
-
-static inline int pl022_dma_probe(struct pl022 *pl022)
-{
- return 0;
-}
-
-static inline void pl022_dma_remove(struct pl022 *pl022)
-{
-}
-#endif
-
-/**
- * pl022_interrupt_handler - Interrupt handler for SSP controller
- *
- * This function handles interrupts generated for an interrupt based transfer.
- * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the
- * current message's state as STATE_ERROR and schedule the tasklet
- * pump_transfers which will do the postprocessing of the current message by
- * calling giveback(). Otherwise it reads data from RX FIFO till there is no
- * more data, and writes data in TX FIFO till it is not full. If we complete
- * the transfer we move to the next transfer and schedule the tasklet.
- */
-static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
-{
- struct pl022 *pl022 = dev_id;
- struct spi_message *msg = pl022->cur_msg;
- u16 irq_status = 0;
- u16 flag = 0;
-
- if (unlikely(!msg)) {
- dev_err(&pl022->adev->dev,
- "bad message state in interrupt handler");
- /* Never fail */
- return IRQ_HANDLED;
- }
-
- /* Read the Interrupt Status Register */
- irq_status = readw(SSP_MIS(pl022->virtbase));
-
- if (unlikely(!irq_status))
- return IRQ_NONE;
-
- /*
- * This handles the FIFO interrupts, the timeout
- * interrupts are flatly ignored, they cannot be
- * trusted.
- */
- if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) {
- /*
- * Overrun interrupt - bail out since our Data has been
- * corrupted
- */
- dev_err(&pl022->adev->dev, "FIFO overrun\n");
- if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
- dev_err(&pl022->adev->dev,
- "RXFIFO is full\n");
- if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
- dev_err(&pl022->adev->dev,
- "TXFIFO is full\n");
-
- /*
- * Disable and clear interrupts, disable SSP,
- * mark message with bad status so it can be
- * retried.
- */
- writew(DISABLE_ALL_INTERRUPTS,
- SSP_IMSC(pl022->virtbase));
- writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
- writew((readw(SSP_CR1(pl022->virtbase)) &
- (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
- msg->state = STATE_ERROR;
-
- /* Schedule message queue handler */
- tasklet_schedule(&pl022->pump_transfers);
- return IRQ_HANDLED;
- }
-
- readwriter(pl022);
-
- if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
- flag = 1;
- /* Disable Transmit interrupt, enable receive interrupt */
- writew((readw(SSP_IMSC(pl022->virtbase)) &
- ~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM,
- SSP_IMSC(pl022->virtbase));
- }
-
- /*
- * Since all transactions must write as much as shall be read,
- * we can conclude the entire transaction once RX is complete.
- * At this point, all TX will always be finished.
- */
- if (pl022->rx >= pl022->rx_end) {
- writew(DISABLE_ALL_INTERRUPTS,
- SSP_IMSC(pl022->virtbase));
- writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
- if (unlikely(pl022->rx > pl022->rx_end)) {
- dev_warn(&pl022->adev->dev, "read %u surplus "
- "bytes (did you request an odd "
- "number of bytes on a 16bit bus?)\n",
- (u32) (pl022->rx - pl022->rx_end));
- }
- /* Update total bytes transferred */
- msg->actual_length += pl022->cur_transfer->len;
- if (pl022->cur_transfer->cs_change)
- pl022->cur_chip->
- cs_control(SSP_CHIP_DESELECT);
- /* Move to next transfer */
- msg->state = next_transfer(pl022);
- tasklet_schedule(&pl022->pump_transfers);
- return IRQ_HANDLED;
- }
-
- return IRQ_HANDLED;
-}
-
-/**
- * This sets up the pointers to memory for the next message to
- * send out on the SPI bus.
- */
-static int set_up_next_transfer(struct pl022 *pl022,
- struct spi_transfer *transfer)
-{
- int residue;
-
- /* Sanity check the message for this bus width */
- residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes;
- if (unlikely(residue != 0)) {
- dev_err(&pl022->adev->dev,
- "message of %u bytes to transmit but the current "
- "chip bus has a data width of %u bytes!\n",
- pl022->cur_transfer->len,
- pl022->cur_chip->n_bytes);
- dev_err(&pl022->adev->dev, "skipping this message\n");
- return -EIO;
- }
- pl022->tx = (void *)transfer->tx_buf;
- pl022->tx_end = pl022->tx + pl022->cur_transfer->len;
- pl022->rx = (void *)transfer->rx_buf;
- pl022->rx_end = pl022->rx + pl022->cur_transfer->len;
- pl022->write =
- pl022->tx ? pl022->cur_chip->write : WRITING_NULL;
- pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL;
- return 0;
-}
-
-/**
- * pump_transfers - Tasklet function which schedules next transfer
- * when running in interrupt or DMA transfer mode.
- * @data: SSP driver private data structure
- *
- */
-static void pump_transfers(unsigned long data)
-{
- struct pl022 *pl022 = (struct pl022 *) data;
- struct spi_message *message = NULL;
- struct spi_transfer *transfer = NULL;
- struct spi_transfer *previous = NULL;
-
- /* Get current state information */
- message = pl022->cur_msg;
- transfer = pl022->cur_transfer;
-
- /* Handle for abort */
- if (message->state == STATE_ERROR) {
- message->status = -EIO;
- giveback(pl022);
- return;
- }
-
- /* Handle end of message */
- if (message->state == STATE_DONE) {
- message->status = 0;
- giveback(pl022);
- return;
- }
-
- /* Delay if requested at end of transfer before CS change */
- if (message->state == STATE_RUNNING) {
- previous = list_entry(transfer->transfer_list.prev,
- struct spi_transfer,
- transfer_list);
- if (previous->delay_usecs)
- /*
- * FIXME: This runs in interrupt context.
- * Is this really smart?
- */
- udelay(previous->delay_usecs);
-
- /* Reselect chip select only if cs_change was requested */
- if (previous->cs_change)
- pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
- } else {
- /* STATE_START */
- message->state = STATE_RUNNING;
- }
-
- if (set_up_next_transfer(pl022, transfer)) {
- message->state = STATE_ERROR;
- message->status = -EIO;
- giveback(pl022);
- return;
- }
- /* Flush the FIFOs and let's go! */
- flush(pl022);
-
- if (pl022->cur_chip->enable_dma) {
- if (configure_dma(pl022)) {
- dev_dbg(&pl022->adev->dev,
- "configuration of DMA failed, fall back to interrupt mode\n");
- goto err_config_dma;
- }
- return;
- }
-
-err_config_dma:
- /* enable all interrupts except RX */
- writew(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM, SSP_IMSC(pl022->virtbase));
-}
-
-static void do_interrupt_dma_transfer(struct pl022 *pl022)
-{
- /*
- * Default is to enable all interrupts except RX -
- * this will be enabled once TX is complete
- */
- u32 irqflags = ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM;
-
- /* Enable target chip, if not already active */
- if (!pl022->next_msg_cs_active)
- pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-
- if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
- /* Error path */
- pl022->cur_msg->state = STATE_ERROR;
- pl022->cur_msg->status = -EIO;
- giveback(pl022);
- return;
- }
- /* If we're using DMA, set up DMA here */
- if (pl022->cur_chip->enable_dma) {
- /* Configure DMA transfer */
- if (configure_dma(pl022)) {
- dev_dbg(&pl022->adev->dev,
- "configuration of DMA failed, fall back to interrupt mode\n");
- goto err_config_dma;
- }
- /* Disable interrupts in DMA mode, IRQ from DMA controller */
- irqflags = DISABLE_ALL_INTERRUPTS;
- }
-err_config_dma:
- /* Enable SSP, turn on interrupts */
- writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
- SSP_CR1(pl022->virtbase));
- writew(irqflags, SSP_IMSC(pl022->virtbase));
-}
-
-static void do_polling_transfer(struct pl022 *pl022)
-{
- struct spi_message *message = NULL;
- struct spi_transfer *transfer = NULL;
- struct spi_transfer *previous = NULL;
- struct chip_data *chip;
- unsigned long time, timeout;
-
- chip = pl022->cur_chip;
- message = pl022->cur_msg;
-
- while (message->state != STATE_DONE) {
- /* Handle for abort */
- if (message->state == STATE_ERROR)
- break;
- transfer = pl022->cur_transfer;
-
- /* Delay if requested at end of transfer */
- if (message->state == STATE_RUNNING) {
- previous =
- list_entry(transfer->transfer_list.prev,
- struct spi_transfer, transfer_list);
- if (previous->delay_usecs)
- udelay(previous->delay_usecs);
- if (previous->cs_change)
- pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
- } else {
- /* STATE_START */
- message->state = STATE_RUNNING;
- if (!pl022->next_msg_cs_active)
- pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
- }
-
- /* Configuration Changing Per Transfer */
- if (set_up_next_transfer(pl022, transfer)) {
- /* Error path */
- message->state = STATE_ERROR;
- break;
- }
- /* Flush FIFOs and enable SSP */
- flush(pl022);
- writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
- SSP_CR1(pl022->virtbase));
-
- dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n");
-
- timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT);
- while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) {
- time = jiffies;
- readwriter(pl022);
- if (time_after(time, timeout)) {
- dev_warn(&pl022->adev->dev,
- "%s: timeout!\n", __func__);
- message->state = STATE_ERROR;
- goto out;
- }
- cpu_relax();
- }
-
- /* Update total byte transferred */
- message->actual_length += pl022->cur_transfer->len;
- if (pl022->cur_transfer->cs_change)
- pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
- /* Move to next transfer */
- message->state = next_transfer(pl022);
- }
-out:
- /* Handle end of message */
- if (message->state == STATE_DONE)
- message->status = 0;
- else
- message->status = -EIO;
-
- giveback(pl022);
- return;
-}
-
-static int pl022_transfer_one_message(struct spi_master *master,
- struct spi_message *msg)
-{
- struct pl022 *pl022 = spi_master_get_devdata(master);
-
- /* Initial message state */
- pl022->cur_msg = msg;
- msg->state = STATE_START;
-
- pl022->cur_transfer = list_entry(msg->transfers.next,
- struct spi_transfer, transfer_list);
-
- /* Setup the SPI using the per chip configuration */
- pl022->cur_chip = spi_get_ctldata(msg->spi);
-
- restore_state(pl022);
- flush(pl022);
-
- if (pl022->cur_chip->xfer_type == POLLING_TRANSFER)
- do_polling_transfer(pl022);
- else
- do_interrupt_dma_transfer(pl022);
-
- return 0;
-}
-
-static int pl022_prepare_transfer_hardware(struct spi_master *master)
-{
- struct pl022 *pl022 = spi_master_get_devdata(master);
-
- /*
- * Just make sure we have all we need to run the transfer by syncing
- * with the runtime PM framework.
- */
- pm_runtime_get_sync(&pl022->adev->dev);
- return 0;
-}
-
-static int pl022_unprepare_transfer_hardware(struct spi_master *master)
-{
- struct pl022 *pl022 = spi_master_get_devdata(master);
-
- /* nothing more to do - disable spi/ssp and power off */
- writew((readw(SSP_CR1(pl022->virtbase)) &
- (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
-
- if (pl022->master_info->autosuspend_delay > 0) {
- pm_runtime_mark_last_busy(&pl022->adev->dev);
- pm_runtime_put_autosuspend(&pl022->adev->dev);
- } else {
- pm_runtime_put(&pl022->adev->dev);
- }
-
- return 0;
-}
-
-static int verify_controller_parameters(struct pl022 *pl022,
- struct pl022_config_chip const *chip_info)
-{
- if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
- || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
- dev_err(&pl022->adev->dev,
- "interface is configured incorrectly\n");
- return -EINVAL;
- }
- if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
- (!pl022->vendor->unidir)) {
- dev_err(&pl022->adev->dev,
- "unidirectional mode not supported in this "
- "hardware version\n");
- return -EINVAL;
- }
- if ((chip_info->hierarchy != SSP_MASTER)
- && (chip_info->hierarchy != SSP_SLAVE)) {
- dev_err(&pl022->adev->dev,
- "hierarchy is configured incorrectly\n");
- return -EINVAL;
- }
- if ((chip_info->com_mode != INTERRUPT_TRANSFER)
- && (chip_info->com_mode != DMA_TRANSFER)
- && (chip_info->com_mode != POLLING_TRANSFER)) {
- dev_err(&pl022->adev->dev,
- "Communication mode is configured incorrectly\n");
- return -EINVAL;
- }
- 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;
- }
- 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)
- || (chip_info->ctrl_len > SSP_BITS_32)) {
- dev_err(&pl022->adev->dev,
- "CTRL LEN is configured incorrectly\n");
- return -EINVAL;
- }
- if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
- && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
- dev_err(&pl022->adev->dev,
- "Wait State is configured incorrectly\n");
- return -EINVAL;
- }
- /* Half duplex is only available in the ST Micro version */
- if (pl022->vendor->extended_cr) {
- if ((chip_info->duplex !=
- SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
- && (chip_info->duplex !=
- SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
- dev_err(&pl022->adev->dev,
- "Microwire duplex mode is configured incorrectly\n");
- return -EINVAL;
- }
- } else {
- if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
- dev_err(&pl022->adev->dev,
- "Microwire half duplex mode requested,"
- " but this is only available in the"
- " ST version of PL022\n");
- return -EINVAL;
- }
- }
- return 0;
-}
-
-static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr)
-{
- return rate / (cpsdvsr * (1 + scr));
-}
-
-static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
- ssp_clock_params * clk_freq)
-{
- /* Lets calculate the frequency parameters */
- u16 cpsdvsr = CPSDVR_MIN, scr = SCR_MIN;
- u32 rate, max_tclk, min_tclk, best_freq = 0, best_cpsdvsr = 0,
- best_scr = 0, tmp, found = 0;
-
- rate = clk_get_rate(pl022->clk);
- /* cpsdvscr = 2 & scr 0 */
- max_tclk = spi_rate(rate, CPSDVR_MIN, SCR_MIN);
- /* cpsdvsr = 254 & scr = 255 */
- min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
-
- if (freq > max_tclk)
- dev_warn(&pl022->adev->dev,
- "Max speed that can be programmed is %d Hz, you requested %d\n",
- max_tclk, freq);
-
- if (freq < min_tclk) {
- dev_err(&pl022->adev->dev,
- "Requested frequency: %d Hz is less than minimum possible %d Hz\n",
- freq, min_tclk);
- return -EINVAL;
- }
-
- /*
- * best_freq will give closest possible available rate (<= requested
- * freq) for all values of scr & cpsdvsr.
- */
- while ((cpsdvsr <= CPSDVR_MAX) && !found) {
- while (scr <= SCR_MAX) {
- tmp = spi_rate(rate, cpsdvsr, scr);
-
- if (tmp > freq) {
- /* we need lower freq */
- scr++;
- continue;
- }
-
- /*
- * If found exact value, mark found and break.
- * If found more closer value, update and break.
- */
- if (tmp > best_freq) {
- best_freq = tmp;
- best_cpsdvsr = cpsdvsr;
- best_scr = scr;
-
- if (tmp == freq)
- found = 1;
- }
- /*
- * increased scr will give lower rates, which are not
- * required
- */
- break;
- }
- cpsdvsr += 2;
- scr = SCR_MIN;
- }
-
- WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n",
- freq);
-
- clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
- clk_freq->scr = (u8) (best_scr & 0xFF);
- dev_dbg(&pl022->adev->dev,
- "SSP Target Frequency is: %u, Effective Frequency is %u\n",
- freq, best_freq);
- dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
- clk_freq->cpsdvsr, clk_freq->scr);
-
- return 0;
-}
-
-/*
- * A piece of default chip info unless the platform
- * supplies it.
- */
-static const struct pl022_config_chip pl022_default_chip_info = {
- .com_mode = POLLING_TRANSFER,
- .iface = SSP_INTERFACE_MOTOROLA_SPI,
- .hierarchy = SSP_SLAVE,
- .slave_tx_disable = DO_NOT_DRIVE_TX,
- .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
- .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
- .ctrl_len = SSP_BITS_8,
- .wait_state = SSP_MWIRE_WAIT_ZERO,
- .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
- .cs_control = null_cs_control,
-};
-
-/**
- * pl022_setup - setup function registered to SPI master framework
- * @spi: spi device which is requesting setup
- *
- * This function is registered to the SPI framework for this SPI master
- * controller. If it is the first time when setup is called by this device,
- * this function will initialize the runtime state for this chip and save
- * the same in the device structure. Else it will update the runtime info
- * with the updated chip info. Nothing is really being written to the
- * controller hardware here, that is not done until the actual transfer
- * commence.
- */
-static int pl022_setup(struct spi_device *spi)
-{
- struct pl022_config_chip const *chip_info;
- struct chip_data *chip;
- struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0};
- int status = 0;
- struct pl022 *pl022 = spi_master_get_devdata(spi->master);
- unsigned int bits = spi->bits_per_word;
- u32 tmp;
-
- if (!spi->max_speed_hz)
- return -EINVAL;
-
- /* Get controller_state if one is supplied */
- chip = spi_get_ctldata(spi);
-
- if (chip == NULL) {
- chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
- if (!chip) {
- dev_err(&spi->dev,
- "cannot allocate controller state\n");
- return -ENOMEM;
- }
- dev_dbg(&spi->dev,
- "allocated memory for controller's runtime state\n");
- }
-
- /* Get controller data if one is supplied */
- chip_info = spi->controller_data;
-
- if (chip_info == NULL) {
- chip_info = &pl022_default_chip_info;
- /* spi_board_info.controller_data not is supplied */
- dev_dbg(&spi->dev,
- "using default controller_data settings\n");
- } else
- dev_dbg(&spi->dev,
- "using user supplied controller_data settings\n");
-
- /*
- * We can override with custom divisors, else we use the board
- * frequency setting
- */
- if ((0 == chip_info->clk_freq.cpsdvsr)
- && (0 == chip_info->clk_freq.scr)) {
- status = calculate_effective_freq(pl022,
- spi->max_speed_hz,
- &clk_freq);
- if (status < 0)
- goto err_config_params;
- } else {
- memcpy(&clk_freq, &chip_info->clk_freq, sizeof(clk_freq));
- if ((clk_freq.cpsdvsr % 2) != 0)
- clk_freq.cpsdvsr =
- clk_freq.cpsdvsr - 1;
- }
- 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;
- }
-
- status = verify_controller_parameters(pl022, chip_info);
- if (status) {
- dev_err(&spi->dev, "controller data is incorrect");
- 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) {
- chip->cs_control = null_cs_control;
- dev_warn(&spi->dev,
- "chip select function is NULL for this chip\n");
- } else
- chip->cs_control = chip_info->cs_control;
-
- /* Check bits per word with vendor specific range */
- if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) {
- status = -ENOTSUPP;
- dev_err(&spi->dev, "illegal data size for this controller!\n");
- dev_err(&spi->dev, "This controller can only handle 4 <= n <= %d bit words\n",
- pl022->vendor->max_bpw);
- goto err_config_params;
- } else if (bits <= 8) {
- dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
- chip->n_bytes = 1;
- chip->read = READING_U8;
- chip->write = WRITING_U8;
- } else if (bits <= 16) {
- dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
- chip->n_bytes = 2;
- chip->read = READING_U16;
- chip->write = WRITING_U16;
- } else {
- dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
- chip->n_bytes = 4;
- chip->read = READING_U32;
- chip->write = WRITING_U32;
- }
-
- /* Now Initialize all register settings required for this chip */
- chip->cr0 = 0;
- chip->cr1 = 0;
- chip->dmacr = 0;
- chip->cpsr = 0;
- if ((chip_info->com_mode == DMA_TRANSFER)
- && ((pl022->master_info)->enable_dma)) {
- chip->enable_dma = true;
- dev_dbg(&spi->dev, "DMA mode set in controller state\n");
- SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
- SSP_DMACR_MASK_RXDMAE, 0);
- SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
- SSP_DMACR_MASK_TXDMAE, 1);
- } else {
- chip->enable_dma = false;
- dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n");
- SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
- SSP_DMACR_MASK_RXDMAE, 0);
- SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
- SSP_DMACR_MASK_TXDMAE, 1);
- }
-
- chip->cpsr = clk_freq.cpsdvsr;
-
- /* Special setup for the ST micro extended control registers */
- if (pl022->vendor->extended_cr) {
- u32 etx;
-
- if (pl022->vendor->pl023) {
- /* These bits are only in the PL023 */
- SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
- SSP_CR1_MASK_FBCLKDEL_ST, 13);
- } else {
- /* These bits are in the PL022 but not PL023 */
- SSP_WRITE_BITS(chip->cr0, chip_info->duplex,
- SSP_CR0_MASK_HALFDUP_ST, 5);
- SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len,
- SSP_CR0_MASK_CSS_ST, 16);
- SSP_WRITE_BITS(chip->cr0, chip_info->iface,
- SSP_CR0_MASK_FRF_ST, 21);
- SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
- SSP_CR1_MASK_MWAIT_ST, 6);
- }
- SSP_WRITE_BITS(chip->cr0, bits - 1,
- SSP_CR0_MASK_DSS_ST, 0);
-
- if (spi->mode & SPI_LSB_FIRST) {
- tmp = SSP_RX_LSB;
- etx = SSP_TX_LSB;
- } else {
- tmp = SSP_RX_MSB;
- etx = SSP_TX_MSB;
- }
- SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4);
- SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5);
- SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
- SSP_CR1_MASK_RXIFLSEL_ST, 7);
- SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
- SSP_CR1_MASK_TXIFLSEL_ST, 10);
- } else {
- SSP_WRITE_BITS(chip->cr0, bits - 1,
- SSP_CR0_MASK_DSS, 0);
- SSP_WRITE_BITS(chip->cr0, chip_info->iface,
- SSP_CR0_MASK_FRF, 4);
- }
-
- /* Stuff that is common for all versions */
- if (spi->mode & SPI_CPOL)
- tmp = SSP_CLK_POL_IDLE_HIGH;
- else
- tmp = SSP_CLK_POL_IDLE_LOW;
- SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
-
- if (spi->mode & SPI_CPHA)
- tmp = SSP_CLK_SECOND_EDGE;
- else
- tmp = SSP_CLK_FIRST_EDGE;
- SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7);
-
- SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8);
- /* Loopback is available on all versions except PL023 */
- if (pl022->vendor->loopback) {
- if (spi->mode & SPI_LOOP)
- tmp = LOOPBACK_ENABLED;
- else
- tmp = LOOPBACK_DISABLED;
- SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0);
- }
- SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
- SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
- SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD,
- 3);
-
- /* Save controller_state */
- spi_set_ctldata(spi, chip);
- return status;
- err_config_params:
- spi_set_ctldata(spi, NULL);
- kfree(chip);
- return status;
-}
-
-/**
- * pl022_cleanup - cleanup function registered to SPI master framework
- * @spi: spi device which is requesting cleanup
- *
- * This function is registered to the SPI framework for this SPI master
- * controller. It will free the runtime state of chip.
- */
-static void pl022_cleanup(struct spi_device *spi)
-{
- struct chip_data *chip = spi_get_ctldata(spi);
-
- spi_set_ctldata(spi, NULL);
- kfree(chip);
-}
-
-static int __devinit
-pl022_probe(struct amba_device *adev, const struct amba_id *id)
-{
- struct device *dev = &adev->dev;
- struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
- struct spi_master *master;
- struct pl022 *pl022 = NULL; /*Data for this driver */
- int status = 0;
-
- dev_info(&adev->dev,
- "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
- if (platform_info == NULL) {
- dev_err(&adev->dev, "probe - no platform data supplied\n");
- status = -ENODEV;
- goto err_no_pdata;
- }
-
- /* Allocate master with space for data */
- master = spi_alloc_master(dev, sizeof(struct pl022));
- if (master == NULL) {
- dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
- status = -ENOMEM;
- goto err_no_master;
- }
-
- pl022 = spi_master_get_devdata(master);
- pl022->master = master;
- pl022->master_info = platform_info;
- pl022->adev = adev;
- pl022->vendor = id->data;
-
- /*
- * Bus Number Which has been Assigned to this SSP controller
- * on this board
- */
- master->bus_num = platform_info->bus_id;
- master->num_chipselect = platform_info->num_chipselect;
- master->cleanup = pl022_cleanup;
- master->setup = pl022_setup;
- master->prepare_transfer_hardware = pl022_prepare_transfer_hardware;
- master->transfer_one_message = pl022_transfer_one_message;
- master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
- master->rt = platform_info->rt;
-
- /*
- * Supports mode 0-3, loopback, and active low CS. Transfers are
- * always MS bit first on the original pl022.
- */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
- if (pl022->vendor->extended_cr)
- master->mode_bits |= SPI_LSB_FIRST;
-
- dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
-
- status = amba_request_regions(adev, NULL);
- if (status)
- goto err_no_ioregion;
-
- pl022->phybase = adev->res.start;
- pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
- if (pl022->virtbase == NULL) {
- status = -ENOMEM;
- goto err_no_ioremap;
- }
- printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
- adev->res.start, pl022->virtbase);
-
- pl022->clk = clk_get(&adev->dev, NULL);
- if (IS_ERR(pl022->clk)) {
- status = PTR_ERR(pl022->clk);
- dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
- goto err_no_clk;
- }
-
- status = clk_prepare(pl022->clk);
- if (status) {
- dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
- goto err_clk_prep;
- }
-
- status = clk_enable(pl022->clk);
- if (status) {
- dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
- goto err_no_clk_en;
- }
-
- /* Initialize transfer pump */
- tasklet_init(&pl022->pump_transfers, pump_transfers,
- (unsigned long)pl022);
-
- /* Disable SSP */
- writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
- SSP_CR1(pl022->virtbase));
- load_ssp_default_config(pl022);
-
- status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
- pl022);
- if (status < 0) {
- dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
- goto err_no_irq;
- }
-
- /* Get DMA channels */
- if (platform_info->enable_dma) {
- status = pl022_dma_probe(pl022);
- if (status != 0)
- platform_info->enable_dma = 0;
- }
-
- /* Register with the SPI framework */
- amba_set_drvdata(adev, pl022);
- status = spi_register_master(master);
- if (status != 0) {
- dev_err(&adev->dev,
- "probe - problem registering spi master\n");
- goto err_spi_register;
- }
- dev_dbg(dev, "probe succeeded\n");
-
- /* let runtime pm put suspend */
- if (platform_info->autosuspend_delay > 0) {
- dev_info(&adev->dev,
- "will use autosuspend for runtime pm, delay %dms\n",
- platform_info->autosuspend_delay);
- pm_runtime_set_autosuspend_delay(dev,
- platform_info->autosuspend_delay);
- pm_runtime_use_autosuspend(dev);
- pm_runtime_put_autosuspend(dev);
- } else {
- pm_runtime_put(dev);
- }
- return 0;
-
- err_spi_register:
- if (platform_info->enable_dma)
- pl022_dma_remove(pl022);
-
- free_irq(adev->irq[0], pl022);
- err_no_irq:
- clk_disable(pl022->clk);
- err_no_clk_en:
- clk_unprepare(pl022->clk);
- err_clk_prep:
- clk_put(pl022->clk);
- err_no_clk:
- iounmap(pl022->virtbase);
- err_no_ioremap:
- amba_release_regions(adev);
- err_no_ioregion:
- spi_master_put(master);
- err_no_master:
- err_no_pdata:
- return status;
-}
-
-static int __devexit
-pl022_remove(struct amba_device *adev)
-{
- struct pl022 *pl022 = amba_get_drvdata(adev);
-
- if (!pl022)
- return 0;
-
- /*
- * undo pm_runtime_put() in probe. I assume that we're not
- * accessing the primecell here.
- */
- pm_runtime_get_noresume(&adev->dev);
-
- load_ssp_default_config(pl022);
- if (pl022->master_info->enable_dma)
- pl022_dma_remove(pl022);
-
- free_irq(adev->irq[0], pl022);
- clk_disable(pl022->clk);
- clk_unprepare(pl022->clk);
- clk_put(pl022->clk);
- iounmap(pl022->virtbase);
- amba_release_regions(adev);
- tasklet_disable(&pl022->pump_transfers);
- spi_unregister_master(pl022->master);
- spi_master_put(pl022->master);
- amba_set_drvdata(adev, NULL);
- return 0;
-}
-
-#ifdef CONFIG_SUSPEND
-static int pl022_suspend(struct device *dev)
-{
- struct pl022 *pl022 = dev_get_drvdata(dev);
- int ret;
-
- ret = spi_master_suspend(pl022->master);
- if (ret) {
- dev_warn(dev, "cannot suspend master\n");
- return ret;
- }
-
- dev_dbg(dev, "suspended\n");
- return 0;
-}
-
-static int pl022_resume(struct device *dev)
-{
- struct pl022 *pl022 = dev_get_drvdata(dev);
- int ret;
-
- /* Start the queue running */
- ret = spi_master_resume(pl022->master);
- if (ret)
- dev_err(dev, "problem starting queue (%d)\n", ret);
- else
- dev_dbg(dev, "resumed\n");
-
- return ret;
-}
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_RUNTIME
-static int pl022_runtime_suspend(struct device *dev)
-{
- struct pl022 *pl022 = dev_get_drvdata(dev);
-
- clk_disable(pl022->clk);
-
- return 0;
-}
-
-static int pl022_runtime_resume(struct device *dev)
-{
- struct pl022 *pl022 = dev_get_drvdata(dev);
-
- clk_enable(pl022->clk);
-
- return 0;
-}
-#endif
-
-static const struct dev_pm_ops pl022_dev_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
- SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
-};
-
-static struct vendor_data vendor_arm = {
- .fifodepth = 8,
- .max_bpw = 16,
- .unidir = false,
- .extended_cr = false,
- .pl023 = false,
- .loopback = true,
-};
-
-static struct vendor_data vendor_st = {
- .fifodepth = 32,
- .max_bpw = 32,
- .unidir = false,
- .extended_cr = true,
- .pl023 = false,
- .loopback = true,
-};
-
-static struct vendor_data vendor_st_pl023 = {
- .fifodepth = 32,
- .max_bpw = 32,
- .unidir = false,
- .extended_cr = true,
- .pl023 = true,
- .loopback = false,
-};
-
-static struct vendor_data vendor_db5500_pl023 = {
- .fifodepth = 32,
- .max_bpw = 32,
- .unidir = false,
- .extended_cr = true,
- .pl023 = true,
- .loopback = true,
-};
-
-static struct amba_id pl022_ids[] = {
- {
- /*
- * ARM PL022 variant, this has a 16bit wide
- * and 8 locations deep TX/RX FIFO
- */
- .id = 0x00041022,
- .mask = 0x000fffff,
- .data = &vendor_arm,
- },
- {
- /*
- * ST Micro derivative, this has 32bit wide
- * and 32 locations deep TX/RX FIFO
- */
- .id = 0x01080022,
- .mask = 0xffffffff,
- .data = &vendor_st,
- },
- {
- /*
- * ST-Ericsson derivative "PL023" (this is not
- * an official ARM number), this is a PL022 SSP block
- * stripped to SPI mode only, it has 32bit wide
- * and 32 locations deep TX/RX FIFO but no extended
- * CR0/CR1 register
- */
- .id = 0x00080023,
- .mask = 0xffffffff,
- .data = &vendor_st_pl023,
- },
- {
- .id = 0x10080023,
- .mask = 0xffffffff,
- .data = &vendor_db5500_pl023,
- },
- { 0, 0 },
-};
-
-MODULE_DEVICE_TABLE(amba, pl022_ids);
-
-static struct amba_driver pl022_driver = {
- .drv = {
- .name = "ssp-pl022",
- .pm = &pl022_dev_pm_ops,
- },
- .id_table = pl022_ids,
- .probe = pl022_probe,
- .remove = __devexit_p(pl022_remove),
-};
-
-static int __init pl022_init(void)
-{
- return amba_driver_register(&pl022_driver);
-}
-subsys_initcall(pl022_init);
-
-static void __exit pl022_exit(void)
-{
- amba_driver_unregister(&pl022_driver);
-}
-module_exit(pl022_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-MODULE_DESCRIPTION("PL022 SSP Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-ppc4xx.c b/ANDROID_3.4.5/drivers/spi/spi-ppc4xx.c
deleted file mode 100644
index 98ec5328..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-ppc4xx.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * SPI_PPC4XX SPI controller driver.
- *
- * Copyright (C) 2007 Gary Jennejohn <garyj@denx.de>
- * Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering
- * Copyright 2009 Harris Corporation, Steven A. Falco <sfalco@harris.com>
- *
- * Based in part on drivers/spi/spi_s3c24xx.c
- *
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * 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.
- */
-
-/*
- * The PPC4xx SPI controller has no FIFO so each sent/received byte will
- * generate an interrupt to the CPU. This can cause high CPU utilization.
- * This driver allows platforms to reduce the interrupt load on the CPU
- * during SPI transfers by setting max_speed_hz via the device tree.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/of_platform.h>
-#include <linux/of_spi.h>
-#include <linux/of_gpio.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <asm/io.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-
-/* bits in mode register - bit 0 is MSb */
-
-/*
- * SPI_PPC4XX_MODE_SCP = 0 means "data latched on trailing edge of clock"
- * SPI_PPC4XX_MODE_SCP = 1 means "data latched on leading edge of clock"
- * Note: This is the inverse of CPHA.
- */
-#define SPI_PPC4XX_MODE_SCP (0x80 >> 3)
-
-/* SPI_PPC4XX_MODE_SPE = 1 means "port enabled" */
-#define SPI_PPC4XX_MODE_SPE (0x80 >> 4)
-
-/*
- * SPI_PPC4XX_MODE_RD = 0 means "MSB first" - this is the normal mode
- * SPI_PPC4XX_MODE_RD = 1 means "LSB first" - this is bit-reversed mode
- * Note: This is identical to SPI_LSB_FIRST.
- */
-#define SPI_PPC4XX_MODE_RD (0x80 >> 5)
-
-/*
- * SPI_PPC4XX_MODE_CI = 0 means "clock idles low"
- * SPI_PPC4XX_MODE_CI = 1 means "clock idles high"
- * Note: This is identical to CPOL.
- */
-#define SPI_PPC4XX_MODE_CI (0x80 >> 6)
-
-/*
- * SPI_PPC4XX_MODE_IL = 0 means "loopback disable"
- * SPI_PPC4XX_MODE_IL = 1 means "loopback enable"
- */
-#define SPI_PPC4XX_MODE_IL (0x80 >> 7)
-
-/* bits in control register */
-/* starts a transfer when set */
-#define SPI_PPC4XX_CR_STR (0x80 >> 7)
-
-/* bits in status register */
-/* port is busy with a transfer */
-#define SPI_PPC4XX_SR_BSY (0x80 >> 6)
-/* RxD ready */
-#define SPI_PPC4XX_SR_RBR (0x80 >> 7)
-
-/* clock settings (SCP and CI) for various SPI modes */
-#define SPI_CLK_MODE0 (SPI_PPC4XX_MODE_SCP | 0)
-#define SPI_CLK_MODE1 (0 | 0)
-#define SPI_CLK_MODE2 (SPI_PPC4XX_MODE_SCP | SPI_PPC4XX_MODE_CI)
-#define SPI_CLK_MODE3 (0 | SPI_PPC4XX_MODE_CI)
-
-#define DRIVER_NAME "spi_ppc4xx_of"
-
-struct spi_ppc4xx_regs {
- u8 mode;
- u8 rxd;
- u8 txd;
- u8 cr;
- u8 sr;
- u8 dummy;
- /*
- * Clock divisor modulus register
- * This uses the follwing formula:
- * SCPClkOut = OPBCLK/(4(CDM + 1))
- * or
- * CDM = (OPBCLK/4*SCPClkOut) - 1
- * bit 0 is the MSb!
- */
- u8 cdm;
-};
-
-/* SPI Controller driver's private data. */
-struct ppc4xx_spi {
- /* bitbang has to be first */
- struct spi_bitbang bitbang;
- struct completion done;
-
- u64 mapbase;
- u64 mapsize;
- int irqnum;
- /* need this to set the SPI clock */
- unsigned int opb_freq;
-
- /* for transfers */
- int len;
- int count;
- /* data buffers */
- const unsigned char *tx;
- unsigned char *rx;
-
- int *gpios;
-
- struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */
- struct spi_master *master;
- struct device *dev;
-};
-
-/* need this so we can set the clock in the chipselect routine */
-struct spi_ppc4xx_cs {
- u8 mode;
-};
-
-static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct ppc4xx_spi *hw;
- u8 data;
-
- dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
- t->tx_buf, t->rx_buf, t->len);
-
- hw = spi_master_get_devdata(spi->master);
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->len = t->len;
- hw->count = 0;
-
- /* send the first byte */
- data = hw->tx ? hw->tx[0] : 0;
- out_8(&hw->regs->txd, data);
- out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
- wait_for_completion(&hw->done);
-
- return hw->count;
-}
-
-static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master);
- struct spi_ppc4xx_cs *cs = spi->controller_state;
- int scr;
- u8 cdm = 0;
- u32 speed;
- u8 bits_per_word;
-
- /* Start with the generic configuration for this device. */
- bits_per_word = spi->bits_per_word;
- speed = spi->max_speed_hz;
-
- /*
- * Modify the configuration if the transfer overrides it. Do not allow
- * the transfer to overwrite the generic configuration with zeros.
- */
- if (t) {
- if (t->bits_per_word)
- bits_per_word = t->bits_per_word;
-
- if (t->speed_hz)
- speed = min(t->speed_hz, spi->max_speed_hz);
- }
-
- if (bits_per_word != 8) {
- dev_err(&spi->dev, "invalid bits-per-word (%d)\n",
- bits_per_word);
- return -EINVAL;
- }
-
- if (!speed || (speed > spi->max_speed_hz)) {
- dev_err(&spi->dev, "invalid speed_hz (%d)\n", speed);
- return -EINVAL;
- }
-
- /* Write new configration */
- out_8(&hw->regs->mode, cs->mode);
-
- /* Set the clock */
- /* opb_freq was already divided by 4 */
- scr = (hw->opb_freq / speed) - 1;
- if (scr > 0)
- cdm = min(scr, 0xff);
-
- dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, speed);
-
- if (in_8(&hw->regs->cdm) != cdm)
- out_8(&hw->regs->cdm, cdm);
-
- spin_lock(&hw->bitbang.lock);
- if (!hw->bitbang.busy) {
- hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
- /* Need to ndelay here? */
- }
- spin_unlock(&hw->bitbang.lock);
-
- return 0;
-}
-
-static int spi_ppc4xx_setup(struct spi_device *spi)
-{
- struct spi_ppc4xx_cs *cs = spi->controller_state;
-
- if (spi->bits_per_word != 8) {
- dev_err(&spi->dev, "invalid bits-per-word (%d)\n",
- spi->bits_per_word);
- return -EINVAL;
- }
-
- if (!spi->max_speed_hz) {
- dev_err(&spi->dev, "invalid max_speed_hz (must be non-zero)\n");
- return -EINVAL;
- }
-
- if (cs == NULL) {
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs)
- return -ENOMEM;
- spi->controller_state = cs;
- }
-
- /*
- * We set all bits of the SPI0_MODE register, so,
- * no need to read-modify-write
- */
- cs->mode = SPI_PPC4XX_MODE_SPE;
-
- switch (spi->mode & (SPI_CPHA | SPI_CPOL)) {
- case SPI_MODE_0:
- cs->mode |= SPI_CLK_MODE0;
- break;
- case SPI_MODE_1:
- cs->mode |= SPI_CLK_MODE1;
- break;
- case SPI_MODE_2:
- cs->mode |= SPI_CLK_MODE2;
- break;
- case SPI_MODE_3:
- cs->mode |= SPI_CLK_MODE3;
- break;
- }
-
- if (spi->mode & SPI_LSB_FIRST)
- cs->mode |= SPI_PPC4XX_MODE_RD;
-
- return 0;
-}
-
-static void spi_ppc4xx_chipsel(struct spi_device *spi, int value)
-{
- struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master);
- unsigned int cs = spi->chip_select;
- unsigned int cspol;
-
- /*
- * If there are no chip selects at all, or if this is the special
- * case of a non-existent (dummy) chip select, do nothing.
- */
-
- if (!hw->master->num_chipselect || hw->gpios[cs] == -EEXIST)
- return;
-
- cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
- if (value == BITBANG_CS_INACTIVE)
- cspol = !cspol;
-
- gpio_set_value(hw->gpios[cs], cspol);
-}
-
-static irqreturn_t spi_ppc4xx_int(int irq, void *dev_id)
-{
- struct ppc4xx_spi *hw;
- u8 status;
- u8 data;
- unsigned int count;
-
- hw = (struct ppc4xx_spi *)dev_id;
-
- status = in_8(&hw->regs->sr);
- if (!status)
- return IRQ_NONE;
-
- /*
- * BSY de-asserts one cycle after the transfer is complete. The
- * interrupt is asserted after the transfer is complete. The exact
- * relationship is not documented, hence this code.
- */
-
- if (unlikely(status & SPI_PPC4XX_SR_BSY)) {
- u8 lstatus;
- int cnt = 0;
-
- dev_dbg(hw->dev, "got interrupt but spi still busy?\n");
- do {
- ndelay(10);
- lstatus = in_8(&hw->regs->sr);
- } while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY);
-
- if (cnt >= 100) {
- dev_err(hw->dev, "busywait: too many loops!\n");
- complete(&hw->done);
- return IRQ_HANDLED;
- } else {
- /* status is always 1 (RBR) here */
- status = in_8(&hw->regs->sr);
- dev_dbg(hw->dev, "loops %d status %x\n", cnt, status);
- }
- }
-
- count = hw->count;
- hw->count++;
-
- /* RBR triggered this interrupt. Therefore, data must be ready. */
- data = in_8(&hw->regs->rxd);
- if (hw->rx)
- hw->rx[count] = data;
-
- count++;
-
- if (count < hw->len) {
- data = hw->tx ? hw->tx[count] : 0;
- out_8(&hw->regs->txd, data);
- out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
- } else {
- complete(&hw->done);
- }
-
- return IRQ_HANDLED;
-}
-
-static void spi_ppc4xx_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-
-static void spi_ppc4xx_enable(struct ppc4xx_spi *hw)
-{
- /*
- * On all 4xx PPC's the SPI bus is shared/multiplexed with
- * the 2nd I2C bus. We need to enable the the SPI bus before
- * using it.
- */
-
- /* need to clear bit 14 to enable SPC */
- dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0);
-}
-
-static void free_gpios(struct ppc4xx_spi *hw)
-{
- if (hw->master->num_chipselect) {
- int i;
- for (i = 0; i < hw->master->num_chipselect; i++)
- if (gpio_is_valid(hw->gpios[i]))
- gpio_free(hw->gpios[i]);
-
- kfree(hw->gpios);
- hw->gpios = NULL;
- }
-}
-
-/*
- * platform_device layer stuff...
- */
-static int __init spi_ppc4xx_of_probe(struct platform_device *op)
-{
- struct ppc4xx_spi *hw;
- struct spi_master *master;
- struct spi_bitbang *bbp;
- struct resource resource;
- struct device_node *np = op->dev.of_node;
- struct device *dev = &op->dev;
- struct device_node *opbnp;
- int ret;
- int num_gpios;
- const unsigned int *clk;
-
- master = spi_alloc_master(dev, sizeof *hw);
- if (master == NULL)
- return -ENOMEM;
- master->dev.of_node = np;
- dev_set_drvdata(dev, master);
- hw = spi_master_get_devdata(master);
- hw->master = spi_master_get(master);
- hw->dev = dev;
-
- init_completion(&hw->done);
-
- /*
- * A count of zero implies a single SPI device without any chip-select.
- * Note that of_gpio_count counts all gpios assigned to this spi master.
- * This includes both "null" gpio's and real ones.
- */
- num_gpios = of_gpio_count(np);
- if (num_gpios) {
- int i;
-
- hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL);
- if (!hw->gpios) {
- ret = -ENOMEM;
- goto free_master;
- }
-
- for (i = 0; i < num_gpios; i++) {
- int gpio;
- enum of_gpio_flags flags;
-
- gpio = of_get_gpio_flags(np, i, &flags);
- hw->gpios[i] = gpio;
-
- if (gpio_is_valid(gpio)) {
- /* Real CS - set the initial state. */
- ret = gpio_request(gpio, np->name);
- if (ret < 0) {
- dev_err(dev, "can't request gpio "
- "#%d: %d\n", i, ret);
- goto free_gpios;
- }
-
- gpio_direction_output(gpio,
- !!(flags & OF_GPIO_ACTIVE_LOW));
- } else if (gpio == -EEXIST) {
- ; /* No CS, but that's OK. */
- } else {
- dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
- ret = -EINVAL;
- goto free_gpios;
- }
- }
- }
-
- /* Setup the state for the bitbang driver */
- bbp = &hw->bitbang;
- bbp->master = hw->master;
- bbp->setup_transfer = spi_ppc4xx_setupxfer;
- bbp->chipselect = spi_ppc4xx_chipsel;
- bbp->txrx_bufs = spi_ppc4xx_txrx;
- bbp->use_dma = 0;
- bbp->master->setup = spi_ppc4xx_setup;
- bbp->master->cleanup = spi_ppc4xx_cleanup;
-
- /* Allocate bus num dynamically. */
- bbp->master->bus_num = -1;
-
- /* the spi->mode bits understood by this driver: */
- bbp->master->mode_bits =
- SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST;
-
- /* this many pins in all GPIO controllers */
- bbp->master->num_chipselect = num_gpios;
-
- /* Get the clock for the OPB */
- opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb");
- if (opbnp == NULL) {
- dev_err(dev, "OPB: cannot find node\n");
- ret = -ENODEV;
- goto free_gpios;
- }
- /* Get the clock (Hz) for the OPB */
- clk = of_get_property(opbnp, "clock-frequency", NULL);
- if (clk == NULL) {
- dev_err(dev, "OPB: no clock-frequency property set\n");
- of_node_put(opbnp);
- ret = -ENODEV;
- goto free_gpios;
- }
- hw->opb_freq = *clk;
- hw->opb_freq >>= 2;
- of_node_put(opbnp);
-
- ret = of_address_to_resource(np, 0, &resource);
- if (ret) {
- dev_err(dev, "error while parsing device node resource\n");
- goto free_gpios;
- }
- hw->mapbase = resource.start;
- hw->mapsize = resource_size(&resource);
-
- /* Sanity check */
- if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
- dev_err(dev, "too small to map registers\n");
- ret = -EINVAL;
- goto free_gpios;
- }
-
- /* Request IRQ */
- hw->irqnum = irq_of_parse_and_map(np, 0);
- ret = request_irq(hw->irqnum, spi_ppc4xx_int,
- 0, "spi_ppc4xx_of", (void *)hw);
- if (ret) {
- dev_err(dev, "unable to allocate interrupt\n");
- goto free_gpios;
- }
-
- if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) {
- dev_err(dev, "resource unavailable\n");
- ret = -EBUSY;
- goto request_mem_error;
- }
-
- hw->regs = ioremap(hw->mapbase, sizeof(struct spi_ppc4xx_regs));
-
- if (!hw->regs) {
- dev_err(dev, "unable to memory map registers\n");
- ret = -ENXIO;
- goto map_io_error;
- }
-
- spi_ppc4xx_enable(hw);
-
- /* Finally register our spi controller */
- dev->dma_mask = 0;
- ret = spi_bitbang_start(bbp);
- if (ret) {
- dev_err(dev, "failed to register SPI master\n");
- goto unmap_regs;
- }
-
- dev_info(dev, "driver initialized\n");
-
- return 0;
-
-unmap_regs:
- iounmap(hw->regs);
-map_io_error:
- release_mem_region(hw->mapbase, hw->mapsize);
-request_mem_error:
- free_irq(hw->irqnum, hw);
-free_gpios:
- free_gpios(hw);
-free_master:
- dev_set_drvdata(dev, NULL);
- spi_master_put(master);
-
- dev_err(dev, "initialization failed\n");
- return ret;
-}
-
-static int __exit spi_ppc4xx_of_remove(struct platform_device *op)
-{
- struct spi_master *master = dev_get_drvdata(&op->dev);
- struct ppc4xx_spi *hw = spi_master_get_devdata(master);
-
- spi_bitbang_stop(&hw->bitbang);
- dev_set_drvdata(&op->dev, NULL);
- release_mem_region(hw->mapbase, hw->mapsize);
- free_irq(hw->irqnum, hw);
- iounmap(hw->regs);
- free_gpios(hw);
- return 0;
-}
-
-static const struct of_device_id spi_ppc4xx_of_match[] = {
- { .compatible = "ibm,ppc4xx-spi", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match);
-
-static struct platform_driver spi_ppc4xx_of_driver = {
- .probe = spi_ppc4xx_of_probe,
- .remove = __exit_p(spi_ppc4xx_of_remove),
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = spi_ppc4xx_of_match,
- },
-};
-module_platform_driver(spi_ppc4xx_of_driver);
-
-MODULE_AUTHOR("Gary Jennejohn & Stefan Roese");
-MODULE_DESCRIPTION("Simple PPC4xx SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-pxa2xx-pci.c b/ANDROID_3.4.5/drivers/spi/spi-pxa2xx-pci.c
deleted file mode 100644
index 3fb44afe..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-pxa2xx-pci.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * CE4100's SPI device is more or less the same one as found on PXA
- *
- */
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/of_device.h>
-#include <linux/module.h>
-#include <linux/spi/pxa2xx_spi.h>
-
-struct ce4100_info {
- struct ssp_device ssp;
- struct platform_device *spi_pdev;
-};
-
-static DEFINE_MUTEX(ssp_lock);
-static LIST_HEAD(ssp_list);
-
-struct ssp_device *pxa_ssp_request(int port, const char *label)
-{
- struct ssp_device *ssp = NULL;
-
- mutex_lock(&ssp_lock);
-
- list_for_each_entry(ssp, &ssp_list, node) {
- if (ssp->port_id == port && ssp->use_count == 0) {
- ssp->use_count++;
- ssp->label = label;
- break;
- }
- }
-
- mutex_unlock(&ssp_lock);
-
- if (&ssp->node == &ssp_list)
- return NULL;
-
- return ssp;
-}
-EXPORT_SYMBOL_GPL(pxa_ssp_request);
-
-void pxa_ssp_free(struct ssp_device *ssp)
-{
- mutex_lock(&ssp_lock);
- if (ssp->use_count) {
- ssp->use_count--;
- ssp->label = NULL;
- } else
- dev_err(&ssp->pdev->dev, "device already free\n");
- mutex_unlock(&ssp_lock);
-}
-EXPORT_SYMBOL_GPL(pxa_ssp_free);
-
-static int __devinit ce4100_spi_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- int ret;
- resource_size_t phys_beg;
- resource_size_t phys_len;
- struct ce4100_info *spi_info;
- struct platform_device *pdev;
- struct pxa2xx_spi_master spi_pdata;
- struct ssp_device *ssp;
-
- ret = pci_enable_device(dev);
- if (ret)
- return ret;
-
- phys_beg = pci_resource_start(dev, 0);
- phys_len = pci_resource_len(dev, 0);
-
- if (!request_mem_region(phys_beg, phys_len,
- "CE4100 SPI")) {
- dev_err(&dev->dev, "Can't request register space.\n");
- ret = -EBUSY;
- return ret;
- }
-
- pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
- spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
- if (!pdev || !spi_info ) {
- ret = -ENOMEM;
- goto err_nomem;
- }
- memset(&spi_pdata, 0, sizeof(spi_pdata));
- spi_pdata.num_chipselect = dev->devfn;
-
- ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
- if (ret)
- goto err_nomem;
-
- pdev->dev.parent = &dev->dev;
- pdev->dev.of_node = dev->dev.of_node;
- ssp = &spi_info->ssp;
- ssp->phys_base = pci_resource_start(dev, 0);
- ssp->mmio_base = ioremap(phys_beg, phys_len);
- if (!ssp->mmio_base) {
- dev_err(&pdev->dev, "failed to ioremap() registers\n");
- ret = -EIO;
- goto err_nomem;
- }
- ssp->irq = dev->irq;
- ssp->port_id = pdev->id;
- ssp->type = PXA25x_SSP;
-
- mutex_lock(&ssp_lock);
- list_add(&ssp->node, &ssp_list);
- mutex_unlock(&ssp_lock);
-
- pci_set_drvdata(dev, spi_info);
-
- ret = platform_device_add(pdev);
- if (ret)
- goto err_dev_add;
-
- return ret;
-
-err_dev_add:
- pci_set_drvdata(dev, NULL);
- mutex_lock(&ssp_lock);
- list_del(&ssp->node);
- mutex_unlock(&ssp_lock);
- iounmap(ssp->mmio_base);
-
-err_nomem:
- release_mem_region(phys_beg, phys_len);
- platform_device_put(pdev);
- kfree(spi_info);
- return ret;
-}
-
-static void __devexit ce4100_spi_remove(struct pci_dev *dev)
-{
- struct ce4100_info *spi_info;
- struct ssp_device *ssp;
-
- spi_info = pci_get_drvdata(dev);
- ssp = &spi_info->ssp;
- platform_device_unregister(spi_info->spi_pdev);
-
- iounmap(ssp->mmio_base);
- release_mem_region(pci_resource_start(dev, 0),
- pci_resource_len(dev, 0));
-
- mutex_lock(&ssp_lock);
- list_del(&ssp->node);
- mutex_unlock(&ssp_lock);
-
- pci_set_drvdata(dev, NULL);
- pci_disable_device(dev);
- kfree(spi_info);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
- { },
-};
-MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
-
-static struct pci_driver ce4100_spi_driver = {
- .name = "ce4100_spi",
- .id_table = ce4100_spi_devices,
- .probe = ce4100_spi_probe,
- .remove = __devexit_p(ce4100_spi_remove),
-};
-
-static int __init ce4100_spi_init(void)
-{
- return pci_register_driver(&ce4100_spi_driver);
-}
-module_init(ce4100_spi_init);
-
-static void __exit ce4100_spi_exit(void)
-{
- pci_unregister_driver(&ce4100_spi_driver);
-}
-module_exit(ce4100_spi_exit);
-
-MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-pxa2xx.c b/ANDROID_3.4.5/drivers/spi/spi-pxa2xx.c
deleted file mode 100644
index dc25bee8..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-pxa2xx.c
+++ /dev/null
@@ -1,1816 +0,0 @@
-/*
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/pxa2xx_spi.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-
-
-MODULE_AUTHOR("Stephen Street");
-MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-spi");
-
-#define MAX_BUSES 3
-
-#define TIMOUT_DFLT 1000
-
-#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
-#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
-#define MAX_DMA_LEN 8191
-#define DMA_ALIGNMENT 8
-
-/*
- * for testing SSCR1 changes that require SSP restart, basically
- * everything except the service and interrupt enables, the pxa270 developer
- * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
- * list, but the PXA255 dev man says all bits without really meaning the
- * service and interrupt enables
- */
-#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
- | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
- | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
- | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
- | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
- | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
-
-#define DEFINE_SSP_REG(reg, off) \
-static inline u32 read_##reg(void const __iomem *p) \
-{ return __raw_readl(p + (off)); } \
-\
-static inline void write_##reg(u32 v, void __iomem *p) \
-{ __raw_writel(v, p + (off)); }
-
-DEFINE_SSP_REG(SSCR0, 0x00)
-DEFINE_SSP_REG(SSCR1, 0x04)
-DEFINE_SSP_REG(SSSR, 0x08)
-DEFINE_SSP_REG(SSITR, 0x0c)
-DEFINE_SSP_REG(SSDR, 0x10)
-DEFINE_SSP_REG(SSTO, 0x28)
-DEFINE_SSP_REG(SSPSP, 0x2c)
-
-#define START_STATE ((void*)0)
-#define RUNNING_STATE ((void*)1)
-#define DONE_STATE ((void*)2)
-#define ERROR_STATE ((void*)-1)
-
-#define QUEUE_RUNNING 0
-#define QUEUE_STOPPED 1
-
-struct driver_data {
- /* Driver model hookup */
- struct platform_device *pdev;
-
- /* SSP Info */
- struct ssp_device *ssp;
-
- /* SPI framework hookup */
- enum pxa_ssp_type ssp_type;
- struct spi_master *master;
-
- /* PXA hookup */
- struct pxa2xx_spi_master *master_info;
-
- /* DMA setup stuff */
- int rx_channel;
- int tx_channel;
- u32 *null_dma_buf;
-
- /* SSP register addresses */
- void __iomem *ioaddr;
- u32 ssdr_physical;
-
- /* SSP masks*/
- u32 dma_cr1;
- u32 int_cr1;
- u32 clear_sr;
- u32 mask_sr;
-
- /* Driver message queue */
- struct workqueue_struct *workqueue;
- struct work_struct pump_messages;
- spinlock_t lock;
- struct list_head queue;
- int busy;
- int run;
-
- /* Message Transfer pump */
- struct tasklet_struct pump_transfers;
-
- /* Current message transfer state info */
- struct spi_message* cur_msg;
- struct spi_transfer* cur_transfer;
- struct chip_data *cur_chip;
- size_t len;
- void *tx;
- void *tx_end;
- void *rx;
- void *rx_end;
- int dma_mapped;
- dma_addr_t rx_dma;
- dma_addr_t tx_dma;
- size_t rx_map_len;
- size_t tx_map_len;
- u8 n_bytes;
- u32 dma_width;
- int (*write)(struct driver_data *drv_data);
- int (*read)(struct driver_data *drv_data);
- irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
- void (*cs_control)(u32 command);
-};
-
-struct chip_data {
- u32 cr0;
- u32 cr1;
- u32 psp;
- u32 timeout;
- u8 n_bytes;
- u32 dma_width;
- u32 dma_burst_size;
- u32 threshold;
- u32 dma_threshold;
- u8 enable_dma;
- u8 bits_per_word;
- u32 speed_hz;
- union {
- int gpio_cs;
- unsigned int frm;
- };
- int gpio_cs_inverted;
- int (*write)(struct driver_data *drv_data);
- int (*read)(struct driver_data *drv_data);
- void (*cs_control)(u32 command);
-};
-
-static void pump_messages(struct work_struct *work);
-
-static void cs_assert(struct driver_data *drv_data)
-{
- struct chip_data *chip = drv_data->cur_chip;
-
- if (drv_data->ssp_type == CE4100_SSP) {
- write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
- return;
- }
-
- if (chip->cs_control) {
- chip->cs_control(PXA2XX_CS_ASSERT);
- return;
- }
-
- if (gpio_is_valid(chip->gpio_cs))
- gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted);
-}
-
-static void cs_deassert(struct driver_data *drv_data)
-{
- struct chip_data *chip = drv_data->cur_chip;
-
- if (drv_data->ssp_type == CE4100_SSP)
- return;
-
- if (chip->cs_control) {
- chip->cs_control(PXA2XX_CS_DEASSERT);
- return;
- }
-
- if (gpio_is_valid(chip->gpio_cs))
- gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
-}
-
-static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- if (drv_data->ssp_type == CE4100_SSP)
- val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
-
- write_SSSR(val, reg);
-}
-
-static int pxa25x_ssp_comp(struct driver_data *drv_data)
-{
- if (drv_data->ssp_type == PXA25x_SSP)
- return 1;
- if (drv_data->ssp_type == CE4100_SSP)
- return 1;
- return 0;
-}
-
-static int flush(struct driver_data *drv_data)
-{
- unsigned long limit = loops_per_jiffy << 1;
-
- void __iomem *reg = drv_data->ioaddr;
-
- do {
- while (read_SSSR(reg) & SSSR_RNE) {
- read_SSDR(reg);
- }
- } while ((read_SSSR(reg) & SSSR_BSY) && --limit);
- write_SSSR_CS(drv_data, SSSR_ROR);
-
- return limit;
-}
-
-static int null_writer(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
- u8 n_bytes = drv_data->n_bytes;
-
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
- return 0;
-
- write_SSDR(0, reg);
- drv_data->tx += n_bytes;
-
- return 1;
-}
-
-static int null_reader(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
- u8 n_bytes = drv_data->n_bytes;
-
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- read_SSDR(reg);
- drv_data->rx += n_bytes;
- }
-
- return drv_data->rx == drv_data->rx_end;
-}
-
-static int u8_writer(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
- return 0;
-
- write_SSDR(*(u8 *)(drv_data->tx), reg);
- ++drv_data->tx;
-
- return 1;
-}
-
-static int u8_reader(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- *(u8 *)(drv_data->rx) = read_SSDR(reg);
- ++drv_data->rx;
- }
-
- return drv_data->rx == drv_data->rx_end;
-}
-
-static int u16_writer(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
- return 0;
-
- write_SSDR(*(u16 *)(drv_data->tx), reg);
- drv_data->tx += 2;
-
- return 1;
-}
-
-static int u16_reader(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- *(u16 *)(drv_data->rx) = read_SSDR(reg);
- drv_data->rx += 2;
- }
-
- return drv_data->rx == drv_data->rx_end;
-}
-
-static int u32_writer(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
- || (drv_data->tx == drv_data->tx_end))
- return 0;
-
- write_SSDR(*(u32 *)(drv_data->tx), reg);
- drv_data->tx += 4;
-
- return 1;
-}
-
-static int u32_reader(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
- *(u32 *)(drv_data->rx) = read_SSDR(reg);
- drv_data->rx += 4;
- }
-
- return drv_data->rx == drv_data->rx_end;
-}
-
-static void *next_transfer(struct driver_data *drv_data)
-{
- struct spi_message *msg = drv_data->cur_msg;
- struct spi_transfer *trans = drv_data->cur_transfer;
-
- /* Move to next transfer */
- if (trans->transfer_list.next != &msg->transfers) {
- drv_data->cur_transfer =
- list_entry(trans->transfer_list.next,
- struct spi_transfer,
- transfer_list);
- return RUNNING_STATE;
- } else
- return DONE_STATE;
-}
-
-static int map_dma_buffers(struct driver_data *drv_data)
-{
- struct spi_message *msg = drv_data->cur_msg;
- struct device *dev = &msg->spi->dev;
-
- if (!drv_data->cur_chip->enable_dma)
- return 0;
-
- if (msg->is_dma_mapped)
- return drv_data->rx_dma && drv_data->tx_dma;
-
- if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
- return 0;
-
- /* Modify setup if rx buffer is null */
- if (drv_data->rx == NULL) {
- *drv_data->null_dma_buf = 0;
- drv_data->rx = drv_data->null_dma_buf;
- drv_data->rx_map_len = 4;
- } else
- drv_data->rx_map_len = drv_data->len;
-
-
- /* Modify setup if tx buffer is null */
- if (drv_data->tx == NULL) {
- *drv_data->null_dma_buf = 0;
- drv_data->tx = drv_data->null_dma_buf;
- drv_data->tx_map_len = 4;
- } else
- drv_data->tx_map_len = drv_data->len;
-
- /* Stream map the tx buffer. Always do DMA_TO_DEVICE first
- * so we flush the cache *before* invalidating it, in case
- * the tx and rx buffers overlap.
- */
- drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
- drv_data->tx_map_len, DMA_TO_DEVICE);
- if (dma_mapping_error(dev, drv_data->tx_dma))
- return 0;
-
- /* Stream map the rx buffer */
- drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
- drv_data->rx_map_len, DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, drv_data->rx_dma)) {
- dma_unmap_single(dev, drv_data->tx_dma,
- drv_data->tx_map_len, DMA_TO_DEVICE);
- return 0;
- }
-
- return 1;
-}
-
-static void unmap_dma_buffers(struct driver_data *drv_data)
-{
- struct device *dev;
-
- if (!drv_data->dma_mapped)
- return;
-
- if (!drv_data->cur_msg->is_dma_mapped) {
- dev = &drv_data->cur_msg->spi->dev;
- dma_unmap_single(dev, drv_data->rx_dma,
- drv_data->rx_map_len, DMA_FROM_DEVICE);
- dma_unmap_single(dev, drv_data->tx_dma,
- drv_data->tx_map_len, DMA_TO_DEVICE);
- }
-
- drv_data->dma_mapped = 0;
-}
-
-/* caller already set message->status; dma and pio irqs are blocked */
-static void giveback(struct driver_data *drv_data)
-{
- struct spi_transfer* last_transfer;
- unsigned long flags;
- struct spi_message *msg;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- msg = drv_data->cur_msg;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- last_transfer = list_entry(msg->transfers.prev,
- struct spi_transfer,
- transfer_list);
-
- /* Delay if requested before any change in chip select */
- if (last_transfer->delay_usecs)
- udelay(last_transfer->delay_usecs);
-
- /* Drop chip select UNLESS cs_change is true or we are returning
- * a message with an error, or next message is for another chip
- */
- if (!last_transfer->cs_change)
- cs_deassert(drv_data);
- else {
- struct spi_message *next_msg;
-
- /* Holding of cs was hinted, but we need to make sure
- * the next message is for the same chip. Don't waste
- * time with the following tests unless this was hinted.
- *
- * We cannot postpone this until pump_messages, because
- * after calling msg->complete (below) the driver that
- * sent the current message could be unloaded, which
- * could invalidate the cs_control() callback...
- */
-
- /* get a pointer to the next message, if any */
- spin_lock_irqsave(&drv_data->lock, flags);
- if (list_empty(&drv_data->queue))
- next_msg = NULL;
- else
- next_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- /* see if the next and current messages point
- * to the same chip
- */
- if (next_msg && next_msg->spi != msg->spi)
- next_msg = NULL;
- if (!next_msg || msg->state == ERROR_STATE)
- cs_deassert(drv_data);
- }
-
- msg->state = NULL;
- if (msg->complete)
- msg->complete(msg->context);
-
- drv_data->cur_chip = NULL;
-}
-
-static int wait_ssp_rx_stall(void const __iomem *ioaddr)
-{
- unsigned long limit = loops_per_jiffy << 1;
-
- while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
- cpu_relax();
-
- return limit;
-}
-
-static int wait_dma_channel_stop(int channel)
-{
- unsigned long limit = loops_per_jiffy << 1;
-
- while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
- cpu_relax();
-
- return limit;
-}
-
-static void dma_error_stop(struct driver_data *drv_data, const char *msg)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- /* Stop and reset */
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
- flush(drv_data);
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-
- unmap_dma_buffers(drv_data);
-
- dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
- drv_data->cur_msg->state = ERROR_STATE;
- tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void dma_transfer_complete(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
- struct spi_message *msg = drv_data->cur_msg;
-
- /* Clear and disable interrupts on SSP and DMA channels*/
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-
- if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_handler: dma rx channel stop failed\n");
-
- if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_transfer: ssp rx stall failed\n");
-
- unmap_dma_buffers(drv_data);
-
- /* update the buffer pointer for the amount completed in dma */
- drv_data->rx += drv_data->len -
- (DCMD(drv_data->rx_channel) & DCMD_LENGTH);
-
- /* read trailing data from fifo, it does not matter how many
- * bytes are in the fifo just read until buffer is full
- * or fifo is empty, which ever occurs first */
- drv_data->read(drv_data);
-
- /* return count of what was actually read */
- msg->actual_length += drv_data->len -
- (drv_data->rx_end - drv_data->rx);
-
- /* Transfer delays and chip select release are
- * handled in pump_transfers or giveback
- */
-
- /* Move to next transfer */
- msg->state = next_transfer(drv_data);
-
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void dma_handler(int channel, void *data)
-{
- struct driver_data *drv_data = data;
- u32 irq_status = DCSR(channel) & DMA_INT_MASK;
-
- if (irq_status & DCSR_BUSERR) {
-
- if (channel == drv_data->tx_channel)
- dma_error_stop(drv_data,
- "dma_handler: "
- "bad bus address on tx channel");
- else
- dma_error_stop(drv_data,
- "dma_handler: "
- "bad bus address on rx channel");
- return;
- }
-
- /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
- if ((channel == drv_data->tx_channel)
- && (irq_status & DCSR_ENDINTR)
- && (drv_data->ssp_type == PXA25x_SSP)) {
-
- /* Wait for rx to stall */
- if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_handler: ssp rx stall failed\n");
-
- /* finish this transfer, start the next */
- dma_transfer_complete(drv_data);
- }
-}
-
-static irqreturn_t dma_transfer(struct driver_data *drv_data)
-{
- u32 irq_status;
- void __iomem *reg = drv_data->ioaddr;
-
- irq_status = read_SSSR(reg) & drv_data->mask_sr;
- if (irq_status & SSSR_ROR) {
- dma_error_stop(drv_data, "dma_transfer: fifo overrun");
- return IRQ_HANDLED;
- }
-
- /* Check for false positive timeout */
- if ((irq_status & SSSR_TINT)
- && (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
- write_SSSR(SSSR_TINT, reg);
- return IRQ_HANDLED;
- }
-
- if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
-
- /* Clear and disable timeout interrupt, do the rest in
- * dma_transfer_complete */
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
-
- /* finish this transfer, start the next */
- dma_transfer_complete(drv_data);
-
- return IRQ_HANDLED;
- }
-
- /* Opps problem detected */
- return IRQ_NONE;
-}
-
-static void reset_sccr1(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
- struct chip_data *chip = drv_data->cur_chip;
- u32 sccr1_reg;
-
- sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
- sccr1_reg &= ~SSCR1_RFT;
- sccr1_reg |= chip->threshold;
- write_SSCR1(sccr1_reg, reg);
-}
-
-static void int_error_stop(struct driver_data *drv_data, const char* msg)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- /* Stop and reset SSP */
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- reset_sccr1(drv_data);
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
- flush(drv_data);
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-
- dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
- drv_data->cur_msg->state = ERROR_STATE;
- tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void int_transfer_complete(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- /* Stop SSP */
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- reset_sccr1(drv_data);
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
-
- /* Update total byte transferred return count actual bytes read */
- drv_data->cur_msg->actual_length += drv_data->len -
- (drv_data->rx_end - drv_data->rx);
-
- /* Transfer delays and chip select release are
- * handled in pump_transfers or giveback
- */
-
- /* Move to next transfer */
- drv_data->cur_msg->state = next_transfer(drv_data);
-
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
-{
- void __iomem *reg = drv_data->ioaddr;
-
- u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
- drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
-
- u32 irq_status = read_SSSR(reg) & irq_mask;
-
- if (irq_status & SSSR_ROR) {
- int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
- return IRQ_HANDLED;
- }
-
- if (irq_status & SSSR_TINT) {
- write_SSSR(SSSR_TINT, reg);
- if (drv_data->read(drv_data)) {
- int_transfer_complete(drv_data);
- return IRQ_HANDLED;
- }
- }
-
- /* Drain rx fifo, Fill tx fifo and prevent overruns */
- do {
- if (drv_data->read(drv_data)) {
- int_transfer_complete(drv_data);
- return IRQ_HANDLED;
- }
- } while (drv_data->write(drv_data));
-
- if (drv_data->read(drv_data)) {
- int_transfer_complete(drv_data);
- return IRQ_HANDLED;
- }
-
- if (drv_data->tx == drv_data->tx_end) {
- u32 bytes_left;
- u32 sccr1_reg;
-
- sccr1_reg = read_SSCR1(reg);
- sccr1_reg &= ~SSCR1_TIE;
-
- /*
- * PXA25x_SSP has no timeout, set up rx threshould for the
- * remaining RX bytes.
- */
- if (pxa25x_ssp_comp(drv_data)) {
-
- sccr1_reg &= ~SSCR1_RFT;
-
- bytes_left = drv_data->rx_end - drv_data->rx;
- switch (drv_data->n_bytes) {
- case 4:
- bytes_left >>= 1;
- case 2:
- bytes_left >>= 1;
- }
-
- if (bytes_left > RX_THRESH_DFLT)
- bytes_left = RX_THRESH_DFLT;
-
- sccr1_reg |= SSCR1_RxTresh(bytes_left);
- }
- write_SSCR1(sccr1_reg, reg);
- }
-
- /* We did something */
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ssp_int(int irq, void *dev_id)
-{
- struct driver_data *drv_data = dev_id;
- void __iomem *reg = drv_data->ioaddr;
- u32 sccr1_reg = read_SSCR1(reg);
- u32 mask = drv_data->mask_sr;
- u32 status;
-
- status = read_SSSR(reg);
-
- /* Ignore possible writes if we don't need to write */
- if (!(sccr1_reg & SSCR1_TIE))
- mask &= ~SSSR_TFS;
-
- if (!(status & mask))
- return IRQ_NONE;
-
- if (!drv_data->cur_msg) {
-
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, reg);
- write_SSSR_CS(drv_data, drv_data->clear_sr);
-
- dev_err(&drv_data->pdev->dev, "bad message state "
- "in interrupt handler\n");
-
- /* Never fail */
- return IRQ_HANDLED;
- }
-
- return drv_data->transfer_handler(drv_data);
-}
-
-static int set_dma_burst_and_threshold(struct chip_data *chip,
- struct spi_device *spi,
- u8 bits_per_word, u32 *burst_code,
- u32 *threshold)
-{
- struct pxa2xx_spi_chip *chip_info =
- (struct pxa2xx_spi_chip *)spi->controller_data;
- int bytes_per_word;
- int burst_bytes;
- int thresh_words;
- int req_burst_size;
- int retval = 0;
-
- /* Set the threshold (in registers) to equal the same amount of data
- * as represented by burst size (in bytes). The computation below
- * is (burst_size rounded up to nearest 8 byte, word or long word)
- * divided by (bytes/register); the tx threshold is the inverse of
- * the rx, so that there will always be enough data in the rx fifo
- * to satisfy a burst, and there will always be enough space in the
- * tx fifo to accept a burst (a tx burst will overwrite the fifo if
- * there is not enough space), there must always remain enough empty
- * space in the rx fifo for any data loaded to the tx fifo.
- * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
- * will be 8, or half the fifo;
- * The threshold can only be set to 2, 4 or 8, but not 16, because
- * to burst 16 to the tx fifo, the fifo would have to be empty;
- * however, the minimum fifo trigger level is 1, and the tx will
- * request service when the fifo is at this level, with only 15 spaces.
- */
-
- /* find bytes/word */
- if (bits_per_word <= 8)
- bytes_per_word = 1;
- else if (bits_per_word <= 16)
- bytes_per_word = 2;
- else
- bytes_per_word = 4;
-
- /* use struct pxa2xx_spi_chip->dma_burst_size if available */
- if (chip_info)
- req_burst_size = chip_info->dma_burst_size;
- else {
- switch (chip->dma_burst_size) {
- default:
- /* if the default burst size is not set,
- * do it now */
- chip->dma_burst_size = DCMD_BURST8;
- case DCMD_BURST8:
- req_burst_size = 8;
- break;
- case DCMD_BURST16:
- req_burst_size = 16;
- break;
- case DCMD_BURST32:
- req_burst_size = 32;
- break;
- }
- }
- if (req_burst_size <= 8) {
- *burst_code = DCMD_BURST8;
- burst_bytes = 8;
- } else if (req_burst_size <= 16) {
- if (bytes_per_word == 1) {
- /* don't burst more than 1/2 the fifo */
- *burst_code = DCMD_BURST8;
- burst_bytes = 8;
- retval = 1;
- } else {
- *burst_code = DCMD_BURST16;
- burst_bytes = 16;
- }
- } else {
- if (bytes_per_word == 1) {
- /* don't burst more than 1/2 the fifo */
- *burst_code = DCMD_BURST8;
- burst_bytes = 8;
- retval = 1;
- } else if (bytes_per_word == 2) {
- /* don't burst more than 1/2 the fifo */
- *burst_code = DCMD_BURST16;
- burst_bytes = 16;
- retval = 1;
- } else {
- *burst_code = DCMD_BURST32;
- burst_bytes = 32;
- }
- }
-
- thresh_words = burst_bytes / bytes_per_word;
-
- /* thresh_words will be between 2 and 8 */
- *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
- | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
-
- return retval;
-}
-
-static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
-{
- unsigned long ssp_clk = clk_get_rate(ssp->clk);
-
- if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
- return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
- else
- return ((ssp_clk / rate - 1) & 0xfff) << 8;
-}
-
-static void pump_transfers(unsigned long data)
-{
- struct driver_data *drv_data = (struct driver_data *)data;
- struct spi_message *message = NULL;
- struct spi_transfer *transfer = NULL;
- struct spi_transfer *previous = NULL;
- struct chip_data *chip = NULL;
- struct ssp_device *ssp = drv_data->ssp;
- void __iomem *reg = drv_data->ioaddr;
- u32 clk_div = 0;
- u8 bits = 0;
- u32 speed = 0;
- u32 cr0;
- u32 cr1;
- u32 dma_thresh = drv_data->cur_chip->dma_threshold;
- u32 dma_burst = drv_data->cur_chip->dma_burst_size;
-
- /* Get current state information */
- message = drv_data->cur_msg;
- transfer = drv_data->cur_transfer;
- chip = drv_data->cur_chip;
-
- /* Handle for abort */
- if (message->state == ERROR_STATE) {
- message->status = -EIO;
- giveback(drv_data);
- return;
- }
-
- /* Handle end of message */
- if (message->state == DONE_STATE) {
- message->status = 0;
- giveback(drv_data);
- return;
- }
-
- /* Delay if requested at end of transfer before CS change */
- if (message->state == RUNNING_STATE) {
- previous = list_entry(transfer->transfer_list.prev,
- struct spi_transfer,
- transfer_list);
- if (previous->delay_usecs)
- udelay(previous->delay_usecs);
-
- /* Drop chip select only if cs_change is requested */
- if (previous->cs_change)
- cs_deassert(drv_data);
- }
-
- /* Check for transfers that need multiple DMA segments */
- if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
-
- /* reject already-mapped transfers; PIO won't always work */
- if (message->is_dma_mapped
- || transfer->rx_dma || transfer->tx_dma) {
- dev_err(&drv_data->pdev->dev,
- "pump_transfers: mapped transfer length "
- "of %u is greater than %d\n",
- transfer->len, MAX_DMA_LEN);
- message->status = -EINVAL;
- giveback(drv_data);
- return;
- }
-
- /* warn ... we force this to PIO mode */
- if (printk_ratelimit())
- dev_warn(&message->spi->dev, "pump_transfers: "
- "DMA disabled for transfer length %ld "
- "greater than %d\n",
- (long)drv_data->len, MAX_DMA_LEN);
- }
-
- /* Setup the transfer state based on the type of transfer */
- if (flush(drv_data) == 0) {
- dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
- message->status = -EIO;
- giveback(drv_data);
- return;
- }
- drv_data->n_bytes = chip->n_bytes;
- drv_data->dma_width = chip->dma_width;
- drv_data->tx = (void *)transfer->tx_buf;
- drv_data->tx_end = drv_data->tx + transfer->len;
- drv_data->rx = transfer->rx_buf;
- drv_data->rx_end = drv_data->rx + transfer->len;
- drv_data->rx_dma = transfer->rx_dma;
- drv_data->tx_dma = transfer->tx_dma;
- drv_data->len = transfer->len & DCMD_LENGTH;
- drv_data->write = drv_data->tx ? chip->write : null_writer;
- drv_data->read = drv_data->rx ? chip->read : null_reader;
-
- /* Change speed and bit per word on a per transfer */
- cr0 = chip->cr0;
- if (transfer->speed_hz || transfer->bits_per_word) {
-
- bits = chip->bits_per_word;
- speed = chip->speed_hz;
-
- if (transfer->speed_hz)
- speed = transfer->speed_hz;
-
- if (transfer->bits_per_word)
- bits = transfer->bits_per_word;
-
- clk_div = ssp_get_clk_div(ssp, speed);
-
- if (bits <= 8) {
- drv_data->n_bytes = 1;
- drv_data->dma_width = DCMD_WIDTH1;
- drv_data->read = drv_data->read != null_reader ?
- u8_reader : null_reader;
- drv_data->write = drv_data->write != null_writer ?
- u8_writer : null_writer;
- } else if (bits <= 16) {
- drv_data->n_bytes = 2;
- drv_data->dma_width = DCMD_WIDTH2;
- drv_data->read = drv_data->read != null_reader ?
- u16_reader : null_reader;
- drv_data->write = drv_data->write != null_writer ?
- u16_writer : null_writer;
- } else if (bits <= 32) {
- drv_data->n_bytes = 4;
- drv_data->dma_width = DCMD_WIDTH4;
- drv_data->read = drv_data->read != null_reader ?
- u32_reader : null_reader;
- drv_data->write = drv_data->write != null_writer ?
- u32_writer : null_writer;
- }
- /* if bits/word is changed in dma mode, then must check the
- * thresholds and burst also */
- if (chip->enable_dma) {
- if (set_dma_burst_and_threshold(chip, message->spi,
- bits, &dma_burst,
- &dma_thresh))
- if (printk_ratelimit())
- dev_warn(&message->spi->dev,
- "pump_transfers: "
- "DMA burst size reduced to "
- "match bits_per_word\n");
- }
-
- cr0 = clk_div
- | SSCR0_Motorola
- | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
- | SSCR0_SSE
- | (bits > 16 ? SSCR0_EDSS : 0);
- }
-
- message->state = RUNNING_STATE;
-
- /* Try to map dma buffer and do a dma transfer if successful, but
- * only if the length is non-zero and less than MAX_DMA_LEN.
- *
- * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
- * of PIO instead. Care is needed above because the transfer may
- * have have been passed with buffers that are already dma mapped.
- * A zero-length transfer in PIO mode will not try to write/read
- * to/from the buffers
- *
- * REVISIT large transfers are exactly where we most want to be
- * using DMA. If this happens much, split those transfers into
- * multiple DMA segments rather than forcing PIO.
- */
- drv_data->dma_mapped = 0;
- if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
- drv_data->dma_mapped = map_dma_buffers(drv_data);
- if (drv_data->dma_mapped) {
-
- /* Ensure we have the correct interrupt handler */
- drv_data->transfer_handler = dma_transfer;
-
- /* Setup rx DMA Channel */
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
- DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
- DTADR(drv_data->rx_channel) = drv_data->rx_dma;
- if (drv_data->rx == drv_data->null_dma_buf)
- /* No target address increment */
- DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
- | drv_data->dma_width
- | dma_burst
- | drv_data->len;
- else
- DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
- | DCMD_FLOWSRC
- | drv_data->dma_width
- | dma_burst
- | drv_data->len;
-
- /* Setup tx DMA Channel */
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- DSADR(drv_data->tx_channel) = drv_data->tx_dma;
- DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
- if (drv_data->tx == drv_data->null_dma_buf)
- /* No source address increment */
- DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
- | drv_data->dma_width
- | dma_burst
- | drv_data->len;
- else
- DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
- | DCMD_FLOWTRG
- | drv_data->dma_width
- | dma_burst
- | drv_data->len;
-
- /* Enable dma end irqs on SSP to detect end of transfer */
- if (drv_data->ssp_type == PXA25x_SSP)
- DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
-
- /* Clear status and start DMA engine */
- cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
- write_SSSR(drv_data->clear_sr, reg);
- DCSR(drv_data->rx_channel) |= DCSR_RUN;
- DCSR(drv_data->tx_channel) |= DCSR_RUN;
- } else {
- /* Ensure we have the correct interrupt handler */
- drv_data->transfer_handler = interrupt_transfer;
-
- /* Clear status */
- cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
- write_SSSR_CS(drv_data, drv_data->clear_sr);
- }
-
- /* see if we need to reload the config registers */
- if ((read_SSCR0(reg) != cr0)
- || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
- (cr1 & SSCR1_CHANGE_MASK)) {
-
- /* stop the SSP, and update the other bits */
- write_SSCR0(cr0 & ~SSCR0_SSE, reg);
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(chip->timeout, reg);
- /* first set CR1 without interrupt and service enables */
- write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
- /* restart the SSP */
- write_SSCR0(cr0, reg);
-
- } else {
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(chip->timeout, reg);
- }
-
- cs_assert(drv_data);
-
- /* after chip select, release the data by enabling service
- * requests and interrupts, without changing any mode bits */
- write_SSCR1(cr1, reg);
-}
-
-static void pump_messages(struct work_struct *work)
-{
- struct driver_data *drv_data =
- container_of(work, struct driver_data, pump_messages);
- unsigned long flags;
-
- /* Lock queue and check for queue work */
- spin_lock_irqsave(&drv_data->lock, flags);
- if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
- drv_data->busy = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Make sure we are not already running a message */
- if (drv_data->cur_msg) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
-
- /* Extract head of queue */
- drv_data->cur_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
- list_del_init(&drv_data->cur_msg->queue);
-
- /* Initial message state*/
- drv_data->cur_msg->state = START_STATE;
- drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
- struct spi_transfer,
- transfer_list);
-
- /* prepare to setup the SSP, in pump_transfers, using the per
- * chip configuration */
- drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-
- /* Mark as busy and launch transfers */
- tasklet_schedule(&drv_data->pump_transfers);
-
- drv_data->busy = 1;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-static int transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct driver_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (drv_data->run == QUEUE_STOPPED) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -ESHUTDOWN;
- }
-
- msg->actual_length = 0;
- msg->status = -EINPROGRESS;
- msg->state = START_STATE;
-
- list_add_tail(&msg->queue, &drv_data->queue);
-
- if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return 0;
-}
-
-static int setup_cs(struct spi_device *spi, struct chip_data *chip,
- struct pxa2xx_spi_chip *chip_info)
-{
- int err = 0;
-
- if (chip == NULL || chip_info == NULL)
- return 0;
-
- /* NOTE: setup() can be called multiple times, possibly with
- * different chip_info, release previously requested GPIO
- */
- if (gpio_is_valid(chip->gpio_cs))
- gpio_free(chip->gpio_cs);
-
- /* If (*cs_control) is provided, ignore GPIO chip select */
- if (chip_info->cs_control) {
- chip->cs_control = chip_info->cs_control;
- return 0;
- }
-
- if (gpio_is_valid(chip_info->gpio_cs)) {
- err = gpio_request(chip_info->gpio_cs, "SPI_CS");
- if (err) {
- dev_err(&spi->dev, "failed to request chip select "
- "GPIO%d\n", chip_info->gpio_cs);
- return err;
- }
-
- chip->gpio_cs = chip_info->gpio_cs;
- chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
-
- err = gpio_direction_output(chip->gpio_cs,
- !chip->gpio_cs_inverted);
- }
-
- return err;
-}
-
-static int setup(struct spi_device *spi)
-{
- struct pxa2xx_spi_chip *chip_info = NULL;
- struct chip_data *chip;
- struct driver_data *drv_data = spi_master_get_devdata(spi->master);
- struct ssp_device *ssp = drv_data->ssp;
- unsigned int clk_div;
- uint tx_thres = TX_THRESH_DFLT;
- uint rx_thres = RX_THRESH_DFLT;
-
- if (!pxa25x_ssp_comp(drv_data)
- && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
- dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
- "b/w not 4-32 for type non-PXA25x_SSP\n",
- drv_data->ssp_type, spi->bits_per_word);
- return -EINVAL;
- } else if (pxa25x_ssp_comp(drv_data)
- && (spi->bits_per_word < 4
- || spi->bits_per_word > 16)) {
- dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
- "b/w not 4-16 for type PXA25x_SSP\n",
- drv_data->ssp_type, spi->bits_per_word);
- return -EINVAL;
- }
-
- /* Only alloc on first setup */
- chip = spi_get_ctldata(spi);
- if (!chip) {
- chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
- if (!chip) {
- dev_err(&spi->dev,
- "failed setup: can't allocate chip data\n");
- return -ENOMEM;
- }
-
- if (drv_data->ssp_type == CE4100_SSP) {
- if (spi->chip_select > 4) {
- dev_err(&spi->dev, "failed setup: "
- "cs number must not be > 4.\n");
- kfree(chip);
- return -EINVAL;
- }
-
- chip->frm = spi->chip_select;
- } else
- chip->gpio_cs = -1;
- chip->enable_dma = 0;
- chip->timeout = TIMOUT_DFLT;
- chip->dma_burst_size = drv_data->master_info->enable_dma ?
- DCMD_BURST8 : 0;
- }
-
- /* protocol drivers may change the chip settings, so...
- * if chip_info exists, use it */
- chip_info = spi->controller_data;
-
- /* chip_info isn't always needed */
- chip->cr1 = 0;
- if (chip_info) {
- if (chip_info->timeout)
- chip->timeout = chip_info->timeout;
- if (chip_info->tx_threshold)
- tx_thres = chip_info->tx_threshold;
- if (chip_info->rx_threshold)
- rx_thres = chip_info->rx_threshold;
- chip->enable_dma = drv_data->master_info->enable_dma;
- chip->dma_threshold = 0;
- if (chip_info->enable_loopback)
- chip->cr1 = SSCR1_LBM;
- }
-
- chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
- (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
-
- /* set dma burst and threshold outside of chip_info path so that if
- * chip_info goes away after setting chip->enable_dma, the
- * burst and threshold can still respond to changes in bits_per_word */
- if (chip->enable_dma) {
- /* set up legal burst and threshold for dma */
- if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word,
- &chip->dma_burst_size,
- &chip->dma_threshold)) {
- dev_warn(&spi->dev, "in setup: DMA burst size reduced "
- "to match bits_per_word\n");
- }
- }
-
- clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
- chip->speed_hz = spi->max_speed_hz;
-
- chip->cr0 = clk_div
- | SSCR0_Motorola
- | SSCR0_DataSize(spi->bits_per_word > 16 ?
- spi->bits_per_word - 16 : spi->bits_per_word)
- | SSCR0_SSE
- | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
- chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
- chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
- | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
-
- /* NOTE: PXA25x_SSP _could_ use external clocking ... */
- if (!pxa25x_ssp_comp(drv_data))
- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
- clk_get_rate(ssp->clk)
- / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
- chip->enable_dma ? "DMA" : "PIO");
- else
- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
- clk_get_rate(ssp->clk) / 2
- / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
- chip->enable_dma ? "DMA" : "PIO");
-
- if (spi->bits_per_word <= 8) {
- chip->n_bytes = 1;
- chip->dma_width = DCMD_WIDTH1;
- chip->read = u8_reader;
- chip->write = u8_writer;
- } else if (spi->bits_per_word <= 16) {
- chip->n_bytes = 2;
- chip->dma_width = DCMD_WIDTH2;
- chip->read = u16_reader;
- chip->write = u16_writer;
- } else if (spi->bits_per_word <= 32) {
- chip->cr0 |= SSCR0_EDSS;
- chip->n_bytes = 4;
- chip->dma_width = DCMD_WIDTH4;
- chip->read = u32_reader;
- chip->write = u32_writer;
- } else {
- dev_err(&spi->dev, "invalid wordsize\n");
- return -ENODEV;
- }
- chip->bits_per_word = spi->bits_per_word;
-
- spi_set_ctldata(spi, chip);
-
- if (drv_data->ssp_type == CE4100_SSP)
- return 0;
-
- return setup_cs(spi, chip, chip_info);
-}
-
-static void cleanup(struct spi_device *spi)
-{
- struct chip_data *chip = spi_get_ctldata(spi);
- struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-
- if (!chip)
- return;
-
- if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
- gpio_free(chip->gpio_cs);
-
- kfree(chip);
-}
-
-static int __devinit init_queue(struct driver_data *drv_data)
-{
- INIT_LIST_HEAD(&drv_data->queue);
- spin_lock_init(&drv_data->lock);
-
- drv_data->run = QUEUE_STOPPED;
- drv_data->busy = 0;
-
- tasklet_init(&drv_data->pump_transfers,
- pump_transfers, (unsigned long)drv_data);
-
- INIT_WORK(&drv_data->pump_messages, pump_messages);
- drv_data->workqueue = create_singlethread_workqueue(
- dev_name(drv_data->master->dev.parent));
- if (drv_data->workqueue == NULL)
- return -EBUSY;
-
- return 0;
-}
-
-static int start_queue(struct driver_data *drv_data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -EBUSY;
- }
-
- drv_data->run = QUEUE_RUNNING;
- drv_data->cur_msg = NULL;
- drv_data->cur_transfer = NULL;
- drv_data->cur_chip = NULL;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
- return 0;
-}
-
-static int stop_queue(struct driver_data *drv_data)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&drv_data->lock, flags);
-
- /* This is a bit lame, but is optimized for the common execution path.
- * A wait_queue on the drv_data->busy could be used, but then the common
- * execution path (pump_messages) would be required to call wake_up or
- * friends on every SPI message. Do this instead */
- drv_data->run = QUEUE_STOPPED;
- while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- msleep(10);
- spin_lock_irqsave(&drv_data->lock, flags);
- }
-
- if (!list_empty(&drv_data->queue) || drv_data->busy)
- status = -EBUSY;
-
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return status;
-}
-
-static int destroy_queue(struct driver_data *drv_data)
-{
- int status;
-
- status = stop_queue(drv_data);
- /* we are unloading the module or failing to load (only two calls
- * to this routine), and neither call can handle a return value.
- * However, destroy_workqueue calls flush_workqueue, and that will
- * block until all work is done. If the reason that stop_queue
- * timed out is that the work will never finish, then it does no
- * good to call destroy_workqueue, so return anyway. */
- if (status != 0)
- return status;
-
- destroy_workqueue(drv_data->workqueue);
-
- return 0;
-}
-
-static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct pxa2xx_spi_master *platform_info;
- struct spi_master *master;
- struct driver_data *drv_data;
- struct ssp_device *ssp;
- int status;
-
- platform_info = dev->platform_data;
-
- ssp = pxa_ssp_request(pdev->id, pdev->name);
- if (ssp == NULL) {
- dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id);
- return -ENODEV;
- }
-
- /* Allocate master with space for drv_data and null dma buffer */
- master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
- if (!master) {
- dev_err(&pdev->dev, "cannot alloc spi_master\n");
- pxa_ssp_free(ssp);
- return -ENOMEM;
- }
- drv_data = spi_master_get_devdata(master);
- drv_data->master = master;
- drv_data->master_info = platform_info;
- drv_data->pdev = pdev;
- drv_data->ssp = ssp;
-
- master->dev.parent = &pdev->dev;
- master->dev.of_node = pdev->dev.of_node;
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- master->bus_num = pdev->id;
- master->num_chipselect = platform_info->num_chipselect;
- master->dma_alignment = DMA_ALIGNMENT;
- master->cleanup = cleanup;
- master->setup = setup;
- master->transfer = transfer;
-
- drv_data->ssp_type = ssp->type;
- drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
- sizeof(struct driver_data)), 8);
-
- drv_data->ioaddr = ssp->mmio_base;
- drv_data->ssdr_physical = ssp->phys_base + SSDR;
- if (pxa25x_ssp_comp(drv_data)) {
- drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
- drv_data->dma_cr1 = 0;
- drv_data->clear_sr = SSSR_ROR;
- drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
- } else {
- drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
- drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE;
- drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
- drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
- }
-
- status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
- drv_data);
- if (status < 0) {
- dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
- goto out_error_master_alloc;
- }
-
- /* Setup DMA if requested */
- drv_data->tx_channel = -1;
- drv_data->rx_channel = -1;
- if (platform_info->enable_dma) {
-
- /* Get two DMA channels (rx and tx) */
- drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
- DMA_PRIO_HIGH,
- dma_handler,
- drv_data);
- if (drv_data->rx_channel < 0) {
- dev_err(dev, "problem (%d) requesting rx channel\n",
- drv_data->rx_channel);
- status = -ENODEV;
- goto out_error_irq_alloc;
- }
- drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
- DMA_PRIO_MEDIUM,
- dma_handler,
- drv_data);
- if (drv_data->tx_channel < 0) {
- dev_err(dev, "problem (%d) requesting tx channel\n",
- drv_data->tx_channel);
- status = -ENODEV;
- goto out_error_dma_alloc;
- }
-
- DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
- DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
- }
-
- /* Enable SOC clock */
- clk_enable(ssp->clk);
-
- /* Load default SSP configuration */
- write_SSCR0(0, drv_data->ioaddr);
- write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
- SSCR1_TxTresh(TX_THRESH_DFLT),
- drv_data->ioaddr);
- write_SSCR0(SSCR0_SCR(2)
- | SSCR0_Motorola
- | SSCR0_DataSize(8),
- drv_data->ioaddr);
- if (!pxa25x_ssp_comp(drv_data))
- write_SSTO(0, drv_data->ioaddr);
- write_SSPSP(0, drv_data->ioaddr);
-
- /* Initial and start queue */
- status = init_queue(drv_data);
- if (status != 0) {
- dev_err(&pdev->dev, "problem initializing queue\n");
- goto out_error_clock_enabled;
- }
- status = start_queue(drv_data);
- if (status != 0) {
- dev_err(&pdev->dev, "problem starting queue\n");
- goto out_error_clock_enabled;
- }
-
- /* Register with the SPI framework */
- platform_set_drvdata(pdev, drv_data);
- status = spi_register_master(master);
- if (status != 0) {
- dev_err(&pdev->dev, "problem registering spi master\n");
- goto out_error_queue_alloc;
- }
-
- return status;
-
-out_error_queue_alloc:
- destroy_queue(drv_data);
-
-out_error_clock_enabled:
- clk_disable(ssp->clk);
-
-out_error_dma_alloc:
- if (drv_data->tx_channel != -1)
- pxa_free_dma(drv_data->tx_channel);
- if (drv_data->rx_channel != -1)
- pxa_free_dma(drv_data->rx_channel);
-
-out_error_irq_alloc:
- free_irq(ssp->irq, drv_data);
-
-out_error_master_alloc:
- spi_master_put(master);
- pxa_ssp_free(ssp);
- return status;
-}
-
-static int pxa2xx_spi_remove(struct platform_device *pdev)
-{
- struct driver_data *drv_data = platform_get_drvdata(pdev);
- struct ssp_device *ssp;
- int status = 0;
-
- if (!drv_data)
- return 0;
- ssp = drv_data->ssp;
-
- /* Remove the queue */
- status = destroy_queue(drv_data);
- if (status != 0)
- /* the kernel does not check the return status of this
- * this routine (mod->exit, within the kernel). Therefore
- * nothing is gained by returning from here, the module is
- * going away regardless, and we should not leave any more
- * resources allocated than necessary. We cannot free the
- * message memory in drv_data->queue, but we can release the
- * resources below. I think the kernel should honor -EBUSY
- * returns but... */
- dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
- "complete, message memory not freed\n");
-
- /* Disable the SSP at the peripheral and SOC level */
- write_SSCR0(0, drv_data->ioaddr);
- clk_disable(ssp->clk);
-
- /* Release DMA */
- if (drv_data->master_info->enable_dma) {
- DRCMR(ssp->drcmr_rx) = 0;
- DRCMR(ssp->drcmr_tx) = 0;
- pxa_free_dma(drv_data->tx_channel);
- pxa_free_dma(drv_data->rx_channel);
- }
-
- /* Release IRQ */
- free_irq(ssp->irq, drv_data);
-
- /* Release SSP */
- pxa_ssp_free(ssp);
-
- /* Disconnect from the SPI framework */
- spi_unregister_master(drv_data->master);
-
- /* Prevent double remove */
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-static void pxa2xx_spi_shutdown(struct platform_device *pdev)
-{
- int status = 0;
-
- if ((status = pxa2xx_spi_remove(pdev)) != 0)
- dev_err(&pdev->dev, "shutdown failed with %d\n", status);
-}
-
-#ifdef CONFIG_PM
-static int pxa2xx_spi_suspend(struct device *dev)
-{
- struct driver_data *drv_data = dev_get_drvdata(dev);
- struct ssp_device *ssp = drv_data->ssp;
- int status = 0;
-
- status = stop_queue(drv_data);
- if (status != 0)
- return status;
- write_SSCR0(0, drv_data->ioaddr);
- clk_disable(ssp->clk);
-
- return 0;
-}
-
-static int pxa2xx_spi_resume(struct device *dev)
-{
- struct driver_data *drv_data = dev_get_drvdata(dev);
- struct ssp_device *ssp = drv_data->ssp;
- int status = 0;
-
- if (drv_data->rx_channel != -1)
- DRCMR(drv_data->ssp->drcmr_rx) =
- DRCMR_MAPVLD | drv_data->rx_channel;
- if (drv_data->tx_channel != -1)
- DRCMR(drv_data->ssp->drcmr_tx) =
- DRCMR_MAPVLD | drv_data->tx_channel;
-
- /* Enable the SSP clock */
- clk_enable(ssp->clk);
-
- /* Start the queue running */
- status = start_queue(drv_data);
- if (status != 0) {
- dev_err(dev, "problem starting queue (%d)\n", status);
- return status;
- }
-
- return 0;
-}
-
-static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
- .suspend = pxa2xx_spi_suspend,
- .resume = pxa2xx_spi_resume,
-};
-#endif
-
-static struct platform_driver driver = {
- .driver = {
- .name = "pxa2xx-spi",
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &pxa2xx_spi_pm_ops,
-#endif
- },
- .probe = pxa2xx_spi_probe,
- .remove = pxa2xx_spi_remove,
- .shutdown = pxa2xx_spi_shutdown,
-};
-
-static int __init pxa2xx_spi_init(void)
-{
- return platform_driver_register(&driver);
-}
-subsys_initcall(pxa2xx_spi_init);
-
-static void __exit pxa2xx_spi_exit(void)
-{
- platform_driver_unregister(&driver);
-}
-module_exit(pxa2xx_spi_exit);
diff --git a/ANDROID_3.4.5/drivers/spi/spi-rspi.c b/ANDROID_3.4.5/drivers/spi/spi-rspi.c
deleted file mode 100644
index 354f170e..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-rspi.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * SH RSPI driver
- *
- * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * Based on spi-sh.c:
- * Copyright (C) 2011 Renesas Solutions Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/spi/spi.h>
-
-#define RSPI_SPCR 0x00
-#define RSPI_SSLP 0x01
-#define RSPI_SPPCR 0x02
-#define RSPI_SPSR 0x03
-#define RSPI_SPDR 0x04
-#define RSPI_SPSCR 0x08
-#define RSPI_SPSSR 0x09
-#define RSPI_SPBR 0x0a
-#define RSPI_SPDCR 0x0b
-#define RSPI_SPCKD 0x0c
-#define RSPI_SSLND 0x0d
-#define RSPI_SPND 0x0e
-#define RSPI_SPCR2 0x0f
-#define RSPI_SPCMD0 0x10
-#define RSPI_SPCMD1 0x12
-#define RSPI_SPCMD2 0x14
-#define RSPI_SPCMD3 0x16
-#define RSPI_SPCMD4 0x18
-#define RSPI_SPCMD5 0x1a
-#define RSPI_SPCMD6 0x1c
-#define RSPI_SPCMD7 0x1e
-
-/* SPCR */
-#define SPCR_SPRIE 0x80
-#define SPCR_SPE 0x40
-#define SPCR_SPTIE 0x20
-#define SPCR_SPEIE 0x10
-#define SPCR_MSTR 0x08
-#define SPCR_MODFEN 0x04
-#define SPCR_TXMD 0x02
-#define SPCR_SPMS 0x01
-
-/* SSLP */
-#define SSLP_SSL1P 0x02
-#define SSLP_SSL0P 0x01
-
-/* SPPCR */
-#define SPPCR_MOIFE 0x20
-#define SPPCR_MOIFV 0x10
-#define SPPCR_SPOM 0x04
-#define SPPCR_SPLP2 0x02
-#define SPPCR_SPLP 0x01
-
-/* SPSR */
-#define SPSR_SPRF 0x80
-#define SPSR_SPTEF 0x20
-#define SPSR_PERF 0x08
-#define SPSR_MODF 0x04
-#define SPSR_IDLNF 0x02
-#define SPSR_OVRF 0x01
-
-/* SPSCR */
-#define SPSCR_SPSLN_MASK 0x07
-
-/* SPSSR */
-#define SPSSR_SPECM_MASK 0x70
-#define SPSSR_SPCP_MASK 0x07
-
-/* SPDCR */
-#define SPDCR_SPLW 0x20
-#define SPDCR_SPRDTD 0x10
-#define SPDCR_SLSEL1 0x08
-#define SPDCR_SLSEL0 0x04
-#define SPDCR_SLSEL_MASK 0x0c
-#define SPDCR_SPFC1 0x02
-#define SPDCR_SPFC0 0x01
-
-/* SPCKD */
-#define SPCKD_SCKDL_MASK 0x07
-
-/* SSLND */
-#define SSLND_SLNDL_MASK 0x07
-
-/* SPND */
-#define SPND_SPNDL_MASK 0x07
-
-/* SPCR2 */
-#define SPCR2_PTE 0x08
-#define SPCR2_SPIE 0x04
-#define SPCR2_SPOE 0x02
-#define SPCR2_SPPE 0x01
-
-/* SPCMDn */
-#define SPCMD_SCKDEN 0x8000
-#define SPCMD_SLNDEN 0x4000
-#define SPCMD_SPNDEN 0x2000
-#define SPCMD_LSBF 0x1000
-#define SPCMD_SPB_MASK 0x0f00
-#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
-#define SPCMD_SPB_20BIT 0x0000
-#define SPCMD_SPB_24BIT 0x0100
-#define SPCMD_SPB_32BIT 0x0200
-#define SPCMD_SSLKP 0x0080
-#define SPCMD_SSLA_MASK 0x0030
-#define SPCMD_BRDV_MASK 0x000c
-#define SPCMD_CPOL 0x0002
-#define SPCMD_CPHA 0x0001
-
-struct rspi_data {
- void __iomem *addr;
- u32 max_speed_hz;
- struct spi_master *master;
- struct list_head queue;
- struct work_struct ws;
- wait_queue_head_t wait;
- spinlock_t lock;
- struct clk *clk;
- unsigned char spsr;
-};
-
-static void rspi_write8(struct rspi_data *rspi, u8 data, u16 offset)
-{
- iowrite8(data, rspi->addr + offset);
-}
-
-static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset)
-{
- iowrite16(data, rspi->addr + offset);
-}
-
-static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
-{
- return ioread8(rspi->addr + offset);
-}
-
-static u16 rspi_read16(struct rspi_data *rspi, u16 offset)
-{
- return ioread16(rspi->addr + offset);
-}
-
-static unsigned char rspi_calc_spbr(struct rspi_data *rspi)
-{
- int tmp;
- unsigned char spbr;
-
- tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
- spbr = clamp(tmp, 0, 255);
-
- return spbr;
-}
-
-static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
-{
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
-}
-
-static void rspi_disable_irq(struct rspi_data *rspi, u8 disable)
-{
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
-}
-
-static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
- u8 enable_bit)
-{
- int ret;
-
- rspi->spsr = rspi_read8(rspi, RSPI_SPSR);
- rspi_enable_irq(rspi, enable_bit);
- ret = wait_event_timeout(rspi->wait, rspi->spsr & wait_mask, HZ);
- if (ret == 0 && !(rspi->spsr & wait_mask))
- return -ETIMEDOUT;
-
- return 0;
-}
-
-static void rspi_assert_ssl(struct rspi_data *rspi)
-{
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
-}
-
-static void rspi_negate_ssl(struct rspi_data *rspi)
-{
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
-}
-
-static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
-{
- /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
- rspi_write8(rspi, 0x00, RSPI_SPPCR);
-
- /* Sets transfer bit rate */
- rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR);
-
- /* Sets number of frames to be used: 1 frame */
- rspi_write8(rspi, 0x00, RSPI_SPDCR);
-
- /* Sets RSPCK, SSL, next-access delay value */
- rspi_write8(rspi, 0x00, RSPI_SPCKD);
- rspi_write8(rspi, 0x00, RSPI_SSLND);
- rspi_write8(rspi, 0x00, RSPI_SPND);
-
- /* Sets parity, interrupt mask */
- rspi_write8(rspi, 0x00, RSPI_SPCR2);
-
- /* Sets SPCMD */
- rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
- RSPI_SPCMD0);
-
- /* Sets RSPI mode */
- rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
-
- return 0;
-}
-
-static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
- struct spi_transfer *t)
-{
- int remain = t->len;
- u8 *data;
-
- data = (u8 *)t->tx_buf;
- while (remain > 0) {
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
- RSPI_SPCR);
-
- if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: tx empty timeout\n", __func__);
- return -ETIMEDOUT;
- }
-
- rspi_write16(rspi, *data, RSPI_SPDR);
- data++;
- remain--;
- }
-
- /* Waiting for the last transmition */
- rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
-
- return 0;
-}
-
-static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
- struct spi_transfer *t)
-{
- int remain = t->len;
- u8 *data;
- unsigned char spsr;
-
- spsr = rspi_read8(rspi, RSPI_SPSR);
- if (spsr & SPSR_SPRF)
- rspi_read16(rspi, RSPI_SPDR); /* dummy read */
- if (spsr & SPSR_OVRF)
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
- RSPI_SPCR);
-
- data = (u8 *)t->rx_buf;
- while (remain > 0) {
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
- RSPI_SPCR);
-
- if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: tx empty timeout\n", __func__);
- return -ETIMEDOUT;
- }
- /* dummy write for generate clock */
- rspi_write16(rspi, 0x00, RSPI_SPDR);
-
- if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
- dev_err(&rspi->master->dev,
- "%s: receive timeout\n", __func__);
- return -ETIMEDOUT;
- }
- /* SPDR allows 16 or 32-bit access only */
- *data = (u8)rspi_read16(rspi, RSPI_SPDR);
-
- data++;
- remain--;
- }
-
- return 0;
-}
-
-static void rspi_work(struct work_struct *work)
-{
- struct rspi_data *rspi = container_of(work, struct rspi_data, ws);
- struct spi_message *mesg;
- struct spi_transfer *t;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&rspi->lock, flags);
- while (!list_empty(&rspi->queue)) {
- mesg = list_entry(rspi->queue.next, struct spi_message, queue);
- list_del_init(&mesg->queue);
- spin_unlock_irqrestore(&rspi->lock, flags);
-
- rspi_assert_ssl(rspi);
-
- list_for_each_entry(t, &mesg->transfers, transfer_list) {
- if (t->tx_buf) {
- ret = rspi_send_pio(rspi, mesg, t);
- if (ret < 0)
- goto error;
- }
- if (t->rx_buf) {
- ret = rspi_receive_pio(rspi, mesg, t);
- if (ret < 0)
- goto error;
- }
- mesg->actual_length += t->len;
- }
- rspi_negate_ssl(rspi);
-
- mesg->status = 0;
- mesg->complete(mesg->context);
-
- spin_lock_irqsave(&rspi->lock, flags);
- }
-
- return;
-
-error:
- mesg->status = ret;
- mesg->complete(mesg->context);
-}
-
-static int rspi_setup(struct spi_device *spi)
-{
- struct rspi_data *rspi = spi_master_get_devdata(spi->master);
-
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
- rspi->max_speed_hz = spi->max_speed_hz;
-
- rspi_set_config_register(rspi, 8);
-
- return 0;
-}
-
-static int rspi_transfer(struct spi_device *spi, struct spi_message *mesg)
-{
- struct rspi_data *rspi = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- mesg->actual_length = 0;
- mesg->status = -EINPROGRESS;
-
- spin_lock_irqsave(&rspi->lock, flags);
- list_add_tail(&mesg->queue, &rspi->queue);
- schedule_work(&rspi->ws);
- spin_unlock_irqrestore(&rspi->lock, flags);
-
- return 0;
-}
-
-static void rspi_cleanup(struct spi_device *spi)
-{
-}
-
-static irqreturn_t rspi_irq(int irq, void *_sr)
-{
- struct rspi_data *rspi = (struct rspi_data *)_sr;
- unsigned long spsr;
- irqreturn_t ret = IRQ_NONE;
- unsigned char disable_irq = 0;
-
- rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
- if (spsr & SPSR_SPRF)
- disable_irq |= SPCR_SPRIE;
- if (spsr & SPSR_SPTEF)
- disable_irq |= SPCR_SPTIE;
-
- if (disable_irq) {
- ret = IRQ_HANDLED;
- rspi_disable_irq(rspi, disable_irq);
- wake_up(&rspi->wait);
- }
-
- return ret;
-}
-
-static int __devexit rspi_remove(struct platform_device *pdev)
-{
- struct rspi_data *rspi = dev_get_drvdata(&pdev->dev);
-
- spi_unregister_master(rspi->master);
- free_irq(platform_get_irq(pdev, 0), rspi);
- clk_put(rspi->clk);
- iounmap(rspi->addr);
- spi_master_put(rspi->master);
-
- return 0;
-}
-
-static int __devinit rspi_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct spi_master *master;
- struct rspi_data *rspi;
- int ret, irq;
- char clk_name[16];
-
- /* get base addr */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(res == NULL)) {
- dev_err(&pdev->dev, "invalid resource\n");
- return -EINVAL;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "platform_get_irq error\n");
- return -ENODEV;
- }
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data));
- if (master == NULL) {
- dev_err(&pdev->dev, "spi_alloc_master error.\n");
- return -ENOMEM;
- }
-
- rspi = spi_master_get_devdata(master);
- dev_set_drvdata(&pdev->dev, rspi);
-
- rspi->master = master;
- rspi->addr = ioremap(res->start, resource_size(res));
- if (rspi->addr == NULL) {
- dev_err(&pdev->dev, "ioremap error.\n");
- ret = -ENOMEM;
- goto error1;
- }
-
- snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id);
- rspi->clk = clk_get(&pdev->dev, clk_name);
- if (IS_ERR(rspi->clk)) {
- dev_err(&pdev->dev, "cannot get clock\n");
- ret = PTR_ERR(rspi->clk);
- goto error2;
- }
- clk_enable(rspi->clk);
-
- INIT_LIST_HEAD(&rspi->queue);
- spin_lock_init(&rspi->lock);
- INIT_WORK(&rspi->ws, rspi_work);
- init_waitqueue_head(&rspi->wait);
-
- master->num_chipselect = 2;
- master->bus_num = pdev->id;
- master->setup = rspi_setup;
- master->transfer = rspi_transfer;
- master->cleanup = rspi_cleanup;
-
- ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi);
- if (ret < 0) {
- dev_err(&pdev->dev, "request_irq error\n");
- goto error3;
- }
-
- ret = spi_register_master(master);
- if (ret < 0) {
- dev_err(&pdev->dev, "spi_register_master error.\n");
- goto error4;
- }
-
- dev_info(&pdev->dev, "probed\n");
-
- return 0;
-
-error4:
- free_irq(irq, rspi);
-error3:
- clk_put(rspi->clk);
-error2:
- iounmap(rspi->addr);
-error1:
- spi_master_put(master);
-
- return ret;
-}
-
-static struct platform_driver rspi_driver = {
- .probe = rspi_probe,
- .remove = __devexit_p(rspi_remove),
- .driver = {
- .name = "rspi",
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(rspi_driver);
-
-MODULE_DESCRIPTION("Renesas RSPI bus driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Yoshihiro Shimoda");
-MODULE_ALIAS("platform:rspi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.S b/ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.S
deleted file mode 100644
index 059f2dc1..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.S
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_fiq.S
- *
- * Copyright 2009 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX SPI - FIQ pseudo-DMA transfer code
- *
- * 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/linkage.h>
-#include <asm/assembler.h>
-
-#include <mach/map.h>
-#include <mach/regs-irq.h>
-#include <plat/regs-spi.h>
-
-#include "spi-s3c24xx-fiq.h"
-
- .text
-
- @ entry to these routines is as follows, with the register names
- @ defined in fiq.h so that they can be shared with the C files which
- @ setup the calling registers.
- @
- @ fiq_rirq The base of the IRQ registers to find S3C2410_SRCPND
- @ fiq_rtmp Temporary register to hold tx/rx data
- @ fiq_rspi The base of the SPI register block
- @ fiq_rtx The tx buffer pointer
- @ fiq_rrx The rx buffer pointer
- @ fiq_rcount The number of bytes to move
-
- @ each entry starts with a word entry of how long it is
- @ and an offset to the irq acknowledgment word
-
-ENTRY(s3c24xx_spi_fiq_rx)
-s3c24xx_spi_fix_rx:
- .word fiq_rx_end - fiq_rx_start
- .word fiq_rx_irq_ack - fiq_rx_start
-fiq_rx_start:
- ldr fiq_rtmp, fiq_rx_irq_ack
- str fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
-
- ldrb fiq_rtmp, [ fiq_rspi, # S3C2410_SPRDAT ]
- strb fiq_rtmp, [ fiq_rrx ], #1
-
- mov fiq_rtmp, #0xff
- strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
-
- subs fiq_rcount, fiq_rcount, #1
- subnes pc, lr, #4 @@ return, still have work to do
-
- @@ set IRQ controller so that next op will trigger IRQ
- mov fiq_rtmp, #0
- str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ]
- subs pc, lr, #4
-
-fiq_rx_irq_ack:
- .word 0
-fiq_rx_end:
-
-ENTRY(s3c24xx_spi_fiq_txrx)
-s3c24xx_spi_fiq_txrx:
- .word fiq_txrx_end - fiq_txrx_start
- .word fiq_txrx_irq_ack - fiq_txrx_start
-fiq_txrx_start:
-
- ldrb fiq_rtmp, [ fiq_rspi, # S3C2410_SPRDAT ]
- strb fiq_rtmp, [ fiq_rrx ], #1
-
- ldr fiq_rtmp, fiq_txrx_irq_ack
- str fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
-
- ldrb fiq_rtmp, [ fiq_rtx ], #1
- strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
-
- subs fiq_rcount, fiq_rcount, #1
- subnes pc, lr, #4 @@ return, still have work to do
-
- mov fiq_rtmp, #0
- str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ]
- subs pc, lr, #4
-
-fiq_txrx_irq_ack:
- .word 0
-
-fiq_txrx_end:
-
-ENTRY(s3c24xx_spi_fiq_tx)
-s3c24xx_spi_fix_tx:
- .word fiq_tx_end - fiq_tx_start
- .word fiq_tx_irq_ack - fiq_tx_start
-fiq_tx_start:
- ldrb fiq_rtmp, [ fiq_rspi, # S3C2410_SPRDAT ]
-
- ldr fiq_rtmp, fiq_tx_irq_ack
- str fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
-
- ldrb fiq_rtmp, [ fiq_rtx ], #1
- strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
-
- subs fiq_rcount, fiq_rcount, #1
- subnes pc, lr, #4 @@ return, still have work to do
-
- mov fiq_rtmp, #0
- str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ]
- subs pc, lr, #4
-
-fiq_tx_irq_ack:
- .word 0
-
-fiq_tx_end:
-
- .end
diff --git a/ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.h b/ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.h
deleted file mode 100644
index a5950bb2..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-s3c24xx-fiq.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_fiq.h
- *
- * Copyright 2009 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX SPI - FIQ pseudo-DMA transfer support
- *
- * 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.
-*/
-
-/* We have R8 through R13 to play with */
-
-#ifdef __ASSEMBLY__
-#define __REG_NR(x) r##x
-#else
-#define __REG_NR(x) (x)
-#endif
-
-#define fiq_rspi __REG_NR(8)
-#define fiq_rtmp __REG_NR(9)
-#define fiq_rrx __REG_NR(10)
-#define fiq_rtx __REG_NR(11)
-#define fiq_rcount __REG_NR(12)
-#define fiq_rirq __REG_NR(13)
diff --git a/ANDROID_3.4.5/drivers/spi/spi-s3c24xx.c b/ANDROID_3.4.5/drivers/spi/spi-s3c24xx.c
deleted file mode 100644
index 8ee7d790..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-s3c24xx.c
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * Copyright (c) 2006 Ben Dooks
- * Copyright 2006-2009 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * 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/init.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/s3c24xx.h>
-#include <linux/module.h>
-
-#include <plat/regs-spi.h>
-
-#include <plat/fiq.h>
-#include <asm/fiq.h>
-
-#include "spi-s3c24xx-fiq.h"
-
-/**
- * s3c24xx_spi_devstate - per device data
- * @hz: Last frequency calculated for @sppre field.
- * @mode: Last mode setting for the @spcon field.
- * @spcon: Value to write to the SPCON register.
- * @sppre: Value to write to the SPPRE register.
- */
-struct s3c24xx_spi_devstate {
- unsigned int hz;
- unsigned int mode;
- u8 spcon;
- u8 sppre;
-};
-
-enum spi_fiq_mode {
- FIQ_MODE_NONE = 0,
- FIQ_MODE_TX = 1,
- FIQ_MODE_RX = 2,
- FIQ_MODE_TXRX = 3,
-};
-
-struct s3c24xx_spi {
- /* bitbang has to be first */
- struct spi_bitbang bitbang;
- struct completion done;
-
- void __iomem *regs;
- int irq;
- int len;
- int count;
-
- struct fiq_handler fiq_handler;
- enum spi_fiq_mode fiq_mode;
- unsigned char fiq_inuse;
- unsigned char fiq_claimed;
-
- void (*set_cs)(struct s3c2410_spi_info *spi,
- int cs, int pol);
-
- /* data buffers */
- const unsigned char *tx;
- unsigned char *rx;
-
- struct clk *clk;
- struct resource *ioarea;
- struct spi_master *master;
- struct spi_device *curdev;
- struct device *dev;
- struct s3c2410_spi_info *pdata;
-};
-
-
-#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
-#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
-
-static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
-{
- return spi_master_get_devdata(sdev->master);
-}
-
-static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
-{
- gpio_set_value(spi->pin_cs, pol);
-}
-
-static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
-{
- struct s3c24xx_spi_devstate *cs = spi->controller_state;
- struct s3c24xx_spi *hw = to_hw(spi);
- unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
-
- /* change the chipselect state and the state of the spi engine clock */
-
- switch (value) {
- case BITBANG_CS_INACTIVE:
- hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
- writeb(cs->spcon, hw->regs + S3C2410_SPCON);
- break;
-
- case BITBANG_CS_ACTIVE:
- writeb(cs->spcon | S3C2410_SPCON_ENSCK,
- hw->regs + S3C2410_SPCON);
- hw->set_cs(hw->pdata, spi->chip_select, cspol);
- break;
- }
-}
-
-static int s3c24xx_spi_update_state(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct s3c24xx_spi *hw = to_hw(spi);
- struct s3c24xx_spi_devstate *cs = spi->controller_state;
- unsigned int bpw;
- unsigned int hz;
- unsigned int div;
- unsigned long clk;
-
- bpw = t ? t->bits_per_word : spi->bits_per_word;
- hz = t ? t->speed_hz : spi->max_speed_hz;
-
- if (!bpw)
- bpw = 8;
-
- if (!hz)
- hz = spi->max_speed_hz;
-
- if (bpw != 8) {
- dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
- return -EINVAL;
- }
-
- if (spi->mode != cs->mode) {
- u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
-
- if (spi->mode & SPI_CPHA)
- spcon |= S3C2410_SPCON_CPHA_FMTB;
-
- if (spi->mode & SPI_CPOL)
- spcon |= S3C2410_SPCON_CPOL_HIGH;
-
- cs->mode = spi->mode;
- cs->spcon = spcon;
- }
-
- if (cs->hz != hz) {
- clk = clk_get_rate(hw->clk);
- div = DIV_ROUND_UP(clk, hz * 2) - 1;
-
- if (div > 255)
- div = 255;
-
- dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n",
- div, hz, clk / (2 * (div + 1)));
-
- cs->hz = hz;
- cs->sppre = div;
- }
-
- return 0;
-}
-
-static int s3c24xx_spi_setupxfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct s3c24xx_spi_devstate *cs = spi->controller_state;
- struct s3c24xx_spi *hw = to_hw(spi);
- int ret;
-
- ret = s3c24xx_spi_update_state(spi, t);
- if (!ret)
- writeb(cs->sppre, hw->regs + S3C2410_SPPRE);
-
- return ret;
-}
-
-static int s3c24xx_spi_setup(struct spi_device *spi)
-{
- struct s3c24xx_spi_devstate *cs = spi->controller_state;
- struct s3c24xx_spi *hw = to_hw(spi);
- int ret;
-
- /* allocate settings on the first call */
- if (!cs) {
- cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
- if (!cs) {
- dev_err(&spi->dev, "no memory for controller state\n");
- return -ENOMEM;
- }
-
- cs->spcon = SPCON_DEFAULT;
- cs->hz = -1;
- spi->controller_state = cs;
- }
-
- /* initialise the state from the device */
- ret = s3c24xx_spi_update_state(spi, NULL);
- if (ret)
- return ret;
-
- spin_lock(&hw->bitbang.lock);
- if (!hw->bitbang.busy) {
- hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
- /* need to ndelay for 0.5 clocktick ? */
- }
- spin_unlock(&hw->bitbang.lock);
-
- return 0;
-}
-
-static void s3c24xx_spi_cleanup(struct spi_device *spi)
-{
- kfree(spi->controller_state);
-}
-
-static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
-{
- return hw->tx ? hw->tx[count] : 0;
-}
-
-#ifdef CONFIG_SPI_S3C24XX_FIQ
-/* Support for FIQ based pseudo-DMA to improve the transfer speed.
- *
- * This code uses the assembly helper in spi_s3c24xx_spi.S which is
- * used by the FIQ core to move data between main memory and the peripheral
- * block. Since this is code running on the processor, there is no problem
- * with cache coherency of the buffers, so we can use any buffer we like.
- */
-
-/**
- * struct spi_fiq_code - FIQ code and header
- * @length: The length of the code fragment, excluding this header.
- * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
- * @data: The code itself to install as a FIQ handler.
- */
-struct spi_fiq_code {
- u32 length;
- u32 ack_offset;
- u8 data[0];
-};
-
-extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
-extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
-extern struct spi_fiq_code s3c24xx_spi_fiq_rx;
-
-/**
- * ack_bit - turn IRQ into IRQ acknowledgement bit
- * @irq: The interrupt number
- *
- * Returns the bit to write to the interrupt acknowledge register.
- */
-static inline u32 ack_bit(unsigned int irq)
-{
- return 1 << (irq - IRQ_EINT0);
-}
-
-/**
- * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
- * @hw: The hardware state.
- *
- * Claim the FIQ handler (only one can be active at any one time) and
- * then setup the correct transfer code for this transfer.
- *
- * This call updates all the necessary state information if successful,
- * so the caller does not need to do anything more than start the transfer
- * as normal, since the IRQ will have been re-routed to the FIQ handler.
-*/
-void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
-{
- struct pt_regs regs;
- enum spi_fiq_mode mode;
- struct spi_fiq_code *code;
- int ret;
-
- if (!hw->fiq_claimed) {
- /* try and claim fiq if we haven't got it, and if not
- * then return and simply use another transfer method */
-
- ret = claim_fiq(&hw->fiq_handler);
- if (ret)
- return;
- }
-
- if (hw->tx && !hw->rx)
- mode = FIQ_MODE_TX;
- else if (hw->rx && !hw->tx)
- mode = FIQ_MODE_RX;
- else
- mode = FIQ_MODE_TXRX;
-
- regs.uregs[fiq_rspi] = (long)hw->regs;
- regs.uregs[fiq_rrx] = (long)hw->rx;
- regs.uregs[fiq_rtx] = (long)hw->tx + 1;
- regs.uregs[fiq_rcount] = hw->len - 1;
- regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;
-
- set_fiq_regs(&regs);
-
- if (hw->fiq_mode != mode) {
- u32 *ack_ptr;
-
- hw->fiq_mode = mode;
-
- switch (mode) {
- case FIQ_MODE_TX:
- code = &s3c24xx_spi_fiq_tx;
- break;
- case FIQ_MODE_RX:
- code = &s3c24xx_spi_fiq_rx;
- break;
- case FIQ_MODE_TXRX:
- code = &s3c24xx_spi_fiq_txrx;
- break;
- default:
- code = NULL;
- }
-
- BUG_ON(!code);
-
- ack_ptr = (u32 *)&code->data[code->ack_offset];
- *ack_ptr = ack_bit(hw->irq);
-
- set_fiq_handler(&code->data, code->length);
- }
-
- s3c24xx_set_fiq(hw->irq, true);
-
- hw->fiq_mode = mode;
- hw->fiq_inuse = 1;
-}
-
-/**
- * s3c24xx_spi_fiqop - FIQ core code callback
- * @pw: Data registered with the handler
- * @release: Whether this is a release or a return.
- *
- * Called by the FIQ code when another module wants to use the FIQ, so
- * return whether we are currently using this or not and then update our
- * internal state.
- */
-static int s3c24xx_spi_fiqop(void *pw, int release)
-{
- struct s3c24xx_spi *hw = pw;
- int ret = 0;
-
- if (release) {
- if (hw->fiq_inuse)
- ret = -EBUSY;
-
- /* note, we do not need to unroute the FIQ, as the FIQ
- * vector code de-routes it to signal the end of transfer */
-
- hw->fiq_mode = FIQ_MODE_NONE;
- hw->fiq_claimed = 0;
- } else {
- hw->fiq_claimed = 1;
- }
-
- return ret;
-}
-
-/**
- * s3c24xx_spi_initfiq - setup the information for the FIQ core
- * @hw: The hardware state.
- *
- * Setup the fiq_handler block to pass to the FIQ core.
- */
-static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *hw)
-{
- hw->fiq_handler.dev_id = hw;
- hw->fiq_handler.name = dev_name(hw->dev);
- hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop;
-}
-
-/**
- * s3c24xx_spi_usefiq - return if we should be using FIQ.
- * @hw: The hardware state.
- *
- * Return true if the platform data specifies whether this channel is
- * allowed to use the FIQ.
- */
-static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *hw)
-{
- return hw->pdata->use_fiq;
-}
-
-/**
- * s3c24xx_spi_usingfiq - return if channel is using FIQ
- * @spi: The hardware state.
- *
- * Return whether the channel is currently using the FIQ (separate from
- * whether the FIQ is claimed).
- */
-static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *spi)
-{
- return spi->fiq_inuse;
-}
-#else
-
-static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *s) { }
-static inline void s3c24xx_spi_tryfiq(struct s3c24xx_spi *s) { }
-static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *s) { return false; }
-static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *s) { return false; }
-
-#endif /* CONFIG_SPI_S3C24XX_FIQ */
-
-static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct s3c24xx_spi *hw = to_hw(spi);
-
- hw->tx = t->tx_buf;
- hw->rx = t->rx_buf;
- hw->len = t->len;
- hw->count = 0;
-
- init_completion(&hw->done);
-
- hw->fiq_inuse = 0;
- if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
- s3c24xx_spi_tryfiq(hw);
-
- /* send the first byte */
- writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
-
- wait_for_completion(&hw->done);
- return hw->count;
-}
-
-static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
-{
- struct s3c24xx_spi *hw = dev;
- unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
- unsigned int count = hw->count;
-
- if (spsta & S3C2410_SPSTA_DCOL) {
- dev_dbg(hw->dev, "data-collision\n");
- complete(&hw->done);
- goto irq_done;
- }
-
- if (!(spsta & S3C2410_SPSTA_READY)) {
- dev_dbg(hw->dev, "spi not ready for tx?\n");
- complete(&hw->done);
- goto irq_done;
- }
-
- if (!s3c24xx_spi_usingfiq(hw)) {
- hw->count++;
-
- if (hw->rx)
- hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
-
- count++;
-
- if (count < hw->len)
- writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
- else
- complete(&hw->done);
- } else {
- hw->count = hw->len;
- hw->fiq_inuse = 0;
-
- if (hw->rx)
- hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT);
-
- complete(&hw->done);
- }
-
- irq_done:
- return IRQ_HANDLED;
-}
-
-static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
-{
- /* for the moment, permanently enable the clock */
-
- clk_enable(hw->clk);
-
- /* program defaults into the registers */
-
- writeb(0xff, hw->regs + S3C2410_SPPRE);
- writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
- writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
-
- if (hw->pdata) {
- if (hw->set_cs == s3c24xx_spi_gpiocs)
- gpio_direction_output(hw->pdata->pin_cs, 1);
-
- if (hw->pdata->gpio_setup)
- hw->pdata->gpio_setup(hw->pdata, 1);
- }
-}
-
-static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
-{
- struct s3c2410_spi_info *pdata;
- struct s3c24xx_spi *hw;
- struct spi_master *master;
- struct resource *res;
- int err = 0;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
- if (master == NULL) {
- dev_err(&pdev->dev, "No memory for spi_master\n");
- err = -ENOMEM;
- goto err_nomem;
- }
-
- hw = spi_master_get_devdata(master);
- memset(hw, 0, sizeof(struct s3c24xx_spi));
-
- hw->master = spi_master_get(master);
- hw->pdata = pdata = pdev->dev.platform_data;
- hw->dev = &pdev->dev;
-
- if (pdata == NULL) {
- dev_err(&pdev->dev, "No platform data supplied\n");
- err = -ENOENT;
- goto err_no_pdata;
- }
-
- platform_set_drvdata(pdev, hw);
- init_completion(&hw->done);
-
- /* initialise fiq handler */
-
- s3c24xx_spi_initfiq(hw);
-
- /* setup the master state. */
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- master->num_chipselect = hw->pdata->num_cs;
- master->bus_num = pdata->bus_num;
-
- /* setup the state for the bitbang driver */
-
- hw->bitbang.master = hw->master;
- hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
- hw->bitbang.chipselect = s3c24xx_spi_chipsel;
- hw->bitbang.txrx_bufs = s3c24xx_spi_txrx;
-
- hw->master->setup = s3c24xx_spi_setup;
- hw->master->cleanup = s3c24xx_spi_cleanup;
-
- dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
-
- /* find and map our resources */
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- err = -ENOENT;
- goto err_no_iores;
- }
-
- hw->ioarea = request_mem_region(res->start, resource_size(res),
- pdev->name);
-
- if (hw->ioarea == NULL) {
- dev_err(&pdev->dev, "Cannot reserve region\n");
- err = -ENXIO;
- goto err_no_iores;
- }
-
- hw->regs = ioremap(res->start, resource_size(res));
- if (hw->regs == NULL) {
- dev_err(&pdev->dev, "Cannot map IO\n");
- err = -ENXIO;
- goto err_no_iomap;
- }
-
- hw->irq = platform_get_irq(pdev, 0);
- if (hw->irq < 0) {
- dev_err(&pdev->dev, "No IRQ specified\n");
- err = -ENOENT;
- goto err_no_irq;
- }
-
- err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
- if (err) {
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_no_irq;
- }
-
- hw->clk = clk_get(&pdev->dev, "spi");
- if (IS_ERR(hw->clk)) {
- dev_err(&pdev->dev, "No clock for device\n");
- err = PTR_ERR(hw->clk);
- goto err_no_clk;
- }
-
- /* setup any gpio we can */
-
- if (!pdata->set_cs) {
- if (pdata->pin_cs < 0) {
- dev_err(&pdev->dev, "No chipselect pin\n");
- goto err_register;
- }
-
- err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
- if (err) {
- dev_err(&pdev->dev, "Failed to get gpio for cs\n");
- goto err_register;
- }
-
- hw->set_cs = s3c24xx_spi_gpiocs;
- gpio_direction_output(pdata->pin_cs, 1);
- } else
- hw->set_cs = pdata->set_cs;
-
- s3c24xx_spi_initialsetup(hw);
-
- /* register our spi controller */
-
- err = spi_bitbang_start(&hw->bitbang);
- if (err) {
- dev_err(&pdev->dev, "Failed to register SPI master\n");
- goto err_register;
- }
-
- return 0;
-
- err_register:
- if (hw->set_cs == s3c24xx_spi_gpiocs)
- gpio_free(pdata->pin_cs);
-
- clk_disable(hw->clk);
- clk_put(hw->clk);
-
- err_no_clk:
- free_irq(hw->irq, hw);
-
- err_no_irq:
- iounmap(hw->regs);
-
- err_no_iomap:
- release_resource(hw->ioarea);
- kfree(hw->ioarea);
-
- err_no_iores:
- err_no_pdata:
- spi_master_put(hw->master);
-
- err_nomem:
- return err;
-}
-
-static int __devexit s3c24xx_spi_remove(struct platform_device *dev)
-{
- struct s3c24xx_spi *hw = platform_get_drvdata(dev);
-
- platform_set_drvdata(dev, NULL);
-
- spi_bitbang_stop(&hw->bitbang);
-
- clk_disable(hw->clk);
- clk_put(hw->clk);
-
- free_irq(hw->irq, hw);
- iounmap(hw->regs);
-
- if (hw->set_cs == s3c24xx_spi_gpiocs)
- gpio_free(hw->pdata->pin_cs);
-
- release_resource(hw->ioarea);
- kfree(hw->ioarea);
-
- spi_master_put(hw->master);
- return 0;
-}
-
-
-#ifdef CONFIG_PM
-
-static int s3c24xx_spi_suspend(struct device *dev)
-{
- struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
-
- if (hw->pdata && hw->pdata->gpio_setup)
- hw->pdata->gpio_setup(hw->pdata, 0);
-
- clk_disable(hw->clk);
- return 0;
-}
-
-static int s3c24xx_spi_resume(struct device *dev)
-{
- struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
-
- s3c24xx_spi_initialsetup(hw);
- return 0;
-}
-
-static const struct dev_pm_ops s3c24xx_spi_pmops = {
- .suspend = s3c24xx_spi_suspend,
- .resume = s3c24xx_spi_resume,
-};
-
-#define S3C24XX_SPI_PMOPS &s3c24xx_spi_pmops
-#else
-#define S3C24XX_SPI_PMOPS NULL
-#endif /* CONFIG_PM */
-
-MODULE_ALIAS("platform:s3c2410-spi");
-static struct platform_driver s3c24xx_spi_driver = {
- .probe = s3c24xx_spi_probe,
- .remove = __devexit_p(s3c24xx_spi_remove),
- .driver = {
- .name = "s3c2410-spi",
- .owner = THIS_MODULE,
- .pm = S3C24XX_SPI_PMOPS,
- },
-};
-module_platform_driver(s3c24xx_spi_driver);
-
-MODULE_DESCRIPTION("S3C24XX SPI Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-s3c64xx.c b/ANDROID_3.4.5/drivers/spi/spi-s3c64xx.c
deleted file mode 100644
index 972a94c5..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-s3c64xx.c
+++ /dev/null
@@ -1,1258 +0,0 @@
-/*
- * Copyright (C) 2009 Samsung Electronics Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/spi/spi.h>
-
-#include <mach/dma.h>
-#include <plat/s3c64xx-spi.h>
-
-/* Registers and bit-fields */
-
-#define S3C64XX_SPI_CH_CFG 0x00
-#define S3C64XX_SPI_CLK_CFG 0x04
-#define S3C64XX_SPI_MODE_CFG 0x08
-#define S3C64XX_SPI_SLAVE_SEL 0x0C
-#define S3C64XX_SPI_INT_EN 0x10
-#define S3C64XX_SPI_STATUS 0x14
-#define S3C64XX_SPI_TX_DATA 0x18
-#define S3C64XX_SPI_RX_DATA 0x1C
-#define S3C64XX_SPI_PACKET_CNT 0x20
-#define S3C64XX_SPI_PENDING_CLR 0x24
-#define S3C64XX_SPI_SWAP_CFG 0x28
-#define S3C64XX_SPI_FB_CLK 0x2C
-
-#define S3C64XX_SPI_CH_HS_EN (1<<6) /* High Speed Enable */
-#define S3C64XX_SPI_CH_SW_RST (1<<5)
-#define S3C64XX_SPI_CH_SLAVE (1<<4)
-#define S3C64XX_SPI_CPOL_L (1<<3)
-#define S3C64XX_SPI_CPHA_B (1<<2)
-#define S3C64XX_SPI_CH_RXCH_ON (1<<1)
-#define S3C64XX_SPI_CH_TXCH_ON (1<<0)
-
-#define S3C64XX_SPI_CLKSEL_SRCMSK (3<<9)
-#define S3C64XX_SPI_CLKSEL_SRCSHFT 9
-#define S3C64XX_SPI_ENCLK_ENABLE (1<<8)
-#define S3C64XX_SPI_PSR_MASK 0xff
-
-#define S3C64XX_SPI_MODE_CH_TSZ_BYTE (0<<29)
-#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD (1<<29)
-#define S3C64XX_SPI_MODE_CH_TSZ_WORD (2<<29)
-#define S3C64XX_SPI_MODE_CH_TSZ_MASK (3<<29)
-#define S3C64XX_SPI_MODE_BUS_TSZ_BYTE (0<<17)
-#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD (1<<17)
-#define S3C64XX_SPI_MODE_BUS_TSZ_WORD (2<<17)
-#define S3C64XX_SPI_MODE_BUS_TSZ_MASK (3<<17)
-#define S3C64XX_SPI_MODE_RXDMA_ON (1<<2)
-#define S3C64XX_SPI_MODE_TXDMA_ON (1<<1)
-#define S3C64XX_SPI_MODE_4BURST (1<<0)
-
-#define S3C64XX_SPI_SLAVE_AUTO (1<<1)
-#define S3C64XX_SPI_SLAVE_SIG_INACT (1<<0)
-
-#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
-#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
- (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
-#define S3C64XX_SPI_INT_TRAILING_EN (1<<6)
-#define S3C64XX_SPI_INT_RX_OVERRUN_EN (1<<5)
-#define S3C64XX_SPI_INT_RX_UNDERRUN_EN (1<<4)
-#define S3C64XX_SPI_INT_TX_OVERRUN_EN (1<<3)
-#define S3C64XX_SPI_INT_TX_UNDERRUN_EN (1<<2)
-#define S3C64XX_SPI_INT_RX_FIFORDY_EN (1<<1)
-#define S3C64XX_SPI_INT_TX_FIFORDY_EN (1<<0)
-
-#define S3C64XX_SPI_ST_RX_OVERRUN_ERR (1<<5)
-#define S3C64XX_SPI_ST_RX_UNDERRUN_ERR (1<<4)
-#define S3C64XX_SPI_ST_TX_OVERRUN_ERR (1<<3)
-#define S3C64XX_SPI_ST_TX_UNDERRUN_ERR (1<<2)
-#define S3C64XX_SPI_ST_RX_FIFORDY (1<<1)
-#define S3C64XX_SPI_ST_TX_FIFORDY (1<<0)
-
-#define S3C64XX_SPI_PACKET_CNT_EN (1<<16)
-
-#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR (1<<4)
-#define S3C64XX_SPI_PND_TX_OVERRUN_CLR (1<<3)
-#define S3C64XX_SPI_PND_RX_UNDERRUN_CLR (1<<2)
-#define S3C64XX_SPI_PND_RX_OVERRUN_CLR (1<<1)
-#define S3C64XX_SPI_PND_TRAILING_CLR (1<<0)
-
-#define S3C64XX_SPI_SWAP_RX_HALF_WORD (1<<7)
-#define S3C64XX_SPI_SWAP_RX_BYTE (1<<6)
-#define S3C64XX_SPI_SWAP_RX_BIT (1<<5)
-#define S3C64XX_SPI_SWAP_RX_EN (1<<4)
-#define S3C64XX_SPI_SWAP_TX_HALF_WORD (1<<3)
-#define S3C64XX_SPI_SWAP_TX_BYTE (1<<2)
-#define S3C64XX_SPI_SWAP_TX_BIT (1<<1)
-#define S3C64XX_SPI_SWAP_TX_EN (1<<0)
-
-#define S3C64XX_SPI_FBCLK_MSK (3<<0)
-
-#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
- (((i)->fifo_lvl_mask + 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)
-
-#define S3C64XX_SPI_MAX_TRAILCNT 0x3ff
-#define S3C64XX_SPI_TRAILCNT_OFF 19
-
-#define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT
-
-#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-
-#define RXBUSY (1<<2)
-#define TXBUSY (1<<3)
-
-struct s3c64xx_spi_dma_data {
- unsigned ch;
- enum dma_data_direction direction;
- enum dma_ch dmach;
-};
-
-/**
- * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
- * @clk: Pointer to the spi clock.
- * @src_clk: Pointer to the clock used to generate SPI signals.
- * @master: Pointer to the SPI Protocol master.
- * @cntrlr_info: Platform specific data for the controller this driver manages.
- * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
- * @queue: To log SPI xfer requests.
- * @lock: Controller specific lock.
- * @state: Set of FLAGS to indicate status.
- * @rx_dmach: Controller's DMA channel for Rx.
- * @tx_dmach: Controller's DMA channel for Tx.
- * @sfr_start: BUS address of SPI controller regs.
- * @regs: Pointer to ioremap'ed controller registers.
- * @irq: interrupt
- * @xfer_completion: To indicate completion of xfer task.
- * @cur_mode: Stores the active configuration of the controller.
- * @cur_bpw: Stores the active bits per word settings.
- * @cur_speed: Stores the active xfer clock speed.
- */
-struct s3c64xx_spi_driver_data {
- void __iomem *regs;
- struct clk *clk;
- struct clk *src_clk;
- struct platform_device *pdev;
- struct spi_master *master;
- struct s3c64xx_spi_info *cntrlr_info;
- struct spi_device *tgl_spi;
- struct list_head queue;
- spinlock_t lock;
- unsigned long sfr_start;
- struct completion xfer_completion;
- unsigned state;
- unsigned cur_mode, cur_bpw;
- unsigned cur_speed;
- struct s3c64xx_spi_dma_data rx_dma;
- struct s3c64xx_spi_dma_data tx_dma;
- struct samsung_dma_ops *ops;
-};
-
-static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
- .name = "samsung-spi-dma",
-};
-
-static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- void __iomem *regs = sdd->regs;
- unsigned long loops;
- u32 val;
-
- writel(0, regs + S3C64XX_SPI_PACKET_CNT);
-
- val = readl(regs + S3C64XX_SPI_CH_CFG);
- val |= S3C64XX_SPI_CH_SW_RST;
- val &= ~S3C64XX_SPI_CH_HS_EN;
- writel(val, regs + S3C64XX_SPI_CH_CFG);
-
- /* Flush TxFIFO*/
- loops = msecs_to_loops(1);
- do {
- val = readl(regs + S3C64XX_SPI_STATUS);
- } while (TX_FIFO_LVL(val, sci) && loops--);
-
- if (loops == 0)
- dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
-
- /* Flush RxFIFO*/
- loops = msecs_to_loops(1);
- do {
- val = readl(regs + S3C64XX_SPI_STATUS);
- if (RX_FIFO_LVL(val, sci))
- readl(regs + S3C64XX_SPI_RX_DATA);
- else
- break;
- } while (loops--);
-
- if (loops == 0)
- dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n");
-
- val = readl(regs + S3C64XX_SPI_CH_CFG);
- val &= ~S3C64XX_SPI_CH_SW_RST;
- writel(val, regs + S3C64XX_SPI_CH_CFG);
-
- val = readl(regs + S3C64XX_SPI_MODE_CFG);
- val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
- writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
- val = readl(regs + S3C64XX_SPI_CH_CFG);
- val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
- writel(val, regs + S3C64XX_SPI_CH_CFG);
-}
-
-static void s3c64xx_spi_dmacb(void *data)
-{
- struct s3c64xx_spi_driver_data *sdd;
- struct s3c64xx_spi_dma_data *dma = data;
- unsigned long flags;
-
- if (dma->direction == DMA_DEV_TO_MEM)
- sdd = container_of(data,
- struct s3c64xx_spi_driver_data, rx_dma);
- else
- sdd = container_of(data,
- struct s3c64xx_spi_driver_data, tx_dma);
-
- spin_lock_irqsave(&sdd->lock, flags);
-
- if (dma->direction == DMA_DEV_TO_MEM) {
- sdd->state &= ~RXBUSY;
- if (!(sdd->state & TXBUSY))
- complete(&sdd->xfer_completion);
- } else {
- sdd->state &= ~TXBUSY;
- if (!(sdd->state & RXBUSY))
- complete(&sdd->xfer_completion);
- }
-
- spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
- unsigned len, dma_addr_t buf)
-{
- struct s3c64xx_spi_driver_data *sdd;
- struct samsung_dma_prep_info info;
-
- if (dma->direction == DMA_DEV_TO_MEM)
- sdd = container_of((void *)dma,
- struct s3c64xx_spi_driver_data, rx_dma);
- else
- sdd = container_of((void *)dma,
- struct s3c64xx_spi_driver_data, tx_dma);
-
- info.cap = DMA_SLAVE;
- info.len = len;
- info.fp = s3c64xx_spi_dmacb;
- info.fp_param = dma;
- info.direction = dma->direction;
- info.buf = buf;
-
- sdd->ops->prepare(dma->ch, &info);
- sdd->ops->trigger(dma->ch);
-}
-
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
- struct samsung_dma_info info;
-
- sdd->ops = samsung_dma_get_ops();
-
- info.cap = DMA_SLAVE;
- info.client = &s3c64xx_spi_dma_client;
- info.width = sdd->cur_bpw / 8;
-
- info.direction = sdd->rx_dma.direction;
- info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
- sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
- info.direction = sdd->tx_dma.direction;
- info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
- sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
-
- return 1;
-}
-
-static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
- struct spi_device *spi,
- struct spi_transfer *xfer, int dma_mode)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- void __iomem *regs = sdd->regs;
- u32 modecfg, chcfg;
-
- modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
- modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
-
- chcfg = readl(regs + S3C64XX_SPI_CH_CFG);
- chcfg &= ~S3C64XX_SPI_CH_TXCH_ON;
-
- if (dma_mode) {
- chcfg &= ~S3C64XX_SPI_CH_RXCH_ON;
- } else {
- /* Always shift in data in FIFO, even if xfer is Tx only,
- * this helps setting PCKT_CNT value for generating clocks
- * as exactly needed.
- */
- chcfg |= S3C64XX_SPI_CH_RXCH_ON;
- writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
- | S3C64XX_SPI_PACKET_CNT_EN,
- regs + S3C64XX_SPI_PACKET_CNT);
- }
-
- if (xfer->tx_buf != NULL) {
- sdd->state |= TXBUSY;
- chcfg |= S3C64XX_SPI_CH_TXCH_ON;
- if (dma_mode) {
- modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
- prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
- } else {
- switch (sdd->cur_bpw) {
- case 32:
- iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
- xfer->tx_buf, xfer->len / 4);
- break;
- case 16:
- iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
- xfer->tx_buf, xfer->len / 2);
- break;
- default:
- iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
- xfer->tx_buf, xfer->len);
- break;
- }
- }
- }
-
- if (xfer->rx_buf != NULL) {
- sdd->state |= RXBUSY;
-
- if (sci->high_speed && sdd->cur_speed >= 30000000UL
- && !(sdd->cur_mode & SPI_CPHA))
- chcfg |= S3C64XX_SPI_CH_HS_EN;
-
- if (dma_mode) {
- modecfg |= S3C64XX_SPI_MODE_RXDMA_ON;
- chcfg |= S3C64XX_SPI_CH_RXCH_ON;
- writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
- | S3C64XX_SPI_PACKET_CNT_EN,
- regs + S3C64XX_SPI_PACKET_CNT);
- prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
- }
- }
-
- writel(modecfg, regs + S3C64XX_SPI_MODE_CFG);
- writel(chcfg, regs + S3C64XX_SPI_CH_CFG);
-}
-
-static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
- struct spi_device *spi)
-{
- struct s3c64xx_spi_csinfo *cs;
-
- if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
- if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
- /* Deselect the last toggled device */
- cs = sdd->tgl_spi->controller_data;
- cs->set_level(cs->line,
- spi->mode & SPI_CS_HIGH ? 0 : 1);
- }
- sdd->tgl_spi = NULL;
- }
-
- cs = spi->controller_data;
- cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
-}
-
-static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
- struct spi_transfer *xfer, int dma_mode)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- void __iomem *regs = sdd->regs;
- unsigned long val;
- int ms;
-
- /* millisecs to xfer 'len' bytes @ 'cur_speed' */
- ms = xfer->len * 8 * 1000 / sdd->cur_speed;
- ms += 10; /* some tolerance */
-
- if (dma_mode) {
- val = msecs_to_jiffies(ms) + 10;
- val = wait_for_completion_timeout(&sdd->xfer_completion, val);
- } else {
- u32 status;
- val = msecs_to_loops(ms);
- do {
- status = readl(regs + S3C64XX_SPI_STATUS);
- } while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
- }
-
- if (!val)
- return -EIO;
-
- if (dma_mode) {
- u32 status;
-
- /*
- * DmaTx returns after simply writing data in the FIFO,
- * w/o waiting for real transmission on the bus to finish.
- * DmaRx returns only after Dma read data from FIFO which
- * needs bus transmission to finish, so we don't worry if
- * Xfer involved Rx(with or without Tx).
- */
- if (xfer->rx_buf == NULL) {
- val = msecs_to_loops(10);
- status = readl(regs + S3C64XX_SPI_STATUS);
- while ((TX_FIFO_LVL(status, sci)
- || !S3C64XX_SPI_ST_TX_DONE(status, sci))
- && --val) {
- cpu_relax();
- status = readl(regs + S3C64XX_SPI_STATUS);
- }
-
- if (!val)
- return -EIO;
- }
- } else {
- /* If it was only Tx */
- if (xfer->rx_buf == NULL) {
- sdd->state &= ~TXBUSY;
- return 0;
- }
-
- switch (sdd->cur_bpw) {
- case 32:
- ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
- xfer->rx_buf, xfer->len / 4);
- break;
- case 16:
- ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
- xfer->rx_buf, xfer->len / 2);
- break;
- default:
- ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
- xfer->rx_buf, xfer->len);
- break;
- }
- sdd->state &= ~RXBUSY;
- }
-
- return 0;
-}
-
-static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
- struct spi_device *spi)
-{
- struct s3c64xx_spi_csinfo *cs = spi->controller_data;
-
- if (sdd->tgl_spi == spi)
- sdd->tgl_spi = NULL;
-
- cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
-}
-
-static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- void __iomem *regs = sdd->regs;
- u32 val;
-
- /* Disable Clock */
- if (sci->clk_from_cmu) {
- clk_disable(sdd->src_clk);
- } else {
- val = readl(regs + S3C64XX_SPI_CLK_CFG);
- val &= ~S3C64XX_SPI_ENCLK_ENABLE;
- writel(val, regs + S3C64XX_SPI_CLK_CFG);
- }
-
- /* Set Polarity and Phase */
- val = readl(regs + S3C64XX_SPI_CH_CFG);
- val &= ~(S3C64XX_SPI_CH_SLAVE |
- S3C64XX_SPI_CPOL_L |
- S3C64XX_SPI_CPHA_B);
-
- if (sdd->cur_mode & SPI_CPOL)
- val |= S3C64XX_SPI_CPOL_L;
-
- if (sdd->cur_mode & SPI_CPHA)
- val |= S3C64XX_SPI_CPHA_B;
-
- writel(val, regs + S3C64XX_SPI_CH_CFG);
-
- /* Set Channel & DMA Mode */
- val = readl(regs + S3C64XX_SPI_MODE_CFG);
- val &= ~(S3C64XX_SPI_MODE_BUS_TSZ_MASK
- | S3C64XX_SPI_MODE_CH_TSZ_MASK);
-
- switch (sdd->cur_bpw) {
- case 32:
- val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
- val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
- break;
- case 16:
- val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
- val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
- break;
- default:
- val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
- val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
- break;
- }
-
- writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
- if (sci->clk_from_cmu) {
- /* Configure Clock */
- /* There is half-multiplier before the SPI */
- clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
- /* Enable Clock */
- clk_enable(sdd->src_clk);
- } else {
- /* Configure Clock */
- val = readl(regs + S3C64XX_SPI_CLK_CFG);
- val &= ~S3C64XX_SPI_PSR_MASK;
- val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
- & S3C64XX_SPI_PSR_MASK);
- writel(val, regs + S3C64XX_SPI_CLK_CFG);
-
- /* Enable Clock */
- val = readl(regs + S3C64XX_SPI_CLK_CFG);
- val |= S3C64XX_SPI_ENCLK_ENABLE;
- writel(val, regs + S3C64XX_SPI_CLK_CFG);
- }
-}
-
-#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
-
-static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
- struct spi_message *msg)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- struct device *dev = &sdd->pdev->dev;
- struct spi_transfer *xfer;
-
- if (msg->is_dma_mapped)
- return 0;
-
- /* First mark all xfer unmapped */
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- xfer->rx_dma = XFER_DMAADDR_INVALID;
- xfer->tx_dma = XFER_DMAADDR_INVALID;
- }
-
- /* Map until end or first fail */
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
- if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
- continue;
-
- if (xfer->tx_buf != NULL) {
- xfer->tx_dma = dma_map_single(dev,
- (void *)xfer->tx_buf, xfer->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, xfer->tx_dma)) {
- dev_err(dev, "dma_map_single Tx failed\n");
- xfer->tx_dma = XFER_DMAADDR_INVALID;
- return -ENOMEM;
- }
- }
-
- if (xfer->rx_buf != NULL) {
- xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
- xfer->len, DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, xfer->rx_dma)) {
- dev_err(dev, "dma_map_single Rx failed\n");
- dma_unmap_single(dev, xfer->tx_dma,
- xfer->len, DMA_TO_DEVICE);
- xfer->tx_dma = XFER_DMAADDR_INVALID;
- xfer->rx_dma = XFER_DMAADDR_INVALID;
- return -ENOMEM;
- }
- }
- }
-
- return 0;
-}
-
-static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
- struct spi_message *msg)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- struct device *dev = &sdd->pdev->dev;
- struct spi_transfer *xfer;
-
- if (msg->is_dma_mapped)
- return;
-
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
- if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
- continue;
-
- if (xfer->rx_buf != NULL
- && xfer->rx_dma != XFER_DMAADDR_INVALID)
- dma_unmap_single(dev, xfer->rx_dma,
- xfer->len, DMA_FROM_DEVICE);
-
- if (xfer->tx_buf != NULL
- && xfer->tx_dma != XFER_DMAADDR_INVALID)
- dma_unmap_single(dev, xfer->tx_dma,
- xfer->len, DMA_TO_DEVICE);
- }
-}
-
-static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
- struct spi_message *msg)
-{
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- struct spi_device *spi = msg->spi;
- struct s3c64xx_spi_csinfo *cs = spi->controller_data;
- struct spi_transfer *xfer;
- int status = 0, cs_toggle = 0;
- u32 speed;
- u8 bpw;
-
- /* If Master's(controller) state differs from that needed by Slave */
- if (sdd->cur_speed != spi->max_speed_hz
- || sdd->cur_mode != spi->mode
- || sdd->cur_bpw != spi->bits_per_word) {
- sdd->cur_bpw = spi->bits_per_word;
- sdd->cur_speed = spi->max_speed_hz;
- sdd->cur_mode = spi->mode;
- s3c64xx_spi_config(sdd);
- }
-
- /* Map all the transfers if needed */
- if (s3c64xx_spi_map_mssg(sdd, msg)) {
- dev_err(&spi->dev,
- "Xfer: Unable to map message buffers!\n");
- status = -ENOMEM;
- goto out;
- }
-
- /* Configure feedback delay */
- writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
-
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
- unsigned long flags;
- int use_dma;
-
- INIT_COMPLETION(sdd->xfer_completion);
-
- /* Only BPW and Speed may change across transfers */
- bpw = xfer->bits_per_word ? : spi->bits_per_word;
- speed = xfer->speed_hz ? : spi->max_speed_hz;
-
- if (xfer->len % (bpw / 8)) {
- dev_err(&spi->dev,
- "Xfer length(%u) not a multiple of word size(%u)\n",
- xfer->len, bpw / 8);
- status = -EIO;
- goto out;
- }
-
- if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
- sdd->cur_bpw = bpw;
- sdd->cur_speed = speed;
- s3c64xx_spi_config(sdd);
- }
-
- /* Polling method for xfers not bigger than FIFO capacity */
- if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
- use_dma = 0;
- else
- use_dma = 1;
-
- spin_lock_irqsave(&sdd->lock, flags);
-
- /* Pending only which is to be done */
- sdd->state &= ~RXBUSY;
- sdd->state &= ~TXBUSY;
-
- enable_datapath(sdd, spi, xfer, use_dma);
-
- /* Slave Select */
- enable_cs(sdd, spi);
-
- /* Start the signals */
- S3C64XX_SPI_ACT(sdd);
-
- spin_unlock_irqrestore(&sdd->lock, flags);
-
- status = wait_for_xfer(sdd, xfer, use_dma);
-
- /* Quiese the signals */
- S3C64XX_SPI_DEACT(sdd);
-
- if (status) {
- dev_err(&spi->dev, "I/O Error: "
- "rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
- xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
- (sdd->state & RXBUSY) ? 'f' : 'p',
- (sdd->state & TXBUSY) ? 'f' : 'p',
- xfer->len);
-
- if (use_dma) {
- if (xfer->tx_buf != NULL
- && (sdd->state & TXBUSY))
- sdd->ops->stop(sdd->tx_dma.ch);
- if (xfer->rx_buf != NULL
- && (sdd->state & RXBUSY))
- sdd->ops->stop(sdd->rx_dma.ch);
- }
-
- goto out;
- }
-
- if (xfer->delay_usecs)
- udelay(xfer->delay_usecs);
-
- if (xfer->cs_change) {
- /* Hint that the next mssg is gonna be
- for the same device */
- if (list_is_last(&xfer->transfer_list,
- &msg->transfers))
- cs_toggle = 1;
- else
- disable_cs(sdd, spi);
- }
-
- msg->actual_length += xfer->len;
-
- flush_fifo(sdd);
- }
-
-out:
- if (!cs_toggle || status)
- disable_cs(sdd, spi);
- else
- sdd->tgl_spi = spi;
-
- s3c64xx_spi_unmap_mssg(sdd, msg);
-
- msg->status = status;
-
- spi_finalize_current_message(master);
-
- return 0;
-}
-
-static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
-{
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
-
- /* Acquire DMA channels */
- while (!acquire_dma(sdd))
- msleep(10);
-
- pm_runtime_get_sync(&sdd->pdev->dev);
-
- return 0;
-}
-
-static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
-{
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
-
- /* Free DMA channels */
- sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
- sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
-
- pm_runtime_put(&sdd->pdev->dev);
-
- return 0;
-}
-
-/*
- * Here we only check the validity of requested configuration
- * and save the configuration in a local data-structure.
- * The controller is actually configured only just before we
- * get a message to transfer.
- */
-static int s3c64xx_spi_setup(struct spi_device *spi)
-{
- struct s3c64xx_spi_csinfo *cs = spi->controller_data;
- struct s3c64xx_spi_driver_data *sdd;
- struct s3c64xx_spi_info *sci;
- struct spi_message *msg;
- unsigned long flags;
- int err = 0;
-
- if (cs == NULL || cs->set_level == NULL) {
- dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
- return -ENODEV;
- }
-
- sdd = spi_master_get_devdata(spi->master);
- sci = sdd->cntrlr_info;
-
- spin_lock_irqsave(&sdd->lock, flags);
-
- list_for_each_entry(msg, &sdd->queue, queue) {
- /* Is some mssg is already queued for this device */
- if (msg->spi == spi) {
- dev_err(&spi->dev,
- "setup: attempt while mssg in queue!\n");
- spin_unlock_irqrestore(&sdd->lock, flags);
- return -EBUSY;
- }
- }
-
- spin_unlock_irqrestore(&sdd->lock, flags);
-
- if (spi->bits_per_word != 8
- && spi->bits_per_word != 16
- && spi->bits_per_word != 32) {
- dev_err(&spi->dev, "setup: %dbits/wrd not supported!\n",
- spi->bits_per_word);
- err = -EINVAL;
- goto setup_exit;
- }
-
- pm_runtime_get_sync(&sdd->pdev->dev);
-
- /* Check if we can provide the requested rate */
- if (!sci->clk_from_cmu) {
- u32 psr, speed;
-
- /* Max possible */
- speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
-
- if (spi->max_speed_hz > speed)
- spi->max_speed_hz = speed;
-
- psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
- psr &= S3C64XX_SPI_PSR_MASK;
- if (psr == S3C64XX_SPI_PSR_MASK)
- psr--;
-
- speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
- if (spi->max_speed_hz < speed) {
- if (psr+1 < S3C64XX_SPI_PSR_MASK) {
- psr++;
- } else {
- err = -EINVAL;
- goto setup_exit;
- }
- }
-
- speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
- if (spi->max_speed_hz >= speed)
- spi->max_speed_hz = speed;
- else
- err = -EINVAL;
- }
-
- pm_runtime_put(&sdd->pdev->dev);
-
-setup_exit:
-
- /* setup() returns with device de-selected */
- disable_cs(sdd, spi);
-
- return err;
-}
-
-static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
-{
- struct s3c64xx_spi_driver_data *sdd = data;
- struct spi_master *spi = sdd->master;
- unsigned int val;
-
- val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
- val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
- S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
- S3C64XX_SPI_PND_TX_OVERRUN_CLR |
- S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
-
- writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
- if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
- dev_err(&spi->dev, "RX overrun\n");
- if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
- dev_err(&spi->dev, "RX underrun\n");
- if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
- dev_err(&spi->dev, "TX overrun\n");
- if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
- dev_err(&spi->dev, "TX underrun\n");
-
- return IRQ_HANDLED;
-}
-
-static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
-{
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
- void __iomem *regs = sdd->regs;
- unsigned int val;
-
- sdd->cur_speed = 0;
-
- S3C64XX_SPI_DEACT(sdd);
-
- /* Disable Interrupts - we use Polling if not DMA mode */
- writel(0, regs + S3C64XX_SPI_INT_EN);
-
- if (!sci->clk_from_cmu)
- writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
- regs + S3C64XX_SPI_CLK_CFG);
- writel(0, regs + S3C64XX_SPI_MODE_CFG);
- writel(0, regs + S3C64XX_SPI_PACKET_CNT);
-
- /* Clear any irq pending bits */
- writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
- regs + S3C64XX_SPI_PENDING_CLR);
-
- writel(0, regs + S3C64XX_SPI_SWAP_CFG);
-
- val = readl(regs + S3C64XX_SPI_MODE_CFG);
- val &= ~S3C64XX_SPI_MODE_4BURST;
- val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
- val |= (S3C64XX_SPI_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
- writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
- flush_fifo(sdd);
-}
-
-static int __init s3c64xx_spi_probe(struct platform_device *pdev)
-{
- struct resource *mem_res, *dmatx_res, *dmarx_res;
- struct s3c64xx_spi_driver_data *sdd;
- struct s3c64xx_spi_info *sci;
- struct spi_master *master;
- int ret, irq;
- char clk_name[16];
-
- if (pdev->id < 0) {
- dev_err(&pdev->dev,
- "Invalid platform device id-%d\n", pdev->id);
- return -ENODEV;
- }
-
- if (pdev->dev.platform_data == NULL) {
- dev_err(&pdev->dev, "platform_data missing!\n");
- return -ENODEV;
- }
-
- sci = pdev->dev.platform_data;
-
- /* Check for availability of necessary resource */
-
- dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (dmatx_res == NULL) {
- dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
- return -ENXIO;
- }
-
- dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (dmarx_res == NULL) {
- dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
- return -ENXIO;
- }
-
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem_res == NULL) {
- dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
- return -ENXIO;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_warn(&pdev->dev, "Failed to get IRQ: %d\n", irq);
- return irq;
- }
-
- master = spi_alloc_master(&pdev->dev,
- sizeof(struct s3c64xx_spi_driver_data));
- if (master == NULL) {
- dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(pdev, master);
-
- sdd = spi_master_get_devdata(master);
- sdd->master = master;
- sdd->cntrlr_info = sci;
- sdd->pdev = pdev;
- sdd->sfr_start = mem_res->start;
- sdd->tx_dma.dmach = dmatx_res->start;
- sdd->tx_dma.direction = DMA_MEM_TO_DEV;
- sdd->rx_dma.dmach = dmarx_res->start;
- sdd->rx_dma.direction = DMA_DEV_TO_MEM;
-
- sdd->cur_bpw = 8;
-
- master->bus_num = pdev->id;
- master->setup = s3c64xx_spi_setup;
- master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
- master->transfer_one_message = s3c64xx_spi_transfer_one_message;
- master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
- master->num_chipselect = sci->num_cs;
- master->dma_alignment = 8;
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- if (request_mem_region(mem_res->start,
- resource_size(mem_res), pdev->name) == NULL) {
- dev_err(&pdev->dev, "Req mem region failed\n");
- ret = -ENXIO;
- goto err0;
- }
-
- sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
- if (sdd->regs == NULL) {
- dev_err(&pdev->dev, "Unable to remap IO\n");
- ret = -ENXIO;
- goto err1;
- }
-
- if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
- dev_err(&pdev->dev, "Unable to config gpio\n");
- ret = -EBUSY;
- goto err2;
- }
-
- /* Setup clocks */
- sdd->clk = clk_get(&pdev->dev, "spi");
- if (IS_ERR(sdd->clk)) {
- dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
- ret = PTR_ERR(sdd->clk);
- goto err3;
- }
-
- if (clk_enable(sdd->clk)) {
- dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
- ret = -EBUSY;
- goto err4;
- }
-
- sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
- sdd->src_clk = clk_get(&pdev->dev, clk_name);
- if (IS_ERR(sdd->src_clk)) {
- dev_err(&pdev->dev,
- "Unable to acquire clock '%s'\n", clk_name);
- ret = PTR_ERR(sdd->src_clk);
- goto err5;
- }
-
- if (clk_enable(sdd->src_clk)) {
- dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
- ret = -EBUSY;
- goto err6;
- }
-
- /* Setup Deufult Mode */
- s3c64xx_spi_hwinit(sdd, pdev->id);
-
- spin_lock_init(&sdd->lock);
- init_completion(&sdd->xfer_completion);
- INIT_LIST_HEAD(&sdd->queue);
-
- ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n",
- irq, ret);
- goto err7;
- }
-
- writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN |
- S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
- sdd->regs + S3C64XX_SPI_INT_EN);
-
- if (spi_register_master(master)) {
- dev_err(&pdev->dev, "cannot register SPI master\n");
- ret = -EBUSY;
- goto err8;
- }
-
- dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
- "with %d Slaves attached\n",
- pdev->id, master->num_chipselect);
- dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
- mem_res->end, mem_res->start,
- sdd->rx_dma.dmach, sdd->tx_dma.dmach);
-
- pm_runtime_enable(&pdev->dev);
-
- return 0;
-
-err8:
- free_irq(irq, sdd);
-err7:
- clk_disable(sdd->src_clk);
-err6:
- clk_put(sdd->src_clk);
-err5:
- clk_disable(sdd->clk);
-err4:
- clk_put(sdd->clk);
-err3:
-err2:
- iounmap((void *) sdd->regs);
-err1:
- release_mem_region(mem_res->start, resource_size(mem_res));
-err0:
- platform_set_drvdata(pdev, NULL);
- spi_master_put(master);
-
- return ret;
-}
-
-static int s3c64xx_spi_remove(struct platform_device *pdev)
-{
- struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
- struct resource *mem_res;
-
- pm_runtime_disable(&pdev->dev);
-
- spi_unregister_master(master);
-
- writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
-
- free_irq(platform_get_irq(pdev, 0), sdd);
-
- clk_disable(sdd->src_clk);
- clk_put(sdd->src_clk);
-
- clk_disable(sdd->clk);
- clk_put(sdd->clk);
-
- iounmap((void *) sdd->regs);
-
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem_res != NULL)
- release_mem_region(mem_res->start, resource_size(mem_res));
-
- platform_set_drvdata(pdev, NULL);
- spi_master_put(master);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int s3c64xx_spi_suspend(struct device *dev)
-{
- struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-
- spi_master_suspend(master);
-
- /* Disable the clock */
- clk_disable(sdd->src_clk);
- clk_disable(sdd->clk);
-
- sdd->cur_speed = 0; /* Output Clock is stopped */
-
- return 0;
-}
-
-static int s3c64xx_spi_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
- struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-
- sci->cfg_gpio(pdev);
-
- /* Enable the clock */
- clk_enable(sdd->src_clk);
- clk_enable(sdd->clk);
-
- s3c64xx_spi_hwinit(sdd, pdev->id);
-
- spi_master_resume(master);
-
- return 0;
-}
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_RUNTIME
-static int s3c64xx_spi_runtime_suspend(struct device *dev)
-{
- struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-
- clk_disable(sdd->clk);
- clk_disable(sdd->src_clk);
-
- return 0;
-}
-
-static int s3c64xx_spi_runtime_resume(struct device *dev)
-{
- struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
- struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-
- clk_enable(sdd->src_clk);
- clk_enable(sdd->clk);
-
- return 0;
-}
-#endif /* CONFIG_PM_RUNTIME */
-
-static const struct dev_pm_ops s3c64xx_spi_pm = {
- SET_SYSTEM_SLEEP_PM_OPS(s3c64xx_spi_suspend, s3c64xx_spi_resume)
- SET_RUNTIME_PM_OPS(s3c64xx_spi_runtime_suspend,
- s3c64xx_spi_runtime_resume, NULL)
-};
-
-static struct platform_driver s3c64xx_spi_driver = {
- .driver = {
- .name = "s3c64xx-spi",
- .owner = THIS_MODULE,
- .pm = &s3c64xx_spi_pm,
- },
- .remove = s3c64xx_spi_remove,
-};
-MODULE_ALIAS("platform:s3c64xx-spi");
-
-static int __init s3c64xx_spi_init(void)
-{
- return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
-}
-subsys_initcall(s3c64xx_spi_init);
-
-static void __exit s3c64xx_spi_exit(void)
-{
- platform_driver_unregister(&s3c64xx_spi_driver);
-}
-module_exit(s3c64xx_spi_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-sh-hspi.c b/ANDROID_3.4.5/drivers/spi/spi-sh-hspi.c
deleted file mode 100644
index 934138c7..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-sh-hspi.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * SuperH HSPI bus driver
- *
- * Copyright (C) 2011 Kuninori Morimoto
- *
- * Based on spi-sh.c:
- * Based on pxa2xx_spi.c:
- * Copyright (C) 2011 Renesas Solutions Corp.
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/sh_hspi.h>
-
-#define SPCR 0x00
-#define SPSR 0x04
-#define SPSCR 0x08
-#define SPTBR 0x0C
-#define SPRBR 0x10
-#define SPCR2 0x14
-
-/* SPSR */
-#define RXFL (1 << 2)
-
-#define hspi2info(h) (h->dev->platform_data)
-
-struct hspi_priv {
- void __iomem *addr;
- struct spi_master *master;
- struct device *dev;
- struct clk *clk;
-};
-
-/*
- * basic function
- */
-static void hspi_write(struct hspi_priv *hspi, int reg, u32 val)
-{
- iowrite32(val, hspi->addr + reg);
-}
-
-static u32 hspi_read(struct hspi_priv *hspi, int reg)
-{
- return ioread32(hspi->addr + reg);
-}
-
-/*
- * transfer function
- */
-static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
-{
- int t = 256;
-
- while (t--) {
- if ((mask & hspi_read(hspi, SPSR)) == val)
- return 0;
-
- msleep(20);
- }
-
- dev_err(hspi->dev, "timeout\n");
- return -ETIMEDOUT;
-}
-
-/*
- * spi master function
- */
-static int hspi_prepare_transfer(struct spi_master *master)
-{
- struct hspi_priv *hspi = spi_master_get_devdata(master);
-
- pm_runtime_get_sync(hspi->dev);
- return 0;
-}
-
-static int hspi_unprepare_transfer(struct spi_master *master)
-{
- struct hspi_priv *hspi = spi_master_get_devdata(master);
-
- pm_runtime_put_sync(hspi->dev);
- return 0;
-}
-
-static void hspi_hw_setup(struct hspi_priv *hspi,
- struct spi_message *msg,
- struct spi_transfer *t)
-{
- struct spi_device *spi = msg->spi;
- struct device *dev = hspi->dev;
- u32 target_rate;
- u32 spcr, idiv_clk;
- u32 rate, best_rate, min, tmp;
-
- target_rate = t ? t->speed_hz : 0;
- if (!target_rate)
- target_rate = spi->max_speed_hz;
-
- /*
- * find best IDIV/CLKCx settings
- */
- min = ~0;
- best_rate = 0;
- spcr = 0;
- for (idiv_clk = 0x00; idiv_clk <= 0x3F; idiv_clk++) {
- rate = clk_get_rate(hspi->clk);
-
- /* IDIV calculation */
- if (idiv_clk & (1 << 5))
- rate /= 128;
- else
- rate /= 16;
-
- /* CLKCx calculation */
- rate /= (((idiv_clk & 0x1F) + 1) * 2) ;
-
- /* save best settings */
- tmp = abs(target_rate - rate);
- if (tmp < min) {
- min = tmp;
- spcr = idiv_clk;
- best_rate = rate;
- }
- }
-
- if (spi->mode & SPI_CPHA)
- spcr |= 1 << 7;
- if (spi->mode & SPI_CPOL)
- spcr |= 1 << 6;
-
- dev_dbg(dev, "speed %d/%d\n", target_rate, best_rate);
-
- hspi_write(hspi, SPCR, spcr);
- hspi_write(hspi, SPSR, 0x0);
- hspi_write(hspi, SPSCR, 0x1); /* master mode */
-}
-
-static int hspi_transfer_one_message(struct spi_master *master,
- struct spi_message *msg)
-{
- struct hspi_priv *hspi = spi_master_get_devdata(master);
- struct spi_transfer *t;
- u32 tx;
- u32 rx;
- int ret, i;
-
- dev_dbg(hspi->dev, "%s\n", __func__);
-
- ret = 0;
- list_for_each_entry(t, &msg->transfers, transfer_list) {
- hspi_hw_setup(hspi, msg, t);
-
- for (i = 0; i < t->len; i++) {
-
- /* wait remains */
- ret = hspi_status_check_timeout(hspi, 0x1, 0);
- if (ret < 0)
- break;
-
- tx = 0;
- if (t->tx_buf)
- tx = (u32)((u8 *)t->tx_buf)[i];
-
- hspi_write(hspi, SPTBR, tx);
-
- /* wait recive */
- ret = hspi_status_check_timeout(hspi, 0x4, 0x4);
- if (ret < 0)
- break;
-
- rx = hspi_read(hspi, SPRBR);
- if (t->rx_buf)
- ((u8 *)t->rx_buf)[i] = (u8)rx;
-
- }
-
- msg->actual_length += t->len;
- }
-
- msg->status = ret;
- spi_finalize_current_message(master);
-
- return ret;
-}
-
-static int hspi_setup(struct spi_device *spi)
-{
- struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
- struct device *dev = hspi->dev;
-
- if (8 != spi->bits_per_word) {
- dev_err(dev, "bits_per_word should be 8\n");
- return -EIO;
- }
-
- dev_dbg(dev, "%s setup\n", spi->modalias);
-
- return 0;
-}
-
-static void hspi_cleanup(struct spi_device *spi)
-{
- struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
- struct device *dev = hspi->dev;
-
- dev_dbg(dev, "%s cleanup\n", spi->modalias);
-}
-
-static int __devinit hspi_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct spi_master *master;
- struct hspi_priv *hspi;
- struct clk *clk;
- int ret;
-
- /* get base addr */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "invalid resource\n");
- return -EINVAL;
- }
-
- master = spi_alloc_master(&pdev->dev, sizeof(*hspi));
- if (!master) {
- dev_err(&pdev->dev, "spi_alloc_master error.\n");
- return -ENOMEM;
- }
-
- clk = clk_get(NULL, "shyway_clk");
- if (!clk) {
- dev_err(&pdev->dev, "shyway_clk is required\n");
- ret = -EINVAL;
- goto error0;
- }
-
- hspi = spi_master_get_devdata(master);
- dev_set_drvdata(&pdev->dev, hspi);
-
- /* init hspi */
- hspi->master = master;
- hspi->dev = &pdev->dev;
- hspi->clk = clk;
- hspi->addr = devm_ioremap(hspi->dev,
- res->start, resource_size(res));
- if (!hspi->addr) {
- dev_err(&pdev->dev, "ioremap error.\n");
- ret = -ENOMEM;
- goto error1;
- }
-
- master->num_chipselect = 1;
- master->bus_num = pdev->id;
- master->setup = hspi_setup;
- master->cleanup = hspi_cleanup;
- master->mode_bits = SPI_CPOL | SPI_CPHA;
- master->prepare_transfer_hardware = hspi_prepare_transfer;
- master->transfer_one_message = hspi_transfer_one_message;
- master->unprepare_transfer_hardware = hspi_unprepare_transfer;
- ret = spi_register_master(master);
- if (ret < 0) {
- dev_err(&pdev->dev, "spi_register_master error.\n");
- goto error2;
- }
-
- pm_runtime_enable(&pdev->dev);
-
- dev_info(&pdev->dev, "probed\n");
-
- return 0;
-
- error2:
- devm_iounmap(hspi->dev, hspi->addr);
- error1:
- clk_put(clk);
- error0:
- spi_master_put(master);
-
- return ret;
-}
-
-static int __devexit hspi_remove(struct platform_device *pdev)
-{
- struct hspi_priv *hspi = dev_get_drvdata(&pdev->dev);
-
- pm_runtime_disable(&pdev->dev);
-
- clk_put(hspi->clk);
- spi_unregister_master(hspi->master);
- devm_iounmap(hspi->dev, hspi->addr);
-
- return 0;
-}
-
-static struct platform_driver hspi_driver = {
- .probe = hspi_probe,
- .remove = __devexit_p(hspi_remove),
- .driver = {
- .name = "sh-hspi",
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(hspi_driver);
-
-MODULE_DESCRIPTION("SuperH HSPI bus driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_ALIAS("platform:sh_spi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-sh-msiof.c b/ANDROID_3.4.5/drivers/spi/spi-sh-msiof.c
deleted file mode 100644
index 1f466bc6..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-sh-msiof.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- * SuperH MSIOF SPI Master Interface
- *
- * Copyright (c) 2009 Magnus Damm
- *
- * 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/bitmap.h>
-#include <linux/clk.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <linux/spi/sh_msiof.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <asm/unaligned.h>
-
-struct sh_msiof_spi_priv {
- struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
- void __iomem *mapbase;
- struct clk *clk;
- struct platform_device *pdev;
- struct sh_msiof_spi_info *info;
- struct completion done;
- unsigned long flags;
- int tx_fifo_size;
- int rx_fifo_size;
-};
-
-#define TMDR1 0x00
-#define TMDR2 0x04
-#define TMDR3 0x08
-#define RMDR1 0x10
-#define RMDR2 0x14
-#define RMDR3 0x18
-#define TSCR 0x20
-#define RSCR 0x22
-#define CTR 0x28
-#define FCTR 0x30
-#define STR 0x40
-#define IER 0x44
-#define TDR1 0x48
-#define TDR2 0x4c
-#define TFDR 0x50
-#define RDR1 0x58
-#define RDR2 0x5c
-#define RFDR 0x60
-
-#define CTR_TSCKE (1 << 15)
-#define CTR_TFSE (1 << 14)
-#define CTR_TXE (1 << 9)
-#define CTR_RXE (1 << 8)
-
-#define STR_TEOF (1 << 23)
-#define STR_REOF (1 << 7)
-
-static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
-{
- switch (reg_offs) {
- case TSCR:
- case RSCR:
- return ioread16(p->mapbase + reg_offs);
- default:
- return ioread32(p->mapbase + reg_offs);
- }
-}
-
-static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs,
- u32 value)
-{
- switch (reg_offs) {
- case TSCR:
- case RSCR:
- iowrite16(value, p->mapbase + reg_offs);
- break;
- default:
- iowrite32(value, p->mapbase + reg_offs);
- break;
- }
-}
-
-static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p,
- u32 clr, u32 set)
-{
- u32 mask = clr | set;
- u32 data;
- int k;
-
- data = sh_msiof_read(p, CTR);
- data &= ~clr;
- data |= set;
- sh_msiof_write(p, CTR, data);
-
- for (k = 100; k > 0; k--) {
- if ((sh_msiof_read(p, CTR) & mask) == set)
- break;
-
- udelay(10);
- }
-
- return k > 0 ? 0 : -ETIMEDOUT;
-}
-
-static irqreturn_t sh_msiof_spi_irq(int irq, void *data)
-{
- struct sh_msiof_spi_priv *p = data;
-
- /* just disable the interrupt and wake up */
- sh_msiof_write(p, IER, 0);
- complete(&p->done);
-
- return IRQ_HANDLED;
-}
-
-static struct {
- unsigned short div;
- unsigned short scr;
-} const sh_msiof_spi_clk_table[] = {
- { 1, 0x0007 },
- { 2, 0x0000 },
- { 4, 0x0001 },
- { 8, 0x0002 },
- { 16, 0x0003 },
- { 32, 0x0004 },
- { 64, 0x1f00 },
- { 128, 0x1f01 },
- { 256, 0x1f02 },
- { 512, 0x1f03 },
- { 1024, 0x1f04 },
-};
-
-static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
- unsigned long parent_rate,
- unsigned long spi_hz)
-{
- unsigned long div = 1024;
- size_t k;
-
- if (!WARN_ON(!spi_hz || !parent_rate))
- div = parent_rate / spi_hz;
-
- /* TODO: make more fine grained */
-
- for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_clk_table); k++) {
- if (sh_msiof_spi_clk_table[k].div >= div)
- break;
- }
-
- k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1);
-
- sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr);
- sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
-}
-
-static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
- u32 cpol, u32 cpha,
- u32 tx_hi_z, u32 lsb_first)
-{
- u32 tmp;
- int edge;
-
- /*
- * CPOL CPHA TSCKIZ RSCKIZ TEDG REDG
- * 0 0 10 10 1 1
- * 0 1 10 10 0 0
- * 1 0 11 11 0 0
- * 1 1 11 11 1 1
- */
- sh_msiof_write(p, FCTR, 0);
- sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24));
- sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24));
-
- tmp = 0xa0000000;
- tmp |= cpol << 30; /* TSCKIZ */
- tmp |= cpol << 28; /* RSCKIZ */
-
- edge = cpol ^ !cpha;
-
- tmp |= edge << 27; /* TEDG */
- tmp |= edge << 26; /* REDG */
- tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */
- sh_msiof_write(p, CTR, tmp);
-}
-
-static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
- const void *tx_buf, void *rx_buf,
- u32 bits, u32 words)
-{
- u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
-
- if (tx_buf)
- sh_msiof_write(p, TMDR2, dr2);
- else
- sh_msiof_write(p, TMDR2, dr2 | 1);
-
- if (rx_buf)
- sh_msiof_write(p, RMDR2, dr2);
-
- sh_msiof_write(p, IER, STR_TEOF | STR_REOF);
-}
-
-static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
-{
- sh_msiof_write(p, STR, sh_msiof_read(p, STR));
-}
-
-static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u8 *buf_8 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, buf_8[k] << fs);
-}
-
-static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u16 *buf_16 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, buf_16[k] << fs);
-}
-
-static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u16 *buf_16 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, get_unaligned(&buf_16[k]) << fs);
-}
-
-static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u32 *buf_32 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, buf_32[k] << fs);
-}
-
-static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u32 *buf_32 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs);
-}
-
-static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u32 *buf_32 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs));
-}
-
-static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p,
- const void *tx_buf, int words, int fs)
-{
- const u32 *buf_32 = tx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs));
-}
-
-static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u8 *buf_8 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- buf_8[k] = sh_msiof_read(p, RFDR) >> fs;
-}
-
-static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u16 *buf_16 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- buf_16[k] = sh_msiof_read(p, RFDR) >> fs;
-}
-
-static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u16 *buf_16 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_16[k]);
-}
-
-static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u32 *buf_32 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- buf_32[k] = sh_msiof_read(p, RFDR) >> fs;
-}
-
-static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u32 *buf_32 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]);
-}
-
-static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u32 *buf_32 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs);
-}
-
-static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
- void *rx_buf, int words, int fs)
-{
- u32 *buf_32 = rx_buf;
- int k;
-
- for (k = 0; k < words; k++)
- put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
-}
-
-static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
-{
- int bits;
-
- bits = t ? t->bits_per_word : 0;
- if (!bits)
- bits = spi->bits_per_word;
- return bits;
-}
-
-static unsigned long sh_msiof_spi_hz(struct spi_device *spi,
- struct spi_transfer *t)
-{
- unsigned long hz;
-
- hz = t ? t->speed_hz : 0;
- if (!hz)
- hz = spi->max_speed_hz;
- return hz;
-}
-
-static int sh_msiof_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- int bits;
-
- /* noting to check hz values against since parent clock is disabled */
-
- bits = sh_msiof_spi_bits(spi, t);
- if (bits < 8)
- return -EINVAL;
- if (bits > 32)
- return -EINVAL;
-
- return spi_bitbang_setup_transfer(spi, t);
-}
-
-static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
-{
- struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
- int value;
-
- /* chip select is active low unless SPI_CS_HIGH is set */
- if (spi->mode & SPI_CS_HIGH)
- value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0;
- else
- value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1;
-
- if (is_on == BITBANG_CS_ACTIVE) {
- if (!test_and_set_bit(0, &p->flags)) {
- pm_runtime_get_sync(&p->pdev->dev);
- clk_enable(p->clk);
- }
-
- /* Configure pins before asserting CS */
- sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
- !!(spi->mode & SPI_CPHA),
- !!(spi->mode & SPI_3WIRE),
- !!(spi->mode & SPI_LSB_FIRST));
- }
-
- /* use spi->controller data for CS (same strategy as spi_gpio) */
- gpio_set_value((unsigned)spi->controller_data, value);
-
- if (is_on == BITBANG_CS_INACTIVE) {
- if (test_and_clear_bit(0, &p->flags)) {
- clk_disable(p->clk);
- pm_runtime_put(&p->pdev->dev);
- }
- }
-}
-
-static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
- void (*tx_fifo)(struct sh_msiof_spi_priv *,
- const void *, int, int),
- void (*rx_fifo)(struct sh_msiof_spi_priv *,
- void *, int, int),
- const void *tx_buf, void *rx_buf,
- int words, int bits)
-{
- int fifo_shift;
- int ret;
-
- /* limit maximum word transfer to rx/tx fifo size */
- if (tx_buf)
- words = min_t(int, words, p->tx_fifo_size);
- if (rx_buf)
- words = min_t(int, words, p->rx_fifo_size);
-
- /* the fifo contents need shifting */
- fifo_shift = 32 - bits;
-
- /* setup msiof transfer mode registers */
- sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words);
-
- /* write tx fifo */
- if (tx_buf)
- tx_fifo(p, tx_buf, words, fifo_shift);
-
- /* setup clock and rx/tx signals */
- ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
- if (rx_buf)
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
-
- /* start by setting frame bit */
- INIT_COMPLETION(p->done);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
- if (ret) {
- dev_err(&p->pdev->dev, "failed to start hardware\n");
- goto err;
- }
-
- /* wait for tx fifo to be emptied / rx fifo to be filled */
- wait_for_completion(&p->done);
-
- /* read rx fifo */
- if (rx_buf)
- rx_fifo(p, rx_buf, words, fifo_shift);
-
- /* clear status bits */
- sh_msiof_reset_str(p);
-
- /* shut down frame, tx/tx and clock signals */
- ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
- if (rx_buf)
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
- if (ret) {
- dev_err(&p->pdev->dev, "failed to shut down hardware\n");
- goto err;
- }
-
- return words;
-
- err:
- sh_msiof_write(p, IER, 0);
- return ret;
-}
-
-static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
- struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
- void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
- void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
- int bits;
- int bytes_per_word;
- int bytes_done;
- int words;
- int n;
- bool swab;
-
- bits = sh_msiof_spi_bits(spi, t);
-
- if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
- bits = 32;
- swab = true;
- } else {
- swab = false;
- }
-
- /* setup bytes per word and fifo read/write functions */
- if (bits <= 8) {
- bytes_per_word = 1;
- tx_fifo = sh_msiof_spi_write_fifo_8;
- rx_fifo = sh_msiof_spi_read_fifo_8;
- } else if (bits <= 16) {
- bytes_per_word = 2;
- if ((unsigned long)t->tx_buf & 0x01)
- tx_fifo = sh_msiof_spi_write_fifo_16u;
- else
- tx_fifo = sh_msiof_spi_write_fifo_16;
-
- if ((unsigned long)t->rx_buf & 0x01)
- rx_fifo = sh_msiof_spi_read_fifo_16u;
- else
- rx_fifo = sh_msiof_spi_read_fifo_16;
- } else if (swab) {
- bytes_per_word = 4;
- if ((unsigned long)t->tx_buf & 0x03)
- tx_fifo = sh_msiof_spi_write_fifo_s32u;
- else
- tx_fifo = sh_msiof_spi_write_fifo_s32;
-
- if ((unsigned long)t->rx_buf & 0x03)
- rx_fifo = sh_msiof_spi_read_fifo_s32u;
- else
- rx_fifo = sh_msiof_spi_read_fifo_s32;
- } else {
- bytes_per_word = 4;
- if ((unsigned long)t->tx_buf & 0x03)
- tx_fifo = sh_msiof_spi_write_fifo_32u;
- else
- tx_fifo = sh_msiof_spi_write_fifo_32;
-
- if ((unsigned long)t->rx_buf & 0x03)
- rx_fifo = sh_msiof_spi_read_fifo_32u;
- else
- rx_fifo = sh_msiof_spi_read_fifo_32;
- }
-
- /* setup clocks (clock already enabled in chipselect()) */
- sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
- sh_msiof_spi_hz(spi, t));
-
- /* transfer in fifo sized chunks */
- words = t->len / bytes_per_word;
- bytes_done = 0;
-
- while (bytes_done < t->len) {
- void *rx_buf = t->rx_buf ? t->rx_buf + bytes_done : NULL;
- const void *tx_buf = t->tx_buf ? t->tx_buf + bytes_done : NULL;
- n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo,
- tx_buf,
- rx_buf,
- words, bits);
- if (n < 0)
- break;
-
- bytes_done += n * bytes_per_word;
- words -= n;
- }
-
- return bytes_done;
-}
-
-static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
- u32 word, u8 bits)
-{
- BUG(); /* unused but needed by bitbang code */
- return 0;
-}
-
-static int sh_msiof_spi_probe(struct platform_device *pdev)
-{
- struct resource *r;
- struct spi_master *master;
- struct sh_msiof_spi_priv *p;
- char clk_name[16];
- int i;
- int ret;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
- if (master == NULL) {
- dev_err(&pdev->dev, "failed to allocate spi master\n");
- ret = -ENOMEM;
- goto err0;
- }
-
- p = spi_master_get_devdata(master);
-
- platform_set_drvdata(pdev, p);
- p->info = pdev->dev.platform_data;
- init_completion(&p->done);
-
- snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id);
- p->clk = clk_get(&pdev->dev, clk_name);
- if (IS_ERR(p->clk)) {
- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
- ret = PTR_ERR(p->clk);
- goto err1;
- }
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- i = platform_get_irq(pdev, 0);
- if (!r || i < 0) {
- dev_err(&pdev->dev, "cannot get platform resources\n");
- ret = -ENOENT;
- goto err2;
- }
- p->mapbase = ioremap_nocache(r->start, resource_size(r));
- if (!p->mapbase) {
- dev_err(&pdev->dev, "unable to ioremap\n");
- ret = -ENXIO;
- goto err2;
- }
-
- ret = request_irq(i, sh_msiof_spi_irq, 0,
- dev_name(&pdev->dev), p);
- if (ret) {
- dev_err(&pdev->dev, "unable to request irq\n");
- goto err3;
- }
-
- p->pdev = pdev;
- pm_runtime_enable(&pdev->dev);
-
- /* The standard version of MSIOF use 64 word FIFOs */
- p->tx_fifo_size = 64;
- p->rx_fifo_size = 64;
-
- /* Platform data may override FIFO sizes */
- if (p->info->tx_fifo_override)
- p->tx_fifo_size = p->info->tx_fifo_override;
- if (p->info->rx_fifo_override)
- p->rx_fifo_size = p->info->rx_fifo_override;
-
- /* init master and bitbang code */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
- master->flags = 0;
- master->bus_num = pdev->id;
- master->num_chipselect = p->info->num_chipselect;
- master->setup = spi_bitbang_setup;
- master->cleanup = spi_bitbang_cleanup;
-
- p->bitbang.master = master;
- p->bitbang.chipselect = sh_msiof_spi_chipselect;
- p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer;
- p->bitbang.txrx_bufs = sh_msiof_spi_txrx;
- p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word;
- p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word;
- p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word;
- p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word;
-
- ret = spi_bitbang_start(&p->bitbang);
- if (ret == 0)
- return 0;
-
- pm_runtime_disable(&pdev->dev);
- err3:
- iounmap(p->mapbase);
- err2:
- clk_put(p->clk);
- err1:
- spi_master_put(master);
- err0:
- return ret;
-}
-
-static int sh_msiof_spi_remove(struct platform_device *pdev)
-{
- struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
- int ret;
-
- ret = spi_bitbang_stop(&p->bitbang);
- if (!ret) {
- pm_runtime_disable(&pdev->dev);
- free_irq(platform_get_irq(pdev, 0), p);
- iounmap(p->mapbase);
- clk_put(p->clk);
- spi_master_put(p->bitbang.master);
- }
- return ret;
-}
-
-static int sh_msiof_spi_runtime_nop(struct device *dev)
-{
- /* Runtime PM callback shared between ->runtime_suspend()
- * and ->runtime_resume(). Simply returns success.
- *
- * This driver re-initializes all registers after
- * pm_runtime_get_sync() anyway so there is no need
- * to save and restore registers here.
- */
- return 0;
-}
-
-static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
- .runtime_suspend = sh_msiof_spi_runtime_nop,
- .runtime_resume = sh_msiof_spi_runtime_nop,
-};
-
-static struct platform_driver sh_msiof_spi_drv = {
- .probe = sh_msiof_spi_probe,
- .remove = sh_msiof_spi_remove,
- .driver = {
- .name = "spi_sh_msiof",
- .owner = THIS_MODULE,
- .pm = &sh_msiof_spi_dev_pm_ops,
- },
-};
-module_platform_driver(sh_msiof_spi_drv);
-
-MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver");
-MODULE_AUTHOR("Magnus Damm");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:spi_sh_msiof");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-sh-sci.c b/ANDROID_3.4.5/drivers/spi/spi-sh-sci.c
deleted file mode 100644
index 097e5060..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-sh-sci.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * SH SCI SPI interface
- *
- * Copyright (c) 2008 Magnus Damm
- *
- * Based on S3C24XX GPIO based SPI driver, which is:
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *
- * 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/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/module.h>
-
-#include <asm/spi.h>
-#include <asm/io.h>
-
-struct sh_sci_spi {
- struct spi_bitbang bitbang;
-
- void __iomem *membase;
- unsigned char val;
- struct sh_spi_info *info;
- struct platform_device *dev;
-};
-
-#define SCSPTR(sp) (sp->membase + 0x1c)
-#define PIN_SCK (1 << 2)
-#define PIN_TXD (1 << 0)
-#define PIN_RXD PIN_TXD
-#define PIN_INIT ((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD)
-
-static inline void setbits(struct sh_sci_spi *sp, int bits, int on)
-{
- /*
- * We are the only user of SCSPTR so no locking is required.
- * Reading bit 2 and 0 in SCSPTR gives pin state as input.
- * Writing the same bits sets the output value.
- * This makes regular read-modify-write difficult so we
- * use sp->val to keep track of the latest register value.
- */
-
- if (on)
- sp->val |= bits;
- else
- sp->val &= ~bits;
-
- iowrite8(sp->val, SCSPTR(sp));
-}
-
-static inline void setsck(struct spi_device *dev, int on)
-{
- setbits(spi_master_get_devdata(dev->master), PIN_SCK, on);
-}
-
-static inline void setmosi(struct spi_device *dev, int on)
-{
- setbits(spi_master_get_devdata(dev->master), PIN_TXD, on);
-}
-
-static inline u32 getmiso(struct spi_device *dev)
-{
- struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
-
- return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0;
-}
-
-#define spidelay(x) ndelay(x)
-
-#include "spi-bitbang-txrx.h"
-
-static u32 sh_sci_spi_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 sh_sci_spi_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 sh_sci_spi_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 sh_sci_spi_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 sh_sci_spi_chipselect(struct spi_device *dev, int value)
-{
- struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
-
- if (sp->info && sp->info->chip_select)
- (sp->info->chip_select)(sp->info, dev->chip_select, value);
-}
-
-static int sh_sci_spi_probe(struct platform_device *dev)
-{
- struct resource *r;
- struct spi_master *master;
- struct sh_sci_spi *sp;
- int ret;
-
- master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi));
- if (master == NULL) {
- dev_err(&dev->dev, "failed to allocate spi master\n");
- ret = -ENOMEM;
- goto err0;
- }
-
- sp = spi_master_get_devdata(master);
-
- platform_set_drvdata(dev, sp);
- sp->info = dev->dev.platform_data;
-
- /* setup spi bitbang adaptor */
- sp->bitbang.master = spi_master_get(master);
- sp->bitbang.master->bus_num = sp->info->bus_num;
- sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
- sp->bitbang.chipselect = sh_sci_spi_chipselect;
-
- sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0;
- sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1;
- sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2;
- sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3;
-
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENOENT;
- goto err1;
- }
- sp->membase = ioremap(r->start, resource_size(r));
- if (!sp->membase) {
- ret = -ENXIO;
- goto err1;
- }
- sp->val = ioread8(SCSPTR(sp));
- setbits(sp, PIN_INIT, 1);
-
- ret = spi_bitbang_start(&sp->bitbang);
- if (!ret)
- return 0;
-
- setbits(sp, PIN_INIT, 0);
- iounmap(sp->membase);
- err1:
- spi_master_put(sp->bitbang.master);
- err0:
- return ret;
-}
-
-static int sh_sci_spi_remove(struct platform_device *dev)
-{
- struct sh_sci_spi *sp = platform_get_drvdata(dev);
-
- iounmap(sp->membase);
- setbits(sp, PIN_INIT, 0);
- spi_bitbang_stop(&sp->bitbang);
- spi_master_put(sp->bitbang.master);
- return 0;
-}
-
-static struct platform_driver sh_sci_spi_drv = {
- .probe = sh_sci_spi_probe,
- .remove = sh_sci_spi_remove,
- .driver = {
- .name = "spi_sh_sci",
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(sh_sci_spi_drv);
-
-MODULE_DESCRIPTION("SH SCI SPI Driver");
-MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:spi_sh_sci");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-sh.c b/ANDROID_3.4.5/drivers/spi/spi-sh.c
deleted file mode 100644
index 79442c31..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-sh.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * SH SPI bus driver
- *
- * Copyright (C) 2011 Renesas Solutions Corp.
- *
- * Based on pxa2xx_spi.c:
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/list.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-
-#define SPI_SH_TBR 0x00
-#define SPI_SH_RBR 0x00
-#define SPI_SH_CR1 0x08
-#define SPI_SH_CR2 0x10
-#define SPI_SH_CR3 0x18
-#define SPI_SH_CR4 0x20
-#define SPI_SH_CR5 0x28
-
-/* CR1 */
-#define SPI_SH_TBE 0x80
-#define SPI_SH_TBF 0x40
-#define SPI_SH_RBE 0x20
-#define SPI_SH_RBF 0x10
-#define SPI_SH_PFONRD 0x08
-#define SPI_SH_SSDB 0x04
-#define SPI_SH_SSD 0x02
-#define SPI_SH_SSA 0x01
-
-/* CR2 */
-#define SPI_SH_RSTF 0x80
-#define SPI_SH_LOOPBK 0x40
-#define SPI_SH_CPOL 0x20
-#define SPI_SH_CPHA 0x10
-#define SPI_SH_L1M0 0x08
-
-/* CR3 */
-#define SPI_SH_MAX_BYTE 0xFF
-
-/* CR4 */
-#define SPI_SH_TBEI 0x80
-#define SPI_SH_TBFI 0x40
-#define SPI_SH_RBEI 0x20
-#define SPI_SH_RBFI 0x10
-#define SPI_SH_WPABRT 0x04
-#define SPI_SH_SSS 0x01
-
-/* CR8 */
-#define SPI_SH_P1L0 0x80
-#define SPI_SH_PP1L0 0x40
-#define SPI_SH_MUXI 0x20
-#define SPI_SH_MUXIRQ 0x10
-
-#define SPI_SH_FIFO_SIZE 32
-#define SPI_SH_SEND_TIMEOUT (3 * HZ)
-#define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3)
-
-#undef DEBUG
-
-struct spi_sh_data {
- void __iomem *addr;
- int irq;
- struct spi_master *master;
- struct list_head queue;
- struct workqueue_struct *workqueue;
- struct work_struct ws;
- unsigned long cr1;
- wait_queue_head_t wait;
- spinlock_t lock;
- int width;
-};
-
-static void spi_sh_write(struct spi_sh_data *ss, unsigned long data,
- unsigned long offset)
-{
- if (ss->width == 8)
- iowrite8(data, ss->addr + (offset >> 2));
- else if (ss->width == 32)
- iowrite32(data, ss->addr + offset);
-}
-
-static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset)
-{
- if (ss->width == 8)
- return ioread8(ss->addr + (offset >> 2));
- else if (ss->width == 32)
- return ioread32(ss->addr + offset);
- else
- return 0;
-}
-
-static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val,
- unsigned long offset)
-{
- unsigned long tmp;
-
- tmp = spi_sh_read(ss, offset);
- tmp |= val;
- spi_sh_write(ss, tmp, offset);
-}
-
-static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val,
- unsigned long offset)
-{
- unsigned long tmp;
-
- tmp = spi_sh_read(ss, offset);
- tmp &= ~val;
- spi_sh_write(ss, tmp, offset);
-}
-
-static void clear_fifo(struct spi_sh_data *ss)
-{
- spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
- spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
-}
-
-static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss)
-{
- int timeout = 100000;
-
- while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
- udelay(10);
- if (timeout-- < 0)
- return -ETIMEDOUT;
- }
- return 0;
-}
-
-static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss)
-{
- int timeout = 100000;
-
- while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) {
- udelay(10);
- if (timeout-- < 0)
- return -ETIMEDOUT;
- }
- return 0;
-}
-
-static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
- struct spi_transfer *t)
-{
- int i, retval = 0;
- int remain = t->len;
- int cur_len;
- unsigned char *data;
- unsigned long tmp;
- long ret;
-
- if (t->len)
- spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
- data = (unsigned char *)t->tx_buf;
- while (remain > 0) {
- cur_len = min(SPI_SH_FIFO_SIZE, remain);
- for (i = 0; i < cur_len &&
- !(spi_sh_read(ss, SPI_SH_CR4) &
- SPI_SH_WPABRT) &&
- !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF);
- i++)
- spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR);
-
- if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) {
- /* Abort SPI operation */
- spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4);
- retval = -EIO;
- break;
- }
-
- cur_len = i;
-
- remain -= cur_len;
- data += cur_len;
-
- if (remain > 0) {
- ss->cr1 &= ~SPI_SH_TBE;
- spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
- ret = wait_event_interruptible_timeout(ss->wait,
- ss->cr1 & SPI_SH_TBE,
- SPI_SH_SEND_TIMEOUT);
- if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) {
- printk(KERN_ERR "%s: timeout\n", __func__);
- return -ETIMEDOUT;
- }
- }
- }
-
- if (list_is_last(&t->transfer_list, &mesg->transfers)) {
- tmp = spi_sh_read(ss, SPI_SH_CR1);
- tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
- spi_sh_write(ss, tmp, SPI_SH_CR1);
- spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
- ss->cr1 &= ~SPI_SH_TBE;
- spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
- ret = wait_event_interruptible_timeout(ss->wait,
- ss->cr1 & SPI_SH_TBE,
- SPI_SH_SEND_TIMEOUT);
- if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) {
- printk(KERN_ERR "%s: timeout\n", __func__);
- return -ETIMEDOUT;
- }
- }
-
- return retval;
-}
-
-static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
- struct spi_transfer *t)
-{
- int i;
- int remain = t->len;
- int cur_len;
- unsigned char *data;
- unsigned long tmp;
- long ret;
-
- if (t->len > SPI_SH_MAX_BYTE)
- spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3);
- else
- spi_sh_write(ss, t->len, SPI_SH_CR3);
-
- tmp = spi_sh_read(ss, SPI_SH_CR1);
- tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
- spi_sh_write(ss, tmp, SPI_SH_CR1);
- spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
- spi_sh_wait_write_buffer_empty(ss);
-
- data = (unsigned char *)t->rx_buf;
- while (remain > 0) {
- if (remain >= SPI_SH_FIFO_SIZE) {
- ss->cr1 &= ~SPI_SH_RBF;
- spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4);
- ret = wait_event_interruptible_timeout(ss->wait,
- ss->cr1 & SPI_SH_RBF,
- SPI_SH_RECEIVE_TIMEOUT);
- if (ret == 0 &&
- spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
- printk(KERN_ERR "%s: timeout\n", __func__);
- return -ETIMEDOUT;
- }
- }
-
- cur_len = min(SPI_SH_FIFO_SIZE, remain);
- for (i = 0; i < cur_len; i++) {
- if (spi_sh_wait_receive_buffer(ss))
- break;
- data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR);
- }
-
- remain -= cur_len;
- data += cur_len;
- }
-
- /* deassert CS when SPI is receiving. */
- if (t->len > SPI_SH_MAX_BYTE) {
- clear_fifo(ss);
- spi_sh_write(ss, 1, SPI_SH_CR3);
- } else {
- spi_sh_write(ss, 0, SPI_SH_CR3);
- }
-
- return 0;
-}
-
-static void spi_sh_work(struct work_struct *work)
-{
- struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws);
- struct spi_message *mesg;
- struct spi_transfer *t;
- unsigned long flags;
- int ret;
-
- pr_debug("%s: enter\n", __func__);
-
- spin_lock_irqsave(&ss->lock, flags);
- while (!list_empty(&ss->queue)) {
- mesg = list_entry(ss->queue.next, struct spi_message, queue);
- list_del_init(&mesg->queue);
-
- spin_unlock_irqrestore(&ss->lock, flags);
- list_for_each_entry(t, &mesg->transfers, transfer_list) {
- pr_debug("tx_buf = %p, rx_buf = %p\n",
- t->tx_buf, t->rx_buf);
- pr_debug("len = %d, delay_usecs = %d\n",
- t->len, t->delay_usecs);
-
- if (t->tx_buf) {
- ret = spi_sh_send(ss, mesg, t);
- if (ret < 0)
- goto error;
- }
- if (t->rx_buf) {
- ret = spi_sh_receive(ss, mesg, t);
- if (ret < 0)
- goto error;
- }
- mesg->actual_length += t->len;
- }
- spin_lock_irqsave(&ss->lock, flags);
-
- mesg->status = 0;
- mesg->complete(mesg->context);
- }
-
- clear_fifo(ss);
- spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1);
- udelay(100);
-
- spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
- SPI_SH_CR1);
-
- clear_fifo(ss);
-
- spin_unlock_irqrestore(&ss->lock, flags);
-
- return;
-
- error:
- mesg->status = ret;
- mesg->complete(mesg->context);
-
- spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
- SPI_SH_CR1);
- clear_fifo(ss);
-
-}
-
-static int spi_sh_setup(struct spi_device *spi)
-{
- struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
-
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
-
- pr_debug("%s: enter\n", __func__);
-
- spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */
- spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */
- spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */
-
- clear_fifo(ss);
-
- /* 1/8 clock */
- spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2);
- udelay(10);
-
- return 0;
-}
-
-static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg)
-{
- struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- pr_debug("%s: enter\n", __func__);
- pr_debug("\tmode = %02x\n", spi->mode);
-
- spin_lock_irqsave(&ss->lock, flags);
-
- mesg->actual_length = 0;
- mesg->status = -EINPROGRESS;
-
- spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
- list_add_tail(&mesg->queue, &ss->queue);
- queue_work(ss->workqueue, &ss->ws);
-
- spin_unlock_irqrestore(&ss->lock, flags);
-
- return 0;
-}
-
-static void spi_sh_cleanup(struct spi_device *spi)
-{
- struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
-
- pr_debug("%s: enter\n", __func__);
-
- spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
- SPI_SH_CR1);
-}
-
-static irqreturn_t spi_sh_irq(int irq, void *_ss)
-{
- struct spi_sh_data *ss = (struct spi_sh_data *)_ss;
- unsigned long cr1;
-
- cr1 = spi_sh_read(ss, SPI_SH_CR1);
- if (cr1 & SPI_SH_TBE)
- ss->cr1 |= SPI_SH_TBE;
- if (cr1 & SPI_SH_TBF)
- ss->cr1 |= SPI_SH_TBF;
- if (cr1 & SPI_SH_RBE)
- ss->cr1 |= SPI_SH_RBE;
- if (cr1 & SPI_SH_RBF)
- ss->cr1 |= SPI_SH_RBF;
-
- if (ss->cr1) {
- spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4);
- wake_up(&ss->wait);
- }
-
- return IRQ_HANDLED;
-}
-
-static int __devexit spi_sh_remove(struct platform_device *pdev)
-{
- struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev);
-
- spi_unregister_master(ss->master);
- destroy_workqueue(ss->workqueue);
- free_irq(ss->irq, ss);
- iounmap(ss->addr);
-
- return 0;
-}
-
-static int __devinit spi_sh_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct spi_master *master;
- struct spi_sh_data *ss;
- int ret, irq;
-
- /* get base addr */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(res == NULL)) {
- dev_err(&pdev->dev, "invalid resource\n");
- return -EINVAL;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "platform_get_irq error\n");
- return -ENODEV;
- }
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
- if (master == NULL) {
- dev_err(&pdev->dev, "spi_alloc_master error.\n");
- return -ENOMEM;
- }
-
- ss = spi_master_get_devdata(master);
- dev_set_drvdata(&pdev->dev, ss);
-
- switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
- case IORESOURCE_MEM_8BIT:
- ss->width = 8;
- break;
- case IORESOURCE_MEM_32BIT:
- ss->width = 32;
- break;
- default:
- dev_err(&pdev->dev, "No support width\n");
- ret = -ENODEV;
- goto error1;
- }
- ss->irq = irq;
- ss->master = master;
- ss->addr = ioremap(res->start, resource_size(res));
- if (ss->addr == NULL) {
- dev_err(&pdev->dev, "ioremap error.\n");
- ret = -ENOMEM;
- goto error1;
- }
- INIT_LIST_HEAD(&ss->queue);
- spin_lock_init(&ss->lock);
- INIT_WORK(&ss->ws, spi_sh_work);
- init_waitqueue_head(&ss->wait);
- ss->workqueue = create_singlethread_workqueue(
- dev_name(master->dev.parent));
- if (ss->workqueue == NULL) {
- dev_err(&pdev->dev, "create workqueue error\n");
- ret = -EBUSY;
- goto error2;
- }
-
- ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
- if (ret < 0) {
- dev_err(&pdev->dev, "request_irq error\n");
- goto error3;
- }
-
- master->num_chipselect = 2;
- master->bus_num = pdev->id;
- master->setup = spi_sh_setup;
- master->transfer = spi_sh_transfer;
- master->cleanup = spi_sh_cleanup;
-
- ret = spi_register_master(master);
- if (ret < 0) {
- printk(KERN_ERR "spi_register_master error.\n");
- goto error4;
- }
-
- return 0;
-
- error4:
- free_irq(irq, ss);
- error3:
- destroy_workqueue(ss->workqueue);
- error2:
- iounmap(ss->addr);
- error1:
- spi_master_put(master);
-
- return ret;
-}
-
-static struct platform_driver spi_sh_driver = {
- .probe = spi_sh_probe,
- .remove = __devexit_p(spi_sh_remove),
- .driver = {
- .name = "sh_spi",
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(spi_sh_driver);
-
-MODULE_DESCRIPTION("SH SPI bus driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yoshihiro Shimoda");
-MODULE_ALIAS("platform:sh_spi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-sirf.c b/ANDROID_3.4.5/drivers/spi/spi-sirf.c
deleted file mode 100644
index 52fe495b..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-sirf.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * SPI bus driver for CSR SiRFprimaII
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/bitops.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/of_gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/pinctrl/pinmux.h>
-
-#define DRIVER_NAME "sirfsoc_spi"
-
-#define SIRFSOC_SPI_CTRL 0x0000
-#define SIRFSOC_SPI_CMD 0x0004
-#define SIRFSOC_SPI_TX_RX_EN 0x0008
-#define SIRFSOC_SPI_INT_EN 0x000C
-#define SIRFSOC_SPI_INT_STATUS 0x0010
-#define SIRFSOC_SPI_TX_DMA_IO_CTRL 0x0100
-#define SIRFSOC_SPI_TX_DMA_IO_LEN 0x0104
-#define SIRFSOC_SPI_TXFIFO_CTRL 0x0108
-#define SIRFSOC_SPI_TXFIFO_LEVEL_CHK 0x010C
-#define SIRFSOC_SPI_TXFIFO_OP 0x0110
-#define SIRFSOC_SPI_TXFIFO_STATUS 0x0114
-#define SIRFSOC_SPI_TXFIFO_DATA 0x0118
-#define SIRFSOC_SPI_RX_DMA_IO_CTRL 0x0120
-#define SIRFSOC_SPI_RX_DMA_IO_LEN 0x0124
-#define SIRFSOC_SPI_RXFIFO_CTRL 0x0128
-#define SIRFSOC_SPI_RXFIFO_LEVEL_CHK 0x012C
-#define SIRFSOC_SPI_RXFIFO_OP 0x0130
-#define SIRFSOC_SPI_RXFIFO_STATUS 0x0134
-#define SIRFSOC_SPI_RXFIFO_DATA 0x0138
-#define SIRFSOC_SPI_DUMMY_DELAY_CTL 0x0144
-
-/* SPI CTRL register defines */
-#define SIRFSOC_SPI_SLV_MODE BIT(16)
-#define SIRFSOC_SPI_CMD_MODE BIT(17)
-#define SIRFSOC_SPI_CS_IO_OUT BIT(18)
-#define SIRFSOC_SPI_CS_IO_MODE BIT(19)
-#define SIRFSOC_SPI_CLK_IDLE_STAT BIT(20)
-#define SIRFSOC_SPI_CS_IDLE_STAT BIT(21)
-#define SIRFSOC_SPI_TRAN_MSB BIT(22)
-#define SIRFSOC_SPI_DRV_POS_EDGE BIT(23)
-#define SIRFSOC_SPI_CS_HOLD_TIME BIT(24)
-#define SIRFSOC_SPI_CLK_SAMPLE_MODE BIT(25)
-#define SIRFSOC_SPI_TRAN_DAT_FORMAT_8 (0 << 26)
-#define SIRFSOC_SPI_TRAN_DAT_FORMAT_12 (1 << 26)
-#define SIRFSOC_SPI_TRAN_DAT_FORMAT_16 (2 << 26)
-#define SIRFSOC_SPI_TRAN_DAT_FORMAT_32 (3 << 26)
-#define SIRFSOC_SPI_CMD_BYTE_NUM(x) ((x & 3) << 28)
-#define SIRFSOC_SPI_ENA_AUTO_CLR BIT(30)
-#define SIRFSOC_SPI_MUL_DAT_MODE BIT(31)
-
-/* Interrupt Enable */
-#define SIRFSOC_SPI_RX_DONE_INT_EN BIT(0)
-#define SIRFSOC_SPI_TX_DONE_INT_EN BIT(1)
-#define SIRFSOC_SPI_RX_OFLOW_INT_EN BIT(2)
-#define SIRFSOC_SPI_TX_UFLOW_INT_EN BIT(3)
-#define SIRFSOC_SPI_RX_IO_DMA_INT_EN BIT(4)
-#define SIRFSOC_SPI_TX_IO_DMA_INT_EN BIT(5)
-#define SIRFSOC_SPI_RXFIFO_FULL_INT_EN BIT(6)
-#define SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN BIT(7)
-#define SIRFSOC_SPI_RXFIFO_THD_INT_EN BIT(8)
-#define SIRFSOC_SPI_TXFIFO_THD_INT_EN BIT(9)
-#define SIRFSOC_SPI_FRM_END_INT_EN BIT(10)
-
-#define SIRFSOC_SPI_INT_MASK_ALL 0x1FFF
-
-/* Interrupt status */
-#define SIRFSOC_SPI_RX_DONE BIT(0)
-#define SIRFSOC_SPI_TX_DONE BIT(1)
-#define SIRFSOC_SPI_RX_OFLOW BIT(2)
-#define SIRFSOC_SPI_TX_UFLOW BIT(3)
-#define SIRFSOC_SPI_RX_FIFO_FULL BIT(6)
-#define SIRFSOC_SPI_TXFIFO_EMPTY BIT(7)
-#define SIRFSOC_SPI_RXFIFO_THD_REACH BIT(8)
-#define SIRFSOC_SPI_TXFIFO_THD_REACH BIT(9)
-#define SIRFSOC_SPI_FRM_END BIT(10)
-
-/* TX RX enable */
-#define SIRFSOC_SPI_RX_EN BIT(0)
-#define SIRFSOC_SPI_TX_EN BIT(1)
-#define SIRFSOC_SPI_CMD_TX_EN BIT(2)
-
-#define SIRFSOC_SPI_IO_MODE_SEL BIT(0)
-#define SIRFSOC_SPI_RX_DMA_FLUSH BIT(2)
-
-/* FIFO OPs */
-#define SIRFSOC_SPI_FIFO_RESET BIT(0)
-#define SIRFSOC_SPI_FIFO_START BIT(1)
-
-/* FIFO CTRL */
-#define SIRFSOC_SPI_FIFO_WIDTH_BYTE (0 << 0)
-#define SIRFSOC_SPI_FIFO_WIDTH_WORD (1 << 0)
-#define SIRFSOC_SPI_FIFO_WIDTH_DWORD (2 << 0)
-
-/* FIFO Status */
-#define SIRFSOC_SPI_FIFO_LEVEL_MASK 0xFF
-#define SIRFSOC_SPI_FIFO_FULL BIT(8)
-#define SIRFSOC_SPI_FIFO_EMPTY BIT(9)
-
-/* 256 bytes rx/tx FIFO */
-#define SIRFSOC_SPI_FIFO_SIZE 256
-#define SIRFSOC_SPI_DAT_FRM_LEN_MAX (64 * 1024)
-
-#define SIRFSOC_SPI_FIFO_SC(x) ((x) & 0x3F)
-#define SIRFSOC_SPI_FIFO_LC(x) (((x) & 0x3F) << 10)
-#define SIRFSOC_SPI_FIFO_HC(x) (((x) & 0x3F) << 20)
-#define SIRFSOC_SPI_FIFO_THD(x) (((x) & 0xFF) << 2)
-
-struct sirfsoc_spi {
- struct spi_bitbang bitbang;
- struct completion done;
-
- void __iomem *base;
- u32 ctrl_freq; /* SPI controller clock speed */
- struct clk *clk;
- struct pinmux *pmx;
-
- /* rx & tx bufs from the spi_transfer */
- const void *tx;
- void *rx;
-
- /* place received word into rx buffer */
- void (*rx_word) (struct sirfsoc_spi *);
- /* get word from tx buffer for sending */
- void (*tx_word) (struct sirfsoc_spi *);
-
- /* number of words left to be tranmitted/received */
- unsigned int left_tx_cnt;
- unsigned int left_rx_cnt;
-
- /* tasklet to push tx msg into FIFO */
- struct tasklet_struct tasklet_tx;
-
- int chipselect[0];
-};
-
-static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi)
-{
- u32 data;
- u8 *rx = sspi->rx;
-
- data = readl(sspi->base + SIRFSOC_SPI_RXFIFO_DATA);
-
- if (rx) {
- *rx++ = (u8) data;
- sspi->rx = rx;
- }
-
- sspi->left_rx_cnt--;
-}
-
-static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi)
-{
- u32 data = 0;
- const u8 *tx = sspi->tx;
-
- if (tx) {
- data = *tx++;
- sspi->tx = tx;
- }
-
- writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA);
- sspi->left_tx_cnt--;
-}
-
-static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi)
-{
- u32 data;
- u16 *rx = sspi->rx;
-
- data = readl(sspi->base + SIRFSOC_SPI_RXFIFO_DATA);
-
- if (rx) {
- *rx++ = (u16) data;
- sspi->rx = rx;
- }
-
- sspi->left_rx_cnt--;
-}
-
-static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi)
-{
- u32 data = 0;
- const u16 *tx = sspi->tx;
-
- if (tx) {
- data = *tx++;
- sspi->tx = tx;
- }
-
- writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA);
- sspi->left_tx_cnt--;
-}
-
-static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi)
-{
- u32 data;
- u32 *rx = sspi->rx;
-
- data = readl(sspi->base + SIRFSOC_SPI_RXFIFO_DATA);
-
- if (rx) {
- *rx++ = (u32) data;
- sspi->rx = rx;
- }
-
- sspi->left_rx_cnt--;
-
-}
-
-static void spi_sirfsoc_tx_word_u32(struct sirfsoc_spi *sspi)
-{
- u32 data = 0;
- const u32 *tx = sspi->tx;
-
- if (tx) {
- data = *tx++;
- sspi->tx = tx;
- }
-
- writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA);
- sspi->left_tx_cnt--;
-}
-
-static void spi_sirfsoc_tasklet_tx(unsigned long arg)
-{
- struct sirfsoc_spi *sspi = (struct sirfsoc_spi *)arg;
-
- /* Fill Tx FIFO while there are left words to be transmitted */
- while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) &
- SIRFSOC_SPI_FIFO_FULL)) &&
- sspi->left_tx_cnt)
- sspi->tx_word(sspi);
-}
-
-static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
-{
- struct sirfsoc_spi *sspi = dev_id;
- u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS);
-
- writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS);
-
- /* Error Conditions */
- if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
- spi_stat & SIRFSOC_SPI_TX_UFLOW) {
- complete(&sspi->done);
- writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
- }
-
- if (spi_stat & SIRFSOC_SPI_FRM_END) {
- while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS)
- & SIRFSOC_SPI_FIFO_EMPTY)) &&
- sspi->left_rx_cnt)
- sspi->rx_word(sspi);
-
- /* Received all words */
- if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) {
- complete(&sspi->done);
- writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
- }
- }
-
- if (spi_stat & SIRFSOC_SPI_RXFIFO_THD_REACH ||
- spi_stat & SIRFSOC_SPI_TXFIFO_THD_REACH ||
- spi_stat & SIRFSOC_SPI_RX_FIFO_FULL ||
- spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY)
- tasklet_schedule(&sspi->tasklet_tx);
-
- return IRQ_HANDLED;
-}
-
-static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct sirfsoc_spi *sspi;
- int timeout = t->len * 10;
- sspi = spi_master_get_devdata(spi->master);
-
- sspi->tx = t->tx_buf;
- sspi->rx = t->rx_buf;
- sspi->left_tx_cnt = sspi->left_rx_cnt = t->len;
- INIT_COMPLETION(sspi->done);
-
- writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
-
- if (t->len == 1) {
- writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
- SIRFSOC_SPI_ENA_AUTO_CLR,
- sspi->base + SIRFSOC_SPI_CTRL);
- writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
- writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
- } else if ((t->len > 1) && (t->len < SIRFSOC_SPI_DAT_FRM_LEN_MAX)) {
- writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
- SIRFSOC_SPI_MUL_DAT_MODE |
- SIRFSOC_SPI_ENA_AUTO_CLR,
- sspi->base + SIRFSOC_SPI_CTRL);
- writel(t->len - 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
- writel(t->len - 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
- } else {
- writel(readl(sspi->base + SIRFSOC_SPI_CTRL),
- sspi->base + SIRFSOC_SPI_CTRL);
- writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
- writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
- }
-
- writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
-
- /* Send the first word to trigger the whole tx/rx process */
- sspi->tx_word(sspi);
-
- writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
- SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
- SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
- SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
- writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN);
-
- if (wait_for_completion_timeout(&sspi->done, timeout) == 0)
- dev_err(&spi->dev, "transfer timeout\n");
-
- /* TX, RX FIFO stop */
- writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
- writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN);
- writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
-
- return t->len - sspi->left_rx_cnt;
-}
-
-static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
-{
- struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master);
-
- if (sspi->chipselect[spi->chip_select] == 0) {
- u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL);
- regval |= SIRFSOC_SPI_CS_IO_OUT;
- switch (value) {
- case BITBANG_CS_ACTIVE:
- if (spi->mode & SPI_CS_HIGH)
- regval |= SIRFSOC_SPI_CS_IO_OUT;
- else
- regval &= ~SIRFSOC_SPI_CS_IO_OUT;
- break;
- case BITBANG_CS_INACTIVE:
- if (spi->mode & SPI_CS_HIGH)
- regval &= ~SIRFSOC_SPI_CS_IO_OUT;
- else
- regval |= SIRFSOC_SPI_CS_IO_OUT;
- break;
- }
- writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
- } else {
- int gpio = sspi->chipselect[spi->chip_select];
- gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
- }
-}
-
-static int
-spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
- struct sirfsoc_spi *sspi;
- u8 bits_per_word = 0;
- int hz = 0;
- u32 regval;
- u32 txfifo_ctrl, rxfifo_ctrl;
- u32 fifo_size = SIRFSOC_SPI_FIFO_SIZE / 4;
-
- sspi = spi_master_get_devdata(spi->master);
-
- bits_per_word = t && t->bits_per_word ? t->bits_per_word :
- spi->bits_per_word;
- hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz;
-
- /* Enable IO mode for RX, TX */
- writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
- writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
- regval = (sspi->ctrl_freq / (2 * hz)) - 1;
-
- if (regval > 0xFFFF || regval < 0) {
- dev_err(&spi->dev, "Speed %d not supported\n", hz);
- return -EINVAL;
- }
-
- switch (bits_per_word) {
- case 8:
- regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_8;
- sspi->rx_word = spi_sirfsoc_rx_word_u8;
- sspi->tx_word = spi_sirfsoc_tx_word_u8;
- txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
- SIRFSOC_SPI_FIFO_WIDTH_BYTE;
- rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
- SIRFSOC_SPI_FIFO_WIDTH_BYTE;
- break;
- case 12:
- case 16:
- regval |= (bits_per_word == 12) ? SIRFSOC_SPI_TRAN_DAT_FORMAT_12 :
- SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
- sspi->rx_word = spi_sirfsoc_rx_word_u16;
- sspi->tx_word = spi_sirfsoc_tx_word_u16;
- txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
- SIRFSOC_SPI_FIFO_WIDTH_WORD;
- rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
- SIRFSOC_SPI_FIFO_WIDTH_WORD;
- break;
- case 32:
- regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
- sspi->rx_word = spi_sirfsoc_rx_word_u32;
- sspi->tx_word = spi_sirfsoc_tx_word_u32;
- txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
- SIRFSOC_SPI_FIFO_WIDTH_DWORD;
- rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
- SIRFSOC_SPI_FIFO_WIDTH_DWORD;
- break;
- default:
- dev_err(&spi->dev, "Bits per word %d not supported\n",
- bits_per_word);
- return -EINVAL;
- }
-
- if (!(spi->mode & SPI_CS_HIGH))
- regval |= SIRFSOC_SPI_CS_IDLE_STAT;
- if (!(spi->mode & SPI_LSB_FIRST))
- regval |= SIRFSOC_SPI_TRAN_MSB;
- if (spi->mode & SPI_CPOL)
- regval |= SIRFSOC_SPI_CLK_IDLE_STAT;
-
- /*
- * Data should be driven at least 1/2 cycle before the fetch edge to make
- * sure that data gets stable at the fetch edge.
- */
- if (((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA)) ||
- (!(spi->mode & SPI_CPOL) && !(spi->mode & SPI_CPHA)))
- regval &= ~SIRFSOC_SPI_DRV_POS_EDGE;
- else
- regval |= SIRFSOC_SPI_DRV_POS_EDGE;
-
- writel(SIRFSOC_SPI_FIFO_SC(fifo_size - 2) |
- SIRFSOC_SPI_FIFO_LC(fifo_size / 2) |
- SIRFSOC_SPI_FIFO_HC(2),
- sspi->base + SIRFSOC_SPI_TXFIFO_LEVEL_CHK);
- writel(SIRFSOC_SPI_FIFO_SC(2) |
- SIRFSOC_SPI_FIFO_LC(fifo_size / 2) |
- SIRFSOC_SPI_FIFO_HC(fifo_size - 2),
- sspi->base + SIRFSOC_SPI_RXFIFO_LEVEL_CHK);
- writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL);
- writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL);
-
- writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
- return 0;
-}
-
-static int spi_sirfsoc_setup(struct spi_device *spi)
-{
- struct sirfsoc_spi *sspi;
-
- if (!spi->max_speed_hz)
- return -EINVAL;
-
- sspi = spi_master_get_devdata(spi->master);
-
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
-
- return spi_sirfsoc_setup_transfer(spi, NULL);
-}
-
-static int __devinit spi_sirfsoc_probe(struct platform_device *pdev)
-{
- struct sirfsoc_spi *sspi;
- struct spi_master *master;
- struct resource *mem_res;
- int num_cs, cs_gpio, irq;
- int i;
- int ret;
-
- ret = of_property_read_u32(pdev->dev.of_node,
- "sirf,spi-num-chipselects", &num_cs);
- if (ret < 0) {
- dev_err(&pdev->dev, "Unable to get chip select number\n");
- goto err_cs;
- }
-
- master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs);
- if (!master) {
- dev_err(&pdev->dev, "Unable to allocate SPI master\n");
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, master);
- sspi = spi_master_get_devdata(master);
-
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem_res) {
- dev_err(&pdev->dev, "Unable to get IO resource\n");
- ret = -ENODEV;
- goto free_master;
- }
- master->num_chipselect = num_cs;
-
- for (i = 0; i < master->num_chipselect; i++) {
- cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i);
- if (cs_gpio < 0) {
- dev_err(&pdev->dev, "can't get cs gpio from DT\n");
- ret = -ENODEV;
- goto free_master;
- }
-
- sspi->chipselect[i] = cs_gpio;
- if (cs_gpio == 0)
- continue; /* use cs from spi controller */
-
- ret = gpio_request(cs_gpio, DRIVER_NAME);
- if (ret) {
- while (i > 0) {
- i--;
- if (sspi->chipselect[i] > 0)
- gpio_free(sspi->chipselect[i]);
- }
- dev_err(&pdev->dev, "fail to request cs gpios\n");
- goto free_master;
- }
- }
-
- sspi->base = devm_request_and_ioremap(&pdev->dev, mem_res);
- if (!sspi->base) {
- dev_err(&pdev->dev, "IO remap failed!\n");
- ret = -ENOMEM;
- goto free_master;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- ret = -ENXIO;
- goto free_master;
- }
- ret = devm_request_irq(&pdev->dev, irq, spi_sirfsoc_irq, 0,
- DRIVER_NAME, sspi);
- if (ret)
- goto free_master;
-
- sspi->bitbang.master = spi_master_get(master);
- sspi->bitbang.chipselect = spi_sirfsoc_chipselect;
- sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer;
- sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
- sspi->bitbang.master->setup = spi_sirfsoc_setup;
- master->bus_num = pdev->id;
- sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
-
- sspi->pmx = pinmux_get(&pdev->dev, NULL);
- ret = IS_ERR(sspi->pmx);
- if (ret)
- goto free_master;
-
- pinmux_enable(sspi->pmx);
-
- sspi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(sspi->clk)) {
- ret = -EINVAL;
- goto free_pmx;
- }
- clk_enable(sspi->clk);
- sspi->ctrl_freq = clk_get_rate(sspi->clk);
-
- init_completion(&sspi->done);
-
- tasklet_init(&sspi->tasklet_tx, spi_sirfsoc_tasklet_tx,
- (unsigned long)sspi);
-
- writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
- /* We are not using dummy delay between command and data */
- writel(0, sspi->base + SIRFSOC_SPI_DUMMY_DELAY_CTL);
-
- ret = spi_bitbang_start(&sspi->bitbang);
- if (ret)
- goto free_clk;
-
- dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num);
-
- return 0;
-
-free_clk:
- clk_disable(sspi->clk);
- clk_put(sspi->clk);
-free_pmx:
- pinmux_disable(sspi->pmx);
- pinmux_put(sspi->pmx);
-free_master:
- spi_master_put(master);
-err_cs:
- return ret;
-}
-
-static int __devexit spi_sirfsoc_remove(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct sirfsoc_spi *sspi;
- int i;
-
- master = platform_get_drvdata(pdev);
- sspi = spi_master_get_devdata(master);
-
- spi_bitbang_stop(&sspi->bitbang);
- for (i = 0; i < master->num_chipselect; i++) {
- if (sspi->chipselect[i] > 0)
- gpio_free(sspi->chipselect[i]);
- }
- clk_disable(sspi->clk);
- clk_put(sspi->clk);
- pinmux_disable(sspi->pmx);
- pinmux_put(sspi->pmx);
- spi_master_put(master);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int spi_sirfsoc_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct spi_master *master = platform_get_drvdata(pdev);
- struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
-
- clk_disable(sspi->clk);
- return 0;
-}
-
-static int spi_sirfsoc_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct spi_master *master = platform_get_drvdata(pdev);
- struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
-
- clk_enable(sspi->clk);
- writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
- writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
-
- return 0;
-}
-
-static const struct dev_pm_ops spi_sirfsoc_pm_ops = {
- .suspend = spi_sirfsoc_suspend,
- .resume = spi_sirfsoc_resume,
-};
-#endif
-
-static const struct of_device_id spi_sirfsoc_of_match[] = {
- { .compatible = "sirf,prima2-spi", },
- {}
-};
-MODULE_DEVICE_TABLE(of, sirfsoc_spi_of_match);
-
-static struct platform_driver spi_sirfsoc_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &spi_sirfsoc_pm_ops,
-#endif
- .of_match_table = spi_sirfsoc_of_match,
- },
- .probe = spi_sirfsoc_probe,
- .remove = __devexit_p(spi_sirfsoc_remove),
-};
-module_platform_driver(spi_sirfsoc_driver);
-
-MODULE_DESCRIPTION("SiRF SoC SPI master driver");
-MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, "
- "Barry Song <Baohua.Song@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-stmp.c b/ANDROID_3.4.5/drivers/spi/spi-stmp.c
deleted file mode 100644
index 58e38528..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-stmp.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * Freescale STMP378X SPI master driver
- *
- * Author: dmitry pervushin <dimka@embeddedalley.com>
- *
- * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-
-#include <mach/platform.h>
-#include <mach/stmp3xxx.h>
-#include <mach/dma.h>
-#include <mach/regs-ssp.h>
-#include <mach/regs-apbh.h>
-
-
-/* 0 means DMA mode(recommended, default), !0 - PIO mode */
-static int pio;
-static int clock;
-
-/* default timeout for busy waits is 2 seconds */
-#define STMP_SPI_TIMEOUT (2 * HZ)
-
-struct stmp_spi {
- int id;
-
- void * __iomem regs; /* vaddr of the control registers */
-
- int irq, err_irq;
- u32 dma;
- struct stmp3xxx_dma_descriptor d;
-
- u32 speed_khz;
- u32 saved_timings;
- u32 divider;
-
- struct clk *clk;
- struct device *master_dev;
-
- struct work_struct work;
- struct workqueue_struct *workqueue;
-
- /* lock protects queue access */
- spinlock_t lock;
- struct list_head queue;
-
- struct completion done;
-};
-
-#define busy_wait(cond) \
- ({ \
- unsigned long end_jiffies = jiffies + STMP_SPI_TIMEOUT; \
- bool succeeded = false; \
- do { \
- if (cond) { \
- succeeded = true; \
- break; \
- } \
- cpu_relax(); \
- } while (time_before(jiffies, end_jiffies)); \
- succeeded; \
- })
-
-/**
- * stmp_spi_init_hw
- * Initialize the SSP port
- */
-static int stmp_spi_init_hw(struct stmp_spi *ss)
-{
- int err = 0;
- void *pins = ss->master_dev->platform_data;
-
- err = stmp3xxx_request_pin_group(pins, dev_name(ss->master_dev));
- if (err)
- goto out;
-
- ss->clk = clk_get(NULL, "ssp");
- if (IS_ERR(ss->clk)) {
- err = PTR_ERR(ss->clk);
- goto out_free_pins;
- }
- clk_enable(ss->clk);
-
- stmp3xxx_reset_block(ss->regs, false);
- stmp3xxx_dma_reset_channel(ss->dma);
-
- return 0;
-
-out_free_pins:
- stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
-out:
- return err;
-}
-
-static void stmp_spi_release_hw(struct stmp_spi *ss)
-{
- void *pins = ss->master_dev->platform_data;
-
- if (ss->clk && !IS_ERR(ss->clk)) {
- clk_disable(ss->clk);
- clk_put(ss->clk);
- }
- stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
-}
-
-static int stmp_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- u8 bits_per_word;
- u32 hz;
- struct stmp_spi *ss = spi_master_get_devdata(spi->master);
- u16 rate;
-
- bits_per_word = spi->bits_per_word;
- if (t && t->bits_per_word)
- bits_per_word = t->bits_per_word;
-
- /*
- * Calculate speed:
- * - by default, use maximum speed from ssp clk
- * - if device overrides it, use it
- * - if transfer specifies other speed, use transfer's one
- */
- hz = 1000 * ss->speed_khz / ss->divider;
- if (spi->max_speed_hz)
- hz = min(hz, spi->max_speed_hz);
- if (t && t->speed_hz)
- hz = min(hz, t->speed_hz);
-
- if (hz == 0) {
- dev_err(&spi->dev, "Cannot continue with zero clock\n");
- return -EINVAL;
- }
-
- if (bits_per_word != 8) {
- dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
- __func__, bits_per_word);
- return -EINVAL;
- }
-
- dev_dbg(&spi->dev, "Requested clk rate = %uHz, max = %uHz/%d = %uHz\n",
- hz, ss->speed_khz, ss->divider,
- ss->speed_khz * 1000 / ss->divider);
-
- if (ss->speed_khz * 1000 / ss->divider < hz) {
- dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
- __func__, hz);
- return -EINVAL;
- }
-
- rate = 1000 * ss->speed_khz/ss->divider/hz;
-
- writel(BF(ss->divider, SSP_TIMING_CLOCK_DIVIDE) |
- BF(rate - 1, SSP_TIMING_CLOCK_RATE),
- HW_SSP_TIMING + ss->regs);
-
- writel(BF(1 /* mode SPI */, SSP_CTRL1_SSP_MODE) |
- BF(4 /* 8 bits */, SSP_CTRL1_WORD_LENGTH) |
- ((spi->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
- ((spi->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0) |
- (pio ? 0 : BM_SSP_CTRL1_DMA_ENABLE),
- ss->regs + HW_SSP_CTRL1);
-
- return 0;
-}
-
-static int stmp_spi_setup(struct spi_device *spi)
-{
- /* spi_setup() does basic checks,
- * stmp_spi_setup_transfer() does more later
- */
- if (spi->bits_per_word != 8) {
- dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
- __func__, spi->bits_per_word);
- return -EINVAL;
- }
- return 0;
-}
-
-static inline u32 stmp_spi_cs(unsigned cs)
-{
- return ((cs & 1) ? BM_SSP_CTRL0_WAIT_FOR_CMD : 0) |
- ((cs & 2) ? BM_SSP_CTRL0_WAIT_FOR_IRQ : 0);
-}
-
-static int stmp_spi_txrx_dma(struct stmp_spi *ss, int cs,
- unsigned char *buf, dma_addr_t dma_buf, int len,
- int first, int last, bool write)
-{
- u32 c0 = 0;
- dma_addr_t spi_buf_dma = dma_buf;
- int status = 0;
- enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
- c0 |= (first ? BM_SSP_CTRL0_LOCK_CS : 0);
- c0 |= (last ? BM_SSP_CTRL0_IGNORE_CRC : 0);
- c0 |= (write ? 0 : BM_SSP_CTRL0_READ);
- c0 |= BM_SSP_CTRL0_DATA_XFER;
-
- c0 |= stmp_spi_cs(cs);
-
- c0 |= BF(len, SSP_CTRL0_XFER_COUNT);
-
- if (!dma_buf)
- spi_buf_dma = dma_map_single(ss->master_dev, buf, len, dir);
-
- ss->d.command->cmd =
- BF(len, APBH_CHn_CMD_XFER_COUNT) |
- BF(1, APBH_CHn_CMD_CMDWORDS) |
- BM_APBH_CHn_CMD_WAIT4ENDCMD |
- BM_APBH_CHn_CMD_IRQONCMPLT |
- BF(write ? BV_APBH_CHn_CMD_COMMAND__DMA_READ :
- BV_APBH_CHn_CMD_COMMAND__DMA_WRITE,
- APBH_CHn_CMD_COMMAND);
- ss->d.command->pio_words[0] = c0;
- ss->d.command->buf_ptr = spi_buf_dma;
-
- stmp3xxx_dma_reset_channel(ss->dma);
- stmp3xxx_dma_clear_interrupt(ss->dma);
- stmp3xxx_dma_enable_interrupt(ss->dma);
- init_completion(&ss->done);
- stmp3xxx_dma_go(ss->dma, &ss->d, 1);
- wait_for_completion(&ss->done);
-
- if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN))
- status = -ETIMEDOUT;
-
- if (!dma_buf)
- dma_unmap_single(ss->master_dev, spi_buf_dma, len, dir);
-
- return status;
-}
-
-static inline void stmp_spi_enable(struct stmp_spi *ss)
-{
- stmp3xxx_setl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
- stmp3xxx_clearl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
-}
-
-static inline void stmp_spi_disable(struct stmp_spi *ss)
-{
- stmp3xxx_clearl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
- stmp3xxx_setl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
-}
-
-static int stmp_spi_txrx_pio(struct stmp_spi *ss, int cs,
- unsigned char *buf, int len,
- bool first, bool last, bool write)
-{
- if (first)
- stmp_spi_enable(ss);
-
- stmp3xxx_setl(stmp_spi_cs(cs), ss->regs + HW_SSP_CTRL0);
-
- while (len--) {
- if (last && len <= 0)
- stmp_spi_disable(ss);
-
- stmp3xxx_clearl(BM_SSP_CTRL0_XFER_COUNT,
- ss->regs + HW_SSP_CTRL0);
- stmp3xxx_setl(1, ss->regs + HW_SSP_CTRL0);
-
- if (write)
- stmp3xxx_clearl(BM_SSP_CTRL0_READ,
- ss->regs + HW_SSP_CTRL0);
- else
- stmp3xxx_setl(BM_SSP_CTRL0_READ,
- ss->regs + HW_SSP_CTRL0);
-
- /* Run! */
- stmp3xxx_setl(BM_SSP_CTRL0_RUN, ss->regs + HW_SSP_CTRL0);
-
- if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
- BM_SSP_CTRL0_RUN))
- break;
-
- if (write)
- writel(*buf, ss->regs + HW_SSP_DATA);
-
- /* Set TRANSFER */
- stmp3xxx_setl(BM_SSP_CTRL0_DATA_XFER, ss->regs + HW_SSP_CTRL0);
-
- if (!write) {
- if (busy_wait((readl(ss->regs + HW_SSP_STATUS) &
- BM_SSP_STATUS_FIFO_EMPTY)))
- break;
- *buf = readl(ss->regs + HW_SSP_DATA) & 0xFF;
- }
-
- if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
- BM_SSP_CTRL0_RUN))
- break;
-
- /* advance to the next byte */
- buf++;
- }
-
- return len < 0 ? 0 : -ETIMEDOUT;
-}
-
-static int stmp_spi_handle_message(struct stmp_spi *ss, struct spi_message *m)
-{
- bool first, last;
- struct spi_transfer *t, *tmp_t;
- int status = 0;
- int cs;
-
- cs = m->spi->chip_select;
-
- list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
-
- first = (&t->transfer_list == m->transfers.next);
- last = (&t->transfer_list == m->transfers.prev);
-
- if (first || t->speed_hz || t->bits_per_word)
- stmp_spi_setup_transfer(m->spi, t);
-
- /* reject "not last" transfers which request to change cs */
- if (t->cs_change && !last) {
- dev_err(&m->spi->dev,
- "Message with t->cs_change has been skipped\n");
- continue;
- }
-
- if (t->tx_buf) {
- status = pio ?
- stmp_spi_txrx_pio(ss, cs, (void *)t->tx_buf,
- t->len, first, last, true) :
- stmp_spi_txrx_dma(ss, cs, (void *)t->tx_buf,
- t->tx_dma, t->len, first, last, true);
-#ifdef DEBUG
- if (t->len < 0x10)
- print_hex_dump_bytes("Tx ",
- DUMP_PREFIX_OFFSET,
- t->tx_buf, t->len);
- else
- pr_debug("Tx: %d bytes\n", t->len);
-#endif
- }
- if (t->rx_buf) {
- status = pio ?
- stmp_spi_txrx_pio(ss, cs, t->rx_buf,
- t->len, first, last, false) :
- stmp_spi_txrx_dma(ss, cs, t->rx_buf,
- t->rx_dma, t->len, first, last, false);
-#ifdef DEBUG
- if (t->len < 0x10)
- print_hex_dump_bytes("Rx ",
- DUMP_PREFIX_OFFSET,
- t->rx_buf, t->len);
- else
- pr_debug("Rx: %d bytes\n", t->len);
-#endif
- }
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (status)
- break;
-
- }
- return status;
-}
-
-/**
- * stmp_spi_handle - handle messages from the queue
- */
-static void stmp_spi_handle(struct work_struct *w)
-{
- struct stmp_spi *ss = container_of(w, struct stmp_spi, work);
- unsigned long flags;
- struct spi_message *m;
-
- spin_lock_irqsave(&ss->lock, flags);
- while (!list_empty(&ss->queue)) {
- m = list_entry(ss->queue.next, struct spi_message, queue);
- list_del_init(&m->queue);
- spin_unlock_irqrestore(&ss->lock, flags);
-
- m->status = stmp_spi_handle_message(ss, m);
- m->complete(m->context);
-
- spin_lock_irqsave(&ss->lock, flags);
- }
- spin_unlock_irqrestore(&ss->lock, flags);
-
- return;
-}
-
-/**
- * stmp_spi_transfer - perform message transfer.
- * Called indirectly from spi_async, queues all the messages to
- * spi_handle_message.
- * @spi: spi device
- * @m: message to be queued
- */
-static int stmp_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct stmp_spi *ss = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- m->status = -EINPROGRESS;
- spin_lock_irqsave(&ss->lock, flags);
- list_add_tail(&m->queue, &ss->queue);
- queue_work(ss->workqueue, &ss->work);
- spin_unlock_irqrestore(&ss->lock, flags);
- return 0;
-}
-
-static irqreturn_t stmp_spi_irq(int irq, void *dev_id)
-{
- struct stmp_spi *ss = dev_id;
-
- stmp3xxx_dma_clear_interrupt(ss->dma);
- complete(&ss->done);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t stmp_spi_irq_err(int irq, void *dev_id)
-{
- struct stmp_spi *ss = dev_id;
- u32 c1, st;
-
- c1 = readl(ss->regs + HW_SSP_CTRL1);
- st = readl(ss->regs + HW_SSP_STATUS);
- dev_err(ss->master_dev, "%s: status = 0x%08X, c1 = 0x%08X\n",
- __func__, st, c1);
- stmp3xxx_clearl(c1 & 0xCCCC0000, ss->regs + HW_SSP_CTRL1);
-
- return IRQ_HANDLED;
-}
-
-static int __devinit stmp_spi_probe(struct platform_device *dev)
-{
- int err = 0;
- struct spi_master *master;
- struct stmp_spi *ss;
- struct resource *r;
-
- master = spi_alloc_master(&dev->dev, sizeof(struct stmp_spi));
- if (master == NULL) {
- err = -ENOMEM;
- goto out0;
- }
- master->flags = SPI_MASTER_HALF_DUPLEX;
-
- ss = spi_master_get_devdata(master);
- platform_set_drvdata(dev, master);
-
- /* Get resources(memory, IRQ) associated with the device */
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- err = -ENODEV;
- goto out_put_master;
- }
- ss->regs = ioremap(r->start, resource_size(r));
- if (!ss->regs) {
- err = -EINVAL;
- goto out_put_master;
- }
-
- ss->master_dev = &dev->dev;
- ss->id = dev->id;
-
- INIT_WORK(&ss->work, stmp_spi_handle);
- INIT_LIST_HEAD(&ss->queue);
- spin_lock_init(&ss->lock);
-
- ss->workqueue = create_singlethread_workqueue(dev_name(&dev->dev));
- if (!ss->workqueue) {
- err = -ENXIO;
- goto out_put_master;
- }
- master->transfer = stmp_spi_transfer;
- master->setup = stmp_spi_setup;
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA;
-
- ss->irq = platform_get_irq(dev, 0);
- if (ss->irq < 0) {
- err = ss->irq;
- goto out_put_master;
- }
- ss->err_irq = platform_get_irq(dev, 1);
- if (ss->err_irq < 0) {
- err = ss->err_irq;
- goto out_put_master;
- }
-
- r = platform_get_resource(dev, IORESOURCE_DMA, 0);
- if (r == NULL) {
- err = -ENODEV;
- goto out_put_master;
- }
-
- ss->dma = r->start;
- err = stmp3xxx_dma_request(ss->dma, &dev->dev, dev_name(&dev->dev));
- if (err)
- goto out_put_master;
-
- err = stmp3xxx_dma_allocate_command(ss->dma, &ss->d);
- if (err)
- goto out_free_dma;
-
- master->bus_num = dev->id;
- master->num_chipselect = 1;
-
- /* SPI controller initializations */
- err = stmp_spi_init_hw(ss);
- if (err) {
- dev_dbg(&dev->dev, "cannot initialize hardware\n");
- goto out_free_dma_desc;
- }
-
- if (clock) {
- dev_info(&dev->dev, "clock rate forced to %d\n", clock);
- clk_set_rate(ss->clk, clock);
- }
- ss->speed_khz = clk_get_rate(ss->clk);
- ss->divider = 2;
- dev_info(&dev->dev, "max possible speed %d = %ld/%d kHz\n",
- ss->speed_khz, clk_get_rate(ss->clk), ss->divider);
-
- /* Register for SPI interrupt */
- err = request_irq(ss->irq, stmp_spi_irq, 0,
- dev_name(&dev->dev), ss);
- if (err) {
- dev_dbg(&dev->dev, "request_irq failed, %d\n", err);
- goto out_release_hw;
- }
-
- /* ..and shared interrupt for all SSP controllers */
- err = request_irq(ss->err_irq, stmp_spi_irq_err, IRQF_SHARED,
- dev_name(&dev->dev), ss);
- if (err) {
- dev_dbg(&dev->dev, "request_irq(error) failed, %d\n", err);
- goto out_free_irq;
- }
-
- err = spi_register_master(master);
- if (err) {
- dev_dbg(&dev->dev, "cannot register spi master, %d\n", err);
- goto out_free_irq_2;
- }
- dev_info(&dev->dev, "at (mapped) 0x%08X, irq=%d, bus %d, %s mode\n",
- (u32)ss->regs, ss->irq, master->bus_num,
- pio ? "PIO" : "DMA");
- return 0;
-
-out_free_irq_2:
- free_irq(ss->err_irq, ss);
-out_free_irq:
- free_irq(ss->irq, ss);
-out_free_dma_desc:
- stmp3xxx_dma_free_command(ss->dma, &ss->d);
-out_free_dma:
- stmp3xxx_dma_release(ss->dma);
-out_release_hw:
- stmp_spi_release_hw(ss);
-out_put_master:
- if (ss->workqueue)
- destroy_workqueue(ss->workqueue);
- if (ss->regs)
- iounmap(ss->regs);
- platform_set_drvdata(dev, NULL);
- spi_master_put(master);
-out0:
- return err;
-}
-
-static int __devexit stmp_spi_remove(struct platform_device *dev)
-{
- struct stmp_spi *ss;
- struct spi_master *master;
-
- master = platform_get_drvdata(dev);
- if (master == NULL)
- goto out0;
- ss = spi_master_get_devdata(master);
-
- spi_unregister_master(master);
-
- free_irq(ss->err_irq, ss);
- free_irq(ss->irq, ss);
- stmp3xxx_dma_free_command(ss->dma, &ss->d);
- stmp3xxx_dma_release(ss->dma);
- stmp_spi_release_hw(ss);
- destroy_workqueue(ss->workqueue);
- iounmap(ss->regs);
- spi_master_put(master);
- platform_set_drvdata(dev, NULL);
-out0:
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int stmp_spi_suspend(struct platform_device *pdev, pm_message_t pmsg)
-{
- struct stmp_spi *ss;
- struct spi_master *master;
-
- master = platform_get_drvdata(pdev);
- ss = spi_master_get_devdata(master);
-
- ss->saved_timings = readl(HW_SSP_TIMING + ss->regs);
- clk_disable(ss->clk);
-
- return 0;
-}
-
-static int stmp_spi_resume(struct platform_device *pdev)
-{
- struct stmp_spi *ss;
- struct spi_master *master;
-
- master = platform_get_drvdata(pdev);
- ss = spi_master_get_devdata(master);
-
- clk_enable(ss->clk);
- stmp3xxx_reset_block(ss->regs, false);
- writel(ss->saved_timings, ss->regs + HW_SSP_TIMING);
-
- return 0;
-}
-
-#else
-#define stmp_spi_suspend NULL
-#define stmp_spi_resume NULL
-#endif
-
-static struct platform_driver stmp_spi_driver = {
- .probe = stmp_spi_probe,
- .remove = __devexit_p(stmp_spi_remove),
- .driver = {
- .name = "stmp3xxx_ssp",
- .owner = THIS_MODULE,
- },
- .suspend = stmp_spi_suspend,
- .resume = stmp_spi_resume,
-};
-module_platform_driver(stmp_spi_driver);
-
-module_param(pio, int, S_IRUGO);
-module_param(clock, int, S_IRUGO);
-MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
-MODULE_DESCRIPTION("STMP3xxx SPI/SSP driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-tegra.c b/ANDROID_3.4.5/drivers/spi/spi-tegra.c
deleted file mode 100644
index ae6d78a3..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-tegra.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Driver for Nvidia TEGRA spi controller.
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Erik Gilling <konkers@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <linux/spi/spi.h>
-
-#include <mach/dma.h>
-
-#define SLINK_COMMAND 0x000
-#define SLINK_BIT_LENGTH(x) (((x) & 0x1f) << 0)
-#define SLINK_WORD_SIZE(x) (((x) & 0x1f) << 5)
-#define SLINK_BOTH_EN (1 << 10)
-#define SLINK_CS_SW (1 << 11)
-#define SLINK_CS_VALUE (1 << 12)
-#define SLINK_CS_POLARITY (1 << 13)
-#define SLINK_IDLE_SDA_DRIVE_LOW (0 << 16)
-#define SLINK_IDLE_SDA_DRIVE_HIGH (1 << 16)
-#define SLINK_IDLE_SDA_PULL_LOW (2 << 16)
-#define SLINK_IDLE_SDA_PULL_HIGH (3 << 16)
-#define SLINK_IDLE_SDA_MASK (3 << 16)
-#define SLINK_CS_POLARITY1 (1 << 20)
-#define SLINK_CK_SDA (1 << 21)
-#define SLINK_CS_POLARITY2 (1 << 22)
-#define SLINK_CS_POLARITY3 (1 << 23)
-#define SLINK_IDLE_SCLK_DRIVE_LOW (0 << 24)
-#define SLINK_IDLE_SCLK_DRIVE_HIGH (1 << 24)
-#define SLINK_IDLE_SCLK_PULL_LOW (2 << 24)
-#define SLINK_IDLE_SCLK_PULL_HIGH (3 << 24)
-#define SLINK_IDLE_SCLK_MASK (3 << 24)
-#define SLINK_M_S (1 << 28)
-#define SLINK_WAIT (1 << 29)
-#define SLINK_GO (1 << 30)
-#define SLINK_ENB (1 << 31)
-
-#define SLINK_COMMAND2 0x004
-#define SLINK_LSBFE (1 << 0)
-#define SLINK_SSOE (1 << 1)
-#define SLINK_SPIE (1 << 4)
-#define SLINK_BIDIROE (1 << 6)
-#define SLINK_MODFEN (1 << 7)
-#define SLINK_INT_SIZE(x) (((x) & 0x1f) << 8)
-#define SLINK_CS_ACTIVE_BETWEEN (1 << 17)
-#define SLINK_SS_EN_CS(x) (((x) & 0x3) << 18)
-#define SLINK_SS_SETUP(x) (((x) & 0x3) << 20)
-#define SLINK_FIFO_REFILLS_0 (0 << 22)
-#define SLINK_FIFO_REFILLS_1 (1 << 22)
-#define SLINK_FIFO_REFILLS_2 (2 << 22)
-#define SLINK_FIFO_REFILLS_3 (3 << 22)
-#define SLINK_FIFO_REFILLS_MASK (3 << 22)
-#define SLINK_WAIT_PACK_INT(x) (((x) & 0x7) << 26)
-#define SLINK_SPC0 (1 << 29)
-#define SLINK_TXEN (1 << 30)
-#define SLINK_RXEN (1 << 31)
-
-#define SLINK_STATUS 0x008
-#define SLINK_COUNT(val) (((val) >> 0) & 0x1f)
-#define SLINK_WORD(val) (((val) >> 5) & 0x1f)
-#define SLINK_BLK_CNT(val) (((val) >> 0) & 0xffff)
-#define SLINK_MODF (1 << 16)
-#define SLINK_RX_UNF (1 << 18)
-#define SLINK_TX_OVF (1 << 19)
-#define SLINK_TX_FULL (1 << 20)
-#define SLINK_TX_EMPTY (1 << 21)
-#define SLINK_RX_FULL (1 << 22)
-#define SLINK_RX_EMPTY (1 << 23)
-#define SLINK_TX_UNF (1 << 24)
-#define SLINK_RX_OVF (1 << 25)
-#define SLINK_TX_FLUSH (1 << 26)
-#define SLINK_RX_FLUSH (1 << 27)
-#define SLINK_SCLK (1 << 28)
-#define SLINK_ERR (1 << 29)
-#define SLINK_RDY (1 << 30)
-#define SLINK_BSY (1 << 31)
-
-#define SLINK_MAS_DATA 0x010
-#define SLINK_SLAVE_DATA 0x014
-
-#define SLINK_DMA_CTL 0x018
-#define SLINK_DMA_BLOCK_SIZE(x) (((x) & 0xffff) << 0)
-#define SLINK_TX_TRIG_1 (0 << 16)
-#define SLINK_TX_TRIG_4 (1 << 16)
-#define SLINK_TX_TRIG_8 (2 << 16)
-#define SLINK_TX_TRIG_16 (3 << 16)
-#define SLINK_TX_TRIG_MASK (3 << 16)
-#define SLINK_RX_TRIG_1 (0 << 18)
-#define SLINK_RX_TRIG_4 (1 << 18)
-#define SLINK_RX_TRIG_8 (2 << 18)
-#define SLINK_RX_TRIG_16 (3 << 18)
-#define SLINK_RX_TRIG_MASK (3 << 18)
-#define SLINK_PACKED (1 << 20)
-#define SLINK_PACK_SIZE_4 (0 << 21)
-#define SLINK_PACK_SIZE_8 (1 << 21)
-#define SLINK_PACK_SIZE_16 (2 << 21)
-#define SLINK_PACK_SIZE_32 (3 << 21)
-#define SLINK_PACK_SIZE_MASK (3 << 21)
-#define SLINK_IE_TXC (1 << 26)
-#define SLINK_IE_RXC (1 << 27)
-#define SLINK_DMA_EN (1 << 31)
-
-#define SLINK_STATUS2 0x01c
-#define SLINK_TX_FIFO_EMPTY_COUNT(val) (((val) & 0x3f) >> 0)
-#define SLINK_RX_FIFO_FULL_COUNT(val) (((val) & 0x3f) >> 16)
-
-#define SLINK_TX_FIFO 0x100
-#define SLINK_RX_FIFO 0x180
-
-static const unsigned long spi_tegra_req_sels[] = {
- TEGRA_DMA_REQ_SEL_SL2B1,
- TEGRA_DMA_REQ_SEL_SL2B2,
- TEGRA_DMA_REQ_SEL_SL2B3,
- TEGRA_DMA_REQ_SEL_SL2B4,
-};
-
-#define BB_LEN 32
-
-struct spi_tegra_data {
- struct spi_master *master;
- struct platform_device *pdev;
- spinlock_t lock;
-
- struct clk *clk;
- void __iomem *base;
- unsigned long phys;
-
- u32 cur_speed;
-
- struct list_head queue;
- struct spi_transfer *cur;
- unsigned cur_pos;
- unsigned cur_len;
- unsigned cur_bytes_per_word;
-
- /* The tegra spi controller has a bug which causes the first word
- * in PIO transactions to be garbage. Since packed DMA transactions
- * require transfers to be 4 byte aligned we need a bounce buffer
- * for the generic case.
- */
- struct tegra_dma_req rx_dma_req;
- struct tegra_dma_channel *rx_dma;
- u32 *rx_bb;
- dma_addr_t rx_bb_phys;
-};
-
-
-static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
- unsigned long reg)
-{
- return readl(tspi->base + reg);
-}
-
-static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
- unsigned long val,
- unsigned long reg)
-{
- writel(val, tspi->base + reg);
-}
-
-static void spi_tegra_go(struct spi_tegra_data *tspi)
-{
- unsigned long val;
-
- wmb();
-
- val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
- val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
- val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1);
- spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-
- tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
-
- val |= SLINK_DMA_EN;
- spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-}
-
-static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
- struct spi_transfer *t)
-{
- unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
- tspi->cur_bytes_per_word);
- u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
- int i, j;
- unsigned long val;
-
- val = spi_tegra_readl(tspi, SLINK_COMMAND);
- val &= ~SLINK_WORD_SIZE(~0);
- val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
- spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
- for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
- val = 0;
- for (j = 0; j < tspi->cur_bytes_per_word; j++)
- val |= tx_buf[i + j] << j * 8;
-
- spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
- }
-
- tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4;
-
- return len;
-}
-
-static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
- struct spi_transfer *t)
-{
- unsigned len = tspi->cur_len;
- u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
- int i, j;
- unsigned long val;
-
- for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
- val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
- for (j = 0; j < tspi->cur_bytes_per_word; j++)
- rx_buf[i + j] = (val >> (j * 8)) & 0xff;
- }
-
- return len;
-}
-
-static void spi_tegra_start_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
- u32 speed;
- u8 bits_per_word;
- unsigned long val;
-
- speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
- bits_per_word = t->bits_per_word ? t->bits_per_word :
- spi->bits_per_word;
-
- tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
-
- if (speed != tspi->cur_speed)
- clk_set_rate(tspi->clk, speed);
-
- if (tspi->cur_speed == 0)
- clk_enable(tspi->clk);
-
- tspi->cur_speed = speed;
-
- val = spi_tegra_readl(tspi, SLINK_COMMAND2);
- val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
- if (t->rx_buf)
- val |= SLINK_RXEN;
- if (t->tx_buf)
- val |= SLINK_TXEN;
- val |= SLINK_SS_EN_CS(spi->chip_select);
- val |= SLINK_SPIE;
- spi_tegra_writel(tspi, val, SLINK_COMMAND2);
-
- val = spi_tegra_readl(tspi, SLINK_COMMAND);
- val &= ~SLINK_BIT_LENGTH(~0);
- val |= SLINK_BIT_LENGTH(bits_per_word - 1);
-
- /* FIXME: should probably control CS manually so that we can be sure
- * it does not go low between transfer and to support delay_usecs
- * correctly.
- */
- val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
-
- if (spi->mode & SPI_CPHA)
- val |= SLINK_CK_SDA;
-
- if (spi->mode & SPI_CPOL)
- val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
- else
- val |= SLINK_IDLE_SCLK_DRIVE_LOW;
-
- val |= SLINK_M_S;
-
- spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
- spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
-
- tspi->cur = t;
- tspi->cur_pos = 0;
- tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
-
- spi_tegra_go(tspi);
-}
-
-static void spi_tegra_start_message(struct spi_device *spi,
- struct spi_message *m)
-{
- struct spi_transfer *t;
-
- m->actual_length = 0;
- m->status = 0;
-
- t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
- spi_tegra_start_transfer(spi, t);
-}
-
-static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
-{
- struct spi_tegra_data *tspi = req->dev;
- unsigned long flags;
- struct spi_message *m;
- struct spi_device *spi;
- int timeout = 0;
- unsigned long val;
-
- /* the SPI controller may come back with both the BSY and RDY bits
- * set. In this case we need to wait for the BSY bit to clear so
- * that we are sure the DMA is finished. 1000 reads was empirically
- * determined to be long enough.
- */
- while (timeout++ < 1000) {
- if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
- break;
- }
-
- spin_lock_irqsave(&tspi->lock, flags);
-
- val = spi_tegra_readl(tspi, SLINK_STATUS);
- val |= SLINK_RDY;
- spi_tegra_writel(tspi, val, SLINK_STATUS);
-
- m = list_first_entry(&tspi->queue, struct spi_message, queue);
-
- if (timeout >= 1000)
- m->status = -EIO;
-
- spi = m->state;
-
- tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
- m->actual_length += tspi->cur_pos;
-
- if (tspi->cur_pos < tspi->cur->len) {
- tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
- spi_tegra_go(tspi);
- } else if (!list_is_last(&tspi->cur->transfer_list,
- &m->transfers)) {
- tspi->cur = list_first_entry(&tspi->cur->transfer_list,
- struct spi_transfer,
- transfer_list);
- spi_tegra_start_transfer(spi, tspi->cur);
- } else {
- list_del(&m->queue);
-
- m->complete(m->context);
-
- if (!list_empty(&tspi->queue)) {
- m = list_first_entry(&tspi->queue, struct spi_message,
- queue);
- spi = m->state;
- spi_tegra_start_message(spi, m);
- } else {
- clk_disable(tspi->clk);
- tspi->cur_speed = 0;
- }
- }
-
- spin_unlock_irqrestore(&tspi->lock, flags);
-}
-
-static int spi_tegra_setup(struct spi_device *spi)
-{
- struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
- unsigned long cs_bit;
- unsigned long val;
- unsigned long flags;
-
- dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
- spi->bits_per_word,
- spi->mode & SPI_CPOL ? "" : "~",
- spi->mode & SPI_CPHA ? "" : "~",
- spi->max_speed_hz);
-
-
- switch (spi->chip_select) {
- case 0:
- cs_bit = SLINK_CS_POLARITY;
- break;
-
- case 1:
- cs_bit = SLINK_CS_POLARITY1;
- break;
-
- case 2:
- cs_bit = SLINK_CS_POLARITY2;
- break;
-
- case 4:
- cs_bit = SLINK_CS_POLARITY3;
- break;
-
- default:
- return -EINVAL;
- }
-
- spin_lock_irqsave(&tspi->lock, flags);
-
- val = spi_tegra_readl(tspi, SLINK_COMMAND);
- if (spi->mode & SPI_CS_HIGH)
- val |= cs_bit;
- else
- val &= ~cs_bit;
- spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
- spin_unlock_irqrestore(&tspi->lock, flags);
-
- return 0;
-}
-
-static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
- struct spi_transfer *t;
- unsigned long flags;
- int was_empty;
-
- if (list_empty(&m->transfers) || !m->complete)
- return -EINVAL;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->bits_per_word < 0 || t->bits_per_word > 32)
- return -EINVAL;
-
- if (t->len == 0)
- return -EINVAL;
-
- if (!t->rx_buf && !t->tx_buf)
- return -EINVAL;
- }
-
- m->state = spi;
-
- spin_lock_irqsave(&tspi->lock, flags);
- was_empty = list_empty(&tspi->queue);
- list_add_tail(&m->queue, &tspi->queue);
-
- if (was_empty)
- spi_tegra_start_message(spi, m);
-
- spin_unlock_irqrestore(&tspi->lock, flags);
-
- return 0;
-}
-
-static int __devinit spi_tegra_probe(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct spi_tegra_data *tspi;
- struct resource *r;
- int ret;
-
- master = spi_alloc_master(&pdev->dev, sizeof *tspi);
- if (master == NULL) {
- dev_err(&pdev->dev, "master allocation failed\n");
- return -ENOMEM;
- }
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- master->bus_num = pdev->id;
-
- master->setup = spi_tegra_setup;
- master->transfer = spi_tegra_transfer;
- master->num_chipselect = 4;
-
- dev_set_drvdata(&pdev->dev, master);
- tspi = spi_master_get_devdata(master);
- tspi->master = master;
- tspi->pdev = pdev;
- spin_lock_init(&tspi->lock);
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENODEV;
- goto err0;
- }
-
- 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, resource_size(r));
- if (!tspi->base) {
- dev_err(&pdev->dev, "can't ioremap iomem\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- tspi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(tspi->clk)) {
- dev_err(&pdev->dev, "can not get clock\n");
- ret = PTR_ERR(tspi->clk);
- goto err2;
- }
-
- INIT_LIST_HEAD(&tspi->queue);
-
- tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
- if (!tspi->rx_dma) {
- dev_err(&pdev->dev, "can not allocate rx dma channel\n");
- ret = -ENODEV;
- goto err3;
- }
-
- tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
- &tspi->rx_bb_phys, GFP_KERNEL);
- if (!tspi->rx_bb) {
- dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
- ret = -ENOMEM;
- goto err4;
- }
-
- tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
- tspi->rx_dma_req.to_memory = 1;
- tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
- tspi->rx_dma_req.dest_bus_width = 32;
- tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
- tspi->rx_dma_req.source_bus_width = 32;
- tspi->rx_dma_req.source_wrap = 4;
- 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)
- goto err5;
-
- return ret;
-
-err5:
- dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
- tspi->rx_bb, tspi->rx_bb_phys);
-err4:
- tegra_dma_free_channel(tspi->rx_dma);
-err3:
- clk_put(tspi->clk);
-err2:
- iounmap(tspi->base);
-err1:
- release_mem_region(r->start, resource_size(r));
-err0:
- spi_master_put(master);
- return ret;
-}
-
-static int __devexit spi_tegra_remove(struct platform_device *pdev)
-{
- struct spi_master *master;
- struct spi_tegra_data *tspi;
- struct resource *r;
-
- master = dev_get_drvdata(&pdev->dev);
- tspi = spi_master_get_devdata(master);
-
- spi_unregister_master(master);
- tegra_dma_free_channel(tspi->rx_dma);
-
- dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
- tspi->rx_bb, tspi->rx_bb_phys);
-
- clk_put(tspi->clk);
- iounmap(tspi->base);
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- 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,
- },
- .probe = spi_tegra_probe,
- .remove = __devexit_p(spi_tegra_remove),
-};
-module_platform_driver(spi_tegra_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-ti-ssp.c b/ANDROID_3.4.5/drivers/spi/spi-ti-ssp.c
deleted file mode 100644
index 3f6f6e81..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-ti-ssp.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Sequencer Serial Port (SSP) based SPI master driver
- *
- * Copyright (C) 2010 Texas Instruments Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/ti_ssp.h>
-
-#define MODE_BITS (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
-
-struct ti_ssp_spi {
- struct spi_master *master;
- struct device *dev;
- spinlock_t lock;
- struct list_head msg_queue;
- struct completion complete;
- bool shutdown;
- struct workqueue_struct *workqueue;
- struct work_struct work;
- u8 mode, bpw;
- int cs_active;
- u32 pc_en, pc_dis, pc_wr, pc_rd;
- void (*select)(int cs);
-};
-
-static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
-{
- u32 ret;
-
- ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
- return ret;
-}
-
-static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
-{
- ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
-}
-
-static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
- struct spi_transfer *t)
-{
- int count;
-
- if (hw->bpw <= 8) {
- u8 *rx = t->rx_buf;
- const u8 *tx = t->tx_buf;
-
- for (count = 0; count < t->len; count += 1) {
- if (t->tx_buf)
- ti_ssp_spi_tx(hw, *tx++);
- if (t->rx_buf)
- *rx++ = ti_ssp_spi_rx(hw);
- }
- } else if (hw->bpw <= 16) {
- u16 *rx = t->rx_buf;
- const u16 *tx = t->tx_buf;
-
- for (count = 0; count < t->len; count += 2) {
- if (t->tx_buf)
- ti_ssp_spi_tx(hw, *tx++);
- if (t->rx_buf)
- *rx++ = ti_ssp_spi_rx(hw);
- }
- } else {
- u32 *rx = t->rx_buf;
- const u32 *tx = t->tx_buf;
-
- for (count = 0; count < t->len; count += 4) {
- if (t->tx_buf)
- ti_ssp_spi_tx(hw, *tx++);
- if (t->rx_buf)
- *rx++ = ti_ssp_spi_rx(hw);
- }
- }
-
- msg->actual_length += count; /* bytes transferred */
-
- dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
- t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
- hw->bpw, count, (count < t->len) ? " (under)" : "");
-
- return (count < t->len) ? -EIO : 0; /* left over data */
-}
-
-static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
-{
- cs_active = !!cs_active;
- if (cs_active == hw->cs_active)
- return;
- ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
- hw->cs_active = cs_active;
-}
-
-#define __SHIFT_OUT(bits) (SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
- cs_en | clk | SSP_COUNT((bits) * 2 - 1))
-#define __SHIFT_IN(bits) (SSP_OPCODE_SHIFT | SSP_IN_MODE | \
- cs_en | clk | SSP_COUNT((bits) * 2 - 1))
-
-static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
-{
- int error, idx = 0;
- u32 seqram[16];
- u32 cs_en, cs_dis, clk;
- u32 topbits, botbits;
-
- mode &= MODE_BITS;
- if (mode == hw->mode && bpw == hw->bpw)
- return 0;
-
- cs_en = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
- cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW : SSP_CS_HIGH;
- clk = (mode & SPI_CPOL) ? SSP_CLK_HIGH : SSP_CLK_LOW;
-
- /* Construct instructions */
-
- /* Disable Chip Select */
- hw->pc_dis = idx;
- seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
- seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_dis | clk;
-
- /* Enable Chip Select */
- hw->pc_en = idx;
- seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
- seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
-
- /* Reads and writes need to be split for bpw > 16 */
- topbits = (bpw > 16) ? 16 : bpw;
- botbits = bpw - topbits;
-
- /* Write */
- hw->pc_wr = idx;
- seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
- if (botbits)
- seqram[idx++] = __SHIFT_OUT(botbits) | SSP_DATA_REG;
- seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
-
- /* Read */
- hw->pc_rd = idx;
- if (botbits)
- seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
- seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
- seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
-
- error = ti_ssp_load(hw->dev, 0, seqram, idx);
- if (error < 0)
- return error;
-
- error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
- 0 : SSP_EARLY_DIN));
- if (error < 0)
- return error;
-
- hw->bpw = bpw;
- hw->mode = mode;
-
- return error;
-}
-
-static void ti_ssp_spi_work(struct work_struct *work)
-{
- struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
-
- spin_lock(&hw->lock);
-
- while (!list_empty(&hw->msg_queue)) {
- struct spi_message *m;
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
- int status = 0;
-
- m = container_of(hw->msg_queue.next, struct spi_message,
- queue);
-
- list_del_init(&m->queue);
-
- spin_unlock(&hw->lock);
-
- spi = m->spi;
-
- if (hw->select)
- hw->select(spi->chip_select);
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- int bpw = spi->bits_per_word;
- int xfer_status;
-
- if (t->bits_per_word)
- bpw = t->bits_per_word;
-
- if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
- break;
-
- ti_ssp_spi_chip_select(hw, 1);
-
- xfer_status = ti_ssp_spi_txrx(hw, m, t);
- if (xfer_status < 0)
- status = xfer_status;
-
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (t->cs_change)
- ti_ssp_spi_chip_select(hw, 0);
- }
-
- ti_ssp_spi_chip_select(hw, 0);
- m->status = status;
- m->complete(m->context);
-
- spin_lock(&hw->lock);
- }
-
- if (hw->shutdown)
- complete(&hw->complete);
-
- spin_unlock(&hw->lock);
-}
-
-static int ti_ssp_spi_setup(struct spi_device *spi)
-{
- if (spi->bits_per_word > 32)
- return -EINVAL;
-
- return 0;
-}
-
-static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct ti_ssp_spi *hw;
- struct spi_transfer *t;
- int error = 0;
-
- m->actual_length = 0;
- m->status = -EINPROGRESS;
-
- hw = spi_master_get_devdata(spi->master);
-
- if (list_empty(&m->transfers) || !m->complete)
- return -EINVAL;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->len && !(t->rx_buf || t->tx_buf)) {
- dev_err(&spi->dev, "invalid xfer, no buffer\n");
- return -EINVAL;
- }
-
- if (t->len && t->rx_buf && t->tx_buf) {
- dev_err(&spi->dev, "invalid xfer, full duplex\n");
- return -EINVAL;
- }
-
- if (t->bits_per_word > 32) {
- dev_err(&spi->dev, "invalid xfer width %d\n",
- t->bits_per_word);
- return -EINVAL;
- }
- }
-
- spin_lock(&hw->lock);
- if (hw->shutdown) {
- error = -ESHUTDOWN;
- goto error_unlock;
- }
- list_add_tail(&m->queue, &hw->msg_queue);
- queue_work(hw->workqueue, &hw->work);
-error_unlock:
- spin_unlock(&hw->lock);
- return error;
-}
-
-static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
-{
- const struct ti_ssp_spi_data *pdata;
- struct ti_ssp_spi *hw;
- struct spi_master *master;
- struct device *dev = &pdev->dev;
- int error = 0;
-
- pdata = dev->platform_data;
- if (!pdata) {
- dev_err(dev, "platform data not found\n");
- return -EINVAL;
- }
-
- master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
- if (!master) {
- dev_err(dev, "cannot allocate SPI master\n");
- return -ENOMEM;
- }
-
- hw = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, hw);
-
- hw->master = master;
- hw->dev = dev;
- hw->select = pdata->select;
-
- spin_lock_init(&hw->lock);
- init_completion(&hw->complete);
- INIT_LIST_HEAD(&hw->msg_queue);
- INIT_WORK(&hw->work, ti_ssp_spi_work);
-
- hw->workqueue = create_singlethread_workqueue(dev_name(dev));
- if (!hw->workqueue) {
- error = -ENOMEM;
- dev_err(dev, "work queue creation failed\n");
- goto error_wq;
- }
-
- error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
- if (error < 0) {
- dev_err(dev, "io setup failed\n");
- goto error_iosel;
- }
-
- master->bus_num = pdev->id;
- master->num_chipselect = pdata->num_cs;
- master->mode_bits = MODE_BITS;
- master->flags = SPI_MASTER_HALF_DUPLEX;
- master->setup = ti_ssp_spi_setup;
- master->transfer = ti_ssp_spi_transfer;
-
- error = spi_register_master(master);
- if (error) {
- dev_err(dev, "master registration failed\n");
- goto error_reg;
- }
-
- return 0;
-
-error_reg:
-error_iosel:
- destroy_workqueue(hw->workqueue);
-error_wq:
- spi_master_put(master);
- return error;
-}
-
-static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
-{
- struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
- int error;
-
- hw->shutdown = 1;
- while (!list_empty(&hw->msg_queue)) {
- error = wait_for_completion_interruptible(&hw->complete);
- if (error < 0) {
- hw->shutdown = 0;
- return error;
- }
- }
- destroy_workqueue(hw->workqueue);
- spi_unregister_master(hw->master);
-
- return 0;
-}
-
-static struct platform_driver ti_ssp_spi_driver = {
- .probe = ti_ssp_spi_probe,
- .remove = __devexit_p(ti_ssp_spi_remove),
- .driver = {
- .name = "ti-ssp-spi",
- .owner = THIS_MODULE,
- },
-};
-module_platform_driver(ti_ssp_spi_driver);
-
-MODULE_DESCRIPTION("SSP SPI Master");
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ti-ssp-spi");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-tle62x0.c b/ANDROID_3.4.5/drivers/spi/spi-tle62x0.c
deleted file mode 100644
index 0ce5c12a..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-tle62x0.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Support Infineon TLE62x0 driver chips
- *
- * Copyright (c) 2007 Simtec Electronics
- * Ben Dooks, <ben@simtec.co.uk>
- *
- * 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/device.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/tle62x0.h>
-
-
-#define CMD_READ 0x00
-#define CMD_SET 0xff
-
-#define DIAG_NORMAL 0x03
-#define DIAG_OVERLOAD 0x02
-#define DIAG_OPEN 0x01
-#define DIAG_SHORTGND 0x00
-
-struct tle62x0_state {
- struct spi_device *us;
- struct mutex lock;
- unsigned int nr_gpio;
- unsigned int gpio_state;
-
- unsigned char tx_buff[4];
- unsigned char rx_buff[4];
-};
-
-static int to_gpio_num(struct device_attribute *attr);
-
-static inline int tle62x0_write(struct tle62x0_state *st)
-{
- unsigned char *buff = st->tx_buff;
- unsigned int gpio_state = st->gpio_state;
-
- buff[0] = CMD_SET;
-
- if (st->nr_gpio == 16) {
- buff[1] = gpio_state >> 8;
- buff[2] = gpio_state;
- } else {
- buff[1] = gpio_state;
- }
-
- dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
- buff[0], buff[1], buff[2]);
-
- return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
-}
-
-static inline int tle62x0_read(struct tle62x0_state *st)
-{
- unsigned char *txbuff = st->tx_buff;
- struct spi_transfer xfer = {
- .tx_buf = txbuff,
- .rx_buf = st->rx_buff,
- .len = (st->nr_gpio * 2) / 8,
- };
- struct spi_message msg;
-
- txbuff[0] = CMD_READ;
- txbuff[1] = 0x00;
- txbuff[2] = 0x00;
- txbuff[3] = 0x00;
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
-
- return spi_sync(st->us, &msg);
-}
-
-static unsigned char *decode_fault(unsigned int fault_code)
-{
- fault_code &= 3;
-
- switch (fault_code) {
- case DIAG_NORMAL:
- return "N";
- case DIAG_OVERLOAD:
- return "V";
- case DIAG_OPEN:
- return "O";
- case DIAG_SHORTGND:
- return "G";
- }
-
- return "?";
-}
-
-static ssize_t tle62x0_status_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tle62x0_state *st = dev_get_drvdata(dev);
- char *bp = buf;
- unsigned char *buff = st->rx_buff;
- unsigned long fault = 0;
- int ptr;
- int ret;
-
- mutex_lock(&st->lock);
- ret = tle62x0_read(st);
- dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
- if (ret < 0) {
- mutex_unlock(&st->lock);
- return ret;
- }
-
- for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
- fault <<= 8;
- fault |= ((unsigned long)buff[ptr]);
-
- dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
- }
-
- for (ptr = 0; ptr < st->nr_gpio; ptr++) {
- bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
- }
-
- *bp++ = '\n';
-
- mutex_unlock(&st->lock);
- return bp - buf;
-}
-
-static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
-
-static ssize_t tle62x0_gpio_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tle62x0_state *st = dev_get_drvdata(dev);
- int gpio_num = to_gpio_num(attr);
- int value;
-
- mutex_lock(&st->lock);
- value = (st->gpio_state >> gpio_num) & 1;
- mutex_unlock(&st->lock);
-
- return snprintf(buf, PAGE_SIZE, "%d", value);
-}
-
-static ssize_t tle62x0_gpio_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct tle62x0_state *st = dev_get_drvdata(dev);
- int gpio_num = to_gpio_num(attr);
- unsigned long val;
- char *endp;
-
- val = simple_strtoul(buf, &endp, 0);
- if (buf == endp)
- return -EINVAL;
-
- dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
-
- mutex_lock(&st->lock);
-
- if (val)
- st->gpio_state |= 1 << gpio_num;
- else
- st->gpio_state &= ~(1 << gpio_num);
-
- tle62x0_write(st);
- mutex_unlock(&st->lock);
-
- return len;
-}
-
-static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
- tle62x0_gpio_show, tle62x0_gpio_store);
-
-static struct device_attribute *gpio_attrs[] = {
- [0] = &dev_attr_gpio1,
- [1] = &dev_attr_gpio2,
- [2] = &dev_attr_gpio3,
- [3] = &dev_attr_gpio4,
- [4] = &dev_attr_gpio5,
- [5] = &dev_attr_gpio6,
- [6] = &dev_attr_gpio7,
- [7] = &dev_attr_gpio8,
- [8] = &dev_attr_gpio9,
- [9] = &dev_attr_gpio10,
- [10] = &dev_attr_gpio11,
- [11] = &dev_attr_gpio12,
- [12] = &dev_attr_gpio13,
- [13] = &dev_attr_gpio14,
- [14] = &dev_attr_gpio15,
- [15] = &dev_attr_gpio16
-};
-
-static int to_gpio_num(struct device_attribute *attr)
-{
- int ptr;
-
- for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
- if (gpio_attrs[ptr] == attr)
- return ptr;
- }
-
- return -1;
-}
-
-static int __devinit tle62x0_probe(struct spi_device *spi)
-{
- struct tle62x0_state *st;
- struct tle62x0_pdata *pdata;
- int ptr;
- int ret;
-
- pdata = spi->dev.platform_data;
- if (pdata == NULL) {
- dev_err(&spi->dev, "no device data specified\n");
- return -EINVAL;
- }
-
- st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
- if (st == NULL) {
- dev_err(&spi->dev, "no memory for device state\n");
- return -ENOMEM;
- }
-
- st->us = spi;
- st->nr_gpio = pdata->gpio_count;
- st->gpio_state = pdata->init_state;
-
- mutex_init(&st->lock);
-
- ret = device_create_file(&spi->dev, &dev_attr_status_show);
- if (ret) {
- dev_err(&spi->dev, "cannot create status attribute\n");
- goto err_status;
- }
-
- for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
- ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
- if (ret) {
- dev_err(&spi->dev, "cannot create gpio attribute\n");
- goto err_gpios;
- }
- }
-
- /* tle62x0_write(st); */
- spi_set_drvdata(spi, st);
- return 0;
-
- err_gpios:
- while (--ptr >= 0)
- device_remove_file(&spi->dev, gpio_attrs[ptr]);
-
- device_remove_file(&spi->dev, &dev_attr_status_show);
-
- err_status:
- kfree(st);
- return ret;
-}
-
-static int __devexit tle62x0_remove(struct spi_device *spi)
-{
- struct tle62x0_state *st = spi_get_drvdata(spi);
- int ptr;
-
- for (ptr = 0; ptr < st->nr_gpio; ptr++)
- device_remove_file(&spi->dev, gpio_attrs[ptr]);
-
- device_remove_file(&spi->dev, &dev_attr_status_show);
- kfree(st);
- return 0;
-}
-
-static struct spi_driver tle62x0_driver = {
- .driver = {
- .name = "tle62x0",
- .owner = THIS_MODULE,
- },
- .probe = tle62x0_probe,
- .remove = __devexit_p(tle62x0_remove),
-};
-
-static __init int tle62x0_init(void)
-{
- return spi_register_driver(&tle62x0_driver);
-}
-
-static __exit void tle62x0_exit(void)
-{
- spi_unregister_driver(&tle62x0_driver);
-}
-
-module_init(tle62x0_init);
-module_exit(tle62x0_exit);
-
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("TLE62x0 SPI driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:tle62x0");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-topcliff-pch.c b/ANDROID_3.4.5/drivers/spi/spi-topcliff-pch.c
deleted file mode 100644
index ec47d3bd..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-topcliff-pch.c
+++ /dev/null
@@ -1,1814 +0,0 @@
-/*
- * SPI bus driver for the Topcliff PCH used by Intel SoCs
- *
- * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/wait.h>
-#include <linux/spi/spi.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#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 */
-#define PCH_SPBRR 0x04 /* SPI baud rate register */
-#define PCH_SPSR 0x08 /* SPI status register */
-#define PCH_SPDWR 0x0C /* SPI write data register */
-#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
-
-#define PCH_READABLE(x) (((x) & PCH_SPSR_RFD)>>11)
-#define PCH_WRITABLE(x) (((x) & PCH_SPSR_TFD)>>6)
-
-#define PCH_RX_THOLD 7
-#define PCH_RX_THOLD_MAX 15
-
-#define PCH_TX_THOLD 2
-
-#define PCH_MAX_BAUDRATE 5000000
-#define PCH_MAX_FIFO_DEPTH 16
-
-#define STATUS_RUNNING 1
-#define STATUS_EXITING 2
-#define PCH_SLEEP_TIME 10
-
-#define SSN_LOW 0x02U
-#define SSN_HIGH 0x03U
-#define SSN_NO_CONTROL 0x00U
-#define PCH_MAX_CS 0xFF
-#define PCI_DEVICE_ID_GE_SPI 0x8816
-
-#define SPCR_SPE_BIT (1 << 0)
-#define SPCR_MSTR_BIT (1 << 1)
-#define SPCR_LSBF_BIT (1 << 4)
-#define SPCR_CPHA_BIT (1 << 5)
-#define SPCR_CPOL_BIT (1 << 6)
-#define SPCR_TFIE_BIT (1 << 8)
-#define SPCR_RFIE_BIT (1 << 9)
-#define SPCR_FIE_BIT (1 << 10)
-#define SPCR_ORIE_BIT (1 << 11)
-#define SPCR_MDFIE_BIT (1 << 12)
-#define SPCR_FICLR_BIT (1 << 24)
-#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 SPCR_RFIC_FIELD 20
-#define SPCR_TFIC_FIELD 16
-
-#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/ML7223/ML7831 by LAPIS Semiconductor */
-#define PCI_VENDOR_ID_ROHM 0x10DB
-#define PCI_DEVICE_ID_ML7213_SPI 0x802c
-#define PCI_DEVICE_ID_ML7223_SPI 0x800F
-#define PCI_DEVICE_ID_ML7831_SPI 0x8816
-
-/*
- * Set the number of SPI instance max
- * Intel EG20T PCH : 1ch
- * LAPIS Semiconductor ML7213 IOH : 2ch
- * LAPIS Semiconductor ML7223 IOH : 1ch
- * LAPIS Semiconductor ML7831 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
- * @master: Pointer to the SPI master structure
- * @work: Reference to work queue handler
- * @wk: Workqueue for carrying out execution of the
- * requests
- * @wait: Wait queue for waking up upon receiving an
- * interrupt.
- * @transfer_complete: Status of SPI Transfer
- * @bcurrent_msg_processing: Status flag for message processing
- * @lock: Lock for protecting this structure
- * @queue: SPI Message queue
- * @status: Status of the SPI driver
- * @bpw_len: Length of data to be transferred in bits per
- * word
- * @transfer_active: Flag showing active transfer
- * @tx_index: Transmit data count; for bookkeeping during
- * transfer
- * @rx_index: Receive data count; for bookkeeping during
- * transfer
- * @tx_buff: Buffer for data to be transmitted
- * @rx_index: Buffer for Received data
- * @n_curnt_chip: The chip number that this SPI driver currently
- * operates on
- * @current_chip: Reference to the current chip that this SPI
- * driver currently operates on
- * @current_msg: The current message that this SPI driver is
- * handling
- * @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;
- wait_queue_head_t wait;
- u8 transfer_complete;
- u8 bcurrent_msg_processing;
- spinlock_t lock;
- struct list_head queue;
- u8 status;
- u32 bpw_len;
- u8 transfer_active;
- u32 tx_index;
- u32 rx_index;
- u16 *pkt_tx_buff;
- u16 *pkt_rx_buff;
- u8 n_curnt_chip;
- struct spi_device *current_chip;
- 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;
- int save_total_len;
-};
-
-/**
- * struct pch_spi_board_data - Holds the SPI device specific details
- * @pdev: Pointer to the PCI device
- * @suspend_sts: Status of suspend
- * @num: The number of SPI device instance
- */
-struct pch_spi_board_data {
- struct pci_dev *pdev;
- u8 suspend_sts;
- 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 DEFINE_PCI_DEVICE_TABLE(pch_spi_pcidev_id) = {
- { 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, },
- { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_SPI), 1, },
- { }
-};
-
-/**
- * pch_spi_writereg() - Performs register writes
- * @master: Pointer to struct spi_master.
- * @idx: Register offset.
- * @val: Value to be written to register.
- */
-static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val)
-{
- struct pch_spi_data *data = spi_master_get_devdata(master);
- iowrite32(val, (data->io_remap_addr + idx));
-}
-
-/**
- * pch_spi_readreg() - Performs register reads
- * @master: Pointer to struct spi_master.
- * @idx: Register offset.
- */
-static inline u32 pch_spi_readreg(struct spi_master *master, int idx)
-{
- struct pch_spi_data *data = spi_master_get_devdata(master);
- return ioread32(data->io_remap_addr + idx);
-}
-
-static inline void pch_spi_setclr_reg(struct spi_master *master, int idx,
- u32 set, u32 clr)
-{
- u32 tmp = pch_spi_readreg(master, idx);
- tmp = (tmp & ~clr) | set;
- pch_spi_writereg(master, idx, tmp);
-}
-
-static void pch_spi_set_master_mode(struct spi_master *master)
-{
- pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0);
-}
-
-/**
- * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs
- * @master: Pointer to struct spi_master.
- */
-static void pch_spi_clear_fifo(struct spi_master *master)
-{
- pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0);
- pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT);
-}
-
-static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
- void __iomem *io_remap_addr)
-{
- u32 n_read, tx_index, rx_index, bpw_len;
- u16 *pkt_rx_buffer, *pkt_tx_buff;
- int read_cnt;
- u32 reg_spcr_val;
- void __iomem *spsr;
- void __iomem *spdrr;
- void __iomem *spdwr;
-
- spsr = io_remap_addr + PCH_SPSR;
- iowrite32(reg_spsr_val, spsr);
-
- if (data->transfer_active) {
- rx_index = data->rx_index;
- tx_index = data->tx_index;
- bpw_len = data->bpw_len;
- pkt_rx_buffer = data->pkt_rx_buff;
- pkt_tx_buff = data->pkt_tx_buff;
-
- spdrr = io_remap_addr + PCH_SPDRR;
- spdwr = io_remap_addr + PCH_SPDWR;
-
- n_read = PCH_READABLE(reg_spsr_val);
-
- for (read_cnt = 0; (read_cnt < n_read); read_cnt++) {
- pkt_rx_buffer[rx_index++] = ioread32(spdrr);
- if (tx_index < bpw_len)
- iowrite32(pkt_tx_buff[tx_index++], spdwr);
- }
-
- /* disable RFI if not needed */
- if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) {
- reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR);
- reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
-
- /* reset rx threshold */
- reg_spcr_val &= ~MASK_RFIC_SPCR_BITS;
- reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
-
- iowrite32(reg_spcr_val, (io_remap_addr + PCH_SPCR));
- }
-
- /* update counts */
- data->tx_index = tx_index;
- data->rx_index = rx_index;
-
- /* if transfer complete interrupt */
- if (reg_spsr_val & SPSR_FI_BIT) {
- if ((tx_index == bpw_len) && (rx_index == tx_index)) {
- /* 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);
- } else {
- dev_err(&data->master->dev,
- "%s : Transfer is not completed",
- __func__);
- }
- }
- }
-}
-
-/**
- * pch_spi_handler() - Interrupt handler
- * @irq: The interrupt number.
- * @dev_id: Pointer to struct pch_spi_board_data.
- */
-static irqreturn_t pch_spi_handler(int irq, void *dev_id)
-{
- u32 reg_spsr_val;
- void __iomem *spsr;
- void __iomem *io_remap_addr;
- irqreturn_t ret = IRQ_NONE;
- 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;
- }
-
- 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\n", __func__);
- if (data->current_msg->complete != 0) {
- data->transfer_complete = true;
- data->current_msg->status = -EIO;
- data->current_msg->complete(data->current_msg->context);
- data->bcurrent_msg_processing = false;
- data->current_msg = NULL;
- data->cur_trans = NULL;
- }
- }
-
- if (data->use_dma)
- return IRQ_NONE;
-
- /* 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);
- ret = IRQ_HANDLED;
- }
-
- dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n",
- __func__, ret);
-
- return ret;
-}
-
-/**
- * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR
- * @master: Pointer to struct spi_master.
- * @speed_hz: Baud rate.
- */
-static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
-{
- u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2);
-
- /* if baud rate is less than we can support limit it */
- 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_set_bits_per_word() - Sets SIZE field in SPBRR
- * @master: Pointer to struct spi_master.
- * @bits_per_word: Bits per word for SPI transfer.
- */
-static void pch_spi_set_bits_per_word(struct spi_master *master,
- u8 bits_per_word)
-{
- if (bits_per_word == 8)
- pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT);
- else
- pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0);
-}
-
-/**
- * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer
- * @spi: Pointer to struct spi_device.
- */
-static void pch_spi_setup_transfer(struct spi_device *spi)
-{
- u32 flags = 0;
-
- dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n",
- __func__, pch_spi_readreg(spi->master, PCH_SPBRR),
- spi->max_speed_hz);
- pch_spi_set_baud_rate(spi->master, spi->max_speed_hz);
-
- /* set bits per word */
- pch_spi_set_bits_per_word(spi->master, spi->bits_per_word);
-
- if (!(spi->mode & SPI_LSB_FIRST))
- flags |= SPCR_LSBF_BIT;
- if (spi->mode & SPI_CPOL)
- flags |= SPCR_CPOL_BIT;
- if (spi->mode & SPI_CPHA)
- flags |= SPCR_CPHA_BIT;
- pch_spi_setclr_reg(spi->master, PCH_SPCR, flags,
- (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT));
-
- /* Clear the FIFO by toggling FICLR to 1 and back to 0 */
- pch_spi_clear_fifo(spi->master);
-}
-
-/**
- * pch_spi_reset() - Clears SPI registers
- * @master: Pointer to struct spi_master.
- */
-static void pch_spi_reset(struct spi_master *master)
-{
- /* write 1 to reset SPI */
- pch_spi_writereg(master, PCH_SRST, 0x1);
-
- /* clear reset */
- pch_spi_writereg(master, PCH_SRST, 0x0);
-}
-
-static int pch_spi_setup(struct spi_device *pspi)
-{
- /* check bits per word */
- if (pspi->bits_per_word == 0) {
- pspi->bits_per_word = 8;
- dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
- }
-
- if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) {
- dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__);
- return -EINVAL;
- }
-
- /* Check baud rate setting */
- /* if baud rate of chip is greater than
- max we can support,return error */
- if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
- pspi->max_speed_hz = PCH_MAX_BAUDRATE;
-
- dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
- (pspi->mode) & (SPI_CPOL | SPI_CPHA));
-
- return 0;
-}
-
-static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
-{
-
- struct spi_transfer *transfer;
- struct pch_spi_data *data = spi_master_get_devdata(pspi->master);
- int retval;
- unsigned long flags;
-
- /* validate spi message and baud rate */
- if (unlikely(list_empty(&pmsg->transfers) == 1)) {
- dev_err(&pspi->dev, "%s list empty\n", __func__);
- retval = -EINVAL;
- goto err_out;
- }
-
- if (unlikely(pspi->max_speed_hz == 0)) {
- dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n",
- __func__, pspi->max_speed_hz);
- retval = -EINVAL;
- goto err_out;
- }
-
- 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_return_spinlock;
- }
-
- if (!transfer->len) {
- dev_err(&pspi->dev, "%s Transfer length invalid\n",
- __func__);
- retval = -EINVAL;
- goto err_return_spinlock;
- }
-
- dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
- " valid\n", __func__);
-
- /* if baud rate has been specified validate the same */
- if (transfer->speed_hz > PCH_MAX_BAUDRATE)
- transfer->speed_hz = PCH_MAX_BAUDRATE;
-
- /* if bits per word has been specified validate the same */
- if (transfer->bits_per_word) {
- if ((transfer->bits_per_word != 8)
- && (transfer->bits_per_word != 16)) {
- retval = -EINVAL;
- dev_err(&pspi->dev,
- "%s Invalid bits per word\n", __func__);
- goto err_return_spinlock;
- }
- }
- }
- 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_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_out;
- }
-
- /* set status of message */
- pmsg->actual_length = 0;
- 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 */
- queue_work(data->wk, &data->work);
- dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
-
- retval = 0;
-
-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,
- struct spi_device *pspi)
-{
- if (data->current_chip != NULL) {
- if (pspi->chip_select != data->n_curnt_chip) {
- dev_dbg(&pspi->dev, "%s : different slave\n", __func__);
- data->current_chip = NULL;
- }
- }
-
- data->current_chip = pspi;
-
- data->n_curnt_chip = data->current_chip->chip_select;
-
- dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__);
- pch_spi_setup_transfer(pspi);
-}
-
-static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
-{
- int size;
- u32 n_writes;
- int j;
- struct spi_message *pmsg;
- const u8 *tx_buf;
- const u16 *tx_sbuf;
-
- /* set baud rate if needed */
- if (data->cur_trans->speed_hz) {
- dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
- pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
- }
-
- /* 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__);
- pch_spi_set_bits_per_word(data->master,
- data->cur_trans->bits_per_word);
- *bpw = data->cur_trans->bits_per_word;
- } else {
- *bpw = data->current_msg->spi->bits_per_word;
- }
-
- /* reset Tx/Rx index */
- data->tx_index = 0;
- data->rx_index = 0;
-
- data->bpw_len = data->cur_trans->len / (*bpw / 8);
-
- /* find alloc size */
- size = data->cur_trans->len * sizeof(*data->pkt_tx_buff);
-
- /* allocate memory for pkt_tx_buff & pkt_rx_buffer */
- data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
- if (data->pkt_tx_buff != NULL) {
- data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
- if (!data->pkt_rx_buff)
- kfree(data->pkt_tx_buff);
- }
-
- if (!data->pkt_rx_buff) {
- /* flush queue and set status of all transfers to -ENOMEM */
- dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
- list_for_each_entry(pmsg, data->queue.next, queue) {
- pmsg->status = -ENOMEM;
-
- if (pmsg->complete != 0)
- pmsg->complete(pmsg->context);
-
- /* delete from queue */
- list_del_init(&pmsg->queue);
- }
- return;
- }
-
- /* copy Tx Data */
- if (data->cur_trans->tx_buf != NULL) {
- if (*bpw == 8) {
- tx_buf = data->cur_trans->tx_buf;
- for (j = 0; j < data->bpw_len; j++)
- data->pkt_tx_buff[j] = *tx_buf++;
- } else {
- tx_sbuf = data->cur_trans->tx_buf;
- for (j = 0; j < data->bpw_len; j++)
- data->pkt_tx_buff[j] = *tx_sbuf++;
- }
- }
-
- /* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */
- n_writes = data->bpw_len;
- if (n_writes > PCH_MAX_FIFO_DEPTH)
- n_writes = PCH_MAX_FIFO_DEPTH;
-
- dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
- "0x2 to SSNXCR\n", __func__);
- pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
-
- for (j = 0; j < n_writes; j++)
- pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]);
-
- /* update tx_index */
- data->tx_index = j;
-
- /* reset transfer complete flag */
- data->transfer_complete = false;
- data->transfer_active = true;
-}
-
-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] */
- data->current_msg->status = 0;
-
- if (data->current_msg->complete != 0) {
- dev_dbg(&data->master->dev,
- "%s:Invoking callback of SPI core\n", __func__);
- data->current_msg->complete(data->current_msg->context);
- }
-
- /* update status in global variable */
- data->bcurrent_msg_processing = false;
-
- dev_dbg(&data->master->dev,
- "%s:data->bcurrent_msg_processing = false\n", __func__);
-
- data->current_msg = NULL;
- data->cur_trans = NULL;
-
- /* check if we have items in list and not suspending
- * return 1 if list empty */
- if ((list_empty(&data->queue) == 0) &&
- (!data->board_dat->suspend_sts) &&
- (data->status != STATUS_EXITING)) {
- /* We have some more work to do (either there is more tranint
- * bpw;sfer requests in the current message or there are
- *more messages)
- */
- dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
- queue_work(data->wk, &data->work);
- } else if (data->board_dat->suspend_sts ||
- data->status == STATUS_EXITING) {
- 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;
-
- if (pmsg->complete)
- pmsg->complete(pmsg->context);
-
- /* delete from queue */
- list_del_init(&pmsg->queue);
- }
- }
-}
-
-static void pch_spi_set_ir(struct pch_spi_data *data)
-{
- /* 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 |
- 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_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. */
- dev_dbg(&data->master->dev,
- "%s:waiting for transfer to get over\n", __func__);
-
- wait_event_interruptible(data->wait, data->transfer_complete);
-
- /* clear all interrupts */
- pch_spi_writereg(data->master, PCH_SPSR,
- pch_spi_readreg(data->master, PCH_SPSR));
- /* 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)
-{
- int j;
- u8 *rx_buf;
- u16 *rx_sbuf;
-
- /* copy Rx Data */
- if (!data->cur_trans->rx_buf)
- return;
-
- if (bpw == 8) {
- rx_buf = data->cur_trans->rx_buf;
- for (j = 0; j < data->bpw_len; j++)
- *rx_buf++ = data->pkt_rx_buff[j] & 0xFF;
- } else {
- rx_sbuf = data->cur_trans->rx_buf;
- for (j = 0; j < data->bpw_len; j++)
- *rx_sbuf++ = data->pkt_rx_buff[j];
- }
-}
-
-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;
- data->cur_trans->rx_buf = rx_buf;
- } 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++;
- data->cur_trans->rx_buf = rx_sbuf;
- }
-}
-
-static int pch_spi_start_transfer(struct pch_spi_data *data)
-{
- struct pch_spi_dma_ctrl *dma;
- unsigned long flags;
- int rtn;
-
- 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__);
- rtn = wait_event_interruptible_timeout(data->wait,
- data->transfer_complete,
- msecs_to_jiffies(2 * HZ));
- if (!rtn)
- dev_err(&data->master->dev,
- "%s wait-event timeout\n", __func__);
-
- dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent,
- DMA_FROM_DEVICE);
-
- dma_sync_sg_for_cpu(&data->master->dev, dma->sg_tx_p, dma->nent,
- DMA_FROM_DEVICE);
- memset(data->dma.tx_buf_virt, 0, PAGE_SIZE);
-
- 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);
-
- /* 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);
-
- return rtn;
-}
-
-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(data->board_dat->pdev->bus->number,
- 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;
- int head;
- 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);
-
- if (data->bpw_len > PCH_BUF_SIZE) {
- data->bpw_len = PCH_BUF_SIZE;
- data->cur_trans->len -= PCH_BUF_SIZE;
- }
-
- /* 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++;
- }
- }
-
- /* Calculate Rx parameter for DMA transmitting */
- if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
- if (data->bpw_len % PCH_DMA_TRANS_SIZE) {
- num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
- rem = data->bpw_len % PCH_DMA_TRANS_SIZE;
- } else {
- num = data->bpw_len / PCH_DMA_TRANS_SIZE;
- rem = PCH_DMA_TRANS_SIZE;
- }
- size = 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_TX_THOLD << 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 == (num - 2)) {
- sg->offset = size * i;
- sg->offset = sg->offset * (*bpw / 8);
- sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem,
- sg->offset);
- sg_dma_len(sg) = rem;
- } else if (i == (num - 1)) {
- sg->offset = size * (i - 1) + rem;
- 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;
- } else {
- sg->offset = size * i;
- 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 = dmaengine_prep_slave_sg(dma->chan_rx, sg,
- num, DMA_DEV_TO_MEM,
- 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;
-
- /* Calculate Tx parameter for DMA transmitting */
- if (data->bpw_len > PCH_MAX_FIFO_DEPTH) {
- head = PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE;
- if (data->bpw_len % PCH_DMA_TRANS_SIZE > 4) {
- num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
- rem = data->bpw_len % PCH_DMA_TRANS_SIZE - head;
- } else {
- num = data->bpw_len / PCH_DMA_TRANS_SIZE;
- rem = data->bpw_len % PCH_DMA_TRANS_SIZE +
- PCH_DMA_TRANS_SIZE - head;
- }
- size = PCH_DMA_TRANS_SIZE;
- } else {
- num = 1;
- size = data->bpw_len;
- rem = data->bpw_len;
- head = 0;
- }
-
- 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), size + head,
- sg->offset);
- sg_dma_len(sg) = size + head;
- } else if (i == (num - 1)) {
- sg->offset = head + size * i;
- sg->offset = sg->offset * (*bpw / 8);
- sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem,
- sg->offset);
- sg_dma_len(sg) = rem;
- } else {
- sg->offset = head + size * i;
- 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 = dmaengine_prep_slave_sg(dma->chan_tx,
- sg, num, DMA_MEM_TO_DEV,
- 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)
-{
- struct spi_message *pmsg;
- struct pch_spi_data *data;
- int bpw;
-
- data = container_of(pwork, struct pch_spi_data, work);
- 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__);
- list_for_each_entry(pmsg, data->queue.next, queue) {
- pmsg->status = -EIO;
-
- if (pmsg->complete != 0) {
- spin_unlock(&data->lock);
- pmsg->complete(pmsg->context);
- spin_lock(&data->lock);
- }
-
- /* delete from queue */
- list_del_init(&pmsg->queue);
- }
-
- spin_unlock(&data->lock);
- return;
- }
-
- data->bcurrent_msg_processing = true;
- dev_dbg(&data->master->dev,
- "%s Set data->bcurrent_msg_processing= true\n", __func__);
-
- /* Get the message from the queue and delete it from there. */
- data->current_msg = list_entry(data->queue.next, struct spi_message,
- queue);
-
- list_del_init(&data->current_msg->queue);
-
- data->current_msg->status = 0;
-
- pch_spi_select_chip(data, data->current_msg->spi);
-
- spin_unlock(&data->lock);
-
- if (data->use_dma)
- pch_spi_request_dma(data,
- data->current_msg->spi->bits_per_word);
- pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
- do {
- int cnt;
- /* 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__);
- } 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__);
- }
- spin_unlock(&data->lock);
-
- if (!data->cur_trans->len)
- goto out;
- cnt = (data->cur_trans->len - 1) / PCH_BUF_SIZE + 1;
- data->save_total_len = data->cur_trans->len;
- if (data->use_dma) {
- int i;
- char *save_rx_buf = data->cur_trans->rx_buf;
- for (i = 0; i < cnt; i ++) {
- pch_spi_handle_dma(data, &bpw);
- if (!pch_spi_start_transfer(data)) {
- data->transfer_complete = true;
- data->current_msg->status = -EIO;
- data->current_msg->complete
- (data->current_msg->context);
- data->bcurrent_msg_processing = false;
- data->current_msg = NULL;
- data->cur_trans = NULL;
- goto out;
- }
- pch_spi_copy_rx_data_for_dma(data, bpw);
- }
- data->cur_trans->rx_buf = save_rx_buf;
- } 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->cur_trans->len = data->save_total_len;
- data->current_msg->actual_length += data->cur_trans->len;
-
- dev_dbg(&data->master->dev,
- "%s:data->current_msg->actual_length=%d\n",
- __func__, data->current_msg->actual_length);
-
- /* check for delay */
- if (data->cur_trans->delay_usecs) {
- dev_dbg(&data->master->dev, "%s:"
- "delay in usec=%d\n", __func__,
- data->cur_trans->delay_usecs);
- udelay(data->cur_trans->delay_usecs);
- }
-
- spin_lock(&data->lock);
-
- /* No more transfer in this message. */
- if ((data->cur_trans->transfer_list.next) ==
- &(data->current_msg->transfers)) {
- pch_spi_nomore_transfer(data);
- }
-
- spin_unlock(&data->lock);
-
- } while (data->cur_trans != NULL);
-
-out:
- pch_spi_writereg(data->master, PCH_SSNXCR, SSN_HIGH);
- if (data->use_dma)
- pch_spi_release_dma(data);
-}
-
-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 (data->wk != NULL) {
- destroy_workqueue(data->wk);
- data->wk = NULL;
- dev_dbg(&board_dat->pdev->dev,
- "%s destroy_workqueue invoked successfully\n",
- __func__);
- }
-}
-
-static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
- struct pch_spi_data *data)
-{
- int retval = 0;
-
- dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
-
- /* create workqueue */
- 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;
- }
-
- /* reset PCH SPI h/w */
- pch_spi_reset(data->master);
- dev_dbg(&board_dat->pdev->dev,
- "%s pch_spi_reset invoked successfully\n", __func__);
-
- 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, data);
- }
-
- dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
-
- return retval;
-}
-
-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;
-}
-
-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);
-}
-
-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;
-
- dev_dbg(&plat_dev->dev, "%s:debug\n", __func__);
-
- 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;
- }
-
- data = spi_master_get_devdata(master);
- data->master = master;
-
- platform_set_drvdata(plat_dev, data);
-
- /* 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(&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;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
-
- 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;
- }
-
- 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;
-
- pch_spi_set_master_mode(master);
-
- ret = spi_register_master(master);
- if (ret != 0) {
- dev_err(&plat_dev->dev,
- "%s spi_register_master FAILED\n", __func__);
- goto err_spi_register_master;
- }
-
- 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_register_master:
- free_irq(board_dat->pdev->irq, board_dat);
-err_request_irq:
- pch_spi_free_resources(board_dat, data);
-err_spi_get_resources:
- pci_iounmap(board_dat->pdev, data->io_remap_addr);
-err_pci_iomap:
- spi_master_put(master);
-
- return ret;
-}
-
-static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
-{
- 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(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
- __func__, plat_dev->id, board_dat->pdev->irq);
-
- 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_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_irqrestore(&data->lock, flags);
- msleep(PCH_SLEEP_TIME);
- spin_lock_irqsave(&data->lock, flags);
- }
- spin_unlock_irqrestore(&data->lock, flags);
-
- 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);
- }
-
- 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);
-
- return 0;
-}
-#ifdef CONFIG_PM
-static int pch_spi_pd_suspend(struct platform_device *pd_dev,
- pm_message_t state)
-{
- u8 count;
- 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(&pd_dev->dev, "%s ENTRY\n", __func__);
-
- if (!board_dat) {
- dev_err(&pd_dev->dev,
- "%s pci_get_drvdata returned NULL\n", __func__);
- return -EFAULT;
- }
-
- /* check if the current message is processed:
- Only after thats done the transfer will be suspended */
- count = 255;
- while ((--count) > 0) {
- if (!(data->bcurrent_msg_processing))
- break;
- msleep(PCH_SLEEP_TIME);
- }
-
- /* Free IRQ */
- if (data->irq_reg_sts) {
- /* disable all interrupts */
- pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
- pch_spi_reset(data->master);
- free_irq(board_dat->pdev->irq, data);
-
- 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) {
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
- } else {
- dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
- }
-
- return retval;
-}
-
-static int pch_spi_resume(struct pci_dev *pdev)
-{
- int retval;
- struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
- dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
-
- retval = pci_enable_device(pdev);
- if (retval < 0) {
- dev_err(&pdev->dev,
- "%s pci_enable_device failed\n", __func__);
- } else {
- pci_enable_wake(pdev, PCI_D3hot, 0);
-
- /* set suspend status to false */
- pd_dev_save->board_dat->suspend_sts = false;
- }
-
- return retval;
-}
-#else
-#define pch_spi_suspend NULL
-#define pch_spi_resume NULL
-
-#endif
-
-static struct pci_driver pch_spi_pcidev_driver = {
- .name = "pch_spi",
- .id_table = pch_spi_pcidev_id,
- .probe = pch_spi_probe,
- .remove = pch_spi_remove,
- .suspend = pch_spi_suspend,
- .resume = pch_spi_resume,
-};
-
-static int __init pch_spi_init(void)
-{
- int ret;
- ret = platform_driver_register(&pch_spi_pd_driver);
- if (ret)
- return ret;
-
- ret = pci_register_driver(&pch_spi_pcidev_driver);
- if (ret)
- return ret;
-
- return 0;
-}
-module_init(pch_spi_init);
-
-static void __exit pch_spi_exit(void)
-{
- pci_unregister_driver(&pch_spi_pcidev_driver);
- 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("Intel EG20T PCH/LAPIS Semiconductor ML7xxx IOH SPI Driver");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-txx9.c b/ANDROID_3.4.5/drivers/spi/spi-txx9.c
deleted file mode 100644
index d5a3cbb6..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-txx9.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * TXx9 SPI controller driver.
- *
- * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- *
- * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/spi/spi.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <asm/gpio.h>
-
-
-#define SPI_FIFO_SIZE 4
-#define SPI_MAX_DIVIDER 0xff /* Max. value for SPCR1.SER */
-#define SPI_MIN_DIVIDER 1 /* Min. value for SPCR1.SER */
-
-#define TXx9_SPMCR 0x00
-#define TXx9_SPCR0 0x04
-#define TXx9_SPCR1 0x08
-#define TXx9_SPFS 0x0c
-#define TXx9_SPSR 0x14
-#define TXx9_SPDR 0x18
-
-/* SPMCR : SPI Master Control */
-#define TXx9_SPMCR_OPMODE 0xc0
-#define TXx9_SPMCR_CONFIG 0x40
-#define TXx9_SPMCR_ACTIVE 0x80
-#define TXx9_SPMCR_SPSTP 0x02
-#define TXx9_SPMCR_BCLR 0x01
-
-/* SPCR0 : SPI Control 0 */
-#define TXx9_SPCR0_TXIFL_MASK 0xc000
-#define TXx9_SPCR0_RXIFL_MASK 0x3000
-#define TXx9_SPCR0_SIDIE 0x0800
-#define TXx9_SPCR0_SOEIE 0x0400
-#define TXx9_SPCR0_RBSIE 0x0200
-#define TXx9_SPCR0_TBSIE 0x0100
-#define TXx9_SPCR0_IFSPSE 0x0010
-#define TXx9_SPCR0_SBOS 0x0004
-#define TXx9_SPCR0_SPHA 0x0002
-#define TXx9_SPCR0_SPOL 0x0001
-
-/* SPSR : SPI Status */
-#define TXx9_SPSR_TBSI 0x8000
-#define TXx9_SPSR_RBSI 0x4000
-#define TXx9_SPSR_TBS_MASK 0x3800
-#define TXx9_SPSR_RBS_MASK 0x0700
-#define TXx9_SPSR_SPOE 0x0080
-#define TXx9_SPSR_IFSD 0x0008
-#define TXx9_SPSR_SIDLE 0x0004
-#define TXx9_SPSR_STRDY 0x0002
-#define TXx9_SPSR_SRRDY 0x0001
-
-
-struct txx9spi {
- struct workqueue_struct *workqueue;
- struct work_struct work;
- spinlock_t lock; /* protect 'queue' */
- struct list_head queue;
- wait_queue_head_t waitq;
- void __iomem *membase;
- int baseclk;
- struct clk *clk;
- u32 max_speed_hz, min_speed_hz;
- int last_chipselect;
- int last_chipselect_val;
-};
-
-static u32 txx9spi_rd(struct txx9spi *c, int reg)
-{
- return __raw_readl(c->membase + reg);
-}
-static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
-{
- __raw_writel(val, c->membase + reg);
-}
-
-static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
- int on, unsigned int cs_delay)
-{
- int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
- if (on) {
- /* deselect the chip with cs_change hint in last transfer */
- if (c->last_chipselect >= 0)
- gpio_set_value(c->last_chipselect,
- !c->last_chipselect_val);
- c->last_chipselect = spi->chip_select;
- c->last_chipselect_val = val;
- } else {
- c->last_chipselect = -1;
- ndelay(cs_delay); /* CS Hold Time */
- }
- gpio_set_value(spi->chip_select, val);
- ndelay(cs_delay); /* CS Setup Time / CS Recovery Time */
-}
-
-static int txx9spi_setup(struct spi_device *spi)
-{
- struct txx9spi *c = spi_master_get_devdata(spi->master);
- u8 bits_per_word;
-
- if (!spi->max_speed_hz
- || spi->max_speed_hz > c->max_speed_hz
- || spi->max_speed_hz < c->min_speed_hz)
- return -EINVAL;
-
- bits_per_word = spi->bits_per_word;
- if (bits_per_word != 8 && bits_per_word != 16)
- return -EINVAL;
-
- if (gpio_direction_output(spi->chip_select,
- !(spi->mode & SPI_CS_HIGH))) {
- dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
- return -EINVAL;
- }
-
- /* deselect chip */
- spin_lock(&c->lock);
- txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
- spin_unlock(&c->lock);
-
- return 0;
-}
-
-static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
-{
- struct txx9spi *c = dev_id;
-
- /* disable rx intr */
- txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
- TXx9_SPCR0);
- wake_up(&c->waitq);
- return IRQ_HANDLED;
-}
-
-static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
-{
- struct spi_device *spi = m->spi;
- struct spi_transfer *t;
- unsigned int cs_delay;
- unsigned int cs_change = 1;
- int status = 0;
- u32 mcr;
- u32 prev_speed_hz = 0;
- u8 prev_bits_per_word = 0;
-
- /* CS setup/hold/recovery time in nsec */
- cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
-
- mcr = txx9spi_rd(c, TXx9_SPMCR);
- if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
- dev_err(&spi->dev, "Bad mode.\n");
- status = -EIO;
- goto exit;
- }
- mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
-
- /* enter config mode */
- txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
- txx9spi_wr(c, TXx9_SPCR0_SBOS
- | ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
- | ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
- | 0x08,
- TXx9_SPCR0);
-
- list_for_each_entry (t, &m->transfers, transfer_list) {
- const void *txbuf = t->tx_buf;
- void *rxbuf = t->rx_buf;
- u32 data;
- unsigned int len = t->len;
- unsigned int wsize;
- u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
- u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
-
- bits_per_word = bits_per_word ? : 8;
- wsize = bits_per_word >> 3; /* in bytes */
-
- if (prev_speed_hz != speed_hz
- || prev_bits_per_word != bits_per_word) {
- int n = DIV_ROUND_UP(c->baseclk, speed_hz) - 1;
- n = clamp(n, SPI_MIN_DIVIDER, SPI_MAX_DIVIDER);
- /* enter config mode */
- txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
- TXx9_SPMCR);
- txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
- /* enter active mode */
- txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
-
- prev_speed_hz = speed_hz;
- prev_bits_per_word = bits_per_word;
- }
-
- if (cs_change)
- txx9spi_cs_func(spi, c, 1, cs_delay);
- cs_change = t->cs_change;
- while (len) {
- unsigned int count = SPI_FIFO_SIZE;
- int i;
- u32 cr0;
-
- if (len < count * wsize)
- count = len / wsize;
- /* now tx must be idle... */
- while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
- cpu_relax();
- cr0 = txx9spi_rd(c, TXx9_SPCR0);
- cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
- cr0 |= (count - 1) << 12;
- /* enable rx intr */
- cr0 |= TXx9_SPCR0_RBSIE;
- txx9spi_wr(c, cr0, TXx9_SPCR0);
- /* send */
- for (i = 0; i < count; i++) {
- if (txbuf) {
- data = (wsize == 1)
- ? *(const u8 *)txbuf
- : *(const u16 *)txbuf;
- txx9spi_wr(c, data, TXx9_SPDR);
- txbuf += wsize;
- } else
- txx9spi_wr(c, 0, TXx9_SPDR);
- }
- /* wait all rx data */
- wait_event(c->waitq,
- txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
- /* receive */
- for (i = 0; i < count; i++) {
- data = txx9spi_rd(c, TXx9_SPDR);
- if (rxbuf) {
- if (wsize == 1)
- *(u8 *)rxbuf = data;
- else
- *(u16 *)rxbuf = data;
- rxbuf += wsize;
- }
- }
- len -= count * wsize;
- }
- m->actual_length += t->len;
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (!cs_change)
- continue;
- if (t->transfer_list.next == &m->transfers)
- break;
- /* sometimes a short mid-message deselect of the chip
- * may be needed to terminate a mode or command
- */
- txx9spi_cs_func(spi, c, 0, cs_delay);
- }
-
-exit:
- m->status = status;
- m->complete(m->context);
-
- /* normally deactivate chipselect ... unless no error and
- * cs_change has hinted that the next message will probably
- * be for this chip too.
- */
- if (!(status == 0 && cs_change))
- txx9spi_cs_func(spi, c, 0, cs_delay);
-
- /* enter config mode */
- txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
-}
-
-static void txx9spi_work(struct work_struct *work)
-{
- struct txx9spi *c = container_of(work, struct txx9spi, work);
- unsigned long flags;
-
- spin_lock_irqsave(&c->lock, flags);
- while (!list_empty(&c->queue)) {
- struct spi_message *m;
-
- m = container_of(c->queue.next, struct spi_message, queue);
- list_del_init(&m->queue);
- spin_unlock_irqrestore(&c->lock, flags);
-
- txx9spi_work_one(c, m);
-
- spin_lock_irqsave(&c->lock, flags);
- }
- spin_unlock_irqrestore(&c->lock, flags);
-}
-
-static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
- struct spi_master *master = spi->master;
- struct txx9spi *c = spi_master_get_devdata(master);
- struct spi_transfer *t;
- unsigned long flags;
-
- m->actual_length = 0;
-
- /* check each transfer's parameters */
- list_for_each_entry (t, &m->transfers, transfer_list) {
- u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
- u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
-
- bits_per_word = bits_per_word ? : 8;
- if (!t->tx_buf && !t->rx_buf && t->len)
- return -EINVAL;
- if (bits_per_word != 8 && bits_per_word != 16)
- return -EINVAL;
- if (t->len & ((bits_per_word >> 3) - 1))
- return -EINVAL;
- if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
- return -EINVAL;
- }
-
- spin_lock_irqsave(&c->lock, flags);
- list_add_tail(&m->queue, &c->queue);
- queue_work(c->workqueue, &c->work);
- spin_unlock_irqrestore(&c->lock, flags);
-
- return 0;
-}
-
-static int __init txx9spi_probe(struct platform_device *dev)
-{
- struct spi_master *master;
- struct txx9spi *c;
- struct resource *res;
- int ret = -ENODEV;
- u32 mcr;
- int irq;
-
- master = spi_alloc_master(&dev->dev, sizeof(*c));
- if (!master)
- return ret;
- c = spi_master_get_devdata(master);
- platform_set_drvdata(dev, master);
-
- INIT_WORK(&c->work, txx9spi_work);
- spin_lock_init(&c->lock);
- INIT_LIST_HEAD(&c->queue);
- init_waitqueue_head(&c->waitq);
-
- c->clk = clk_get(&dev->dev, "spi-baseclk");
- if (IS_ERR(c->clk)) {
- ret = PTR_ERR(c->clk);
- c->clk = NULL;
- goto exit;
- }
- ret = clk_enable(c->clk);
- if (ret) {
- clk_put(c->clk);
- c->clk = NULL;
- goto exit;
- }
- c->baseclk = clk_get_rate(c->clk);
- c->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
- c->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
-
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!res)
- goto exit_busy;
- if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
- "spi_txx9"))
- goto exit_busy;
- c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
- if (!c->membase)
- goto exit_busy;
-
- /* enter config mode */
- mcr = txx9spi_rd(c, TXx9_SPMCR);
- mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
- txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
-
- irq = platform_get_irq(dev, 0);
- if (irq < 0)
- goto exit_busy;
- ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0,
- "spi_txx9", c);
- if (ret)
- goto exit;
-
- c->workqueue = create_singlethread_workqueue(
- dev_name(master->dev.parent));
- if (!c->workqueue)
- goto exit_busy;
- c->last_chipselect = -1;
-
- dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
- (unsigned long long)res->start, irq,
- (c->baseclk + 500000) / 1000000);
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
-
- master->bus_num = dev->id;
- master->setup = txx9spi_setup;
- master->transfer = txx9spi_transfer;
- master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
-
- ret = spi_register_master(master);
- if (ret)
- goto exit;
- return 0;
-exit_busy:
- ret = -EBUSY;
-exit:
- if (c->workqueue)
- destroy_workqueue(c->workqueue);
- if (c->clk) {
- clk_disable(c->clk);
- clk_put(c->clk);
- }
- platform_set_drvdata(dev, NULL);
- spi_master_put(master);
- return ret;
-}
-
-static int __exit txx9spi_remove(struct platform_device *dev)
-{
- struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
- struct txx9spi *c = spi_master_get_devdata(master);
-
- spi_unregister_master(master);
- platform_set_drvdata(dev, NULL);
- destroy_workqueue(c->workqueue);
- clk_disable(c->clk);
- clk_put(c->clk);
- spi_master_put(master);
- return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:spi_txx9");
-
-static struct platform_driver txx9spi_driver = {
- .remove = __exit_p(txx9spi_remove),
- .driver = {
- .name = "spi_txx9",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init txx9spi_init(void)
-{
- return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
-}
-subsys_initcall(txx9spi_init);
-
-static void __exit txx9spi_exit(void)
-{
- platform_driver_unregister(&txx9spi_driver);
-}
-module_exit(txx9spi_exit);
-
-MODULE_DESCRIPTION("TXx9 SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi-xilinx.c b/ANDROID_3.4.5/drivers/spi/spi-xilinx.c
deleted file mode 100644
index 4c5a663b..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi-xilinx.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Xilinx SPI controller driver (master mode only)
- *
- * Author: MontaVista Software, Inc.
- * source@mvista.com
- *
- * Copyright (c) 2010 Secret Lab Technologies, Ltd.
- * Copyright (c) 2009 Intel Corporation
- * 2002-2007 (c) MontaVista Software, Inc.
-
- * 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/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/xilinx_spi.h>
-#include <linux/io.h>
-
-#define XILINX_SPI_NAME "xilinx_spi"
-
-/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
- * Product Specification", DS464
- */
-#define XSPI_CR_OFFSET 0x60 /* Control Register */
-
-#define XSPI_CR_ENABLE 0x02
-#define XSPI_CR_MASTER_MODE 0x04
-#define XSPI_CR_CPOL 0x08
-#define XSPI_CR_CPHA 0x10
-#define XSPI_CR_MODE_MASK (XSPI_CR_CPHA | XSPI_CR_CPOL)
-#define XSPI_CR_TXFIFO_RESET 0x20
-#define XSPI_CR_RXFIFO_RESET 0x40
-#define XSPI_CR_MANUAL_SSELECT 0x80
-#define XSPI_CR_TRANS_INHIBIT 0x100
-#define XSPI_CR_LSB_FIRST 0x200
-
-#define XSPI_SR_OFFSET 0x64 /* Status Register */
-
-#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
-#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
-#define XSPI_SR_TX_EMPTY_MASK 0x04 /* Transmit FIFO is empty */
-#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
-#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
-
-#define XSPI_TXD_OFFSET 0x68 /* Data Transmit Register */
-#define XSPI_RXD_OFFSET 0x6c /* Data Receive Register */
-
-#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
-
-/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
- * IPIF registers are 32 bit
- */
-#define XIPIF_V123B_DGIER_OFFSET 0x1c /* IPIF global int enable reg */
-#define XIPIF_V123B_GINTR_ENABLE 0x80000000
-
-#define XIPIF_V123B_IISR_OFFSET 0x20 /* IPIF interrupt status reg */
-#define XIPIF_V123B_IIER_OFFSET 0x28 /* IPIF interrupt enable reg */
-
-#define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */
-#define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while
- * disabled */
-#define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */
-#define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */
-#define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */
-#define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */
-#define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */
-
-#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */
-#define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
-
-struct xilinx_spi {
- /* bitbang has to be first */
- struct spi_bitbang bitbang;
- struct completion done;
- struct resource mem; /* phys mem */
- void __iomem *regs; /* virt. address of the control registers */
-
- u32 irq;
-
- u8 *rx_ptr; /* pointer in the Tx buffer */
- const u8 *tx_ptr; /* pointer in the Rx buffer */
- int remaining_bytes; /* the number of bytes left to transfer */
- u8 bits_per_word;
- unsigned int (*read_fn) (void __iomem *);
- void (*write_fn) (u32, void __iomem *);
- void (*tx_fn) (struct xilinx_spi *);
- void (*rx_fn) (struct xilinx_spi *);
-};
-
-static void xspi_write32(u32 val, void __iomem *addr)
-{
- iowrite32(val, addr);
-}
-
-static unsigned int xspi_read32(void __iomem *addr)
-{
- return ioread32(addr);
-}
-
-static void xspi_write32_be(u32 val, void __iomem *addr)
-{
- iowrite32be(val, addr);
-}
-
-static unsigned int xspi_read32_be(void __iomem *addr)
-{
- return ioread32be(addr);
-}
-
-static void xspi_tx8(struct xilinx_spi *xspi)
-{
- xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr++;
-}
-
-static void xspi_tx16(struct xilinx_spi *xspi)
-{
- xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr += 2;
-}
-
-static void xspi_tx32(struct xilinx_spi *xspi)
-{
- xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr += 4;
-}
-
-static void xspi_rx8(struct xilinx_spi *xspi)
-{
- u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
- *xspi->rx_ptr = data & 0xff;
- xspi->rx_ptr++;
- }
-}
-
-static void xspi_rx16(struct xilinx_spi *xspi)
-{
- u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
- *(u16 *)(xspi->rx_ptr) = data & 0xffff;
- xspi->rx_ptr += 2;
- }
-}
-
-static void xspi_rx32(struct xilinx_spi *xspi)
-{
- u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
- *(u32 *)(xspi->rx_ptr) = data;
- xspi->rx_ptr += 4;
- }
-}
-
-static void xspi_init_hw(struct xilinx_spi *xspi)
-{
- void __iomem *regs_base = xspi->regs;
-
- /* Reset the SPI device */
- xspi->write_fn(XIPIF_V123B_RESET_MASK,
- regs_base + XIPIF_V123B_RESETR_OFFSET);
- /* Disable all the interrupts just in case */
- xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
- /* Enable the global IPIF interrupt */
- xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
- regs_base + XIPIF_V123B_DGIER_OFFSET);
- /* Deselect the slave on the SPI bus */
- xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
- /* Disable the transmitter, enable Manual Slave Select Assertion,
- * put SPI controller into master mode, and enable it */
- xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
- XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
- XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
-}
-
-static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
-{
- struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-
- if (is_on == BITBANG_CS_INACTIVE) {
- /* Deselect the slave on the SPI bus */
- xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET);
- } else if (is_on == BITBANG_CS_ACTIVE) {
- /* Set the SPI clock phase and polarity */
- u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)
- & ~XSPI_CR_MODE_MASK;
- if (spi->mode & SPI_CPHA)
- cr |= XSPI_CR_CPHA;
- if (spi->mode & SPI_CPOL)
- cr |= XSPI_CR_CPOL;
- xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
- /* We do not check spi->max_speed_hz here as the SPI clock
- * frequency is not software programmable (the IP block design
- * parameter)
- */
-
- /* Activate the chip select */
- xspi->write_fn(~(0x0001 << spi->chip_select),
- xspi->regs + XSPI_SSR_OFFSET);
- }
-}
-
-/* spi_bitbang requires custom setup_transfer() to be defined if there is a
- * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
- * supports 8 or 16 bits per word which cannot be changed in software.
- * SPI clock can't be changed in software either.
- * Check for correct bits per word. Chip select delay calculations could be
- * added here as soon as bitbang_work() can be made aware of the delay value.
- */
-static int xilinx_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
-{
- struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
- u8 bits_per_word;
-
- bits_per_word = (t && t->bits_per_word)
- ? t->bits_per_word : spi->bits_per_word;
- if (bits_per_word != xspi->bits_per_word) {
- dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
- __func__, bits_per_word);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int xilinx_spi_setup(struct spi_device *spi)
-{
- /* always return 0, we can not check the number of bits.
- * There are cases when SPI setup is called before any driver is
- * there, in that case the SPI core defaults to 8 bits, which we
- * do not support in some cases. But if we return an error, the
- * SPI device would not be registered and no driver can get hold of it
- * When the driver is there, it will call SPI setup again with the
- * correct number of bits per transfer.
- * If a driver setups with the wrong bit number, it will fail when
- * it tries to do a transfer
- */
- return 0;
-}
-
-static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
-{
- u8 sr;
-
- /* Fill the Tx FIFO with as many bytes as possible */
- sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
- while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
- if (xspi->tx_ptr)
- xspi->tx_fn(xspi);
- else
- xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
- xspi->remaining_bytes -= xspi->bits_per_word / 8;
- sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
- }
-}
-
-static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
- struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
- u32 ipif_ier;
- u16 cr;
-
- /* We get here with transmitter inhibited */
-
- xspi->tx_ptr = t->tx_buf;
- xspi->rx_ptr = t->rx_buf;
- xspi->remaining_bytes = t->len;
- INIT_COMPLETION(xspi->done);
-
- xilinx_spi_fill_tx_fifo(xspi);
-
- /* Enable the transmit empty interrupt, which we use to determine
- * progress on the transmission.
- */
- ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
- xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
- xspi->regs + XIPIF_V123B_IIER_OFFSET);
-
- /* Start the transfer by not inhibiting the transmitter any longer */
- cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
- ~XSPI_CR_TRANS_INHIBIT;
- xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
- wait_for_completion(&xspi->done);
-
- /* Disable the transmit empty interrupt */
- xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
-
- return t->len - xspi->remaining_bytes;
-}
-
-
-/* This driver supports single master mode only. Hence Tx FIFO Empty
- * is the only interrupt we care about.
- * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
- * Fault are not to happen.
- */
-static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
-{
- struct xilinx_spi *xspi = dev_id;
- u32 ipif_isr;
-
- /* Get the IPIF interrupts, and clear them immediately */
- ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
- xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
-
- if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */
- u16 cr;
- u8 sr;
-
- /* A transmit has just completed. Process received data and
- * check for more data to transmit. Always inhibit the
- * transmitter while the Isr refills the transmit register/FIFO,
- * or make sure it is stopped if we're done.
- */
- cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
- xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
- xspi->regs + XSPI_CR_OFFSET);
-
- /* Read out all the data from the Rx FIFO */
- sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
- while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
- xspi->rx_fn(xspi);
- sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
- }
-
- /* See if there is more data to send */
- if (xspi->remaining_bytes > 0) {
- xilinx_spi_fill_tx_fifo(xspi);
- /* Start the transfer by not inhibiting the
- * transmitter any longer
- */
- xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
- } else {
- /* No more data to send.
- * Indicate the transfer is completed.
- */
- complete(&xspi->done);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static const struct of_device_id xilinx_spi_of_match[] = {
- { .compatible = "xlnx,xps-spi-2.00.a", },
- { .compatible = "xlnx,xps-spi-2.00.b", },
- {}
-};
-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
- u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
-{
- struct spi_master *master;
- struct xilinx_spi *xspi;
- int ret;
-
- master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
- if (!master)
- return NULL;
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA;
-
- xspi = spi_master_get_devdata(master);
- xspi->bitbang.master = spi_master_get(master);
- xspi->bitbang.chipselect = xilinx_spi_chipselect;
- xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
- xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
- xspi->bitbang.master->setup = xilinx_spi_setup;
- init_completion(&xspi->done);
-
- if (!request_mem_region(mem->start, resource_size(mem),
- XILINX_SPI_NAME))
- goto put_master;
-
- xspi->regs = ioremap(mem->start, resource_size(mem));
- if (xspi->regs == NULL) {
- dev_warn(dev, "ioremap failure\n");
- goto map_failed;
- }
-
- master->bus_num = bus_num;
- master->num_chipselect = num_cs;
- master->dev.of_node = dev->of_node;
-
- xspi->mem = *mem;
- xspi->irq = irq;
- if (little_endian) {
- xspi->read_fn = xspi_read32;
- xspi->write_fn = xspi_write32;
- } else {
- xspi->read_fn = xspi_read32_be;
- xspi->write_fn = xspi_write32_be;
- }
- xspi->bits_per_word = bits_per_word;
- if (xspi->bits_per_word == 8) {
- xspi->tx_fn = xspi_tx8;
- xspi->rx_fn = xspi_rx8;
- } else if (xspi->bits_per_word == 16) {
- xspi->tx_fn = xspi_tx16;
- xspi->rx_fn = xspi_rx16;
- } else if (xspi->bits_per_word == 32) {
- xspi->tx_fn = xspi_tx32;
- xspi->rx_fn = xspi_rx32;
- } else
- goto unmap_io;
-
-
- /* SPI controller initializations */
- xspi_init_hw(xspi);
-
- /* Register for SPI Interrupt */
- ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
- if (ret)
- goto unmap_io;
-
- ret = spi_bitbang_start(&xspi->bitbang);
- if (ret) {
- dev_err(dev, "spi_bitbang_start FAILED\n");
- goto free_irq;
- }
-
- dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
- (unsigned long long)mem->start, xspi->regs, xspi->irq);
- return master;
-
-free_irq:
- free_irq(xspi->irq, xspi);
-unmap_io:
- iounmap(xspi->regs);
-map_failed:
- release_mem_region(mem->start, resource_size(mem));
-put_master:
- spi_master_put(master);
- return NULL;
-}
-EXPORT_SYMBOL(xilinx_spi_init);
-
-void xilinx_spi_deinit(struct spi_master *master)
-{
- struct xilinx_spi *xspi;
-
- xspi = spi_master_get_devdata(master);
-
- spi_bitbang_stop(&xspi->bitbang);
- free_irq(xspi->irq, xspi);
- iounmap(xspi->regs);
-
- release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
- spi_master_put(xspi->bitbang.master);
-}
-EXPORT_SYMBOL(xilinx_spi_deinit);
-
-static int __devinit xilinx_spi_probe(struct platform_device *dev)
-{
- struct xspi_platform_data *pdata;
- struct resource *r;
- int irq, num_cs = 0, little_endian = 0, bits_per_word = 8;
- struct spi_master *master;
- u8 i;
-
- pdata = dev->dev.platform_data;
- if (pdata) {
- num_cs = pdata->num_chipselect;
- little_endian = pdata->little_endian;
- bits_per_word = pdata->bits_per_word;
- }
-
-#ifdef CONFIG_OF
- if (dev->dev.of_node) {
- const __be32 *prop;
- int len;
-
- /* number of slave select bits is required */
- prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
- &len);
- if (prop && len >= sizeof(*prop))
- num_cs = __be32_to_cpup(prop);
- }
-#endif
-
- if (!num_cs) {
- dev_err(&dev->dev, "Missing slave select configuration data\n");
- return -EINVAL;
- }
-
-
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!r)
- return -ENODEV;
-
- irq = platform_get_irq(dev, 0);
- if (irq < 0)
- return -ENXIO;
-
- master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
- little_endian, bits_per_word);
- if (!master)
- return -ENODEV;
-
- if (pdata) {
- for (i = 0; i < pdata->num_devices; i++)
- spi_new_device(master, pdata->devices + i);
- }
-
- platform_set_drvdata(dev, master);
- return 0;
-}
-
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
-{
- xilinx_spi_deinit(platform_get_drvdata(dev));
- platform_set_drvdata(dev, 0);
-
- return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:" XILINX_SPI_NAME);
-
-static struct platform_driver xilinx_spi_driver = {
- .probe = xilinx_spi_probe,
- .remove = __devexit_p(xilinx_spi_remove),
- .driver = {
- .name = XILINX_SPI_NAME,
- .owner = THIS_MODULE,
- .of_match_table = xilinx_spi_of_match,
- },
-};
-module_platform_driver(xilinx_spi_driver);
-
-MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_DESCRIPTION("Xilinx SPI driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/spi.c b/ANDROID_3.4.5/drivers/spi/spi.c
deleted file mode 100644
index 3d8f662e..00000000
--- a/ANDROID_3.4.5/drivers/spi/spi.c
+++ /dev/null
@@ -1,1480 +0,0 @@
-/*
- * SPI init/core code
- *
- * Copyright (C) 2005 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/cache.h>
-#include <linux/mutex.h>
-#include <linux/of_device.h>
-#include <linux/slab.h>
-#include <linux/mod_devicetable.h>
-#include <linux/spi/spi.h>
-#include <linux/of_spi.h>
-#include <linux/pm_runtime.h>
-#include <linux/export.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-
-static void spidev_release(struct device *dev)
-{
- struct spi_device *spi = to_spi_device(dev);
-
- /* spi masters may cleanup for released devices */
- if (spi->master->cleanup)
- spi->master->cleanup(spi);
-
- spi_master_put(spi->master);
- kfree(spi);
-}
-
-static ssize_t
-modalias_show(struct device *dev, struct device_attribute *a, char *buf)
-{
- const struct spi_device *spi = to_spi_device(dev);
-
- return sprintf(buf, "%s\n", spi->modalias);
-}
-
-static struct device_attribute spi_dev_attrs[] = {
- __ATTR_RO(modalias),
- __ATTR_NULL,
-};
-
-/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
- * and the sysfs version makes coldplug work too.
- */
-
-static const struct spi_device_id *spi_match_id(const struct spi_device_id *id,
- const struct spi_device *sdev)
-{
- while (id->name[0]) {
- if (!strcmp(sdev->modalias, id->name))
- return id;
- id++;
- }
- return NULL;
-}
-
-const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev)
-{
- const struct spi_driver *sdrv = to_spi_driver(sdev->dev.driver);
-
- return spi_match_id(sdrv->id_table, sdev);
-}
-EXPORT_SYMBOL_GPL(spi_get_device_id);
-
-static int spi_match_device(struct device *dev, struct device_driver *drv)
-{
- const struct spi_device *spi = to_spi_device(dev);
- const struct spi_driver *sdrv = to_spi_driver(drv);
-
- /* Attempt an OF style match */
- if (of_driver_match_device(dev, drv))
- return 1;
-
- if (sdrv->id_table)
- return !!spi_match_id(sdrv->id_table, spi);
-
- return strcmp(spi->modalias, drv->name) == 0;
-}
-
-static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- const struct spi_device *spi = to_spi_device(dev);
-
- add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int spi_legacy_suspend(struct device *dev, pm_message_t message)
-{
- int value = 0;
- struct spi_driver *drv = to_spi_driver(dev->driver);
-
- /* suspend will stop irqs and dma; no more i/o */
- if (drv) {
- if (drv->suspend)
- value = drv->suspend(to_spi_device(dev), message);
- else
- dev_dbg(dev, "... can't suspend\n");
- }
- return value;
-}
-
-static int spi_legacy_resume(struct device *dev)
-{
- int value = 0;
- struct spi_driver *drv = to_spi_driver(dev->driver);
-
- /* resume may restart the i/o queue */
- if (drv) {
- if (drv->resume)
- value = drv->resume(to_spi_device(dev));
- else
- dev_dbg(dev, "... can't resume\n");
- }
- return value;
-}
-
-static int spi_pm_suspend(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm)
- return pm_generic_suspend(dev);
- else
- return spi_legacy_suspend(dev, PMSG_SUSPEND);
-}
-
-static int spi_pm_resume(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm)
- return pm_generic_resume(dev);
- else
- return spi_legacy_resume(dev);
-}
-
-static int spi_pm_freeze(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm)
- return pm_generic_freeze(dev);
- else
- return spi_legacy_suspend(dev, PMSG_FREEZE);
-}
-
-static int spi_pm_thaw(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm)
- return pm_generic_thaw(dev);
- else
- return spi_legacy_resume(dev);
-}
-
-static int spi_pm_poweroff(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm)
- return pm_generic_poweroff(dev);
- else
- return spi_legacy_suspend(dev, PMSG_HIBERNATE);
-}
-
-static int spi_pm_restore(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm)
- return pm_generic_restore(dev);
- else
- return spi_legacy_resume(dev);
-}
-#else
-#define spi_pm_suspend NULL
-#define spi_pm_resume NULL
-#define spi_pm_freeze NULL
-#define spi_pm_thaw NULL
-#define spi_pm_poweroff NULL
-#define spi_pm_restore NULL
-#endif
-
-static const struct dev_pm_ops spi_pm = {
- .suspend = spi_pm_suspend,
- .resume = spi_pm_resume,
- .freeze = spi_pm_freeze,
- .thaw = spi_pm_thaw,
- .poweroff = spi_pm_poweroff,
- .restore = spi_pm_restore,
- SET_RUNTIME_PM_OPS(
- pm_generic_runtime_suspend,
- pm_generic_runtime_resume,
- pm_generic_runtime_idle
- )
-};
-
-struct bus_type spi_bus_type = {
- .name = "spi",
- .dev_attrs = spi_dev_attrs,
- .match = spi_match_device,
- .uevent = spi_uevent,
- .pm = &spi_pm,
-};
-EXPORT_SYMBOL_GPL(spi_bus_type);
-
-
-static int spi_drv_probe(struct device *dev)
-{
- const struct spi_driver *sdrv = to_spi_driver(dev->driver);
-
- return sdrv->probe(to_spi_device(dev));
-}
-
-static int spi_drv_remove(struct device *dev)
-{
- const struct spi_driver *sdrv = to_spi_driver(dev->driver);
-
- return sdrv->remove(to_spi_device(dev));
-}
-
-static void spi_drv_shutdown(struct device *dev)
-{
- const struct spi_driver *sdrv = to_spi_driver(dev->driver);
-
- sdrv->shutdown(to_spi_device(dev));
-}
-
-/**
- * spi_register_driver - register a SPI driver
- * @sdrv: the driver to register
- * Context: can sleep
- */
-int spi_register_driver(struct spi_driver *sdrv)
-{
- sdrv->driver.bus = &spi_bus_type;
- if (sdrv->probe)
- sdrv->driver.probe = spi_drv_probe;
- if (sdrv->remove)
- sdrv->driver.remove = spi_drv_remove;
- if (sdrv->shutdown)
- sdrv->driver.shutdown = spi_drv_shutdown;
- return driver_register(&sdrv->driver);
-}
-EXPORT_SYMBOL_GPL(spi_register_driver);
-
-/*-------------------------------------------------------------------------*/
-
-/* SPI devices should normally not be created by SPI device drivers; that
- * would make them board-specific. Similarly with SPI master drivers.
- * Device registration normally goes into like arch/.../mach.../board-YYY.c
- * with other readonly (flashable) information about mainboard devices.
- */
-
-struct boardinfo {
- struct list_head list;
- struct spi_board_info board_info;
-};
-
-static LIST_HEAD(board_list);
-static LIST_HEAD(spi_master_list);
-
-/*
- * Used to protect add/del opertion for board_info list and
- * spi_master list, and their matching process
- */
-static DEFINE_MUTEX(board_lock);
-
-/**
- * spi_alloc_device - Allocate a new SPI device
- * @master: Controller to which device is connected
- * Context: can sleep
- *
- * Allows a driver to allocate and initialize a spi_device without
- * registering it immediately. This allows a driver to directly
- * fill the spi_device with device parameters before calling
- * spi_add_device() on it.
- *
- * Caller is responsible to call spi_add_device() on the returned
- * spi_device structure to add it to the SPI master. If the caller
- * needs to discard the spi_device without adding it, then it should
- * call spi_dev_put() on it.
- *
- * Returns a pointer to the new device, or NULL.
- */
-struct spi_device *spi_alloc_device(struct spi_master *master)
-{
- struct spi_device *spi;
- struct device *dev = master->dev.parent;
-
- if (!spi_master_get(master))
- return NULL;
-
- spi = kzalloc(sizeof *spi, GFP_KERNEL);
- if (!spi) {
- dev_err(dev, "cannot alloc spi_device\n");
- spi_master_put(master);
- return NULL;
- }
-
- spi->master = master;
- spi->dev.parent = &master->dev;
- spi->dev.bus = &spi_bus_type;
- spi->dev.release = spidev_release;
- device_initialize(&spi->dev);
- return spi;
-}
-EXPORT_SYMBOL_GPL(spi_alloc_device);
-
-/**
- * spi_add_device - Add spi_device allocated with spi_alloc_device
- * @spi: spi_device to register
- *
- * Companion function to spi_alloc_device. Devices allocated with
- * spi_alloc_device can be added onto the spi bus with this function.
- *
- * Returns 0 on success; negative errno on failure
- */
-int spi_add_device(struct spi_device *spi)
-{
- static DEFINE_MUTEX(spi_add_lock);
- struct device *dev = spi->master->dev.parent;
- struct device *d;
- int status;
-
- /* Chipselects are numbered 0..max; validate. */
- if (spi->chip_select >= spi->master->num_chipselect) {
- dev_err(dev, "cs%d >= max %d\n",
- spi->chip_select,
- spi->master->num_chipselect);
- return -EINVAL;
- }
-
- /* Set the bus ID string */
- dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
- spi->chip_select);
-
-
- /* We need to make sure there's no other device with this
- * chipselect **BEFORE** we call setup(), else we'll trash
- * its configuration. Lock against concurrent add() calls.
- */
- mutex_lock(&spi_add_lock);
-
- d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
- if (d != NULL) {
- dev_err(dev, "chipselect %d already in use\n",
- spi->chip_select);
- put_device(d);
- status = -EBUSY;
- goto done;
- }
-
- /* Drivers may modify this initial i/o setup, but will
- * normally rely on the device being setup. Devices
- * using SPI_CS_HIGH can't coexist well otherwise...
- */
- status = spi_setup(spi);
- if (status < 0) {
- dev_err(dev, "can't setup %s, status %d\n",
- dev_name(&spi->dev), status);
- goto done;
- }
-
- /* Device may be bound to an active driver when this returns */
- status = device_add(&spi->dev);
- if (status < 0)
- dev_err(dev, "can't add %s, status %d\n",
- dev_name(&spi->dev), status);
- else
- dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
-
-done:
- mutex_unlock(&spi_add_lock);
- return status;
-}
-EXPORT_SYMBOL_GPL(spi_add_device);
-
-/**
- * spi_new_device - instantiate one new SPI device
- * @master: Controller to which device is connected
- * @chip: Describes the SPI device
- * Context: can sleep
- *
- * On typical mainboards, this is purely internal; and it's not needed
- * after board init creates the hard-wired devices. Some development
- * platforms may not be able to use spi_register_board_info though, and
- * this is exported so that for example a USB or parport based adapter
- * driver could add devices (which it would learn about out-of-band).
- *
- * Returns the new device, or NULL.
- */
-struct spi_device *spi_new_device(struct spi_master *master,
- struct spi_board_info *chip)
-{
- struct spi_device *proxy;
- int status;
-
- /* NOTE: caller did any chip->bus_num checks necessary.
- *
- * Also, unless we change the return value convention to use
- * error-or-pointer (not NULL-or-pointer), troubleshootability
- * suggests syslogged diagnostics are best here (ugh).
- */
-
- proxy = spi_alloc_device(master);
- if (!proxy)
- return NULL;
-
- WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
-
- proxy->chip_select = chip->chip_select;
- proxy->max_speed_hz = chip->max_speed_hz;
- proxy->mode = chip->mode;
- proxy->irq = chip->irq;
- strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
- proxy->dev.platform_data = (void *) chip->platform_data;
- proxy->controller_data = chip->controller_data;
- proxy->controller_state = NULL;
-
- status = spi_add_device(proxy);
- if (status < 0) {
- spi_dev_put(proxy);
- return NULL;
- }
-
- return proxy;
-}
-EXPORT_SYMBOL_GPL(spi_new_device);
-
-static void spi_match_master_to_boardinfo(struct spi_master *master,
- struct spi_board_info *bi)
-{
- struct spi_device *dev;
-
- if (master->bus_num != bi->bus_num)
- return;
-
- dev = spi_new_device(master, bi);
- if (!dev)
- dev_err(master->dev.parent, "can't create new device for %s\n",
- bi->modalias);
-}
-
-/**
- * spi_register_board_info - register SPI devices for a given board
- * @info: array of chip descriptors
- * @n: how many descriptors are provided
- * Context: can sleep
- *
- * Board-specific early init code calls this (probably during arch_initcall)
- * with segments of the SPI device table. Any device nodes are created later,
- * after the relevant parent SPI controller (bus_num) is defined. We keep
- * this table of devices forever, so that reloading a controller driver will
- * not make Linux forget about these hard-wired devices.
- *
- * Other code can also call this, e.g. a particular add-on board might provide
- * SPI devices through its expansion connector, so code initializing that board
- * would naturally declare its SPI devices.
- *
- * The board info passed can safely be __initdata ... but be careful of
- * any embedded pointers (platform_data, etc), they're copied as-is.
- */
-int __devinit
-spi_register_board_info(struct spi_board_info const *info, unsigned n)
-{
- struct boardinfo *bi;
- int i;
-
- bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
- if (!bi)
- return -ENOMEM;
-
- for (i = 0; i < n; i++, bi++, info++) {
- struct spi_master *master;
-
- memcpy(&bi->board_info, info, sizeof(*info));
- mutex_lock(&board_lock);
- list_add_tail(&bi->list, &board_list);
- list_for_each_entry(master, &spi_master_list, list)
- spi_match_master_to_boardinfo(master, &bi->board_info);
- mutex_unlock(&board_lock);
- }
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * spi_pump_messages - kthread work function which processes spi message queue
- * @work: pointer to kthread work struct contained in the master struct
- *
- * This function checks if there is any spi message in the queue that
- * needs processing and if so call out to the driver to initialize hardware
- * and transfer each message.
- *
- */
-static void spi_pump_messages(struct kthread_work *work)
-{
- struct spi_master *master =
- container_of(work, struct spi_master, pump_messages);
- unsigned long flags;
- bool was_busy = false;
- int ret;
-
- /* Lock queue and check for queue work */
- spin_lock_irqsave(&master->queue_lock, flags);
- if (list_empty(&master->queue) || !master->running) {
- if (master->busy) {
- ret = master->unprepare_transfer_hardware(master);
- if (ret) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- dev_err(&master->dev,
- "failed to unprepare transfer hardware\n");
- return;
- }
- }
- master->busy = false;
- spin_unlock_irqrestore(&master->queue_lock, flags);
- return;
- }
-
- /* Make sure we are not already running a message */
- if (master->cur_msg) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- return;
- }
- /* Extract head of queue */
- master->cur_msg =
- list_entry(master->queue.next, struct spi_message, queue);
-
- list_del_init(&master->cur_msg->queue);
- if (master->busy)
- was_busy = true;
- else
- master->busy = true;
- spin_unlock_irqrestore(&master->queue_lock, flags);
-
- if (!was_busy) {
- ret = master->prepare_transfer_hardware(master);
- if (ret) {
- dev_err(&master->dev,
- "failed to prepare transfer hardware\n");
- return;
- }
- }
-
- ret = master->transfer_one_message(master, master->cur_msg);
- if (ret) {
- dev_err(&master->dev,
- "failed to transfer one message from queue\n");
- return;
- }
-}
-
-static int spi_init_queue(struct spi_master *master)
-{
- struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
-
- INIT_LIST_HEAD(&master->queue);
- spin_lock_init(&master->queue_lock);
-
- master->running = false;
- master->busy = false;
-
- init_kthread_worker(&master->kworker);
- master->kworker_task = kthread_run(kthread_worker_fn,
- &master->kworker,
- dev_name(&master->dev));
- if (IS_ERR(master->kworker_task)) {
- dev_err(&master->dev, "failed to create message pump task\n");
- return -ENOMEM;
- }
- init_kthread_work(&master->pump_messages, spi_pump_messages);
-
- /*
- * Master config will indicate if this controller should run the
- * message pump with high (realtime) priority to reduce the transfer
- * latency on the bus by minimising the delay between a transfer
- * request and the scheduling of the message pump thread. Without this
- * setting the message pump thread will remain at default priority.
- */
- if (master->rt) {
- dev_info(&master->dev,
- "will run message pump with realtime priority\n");
- sched_setscheduler(master->kworker_task, SCHED_FIFO, &param);
- }
-
- return 0;
-}
-
-/**
- * spi_get_next_queued_message() - called by driver to check for queued
- * messages
- * @master: the master to check for queued messages
- *
- * If there are more messages in the queue, the next message is returned from
- * this call.
- */
-struct spi_message *spi_get_next_queued_message(struct spi_master *master)
-{
- struct spi_message *next;
- unsigned long flags;
-
- /* get a pointer to the next message, if any */
- spin_lock_irqsave(&master->queue_lock, flags);
- if (list_empty(&master->queue))
- next = NULL;
- else
- next = list_entry(master->queue.next,
- struct spi_message, queue);
- spin_unlock_irqrestore(&master->queue_lock, flags);
-
- return next;
-}
-EXPORT_SYMBOL_GPL(spi_get_next_queued_message);
-
-/**
- * spi_finalize_current_message() - the current message is complete
- * @master: the master to return the message to
- *
- * Called by the driver to notify the core that the message in the front of the
- * queue is complete and can be removed from the queue.
- */
-void spi_finalize_current_message(struct spi_master *master)
-{
- struct spi_message *mesg;
- unsigned long flags;
-
- spin_lock_irqsave(&master->queue_lock, flags);
- mesg = master->cur_msg;
- master->cur_msg = NULL;
-
- queue_kthread_work(&master->kworker, &master->pump_messages);
- spin_unlock_irqrestore(&master->queue_lock, flags);
-
- mesg->state = NULL;
- if (mesg->complete)
- mesg->complete(mesg->context);
-}
-EXPORT_SYMBOL_GPL(spi_finalize_current_message);
-
-static int spi_start_queue(struct spi_master *master)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&master->queue_lock, flags);
-
- if (master->running || master->busy) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- return -EBUSY;
- }
-
- master->running = true;
- master->cur_msg = NULL;
- spin_unlock_irqrestore(&master->queue_lock, flags);
-
- queue_kthread_work(&master->kworker, &master->pump_messages);
-
- return 0;
-}
-
-static int spi_stop_queue(struct spi_master *master)
-{
- unsigned long flags;
- unsigned limit = 500;
- int ret = 0;
-
- spin_lock_irqsave(&master->queue_lock, flags);
-
- /*
- * This is a bit lame, but is optimized for the common execution path.
- * A wait_queue on the master->busy could be used, but then the common
- * execution path (pump_messages) would be required to call wake_up or
- * friends on every SPI message. Do this instead.
- */
- while ((!list_empty(&master->queue) || master->busy) && limit--) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- msleep(10);
- spin_lock_irqsave(&master->queue_lock, flags);
- }
-
- if (!list_empty(&master->queue) || master->busy)
- ret = -EBUSY;
- else
- master->running = false;
-
- spin_unlock_irqrestore(&master->queue_lock, flags);
-
- if (ret) {
- dev_warn(&master->dev,
- "could not stop message queue\n");
- return ret;
- }
- return ret;
-}
-
-static int spi_destroy_queue(struct spi_master *master)
-{
- int ret;
-
- ret = spi_stop_queue(master);
-
- /*
- * flush_kthread_worker will block until all work is done.
- * If the reason that stop_queue timed out is that the work will never
- * finish, then it does no good to call flush/stop thread, so
- * return anyway.
- */
- if (ret) {
- dev_err(&master->dev, "problem destroying queue\n");
- return ret;
- }
-
- flush_kthread_worker(&master->kworker);
- kthread_stop(master->kworker_task);
-
- return 0;
-}
-
-/**
- * spi_queued_transfer - transfer function for queued transfers
- * @spi: spi device which is requesting transfer
- * @msg: spi message which is to handled is queued to driver queue
- */
-static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
-{
- struct spi_master *master = spi->master;
- unsigned long flags;
-
- spin_lock_irqsave(&master->queue_lock, flags);
-
- if (!master->running) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- return -ESHUTDOWN;
- }
- msg->actual_length = 0;
- msg->status = -EINPROGRESS;
-
- list_add_tail(&msg->queue, &master->queue);
- if (master->running && !master->busy)
- queue_kthread_work(&master->kworker, &master->pump_messages);
-
- spin_unlock_irqrestore(&master->queue_lock, flags);
- return 0;
-}
-
-static int spi_master_initialize_queue(struct spi_master *master)
-{
- int ret;
-
- master->queued = true;
- master->transfer = spi_queued_transfer;
-
- /* Initialize and start queue */
- ret = spi_init_queue(master);
- if (ret) {
- dev_err(&master->dev, "problem initializing queue\n");
- goto err_init_queue;
- }
- ret = spi_start_queue(master);
- if (ret) {
- dev_err(&master->dev, "problem starting queue\n");
- goto err_start_queue;
- }
-
- return 0;
-
-err_start_queue:
-err_init_queue:
- spi_destroy_queue(master);
- return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void spi_master_release(struct device *dev)
-{
- struct spi_master *master;
-
- master = container_of(dev, struct spi_master, dev);
- kfree(master);
-}
-
-static struct class spi_master_class = {
- .name = "spi_master",
- .owner = THIS_MODULE,
- .dev_release = spi_master_release,
-};
-
-
-
-/**
- * spi_alloc_master - allocate SPI master controller
- * @dev: the controller, possibly using the platform_bus
- * @size: how much zeroed driver-private data to allocate; the pointer to this
- * memory is in the driver_data field of the returned device,
- * accessible with spi_master_get_devdata().
- * Context: can sleep
- *
- * This call is used only by SPI master controller drivers, which are the
- * only ones directly touching chip registers. It's how they allocate
- * an spi_master structure, prior to calling spi_register_master().
- *
- * This must be called from context that can sleep. It returns the SPI
- * master structure on success, else NULL.
- *
- * The caller is responsible for assigning the bus number and initializing
- * the master's methods before calling spi_register_master(); and (after errors
- * adding the device) calling spi_master_put() and kfree() to prevent a memory
- * leak.
- */
-struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
-{
- struct spi_master *master;
-
- if (!dev)
- return NULL;
-
- master = kzalloc(size + sizeof *master, GFP_KERNEL);
- if (!master)
- return NULL;
-
- device_initialize(&master->dev);
- master->dev.class = &spi_master_class;
- master->dev.parent = get_device(dev);
- spi_master_set_devdata(master, &master[1]);
-
- return master;
-}
-EXPORT_SYMBOL_GPL(spi_alloc_master);
-
-/**
- * spi_register_master - register SPI master controller
- * @master: initialized master, originally from spi_alloc_master()
- * Context: can sleep
- *
- * SPI master controllers connect to their drivers using some non-SPI bus,
- * such as the platform bus. The final stage of probe() in that code
- * includes calling spi_register_master() to hook up to this SPI bus glue.
- *
- * SPI controllers use board specific (often SOC specific) bus numbers,
- * and board-specific addressing for SPI devices combines those numbers
- * with chip select numbers. Since SPI does not directly support dynamic
- * device identification, boards need configuration tables telling which
- * chip is at which address.
- *
- * This must be called from context that can sleep. It returns zero on
- * success, else a negative error code (dropping the master's refcount).
- * After a successful return, the caller is responsible for calling
- * spi_unregister_master().
- */
-int spi_register_master(struct spi_master *master)
-{
- static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
- struct device *dev = master->dev.parent;
- struct boardinfo *bi;
- int status = -ENODEV;
- int dynamic = 0;
-
- if (!dev)
- return -ENODEV;
-
- /* even if it's just one always-selected device, there must
- * be at least one chipselect
- */
- if (master->num_chipselect == 0)
- return -EINVAL;
-
- /* convention: dynamically assigned bus IDs count down from the max */
- if (master->bus_num < 0) {
- /* FIXME switch to an IDR based scheme, something like
- * I2C now uses, so we can't run out of "dynamic" IDs
- */
- master->bus_num = atomic_dec_return(&dyn_bus_id);
- dynamic = 1;
- }
-
- spin_lock_init(&master->bus_lock_spinlock);
- mutex_init(&master->bus_lock_mutex);
- master->bus_lock_flag = 0;
-
- /* register the device, then userspace will see it.
- * registration fails if the bus ID is in use.
- */
- dev_set_name(&master->dev, "spi%u", master->bus_num);
- status = device_add(&master->dev);
- if (status < 0)
- goto done;
- dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
- dynamic ? " (dynamic)" : "");
-
- /* If we're using a queued driver, start the queue */
- if (master->transfer)
- dev_info(dev, "master is unqueued, this is deprecated\n");
- else {
- status = spi_master_initialize_queue(master);
- if (status) {
- device_unregister(&master->dev);
- goto done;
- }
- }
-
- mutex_lock(&board_lock);
- list_add_tail(&master->list, &spi_master_list);
- list_for_each_entry(bi, &board_list, list)
- spi_match_master_to_boardinfo(master, &bi->board_info);
- mutex_unlock(&board_lock);
-
- /* Register devices from the device tree */
- of_register_spi_devices(master);
-done:
- return status;
-}
-EXPORT_SYMBOL_GPL(spi_register_master);
-
-static int __unregister(struct device *dev, void *null)
-{
- spi_unregister_device(to_spi_device(dev));
- return 0;
-}
-
-/**
- * spi_unregister_master - unregister SPI master controller
- * @master: the master being unregistered
- * Context: can sleep
- *
- * This call is used only by SPI master controller drivers, which are the
- * only ones directly touching chip registers.
- *
- * This must be called from context that can sleep.
- */
-void spi_unregister_master(struct spi_master *master)
-{
- int dummy;
-
- if (master->queued) {
- if (spi_destroy_queue(master))
- dev_err(&master->dev, "queue remove failed\n");
- }
-
- mutex_lock(&board_lock);
- list_del(&master->list);
- mutex_unlock(&board_lock);
-
- dummy = device_for_each_child(&master->dev, NULL, __unregister);
- device_unregister(&master->dev);
-}
-EXPORT_SYMBOL_GPL(spi_unregister_master);
-
-int spi_master_suspend(struct spi_master *master)
-{
- int ret;
-
- /* Basically no-ops for non-queued masters */
- if (!master->queued)
- return 0;
-
- ret = spi_stop_queue(master);
- if (ret)
- dev_err(&master->dev, "queue stop failed\n");
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(spi_master_suspend);
-
-int spi_master_resume(struct spi_master *master)
-{
- int ret;
-
- if (!master->queued)
- return 0;
-
- ret = spi_start_queue(master);
- if (ret)
- dev_err(&master->dev, "queue restart failed\n");
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(spi_master_resume);
-
-static int __spi_master_match(struct device *dev, void *data)
-{
- struct spi_master *m;
- u16 *bus_num = data;
-
- m = container_of(dev, struct spi_master, dev);
- return m->bus_num == *bus_num;
-}
-
-/**
- * spi_busnum_to_master - look up master associated with bus_num
- * @bus_num: the master's bus number
- * Context: can sleep
- *
- * This call may be used with devices that are registered after
- * arch init time. It returns a refcounted pointer to the relevant
- * spi_master (which the caller must release), or NULL if there is
- * no such master registered.
- */
-struct spi_master *spi_busnum_to_master(u16 bus_num)
-{
- struct device *dev;
- struct spi_master *master = NULL;
-
- dev = class_find_device(&spi_master_class, NULL, &bus_num,
- __spi_master_match);
- if (dev)
- master = container_of(dev, struct spi_master, dev);
- /* reference got in class_find_device */
- return master;
-}
-EXPORT_SYMBOL_GPL(spi_busnum_to_master);
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Core methods for SPI master protocol drivers. Some of the
- * other core methods are currently defined as inline functions.
- */
-
-/**
- * spi_setup - setup SPI mode and clock rate
- * @spi: the device whose settings are being modified
- * Context: can sleep, and no requests are queued to the device
- *
- * SPI protocol drivers may need to update the transfer mode if the
- * device doesn't work with its default. They may likewise need
- * to update clock rates or word sizes from initial values. This function
- * changes those settings, and must be called from a context that can sleep.
- * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
- * effect the next time the device is selected and data is transferred to
- * or from it. When this function returns, the spi device is deselected.
- *
- * Note that this call will fail if the protocol driver specifies an option
- * that the underlying controller or its driver does not support. For
- * example, not all hardware supports wire transfers using nine bit words,
- * LSB-first wire encoding, or active-high chipselects.
- */
-int spi_setup(struct spi_device *spi)
-{
- unsigned bad_bits;
- int status;
-
- /* help drivers fail *cleanly* when they need options
- * that aren't supported with their current master
- */
- bad_bits = spi->mode & ~spi->master->mode_bits;
- if (bad_bits) {
- dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
- bad_bits);
- return -EINVAL;
- }
-
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
-
- status = spi->master->setup(spi);
-
- dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
- "%u bits/w, %u Hz max --> %d\n",
- (int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
- (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
- (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
- (spi->mode & SPI_3WIRE) ? "3wire, " : "",
- (spi->mode & SPI_LOOP) ? "loopback, " : "",
- spi->bits_per_word, spi->max_speed_hz,
- status);
-
- return status;
-}
-EXPORT_SYMBOL_GPL(spi_setup);
-
-static int __spi_async(struct spi_device *spi, struct spi_message *message)
-{
- struct spi_master *master = spi->master;
-
- /* Half-duplex links include original MicroWire, and ones with
- * only one data pin like SPI_3WIRE (switches direction) or where
- * either MOSI or MISO is missing. They can also be caused by
- * software limitations.
- */
- if ((master->flags & SPI_MASTER_HALF_DUPLEX)
- || (spi->mode & SPI_3WIRE)) {
- struct spi_transfer *xfer;
- unsigned flags = master->flags;
-
- list_for_each_entry(xfer, &message->transfers, transfer_list) {
- if (xfer->rx_buf && xfer->tx_buf)
- return -EINVAL;
- if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
- return -EINVAL;
- if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
- return -EINVAL;
- }
- }
-
- message->spi = spi;
- message->status = -EINPROGRESS;
- return master->transfer(spi, message);
-}
-
-/**
- * spi_async - asynchronous SPI transfer
- * @spi: device with which data will be exchanged
- * @message: describes the data transfers, including completion callback
- * Context: any (irqs may be blocked, etc)
- *
- * This call may be used in_irq and other contexts which can't sleep,
- * as well as from task contexts which can sleep.
- *
- * The completion callback is invoked in a context which can't sleep.
- * Before that invocation, the value of message->status is undefined.
- * When the callback is issued, message->status holds either zero (to
- * indicate complete success) or a negative error code. After that
- * callback returns, the driver which issued the transfer request may
- * deallocate the associated memory; it's no longer in use by any SPI
- * core or controller driver code.
- *
- * Note that although all messages to a spi_device are handled in
- * FIFO order, messages may go to different devices in other orders.
- * Some device might be higher priority, or have various "hard" access
- * time requirements, for example.
- *
- * On detection of any fault during the transfer, processing of
- * the entire message is aborted, and the device is deselected.
- * Until returning from the associated message completion callback,
- * no other spi_message queued to that device will be processed.
- * (This rule applies equally to all the synchronous transfer calls,
- * which are wrappers around this core asynchronous primitive.)
- */
-int spi_async(struct spi_device *spi, struct spi_message *message)
-{
- struct spi_master *master = spi->master;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&master->bus_lock_spinlock, flags);
-
- if (master->bus_lock_flag)
- ret = -EBUSY;
- else
- ret = __spi_async(spi, message);
-
- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(spi_async);
-
-/**
- * spi_async_locked - version of spi_async with exclusive bus usage
- * @spi: device with which data will be exchanged
- * @message: describes the data transfers, including completion callback
- * Context: any (irqs may be blocked, etc)
- *
- * This call may be used in_irq and other contexts which can't sleep,
- * as well as from task contexts which can sleep.
- *
- * The completion callback is invoked in a context which can't sleep.
- * Before that invocation, the value of message->status is undefined.
- * When the callback is issued, message->status holds either zero (to
- * indicate complete success) or a negative error code. After that
- * callback returns, the driver which issued the transfer request may
- * deallocate the associated memory; it's no longer in use by any SPI
- * core or controller driver code.
- *
- * Note that although all messages to a spi_device are handled in
- * FIFO order, messages may go to different devices in other orders.
- * Some device might be higher priority, or have various "hard" access
- * time requirements, for example.
- *
- * On detection of any fault during the transfer, processing of
- * the entire message is aborted, and the device is deselected.
- * Until returning from the associated message completion callback,
- * no other spi_message queued to that device will be processed.
- * (This rule applies equally to all the synchronous transfer calls,
- * which are wrappers around this core asynchronous primitive.)
- */
-int spi_async_locked(struct spi_device *spi, struct spi_message *message)
-{
- struct spi_master *master = spi->master;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&master->bus_lock_spinlock, flags);
-
- ret = __spi_async(spi, message);
-
- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
-
- return ret;
-
-}
-EXPORT_SYMBOL_GPL(spi_async_locked);
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Utility methods for SPI master protocol drivers, layered on
- * top of the core. Some other utility methods are defined as
- * inline functions.
- */
-
-static void spi_complete(void *arg)
-{
- complete(arg);
-}
-
-static int __spi_sync(struct spi_device *spi, struct spi_message *message,
- int bus_locked)
-{
- DECLARE_COMPLETION_ONSTACK(done);
- int status;
- struct spi_master *master = spi->master;
-
- message->complete = spi_complete;
- message->context = &done;
-
- if (!bus_locked)
- mutex_lock(&master->bus_lock_mutex);
-
- status = spi_async_locked(spi, message);
-
- if (!bus_locked)
- mutex_unlock(&master->bus_lock_mutex);
-
- if (status == 0) {
- wait_for_completion(&done);
- status = message->status;
- }
- message->context = NULL;
- return status;
-}
-
-/**
- * spi_sync - blocking/synchronous SPI data transfers
- * @spi: device with which data will be exchanged
- * @message: describes the data transfers
- * Context: can sleep
- *
- * This call may only be used from a context that may sleep. The sleep
- * is non-interruptible, and has no timeout. Low-overhead controller
- * drivers may DMA directly into and out of the message buffers.
- *
- * Note that the SPI device's chip select is active during the message,
- * and then is normally disabled between messages. Drivers for some
- * frequently-used devices may want to minimize costs of selecting a chip,
- * by leaving it selected in anticipation that the next message will go
- * to the same chip. (That may increase power usage.)
- *
- * Also, the caller is guaranteeing that the memory associated with the
- * message will not be freed before this call returns.
- *
- * It returns zero on success, else a negative error code.
- */
-int spi_sync(struct spi_device *spi, struct spi_message *message)
-{
- return __spi_sync(spi, message, 0);
-}
-EXPORT_SYMBOL_GPL(spi_sync);
-
-/**
- * spi_sync_locked - version of spi_sync with exclusive bus usage
- * @spi: device with which data will be exchanged
- * @message: describes the data transfers
- * Context: can sleep
- *
- * This call may only be used from a context that may sleep. The sleep
- * is non-interruptible, and has no timeout. Low-overhead controller
- * drivers may DMA directly into and out of the message buffers.
- *
- * This call should be used by drivers that require exclusive access to the
- * SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must
- * be released by a spi_bus_unlock call when the exclusive access is over.
- *
- * It returns zero on success, else a negative error code.
- */
-int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
-{
- return __spi_sync(spi, message, 1);
-}
-EXPORT_SYMBOL_GPL(spi_sync_locked);
-
-/**
- * spi_bus_lock - obtain a lock for exclusive SPI bus usage
- * @master: SPI bus master that should be locked for exclusive bus access
- * Context: can sleep
- *
- * This call may only be used from a context that may sleep. The sleep
- * is non-interruptible, and has no timeout.
- *
- * This call should be used by drivers that require exclusive access to the
- * SPI bus. The SPI bus must be released by a spi_bus_unlock call when the
- * exclusive access is over. Data transfer must be done by spi_sync_locked
- * and spi_async_locked calls when the SPI bus lock is held.
- *
- * It returns zero on success, else a negative error code.
- */
-int spi_bus_lock(struct spi_master *master)
-{
- unsigned long flags;
-
- mutex_lock(&master->bus_lock_mutex);
-
- spin_lock_irqsave(&master->bus_lock_spinlock, flags);
- master->bus_lock_flag = 1;
- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
-
- /* mutex remains locked until spi_bus_unlock is called */
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bus_lock);
-
-/**
- * spi_bus_unlock - release the lock for exclusive SPI bus usage
- * @master: SPI bus master that was locked for exclusive bus access
- * Context: can sleep
- *
- * This call may only be used from a context that may sleep. The sleep
- * is non-interruptible, and has no timeout.
- *
- * This call releases an SPI bus lock previously obtained by an spi_bus_lock
- * call.
- *
- * It returns zero on success, else a negative error code.
- */
-int spi_bus_unlock(struct spi_master *master)
-{
- master->bus_lock_flag = 0;
-
- mutex_unlock(&master->bus_lock_mutex);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bus_unlock);
-
-/* portable code must never pass more than 32 bytes */
-#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
-
-static u8 *buf;
-
-/**
- * spi_write_then_read - SPI synchronous write followed by read
- * @spi: device with which data will be exchanged
- * @txbuf: data to be written (need not be dma-safe)
- * @n_tx: size of txbuf, in bytes
- * @rxbuf: buffer into which data will be read (need not be dma-safe)
- * @n_rx: size of rxbuf, in bytes
- * Context: can sleep
- *
- * This performs a half duplex MicroWire style transaction with the
- * device, sending txbuf and then reading rxbuf. The return value
- * is zero for success, else a negative errno status code.
- * This call may only be used from a context that may sleep.
- *
- * Parameters to this routine are always copied using a small buffer;
- * portable code should never use this for more than 32 bytes.
- * Performance-sensitive or bulk transfer code should instead use
- * spi_{async,sync}() calls with dma-safe buffers.
- */
-int spi_write_then_read(struct spi_device *spi,
- const void *txbuf, unsigned n_tx,
- void *rxbuf, unsigned n_rx)
-{
- static DEFINE_MUTEX(lock);
-
- int status;
- struct spi_message message;
- struct spi_transfer x[2];
- u8 *local_buf;
-
- /* Use preallocated DMA-safe buffer. We can't avoid copying here,
- * (as a pure convenience thing), but we can keep heap costs
- * out of the hot path ...
- */
- if ((n_tx + n_rx) > SPI_BUFSIZ)
- return -EINVAL;
-
- spi_message_init(&message);
- memset(x, 0, sizeof x);
- if (n_tx) {
- x[0].len = n_tx;
- spi_message_add_tail(&x[0], &message);
- }
- if (n_rx) {
- x[1].len = n_rx;
- spi_message_add_tail(&x[1], &message);
- }
-
- /* ... unless someone else is using the pre-allocated buffer */
- if (!mutex_trylock(&lock)) {
- local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
- if (!local_buf)
- return -ENOMEM;
- } else
- local_buf = buf;
-
- memcpy(local_buf, txbuf, n_tx);
- x[0].tx_buf = local_buf;
- x[1].rx_buf = local_buf + n_tx;
-
- /* do the i/o */
- status = spi_sync(spi, &message);
- if (status == 0)
- memcpy(rxbuf, x[1].rx_buf, n_rx);
-
- if (x[0].tx_buf == buf)
- mutex_unlock(&lock);
- else
- kfree(local_buf);
-
- return status;
-}
-EXPORT_SYMBOL_GPL(spi_write_then_read);
-
-/*-------------------------------------------------------------------------*/
-
-static int __init spi_init(void)
-{
- int status;
-
- buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
- if (!buf) {
- status = -ENOMEM;
- goto err0;
- }
-
- status = bus_register(&spi_bus_type);
- if (status < 0)
- goto err1;
-
- status = class_register(&spi_master_class);
- if (status < 0)
- goto err2;
- return 0;
-
-err2:
- bus_unregister(&spi_bus_type);
-err1:
- kfree(buf);
- buf = NULL;
-err0:
- return status;
-}
-
-/* board_info is normally registered in arch_initcall(),
- * but even essential drivers wait till later
- *
- * REVISIT only boardinfo really needs static linking. the rest (device and
- * driver registration) _could_ be dynamically linked (modular) ... costs
- * include needing to have boardinfo data structures be much more public.
- */
-postcore_initcall(spi_init);
-
diff --git a/ANDROID_3.4.5/drivers/spi/spidev.c b/ANDROID_3.4.5/drivers/spi/spidev.c
deleted file mode 100644
index 830adbed..00000000
--- a/ANDROID_3.4.5/drivers/spi/spidev.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
- * Simple synchronous userspace interface to SPI devices
- *
- * Copyright (C) 2006 SWAPP
- * Andrea Paterniani <a.paterniani@swapp-eng.it>
- * Copyright (C) 2007 David Brownell (simplification, cleanup)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/ioctl.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/compat.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spidev.h>
-
-#include <asm/uaccess.h>
-
-
-/*
- * This supports access to SPI devices using normal userspace I/O calls.
- * Note that while traditional UNIX/POSIX I/O semantics are half duplex,
- * and often mask message boundaries, full SPI support requires full duplex
- * transfers. There are several kinds of internal message boundaries to
- * handle chipselect management and other protocol options.
- *
- * SPI has a character major number assigned. We allocate minor numbers
- * dynamically using a bitmask. You must use hotplug tools, such as udev
- * (or mdev with busybox) to create and destroy the /dev/spidevB.C device
- * nodes, since there is no fixed association of minor numbers with any
- * particular SPI bus or device.
- */
-#define SPIDEV_MAJOR 153 /* assigned */
-#define N_SPI_MINORS 32 /* ... up to 256 */
-
-static DECLARE_BITMAP(minors, N_SPI_MINORS);
-
-
-/* Bit masks for spi_device.mode management. Note that incorrect
- * settings for some settings can cause *lots* of trouble for other
- * devices on a shared bus:
- *
- * - CS_HIGH ... this device will be active when it shouldn't be
- * - 3WIRE ... when active, it won't behave as it should
- * - NO_CS ... there will be no explicit message boundaries; this
- * is completely incompatible with the shared bus model
- * - READY ... transfers may proceed when they shouldn't.
- *
- * REVISIT should changing those flags be privileged?
- */
-#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
- | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
- | SPI_NO_CS | SPI_READY)
-
-struct spidev_data {
- dev_t devt;
- spinlock_t spi_lock;
- struct spi_device *spi;
- struct list_head device_entry;
-
- /* buffer is NULL unless this device is open (users > 0) */
- struct mutex buf_lock;
- unsigned users;
- u8 *buffer;
-};
-
-static LIST_HEAD(device_list);
-static DEFINE_MUTEX(device_list_lock);
-
-static unsigned bufsiz = 4096;
-module_param(bufsiz, uint, S_IRUGO);
-MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * We can't use the standard synchronous wrappers for file I/O; we
- * need to protect against async removal of the underlying spi_device.
- */
-static void spidev_complete(void *arg)
-{
- complete(arg);
-}
-
-static ssize_t
-spidev_sync(struct spidev_data *spidev, struct spi_message *message)
-{
- DECLARE_COMPLETION_ONSTACK(done);
- int status;
-
- message->complete = spidev_complete;
- message->context = &done;
-
- spin_lock_irq(&spidev->spi_lock);
- if (spidev->spi == NULL)
- status = -ESHUTDOWN;
- else
- status = spi_async(spidev->spi, message);
- spin_unlock_irq(&spidev->spi_lock);
-
- if (status == 0) {
- wait_for_completion(&done);
- status = message->status;
- if (status == 0)
- status = message->actual_length;
- }
- return status;
-}
-
-static inline ssize_t
-spidev_sync_write(struct spidev_data *spidev, size_t len)
-{
- struct spi_transfer t = {
- .tx_buf = spidev->buffer,
- .len = len,
- };
- struct spi_message m;
-
- spi_message_init(&m);
- spi_message_add_tail(&t, &m);
- return spidev_sync(spidev, &m);
-}
-
-static inline ssize_t
-spidev_sync_read(struct spidev_data *spidev, size_t len)
-{
- struct spi_transfer t = {
- .rx_buf = spidev->buffer,
- .len = len,
- };
- struct spi_message m;
-
- spi_message_init(&m);
- spi_message_add_tail(&t, &m);
- return spidev_sync(spidev, &m);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Read-only message with current device setup */
-static ssize_t
-spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
- struct spidev_data *spidev;
- ssize_t status = 0;
-
- /* chipselect only toggles at start or end of operation */
- if (count > bufsiz)
- return -EMSGSIZE;
-
- spidev = filp->private_data;
-
- mutex_lock(&spidev->buf_lock);
- status = spidev_sync_read(spidev, count);
- if (status > 0) {
- unsigned long missing;
-
- missing = copy_to_user(buf, spidev->buffer, status);
- if (missing == status)
- status = -EFAULT;
- else
- status = status - missing;
- }
- mutex_unlock(&spidev->buf_lock);
-
- return status;
-}
-
-/* Write-only message with current device setup */
-static ssize_t
-spidev_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *f_pos)
-{
- struct spidev_data *spidev;
- ssize_t status = 0;
- unsigned long missing;
-
- /* chipselect only toggles at start or end of operation */
- if (count > bufsiz)
- return -EMSGSIZE;
-
- spidev = filp->private_data;
-
- mutex_lock(&spidev->buf_lock);
- missing = copy_from_user(spidev->buffer, buf, count);
- if (missing == 0) {
- status = spidev_sync_write(spidev, count);
- } else
- status = -EFAULT;
- mutex_unlock(&spidev->buf_lock);
-
- return status;
-}
-
-static int spidev_message(struct spidev_data *spidev,
- struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
-{
- struct spi_message msg;
- struct spi_transfer *k_xfers;
- struct spi_transfer *k_tmp;
- struct spi_ioc_transfer *u_tmp;
- unsigned n, total;
- u8 *buf;
- int status = -EFAULT;
-
- spi_message_init(&msg);
- k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
- if (k_xfers == NULL)
- return -ENOMEM;
-
- /* Construct spi_message, copying any tx data to bounce buffer.
- * We walk the array of user-provided transfers, using each one
- * to initialize a kernel version of the same transfer.
- */
- buf = spidev->buffer;
- total = 0;
- for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
- n;
- n--, k_tmp++, u_tmp++) {
- k_tmp->len = u_tmp->len;
-
- total += k_tmp->len;
- if (total > bufsiz) {
- status = -EMSGSIZE;
- goto done;
- }
-
- if (u_tmp->rx_buf) {
- k_tmp->rx_buf = buf;
- if (!access_ok(VERIFY_WRITE, (u8 __user *)
- (uintptr_t) u_tmp->rx_buf,
- u_tmp->len))
- goto done;
- }
- if (u_tmp->tx_buf) {
- k_tmp->tx_buf = buf;
- if (copy_from_user(buf, (const u8 __user *)
- (uintptr_t) u_tmp->tx_buf,
- u_tmp->len))
- goto done;
- }
- buf += k_tmp->len;
-
- k_tmp->cs_change = !!u_tmp->cs_change;
- k_tmp->bits_per_word = u_tmp->bits_per_word;
- k_tmp->delay_usecs = u_tmp->delay_usecs;
- k_tmp->speed_hz = u_tmp->speed_hz;
-#ifdef VERBOSE
- dev_dbg(&spidev->spi->dev,
- " xfer len %zd %s%s%s%dbits %u usec %uHz\n",
- u_tmp->len,
- u_tmp->rx_buf ? "rx " : "",
- u_tmp->tx_buf ? "tx " : "",
- u_tmp->cs_change ? "cs " : "",
- u_tmp->bits_per_word ? : spidev->spi->bits_per_word,
- u_tmp->delay_usecs,
- u_tmp->speed_hz ? : spidev->spi->max_speed_hz);
-#endif
- spi_message_add_tail(k_tmp, &msg);
- }
-
- status = spidev_sync(spidev, &msg);
- if (status < 0)
- goto done;
-
- /* copy any rx data out of bounce buffer */
- buf = spidev->buffer;
- for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
- if (u_tmp->rx_buf) {
- if (__copy_to_user((u8 __user *)
- (uintptr_t) u_tmp->rx_buf, buf,
- u_tmp->len)) {
- status = -EFAULT;
- goto done;
- }
- }
- buf += u_tmp->len;
- }
- status = total;
-
-done:
- kfree(k_xfers);
- return status;
-}
-
-static long
-spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int err = 0;
- int retval = 0;
- struct spidev_data *spidev;
- struct spi_device *spi;
- u32 tmp;
- unsigned n_ioc;
- struct spi_ioc_transfer *ioc;
-
- /* Check type and command number */
- if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
- return -ENOTTY;
-
- /* Check access direction once here; don't repeat below.
- * IOC_DIR is from the user perspective, while access_ok is
- * from the kernel perspective; so they look reversed.
- */
- if (_IOC_DIR(cmd) & _IOC_READ)
- err = !access_ok(VERIFY_WRITE,
- (void __user *)arg, _IOC_SIZE(cmd));
- if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
- err = !access_ok(VERIFY_READ,
- (void __user *)arg, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
-
- /* guard against device removal before, or while,
- * we issue this ioctl.
- */
- spidev = filp->private_data;
- spin_lock_irq(&spidev->spi_lock);
- spi = spi_dev_get(spidev->spi);
- spin_unlock_irq(&spidev->spi_lock);
-
- if (spi == NULL)
- return -ESHUTDOWN;
-
- /* use the buffer lock here for triple duty:
- * - prevent I/O (from us) so calling spi_setup() is safe;
- * - prevent concurrent SPI_IOC_WR_* from morphing
- * data fields while SPI_IOC_RD_* reads them;
- * - SPI_IOC_MESSAGE needs the buffer locked "normally".
- */
- mutex_lock(&spidev->buf_lock);
-
- switch (cmd) {
- /* read requests */
- case SPI_IOC_RD_MODE:
- retval = __put_user(spi->mode & SPI_MODE_MASK,
- (__u8 __user *)arg);
- break;
- case SPI_IOC_RD_LSB_FIRST:
- retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
- (__u8 __user *)arg);
- break;
- case SPI_IOC_RD_BITS_PER_WORD:
- retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
- break;
- case SPI_IOC_RD_MAX_SPEED_HZ:
- retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
- break;
-
- /* write requests */
- case SPI_IOC_WR_MODE:
- retval = __get_user(tmp, (u8 __user *)arg);
- if (retval == 0) {
- u8 save = spi->mode;
-
- if (tmp & ~SPI_MODE_MASK) {
- retval = -EINVAL;
- break;
- }
-
- tmp |= spi->mode & ~SPI_MODE_MASK;
- spi->mode = (u8)tmp;
- retval = spi_setup(spi);
- if (retval < 0)
- spi->mode = save;
- else
- dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
- }
- break;
- case SPI_IOC_WR_LSB_FIRST:
- retval = __get_user(tmp, (__u8 __user *)arg);
- if (retval == 0) {
- u8 save = spi->mode;
-
- if (tmp)
- spi->mode |= SPI_LSB_FIRST;
- else
- spi->mode &= ~SPI_LSB_FIRST;
- retval = spi_setup(spi);
- if (retval < 0)
- spi->mode = save;
- else
- dev_dbg(&spi->dev, "%csb first\n",
- tmp ? 'l' : 'm');
- }
- break;
- case SPI_IOC_WR_BITS_PER_WORD:
- retval = __get_user(tmp, (__u8 __user *)arg);
- if (retval == 0) {
- u8 save = spi->bits_per_word;
-
- spi->bits_per_word = tmp;
- retval = spi_setup(spi);
- if (retval < 0)
- spi->bits_per_word = save;
- else
- dev_dbg(&spi->dev, "%d bits per word\n", tmp);
- }
- break;
- case SPI_IOC_WR_MAX_SPEED_HZ:
- retval = __get_user(tmp, (__u32 __user *)arg);
- if (retval == 0) {
- u32 save = spi->max_speed_hz;
-
- spi->max_speed_hz = tmp;
- retval = spi_setup(spi);
- if (retval < 0)
- spi->max_speed_hz = save;
- else
- dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
- }
- break;
-
- default:
- /* segmented and/or full-duplex I/O request */
- if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
- || _IOC_DIR(cmd) != _IOC_WRITE) {
- retval = -ENOTTY;
- break;
- }
-
- tmp = _IOC_SIZE(cmd);
- if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
- retval = -EINVAL;
- break;
- }
- n_ioc = tmp / sizeof(struct spi_ioc_transfer);
- if (n_ioc == 0)
- break;
-
- /* copy into scratch area */
- ioc = kmalloc(tmp, GFP_KERNEL);
- if (!ioc) {
- retval = -ENOMEM;
- break;
- }
- if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
- kfree(ioc);
- retval = -EFAULT;
- break;
- }
-
- /* translate to spi_message, execute */
- retval = spidev_message(spidev, ioc, n_ioc);
- kfree(ioc);
- break;
- }
-
- mutex_unlock(&spidev->buf_lock);
- spi_dev_put(spi);
- return retval;
-}
-
-#ifdef CONFIG_COMPAT
-static long
-spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
-}
-#else
-#define spidev_compat_ioctl NULL
-#endif /* CONFIG_COMPAT */
-
-static int spidev_open(struct inode *inode, struct file *filp)
-{
- struct spidev_data *spidev;
- int status = -ENXIO;
-
- mutex_lock(&device_list_lock);
-
- list_for_each_entry(spidev, &device_list, device_entry) {
- if (spidev->devt == inode->i_rdev) {
- status = 0;
- break;
- }
- }
- if (status == 0) {
- if (!spidev->buffer) {
- spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);
- if (!spidev->buffer) {
- dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
- status = -ENOMEM;
- }
- }
- if (status == 0) {
- spidev->users++;
- filp->private_data = spidev;
- nonseekable_open(inode, filp);
- }
- } else
- pr_debug("spidev: nothing for minor %d\n", iminor(inode));
-
- mutex_unlock(&device_list_lock);
- return status;
-}
-
-static int spidev_release(struct inode *inode, struct file *filp)
-{
- struct spidev_data *spidev;
- int status = 0;
-
- mutex_lock(&device_list_lock);
- spidev = filp->private_data;
- filp->private_data = NULL;
-
- /* last close? */
- spidev->users--;
- if (!spidev->users) {
- int dofree;
-
- kfree(spidev->buffer);
- spidev->buffer = NULL;
-
- /* ... after we unbound from the underlying device? */
- spin_lock_irq(&spidev->spi_lock);
- dofree = (spidev->spi == NULL);
- spin_unlock_irq(&spidev->spi_lock);
-
- if (dofree)
- kfree(spidev);
- }
- mutex_unlock(&device_list_lock);
-
- return status;
-}
-
-static const struct file_operations spidev_fops = {
- .owner = THIS_MODULE,
- /* REVISIT switch to aio primitives, so that userspace
- * gets more complete API coverage. It'll simplify things
- * too, except for the locking.
- */
- .write = spidev_write,
- .read = spidev_read,
- .unlocked_ioctl = spidev_ioctl,
- .compat_ioctl = spidev_compat_ioctl,
- .open = spidev_open,
- .release = spidev_release,
- .llseek = no_llseek,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* The main reason to have this class is to make mdev/udev create the
- * /dev/spidevB.C character device nodes exposing our userspace API.
- * It also simplifies memory management.
- */
-
-static struct class *spidev_class;
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit spidev_probe(struct spi_device *spi)
-{
- struct spidev_data *spidev;
- int status;
- unsigned long minor;
-
- /* Allocate driver data */
- spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
- if (!spidev)
- return -ENOMEM;
-
- /* Initialize the driver data */
- spidev->spi = spi;
- spin_lock_init(&spidev->spi_lock);
- mutex_init(&spidev->buf_lock);
-
- INIT_LIST_HEAD(&spidev->device_entry);
-
- /* If we can allocate a minor number, hook up this device.
- * Reusing minors is fine so long as udev or mdev is working.
- */
- mutex_lock(&device_list_lock);
- minor = find_first_zero_bit(minors, N_SPI_MINORS);
- if (minor < N_SPI_MINORS) {
- struct device *dev;
-
- spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
- dev = device_create(spidev_class, &spi->dev, spidev->devt,
- spidev, "spidev%d.%d",
- spi->master->bus_num, spi->chip_select);
- status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
- } else {
- dev_dbg(&spi->dev, "no minor number available!\n");
- status = -ENODEV;
- }
- if (status == 0) {
- set_bit(minor, minors);
- list_add(&spidev->device_entry, &device_list);
- }
- mutex_unlock(&device_list_lock);
-
- if (status == 0)
- spi_set_drvdata(spi, spidev);
- else
- kfree(spidev);
-
- return status;
-}
-
-static int __devexit spidev_remove(struct spi_device *spi)
-{
- struct spidev_data *spidev = spi_get_drvdata(spi);
-
- /* make sure ops on existing fds can abort cleanly */
- spin_lock_irq(&spidev->spi_lock);
- spidev->spi = NULL;
- spi_set_drvdata(spi, NULL);
- spin_unlock_irq(&spidev->spi_lock);
-
- /* prevent new opens */
- mutex_lock(&device_list_lock);
- list_del(&spidev->device_entry);
- device_destroy(spidev_class, spidev->devt);
- clear_bit(MINOR(spidev->devt), minors);
- if (spidev->users == 0)
- kfree(spidev);
- mutex_unlock(&device_list_lock);
-
- return 0;
-}
-
-static struct spi_driver spidev_spi_driver = {
- .driver = {
- .name = "spidev",
- .owner = THIS_MODULE,
- },
- .probe = spidev_probe,
- .remove = __devexit_p(spidev_remove),
-
- /* NOTE: suspend/resume methods are not necessary here.
- * We don't do anything except pass the requests to/from
- * the underlying controller. The refrigerator handles
- * most issues; the controller driver handles the rest.
- */
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init spidev_init(void)
-{
- int status;
-
- /* Claim our 256 reserved device numbers. Then register a class
- * that will key udev/mdev to add/remove /dev nodes. Last, register
- * the driver which manages those device numbers.
- */
- BUILD_BUG_ON(N_SPI_MINORS > 256);
- status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
- if (status < 0)
- return status;
-
- spidev_class = class_create(THIS_MODULE, "spidev");
- if (IS_ERR(spidev_class)) {
- unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
- return PTR_ERR(spidev_class);
- }
-
- status = spi_register_driver(&spidev_spi_driver);
- if (status < 0) {
- class_destroy(spidev_class);
- unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
- }
- return status;
-}
-module_init(spidev_init);
-
-static void __exit spidev_exit(void)
-{
- spi_unregister_driver(&spidev_spi_driver);
- class_destroy(spidev_class);
- unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
-}
-module_exit(spidev_exit);
-
-MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
-MODULE_DESCRIPTION("User mode SPI device interface");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:spidev");
diff --git a/ANDROID_3.4.5/drivers/spi/wmt_spi.c b/ANDROID_3.4.5/drivers/spi/wmt_spi.c
deleted file mode 100755
index 7b301488..00000000
--- a/ANDROID_3.4.5/drivers/spi/wmt_spi.c
+++ /dev/null
@@ -1,1347 +0,0 @@
-/*++
- drivers/spi/wmt_spi.c
-
- Copyright (c) 2008 WonderMedia Technologies, Inc.
-
- This program is free software: you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software Foundation,
- either version 2 of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE. See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along with
- this program. If not, see <http://www.gnu.org/licenses/>.
-
- WonderMedia Technologies, Inc.
- 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
---*/
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/ioport.h>
-#include <linux/dma-mapping.h>
-#include <linux/sched.h>
-
-#include <mach/hardware.h>
-#include <mach/wmt_gpio.h>
-
-//#define DEBUG 1 /* debug open */
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <mach/wmt-spi.h>
-
-#ifdef DEBUG
-#define spi_dbg(fmt, args...) printk(KERN_ERR "[%s]_%d: " fmt, __func__ , __LINE__, ## args)
-#define spi_trace() printk(KERN_ERR "trace in %s %d\n", __func__, __LINE__);
-#else
-#define spi_dbg(fmt, args...)
-#define spi_trace()
-#endif
-
-static unsigned int pllb_input_freq = 83333;
-static bool g_use_ss1 = false;
-static bool g_use_ss2 = false;
-static bool g_use_ss3 = false;
-
-/*
- * spi_set_reg32 - write a u32 value to spi register
- * @spi: spi controller's driver data
- * @reg_offset: register's offset address
- * @val: value register will be set
- */
-static inline void
-spi_set_reg32(struct wmt_spi *spi, u32 reg_offset, u32 val)
-{
- iowrite32(val, spi->regs_base + reg_offset);
-}
-
-/*
- * spi_get_reg32 - read a u32 value from spi register
- * @spi: spi controller's driver data
- * @reg_offset: register's offset address
- */
-static inline unsigned int
-spi_get_reg32(struct wmt_spi *spi, int reg_offset)
-{
- return ioread32(spi->regs_base + reg_offset);
-}
-
-/*
- * spi_setbit: write bit1 to related register's bit
- * @spi: spi controller's driver data
- * @offset: register's offset address
- * @mask: bit setting mask
- */
-static void
-spi_setbit(struct wmt_spi *spi, u32 reg_offset, u32 mask)
-{
- u32 tmp;
- tmp = spi_get_reg32(spi, reg_offset);
- tmp |= mask;
- spi_set_reg32(spi, reg_offset, tmp);
-}
-
-/*
- * spi_clrbit: write bit0 to related register's bit
- * @spi: spi controller's driver data
- * @offset: register's offset address
- * @mask: bit setting mask
- */
-static void
-spi_clrbit(struct wmt_spi *spi, u32 reg_offset, u32 mask)
-{
- u32 tmp;
- tmp = spi_get_reg32(spi, reg_offset);
- tmp &= ~mask;
- spi_set_reg32(spi, reg_offset, tmp);
-}
-
-/*
- * spi_write_fifo: write a u8 value to spi tx fifo
- * @spi: spi controller's driver data
- * @fifo_reg: spi tx fifo register offset
- * @val: value writen to spi tx fifo
- */
-static inline void
-spi_write_fifo(struct wmt_spi *spi, u32 fifo_reg, const u8 val)
-{
- iowrite8(val, spi->regs_base + fifo_reg);
-}
-
-/*
- * spi_read_fifo: read a u8 value from spi rx fifo
- * @spi: spi controller's driver data
- * @fifo_reg: spi rx fifo register offset
- */
-static inline u8
-spi_read_fifo(struct wmt_spi *spi, u32 fifo_reg)
-{
- return ioread8(spi->regs_base + fifo_reg);
-}
-
-/*
- * wmt_spi_clock_enable: set GPIO to SPI mode, ten enable spi
- * clock from Power management module and set default spi clock
- * dividor to 0x04 as default (93Mhz)
- */
-static inline void wmt_spi_clock_enable(void)
-{
- int timeout = POLLING_SPI_REG_TIMEOUT;
-
- GPIO_CTRL_GP12_SPI_BYTE_VAL &= ~(GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_MISO|
- GPIO_SPI0_SS0);
- PULL_EN_GP12_SPI_BYTE_VAL |= (GPIO_SPI0_CLK_PULL_EN |
- GPIO_SPI0_MOSI_PULL_EN|
- GPIO_SPI0_MISO_PULL_EN|
- GPIO_SPI0_SS0_PULL_EN);
- PULL_CTRL_GP12_SPI_BYTE_VAL |= (GPIO_SPI0_CLK_PULL_EN |
- GPIO_SPI0_MOSI_PULL_EN|
- GPIO_SPI0_MISO_PULL_EN);
- PULL_CTRL_GP12_SPI_BYTE_VAL &= ~GPIO_SPI0_CLK_PULL_UP;
- if (g_use_ss1 || g_use_ss2 || g_use_ss3)
- PIN_SHARING_SEL_4BYTE_VAL &= ~BIT7;
-#if 0
- /*Enable SPI function and disable GPIO function for related SPI pin*/
- GPIO_CTRL_GP11_SPI_BYTE_VAL &= ~(GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_MISO);
-
- GPIO_PULL_EN_GP11_SPI_BYTE_VAL |= ( GPIO_SPI0_CLK_PULL_EN |
- GPIO_SPI0_MISO_PULL_EN |
- GPIO_SPI0_MOSI_PULL_EN );
- GPIO_PULL_CTRL_GP11_SPI_BYTE_VAL |= (GPIO_SPI0_MISO_PULL_UP |
- GPIO_SPI0_MOSI_PULL_UP );
-
- GPIO_PULL_CTRL_GP11_SPI_BYTE_VAL &=~ (GPIO_SPI0_CLK_PULL_UP);
- if (g_use_ss0) {
- GPIO_CTRL_GP11_SPI_BYTE_VAL &= ~(GPIO_SPI0_SS);
- GPIO_PULL_EN_GP11_SPI_BYTE_VAL |= GPIO_SPI0_SS_PULL_EN;
- GPIO_PULL_CTRL_GP11_SPI_BYTE_VAL |= GPIO_SPI0_SS_PULL_UP;
- }
- if (g_use_ss1) {
- GPIO_CTRL_GP1_BYTE_VAL &= ~BIT2;
- GPIO_PULL_EN_GP1_BYTE_VAL |= BIT2;
- GPIO_PULL_CTRL_GP1_BYTE_VAL |= BIT2;
- GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT5;
- }
- if (g_use_ss2) {
- GPIO_CTRL_GP31_BYTE_VAL &= ~BIT1;
- GPIO_PULL_EN_GP31_BYTE_VAL |= BIT1;
- GPIO_PULL_CTRL_GP31_BYTE_VAL |= BIT1;
- GPIO_PIN_SHARING_SEL_4BYTE_VAL |= BIT12;
- }
- if (g_use_ss3) {
- GPIO_CTRL_GP31_BYTE_VAL &= ~BIT2;
- GPIO_PULL_EN_GP31_BYTE_VAL |= BIT2;
- GPIO_PULL_CTRL_GP31_BYTE_VAL |= BIT2;
- GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4;
- }
-
-#endif
- /* clock open */
- auto_pll_divisor(DEV_SPI0, CLK_ENABLE, 0, 0);
- pllb_input_freq = auto_pll_divisor(DEV_SPI0, SET_DIV, 1, 100000);
- pllb_input_freq /= 1000;
-
- /* check if config successful */
- while (timeout--) {
- if (!(REG8_VAL(PMC_REG_BASE) & 0x04000000))
- return ;
- udelay(1);
- }
- printk(KERN_ERR "Enable SPI clock from PMC module failed\n!");
-}
-
-/*
- * wmt_spi_clock_disable: reset GPIO and disable spi clock from
- * Power management module
- */
-static inline void wmt_spi_clock_disable(void)
-{
- GPIO_CTRL_GP12_SPI_BYTE_VAL |= (GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_SS0|
- GPIO_SPI0_MISO);
-}
-
-/*
- * spi_is_busy: check spi controller(master) is busy or not
- * @spi: spi controller's driver data
- */
-static int spi_is_busy(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_SR) & SPI_SR_BUSY_MASK) == 0)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_enable: enable spi module
- * @spi: spi controller's driver data
- */
-static void spi_enable(struct wmt_spi *spi)
-{
- spi_setbit(spi, SPI_CR, SPI_CR_ME_MASK);
-}
-
-/*
- * spi_disable: disable spi module
- * @spi: spi controller's driver data
- */
-static void spi_disable(struct wmt_spi *spi)
-{
- if (spi_is_busy(spi)) {
- dev_warn(&spi->master->dev, "Disable spi controller failed\n");
- }
- spi_clrbit(spi, SPI_CR, SPI_CR_ME_MASK);
-}
-
-/*
- * spi_tx_is_finish: polling if data in tx fifo has been sent out
- * @spi: spi controller's driver data
- */
-static int spi_tx_is_finish(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if (spi_get_reg32(spi, SPI_SR) | SPI_SR_TFEI_MASK)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_rx_is_finish: polling if data in rx fifo has been read out
- * @spi: spi controller's driver data
- */
-static int spi_rx_is_finish(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_SR) | SPI_SR_RFEI_MASK))
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * wmt_spi_cs_active: enable chip select signal. SSN is driven
- * low to active if spi controller use SSN_CTRL_PROGRAM mode
- * @spi: spi controller's driver data
- */
-static inline void wmt_spi_cs_active(struct spi_device *spi_dev, struct wmt_spi *spi)
-{
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- /* enable SSN */
- if (hw_info->ssn_ctrl == SSN_CTRL_PROGRAM)
- spi_clrbit(spi, SPI_DFCR, SPI_DFCR_DSV_MASK | SPI_DFCR_DSE_MASK);
-}
-
-/*
- * wmt_spi_cs_inactive: disable chip select signal. A SSN is driven
- * high to inactive if spi controller use SSN_CTRL_PROGRAM mode
- * @spi: spi controller's driver data
- */
-static inline void wmt_spi_cs_inactive(struct spi_device *spi_dev, struct wmt_spi *spi)
-{
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if (hw_info->ssn_ctrl == SSN_CTRL_PROGRAM)
- spi_setbit(spi, SPI_DFCR, SPI_DFCR_DSV_MASK | SPI_DFCR_DSE_MASK);
-}
-
-/*
- * get_spi_input_freq: get spi original input frequence from power
- * management module
- */
-static unsigned int get_spi_input_freq(void)
-{
- return pllb_input_freq;
-}
-
-/*
- * spi_set_clock_div: set clock divider in spi control register,
- * if the divisor is too low or too high, set spi working
- * frequency 5Mhz as default
- * @spi: spi controller's driver data
- * @speed_hz: spi working clock frequency, unit is hz
- */
-static void spi_set_clock_div(struct wmt_spi *spi, int speed_hz)
-{
- unsigned int divisor;
- unsigned int hw_freq = get_spi_input_freq()*1000; /* KHz to Hz */
-
- spi_clrbit(spi, SPI_CR, SPI_CR_TCD_MASK);
- if (!speed_hz)
- goto err;
-
- divisor = hw_freq/(2*speed_hz);
- if (divisor < 0 || divisor > 0x7ff) /* spi cr bit(21,31), max:0x7ff */
- goto err;
-
- spi_setbit(spi, SPI_CR, divisor << SPI_CR_TCD_SHIFT);
- return ;
-
-err:
- divisor = hw_freq/(2*SPI_DFLT_FREQ);
- spi_setbit(spi, SPI_CR, divisor << SPI_CR_TCD_SHIFT);
- dev_err(&spi->master->dev, "SPI frequency %dhz not support, " \
- "set %dhz as default\n", speed_hz, SPI_DFLT_FREQ);
- return ;
-}
-
-/*
- * spi_set_bit_order: set spi redeive/transmit significant bit order
- * @spi: spi controller's driver data
- * @mode: spi device working mode
- */
-static void spi_set_bit_order(struct wmt_spi *spi, u8 mode)
-{
- if (mode & SPI_LSB_FIRST)
- spi_setbit(spi, SPI_DFCR, SPI_DFCR_RSBO_MASK | SPI_DFCR_TSBO_MASK);
-}
-
-/*
- * spi_set_clock_mode: set spi clock polarity and phase (spi clock mode)
- * @spi: spi controller's driver data
- * @clk_mode: spi clock mode
- */
-static void spi_set_clock_mode(struct wmt_spi *spi, u8 clk_mode)
-{
- spi_clrbit(spi, SPI_CR, SPI_CR_CPHS_MASK);
- if (clk_mode > SPI_CLK_MODE3)
- goto err;
- spi_setbit(spi, SPI_CR, clk_mode << SPI_CR_CPHS_SHIFT);
- return ;
-err:
- spi_setbit(spi, SPI_CR, SPI_CLK_MODE3 << SPI_CR_CPHS_SHIFT);
- dev_err(&spi->master->dev, "clock mode err, set clock mode 3 as default\n");
- return ;
-}
-
-/*
- * spi_as_master: spi master/slave select
- * @spi: spi controller's driver data
- * @is_master: if spi configured as master, is_master = 1, else is_master = 0
- */
-static void spi_as_master(struct wmt_spi *spi, u8 is_master)
-{
- if (is_master)
- spi_clrbit(spi, SPI_CR, SPI_CR_MSMS_MASK);
- else
- spi_setbit(spi, SPI_CR, SPI_CR_MSMS_MASK);
-}
-
-/*
- * spi_reset_tx_fifo: reset spi transmit fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_tx_fifo(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- spi_setbit(spi, SPI_CR, SPI_CR_TFR_MASK);
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_CR) & SPI_CR_TFR_MASK) == 0)
- return 0;
- }
- return -1;
-}
-
-/*
- * spi_reset_rx_fifo: reset spi receive fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_rx_fifo(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- spi_setbit(spi, SPI_CR, SPI_CR_RFR_MASK);
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_CR) & SPI_CR_RFR_MASK) == 0)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_reset_fifo: reset both spi transmit fifo and receive fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_fifo(struct wmt_spi *spi)
-{
- if (spi_reset_tx_fifo(spi))
- return -EAGAIN;
- if (spi_reset_rx_fifo(spi))
- return -EAGAIN;
- return 0;
-}
-
-/*
- * spi_reset: reset spi status register and reset spi tx and rx fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset(struct wmt_spi *spi)
-{
- spi_set_reg32(spi, SPI_SR, ~0UL);
- return spi_reset_fifo(spi);
-}
-
-/*
- * spi_reset_transfer_speed: reset spi work frequency according
- * to spi_transfer
- * @spi: spi controller's driver data
- * @t: spi transfer
- */
-static void
-spi_reset_transfer_speed(struct wmt_spi *spi, struct spi_transfer *t)
-{
- if (t && t->speed_hz)
- spi_set_clock_div(spi, t->speed_hz);
-}
-
-/*
- * wmt_spi_regs_config: config spi registers according to the
- * information get from spi_device
- @spi_dev: Master side proxy for an SPI slave device
- */
-static int wmt_spi_regs_config(struct spi_device *spi_dev)
-{
- int ret = 0;
- u8 clk_mode;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *slave_info;
- struct wmt_spi_hw *hw_info;
-
- wmt_spi = spi_master_get_devdata(spi_dev->master);
- slave_info = spi_dev->controller_data;
- hw_info = wmt_spi->spi_hw_info;
-
- /* clear spi control register */
- spi_set_reg32(wmt_spi, SPI_CR, 0x00UL);
- /* clear spi status register */
- spi_set_reg32(wmt_spi, SPI_SR, ~0UL);
- /* spi cre register */
- spi_set_reg32(wmt_spi, SPI_CRE, 0x20);
-
- /* reset tx and rx fifo */
- ret = spi_reset_fifo(wmt_spi);
- if (ret)
- goto err;
- /* setting spi controller register */
- /* 1. set spi clock divider */
- spi_set_clock_div(wmt_spi, spi_dev->max_speed_hz);
- /* 2 set clock mode */
- clk_mode = (spi_dev->mode & (BIT0 | BIT1));
- spi_set_clock_mode(wmt_spi, clk_mode);
- /* 3. spi as master */
- spi_as_master(wmt_spi, 1);
- /* 4. slave selection */
- /*
- spi_setbit(wmt_spi, SPI_CR, spi_dev->chip_select << SPI_CR_SS_SHIFT);
- */
- /*for wm3465 A0*/
- spi_setbit(wmt_spi, SPI_CR, 0 << SPI_CR_SS_SHIFT);
-
- /* setting spi data format control register */
- /* 1. port mode setting */
- if (PORT_MODE_PTP == hw_info->port_mode)
- spi_setbit(wmt_spi, SPI_DFCR, SPI_DFCR_SPM_MASK);
- /* 2. spi tx/rx significant bit order */
- spi_set_bit_order(wmt_spi, spi_dev->mode);
- /* 3. ssn control setting */
- if (SSN_CTRL_PROGRAM == hw_info->ssn_ctrl) {
- if ((clk_mode & SPI_CR_CPHS_MASK) == 0) {
- dev_warn(&spi_dev->dev, "SSN_ctrl conflict with clock mode\n");
- /* do not abort now, the conflict is not a serious problem,
- driver can handle this well, so we work on */
- goto err;
- }
- spi_setbit(wmt_spi, SPI_DFCR, SPI_DFCR_SC_MASK);
- }
- return 0;
-
-err:
- dev_err(&wmt_spi->pdev->dev, "SPI config register error\n");
- return ret;
-}
-
-/*
- * wmt_spi_fifo_tx: transmit data by spi TX_FIFO.
- * @spi: spi controller's driver data
- * @tx_buf: data transmited by spi tx fifo
- * @len: tx buffers length. Note: len is not checked in this function,
- * and wmt spi fifo size is 32bytes, so caller must be sure
- * len <= 32bytes
- */
-static void
-wmt_spi_fifo_tx(struct wmt_spi *spi, const u8 *tx_buf, int len)
-{
- int i;
- /* load data to tx fifo */
- if (tx_buf) {
- for (i = 0; i < len; i++)
- spi_write_fifo(spi, SPI_TXFIFO, tx_buf[i]);
- } /* load idle data to tx fifo */else {
- for (i = 0; i < len; i++)
- spi_write_fifo(spi, SPI_TXFIFO, 0x00);
- }
-}
-
-/*
- * wmt_spi_write_read: spi transfer routine
- * @spi_dev: Master side proxy for an SPI slave device
- * @t: spi transfer
- * wmt spi transmit fifo is SPI_FIFO_SIZE(32bytes),
- * so if transmit data more than 32bytes, we need transmit
- * those data more than one time
- **/
-static int
-wmt_spi_write_read(struct spi_device *spi, struct spi_transfer *t)
-{
- int i = 0;
- const u8 *tx = t->tx_buf;
- u8 *rx = t->rx_buf;
- unsigned int cnt = t->len;
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi->master);
-
- /* reset spi first */
- if (spi_reset(wmt_spi))
- goto out;
- /* if data length more than SPI_FIFO_SIZE(32bytes) */
- while (cnt >= SPI_FIFO_SIZE) {
- /* load data form tx_buf to tx_fifo */
- wmt_spi_fifo_tx(wmt_spi, tx, SPI_FIFO_SIZE);
- /* send data */
- spi_enable(wmt_spi);
- /* waitting for send finish */
- if (spi_tx_is_finish(wmt_spi))
- goto out;
- /* data send has finished */
- spi_disable(wmt_spi);
- /* read data and stroe in rx_buf */
- if (rx) {
- for (i = 0; i < SPI_FIFO_SIZE; i++)
- *rx++ = spi_read_fifo(wmt_spi, SPI_RXFIFO);
- }
- /* check if rx finish */
- if (spi_rx_is_finish(wmt_spi))
- goto out;
- if (tx)
- tx += SPI_FIFO_SIZE;
- cnt -= SPI_FIFO_SIZE;
- if (t->speed_hz < 5*1000*1000)
- udelay(2000);
- /* reset for the next transfer */
- if (spi_reset(wmt_spi))
- goto out;
- }
- /* remain data transfer */
- if (cnt && cnt < SPI_FIFO_SIZE) {
- wmt_spi_fifo_tx(wmt_spi, tx, cnt);
- spi_enable(wmt_spi);
- if (spi_tx_is_finish(wmt_spi))
- goto out;
- spi_disable(wmt_spi);
- if (rx) {
- for (; cnt > 0; cnt--)
- *rx++ = spi_read_fifo(wmt_spi, SPI_RXFIFO);
- } else {
- for (; cnt > 0; cnt--)
- spi_read_fifo(wmt_spi, SPI_RXFIFO);
- }
- }
-out:
- return (t->len - cnt);
-}
-
-/*
- * spi_dsr_w: spi dma transmit callback function
- * @arg: point to wmt_spi
- **/
-static void spi_dsr_w(void *arg)
-{
- struct wmt_spi *spi = (struct wmt_spi *)arg;
- struct wmt_spi_dma *spi_dma = spi->spi_dma_info;
- spi_dma->tx_ack = 1;
- wake_up_interruptible(&spi_dma->tx_event);
-}
-
-/*
- * spi_dsr_r: spi dma receive callback function
- * @arg: point to wmt_spi
- **/
-static void spi_dsr_r(void *arg)
-{
- struct wmt_spi *spi = (struct wmt_spi *)arg;
- struct wmt_spi_dma *spi_dma = spi->spi_dma_info;
- spi_dma->rx_ack = 1;
- wake_up_interruptible(&spi_dma->rx_event);
-}
-
-/*
- * wmt_spi_dma_write_read: spi transfer (use DMA mode)
- * @spi_dev: Master side proxy for an SPI slave device
- * @t: spi transfer1
- **/
-static int
-wmt_spi_dma_write_read(struct spi_device *spi_dev, struct spi_transfer *t)
-{
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi_dev->master);
- struct wmt_spi_dma *spi_dma = wmt_spi->spi_dma_info;
- wait_queue_head_t *event = &spi_dma->tx_event;
- volatile int *ack = &spi_dma->tx_ack;
- unsigned int transfered_cnt = 0;
- u32 ctrl;
-
- /* spi dma transfer need cs inactive first*/
- wmt_spi_cs_inactive(spi_dev, wmt_spi);
- if (t->speed_hz > 15000000)
- spi_set_clock_div(wmt_spi, 15000000);
- ctrl = spi_get_reg32(wmt_spi, SPI_CR);
- ctrl |= SPI_CR_DRC_MASK | SPI_CR_RFTS_MASK | SPI_CR_TFTS_MASK;
- spi_set_reg32(wmt_spi, SPI_CR, ctrl);
- /* reset spi fifo */
- if (spi_reset(wmt_spi))
- goto out;
- /* tx dma buffer prepare */
- if (t->tx_buf)
- memcpy(spi_dma->io_waddr, t->tx_buf, t->len);
- /* tx dma request */
- if (wmt_request_dma(&spi_dma->tx_ch, "wmt_spi_tx",
- spi_dma->tx_config.DeviceReqType,
- spi_dsr_w, wmt_spi)) {
- dev_err(&spi_dev->dev, "SPI request TX DMA failed\n");
- goto out;
- }
- /* rx dma request and start */
- if (t->rx_buf) {
- if (wmt_request_dma(&spi_dma->rx_ch, "wmt_spi_rx",
- spi_dma->rx_config.DeviceReqType,
- spi_dsr_r, wmt_spi)) {
- dev_err(&spi_dev->dev, "SPI request RX DMA failed\n");
- goto free_tx_dma;
- }
- wmt_setup_dma(spi_dma->rx_ch, spi_dma->rx_config);
- wmt_start_dma(spi_dma->rx_ch, spi_dma->phys_raddr, 0x00, t->len);
- event = &spi_dma->rx_event;
- ack = &spi_dma->rx_ack;
- }
- /* transmit dma setup and start */
- wmt_setup_dma(spi_dma->tx_ch, spi_dma->tx_config);
- wmt_start_dma(spi_dma->tx_ch, spi_dma->phys_waddr, 0x00, t->len + 7);
- /* enable spi and active chipselect signal */
- msleep(2);
- spi_enable(wmt_spi);
- /* waitting for transmit finish */
- msleep(2);
- wmt_spi_cs_active(spi_dev, wmt_spi);
- /* waitting transfer finish */
- if (!wait_event_interruptible_timeout(*event, *ack, 100)) {
- dev_err(&spi_dev->dev, "SPI DMA transfer failed\n");
- goto out;
- }
- transfered_cnt = t->len;
- /* if RX buf is not empty, copy received data from dma to t->rx_buf */
- if (t->rx_buf) {
- memcpy(t->rx_buf, spi_dma->io_raddr, t->len);
- wmt_free_dma(spi_dma->rx_ch);
- memset(spi_dma->io_raddr, 0x00, t->len);
- }
-free_tx_dma:
- wmt_free_dma(spi_dma->tx_ch);
- memset(spi_dma->io_waddr, 0x00, t->len);
-out:
- spi_disable(wmt_spi);
- spi_dma->rx_ack = spi_dma->tx_ack = 0;
- return transfered_cnt;
-}
-
-/*
- * wmt_spi_work: wmt spi controller work queue routine function.
- * Check every message which queued in workqueue (wmt_spi->queue),
- * if all things correct, message dequeued and begin transfer routine
- * @work: work which queued in spi controller's work queue
- */
-static void wmt_spi_work(struct work_struct *work)
-{
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *spi_ctrl;
-
- wmt_spi = container_of(work, struct wmt_spi, work);
- spin_lock_irq(&wmt_spi->spinlock);
-
- while (!list_empty(&wmt_spi->queue)) {
- int status = 0;
- u8 cs_active = 0;
- struct spi_message *m = NULL;
- struct spi_transfer *t = NULL;
- struct spi_device *spi;
-
- m = container_of(wmt_spi->queue.next, struct spi_message, queue);
- spi_ctrl = m->spi->controller_data;
-
- list_del_init(&m->queue);
- spin_unlock_irq(&wmt_spi->spinlock);
-
- spi = m->spi;
- status = wmt_spi_regs_config(m->spi);
- if (status < 0)
- goto msg_done;
- /* check every transfer which queued in message,
- * if all things right, begin data transfer */
- list_for_each_entry(t, &m->transfers, transfer_list) {
- spi_reset_transfer_speed(wmt_spi, t);
-
- if (!cs_active) {
- wmt_spi_cs_active(spi, wmt_spi);
- cs_active = 1;
- }
-
- /* data transfer begins here */
- if (t->len) {
- if (wmt_spi->spi_hw_info->dma_support && m->is_dma_mapped
- && spi_ctrl->dma_en && t->len > SPI_FIFO_SIZE) {
- m->actual_length += wmt_spi_dma_write_read(m->spi, t);
- } else {
- m->actual_length += wmt_spi_write_read(m->spi, t);
- }
- }
- /* some device need this feature support */
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- /* if cs need change in next transfer, just inactive it */
- if (t->cs_change) {
- wmt_spi_cs_inactive(spi, wmt_spi);
- cs_active = 0;
- }
- }
-
-msg_done:
- if (status < 0)
- dev_err(&wmt_spi->master->dev, "SPI transfer error!\n");
- if (cs_active)
- wmt_spi_cs_inactive(spi, wmt_spi);
- m->status = status;
- if (m->complete && m->context)
- m->complete(m->context);
- spin_lock_irq(&wmt_spi->spinlock);
- }
- spin_unlock(&wmt_spi->spinlock);
-}
-
-/*
- * bits_per_word_is_support: check if spi controller can support
- * this bits_per_word type or not
- * @spi: spi controller's driver data
- * @bit_per_word: bits_per_word type will be check
- */
-static int
-bits_per_word_is_support(struct wmt_spi *spi, u8 bit_per_word)
-{
- int ret = 0;
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if ((bit_per_word != 8) && (bit_per_word != 16 )) {
- ret = -EINVAL;
- goto err;
- }
-
- if ((bit_per_word == 8) &&
- !(hw_info->bits_per_word_en & BITS8_PER_WORD_EN)) {
- ret = -EINVAL;
- goto err;
- }
-
- if ((bit_per_word == 16) &&
- !(hw_info->bits_per_word_en & BITS16_PER_WORD_EN)) {
- ret = -EINVAL;
- goto err;
- }
-err:
- return ret;
-}
-
-/*
- * speed_hz_is_support: check spi controller can support this
- * frequency or not
- * @spi: spi controller's driver data
- * @speed_hz: frequency spi controller will working with
- */
-static int speed_hz_is_support(struct wmt_spi *spi, u32 speed_hz)
-{
- int ret = 0;
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if (speed_hz < hw_info->min_freq_hz) {
- ret = -EINVAL;
- goto err;
- }
-
- if (speed_hz > hw_info->max_freq_hz) {
- ret = -EINVAL;
- }
-
-err:
- return ret;
-}
-
-/*
- * wmt_spi_transfer: check transfers queued in spi message,
- * then queued spi message in workqueue
- *@spi_dev: Master side proxy for an SPI slave device
- * @m: spi message which will be added to the queue
- */
-/* bidirectional bulk transfers
- *
- * + The transfer() method may not sleep; its main role is
- * just to add the message to the queue.
- * + For now there's no remove-from-queue operation, or
- * any other request management
- * + To a given spi_device, message queueing is pure fifo
- *
- * + The master's main job is to process its message queue,
- * selecting a chip then transferring data
- * + If there are multiple spi_device children, the i/o queue
- * arbitration algorithm is unspecified (round robin, fifo,
- * priority, reservations, preemption, etc)
- *
- * + Chipselect stays active during the entire message
- * (unless modified by spi_transfer.cs_change != 0).
- * + The message transfers use clock and SPI mode parameters
- * previously established by setup() for this device
- */
-static int
-wmt_spi_transfer(struct spi_device *spi_dev, struct spi_message *m)
-{
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi_dev->master);
- struct spi_transfer *t = NULL;
- unsigned long flags = 0;
-
- m->actual_length = 0;
- m->status = 0;
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers) || !m->complete) {
- //if (list_empty(&m->transfers)) { // for none sleep
- dev_err(&spi_dev->dev, "msg rejected: invalid message of transfer\n");
- goto msg_reject;
- }
- /* transfers members bits_per_word and speed_hz checking and setting */
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if ((!t->tx_buf) && (!t->rx_buf) && t->len) {
- dev_err(&spi_dev->dev, "msg rejected: invalid message data\n");
- goto msg_reject;
- }
-
- /* checking transfer length */
- if (t->len > wmt_spi->spi_hw_info->max_transfer_length) {
- dev_err(&spi_dev->dev, "msg rejected: transfer lenth can not be"\
- "bigger than %d, please split it into smaller chunks"\
- "and submit them separately\n",
- wmt_spi->spi_hw_info->max_transfer_length);
- goto msg_reject;
- }
-
- /* checking and resetting transfer bits_per_word */
- if (!t->bits_per_word
- || bits_per_word_is_support(wmt_spi, t->bits_per_word))
- t->bits_per_word = spi_dev->bits_per_word;
-
- /* checking and resetting transfer speed_hz */
- if (!t->speed_hz || speed_hz_is_support(wmt_spi, t->speed_hz))
- t->speed_hz = spi_dev->max_speed_hz;
- }
- spin_lock_irqsave(&wmt_spi->spinlock, flags);
- /* add this message into spi's queue */
- list_add_tail(&m->queue, &wmt_spi->queue);
- /* doing message transfer routine in spi work */
- queue_work(wmt_spi->workqueue, &wmt_spi->work);
- spin_unlock_irqrestore(&wmt_spi->spinlock, flags);
- return 0;
-
-msg_reject:
- m->status = -EINVAL;
- if (m->complete)
- m->complete(m->context);
- return -EINVAL;
-}
-
-/*
- * wmt_spi_setup: updates the device mode, bits_per_word and clocking
- * records used by a device's SPI controller; protocol code may call
- * this. This must fail if an unrecognized or unsupported mode is
- * requested.It's always safe to call this unless transfers are pending
- * on the device whose settings are being modified.
- * @spi_dev: Master side proxy for an SPI slave device
- */
-#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST)
-static int wmt_spi_setup(struct spi_device *spi_dev)
-{
- int ret = 0;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *slave_info;
- struct wmt_spi_hw *hw_info;
-
- wmt_spi = spi_master_get_devdata(spi_dev->master);
- slave_info = spi_dev->controller_data;
- hw_info = wmt_spi->spi_hw_info;
-
- /* mode checking */
- if (spi_dev->mode & ~MODEBITS) {
- dev_err(&spi_dev->dev, "SPI unsupported this mode 0x%08x\n",
- spi_dev->mode & ~MODEBITS);
- ret = -EINVAL;
- goto err;
- }
-
- /* bits_per_word checking */
- if (!spi_dev->bits_per_word)
- spi_dev->bits_per_word = slave_info->bits_per_word;
-
- if (spi_dev->bits_per_word) {
- if (bits_per_word_is_support(wmt_spi, spi_dev->bits_per_word)) {
- if (bits_per_word_is_support(wmt_spi,
- slave_info->bits_per_word)) {
- dev_err(&spi_dev->dev, "SPI unsupport %d and %dbits_per_word\n",
- spi_dev->bits_per_word, slave_info->bits_per_word);
- ret = -EINVAL;
- goto err;
- }
- spi_dev->bits_per_word = slave_info->bits_per_word;
- }
- }
-
- /* max_speed_hz checking */
- if ((spi_dev->max_speed_hz == 0) ||
- (spi_dev->max_speed_hz > hw_info->max_freq_hz))
- spi_dev->max_speed_hz = hw_info->max_freq_hz;
-
- if (spi_dev->max_speed_hz < hw_info->min_freq_hz) {
- dev_err(&spi_dev->dev, "SPI unspport speed lower than %dhz\n",
- hw_info->min_freq_hz);
- ret = -EINVAL;
- goto err;
- }
- return 0;
-
-err:
- dev_err(&spi_dev->dev, "SPI setup spi device failed!\n");
- return ret;
-}
-
-/*
- * wmt_spi_cleanup: called on module_exit to free memory
- * provided by spi_master
- * @wmt_spi: spi controller driver data
- */
-static void wmt_spi_cleanup(struct wmt_spi *wmt_spi)
-{
- if (wmt_spi->spi_hw_info)
- kfree(wmt_spi->spi_hw_info);
- wmt_spi->spi_hw_info = NULL;
-
- if (wmt_spi->spi_dma_info)
- kfree(wmt_spi->spi_dma_info);
- wmt_spi->spi_dma_info = NULL;
-}
-
-/*
- * spi_get_hw_info: get spi controller's configuration infomation
- * form platform device
- * @pdev: spi platform device structure
- */
-static inline void *spi_get_hw_info(struct platform_device *pdev)
-{
- return pdev->dev.platform_data;
-}
-
-/*
- * wmt_spi_dma_init: request spi dma memory and initialize spi dma info
- if dma supported
- * @spi: spi controller's driver data
- */
-static int wmt_spi_dma_init(struct wmt_spi *spi)
-{
- int ret = 0;
- unsigned int dma_size;
-
- if (!spi->spi_hw_info)
- goto out;
- if (!spi->spi_hw_info->dma_support)
- goto out;
- spi->spi_dma_info = kmalloc(sizeof(struct wmt_spi_dma), GFP_KERNEL);
- if (!spi->spi_dma_info) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocating dma info memory failed\n");
- goto out;
- }
- dma_size = spi->spi_hw_info->max_transfer_length;
- /* dma read config */
- spi->spi_dma_info->rx_ch = ~0UL;
- spi->spi_dma_info->rx_config.ChunkSize = SPI_DMA_CHUNK_SIZE;
- spi->spi_dma_info->rx_config.DefaultCCR = SPI_RX_DMA_CFG;
- spi->spi_dma_info->rx_config.DeviceReqType = SPI0_DMA_RX_REQ;
- spi->spi_dma_info->rx_config.MIF1addr = SPI0_BASE_ADDR + SPI_RXFIFO;
- spi->spi_dma_info->io_raddr = dma_alloc_coherent(&spi->pdev->dev,
- dma_size,
- &spi->spi_dma_info->phys_raddr,
- GFP_KERNEL | GFP_DMA);
- if (!spi->spi_dma_info->io_raddr) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocate rdma failed\n");
- goto out;
- }
- memset(spi->spi_dma_info->io_raddr, 0x00, dma_size);
- spi->spi_dma_info->rx_config.MIF0addr = (ulong)spi->spi_dma_info->io_raddr;
- init_waitqueue_head(&spi->spi_dma_info->rx_event);
- spi->spi_dma_info->rx_ack = 0;
- /* dma write config */
- spi->spi_dma_info->tx_ch = ~0UL;
- spi->spi_dma_info->tx_config.ChunkSize = SPI_DMA_CHUNK_SIZE;
- spi->spi_dma_info->tx_config.DefaultCCR = SPI_TX_DMA_CFG;
- spi->spi_dma_info->tx_config.DeviceReqType = SPI0_DMA_TX_REQ;
- spi->spi_dma_info->tx_config.MIF1addr = SPI0_BASE_ADDR + SPI_TXFIFO;
- spi->spi_dma_info->io_waddr = dma_alloc_coherent(&spi->pdev->dev,
- dma_size + 7,
- &spi->spi_dma_info->phys_waddr,
- GFP_KERNEL | GFP_DMA);
- if (!spi->spi_dma_info->io_waddr) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocate wdma failed\n");
- goto free_spi_rx_dma;
- }
- memset(spi->spi_dma_info->io_waddr, 0x00, dma_size + 7);
- spi->spi_dma_info->tx_config.MIF0addr = (ulong)spi->spi_dma_info->io_waddr;
- init_waitqueue_head(&spi->spi_dma_info->tx_event);
- spi->spi_dma_info->tx_ack = 0;
- return 0;
-
-free_spi_rx_dma:
- dma_free_coherent(&spi->pdev->dev,dma_size,spi->spi_dma_info->io_raddr,
- spi->spi_dma_info->phys_raddr);
-out:
- return ret;
-}
-
-/*
- * wmt_spi_dma_release: release spi dma memory if dma supported
- * @spi: spi controller's driver data
- */
-static void wmt_spi_dma_release(struct wmt_spi *spi)
-{
- if (!spi->spi_hw_info)
- goto out;
- if (!spi->spi_hw_info->dma_support)
- goto out;
-
- dma_free_coherent(&spi->pdev->dev,
- spi->spi_hw_info->max_transfer_length,
- spi->spi_dma_info->io_raddr,
- spi->spi_dma_info->phys_raddr);
- dma_free_coherent(&spi->pdev->dev,
- spi->spi_hw_info->max_transfer_length + 7,
- spi->spi_dma_info->io_waddr,
- spi->spi_dma_info->phys_waddr);
-out:
- return ;
-}
-
-static int __devinit wmt_spi_probe(struct platform_device *pdev)
-{
- int ret;
- struct device *dev = &pdev->dev;
- struct spi_master *master;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_hw *wmt_dev_info;
- struct resource *res;
-
- /* SPI master allocation */
- master = spi_alloc_master(dev, sizeof(struct wmt_spi));
- if (!master) {
- ret = -ENOMEM;
- dev_err(dev, "SPI master allocation failed!\n");
- goto the_end;
- }
-
- /* spi controller structure initialization */
- wmt_spi = (struct wmt_spi *)spi_master_get_devdata(master);
- memset(wmt_spi, 0x00, sizeof(struct wmt_spi));
- wmt_spi->master = spi_master_get(master);
- wmt_spi->pdev = pdev;
- wmt_dev_info = spi_get_hw_info(pdev);
- wmt_spi->spi_hw_info = kmalloc(sizeof(struct wmt_spi_hw), GFP_KERNEL);
- if (!wmt_spi->spi_hw_info) {
- dev_err(dev, "SPI allocating hardware info memory failed\n");
- ret = -ENOMEM;
- goto release_master;
- }
- memset(wmt_spi->spi_hw_info, 0x00, sizeof(struct wmt_spi_hw));
- memcpy(wmt_spi->spi_hw_info, wmt_dev_info,
- sizeof(struct wmt_spi_hw));
-
- /* spi master initialization */
- master->bus_num = pdev->id;
- master->num_chipselect = wmt_dev_info->num_chipselect;
- master->setup = wmt_spi_setup;
- master->transfer = wmt_spi_transfer;
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- platform_set_drvdata(pdev, wmt_spi);
-
- /* device resource request */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENXIO;
- dev_err(dev, "SPI getting platform resource failed\n");
- goto release_hw_info;
- }
-#if 0
- if (!request_mem_region(res->start, res->end-res->start+1, pdev->name)) {
- ret = -ENXIO;
- dev_err(dev, "SPI request mem region failed\n");
- goto release_hw_info;
- }
- wmt_spi->regs_base = ioremap(res->start, res->end - res->start + 1);
-#endif
- wmt_spi->regs_base = (void __iomem *)SPI0_BASE_ADDR;
- if (!wmt_spi->regs_base) {
- ret = -ENXIO;
- dev_err(dev, "SPI ioremap failed!\n");
- goto release_region;
- }
-
- if (wmt_dev_info->dma_support) {
- if (wmt_spi_dma_init(wmt_spi)) {
- ret = -ENXIO;
- wmt_dev_info->dma_support = 0;
- dev_err(dev, "SPI dma init failed\n");
- goto release_ioremap;
- }
- }
-
- /* work queue create */
- spin_lock_init(&wmt_spi->spinlock);
- INIT_LIST_HEAD(&wmt_spi->queue);
- INIT_WORK(&wmt_spi->work, wmt_spi_work);
- init_waitqueue_head(&wmt_spi->waitq);
- wmt_spi->workqueue = create_singlethread_workqueue("wmt_spi");
- if (NULL == wmt_spi->workqueue) {
- ret = -ENXIO;
- dev_err(dev, "SPI create workqueue failed!\n");
- goto release_dma;
- }
- /* power and clock open */
- wmt_spi_clock_enable();
-
- /* registe spi master at last */
- ret = spi_register_master(master);
- if (ret) {
- dev_err(dev, "SPI register master failed\n");
- goto release_workqueue;
- }
-
- printk(KERN_INFO "WMT EVB SPI Controlor Driver OK!\n");
- return 0;
-
-release_workqueue:
- wmt_spi_clock_disable();
- destroy_workqueue(wmt_spi->workqueue);
-release_dma:
- wmt_spi_dma_release(wmt_spi);
-release_ioremap:
- iounmap(wmt_spi->regs_base);
-release_region:
- release_mem_region(res->start, res->end - res->start + 1);
-release_hw_info:
- kfree(wmt_spi->spi_hw_info);
- platform_set_drvdata(pdev, NULL);
-release_master:
- spi_master_put(master);
-the_end:
- dev_err(dev, "WMT EVB SPI Controlor Probe Failed!\n");
- return ret;
-}
-
-static int wmt_spi_stop_queue(struct wmt_spi *spi)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&spi->spinlock, flags);
-
- while (!list_empty(&spi->queue) && limit--) {
- spin_unlock_irqrestore(&spi->spinlock, flags);
- msleep(10);
- spin_lock_irqsave(&spi->spinlock, flags);
- }
-
- if (!list_empty(&spi->queue))
- status = -EBUSY;
-
- spin_unlock_irqrestore(&spi->spinlock, flags);
-
- return status;
-}
-
-static int __devexit wmt_spi_remove(struct platform_device *pdev)
-{
- struct wmt_spi *spi;
- struct wmt_spi_hw *spi_hw_info;
- struct resource *res;
-
- spi = (struct wmt_spi *)platform_get_drvdata(pdev);
- spi_hw_info = spi_get_hw_info(pdev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- /* stop spi message queue */
- wmt_spi_stop_queue(spi);
- /* SSN inactive */
- /*
- wmt_spi_cs_inactive(spi);
- */
- spi_disable(spi);
- /* clock and power off */
- wmt_spi_clock_disable();
- /* work queue flush and destory */
- flush_workqueue(spi->workqueue);
- destroy_workqueue(spi->workqueue);
- /* dma free if dma support and enable */
- wmt_spi_dma_release(spi);
- /* irq free */
- if (spi->irq)
- free_irq(spi->irq, spi);
- /* release requested resource */
- iounmap(spi->regs_base);
- release_mem_region(res->start, res->end - res->start + 1);
- /* driver data entry reset */
- platform_set_drvdata(pdev, NULL);
- /* free memory provide by spi master */
- wmt_spi_cleanup(spi);
- /* spi master unregister and free */
- spi_unregister_master(spi->master);
- spi_master_put(spi->master);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-wmt_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- int ret = 0;
- struct wmt_spi *spi = platform_get_drvdata(pdev);
- state = state;
-
- spi_dbg("Enter\n");
- ret = wmt_spi_stop_queue(spi);
- if (ret) {
- dev_warn(&pdev->dev, "suspend wmt spi failed\n");
- return ret;
- }
- /*
- wmt_spi_cs_inactive(spi);
- */
- spi_disable(spi);
-
- spi_dbg("Exit\n");
- return 0;
-}
-
-static int wmt_spi_resume(struct platform_device *pdev)
-{
- struct wmt_spi *spi = platform_get_drvdata(pdev);
-
- spi_dbg("Enter\n");
- /* hardware reset */
- wmt_spi_clock_enable();
- /* start msg queue */
- queue_work(spi->workqueue, &spi->work);
-
- spi_dbg("Exit\n");
- return 0;
-}
-#else
-#define wmt_spi_suspend NULL
-#define wmt_spi_resume NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver wmt_spi_driver = {
- .driver = {
- .name = "wmt_spi_0",
- .owner = THIS_MODULE,
- },
- .suspend = wmt_spi_suspend,
- .resume = wmt_spi_resume,
- .remove = __devexit_p(wmt_spi_remove),
-};
-
-static int __init wmt_spi_init(void)
-{
- return platform_driver_probe(&wmt_spi_driver, wmt_spi_probe);
-}
-module_init(wmt_spi_init);
-
-static void __exit wmt_spi_exit(void)
-{
- platform_driver_unregister(&wmt_spi_driver);
-}
-module_exit(wmt_spi_exit);
-
-MODULE_AUTHOR("WonderMedia Technologies, Inc.");
-MODULE_DESCRIPTION("WMT SPI Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/spi/wmt_spi_1.c b/ANDROID_3.4.5/drivers/spi/wmt_spi_1.c
deleted file mode 100755
index 82398071..00000000
--- a/ANDROID_3.4.5/drivers/spi/wmt_spi_1.c
+++ /dev/null
@@ -1,1363 +0,0 @@
-/*++
- drivers/spi/wmt_spi_1.c
-
- Copyright (c) 2008 WonderMedia Technologies, Inc.
-
- This program is free software: you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software Foundation,
- either version 2 of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE. See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along with
- this program. If not, see <http://www.gnu.org/licenses/>.
-
- WonderMedia Technologies, Inc.
- 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
---*/
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/ioport.h>
-#include <linux/dma-mapping.h>
-#include <linux/sched.h>
-
-#include <mach/wmt_env.h>
-
-#include <mach/hardware.h>
-#include <mach/wmt_gpio.h>
-
-//#define DEBUG 1 /* debug open */
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <mach/wmt-spi.h>
-
-#ifdef DEBUG
-#define spi_dbg(fmt, args...) printk(KERN_ERR "[%s]_%d: " fmt, __func__ , __LINE__, ## args)
-#define spi_trace() printk(KERN_ERR "trace in %s %d\n", __func__, __LINE__);
-#else
-#define spi_dbg(fmt, args...)
-#define spi_trace()
-#endif
-
-#define GPIO_SPI1_MISO BIT2
-#define GPIO_SPI1_MOSI BIT3
-#define GPIO_SPI1_CLK BIT6
-#define GPIO_SPI1_SS0 BIT7
-
-#define GPIO_SPI1_SS1 BIT7
-#define GPIO_SPI1_SS2 BIT0
-#define GPIO_SPI1_SS3 BIT1
-#define MASTER 1
-
-static unsigned int pllb_input_freq = 83333;
-static bool g_use_ss0 = true;
-static bool g_use_ss1 = false;
-static bool g_use_ss2 = false;
-static bool g_use_ss3 = false;
-
-/*
- * spi_set_reg32 - write a u32 value to spi register
- * @spi: spi controller's driver data
- * @reg_offset: register's offset address
- * @val: value register will be set
- */
-static inline void
-spi_set_reg32(struct wmt_spi *spi, u32 reg_offset, u32 val)
-{
- iowrite32(val, spi->regs_base + reg_offset);
-}
-
-/*
- * spi_get_reg32 - read a u32 value from spi register
- * @spi: spi controller's driver data
- * @reg_offset: register's offset address
- */
-static inline unsigned int
-spi_get_reg32(struct wmt_spi *spi, int reg_offset)
-{
- return ioread32(spi->regs_base + reg_offset);
-}
-
-/*
- * spi_setbit: write bit1 to related register's bit
- * @spi: spi controller's driver data
- * @offset: register's offset address
- * @mask: bit setting mask
- */
-static void
-spi_setbit(struct wmt_spi *spi, u32 reg_offset, u32 mask)
-{
- u32 tmp;
- tmp = spi_get_reg32(spi, reg_offset);
- tmp |= mask;
- spi_set_reg32(spi, reg_offset, tmp);
-}
-
-/*
- * spi_clrbit: write bit0 to related register's bit
- * @spi: spi controller's driver data
- * @offset: register's offset address
- * @mask: bit setting mask
- */
-static void
-spi_clrbit(struct wmt_spi *spi, u32 reg_offset, u32 mask)
-{
- u32 tmp;
- tmp = spi_get_reg32(spi, reg_offset);
- tmp &= ~mask;
- spi_set_reg32(spi, reg_offset, tmp);
-}
-
-/*
- * spi_write_fifo: write a u8 value to spi tx fifo
- * @spi: spi controller's driver data
- * @fifo_reg: spi tx fifo register offset
- * @val: value writen to spi tx fifo
- */
-static inline void
-spi_write_fifo(struct wmt_spi *spi, u32 fifo_reg, const u8 val)
-{
- iowrite8(val, spi->regs_base + fifo_reg);
-}
-
-/*
- * spi_read_fifo: read a u8 value from spi rx fifo
- * @spi: spi controller's driver data
- * @fifo_reg: spi rx fifo register offset
- */
-static inline u8
-spi_read_fifo(struct wmt_spi *spi, u32 fifo_reg)
-{
- return ioread8(spi->regs_base + fifo_reg);
-}
-
-/*
- * wmt_spi_clock_enable: set GPIO to SPI mode, ten enable spi
- * clock from Power management module and set default spi clock
- * dividor to 0x04 as default (93Mhz)
- */
-static inline void wmt_spi_clock_enable(void)
-{
- int timeout = POLLING_SPI_REG_TIMEOUT;
-
- /*Enable SPI function and disable GPIO function for related SPI pin*/
- GPIO_CTRL_GP18_UART_BYTE_VAL &= ~(GPIO_SPI1_CLK | GPIO_SPI1_MISO |
- GPIO_SPI1_MOSI | GPIO_SPI1_SS0);
-
- /* miso/mosi : pull up
- * clk : pull down
- */
- PULL_EN_GP18_UART_BYTE_VAL |= (GPIO_SPI1_CLK | GPIO_SPI1_MISO | GPIO_SPI1_MOSI);
- PULL_CTRL_GP18_UART_BYTE_VAL |= (GPIO_SPI1_MISO |GPIO_SPI1_MOSI);
- PULL_CTRL_GP18_UART_BYTE_VAL &= ~(GPIO_SPI1_CLK);
-
- if (g_use_ss0) {
- GPIO_CTRL_GP18_UART_BYTE_VAL &= ~GPIO_SPI1_SS0;
- PULL_EN_GP18_UART_BYTE_VAL |= GPIO_SPI1_SS0;
- PULL_CTRL_GP18_UART_BYTE_VAL |= GPIO_SPI1_SS0;
- }
-
-#if 0
- if (g_use_ss1) {
- GPIO_CTRL_GP0_BYTE_VAL &= ~GPIO_SPI1_SS1;
- GPIO_PULL_EN_GP0_BYTE_VAL |= GPIO_SPI1_SS1;
- GPIO_PULL_CTRL_GP0_BYTE_VAL |= GPIO_SPI1_SS1;
- }
- if (g_use_ss2) {
- GPIO_CTRL_GP1_BYTE_VAL &= ~GPIO_SPI1_SS2;
- GPIO_PULL_EN_GP1_BYTE_VAL |= GPIO_SPI1_SS2;
- GPIO_PULL_CTRL_GP1_BYTE_VAL |= GPIO_SPI1_SS2;
- }
- if (g_use_ss3) {
- GPIO_CTRL_GP1_BYTE_VAL &= ~GPIO_SPI1_SS3;
- GPIO_PULL_EN_GP1_BYTE_VAL |= GPIO_SPI1_SS3;
- GPIO_PULL_CTRL_GP1_BYTE_VAL |= GPIO_SPI1_SS3;
- }
-#endif
-
- PIN_SHARING_SEL_4BYTE_VAL |= BIT10;
-
- /* clock open */
- auto_pll_divisor(DEV_SPI1, CLK_ENABLE, 0, 0);
- pllb_input_freq = auto_pll_divisor(DEV_SPI1, SET_DIV, 1, 100000);
- pllb_input_freq /= 1000;
-
- /* check if config successful */
- while (timeout--) {
- if (!(REG8_VAL(PMC_REG_BASE) & 0x08000000))
- return ;
- udelay(1);
- }
- printk(KERN_ERR "Enable SPI1 clock from PMC module failed\n!");
-}
-
-/*
- * wmt_spi_clock_disable: reset GPIO and disable spi clock from
- * Power management module
- */
-static inline void wmt_spi_clock_disable(void)
-{
-#if 0
- GPIO_CTRL_GP11_SPI_BYTE_VAL |= (GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_SS|
- GPIO_SPI0_MISO|
- GPIO_SPI0_SSB);
-#endif
-}
-
-/*
- * spi_is_busy: check spi controller(master) is busy or not
- * @spi: spi controller's driver data
- */
-static int spi_is_busy(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_SR) & SPI_SR_BUSY_MASK) == 0)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_enable: enable spi module
- * @spi: spi controller's driver data
- */
-static void spi_enable(struct wmt_spi *spi)
-{
- spi_setbit(spi, SPI_CR, SPI_CR_ME_MASK);
-}
-
-/*
- * spi_disable: disable spi module
- * @spi: spi controller's driver data
- */
-static void spi_disable(struct wmt_spi *spi)
-{
- if (spi_is_busy(spi)) {
- dev_warn(&spi->master->dev, "Disable spi controller failed\n");
- }
- spi_clrbit(spi, SPI_CR, SPI_CR_ME_MASK);
-}
-
-/*
- * spi_tx_is_finish: polling if data in tx fifo has been sent out
- * @spi: spi controller's driver data
- */
-static int spi_tx_is_finish(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if (spi_get_reg32(spi, SPI_SR) | SPI_SR_TFEI_MASK)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_rx_is_finish: polling if data in rx fifo has been read out
- * @spi: spi controller's driver data
- */
-static int spi_rx_is_finish(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_SR) | SPI_SR_RFEI_MASK))
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * wmt_spi_cs_active: enable chip select signal. SSN is driven
- * low to active if spi controller use SSN_CTRL_PROGRAM mode
- * @spi: spi controller's driver data
- */
-static inline void wmt_spi_cs_active(struct spi_device *spi_dev, struct wmt_spi *spi)
-{
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- /* enable SSN */
- if (hw_info->ssn_ctrl == SSN_CTRL_PROGRAM)
- spi_clrbit(spi, SPI_DFCR, SPI_DFCR_DSV_MASK | SPI_DFCR_DSE_MASK);
-}
-
-/*
- * wmt_spi_cs_inactive: disable chip select signal. A SSN is driven
- * high to inactive if spi controller use SSN_CTRL_PROGRAM mode
- * @spi: spi controller's driver data
- */
-static inline void wmt_spi_cs_inactive(struct spi_device *spi_dev, struct wmt_spi *spi)
-{
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if (hw_info->ssn_ctrl == SSN_CTRL_PROGRAM)
- spi_setbit(spi, SPI_DFCR, SPI_DFCR_DSV_MASK | SPI_DFCR_DSE_MASK);
-}
-
-/*
- * get_spi_input_freq: get spi original input frequence from power
- * management module
- */
-static unsigned int get_spi_input_freq(void)
-{
- return pllb_input_freq;
-}
-
-/*
- * spi_set_clock_div: set clock divider in spi control register,
- * if the divisor is too low or too high, set spi working
- * frequency 5Mhz as default
- * @spi: spi controller's driver data
- * @speed_hz: spi working clock frequency, unit is hz
- */
-static void spi_set_clock_div(struct wmt_spi *spi, int speed_hz)
-{
- unsigned int divisor;
- unsigned int hw_freq = get_spi_input_freq()*1000; /* KHz to Hz */
-
- spi_clrbit(spi, SPI_CR, SPI_CR_TCD_MASK);
- if (!speed_hz)
- goto err;
-
- divisor = hw_freq/(2*speed_hz);
- if (divisor < 0 || divisor > 0x7ff) /* spi cr bit(21,31), max:0x7ff */
- goto err;
-
- spi_setbit(spi, SPI_CR, divisor << SPI_CR_TCD_SHIFT);
- return ;
-
-err:
- divisor = hw_freq/(2*SPI_DFLT_FREQ);
- spi_setbit(spi, SPI_CR, divisor << SPI_CR_TCD_SHIFT);
- dev_err(&spi->master->dev, "SPI frequency %dhz not support, " \
- "set %dhz as default\n", speed_hz, SPI_DFLT_FREQ);
- return ;
-}
-
-/*
- * spi_set_bit_order: set spi redeive/transmit significant bit order
- * @spi: spi controller's driver data
- * @mode: spi device working mode
- */
-static void spi_set_bit_order(struct wmt_spi *spi, u8 mode)
-{
- if (mode & SPI_LSB_FIRST)
- spi_setbit(spi, SPI_DFCR, SPI_DFCR_RSBO_MASK | SPI_DFCR_TSBO_MASK);
-}
-
-/*
- * spi_set_clock_mode: set spi clock polarity and phase (spi clock mode)
- * @spi: spi controller's driver data
- * @clk_mode: spi clock mode
- */
-static void spi_set_clock_mode(struct wmt_spi *spi, u8 clk_mode)
-{
- spi_clrbit(spi, SPI_CR, SPI_CR_CPHS_MASK);
- if (clk_mode > SPI_CLK_MODE3)
- goto err;
- spi_setbit(spi, SPI_CR, clk_mode << SPI_CR_CPHS_SHIFT);
- return ;
-err:
- spi_setbit(spi, SPI_CR, SPI_CLK_MODE3 << SPI_CR_CPHS_SHIFT);
- dev_err(&spi->master->dev, "clock mode err, set clock mode 3 as default\n");
- return ;
-}
-
-/*
- * spi_as_master: spi master/slave select
- * @spi: spi controller's driver data
- * @is_master: if spi configured as master, is_master = 1, else is_master = 0
- */
-static void spi_as_master(struct wmt_spi *spi, u8 is_master)
-{
- if (is_master)
- spi_clrbit(spi, SPI_CR, SPI_CR_MSMS_MASK);
- else
- spi_setbit(spi, SPI_CR, SPI_CR_MSMS_MASK);
-}
-
-/*
- * spi_reset_tx_fifo: reset spi transmit fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_tx_fifo(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- spi_setbit(spi, SPI_CR, SPI_CR_TFR_MASK);
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_CR) & SPI_CR_TFR_MASK) == 0)
- return 0;
- }
- return -1;
-}
-
-/*
- * spi_reset_rx_fifo: reset spi receive fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_rx_fifo(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- spi_setbit(spi, SPI_CR, SPI_CR_RFR_MASK);
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_CR) & SPI_CR_RFR_MASK) == 0)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_reset_fifo: reset both spi transmit fifo and receive fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_fifo(struct wmt_spi *spi)
-{
- if (spi_reset_tx_fifo(spi))
- return -EAGAIN;
- if (spi_reset_rx_fifo(spi))
- return -EAGAIN;
- return 0;
-}
-
-/*
- * spi_reset: reset spi status register and reset spi tx and rx fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset(struct wmt_spi *spi)
-{
- spi_set_reg32(spi, SPI_SR, ~0UL);
- return spi_reset_fifo(spi);
-}
-
-/*
- * spi_reset_transfer_speed: reset spi work frequency according
- * to spi_transfer
- * @spi: spi controller's driver data
- * @t: spi transfer
- */
-static void
-spi_reset_transfer_speed(struct wmt_spi *spi, struct spi_transfer *t)
-{
- if (t && t->speed_hz)
- spi_set_clock_div(spi, t->speed_hz);
-}
-
-/*
- * wmt_spi_regs_config: config spi registers according to the
- * information get from spi_device
- @spi_dev: Master side proxy for an SPI slave device
- */
-static int wmt_spi_regs_config(struct spi_device *spi_dev)
-{
- int ret = 0;
- u8 clk_mode;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *slave_info;
- struct wmt_spi_hw *hw_info;
-
- wmt_spi = spi_master_get_devdata(spi_dev->master);
- slave_info = spi_dev->controller_data;
- hw_info = wmt_spi->spi_hw_info;
-
- /* clear spi control register */
- spi_set_reg32(wmt_spi, SPI_CR, 0x00UL);
- /* clear spi status register */
- spi_set_reg32(wmt_spi, SPI_SR, ~0UL);
- /* spi cre register */
- spi_set_reg32(wmt_spi, SPI_CRE, 0x20);
-
- /* reset tx and rx fifo */
- ret = spi_reset_fifo(wmt_spi);
- if (ret)
- goto err;
- /* setting spi controller register */
- /* 1. set spi clock divider */
- spi_set_clock_div(wmt_spi, spi_dev->max_speed_hz);
- /* 2 set clock mode */
- clk_mode = (spi_dev->mode & (BIT0 | BIT1));
- spi_set_clock_mode(wmt_spi, clk_mode);
- /* 3. spi as master */
- spi_as_master(wmt_spi, 1);
- /* 4. slave selection */
- /*
- spi_setbit(wmt_spi, SPI_CR, spi_dev->chip_select << SPI_CR_SS_SHIFT);
- */
- /*for wm3465 A0*/
- spi_setbit(wmt_spi, SPI_CR, 0 << SPI_CR_SS_SHIFT);
-
- /* setting spi data format control register */
- /* 1. port mode setting */
- if (PORT_MODE_PTP == hw_info->port_mode)
- spi_setbit(wmt_spi, SPI_DFCR, SPI_DFCR_SPM_MASK);
- /* 2. spi tx/rx significant bit order */
- spi_set_bit_order(wmt_spi, spi_dev->mode);
- /* 3. ssn control setting */
- if (SSN_CTRL_PROGRAM == hw_info->ssn_ctrl) {
- if ((clk_mode & SPI_CR_CPHS_MASK) == 0) {
- dev_warn(&spi_dev->dev, "SSN_ctrl conflict with clock mode\n");
- /* do not abort now, the conflict is not a serious problem,
- driver can handle this well, so we work on */
- goto err;
- }
- spi_setbit(wmt_spi, SPI_DFCR, SPI_DFCR_SC_MASK);
- }
- return 0;
-
-err:
- dev_err(&wmt_spi->pdev->dev, "SPI config register error\n");
- return ret;
-}
-
-/*
- * wmt_spi_fifo_tx: transmit data by spi TX_FIFO.
- * @spi: spi controller's driver data
- * @tx_buf: data transmited by spi tx fifo
- * @len: tx buffers length. Note: len is not checked in this function,
- * and wmt spi fifo size is 32bytes, so caller must be sure
- * len <= 32bytes
- */
-static void
-wmt_spi_fifo_tx(struct wmt_spi *spi, const u8 *tx_buf, int len)
-{
- int i;
- /* load data to tx fifo */
- if (tx_buf) {
- for (i = 0; i < len; i++)
- spi_write_fifo(spi, SPI_TXFIFO, tx_buf[i]);
- } /* load idle data to tx fifo */else {
- for (i = 0; i < len; i++)
- spi_write_fifo(spi, SPI_TXFIFO, 0x00);
- }
-}
-
-/*
- * wmt_spi_write_read: spi transfer routine
- * @spi_dev: Master side proxy for an SPI slave device
- * @t: spi transfer
- * wmt spi transmit fifo is SPI_FIFO_SIZE(32bytes),
- * so if transmit data more than 32bytes, we need transmit
- * those data more than one time
- **/
-static int
-wmt_spi_write_read(struct spi_device *spi, struct spi_transfer *t)
-{
- int i = 0;
- const u8 *tx = t->tx_buf;
- u8 *rx = t->rx_buf;
- unsigned int cnt = t->len;
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi->master);
-
- /* reset spi first */
- if (spi_reset(wmt_spi))
- goto out;
- /* if data length more than SPI_FIFO_SIZE(32bytes) */
- while (cnt >= SPI_FIFO_SIZE) {
- /* load data form tx_buf to tx_fifo */
- wmt_spi_fifo_tx(wmt_spi, tx, SPI_FIFO_SIZE);
- /* send data */
- spi_enable(wmt_spi);
- /* waitting for send finish */
- if (spi_tx_is_finish(wmt_spi))
- goto out;
- /* data send has finished */
- spi_disable(wmt_spi);
- /* read data and stroe in rx_buf */
- if (rx) {
- for (i = 0; i < SPI_FIFO_SIZE; i++)
- *rx++ = spi_read_fifo(wmt_spi, SPI_RXFIFO);
- }
- /* check if rx finish */
- if (spi_rx_is_finish(wmt_spi))
- goto out;
- if (tx)
- tx += SPI_FIFO_SIZE;
- cnt -= SPI_FIFO_SIZE;
- if (t->speed_hz < 5*1000*1000)
- udelay(2000);
- /* reset for the next transfer */
- if (spi_reset(wmt_spi))
- goto out;
- }
- /* remain data transfer */
- if (cnt && cnt < SPI_FIFO_SIZE) {
- wmt_spi_fifo_tx(wmt_spi, tx, cnt);
- spi_enable(wmt_spi);
- if (spi_tx_is_finish(wmt_spi))
- goto out;
- spi_disable(wmt_spi);
- if (rx) {
- for (; cnt > 0; cnt--)
- *rx++ = spi_read_fifo(wmt_spi, SPI_RXFIFO);
- } else {
- for (; cnt > 0; cnt--)
- spi_read_fifo(wmt_spi, SPI_RXFIFO);
- }
- }
-out:
- return (t->len - cnt);
-}
-
-/*
- * spi_dsr_w: spi dma transmit callback function
- * @arg: point to wmt_spi
- **/
-static void spi_dsr_w(void *arg)
-{
- struct wmt_spi *spi = (struct wmt_spi *)arg;
- struct wmt_spi_dma *spi_dma = spi->spi_dma_info;
- spi_dma->tx_ack = 1;
- wake_up_interruptible(&spi_dma->tx_event);
-}
-
-/*
- * spi_dsr_r: spi dma receive callback function
- * @arg: point to wmt_spi
- **/
-static void spi_dsr_r(void *arg)
-{
- struct wmt_spi *spi = (struct wmt_spi *)arg;
- struct wmt_spi_dma *spi_dma = spi->spi_dma_info;
- spi_dma->rx_ack = 1;
- wake_up_interruptible(&spi_dma->rx_event);
-}
-
-/*
- * wmt_spi_dma_write_read: spi transfer (use DMA mode)
- * @spi_dev: Master side proxy for an SPI slave device
- * @t: spi transfer1
- **/
-static int
-wmt_spi_dma_write_read(struct spi_device *spi_dev, struct spi_transfer *t)
-{
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi_dev->master);
- struct wmt_spi_dma *spi_dma = wmt_spi->spi_dma_info;
- wait_queue_head_t *event = &spi_dma->tx_event;
- volatile int *ack = &spi_dma->tx_ack;
- unsigned int transfered_cnt = 0;
- u32 ctrl;
-
- /* spi dma transfer need cs inactive first*/
- wmt_spi_cs_inactive(spi_dev, wmt_spi);
- if (t->speed_hz > 15000000)
- spi_set_clock_div(wmt_spi, 15000000);
- ctrl = spi_get_reg32(wmt_spi, SPI_CR);
- ctrl |= SPI_CR_DRC_MASK | SPI_CR_RFTS_MASK | SPI_CR_TFTS_MASK;
- spi_set_reg32(wmt_spi, SPI_CR, ctrl);
- /* reset spi fifo */
- if (spi_reset(wmt_spi))
- goto out;
- /* tx dma buffer prepare */
- if (t->tx_buf)
- memcpy(spi_dma->io_waddr, t->tx_buf, t->len);
- /* tx dma request */
- if (wmt_request_dma(&spi_dma->tx_ch, "wmt_spi_tx",
- spi_dma->tx_config.DeviceReqType,
- spi_dsr_w, wmt_spi)) {
- dev_err(&spi_dev->dev, "SPI request TX DMA failed\n");
- goto out;
- }
- /* rx dma request and start */
- if (t->rx_buf) {
- if (wmt_request_dma(&spi_dma->rx_ch, "wmt_spi_rx",
- spi_dma->rx_config.DeviceReqType,
- spi_dsr_r, wmt_spi)) {
- dev_err(&spi_dev->dev, "SPI request RX DMA failed\n");
- goto free_tx_dma;
- }
- wmt_setup_dma(spi_dma->rx_ch, spi_dma->rx_config);
- wmt_start_dma(spi_dma->rx_ch, spi_dma->phys_raddr, 0x00, t->len);
- event = &spi_dma->rx_event;
- ack = &spi_dma->rx_ack;
- }
- /* transmit dma setup and start */
- wmt_setup_dma(spi_dma->tx_ch, spi_dma->tx_config);
- wmt_start_dma(spi_dma->tx_ch, spi_dma->phys_waddr, 0x00, t->len + 7);
- /* enable spi and active chipselect signal */
- msleep(2);
- spi_enable(wmt_spi);
- /* waitting for transmit finish */
- msleep(2);
- wmt_spi_cs_active(spi_dev, wmt_spi);
- /* waitting transfer finish */
- if (!wait_event_interruptible_timeout(*event, *ack, 100)) {
- dev_err(&spi_dev->dev, "SPI DMA transfer failed\n");
- goto out;
- }
- transfered_cnt = t->len;
- /* if RX buf is not empty, copy received data from dma to t->rx_buf */
- if (t->rx_buf) {
- memcpy(t->rx_buf, spi_dma->io_raddr, t->len);
- wmt_free_dma(spi_dma->rx_ch);
- memset(spi_dma->io_raddr, 0x00, t->len);
- }
-free_tx_dma:
- wmt_free_dma(spi_dma->tx_ch);
- memset(spi_dma->io_waddr, 0x00, t->len);
-out:
- spi_disable(wmt_spi);
- spi_dma->rx_ack = spi_dma->tx_ack = 0;
- return transfered_cnt;
-}
-
-/*
- * wmt_spi_work: wmt spi controller work queue routine function.
- * Check every message which queued in workqueue (wmt_spi->queue),
- * if all things correct, message dequeued and begin transfer routine
- * @work: work which queued in spi controller's work queue
- */
-static void wmt_spi_work(struct work_struct *work)
-{
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *spi_ctrl;
-
- wmt_spi = container_of(work, struct wmt_spi, work);
- spin_lock_irq(&wmt_spi->spinlock);
-
- while (!list_empty(&wmt_spi->queue)) {
- int status = 0;
- u8 cs_active = 0;
- struct spi_message *m = NULL;
- struct spi_transfer *t = NULL;
- struct spi_device *spi;
-
- m = container_of(wmt_spi->queue.next, struct spi_message, queue);
- spi_ctrl = m->spi->controller_data;
-
- list_del_init(&m->queue);
- spin_unlock_irq(&wmt_spi->spinlock);
-
- spi = m->spi;
- status = wmt_spi_regs_config(m->spi);
- if (status < 0)
- goto msg_done;
- /* check every transfer which queued in message,
- * if all things right, begin data transfer */
- list_for_each_entry(t, &m->transfers, transfer_list) {
- spi_reset_transfer_speed(wmt_spi, t);
-
- if (!cs_active) {
- wmt_spi_cs_active(spi, wmt_spi);
- cs_active = 1;
- }
-
- /* data transfer begins here */
- if (t->len) {
- if (wmt_spi->spi_hw_info->dma_support && m->is_dma_mapped
- && spi_ctrl->dma_en && t->len > SPI_FIFO_SIZE) {
- m->actual_length += wmt_spi_dma_write_read(m->spi, t);
- } else {
- m->actual_length += wmt_spi_write_read(m->spi, t);
- }
- }
- /* some device need this feature support */
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- /* if cs need change in next transfer, just inactive it */
- if (t->cs_change) {
- wmt_spi_cs_inactive(spi, wmt_spi);
- cs_active = 0;
- }
- }
-
-msg_done:
- if (status < 0)
- dev_err(&wmt_spi->master->dev, "SPI transfer error!\n");
- if (cs_active)
- wmt_spi_cs_inactive(spi, wmt_spi);
- m->status = status;
- if (m->complete && m->context)
- m->complete(m->context);
- spin_lock_irq(&wmt_spi->spinlock);
- }
- spin_unlock(&wmt_spi->spinlock);
-}
-
-/*
- * bits_per_word_is_support: check if spi controller can support
- * this bits_per_word type or not
- * @spi: spi controller's driver data
- * @bit_per_word: bits_per_word type will be check
- */
-static int
-bits_per_word_is_support(struct wmt_spi *spi, u8 bit_per_word)
-{
- int ret = 0;
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if ((bit_per_word != 8) && (bit_per_word != 16 )) {
- ret = -EINVAL;
- goto err;
- }
-
- if ((bit_per_word == 8) &&
- !(hw_info->bits_per_word_en & BITS8_PER_WORD_EN)) {
- ret = -EINVAL;
- goto err;
- }
-
- if ((bit_per_word == 16) &&
- !(hw_info->bits_per_word_en & BITS16_PER_WORD_EN)) {
- ret = -EINVAL;
- goto err;
- }
-err:
- return ret;
-}
-
-/*
- * speed_hz_is_support: check spi controller can support this
- * frequency or not
- * @spi: spi controller's driver data
- * @speed_hz: frequency spi controller will working with
- */
-static int speed_hz_is_support(struct wmt_spi *spi, u32 speed_hz)
-{
- int ret = 0;
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if (speed_hz < hw_info->min_freq_hz) {
- ret = -EINVAL;
- goto err;
- }
-
- if (speed_hz > hw_info->max_freq_hz) {
- ret = -EINVAL;
- }
-
-err:
- return ret;
-}
-
-/*
- * wmt_spi_transfer: check transfers queued in spi message,
- * then queued spi message in workqueue
- *@spi_dev: Master side proxy for an SPI slave device
- * @m: spi message which will be added to the queue
- */
-/* bidirectional bulk transfers
- *
- * + The transfer() method may not sleep; its main role is
- * just to add the message to the queue.
- * + For now there's no remove-from-queue operation, or
- * any other request management
- * + To a given spi_device, message queueing is pure fifo
- *
- * + The master's main job is to process its message queue,
- * selecting a chip then transferring data
- * + If there are multiple spi_device children, the i/o queue
- * arbitration algorithm is unspecified (round robin, fifo,
- * priority, reservations, preemption, etc)
- *
- * + Chipselect stays active during the entire message
- * (unless modified by spi_transfer.cs_change != 0).
- * + The message transfers use clock and SPI mode parameters
- * previously established by setup() for this device
- */
-static int
-wmt_spi_transfer(struct spi_device *spi_dev, struct spi_message *m)
-{
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi_dev->master);
- struct spi_transfer *t = NULL;
- unsigned long flags = 0;
-
- m->actual_length = 0;
- m->status = 0;
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers) || !m->complete) {
- //if (list_empty(&m->transfers)) { // for none sleep
- dev_err(&spi_dev->dev, "msg rejected: invalid message of transfer\n");
- goto msg_reject;
- }
- /* transfers members bits_per_word and speed_hz checking and setting */
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if ((!t->tx_buf) && (!t->rx_buf) && t->len) {
- dev_err(&spi_dev->dev, "msg rejected: invalid message data\n");
- goto msg_reject;
- }
-
- /* checking transfer length */
- if (t->len > wmt_spi->spi_hw_info->max_transfer_length) {
- dev_err(&spi_dev->dev, "msg rejected: transfer lenth can not be"\
- "bigger than %d, please split it into smaller chunks"\
- "and submit them separately\n",
- wmt_spi->spi_hw_info->max_transfer_length);
- goto msg_reject;
- }
-
- /* checking and resetting transfer bits_per_word */
- if (!t->bits_per_word
- || bits_per_word_is_support(wmt_spi, t->bits_per_word))
- t->bits_per_word = spi_dev->bits_per_word;
-
- /* checking and resetting transfer speed_hz */
- if (!t->speed_hz || speed_hz_is_support(wmt_spi, t->speed_hz))
- t->speed_hz = spi_dev->max_speed_hz;
- }
- spin_lock_irqsave(&wmt_spi->spinlock, flags);
- /* add this message into spi's queue */
- list_add_tail(&m->queue, &wmt_spi->queue);
- /* doing message transfer routine in spi work */
- queue_work(wmt_spi->workqueue, &wmt_spi->work);
- spin_unlock_irqrestore(&wmt_spi->spinlock, flags);
- return 0;
-
-msg_reject:
- m->status = -EINVAL;
- if (m->complete)
- m->complete(m->context);
- return -EINVAL;
-}
-
-/*
- * wmt_spi_setup: updates the device mode, bits_per_word and clocking
- * records used by a device's SPI controller; protocol code may call
- * this. This must fail if an unrecognized or unsupported mode is
- * requested.It's always safe to call this unless transfers are pending
- * on the device whose settings are being modified.
- * @spi_dev: Master side proxy for an SPI slave device
- */
-#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST)
-static int wmt_spi_setup(struct spi_device *spi_dev)
-{
- int ret = 0;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *slave_info;
- struct wmt_spi_hw *hw_info;
-
- wmt_spi = spi_master_get_devdata(spi_dev->master);
- slave_info = spi_dev->controller_data;
- hw_info = wmt_spi->spi_hw_info;
-
- /* mode checking */
- if (spi_dev->mode & ~MODEBITS) {
- dev_err(&spi_dev->dev, "SPI unsupported this mode 0x%08x\n",
- spi_dev->mode & ~MODEBITS);
- ret = -EINVAL;
- goto err;
- }
-
- /* bits_per_word checking */
- if (!spi_dev->bits_per_word)
- spi_dev->bits_per_word = slave_info->bits_per_word;
-
- if (spi_dev->bits_per_word) {
- if (bits_per_word_is_support(wmt_spi, spi_dev->bits_per_word)) {
- if (bits_per_word_is_support(wmt_spi,
- slave_info->bits_per_word)) {
- dev_err(&spi_dev->dev, "SPI unsupport %d and %dbits_per_word\n",
- spi_dev->bits_per_word, slave_info->bits_per_word);
- ret = -EINVAL;
- goto err;
- }
- spi_dev->bits_per_word = slave_info->bits_per_word;
- }
- }
-
- /* max_speed_hz checking */
- if ((spi_dev->max_speed_hz == 0) ||
- (spi_dev->max_speed_hz > hw_info->max_freq_hz))
- spi_dev->max_speed_hz = hw_info->max_freq_hz;
-
- if (spi_dev->max_speed_hz < hw_info->min_freq_hz) {
- dev_err(&spi_dev->dev, "SPI unspport speed lower than %dhz\n",
- hw_info->min_freq_hz);
- ret = -EINVAL;
- goto err;
- }
- return 0;
-
-err:
- dev_err(&spi_dev->dev, "SPI setup spi device failed!\n");
- return ret;
-}
-
-/*
- * wmt_spi_cleanup: called on module_exit to free memory
- * provided by spi_master
- * @wmt_spi: spi controller driver data
- */
-static void wmt_spi_cleanup(struct wmt_spi *wmt_spi)
-{
- if (wmt_spi->spi_hw_info)
- kfree(wmt_spi->spi_hw_info);
- wmt_spi->spi_hw_info = NULL;
-
- if (wmt_spi->spi_dma_info)
- kfree(wmt_spi->spi_dma_info);
- wmt_spi->spi_dma_info = NULL;
-}
-
-/*
- * spi_get_hw_info: get spi controller's configuration infomation
- * form platform device
- * @pdev: spi platform device structure
- */
-static inline void *spi_get_hw_info(struct platform_device *pdev)
-{
- return pdev->dev.platform_data;
-}
-
-/*
- * wmt_spi_dma_init: request spi dma memory and initialize spi dma info
- if dma supported
- * @spi: spi controller's driver data
- */
-static int wmt_spi_dma_init(struct wmt_spi *spi)
-{
- int ret = 0;
- unsigned int dma_size;
-
- if (!spi->spi_hw_info)
- goto out;
- if (!spi->spi_hw_info->dma_support)
- goto out;
- spi->spi_dma_info = kmalloc(sizeof(struct wmt_spi_dma), GFP_KERNEL);
- if (!spi->spi_dma_info) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocating dma info memory failed\n");
- goto out;
- }
- dma_size = spi->spi_hw_info->max_transfer_length;
- /* dma read config */
- spi->spi_dma_info->rx_ch = ~0UL;
- spi->spi_dma_info->rx_config.ChunkSize = SPI_DMA_CHUNK_SIZE;
- spi->spi_dma_info->rx_config.DefaultCCR = SPI_RX_DMA_CFG;
- spi->spi_dma_info->rx_config.DeviceReqType = SPI0_DMA_RX_REQ;
- spi->spi_dma_info->rx_config.MIF1addr = SPI0_BASE_ADDR + SPI_RXFIFO;
- spi->spi_dma_info->io_raddr = dma_alloc_coherent(&spi->pdev->dev,
- dma_size,
- &spi->spi_dma_info->phys_raddr,
- GFP_KERNEL | GFP_DMA);
- if (!spi->spi_dma_info->io_raddr) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocate rdma failed\n");
- goto out;
- }
- memset(spi->spi_dma_info->io_raddr, 0x00, dma_size);
- spi->spi_dma_info->rx_config.MIF0addr = (ulong)spi->spi_dma_info->io_raddr;
- init_waitqueue_head(&spi->spi_dma_info->rx_event);
- spi->spi_dma_info->rx_ack = 0;
- /* dma write config */
- spi->spi_dma_info->tx_ch = ~0UL;
- spi->spi_dma_info->tx_config.ChunkSize = SPI_DMA_CHUNK_SIZE;
- spi->spi_dma_info->tx_config.DefaultCCR = SPI_TX_DMA_CFG;
- spi->spi_dma_info->tx_config.DeviceReqType = SPI0_DMA_TX_REQ;
- spi->spi_dma_info->tx_config.MIF1addr = SPI0_BASE_ADDR + SPI_TXFIFO;
- spi->spi_dma_info->io_waddr = dma_alloc_coherent(&spi->pdev->dev,
- dma_size + 7,
- &spi->spi_dma_info->phys_waddr,
- GFP_KERNEL | GFP_DMA);
- if (!spi->spi_dma_info->io_waddr) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocate wdma failed\n");
- goto free_spi_rx_dma;
- }
- memset(spi->spi_dma_info->io_waddr, 0x00, dma_size + 7);
- spi->spi_dma_info->tx_config.MIF0addr = (ulong)spi->spi_dma_info->io_waddr;
- init_waitqueue_head(&spi->spi_dma_info->tx_event);
- spi->spi_dma_info->tx_ack = 0;
- return 0;
-
-free_spi_rx_dma:
- dma_free_coherent(&spi->pdev->dev,dma_size,spi->spi_dma_info->io_raddr,
- spi->spi_dma_info->phys_raddr);
-out:
- return ret;
-}
-
-/*
- * wmt_spi_dma_release: release spi dma memory if dma supported
- * @spi: spi controller's driver data
- */
-static void wmt_spi_dma_release(struct wmt_spi *spi)
-{
- if (!spi->spi_hw_info)
- goto out;
- if (!spi->spi_hw_info->dma_support)
- goto out;
-
- dma_free_coherent(&spi->pdev->dev,
- spi->spi_hw_info->max_transfer_length,
- spi->spi_dma_info->io_raddr,
- spi->spi_dma_info->phys_raddr);
- dma_free_coherent(&spi->pdev->dev,
- spi->spi_hw_info->max_transfer_length + 7,
- spi->spi_dma_info->io_waddr,
- spi->spi_dma_info->phys_waddr);
-out:
- return ;
-}
-
-static int __devinit wmt_spi_probe(struct platform_device *pdev)
-{
- int ret;
- struct device *dev = &pdev->dev;
- struct spi_master *master;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_hw *wmt_dev_info;
- struct resource *res;
-
- /* SPI master allocation */
- master = spi_alloc_master(dev, sizeof(struct wmt_spi));
- if (!master) {
- ret = -ENOMEM;
- dev_err(dev, "SPI master allocation failed!\n");
- goto the_end;
- }
-
- /* spi controller structure initialization */
- wmt_spi = (struct wmt_spi *)spi_master_get_devdata(master);
- memset(wmt_spi, 0x00, sizeof(struct wmt_spi));
- wmt_spi->master = spi_master_get(master);
- wmt_spi->pdev = pdev;
- wmt_dev_info = spi_get_hw_info(pdev);
- wmt_spi->spi_hw_info = kmalloc(sizeof(struct wmt_spi_hw), GFP_KERNEL);
- if (!wmt_spi->spi_hw_info) {
- dev_err(dev, "SPI allocating hardware info memory failed\n");
- ret = -ENOMEM;
- goto release_master;
- }
- memset(wmt_spi->spi_hw_info, 0x00, sizeof(struct wmt_spi_hw));
- memcpy(wmt_spi->spi_hw_info, wmt_dev_info,
- sizeof(struct wmt_spi_hw));
-
- /* spi master initialization */
- master->bus_num = pdev->id;
- master->num_chipselect = wmt_dev_info->num_chipselect;
- master->setup = wmt_spi_setup;
- master->transfer = wmt_spi_transfer;
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- platform_set_drvdata(pdev, wmt_spi);
-
- /* device resource request */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENXIO;
- dev_err(dev, "SPI getting platform resource failed\n");
- goto release_hw_info;
- }
-#if 0
- if (!request_mem_region(res->start, res->end-res->start+1, pdev->name)) {
- ret = -ENXIO;
- dev_err(dev, "SPI request mem region failed\n");
- goto release_hw_info;
- }
- wmt_spi->regs_base = ioremap(res->start, res->end - res->start + 1);
-#endif
- wmt_spi->regs_base = (void __iomem *)SPI1_BASE_ADDR;
- if (!wmt_spi->regs_base) {
- ret = -ENXIO;
- dev_err(dev, "SPI ioremap failed!\n");
- goto release_region;
- }
-
- if (wmt_dev_info->dma_support) {
- if (wmt_spi_dma_init(wmt_spi)) {
- ret = -ENXIO;
- wmt_dev_info->dma_support = 0;
- dev_err(dev, "SPI dma init failed\n");
- goto release_ioremap;
- }
- }
-
- /* work queue create */
- spin_lock_init(&wmt_spi->spinlock);
- INIT_LIST_HEAD(&wmt_spi->queue);
- INIT_WORK(&wmt_spi->work, wmt_spi_work);
- init_waitqueue_head(&wmt_spi->waitq);
- wmt_spi->workqueue = create_singlethread_workqueue("wmt_spi");
- if (NULL == wmt_spi->workqueue) {
- ret = -ENXIO;
- dev_err(dev, "SPI create workqueue failed!\n");
- goto release_dma;
- }
- /* power and clock open */
- wmt_spi_clock_enable();
-
- /* registe spi master at last */
- ret = spi_register_master(master);
- if (ret) {
- dev_err(dev, "SPI register master failed\n");
- goto release_workqueue;
- }
-
- printk(KERN_INFO "WMT EVB SPI Controlor Driver OK!\n");
- return 0;
-
-release_workqueue:
- wmt_spi_clock_disable();
- destroy_workqueue(wmt_spi->workqueue);
-release_dma:
- wmt_spi_dma_release(wmt_spi);
-release_ioremap:
- iounmap(wmt_spi->regs_base);
-release_region:
- release_mem_region(res->start, res->end - res->start + 1);
-release_hw_info:
- kfree(wmt_spi->spi_hw_info);
- platform_set_drvdata(pdev, NULL);
-release_master:
- spi_master_put(master);
-the_end:
- dev_err(dev, "WMT EVB SPI Controlor Probe Failed!\n");
- return ret;
-}
-
-static int wmt_spi_stop_queue(struct wmt_spi *spi)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&spi->spinlock, flags);
-
- while (!list_empty(&spi->queue) && limit--) {
- spin_unlock_irqrestore(&spi->spinlock, flags);
- msleep(10);
- spin_lock_irqsave(&spi->spinlock, flags);
- }
-
- if (!list_empty(&spi->queue))
- status = -EBUSY;
-
- spin_unlock_irqrestore(&spi->spinlock, flags);
-
- return status;
-}
-
-static int __devexit wmt_spi_remove(struct platform_device *pdev)
-{
- struct wmt_spi *spi;
- struct wmt_spi_hw *spi_hw_info;
- struct resource *res;
-
- spi = (struct wmt_spi *)platform_get_drvdata(pdev);
- spi_hw_info = spi_get_hw_info(pdev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- /* stop spi message queue */
- wmt_spi_stop_queue(spi);
- /* SSN inactive */
- /*
- wmt_spi_cs_inactive(spi);
- */
- spi_disable(spi);
- /* clock and power off */
- wmt_spi_clock_disable();
- /* work queue flush and destory */
- flush_workqueue(spi->workqueue);
- destroy_workqueue(spi->workqueue);
- /* dma free if dma support and enable */
- wmt_spi_dma_release(spi);
- /* irq free */
- if (spi->irq)
- free_irq(spi->irq, spi);
- /* release requested resource */
- iounmap(spi->regs_base);
- release_mem_region(res->start, res->end - res->start + 1);
- /* driver data entry reset */
- platform_set_drvdata(pdev, NULL);
- /* free memory provide by spi master */
- wmt_spi_cleanup(spi);
- /* spi master unregister and free */
- spi_unregister_master(spi->master);
- spi_master_put(spi->master);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-wmt_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- int ret = 0;
- struct wmt_spi *spi = platform_get_drvdata(pdev);
- state = state;
-
- spi_dbg("Enter\n");
- ret = wmt_spi_stop_queue(spi);
- if (ret) {
- dev_warn(&pdev->dev, "suspend wmt spi failed\n");
- return ret;
- }
- /*
- wmt_spi_cs_inactive(spi);
- */
- spi_disable(spi);
-
- spi_dbg("Exit\n");
- return 0;
-}
-
-static int wmt_spi_resume(struct platform_device *pdev)
-{
- struct wmt_spi *spi = platform_get_drvdata(pdev);
-
- spi_dbg("Enter\n");
- /* hardware reset */
- wmt_spi_clock_enable();
- /* start msg queue */
- queue_work(spi->workqueue, &spi->work);
-
- spi_dbg("Exit\n");
- return 0;
-}
-#else
-#define wmt_spi_suspend NULL
-#define wmt_spi_resume NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver wmt_spi_driver = {
- .driver = {
- .name = "wmt_spi_1",
- .owner = THIS_MODULE,
- },
- .suspend = wmt_spi_suspend,
- .resume = wmt_spi_resume,
- .remove = __devexit_p(wmt_spi_remove),
-};
-
-static int parse_spi1_param(void)
-{
- char buf[64];
- size_t l = sizeof(buf);
- int uart_spi_sel = 0;
-
- if (wmt_getsyspara("wmt.spi1.param", buf, &l) == 0) {
- sscanf(buf, "%d", &uart_spi_sel);
- }
-
- pr_info("spi1 %s.\n", uart_spi_sel == MASTER ? "available" : "invalid");
- return (uart_spi_sel == MASTER);
-}
-
-static int __init wmt_spi_init(void)
-{
- return (parse_spi1_param()) ?
- platform_driver_probe(&wmt_spi_driver, wmt_spi_probe) : 0;
-}
-module_init(wmt_spi_init);
-
-static void __exit wmt_spi_exit(void)
-{
- platform_driver_unregister(&wmt_spi_driver);
-}
-module_exit(wmt_spi_exit);
-
-MODULE_AUTHOR("WonderMedia Technologies, Inc.");
-MODULE_DESCRIPTION("WMT SPI Controller Driver");
-MODULE_LICENSE("GPL");