Browse Source

Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6

* 'next-spi' of git://git.secretlab.ca/git/linux-2.6: (77 commits)
  spi/omap: Fix DMA API usage in OMAP MCSPI driver
  spi/imx: correct the test on platform_get_irq() return value
  spi/topcliff: Typo fix threhold to threshold
  spi/dw_spi Typo change diable to disable.
  spi/fsl_espi: change the read behaviour of the SPIRF
  spi/mpc52xx-psc-spi: move probe/remove to proper sections
  spi/dw_spi: add DMA support
  spi/dw_spi: change to EXPORT_SYMBOL_GPL for exported APIs
  spi/dw_spi: Fix too short timeout in spi polling loop
  spi/pl022: convert running variable
  spi/pl022: convert busy flag to a bool
  spi/pl022: pass the returned sglen to the DMA engine
  spi/pl022: map the buffers on the DMA engine
  spi/topcliff_pch: Fix data transfer issue
  spi/imx: remove autodetection
  spi/pxa2xx: pass of_node to spi device and set a parent device
  spi/pxa2xx: Modify RX-Tresh instead of busy-loop for the remaining RX bytes.
  spi/pxa2xx: Add chipselect support for Sodaville
  spi/pxa2xx: Consider CE4100's FIFO depth
  spi/pxa2xx: Add CE4100 support
  ...
Linus Torvalds 14 years ago
parent
commit
021db8e2bd
45 changed files with 1496 additions and 1248 deletions
  1. 2 2
      Documentation/spi/pxa2xx
  2. 1 6
      arch/arm/mach-davinci/dm355.c
  3. 0 6
      arch/arm/mach-davinci/dm365.c
  4. 46 6
      arch/arm/mach-davinci/include/mach/spi.h
  5. 1 1
      arch/arm/mach-pxa/cm-x255.c
  6. 1 1
      arch/arm/mach-pxa/cm-x270.c
  7. 1 1
      arch/arm/mach-pxa/corgi.c
  8. 1 1
      arch/arm/mach-pxa/devices.c
  9. 1 1
      arch/arm/mach-pxa/em-x270.c
  10. 1 1
      arch/arm/mach-pxa/hx4700.c
  11. 1 1
      arch/arm/mach-pxa/icontrol.c
  12. 0 47
      arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
  13. 1 1
      arch/arm/mach-pxa/littleton.c
  14. 1 1
      arch/arm/mach-pxa/lubbock.c
  15. 1 1
      arch/arm/mach-pxa/pcm027.c
  16. 1 1
      arch/arm/mach-pxa/poodle.c
  17. 1 2
      arch/arm/mach-pxa/spitz.c
  18. 1 1
      arch/arm/mach-pxa/stargate2.c
  19. 1 1
      arch/arm/mach-pxa/tosa.c
  20. 0 1
      arch/arm/mach-pxa/trizeps4.c
  21. 1 1
      arch/arm/mach-pxa/z2.c
  22. 1 1
      arch/arm/mach-pxa/zeus.c
  23. 1 1
      arch/arm/plat-pxa/ssp.c
  24. 17 21
      drivers/spi/Kconfig
  25. 3 3
      drivers/spi/Makefile
  26. 26 30
      drivers/spi/amba-pl022.c
  27. 435 662
      drivers/spi/davinci_spi.c
  28. 32 20
      drivers/spi/dw_spi.c
  29. 223 0
      drivers/spi/dw_spi_mid.c
  30. 14 6
      drivers/spi/dw_spi_pci.c
  31. 15 20
      drivers/spi/mpc52xx_psc_spi.c
  32. 3 8
      drivers/spi/omap2_mcspi.c
  33. 134 56
      drivers/spi/pxa2xx_spi.c
  34. 201 0
      drivers/spi/pxa2xx_spi_pci.c
  35. 3 29
      drivers/spi/spi_imx.c
  36. 1 1
      drivers/spi/spi_nuc900.c
  37. 6 6
      drivers/spi/spi_topcliff_pch.c
  38. 114 19
      drivers/spi/xilinx_spi.c
  39. 0 32
      drivers/spi/xilinx_spi.h
  40. 0 133
      drivers/spi/xilinx_spi_of.c
  41. 0 102
      drivers/spi/xilinx_spi_pltfm.c
  42. 31 8
      include/linux/pxa2xx_ssp.h
  43. 19 5
      include/linux/spi/dw_spi.h
  44. 152 0
      include/linux/spi/pxa2xx_spi.h
  45. 1 1
      sound/soc/pxa/pxa-ssp.c

+ 2 - 2
Documentation/spi/pxa2xx

@@ -19,7 +19,7 @@ Declaring PXA2xx Master Controllers
 -----------------------------------
 -----------------------------------
 Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
 Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
 "platform device".  The master configuration is passed to the driver via a table
 "platform device".  The master configuration is passed to the driver via a table
-found in arch/arm/mach-pxa/include/mach/pxa2xx_spi.h:
+found in include/linux/spi/pxa2xx_spi.h:
 
 
 struct pxa2xx_spi_master {
 struct pxa2xx_spi_master {
 	enum pxa_ssp_type ssp_type;
 	enum pxa_ssp_type ssp_type;
@@ -94,7 +94,7 @@ using the "spi_board_info" structure found in "linux/spi/spi.h". See
 
 
 Each slave device attached to the PXA must provide slave specific configuration
 Each slave device attached to the PXA must provide slave specific configuration
 information via the structure "pxa2xx_spi_chip" found in
 information via the structure "pxa2xx_spi_chip" found in
-"arch/arm/mach-pxa/include/mach/pxa2xx_spi.h".  The pxa2xx_spi master controller driver
+"include/linux/spi/pxa2xx_spi.h".  The pxa2xx_spi master controller driver
 will uses the configuration whenever the driver communicates with the slave
 will uses the configuration whenever the driver communicates with the slave
 device. All fields are optional.
 device. All fields are optional.
 
 

+ 1 - 6
arch/arm/mach-davinci/dm355.c

@@ -412,12 +412,7 @@ static struct resource dm355_spi0_resources[] = {
 static struct davinci_spi_platform_data dm355_spi0_pdata = {
 static struct davinci_spi_platform_data dm355_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
 	.num_chipselect = 2,
-	.clk_internal	= 1,
-	.cs_hold	= 1,
-	.intr_level	= 0,
-	.poll_mode	= 1,	/* 0 -> interrupt mode 1-> polling mode */
-	.c2tdelay	= 0,
-	.t2cdelay	= 0,
+	.cshold_bug	= true,
 };
 };
 static struct platform_device dm355_spi0_device = {
 static struct platform_device dm355_spi0_device = {
 	.name = "spi_davinci",
 	.name = "spi_davinci",

+ 0 - 6
arch/arm/mach-davinci/dm365.c

@@ -625,12 +625,6 @@ static u64 dm365_spi0_dma_mask = DMA_BIT_MASK(32);
 static struct davinci_spi_platform_data dm365_spi0_pdata = {
 static struct davinci_spi_platform_data dm365_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
 	.num_chipselect = 2,
-	.clk_internal	= 1,
-	.cs_hold	= 1,
-	.intr_level	= 0,
-	.poll_mode	= 1,	/* 0 -> interrupt mode 1-> polling mode */
-	.c2tdelay	= 0,
-	.t2cdelay	= 0,
 };
 };
 
 
 static struct resource dm365_spi0_resources[] = {
 static struct resource dm365_spi0_resources[] = {

+ 46 - 6
arch/arm/mach-davinci/include/mach/spi.h

@@ -19,26 +19,66 @@
 #ifndef __ARCH_ARM_DAVINCI_SPI_H
 #ifndef __ARCH_ARM_DAVINCI_SPI_H
 #define __ARCH_ARM_DAVINCI_SPI_H
 #define __ARCH_ARM_DAVINCI_SPI_H
 
 
+#define SPI_INTERN_CS	0xFF
+
 enum {
 enum {
 	SPI_VERSION_1, /* For DM355/DM365/DM6467 */
 	SPI_VERSION_1, /* For DM355/DM365/DM6467 */
 	SPI_VERSION_2, /* For DA8xx */
 	SPI_VERSION_2, /* For DA8xx */
 };
 };
 
 
+/**
+ * davinci_spi_platform_data - Platform data for SPI master device on DaVinci
+ *
+ * @version:	version of the SPI IP. Different DaVinci devices have slightly
+ *		varying versions of the same IP.
+ * @num_chipselect: number of chipselects supported by this SPI master
+ * @intr_line:	interrupt line used to connect the SPI IP to the ARM interrupt
+ *		controller withn the SoC. Possible values are 0 and 1.
+ * @chip_sel:	list of GPIOs which can act as chip-selects for the SPI.
+ *		SPI_INTERN_CS denotes internal SPI chip-select. Not necessary
+ *		to populate if all chip-selects are internal.
+ * @cshold_bug:	set this to true if the SPI controller on your chip requires
+ *		a write to CSHOLD bit in between transfers (like in DM355).
+ */
 struct davinci_spi_platform_data {
 struct davinci_spi_platform_data {
 	u8	version;
 	u8	version;
 	u8	num_chipselect;
 	u8	num_chipselect;
+	u8	intr_line;
+	u8	*chip_sel;
+	bool	cshold_bug;
+};
+
+/**
+ * davinci_spi_config - Per-chip-select configuration for SPI slave devices
+ *
+ * @wdelay:	amount of delay between transmissions. Measured in number of
+ *		SPI module clocks.
+ * @odd_parity:	polarity of parity flag at the end of transmit data stream.
+ *		0 - odd parity, 1 - even parity.
+ * @parity_enable: enable transmission of parity at end of each transmit
+ *		data stream.
+ * @io_type:	type of IO transfer. Choose between polled, interrupt and DMA.
+ * @timer_disable: disable chip-select timers (setup and hold)
+ * @c2tdelay:	chip-select setup time. Measured in number of SPI module clocks.
+ * @t2cdelay:	chip-select hold time. Measured in number of SPI module clocks.
+ * @t2edelay:	transmit data finished to SPI ENAn pin inactive time. Measured
+ *		in number of SPI clocks.
+ * @c2edelay:	chip-select active to SPI ENAn signal active time. Measured in
+ *		number of SPI clocks.
+ */
+struct davinci_spi_config {
 	u8	wdelay;
 	u8	wdelay;
 	u8	odd_parity;
 	u8	odd_parity;
 	u8	parity_enable;
 	u8	parity_enable;
-	u8	wait_enable;
+#define SPI_IO_TYPE_INTR	0
+#define SPI_IO_TYPE_POLL	1
+#define SPI_IO_TYPE_DMA		2
+	u8	io_type;
 	u8	timer_disable;
 	u8	timer_disable;
-	u8	clk_internal;
-	u8	cs_hold;
-	u8	intr_level;
-	u8	poll_mode;
-	u8	use_dma;
 	u8	c2tdelay;
 	u8	c2tdelay;
 	u8	t2cdelay;
 	u8	t2cdelay;
+	u8	t2edelay;
+	u8	c2edelay;
 };
 };
 
 
 #endif	/* __ARCH_ARM_DAVINCI_SPI_H */
 #endif	/* __ARCH_ARM_DAVINCI_SPI_H */

+ 1 - 1
arch/arm/mach-pxa/cm-x255.c

@@ -17,13 +17,13 @@
 #include <linux/mtd/nand-gpio.h>
 #include <linux/mtd/nand-gpio.h>
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 
 
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/map.h>
 
 
 #include <mach/pxa25x.h>
 #include <mach/pxa25x.h>
-#include <mach/pxa2xx_spi.h>
 
 
 #include "generic.h"
 #include "generic.h"
 
 

+ 1 - 1
arch/arm/mach-pxa/cm-x270.c

@@ -19,12 +19,12 @@
 #include <video/mbxfb.h>
 #include <video/mbxfb.h>
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/libertas_spi.h>
 
 
 #include <mach/pxa27x.h>
 #include <mach/pxa27x.h>
 #include <mach/ohci.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <mach/mmc.h>
-#include <mach/pxa2xx_spi.h>
 
 
 #include "generic.h"
 #include "generic.h"
 
 

+ 1 - 1
arch/arm/mach-pxa/corgi.c

@@ -28,6 +28,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/corgi_lcd.h>
 #include <linux/spi/corgi_lcd.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/input/matrix_keypad.h>
 #include <video/w100fb.h>
 #include <video/w100fb.h>
@@ -48,7 +49,6 @@
 #include <mach/irda.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/udc.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/corgi.h>
 #include <mach/corgi.h>
 #include <mach/sharpsl_pm.h>
 #include <mach/sharpsl_pm.h>
 
 

+ 1 - 1
arch/arm/mach-pxa/devices.c

@@ -3,6 +3,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
+#include <linux/spi/pxa2xx_spi.h>
 
 
 #include <asm/pmu.h>
 #include <asm/pmu.h>
 #include <mach/udc.h>
 #include <mach/udc.h>
@@ -12,7 +13,6 @@
 #include <mach/irda.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
 #include <mach/ohci.h>
 #include <plat/pxa27x_keypad.h>
 #include <plat/pxa27x_keypad.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/camera.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <mach/audio.h>
 #include <mach/hardware.h>
 #include <mach/hardware.h>

+ 1 - 1
arch/arm/mach-pxa/em-x270.c

@@ -26,6 +26,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
 #include <linux/spi/tdo24m.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/libertas_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/power_supply.h>
 #include <linux/power_supply.h>
 #include <linux/apm-emulation.h>
 #include <linux/apm-emulation.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
@@ -46,7 +47,6 @@
 #include <plat/pxa27x_keypad.h>
 #include <plat/pxa27x_keypad.h>
 #include <plat/i2c.h>
 #include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/camera.h>
-#include <mach/pxa2xx_spi.h>
 
 
 #include "generic.h"
 #include "generic.h"
 #include "devices.h"
 #include "devices.h"

+ 1 - 1
arch/arm/mach-pxa/hx4700.c

@@ -33,6 +33,7 @@
 #include <linux/regulator/max1586.h>
 #include <linux/regulator/max1586.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/usb/gpio_vbus.h>
 
 
 #include <mach/hardware.h>
 #include <mach/hardware.h>
@@ -43,7 +44,6 @@
 #include <mach/hx4700.h>
 #include <mach/hx4700.h>
 #include <plat/i2c.h>
 #include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/irda.h>
-#include <mach/pxa2xx_spi.h>
 
 
 #include <video/platform_lcd.h>
 #include <video/platform_lcd.h>
 #include <video/w100fb.h>
 #include <video/w100fb.h>

+ 1 - 1
arch/arm/mach-pxa/icontrol.c

@@ -24,7 +24,7 @@
 #include <mach/mxm8x10.h>
 #include <mach/mxm8x10.h>
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
-#include <mach/pxa2xx_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/can/platform/mcp251x.h>
 #include <linux/can/platform/mcp251x.h>
 
 
 #include "generic.h"
 #include "generic.h"

+ 0 - 47
arch/arm/mach-pxa/include/mach/pxa2xx_spi.h

@@ -1,47 +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.
- */
-
-#ifndef PXA2XX_SPI_H_
-#define PXA2XX_SPI_H_
-
-#define PXA2XX_CS_ASSERT (0x01)
-#define PXA2XX_CS_DEASSERT (0x02)
-
-/* device.platform_data for SSP controller devices */
-struct pxa2xx_spi_master {
-	u32 clock_enable;
-	u16 num_chipselect;
-	u8 enable_dma;
-};
-
-/* spi_board_info.controller_data for SPI slave devices,
- * copied to spi_device.platform_data ... mostly for dma tuning
- */
-struct pxa2xx_spi_chip {
-	u8 tx_threshold;
-	u8 rx_threshold;
-	u8 dma_burst_size;
-	u32 timeout;
-	u8 enable_loopback;
-	int gpio_cs;
-	void (*cs_control)(u32 command);
-};
-
-extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
-
-#endif /*PXA2XX_SPI_H_*/

+ 1 - 1
arch/arm/mach-pxa/littleton.c

@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/smc91x.h>
 #include <linux/smc91x.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
@@ -42,7 +43,6 @@
 #include <mach/pxa300.h>
 #include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/mmc.h>
-#include <mach/pxa2xx_spi.h>
 #include <plat/pxa27x_keypad.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/littleton.h>
 #include <mach/littleton.h>
 #include <plat/i2c.h>
 #include <plat/i2c.h>

+ 1 - 1
arch/arm/mach-pxa/lubbock.c

@@ -25,7 +25,7 @@
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/ads7846.h>
-#include <mach/pxa2xx_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 
 
 #include <asm/setup.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/memory.h>

+ 1 - 1
arch/arm/mach-pxa/pcm027.c

@@ -25,12 +25,12 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/max7301.h>
 #include <linux/spi/max7301.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
 
 
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
 #include <mach/pxa27x.h>
 #include <mach/pxa27x.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/pcm027.h>
 #include <mach/pcm027.h>
 #include "generic.h"
 #include "generic.h"
 
 

+ 1 - 1
arch/arm/mach-pxa/poodle.c

@@ -25,6 +25,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/ads7846.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/mtd/sharpsl.h>
 
 
 #include <mach/hardware.h>
 #include <mach/hardware.h>
@@ -43,7 +44,6 @@
 #include <mach/irda.h>
 #include <mach/irda.h>
 #include <mach/poodle.h>
 #include <mach/poodle.h>
 #include <mach/pxafb.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
 #include <plat/i2c.h>
 #include <plat/i2c.h>
 
 
 #include <asm/hardware/scoop.h>
 #include <asm/hardware/scoop.h>

+ 1 - 2
arch/arm/mach-pxa/spitz.c

@@ -23,7 +23,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/corgi_lcd.h>
 #include <linux/spi/corgi_lcd.h>
-#include <linux/mtd/physmap.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/machine.h>
@@ -42,7 +42,6 @@
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/ohci.h>
 #include <mach/pxafb.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/spitz.h>
 #include <mach/spitz.h>
 #include <mach/sharpsl_pm.h>
 #include <mach/sharpsl_pm.h>
 #include <mach/smemc.h>
 #include <mach/smemc.h>

+ 1 - 1
arch/arm/mach-pxa/stargate2.c

@@ -46,11 +46,11 @@
 #include <plat/i2c.h>
 #include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/udc.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/smemc.h>
 #include <mach/smemc.h>
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mfd/da903x.h>
 #include <linux/mfd/da903x.h>
 #include <linux/sht15.h>
 #include <linux/sht15.h>
 
 

+ 1 - 1
arch/arm/mach-pxa/tosa.c

@@ -32,6 +32,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/pda_power.h>
 #include <linux/pda_power.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/input/matrix_keypad.h>
 
 
 #include <asm/setup.h>
 #include <asm/setup.h>
@@ -44,7 +45,6 @@
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
 #include <mach/tosa_bt.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/audio.h>
 #include <mach/audio.h>
 #include <mach/smemc.h>
 #include <mach/smemc.h>
 
 

+ 0 - 1
arch/arm/mach-pxa/trizeps4.c

@@ -40,7 +40,6 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/flash.h>
 
 
 #include <mach/pxa27x.h>
 #include <mach/pxa27x.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/trizeps4.h>
 #include <mach/trizeps4.h>
 #include <mach/audio.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/pxafb.h>

+ 1 - 1
arch/arm/mach-pxa/z2.c

@@ -20,6 +20,7 @@
 #include <linux/z2_battery.h>
 #include <linux/z2_battery.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/lms283gf05.h>
 #include <linux/spi/lms283gf05.h>
 #include <linux/power_supply.h>
 #include <linux/power_supply.h>
@@ -38,7 +39,6 @@
 #include <mach/pxafb.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
 #include <plat/pxa27x_keypad.h>
-#include <mach/pxa2xx_spi.h>
 
 
 #include <plat/i2c.h>
 #include <plat/i2c.h>
 
 

+ 1 - 1
arch/arm/mach-pxa/zeus.c

@@ -20,6 +20,7 @@
 #include <linux/dm9000.h>
 #include <linux/dm9000.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/host.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/physmap.h>
@@ -41,7 +42,6 @@
 #include <mach/pxa27x-udc.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
 #include <mach/mfp-pxa27x.h>
 #include <mach/mfp-pxa27x.h>
 #include <mach/pm.h>
 #include <mach/pm.h>
 #include <mach/audio.h>
 #include <mach/audio.h>

+ 1 - 1
arch/arm/plat-pxa/ssp.c

@@ -28,11 +28,11 @@
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/io.h>
 #include <linux/io.h>
 
 
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/hardware.h>
-#include <plat/ssp.h>
 
 
 static DEFINE_MUTEX(ssp_lock);
 static DEFINE_MUTEX(ssp_lock);
 static LIST_HEAD(ssp_list);
 static LIST_HEAD(ssp_list);

+ 17 - 21
drivers/spi/Kconfig

@@ -111,11 +111,14 @@ config SPI_COLDFIRE_QSPI
 	  will be called coldfire_qspi.
 	  will be called coldfire_qspi.
 
 
 config SPI_DAVINCI
 config SPI_DAVINCI
-	tristate "SPI controller driver for DaVinci/DA8xx SoC's"
+	tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
 	depends on SPI_MASTER && ARCH_DAVINCI
 	depends on SPI_MASTER && ARCH_DAVINCI
 	select SPI_BITBANG
 	select SPI_BITBANG
 	help
 	help
-	  SPI master controller for DaVinci and DA8xx SPI modules.
+	  SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
+
+	  This driver can also be built as a module. The module will be called
+	  davinci_spi.
 
 
 config SPI_EP93XX
 config SPI_EP93XX
 	tristate "Cirrus Logic EP93xx SPI controller"
 	tristate "Cirrus Logic EP93xx SPI controller"
@@ -267,12 +270,15 @@ config SPI_PPC4xx
 
 
 config SPI_PXA2XX
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
 	tristate "PXA2xx SSP SPI master"
-	depends on ARCH_PXA && EXPERIMENTAL
-	select PXA_SSP
+	depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
+	select PXA_SSP if ARCH_PXA
 	help
 	help
-	  This enables using a PXA2xx 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.
+	  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_S3C24XX
 config SPI_S3C24XX
 	tristate "Samsung S3C24XX series SPI"
 	tristate "Samsung S3C24XX series SPI"
@@ -353,7 +359,6 @@ config SPI_XILINX
 	tristate "Xilinx SPI controller common module"
 	tristate "Xilinx SPI controller common module"
 	depends on HAS_IOMEM && EXPERIMENTAL
 	depends on HAS_IOMEM && EXPERIMENTAL
 	select SPI_BITBANG
 	select SPI_BITBANG
-	select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
 	help
 	help
 	  This exposes the SPI controller IP from the Xilinx EDK.
 	  This exposes the SPI controller IP from the Xilinx EDK.
 
 
@@ -362,19 +367,6 @@ config SPI_XILINX
 
 
 	  Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
 	  Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
 
 
-config SPI_XILINX_OF
-	tristate "Xilinx SPI controller OF device"
-	depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE)
-	help
-	  This is the OF driver for the SPI controller IP from the Xilinx EDK.
-
-config SPI_XILINX_PLTFM
-	tristate "Xilinx SPI controller platform device"
-	depends on SPI_XILINX
-	help
-	  This is the platform driver for the SPI controller IP
-	  from the Xilinx EDK.
-
 config SPI_NUC900
 config SPI_NUC900
 	tristate "Nuvoton NUC900 series SPI"
 	tristate "Nuvoton NUC900 series SPI"
 	depends on ARCH_W90X900 && EXPERIMENTAL
 	depends on ARCH_W90X900 && EXPERIMENTAL
@@ -396,6 +388,10 @@ config SPI_DW_PCI
 	tristate "PCI interface driver for DW SPI core"
 	tristate "PCI interface driver for DW SPI core"
 	depends on SPI_DESIGNWARE && PCI
 	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
 config SPI_DW_MMIO
 	tristate "Memory-mapped io interface driver for DW SPI core"
 	tristate "Memory-mapped io interface driver for DW SPI core"
 	depends on SPI_DESIGNWARE && HAVE_CLK
 	depends on SPI_DESIGNWARE && HAVE_CLK

+ 3 - 3
drivers/spi/Makefile

@@ -17,13 +17,15 @@ obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= coldfire_qspi.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= coldfire_qspi.o
 obj-$(CONFIG_SPI_DAVINCI)		+= davinci_spi.o
 obj-$(CONFIG_SPI_DAVINCI)		+= davinci_spi.o
 obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.o
 obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_pci.o
+obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_midpci.o
+dw_spi_midpci-objs			:= dw_spi_pci.o dw_spi_mid.o
 obj-$(CONFIG_SPI_DW_MMIO)		+= dw_spi_mmio.o
 obj-$(CONFIG_SPI_DW_MMIO)		+= dw_spi_mmio.o
 obj-$(CONFIG_SPI_EP93XX)		+= ep93xx_spi.o
 obj-$(CONFIG_SPI_EP93XX)		+= ep93xx_spi.o
 obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
 obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
+obj-$(CONFIG_SPI_PXA2XX_PCI)		+= pxa2xx_spi_pci.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
@@ -43,8 +45,6 @@ obj-$(CONFIG_SPI_TEGRA)			+= spi_tegra.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
-obj-$(CONFIG_SPI_XILINX_OF)		+= xilinx_spi_of.o
-obj-$(CONFIG_SPI_XILINX_PLTFM)		+= xilinx_spi_pltfm.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o

+ 26 - 30
drivers/spi/amba-pl022.c

@@ -252,11 +252,6 @@
 #define STATE_DONE			((void *) 2)
 #define STATE_DONE			((void *) 2)
 #define STATE_ERROR			((void *) -1)
 #define STATE_ERROR			((void *) -1)
 
 
-/*
- * Queue State
- */
-#define QUEUE_RUNNING			(0)
-#define QUEUE_STOPPED			(1)
 /*
 /*
  * SSP State - Whether Enabled or Disabled
  * SSP State - Whether Enabled or Disabled
  */
  */
@@ -344,7 +339,7 @@ struct vendor_data {
  * @lock: spinlock to syncronise access to driver data
  * @lock: spinlock to syncronise access to driver data
  * @workqueue: a workqueue on which any spi_message request is queued
  * @workqueue: a workqueue on which any spi_message request is queued
  * @busy: workqueue is busy
  * @busy: workqueue is busy
- * @run: workqueue is running
+ * @running: workqueue is running
  * @pump_transfers: Tasklet used in Interrupt Transfer mode
  * @pump_transfers: Tasklet used in Interrupt Transfer mode
  * @cur_msg: Pointer to current spi_message being processed
  * @cur_msg: Pointer to current spi_message being processed
  * @cur_transfer: Pointer to current spi_transfer
  * @cur_transfer: Pointer to current spi_transfer
@@ -369,8 +364,8 @@ struct pl022 {
 	struct work_struct		pump_messages;
 	struct work_struct		pump_messages;
 	spinlock_t			queue_lock;
 	spinlock_t			queue_lock;
 	struct list_head		queue;
 	struct list_head		queue;
-	int				busy;
-	int				run;
+	bool				busy;
+	bool				running;
 	/* Message transfer pump */
 	/* Message transfer pump */
 	struct tasklet_struct		pump_transfers;
 	struct tasklet_struct		pump_transfers;
 	struct spi_message		*cur_msg;
 	struct spi_message		*cur_msg;
@@ -782,9 +777,9 @@ static void *next_transfer(struct pl022 *pl022)
 static void unmap_free_dma_scatter(struct pl022 *pl022)
 static void unmap_free_dma_scatter(struct pl022 *pl022)
 {
 {
 	/* Unmap and free the SG tables */
 	/* Unmap and free the SG tables */
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+	dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+	dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
 		     pl022->sgt_rx.nents, DMA_FROM_DEVICE);
 		     pl022->sgt_rx.nents, DMA_FROM_DEVICE);
 	sg_free_table(&pl022->sgt_rx);
 	sg_free_table(&pl022->sgt_rx);
 	sg_free_table(&pl022->sgt_tx);
 	sg_free_table(&pl022->sgt_tx);
@@ -917,7 +912,7 @@ static int configure_dma(struct pl022 *pl022)
 	};
 	};
 	unsigned int pages;
 	unsigned int pages;
 	int ret;
 	int ret;
-	int sglen;
+	int rx_sglen, tx_sglen;
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 	struct dma_async_tx_descriptor *rxdesc;
 	struct dma_async_tx_descriptor *rxdesc;
@@ -956,7 +951,7 @@ static int configure_dma(struct pl022 *pl022)
 		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		break;
 		break;
 	case WRITING_U32:
 	case WRITING_U32:
-		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;;
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		break;
 		break;
 	}
 	}
 
 
@@ -991,20 +986,20 @@ static int configure_dma(struct pl022 *pl022)
 			  pl022->cur_transfer->len, &pl022->sgt_tx);
 			  pl022->cur_transfer->len, &pl022->sgt_tx);
 
 
 	/* Map DMA buffers */
 	/* Map DMA buffers */
-	sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+	rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
 			   pl022->sgt_rx.nents, DMA_FROM_DEVICE);
 			   pl022->sgt_rx.nents, DMA_FROM_DEVICE);
-	if (!sglen)
+	if (!rx_sglen)
 		goto err_rx_sgmap;
 		goto err_rx_sgmap;
 
 
-	sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+	tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl,
 			   pl022->sgt_tx.nents, DMA_TO_DEVICE);
 			   pl022->sgt_tx.nents, DMA_TO_DEVICE);
-	if (!sglen)
+	if (!tx_sglen)
 		goto err_tx_sgmap;
 		goto err_tx_sgmap;
 
 
 	/* Send both scatterlists */
 	/* Send both scatterlists */
 	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
 	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
 				      pl022->sgt_rx.sgl,
 				      pl022->sgt_rx.sgl,
-				      pl022->sgt_rx.nents,
+				      rx_sglen,
 				      DMA_FROM_DEVICE,
 				      DMA_FROM_DEVICE,
 				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!rxdesc)
 	if (!rxdesc)
@@ -1012,7 +1007,7 @@ static int configure_dma(struct pl022 *pl022)
 
 
 	txdesc = txchan->device->device_prep_slave_sg(txchan,
 	txdesc = txchan->device->device_prep_slave_sg(txchan,
 				      pl022->sgt_tx.sgl,
 				      pl022->sgt_tx.sgl,
-				      pl022->sgt_tx.nents,
+				      tx_sglen,
 				      DMA_TO_DEVICE,
 				      DMA_TO_DEVICE,
 				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!txdesc)
 	if (!txdesc)
@@ -1040,10 +1035,10 @@ err_txdesc:
 	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
 	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
 err_rxdesc:
 err_rxdesc:
 	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
 	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+	dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 err_tx_sgmap:
 err_tx_sgmap:
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+	dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
 		     pl022->sgt_tx.nents, DMA_FROM_DEVICE);
 		     pl022->sgt_tx.nents, DMA_FROM_DEVICE);
 err_rx_sgmap:
 err_rx_sgmap:
 	sg_free_table(&pl022->sgt_tx);
 	sg_free_table(&pl022->sgt_tx);
@@ -1460,8 +1455,8 @@ static void pump_messages(struct work_struct *work)
 
 
 	/* Lock queue and check for queue work */
 	/* Lock queue and check for queue work */
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 	spin_lock_irqsave(&pl022->queue_lock, flags);
-	if (list_empty(&pl022->queue) || pl022->run == QUEUE_STOPPED) {
-		pl022->busy = 0;
+	if (list_empty(&pl022->queue) || !pl022->running) {
+		pl022->busy = false;
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return;
 		return;
 	}
 	}
@@ -1475,7 +1470,7 @@ static void pump_messages(struct work_struct *work)
 	    list_entry(pl022->queue.next, struct spi_message, queue);
 	    list_entry(pl022->queue.next, struct spi_message, queue);
 
 
 	list_del_init(&pl022->cur_msg->queue);
 	list_del_init(&pl022->cur_msg->queue);
-	pl022->busy = 1;
+	pl022->busy = true;
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 
 
 	/* Initial message state */
 	/* Initial message state */
@@ -1507,8 +1502,8 @@ static int __init init_queue(struct pl022 *pl022)
 	INIT_LIST_HEAD(&pl022->queue);
 	INIT_LIST_HEAD(&pl022->queue);
 	spin_lock_init(&pl022->queue_lock);
 	spin_lock_init(&pl022->queue_lock);
 
 
-	pl022->run = QUEUE_STOPPED;
-	pl022->busy = 0;
+	pl022->running = false;
+	pl022->busy = false;
 
 
 	tasklet_init(&pl022->pump_transfers,
 	tasklet_init(&pl022->pump_transfers,
 			pump_transfers,	(unsigned long)pl022);
 			pump_transfers,	(unsigned long)pl022);
@@ -1529,12 +1524,12 @@ static int start_queue(struct pl022 *pl022)
 
 
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 
 
-	if (pl022->run == QUEUE_RUNNING || pl022->busy) {
+	if (pl022->running || pl022->busy) {
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 
 
-	pl022->run = QUEUE_RUNNING;
+	pl022->running = true;
 	pl022->cur_msg = NULL;
 	pl022->cur_msg = NULL;
 	pl022->cur_transfer = NULL;
 	pl022->cur_transfer = NULL;
 	pl022->cur_chip = NULL;
 	pl022->cur_chip = NULL;
@@ -1566,7 +1561,8 @@ static int stop_queue(struct pl022 *pl022)
 
 
 	if (!list_empty(&pl022->queue) || pl022->busy)
 	if (!list_empty(&pl022->queue) || pl022->busy)
 		status = -EBUSY;
 		status = -EBUSY;
-	else pl022->run = QUEUE_STOPPED;
+	else
+		pl022->running = false;
 
 
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 
 
@@ -1684,7 +1680,7 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
 
 
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 
 
-	if (pl022->run == QUEUE_STOPPED) {
+	if (!pl022->running) {
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return -ESHUTDOWN;
 		return -ESHUTDOWN;
 	}
 	}
@@ -1693,7 +1689,7 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
 	msg->state = STATE_START;
 	msg->state = STATE_START;
 
 
 	list_add_tail(&msg->queue, &pl022->queue);
 	list_add_tail(&msg->queue, &pl022->queue);
-	if (pl022->run == QUEUE_RUNNING && !pl022->busy)
+	if (pl022->running && !pl022->busy)
 		queue_work(pl022->workqueue, &pl022->pump_messages);
 		queue_work(pl022->workqueue, &pl022->pump_messages);
 
 
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);

File diff suppressed because it is too large
+ 435 - 662
drivers/spi/davinci_spi.c


+ 32 - 20
drivers/spi/dw_spi.c

@@ -164,20 +164,23 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
 
 
 static void wait_till_not_busy(struct dw_spi *dws)
 static void wait_till_not_busy(struct dw_spi *dws)
 {
 {
-	unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);
+	unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
 
 
 	while (time_before(jiffies, end)) {
 	while (time_before(jiffies, end)) {
 		if (!(dw_readw(dws, sr) & SR_BUSY))
 		if (!(dw_readw(dws, sr) & SR_BUSY))
 			return;
 			return;
+		cpu_relax();
 	}
 	}
 	dev_err(&dws->master->dev,
 	dev_err(&dws->master->dev,
-		"DW SPI: Status keeps busy for 1000us after a read/write!\n");
+		"DW SPI: Status keeps busy for 5000us after a read/write!\n");
 }
 }
 
 
 static void flush(struct dw_spi *dws)
 static void flush(struct dw_spi *dws)
 {
 {
-	while (dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+	while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) {
 		dw_readw(dws, dr);
 		dw_readw(dws, dr);
+		cpu_relax();
+	}
 
 
 	wait_till_not_busy(dws);
 	wait_till_not_busy(dws);
 }
 }
@@ -285,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws)
  */
  */
 static int map_dma_buffers(struct dw_spi *dws)
 static int map_dma_buffers(struct dw_spi *dws)
 {
 {
-	if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited
-		|| !dws->cur_chip->enable_dma)
+	if (!dws->cur_msg->is_dma_mapped
+		|| !dws->dma_inited
+		|| !dws->cur_chip->enable_dma
+		|| !dws->dma_ops)
 		return 0;
 		return 0;
 
 
 	if (dws->cur_transfer->tx_dma)
 	if (dws->cur_transfer->tx_dma)
@@ -338,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char *msg)
 	tasklet_schedule(&dws->pump_transfers);
 	tasklet_schedule(&dws->pump_transfers);
 }
 }
 
 
-static void transfer_complete(struct dw_spi *dws)
+void dw_spi_xfer_done(struct dw_spi *dws)
 {
 {
 	/* Update total byte transfered return count actual bytes read */
 	/* Update total byte transfered return count actual bytes read */
 	dws->cur_msg->actual_length += dws->len;
 	dws->cur_msg->actual_length += dws->len;
@@ -353,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws)
 	} else
 	} else
 		tasklet_schedule(&dws->pump_transfers);
 		tasklet_schedule(&dws->pump_transfers);
 }
 }
+EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
 {
@@ -384,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 		if (dws->tx_end > dws->tx)
 		if (dws->tx_end > dws->tx)
 			spi_umask_intr(dws, SPI_INT_TXEI);
 			spi_umask_intr(dws, SPI_INT_TXEI);
 		else
 		else
-			transfer_complete(dws);
+			dw_spi_xfer_done(dws);
 	}
 	}
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
@@ -419,11 +425,7 @@ static void poll_transfer(struct dw_spi *dws)
 	 */
 	 */
 	dws->read(dws);
 	dws->read(dws);
 
 
-	transfer_complete(dws);
-}
-
-static void dma_transfer(struct dw_spi *dws, int cs_change)
-{
+	dw_spi_xfer_done(dws);
 }
 }
 
 
 static void pump_transfers(unsigned long data)
 static void pump_transfers(unsigned long data)
@@ -592,7 +594,7 @@ static void pump_transfers(unsigned long data)
 		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
 		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
 		spi_chip_sel(dws, spi->chip_select);
 		spi_chip_sel(dws, spi->chip_select);
 
 
-		/* Set the interrupt mask, for poll mode just diable all int */
+		/* Set the interrupt mask, for poll mode just disable all int */
 		spi_mask_intr(dws, 0xff);
 		spi_mask_intr(dws, 0xff);
 		if (imask)
 		if (imask)
 			spi_umask_intr(dws, imask);
 			spi_umask_intr(dws, imask);
@@ -605,7 +607,7 @@ static void pump_transfers(unsigned long data)
 	}
 	}
 
 
 	if (dws->dma_mapped)
 	if (dws->dma_mapped)
-		dma_transfer(dws, cs_change);
+		dws->dma_ops->dma_transfer(dws, cs_change);
 
 
 	if (chip->poll_mode)
 	if (chip->poll_mode)
 		poll_transfer(dws);
 		poll_transfer(dws);
@@ -901,11 +903,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
 	master->setup = dw_spi_setup;
 	master->setup = dw_spi_setup;
 	master->transfer = dw_spi_transfer;
 	master->transfer = dw_spi_transfer;
 
 
-	dws->dma_inited = 0;
-
 	/* Basic HW init */
 	/* Basic HW init */
 	spi_hw_init(dws);
 	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 */
 	/* Initial and start queue */
 	ret = init_queue(dws);
 	ret = init_queue(dws);
 	if (ret) {
 	if (ret) {
@@ -930,6 +938,8 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
 
 
 err_queue_alloc:
 err_queue_alloc:
 	destroy_queue(dws);
 	destroy_queue(dws);
+	if (dws->dma_ops && dws->dma_ops->dma_exit)
+		dws->dma_ops->dma_exit(dws);
 err_diable_hw:
 err_diable_hw:
 	spi_enable_chip(dws, 0);
 	spi_enable_chip(dws, 0);
 	free_irq(dws->irq, dws);
 	free_irq(dws->irq, dws);
@@ -938,7 +948,7 @@ err_free_master:
 exit:
 exit:
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(dw_spi_add_host);
+EXPORT_SYMBOL_GPL(dw_spi_add_host);
 
 
 void __devexit dw_spi_remove_host(struct dw_spi *dws)
 void __devexit dw_spi_remove_host(struct dw_spi *dws)
 {
 {
@@ -954,6 +964,8 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws)
 		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
 		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
 			"complete, message memory not freed\n");
 			"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);
 	spi_enable_chip(dws, 0);
 	/* Disable clk */
 	/* Disable clk */
 	spi_set_clk(dws, 0);
 	spi_set_clk(dws, 0);
@@ -962,7 +974,7 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws)
 	/* Disconnect from the SPI framework */
 	/* Disconnect from the SPI framework */
 	spi_unregister_master(dws->master);
 	spi_unregister_master(dws->master);
 }
 }
-EXPORT_SYMBOL(dw_spi_remove_host);
+EXPORT_SYMBOL_GPL(dw_spi_remove_host);
 
 
 int dw_spi_suspend_host(struct dw_spi *dws)
 int dw_spi_suspend_host(struct dw_spi *dws)
 {
 {
@@ -975,7 +987,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)
 	spi_set_clk(dws, 0);
 	spi_set_clk(dws, 0);
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(dw_spi_suspend_host);
+EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
 
 
 int dw_spi_resume_host(struct dw_spi *dws)
 int dw_spi_resume_host(struct dw_spi *dws)
 {
 {
@@ -987,7 +999,7 @@ int dw_spi_resume_host(struct dw_spi *dws)
 		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
 		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(dw_spi_resume_host);
+EXPORT_SYMBOL_GPL(dw_spi_resume_host);
 
 
 MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
 MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
 MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
 MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");

+ 223 - 0
drivers/spi/dw_spi_mid.c

@@ -0,0 +1,223 @@
+/*
+ * dw_spi_mid.c - 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/spi/dw_spi.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, dmardlr, 0xf);
+		dw_writew(dws, dmatdlr, 0x10);
+		if (dws->tx_dma)
+			dma_ctrl |= 0x2;
+		if (dws->rx_dma)
+			dma_ctrl |= 0x1;
+		dw_writew(dws, 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_TO_DEVICE;
+	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;
+
+	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 = txchan->device->device_prep_slave_sg(txchan,
+				&dws->tx_sgl,
+				1,
+				DMA_TO_DEVICE,
+				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_FROM_DEVICE;
+	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;
+
+	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 = rxchan->device->device_prep_slave_sg(rxchan,
+				&dws->rx_sgl,
+				1,
+				DMA_FROM_DEVICE,
+				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)
+{
+	u32 *clk_reg, 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;
+}

+ 14 - 6
drivers/spi/dw_spi_pci.c

@@ -1,5 +1,5 @@
 /*
 /*
- * mrst_spi_pci.c - PCI interface driver for DW SPI Core
+ * dw_spi_pci.c - PCI interface driver for DW SPI Core
  *
  *
  * Copyright (c) 2009, Intel Corporation.
  * Copyright (c) 2009, Intel Corporation.
  *
  *
@@ -26,8 +26,8 @@
 #define DRIVER_NAME "dw_spi_pci"
 #define DRIVER_NAME "dw_spi_pci"
 
 
 struct dw_spi_pci {
 struct dw_spi_pci {
-	struct pci_dev		*pdev;
-	struct dw_spi		dws;
+	struct pci_dev	*pdev;
+	struct dw_spi	dws;
 };
 };
 
 
 static int __devinit spi_pci_probe(struct pci_dev *pdev,
 static int __devinit spi_pci_probe(struct pci_dev *pdev,
@@ -72,9 +72,17 @@ static int __devinit spi_pci_probe(struct pci_dev *pdev,
 	dws->parent_dev = &pdev->dev;
 	dws->parent_dev = &pdev->dev;
 	dws->bus_num = 0;
 	dws->bus_num = 0;
 	dws->num_cs = 4;
 	dws->num_cs = 4;
-	dws->max_freq = 25000000;	/* for Moorestwon */
 	dws->irq = pdev->irq;
 	dws->irq = pdev->irq;
-	dws->fifo_len = 40;		/* FIFO has 40 words buffer */
+
+	/*
+	 * 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);
 	ret = dw_spi_add_host(dws);
 	if (ret)
 	if (ret)
@@ -140,7 +148,7 @@ static int spi_resume(struct pci_dev *pdev)
 #endif
 #endif
 
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
 static const struct pci_device_id pci_ids[] __devinitdata = {
-	/* Intel Moorestown platform SPI controller 0 */
+	/* Intel MID platform SPI controller 0 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
 	{},
 	{},
 };
 };

+ 15 - 20
drivers/spi/mpc52xx_psc_spi.c

@@ -363,7 +363,7 @@ static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
 }
 }
 
 
 /* bus_num is used only for the case dev->platform_data == NULL */
 /* bus_num is used only for the case dev->platform_data == NULL */
-static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+static int __devinit mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
 				u32 size, unsigned int irq, s16 bus_num)
 				u32 size, unsigned int irq, s16 bus_num)
 {
 {
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -450,22 +450,7 @@ free_master:
 	return ret;
 	return ret;
 }
 }
 
 
-static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
-{
-	struct spi_master *master = dev_get_drvdata(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 int __init mpc52xx_psc_spi_of_probe(struct platform_device *op,
+static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op,
 	const struct of_device_id *match)
 	const struct of_device_id *match)
 {
 {
 	const u32 *regaddr_p;
 	const u32 *regaddr_p;
@@ -495,9 +480,19 @@ static int __init mpc52xx_psc_spi_of_probe(struct platform_device *op,
 				irq_of_parse_and_map(op->dev.of_node, 0), id);
 				irq_of_parse_and_map(op->dev.of_node, 0), id);
 }
 }
 
 
-static int __exit mpc52xx_psc_spi_of_remove(struct platform_device *op)
+static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
 {
 {
-	return mpc52xx_psc_spi_do_remove(&op->dev);
+	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[] = {
 static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
@@ -510,7 +505,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
 
 
 static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
 static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
 	.probe = mpc52xx_psc_spi_of_probe,
 	.probe = mpc52xx_psc_spi_of_probe,
-	.remove = __exit_p(mpc52xx_psc_spi_of_remove),
+	.remove = __devexit_p(mpc52xx_psc_spi_of_remove),
 	.driver = {
 	.driver = {
 		.name = "mpc52xx-psc-spi",
 		.name = "mpc52xx-psc-spi",
 		.owner = THIS_MODULE,
 		.owner = THIS_MODULE,

+ 3 - 8
drivers/spi/omap2_mcspi.c

@@ -397,7 +397,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 
 
 	if (tx != NULL) {
 	if (tx != NULL) {
 		wait_for_completion(&mcspi_dma->dma_tx_completion);
 		wait_for_completion(&mcspi_dma->dma_tx_completion);
-		dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+		dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE);
 
 
 		/* for TX_ONLY mode, be sure all words have shifted out */
 		/* for TX_ONLY mode, be sure all words have shifted out */
 		if (rx == NULL) {
 		if (rx == NULL) {
@@ -412,7 +412,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 
 
 	if (rx != NULL) {
 	if (rx != NULL) {
 		wait_for_completion(&mcspi_dma->dma_rx_completion);
 		wait_for_completion(&mcspi_dma->dma_rx_completion);
-		dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+		dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE);
 		omap2_mcspi_set_enable(spi, 0);
 		omap2_mcspi_set_enable(spi, 0);
 
 
 		if (l & OMAP2_MCSPI_CHCONF_TURBO) {
 		if (l & OMAP2_MCSPI_CHCONF_TURBO) {
@@ -1025,11 +1025,6 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
 		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
 		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
 			continue;
 			continue;
 
 
-		/* Do DMA mapping "early" for better error reporting and
-		 * dcache use.  Note that if dma_unmap_single() ever starts
-		 * to do real work on ARM, we'd need to clean up mappings
-		 * for previous transfers on *ALL* exits of this loop...
-		 */
 		if (tx_buf != NULL) {
 		if (tx_buf != NULL) {
 			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
 			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
 					len, DMA_TO_DEVICE);
 					len, DMA_TO_DEVICE);
@@ -1046,7 +1041,7 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
 				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
 				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
 						'R', len);
 						'R', len);
 				if (tx_buf != NULL)
 				if (tx_buf != NULL)
-					dma_unmap_single(NULL, t->tx_dma,
+					dma_unmap_single(&spi->dev, t->tx_dma,
 							len, DMA_TO_DEVICE);
 							len, DMA_TO_DEVICE);
 				return -EINVAL;
 				return -EINVAL;
 			}
 			}

+ 134 - 56
drivers/spi/pxa2xx_spi.c

@@ -23,11 +23,11 @@
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 
 
@@ -35,9 +35,6 @@
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
 #include <asm/delay.h>
 
 
-#include <mach/dma.h>
-#include <plat/ssp.h>
-#include <mach/pxa2xx_spi.h>
 
 
 MODULE_AUTHOR("Stephen Street");
 MODULE_AUTHOR("Stephen Street");
 MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
 MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
@@ -46,8 +43,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 
 
 #define MAX_BUSES 3
 #define MAX_BUSES 3
 
 
-#define RX_THRESH_DFLT 	8
-#define TX_THRESH_DFLT 	8
 #define TIMOUT_DFLT		1000
 #define TIMOUT_DFLT		1000
 
 
 #define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
 #define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
@@ -168,7 +163,10 @@ struct chip_data {
 	u8 enable_dma;
 	u8 enable_dma;
 	u8 bits_per_word;
 	u8 bits_per_word;
 	u32 speed_hz;
 	u32 speed_hz;
-	int gpio_cs;
+	union {
+		int gpio_cs;
+		unsigned int frm;
+	};
 	int gpio_cs_inverted;
 	int gpio_cs_inverted;
 	int (*write)(struct driver_data *drv_data);
 	int (*write)(struct driver_data *drv_data);
 	int (*read)(struct driver_data *drv_data);
 	int (*read)(struct driver_data *drv_data);
@@ -181,6 +179,11 @@ static void cs_assert(struct driver_data *drv_data)
 {
 {
 	struct chip_data *chip = drv_data->cur_chip;
 	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) {
 	if (chip->cs_control) {
 		chip->cs_control(PXA2XX_CS_ASSERT);
 		chip->cs_control(PXA2XX_CS_ASSERT);
 		return;
 		return;
@@ -194,6 +197,9 @@ static void cs_deassert(struct driver_data *drv_data)
 {
 {
 	struct chip_data *chip = drv_data->cur_chip;
 	struct chip_data *chip = drv_data->cur_chip;
 
 
+	if (drv_data->ssp_type == CE4100_SSP)
+		return;
+
 	if (chip->cs_control) {
 	if (chip->cs_control) {
 		chip->cs_control(PXA2XX_CS_DEASSERT);
 		chip->cs_control(PXA2XX_CS_DEASSERT);
 		return;
 		return;
@@ -203,6 +209,25 @@ static void cs_deassert(struct driver_data *drv_data)
 		gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
 		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)
 static int flush(struct driver_data *drv_data)
 {
 {
 	unsigned long limit = loops_per_jiffy << 1;
 	unsigned long limit = loops_per_jiffy << 1;
@@ -214,7 +239,7 @@ static int flush(struct driver_data *drv_data)
 			read_SSDR(reg);
 			read_SSDR(reg);
 		}
 		}
 	} while ((read_SSSR(reg) & SSSR_BSY) && --limit);
 	} while ((read_SSSR(reg) & SSSR_BSY) && --limit);
-	write_SSSR(SSSR_ROR, reg);
+	write_SSSR_CS(drv_data, SSSR_ROR);
 
 
 	return limit;
 	return limit;
 }
 }
@@ -224,7 +249,7 @@ static int null_writer(struct driver_data *drv_data)
 	void __iomem *reg = drv_data->ioaddr;
 	void __iomem *reg = drv_data->ioaddr;
 	u8 n_bytes = drv_data->n_bytes;
 	u8 n_bytes = drv_data->n_bytes;
 
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 		return 0;
 
 
@@ -252,7 +277,7 @@ static int u8_writer(struct driver_data *drv_data)
 {
 {
 	void __iomem *reg = drv_data->ioaddr;
 	void __iomem *reg = drv_data->ioaddr;
 
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 		return 0;
 
 
@@ -279,7 +304,7 @@ static int u16_writer(struct driver_data *drv_data)
 {
 {
 	void __iomem *reg = drv_data->ioaddr;
 	void __iomem *reg = drv_data->ioaddr;
 
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 		return 0;
 
 
@@ -306,7 +331,7 @@ static int u32_writer(struct driver_data *drv_data)
 {
 {
 	void __iomem *reg = drv_data->ioaddr;
 	void __iomem *reg = drv_data->ioaddr;
 
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 		return 0;
 
 
@@ -507,9 +532,9 @@ static void dma_error_stop(struct driver_data *drv_data, const char *msg)
 	/* Stop and reset */
 	/* Stop and reset */
 	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	write_SSSR(drv_data->clear_sr, reg);
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
 	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
 	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 		write_SSTO(0, reg);
 	flush(drv_data);
 	flush(drv_data);
 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
@@ -529,7 +554,7 @@ static void dma_transfer_complete(struct driver_data *drv_data)
 
 
 	/* Clear and disable interrupts on SSP and DMA channels*/
 	/* Clear and disable interrupts on SSP and DMA channels*/
 	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
 	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	write_SSSR(drv_data->clear_sr, reg);
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
 	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 
 
@@ -622,7 +647,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
 
 
 		/* Clear and disable timeout interrupt, do the rest in
 		/* Clear and disable timeout interrupt, do the rest in
 		 * dma_transfer_complete */
 		 * dma_transfer_complete */
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(0, reg);
 			write_SSTO(0, reg);
 
 
 		/* finish this transfer, start the next */
 		/* finish this transfer, start the next */
@@ -635,14 +660,26 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
 	return IRQ_NONE;
 	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)
 static void int_error_stop(struct driver_data *drv_data, const char* msg)
 {
 {
 	void __iomem *reg = drv_data->ioaddr;
 	void __iomem *reg = drv_data->ioaddr;
 
 
 	/* Stop and reset SSP */
 	/* Stop and reset SSP */
-	write_SSSR(drv_data->clear_sr, reg);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	reset_sccr1(drv_data);
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 		write_SSTO(0, reg);
 	flush(drv_data);
 	flush(drv_data);
 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
@@ -658,9 +695,9 @@ static void int_transfer_complete(struct driver_data *drv_data)
 	void __iomem *reg = drv_data->ioaddr;
 	void __iomem *reg = drv_data->ioaddr;
 
 
 	/* Stop SSP */
 	/* Stop SSP */
-	write_SSSR(drv_data->clear_sr, reg);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	reset_sccr1(drv_data);
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 		write_SSTO(0, reg);
 
 
 	/* Update total byte transfered return count actual bytes read */
 	/* Update total byte transfered return count actual bytes read */
@@ -714,24 +751,34 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
 	}
 	}
 
 
 	if (drv_data->tx == drv_data->tx_end) {
 	if (drv_data->tx == drv_data->tx_end) {
-		write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
-		/* PXA25x_SSP has no timeout, read trailing bytes */
-		if (drv_data->ssp_type == PXA25x_SSP) {
-			if (!wait_ssp_rx_stall(reg))
-			{
-				int_error_stop(drv_data, "interrupt_transfer: "
-						"rx stall failed");
-				return IRQ_HANDLED;
-			}
-			if (!drv_data->read(drv_data))
-			{
-				int_error_stop(drv_data,
-						"interrupt_transfer: "
-						"trailing byte read failed");
-				return IRQ_HANDLED;
+		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
+		 * remaing 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;
 			}
 			}
-			int_transfer_complete(drv_data);
+
+			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 */
 	/* We did something */
@@ -742,14 +789,26 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
 {
 {
 	struct driver_data *drv_data = dev_id;
 	struct driver_data *drv_data = dev_id;
 	void __iomem *reg = drv_data->ioaddr;
 	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) {
 	if (!drv_data->cur_msg) {
 
 
 		write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 		write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 		write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
 		write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(0, reg);
 			write_SSTO(0, reg);
-		write_SSSR(drv_data->clear_sr, reg);
+		write_SSSR_CS(drv_data, drv_data->clear_sr);
 
 
 		dev_err(&drv_data->pdev->dev, "bad message state "
 		dev_err(&drv_data->pdev->dev, "bad message state "
 			"in interrupt handler\n");
 			"in interrupt handler\n");
@@ -862,7 +921,7 @@ static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
 {
 {
 	unsigned long ssp_clk = clk_get_rate(ssp->clk);
 	unsigned long ssp_clk = clk_get_rate(ssp->clk);
 
 
-	if (ssp->type == PXA25x_SSP)
+	if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
 		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
 		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
 	else
 	else
 		return ((ssp_clk / rate - 1) & 0xfff) << 8;
 		return ((ssp_clk / rate - 1) & 0xfff) << 8;
@@ -1088,7 +1147,7 @@ static void pump_transfers(unsigned long data)
 
 
 		/* Clear status  */
 		/* Clear status  */
 		cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
 		cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
-		write_SSSR(drv_data->clear_sr, reg);
+		write_SSSR_CS(drv_data, drv_data->clear_sr);
 	}
 	}
 
 
 	/* see if we need to reload the config registers */
 	/* see if we need to reload the config registers */
@@ -1098,7 +1157,7 @@ static void pump_transfers(unsigned long data)
 
 
 		/* stop the SSP, and update the other bits */
 		/* stop the SSP, and update the other bits */
 		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
 		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(chip->timeout, reg);
 			write_SSTO(chip->timeout, reg);
 		/* first set CR1 without interrupt and service enables */
 		/* first set CR1 without interrupt and service enables */
 		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
 		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
@@ -1106,7 +1165,7 @@ static void pump_transfers(unsigned long data)
 		write_SSCR0(cr0, reg);
 		write_SSCR0(cr0, reg);
 
 
 	} else {
 	} else {
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(chip->timeout, reg);
 			write_SSTO(chip->timeout, reg);
 	}
 	}
 
 
@@ -1233,14 +1292,13 @@ static int setup(struct spi_device *spi)
 	uint tx_thres = TX_THRESH_DFLT;
 	uint tx_thres = TX_THRESH_DFLT;
 	uint rx_thres = RX_THRESH_DFLT;
 	uint rx_thres = RX_THRESH_DFLT;
 
 
-	if (drv_data->ssp_type != PXA25x_SSP
+	if (!pxa25x_ssp_comp(drv_data)
 		&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
 		&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
 		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
 		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
 				"b/w not 4-32 for type non-PXA25x_SSP\n",
 				"b/w not 4-32 for type non-PXA25x_SSP\n",
 				drv_data->ssp_type, spi->bits_per_word);
 				drv_data->ssp_type, spi->bits_per_word);
 		return -EINVAL;
 		return -EINVAL;
-	}
-	else if (drv_data->ssp_type == PXA25x_SSP
+	} else if (pxa25x_ssp_comp(drv_data)
 			&& (spi->bits_per_word < 4
 			&& (spi->bits_per_word < 4
 				|| spi->bits_per_word > 16)) {
 				|| spi->bits_per_word > 16)) {
 		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
 		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
@@ -1259,7 +1317,17 @@ static int setup(struct spi_device *spi)
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
 
 
-		chip->gpio_cs = -1;
+		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->enable_dma = 0;
 		chip->timeout = TIMOUT_DFLT;
 		chip->timeout = TIMOUT_DFLT;
 		chip->dma_burst_size = drv_data->master_info->enable_dma ?
 		chip->dma_burst_size = drv_data->master_info->enable_dma ?
@@ -1315,7 +1383,7 @@ static int setup(struct spi_device *spi)
 			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
 			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
 
 
 	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
 	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
-	if (drv_data->ssp_type != PXA25x_SSP)
+	if (!pxa25x_ssp_comp(drv_data))
 		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
 		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
 			clk_get_rate(ssp->clk)
 			clk_get_rate(ssp->clk)
 				/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
 				/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
@@ -1350,23 +1418,27 @@ static int setup(struct spi_device *spi)
 
 
 	spi_set_ctldata(spi, chip);
 	spi_set_ctldata(spi, chip);
 
 
+	if (drv_data->ssp_type == CE4100_SSP)
+		return 0;
+
 	return setup_cs(spi, chip, chip_info);
 	return setup_cs(spi, chip, chip_info);
 }
 }
 
 
 static void cleanup(struct spi_device *spi)
 static void cleanup(struct spi_device *spi)
 {
 {
 	struct chip_data *chip = spi_get_ctldata(spi);
 	struct chip_data *chip = spi_get_ctldata(spi);
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
 
 
 	if (!chip)
 	if (!chip)
 		return;
 		return;
 
 
-	if (gpio_is_valid(chip->gpio_cs))
+	if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
 		gpio_free(chip->gpio_cs);
 		gpio_free(chip->gpio_cs);
 
 
 	kfree(chip);
 	kfree(chip);
 }
 }
 
 
-static int __init init_queue(struct driver_data *drv_data)
+static int __devinit init_queue(struct driver_data *drv_data)
 {
 {
 	INIT_LIST_HEAD(&drv_data->queue);
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
 	spin_lock_init(&drv_data->lock);
@@ -1454,7 +1526,7 @@ static int destroy_queue(struct driver_data *drv_data)
 	return 0;
 	return 0;
 }
 }
 
 
-static int __init pxa2xx_spi_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
 {
 {
 	struct device *dev = &pdev->dev;
 	struct device *dev = &pdev->dev;
 	struct pxa2xx_spi_master *platform_info;
 	struct pxa2xx_spi_master *platform_info;
@@ -1484,6 +1556,10 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
 	drv_data->pdev = pdev;
 	drv_data->pdev = pdev;
 	drv_data->ssp = ssp;
 	drv_data->ssp = ssp;
 
 
+	master->dev.parent = &pdev->dev;
+#ifdef CONFIG_OF
+	master->dev.of_node = pdev->dev.of_node;
+#endif
 	/* the spi->mode bits understood by this driver: */
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
 
@@ -1500,7 +1576,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
 
 
 	drv_data->ioaddr = ssp->mmio_base;
 	drv_data->ioaddr = ssp->mmio_base;
 	drv_data->ssdr_physical = ssp->phys_base + SSDR;
 	drv_data->ssdr_physical = ssp->phys_base + SSDR;
-	if (ssp->type == PXA25x_SSP) {
+	if (pxa25x_ssp_comp(drv_data)) {
 		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
 		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
 		drv_data->dma_cr1 = 0;
 		drv_data->dma_cr1 = 0;
 		drv_data->clear_sr = SSSR_ROR;
 		drv_data->clear_sr = SSSR_ROR;
@@ -1512,7 +1588,8 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
 		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
 		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
 	}
 	}
 
 
-	status = request_irq(ssp->irq, ssp_int, 0, dev_name(dev), drv_data);
+	status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
+			drv_data);
 	if (status < 0) {
 	if (status < 0) {
 		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
 		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
 		goto out_error_master_alloc;
 		goto out_error_master_alloc;
@@ -1561,7 +1638,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
 			| SSCR0_Motorola
 			| SSCR0_Motorola
 			| SSCR0_DataSize(8),
 			| SSCR0_DataSize(8),
 			drv_data->ioaddr);
 			drv_data->ioaddr);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, drv_data->ioaddr);
 		write_SSTO(0, drv_data->ioaddr);
 	write_SSPSP(0, drv_data->ioaddr);
 	write_SSPSP(0, drv_data->ioaddr);
 
 
@@ -1723,13 +1800,14 @@ static struct platform_driver driver = {
 		.pm	= &pxa2xx_spi_pm_ops,
 		.pm	= &pxa2xx_spi_pm_ops,
 #endif
 #endif
 	},
 	},
+	.probe = pxa2xx_spi_probe,
 	.remove = pxa2xx_spi_remove,
 	.remove = pxa2xx_spi_remove,
 	.shutdown = pxa2xx_spi_shutdown,
 	.shutdown = pxa2xx_spi_shutdown,
 };
 };
 
 
 static int __init pxa2xx_spi_init(void)
 static int __init pxa2xx_spi_init(void)
 {
 {
-	return platform_driver_probe(&driver, pxa2xx_spi_probe);
+	return platform_driver_register(&driver);
 }
 }
 subsys_initcall(pxa2xx_spi_init);
 subsys_initcall(pxa2xx_spi_init);
 
 

+ 201 - 0
drivers/spi/pxa2xx_spi_pci.c

@@ -0,0 +1,201 @@
+/*
+ * 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/spi/pxa2xx_spi.h>
+
+struct awesome_struct {
+	struct ssp_device ssp;
+	struct platform_device spi_pdev;
+	struct pxa2xx_spi_master spi_pdata;
+};
+
+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 void plat_dev_release(struct device *dev)
+{
+	struct awesome_struct *as = container_of(dev,
+			struct awesome_struct, spi_pdev.dev);
+
+	of_device_node_put(&as->spi_pdev.dev);
+}
+
+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 awesome_struct *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;
+	}
+
+	spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
+	if (!spi_info) {
+		ret = -ENOMEM;
+		goto err_kz;
+	}
+	ssp = &spi_info->ssp;
+	pdev = &spi_info->spi_pdev;
+	spi_pdata =  &spi_info->spi_pdata;
+
+	pdev->name = "pxa2xx-spi";
+	pdev->id = dev->devfn;
+	pdev->dev.parent = &dev->dev;
+	pdev->dev.platform_data = &spi_info->spi_pdata;
+
+#ifdef CONFIG_OF
+	pdev->dev.of_node = dev->dev.of_node;
+#endif
+	pdev->dev.release = plat_dev_release;
+
+	spi_pdata->num_chipselect = dev->devfn;
+
+	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_remap;
+	}
+	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_register(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_remap:
+	kfree(spi_info);
+
+err_kz:
+	release_mem_region(phys_beg, phys_len);
+
+	return ret;
+}
+
+static void __devexit ce4100_spi_remove(struct pci_dev *dev)
+{
+	struct awesome_struct *spi_info;
+	struct platform_device *pdev;
+	struct ssp_device *ssp;
+
+	spi_info = pci_get_drvdata(dev);
+
+	ssp = &spi_info->ssp;
+	pdev = &spi_info->spi_pdev;
+
+	platform_device_unregister(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 struct pci_device_id ce4100_spi_devices[] __devinitdata = {
+
+	{ 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>");

+ 3 - 29
drivers/spi/spi_imx.c

@@ -66,7 +66,6 @@ enum spi_imx_devtype {
 	SPI_IMX_VER_0_5,
 	SPI_IMX_VER_0_5,
 	SPI_IMX_VER_0_7,
 	SPI_IMX_VER_0_7,
 	SPI_IMX_VER_2_3,
 	SPI_IMX_VER_2_3,
-	SPI_IMX_VER_AUTODETECT,
 };
 };
 
 
 struct spi_imx_data;
 struct spi_imx_data;
@@ -720,9 +719,6 @@ static void spi_imx_cleanup(struct spi_device *spi)
 
 
 static struct platform_device_id spi_imx_devtype[] = {
 static struct platform_device_id spi_imx_devtype[] = {
 	{
 	{
-		.name = DRIVER_NAME,
-		.driver_data = SPI_IMX_VER_AUTODETECT,
-	}, {
 		.name = "imx1-cspi",
 		.name = "imx1-cspi",
 		.driver_data = SPI_IMX_VER_IMX1,
 		.driver_data = SPI_IMX_VER_IMX1,
 	}, {
 	}, {
@@ -802,30 +798,8 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 
 
 	init_completion(&spi_imx->xfer_done);
 	init_completion(&spi_imx->xfer_done);
 
 
-	if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) {
-		if (cpu_is_mx25() || cpu_is_mx35())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_0_7];
-		else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_0_4];
-		else if (cpu_is_mx27() || cpu_is_mx21())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_0_0];
-		else if (cpu_is_mx1())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_IMX1];
-		else
-			BUG();
-	} else
-		spi_imx->devtype_data =
-			spi_imx_devtype_data[pdev->id_entry->driver_data];
-
-	if (!spi_imx->devtype_data.intctrl) {
-		dev_err(&pdev->dev, "no support for this device compiled in\n");
-		ret = -ENODEV;
-		goto out_gpio_free;
-	}
+	spi_imx->devtype_data =
+		spi_imx_devtype_data[pdev->id_entry->driver_data];
 
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 	if (!res) {
@@ -847,7 +821,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	spi_imx->irq = platform_get_irq(pdev, 0);
 	spi_imx->irq = platform_get_irq(pdev, 0);
-	if (spi_imx->irq <= 0) {
+	if (spi_imx->irq < 0) {
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto out_iounmap;
 		goto out_iounmap;
 	}
 	}

+ 1 - 1
drivers/spi/spi_nuc900.c

@@ -449,7 +449,7 @@ err_iomap:
 	release_mem_region(hw->res->start, resource_size(hw->res));
 	release_mem_region(hw->res->start, resource_size(hw->res));
 	kfree(hw->ioarea);
 	kfree(hw->ioarea);
 err_pdata:
 err_pdata:
-	spi_master_put(hw->master);;
+	spi_master_put(hw->master);
 
 
 err_nomem:
 err_nomem:
 	return err;
 	return err;

+ 6 - 6
drivers/spi/spi_topcliff_pch.c

@@ -267,7 +267,7 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
 	if (reg_spsr_val & SPSR_FI_BIT) {
 	if (reg_spsr_val & SPSR_FI_BIT) {
 		/* disable FI & RFI interrupts */
 		/* disable FI & RFI interrupts */
 		pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
 		pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
-				   SPCR_FIE_BIT | SPCR_TFIE_BIT);
+				   SPCR_FIE_BIT | SPCR_RFIE_BIT);
 
 
 		/* transfer is completed;inform pch_spi_process_messages */
 		/* transfer is completed;inform pch_spi_process_messages */
 		data->transfer_complete = true;
 		data->transfer_complete = true;
@@ -677,15 +677,15 @@ static void pch_spi_set_ir(struct pch_spi_data *data)
 {
 {
 	/* enable interrupts */
 	/* enable interrupts */
 	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
 	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
-		/* set receive threhold to PCH_RX_THOLD */
+		/* set receive threshold to PCH_RX_THOLD */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   PCH_RX_THOLD << SPCR_TFIC_FIELD,
-				   ~MASK_TFIC_SPCR_BITS);
+				   PCH_RX_THOLD << SPCR_RFIC_FIELD,
+				   ~MASK_RFIC_SPCR_BITS);
 		/* enable FI and RFI interrupts */
 		/* enable FI and RFI interrupts */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   SPCR_RFIE_BIT | SPCR_TFIE_BIT, 0);
+				   SPCR_RFIE_BIT | SPCR_FIE_BIT, 0);
 	} else {
 	} else {
-		/* set receive threhold to maximum */
+		/* set receive threshold to maximum */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
 				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
 				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
 				   ~MASK_TFIC_SPCR_BITS);
 				   ~MASK_TFIC_SPCR_BITS);

+ 114 - 19
drivers/spi/xilinx_spi.c

@@ -1,26 +1,27 @@
 /*
 /*
- * xilinx_spi.c
- *
  * Xilinx SPI controller driver (master mode only)
  * Xilinx SPI controller driver (master mode only)
  *
  *
  * Author: MontaVista Software, Inc.
  * Author: MontaVista Software, Inc.
  *	source@mvista.com
  *	source@mvista.com
  *
  *
- * 2002-2007 (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.
+ * 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/module.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
-
+#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/spi/spi_bitbang.h>
-#include <linux/io.h>
-
-#include "xilinx_spi.h"
 #include <linux/spi/xilinx_spi.h>
 #include <linux/spi/xilinx_spi.h>
+#include <linux/io.h>
 
 
 #define XILINX_SPI_NAME "xilinx_spi"
 #define XILINX_SPI_NAME "xilinx_spi"
 
 
@@ -350,19 +351,22 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+#ifdef CONFIG_OF
+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);
+#endif
+
 struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-	u32 irq, s16 bus_num)
+	u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
 {
 {
 	struct spi_master *master;
 	struct spi_master *master;
 	struct xilinx_spi *xspi;
 	struct xilinx_spi *xspi;
-	struct xspi_platform_data *pdata = dev->platform_data;
 	int ret;
 	int ret;
 
 
-	if (!pdata) {
-		dev_err(dev, "No platform data attached\n");
-		return NULL;
-	}
-
 	master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
 	master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
 	if (!master)
 	if (!master)
 		return NULL;
 		return NULL;
@@ -389,21 +393,21 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 	}
 	}
 
 
 	master->bus_num = bus_num;
 	master->bus_num = bus_num;
-	master->num_chipselect = pdata->num_chipselect;
+	master->num_chipselect = num_cs;
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 	master->dev.of_node = dev->of_node;
 	master->dev.of_node = dev->of_node;
 #endif
 #endif
 
 
 	xspi->mem = *mem;
 	xspi->mem = *mem;
 	xspi->irq = irq;
 	xspi->irq = irq;
-	if (pdata->little_endian) {
+	if (little_endian) {
 		xspi->read_fn = xspi_read32;
 		xspi->read_fn = xspi_read32;
 		xspi->write_fn = xspi_write32;
 		xspi->write_fn = xspi_write32;
 	} else {
 	} else {
 		xspi->read_fn = xspi_read32_be;
 		xspi->read_fn = xspi_read32_be;
 		xspi->write_fn = xspi_write32_be;
 		xspi->write_fn = xspi_write32_be;
 	}
 	}
-	xspi->bits_per_word = pdata->bits_per_word;
+	xspi->bits_per_word = bits_per_word;
 	if (xspi->bits_per_word == 8) {
 	if (xspi->bits_per_word == 8) {
 		xspi->tx_fn = xspi_tx8;
 		xspi->tx_fn = xspi_tx8;
 		xspi->rx_fn = xspi_rx8;
 		xspi->rx_fn = xspi_rx8;
@@ -462,6 +466,97 @@ void xilinx_spi_deinit(struct spi_master *master)
 }
 }
 EXPORT_SYMBOL(xilinx_spi_deinit);
 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,
+#ifdef CONFIG_OF
+		.of_match_table = xilinx_spi_of_match,
+#endif
+	},
+};
+
+static int __init xilinx_spi_pltfm_init(void)
+{
+	return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_pltfm_init);
+
+static void __exit xilinx_spi_pltfm_exit(void)
+{
+	platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_pltfm_exit);
+
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
 MODULE_DESCRIPTION("Xilinx SPI driver");
 MODULE_DESCRIPTION("Xilinx SPI driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 0 - 32
drivers/spi/xilinx_spi.h

@@ -1,32 +0,0 @@
-/*
- * Xilinx SPI device driver API and platform data header file
- *
- * Copyright (c) 2009 Intel 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.
- *
- * 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.
- */
-
-#ifndef _XILINX_SPI_H_
-#define _XILINX_SPI_H_
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#define XILINX_SPI_NAME "xilinx_spi"
-
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-	u32 irq, s16 bus_num);
-
-void xilinx_spi_deinit(struct spi_master *master);
-#endif

+ 0 - 133
drivers/spi/xilinx_spi_of.c

@@ -1,133 +0,0 @@
-/*
- * Xilinx SPI OF device driver
- *
- * Copyright (c) 2009 Intel 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.
- *
- * 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.
- */
-
-/* Supports:
- * Xilinx SPI devices as OF devices
- *
- * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
-#include <linux/of_spi.h>
-
-#include <linux/spi/xilinx_spi.h>
-#include "xilinx_spi.h"
-
-
-static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev,
-	const struct of_device_id *match)
-{
-	struct spi_master *master;
-	struct xspi_platform_data *pdata;
-	struct resource r_mem;
-	struct resource r_irq;
-	int rc = 0;
-	const u32 *prop;
-	int len;
-
-	rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem);
-	if (rc) {
-		dev_warn(&ofdev->dev, "invalid address\n");
-		return rc;
-	}
-
-	rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
-	if (rc == NO_IRQ) {
-		dev_warn(&ofdev->dev, "no IRQ found\n");
-		return -ENODEV;
-	}
-
-	ofdev->dev.platform_data =
-		kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL);
-	pdata = ofdev->dev.platform_data;
-	if (!pdata)
-		return -ENOMEM;
-
-	/* number of slave select bits is required */
-	prop = of_get_property(ofdev->dev.of_node, "xlnx,num-ss-bits", &len);
-	if (!prop || len < sizeof(*prop)) {
-		dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
-		return -EINVAL;
-	}
-	pdata->num_chipselect = *prop;
-	pdata->bits_per_word = 8;
-	master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1);
-	if (!master)
-		return -ENODEV;
-
-	dev_set_drvdata(&ofdev->dev, master);
-
-	return 0;
-}
-
-static int __devexit xilinx_spi_remove(struct platform_device *ofdev)
-{
-	xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev));
-	dev_set_drvdata(&ofdev->dev, 0);
-	kfree(ofdev->dev.platform_data);
-	ofdev->dev.platform_data = NULL;
-	return 0;
-}
-
-static int __exit xilinx_spi_of_remove(struct platform_device *op)
-{
-	return xilinx_spi_remove(op);
-}
-
-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);
-
-static struct of_platform_driver xilinx_spi_of_driver = {
-	.probe = xilinx_spi_of_probe,
-	.remove = __exit_p(xilinx_spi_of_remove),
-	.driver = {
-		.name = "xilinx-xps-spi",
-		.owner = THIS_MODULE,
-		.of_match_table = xilinx_spi_of_match,
-	},
-};
-
-static int __init xilinx_spi_of_init(void)
-{
-	return of_register_platform_driver(&xilinx_spi_of_driver);
-}
-module_init(xilinx_spi_of_init);
-
-static void __exit xilinx_spi_of_exit(void)
-{
-	of_unregister_platform_driver(&xilinx_spi_of_driver);
-}
-module_exit(xilinx_spi_of_exit);
-
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_DESCRIPTION("Xilinx SPI platform driver");
-MODULE_LICENSE("GPL v2");

+ 0 - 102
drivers/spi/xilinx_spi_pltfm.c

@@ -1,102 +0,0 @@
-/*
- * Support for Xilinx SPI platform devices
- * Copyright (c) 2009 Intel 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.
- *
- * 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.
- */
-
-/* Supports:
- * Xilinx SPI devices as platform devices
- *
- * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/xilinx_spi.h>
-
-#include "xilinx_spi.h"
-
-static int __devinit xilinx_spi_probe(struct platform_device *dev)
-{
-	struct xspi_platform_data *pdata;
-	struct resource *r;
-	int irq;
-	struct spi_master *master;
-	u8 i;
-
-	pdata = dev->dev.platform_data;
-	if (!pdata)
-		return -ENODEV;
-
-	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);
-	if (!master)
-		return -ENODEV;
-
-	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,
-	},
-};
-
-static int __init xilinx_spi_pltfm_init(void)
-{
-	return platform_driver_register(&xilinx_spi_driver);
-}
-module_init(xilinx_spi_pltfm_init);
-
-static void __exit xilinx_spi_pltfm_exit(void)
-{
-	platform_driver_unregister(&xilinx_spi_driver);
-}
-module_exit(xilinx_spi_pltfm_exit);
-
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_DESCRIPTION("Xilinx SPI platform driver");
-MODULE_LICENSE("GPL v2");

+ 31 - 8
arch/arm/plat-pxa/include/plat/ssp.h → include/linux/pxa2xx_ssp.h

@@ -1,5 +1,5 @@
 /*
 /*
- *  ssp.h
+ *  pxa2xx_ssp.h
  *
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *
  *
@@ -16,8 +16,8 @@
  *       PXA3xx     SSP1, SSP2, SSP3, SSP4
  *       PXA3xx     SSP1, SSP2, SSP3, SSP4
  */
  */
 
 
-#ifndef __ASM_ARCH_SSP_H
-#define __ASM_ARCH_SSP_H
+#ifndef __LINUX_SSP_H
+#define __LINUX_SSP_H
 
 
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/io.h>
@@ -71,11 +71,8 @@
 #define SSCR1_SPO	(1 << 3)	/* Motorola SPI SSPSCLK polarity setting */
 #define SSCR1_SPO	(1 << 3)	/* Motorola SPI SSPSCLK polarity setting */
 #define SSCR1_SPH	(1 << 4)	/* Motorola SPI SSPSCLK phase setting */
 #define SSCR1_SPH	(1 << 4)	/* Motorola SPI SSPSCLK phase setting */
 #define SSCR1_MWDS	(1 << 5)	/* Microwire Transmit Data Size */
 #define SSCR1_MWDS	(1 << 5)	/* Microwire Transmit Data Size */
-#define SSCR1_TFT	(0x000003c0)	/* Transmit FIFO Threshold (mask) */
-#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */
-#define SSCR1_RFT	(0x00003c00)	/* Receive FIFO Threshold (mask) */
-#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */
 
 
+#define SSSR_ALT_FRM_MASK	3	/* Masks the SFRM signal number */
 #define SSSR_TNF	(1 << 2)	/* Transmit FIFO Not Full */
 #define SSSR_TNF	(1 << 2)	/* Transmit FIFO Not Full */
 #define SSSR_RNE	(1 << 3)	/* Receive FIFO Not Empty */
 #define SSSR_RNE	(1 << 3)	/* Receive FIFO Not Empty */
 #define SSSR_BSY	(1 << 4)	/* SSP Busy */
 #define SSSR_BSY	(1 << 4)	/* SSP Busy */
@@ -83,6 +80,31 @@
 #define SSSR_RFS	(1 << 6)	/* Receive FIFO Service Request */
 #define SSSR_RFS	(1 << 6)	/* Receive FIFO Service Request */
 #define SSSR_ROR	(1 << 7)	/* Receive FIFO Overrun */
 #define SSSR_ROR	(1 << 7)	/* Receive FIFO Overrun */
 
 
+#ifdef CONFIG_ARCH_PXA
+#define RX_THRESH_DFLT	8
+#define TX_THRESH_DFLT	8
+
+#define SSSR_TFL_MASK	(0xf << 8)	/* Transmit FIFO Level mask */
+#define SSSR_RFL_MASK	(0xf << 12)	/* Receive FIFO Level mask */
+
+#define SSCR1_TFT	(0x000003c0)	/* Transmit FIFO Threshold (mask) */
+#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */
+#define SSCR1_RFT	(0x00003c00)	/* Receive FIFO Threshold (mask) */
+#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */
+
+#else
+
+#define RX_THRESH_DFLT	2
+#define TX_THRESH_DFLT	2
+
+#define SSSR_TFL_MASK	(0x3 << 8)	/* Transmit FIFO Level mask */
+#define SSSR_RFL_MASK	(0x3 << 12)	/* Receive FIFO Level mask */
+
+#define SSCR1_TFT	(0x000000c0)	/* Transmit FIFO Threshold (mask) */
+#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */
+#define SSCR1_RFT	(0x00000c00)	/* Receive FIFO Threshold (mask) */
+#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
+#endif
 
 
 /* extra bits in PXA255, PXA26x and PXA27x SSP ports */
 /* extra bits in PXA255, PXA26x and PXA27x SSP ports */
 #define SSCR0_TISSP		(1 << 4)	/* TI Sync Serial Protocol */
 #define SSCR0_TISSP		(1 << 4)	/* TI Sync Serial Protocol */
@@ -139,6 +161,7 @@ enum pxa_ssp_type {
 	PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
 	PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
 	PXA27x_SSP,
 	PXA27x_SSP,
 	PXA168_SSP,
 	PXA168_SSP,
+	CE4100_SSP,
 };
 };
 
 
 struct ssp_device {
 struct ssp_device {
@@ -183,4 +206,4 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
 
 
 struct ssp_device *pxa_ssp_request(int port, const char *label);
 struct ssp_device *pxa_ssp_request(int port, const char *label);
 void pxa_ssp_free(struct ssp_device *);
 void pxa_ssp_free(struct ssp_device *);
-#endif /* __ASM_ARCH_SSP_H */
+#endif

+ 19 - 5
include/linux/spi/dw_spi.h

@@ -1,5 +1,6 @@
 #ifndef DW_SPI_HEADER_H
 #ifndef DW_SPI_HEADER_H
 #define DW_SPI_HEADER_H
 #define DW_SPI_HEADER_H
+
 #include <linux/io.h>
 #include <linux/io.h>
 
 
 /* Bit fields in CTRLR0 */
 /* Bit fields in CTRLR0 */
@@ -82,6 +83,13 @@ struct dw_spi_reg {
 				though only low 16 bits matters */
 				though only low 16 bits matters */
 } __packed;
 } __packed;
 
 
+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 dw_spi {
 	struct spi_master	*master;
 	struct spi_master	*master;
 	struct spi_device	*cur_dev;
 	struct spi_device	*cur_dev;
@@ -136,13 +144,15 @@ struct dw_spi {
 	/* Dma info */
 	/* Dma info */
 	int			dma_inited;
 	int			dma_inited;
 	struct dma_chan		*txchan;
 	struct dma_chan		*txchan;
+	struct scatterlist	tx_sgl;
 	struct dma_chan		*rxchan;
 	struct dma_chan		*rxchan;
-	int			txdma_done;
-	int			rxdma_done;
-	u64			tx_param;
-	u64			rx_param;
+	struct scatterlist	rx_sgl;
+	int			dma_chan_done;
 	struct device		*dma_dev;
 	struct device		*dma_dev;
-	dma_addr_t		dma_addr;
+	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 */
 	/* Bus interface info */
 	void			*priv;
 	void			*priv;
@@ -216,4 +226,8 @@ extern int dw_spi_add_host(struct dw_spi *dws);
 extern void dw_spi_remove_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_suspend_host(struct dw_spi *dws);
 extern int dw_spi_resume_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 */
 #endif /* DW_SPI_HEADER_H */

+ 152 - 0
include/linux/spi/pxa2xx_spi.h

@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+#ifndef __linux_pxa2xx_spi_h
+#define __linux_pxa2xx_spi_h
+
+#include <linux/pxa2xx_ssp.h>
+
+#define PXA2XX_CS_ASSERT (0x01)
+#define PXA2XX_CS_DEASSERT (0x02)
+
+/* device.platform_data for SSP controller devices */
+struct pxa2xx_spi_master {
+	u32 clock_enable;
+	u16 num_chipselect;
+	u8 enable_dma;
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct pxa2xx_spi_chip {
+	u8 tx_threshold;
+	u8 rx_threshold;
+	u8 dma_burst_size;
+	u32 timeout;
+	u8 enable_loopback;
+	int gpio_cs;
+	void (*cs_control)(u32 command);
+};
+
+#ifdef CONFIG_ARCH_PXA
+
+#include <linux/clk.h>
+#include <mach/dma.h>
+
+extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
+
+#else
+/*
+ * This is the implemtation for CE4100 on x86. ARM defines them in mach/ or
+ * plat/ include path.
+ * The CE4100 does not provide DMA support. This bits are here to let the driver
+ * compile and will never be used. Maybe we get DMA support at a later point in
+ * time.
+ */
+
+#define DCSR(n)         (n)
+#define DSADR(n)        (n)
+#define DTADR(n)        (n)
+#define DCMD(n)         (n)
+#define DRCMR(n)        (n)
+
+#define DCSR_RUN	(1 << 31)	/* Run Bit */
+#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch */
+#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable */
+#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
+#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
+#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt */
+#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt */
+#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt */
+
+#define DCSR_EORIRQEN	(1 << 28)	/* End of Receive Interrupt Enable */
+#define DCSR_EORJMPEN	(1 << 27)	/* Jump to next descriptor on EOR */
+#define DCSR_EORSTOPEN	(1 << 26)	/* STOP on an EOR */
+#define DCSR_SETCMPST	(1 << 25)	/* Set Descriptor Compare Status */
+#define DCSR_CLRCMPST	(1 << 24)	/* Clear Descriptor Compare Status */
+#define DCSR_CMPST	(1 << 10)	/* The Descriptor Compare Status */
+#define DCSR_EORINTR	(1 << 9)	/* The end of Receive */
+
+#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid */
+#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number */
+
+#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor */
+#define DDADR_STOP	(1 << 0)	/* Stop */
+
+#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
+#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
+#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
+#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
+#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
+#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
+#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
+#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
+#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
+#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
+#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
+#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
+#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+
+/*
+ * Descriptor structure for PXA's DMA engine
+ * Note: this structure must always be aligned to a 16-byte boundary.
+ */
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+} pxa_dma_prio;
+
+/*
+ * DMA registration
+ */
+
+static inline int pxa_request_dma(char *name,
+		pxa_dma_prio prio,
+		void (*irq_handler)(int, void *),
+		void *data)
+{
+	return -ENODEV;
+}
+
+static inline void pxa_free_dma(int dma_ch)
+{
+}
+
+/*
+ * The CE4100 does not have the clk framework implemented and SPI clock can
+ * not be switched on/off or the divider changed.
+ */
+static inline void clk_disable(struct clk *clk)
+{
+}
+
+static inline int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+static inline unsigned long clk_get_rate(struct clk *clk)
+{
+	return 3686400;
+}
+
+#endif
+#endif

+ 1 - 1
sound/soc/pxa/pxa-ssp.c

@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/pxa2xx_ssp.h>
 
 
 #include <asm/irq.h>
 #include <asm/irq.h>
 
 
@@ -33,7 +34,6 @@
 #include <mach/hardware.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
 #include <mach/dma.h>
 #include <mach/audio.h>
 #include <mach/audio.h>
-#include <plat/ssp.h>
 
 
 #include "../../arm/pxa2xx-pcm.h"
 #include "../../arm/pxa2xx-pcm.h"
 #include "pxa-ssp.h"
 #include "pxa-ssp.h"

Some files were not shown because too many files changed in this diff