summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-12-29 01:05:14 -0700
committerGrant Likely <grant.likely@secretlab.ca>2010-12-29 01:05:50 -0700
commit94a544a4e8d05a027613443c529c399c39cc3371 (patch)
treeedada38e93a958a918b5826eaef173b1b92079d1
parent496a2e360a34e1f41c336d23947f800216cb9bdf (diff)
parent21486af0f34d03b813b023d7a2b887b329f60486 (diff)
downloadop-kernel-dev-94a544a4e8d05a027613443c529c399c39cc3371.zip
op-kernel-dev-94a544a4e8d05a027613443c529c399c39cc3371.tar.gz
Merge branch 'spi' of git://git.linutronix.de/users/bigeasy/soda into spi/next
* 'spi' of git://git.linutronix.de/users/bigeasy/soda into spi/next spi/pxa2xx: register driver properly spi/pxa2xx: add support for shared IRQ handler spi/pxa2xx: Use define for SSSR_TFL_MASK instead of plain numbers arm/pxa2xx: reorgazine SSP and SPI header files spi/pxa2xx: Add CE4100 support spi/pxa2xx: Consider CE4100's FIFO depth spi/pxa2xx: Add chipselect support for Sodaville spi/pxa2xx: Modify RX-Tresh instead of busy-loop for the remaining RX bytes. spi/pxa2xx: pass of_node to spi device and set a parent device
-rw-r--r--Documentation/spi/pxa2xx4
-rw-r--r--arch/arm/mach-pxa/cm-x255.c2
-rw-r--r--arch/arm/mach-pxa/cm-x270.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c2
-rw-r--r--arch/arm/mach-pxa/devices.c2
-rw-r--r--arch/arm/mach-pxa/em-x270.c2
-rw-r--r--arch/arm/mach-pxa/hx4700.c2
-rw-r--r--arch/arm/mach-pxa/icontrol.c2
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa2xx_spi.h47
-rw-r--r--arch/arm/mach-pxa/littleton.c2
-rw-r--r--arch/arm/mach-pxa/lubbock.c2
-rw-r--r--arch/arm/mach-pxa/pcm027.c2
-rw-r--r--arch/arm/mach-pxa/poodle.c2
-rw-r--r--arch/arm/mach-pxa/spitz.c3
-rw-r--r--arch/arm/mach-pxa/stargate2.c2
-rw-r--r--arch/arm/mach-pxa/tosa.c2
-rw-r--r--arch/arm/mach-pxa/trizeps4.c1
-rw-r--r--arch/arm/mach-pxa/z2.c2
-rw-r--r--arch/arm/mach-pxa/zeus.c2
-rw-r--r--arch/arm/plat-pxa/ssp.c2
-rw-r--r--drivers/spi/Kconfig13
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/pxa2xx_spi.c190
-rw-r--r--drivers/spi/pxa2xx_spi_pci.c201
-rw-r--r--include/linux/pxa2xx_ssp.h (renamed from arch/arm/plat-pxa/include/plat/ssp.h)39
-rw-r--r--include/linux/spi/pxa2xx_spi.h152
-rw-r--r--sound/soc/pxa/pxa-ssp.c2
27 files changed, 547 insertions, 138 deletions
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index 6bb916d..68a4fe3 100644
--- a/Documentation/spi/pxa2xx
+++ b/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
"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 {
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
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
device. All fields are optional.
diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c
index f1a7703..93f59f8 100644
--- a/arch/arm/mach-pxa/cm-x255.c
+++ b/arch/arm/mach-pxa/cm-x255.c
@@ -17,13 +17,13 @@
#include <linux/mtd/nand-gpio.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <mach/pxa25x.h>
-#include <mach/pxa2xx_spi.h>
#include "generic.h"
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index a9926bb..b88d601a 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -19,12 +19,12 @@
#include <video/mbxfb.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/libertas_spi.h>
#include <mach/pxa27x.h>
#include <mach/ohci.h>
#include <mach/mmc.h>
-#include <mach/pxa2xx_spi.h>
#include "generic.h"
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 821229ac..3b8dcac 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -28,6 +28,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/spi/corgi_lcd.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/mtd/sharpsl.h>
#include <linux/input/matrix_keypad.h>
#include <video/w100fb.h>
@@ -48,7 +49,6 @@
#include <mach/irda.h>
#include <mach/mmc.h>
#include <mach/udc.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/corgi.h>
#include <mach/sharpsl_pm.h>
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index aaa1166..c4f9c71 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <asm/pmu.h>
#include <mach/udc.h>
@@ -12,7 +13,6 @@
#include <mach/irda.h>
#include <mach/ohci.h>
#include <plat/pxa27x_keypad.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/camera.h>
#include <mach/audio.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index ed0dbfdb..b20b944 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -26,6 +26,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/tdo24m.h>
#include <linux/spi/libertas_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/power_supply.h>
#include <linux/apm-emulation.h>
#include <linux/i2c.h>
@@ -46,7 +47,6 @@
#include <plat/pxa27x_keypad.h>
#include <plat/i2c.h>
#include <mach/camera.h>
-#include <mach/pxa2xx_spi.h>
#include "generic.h"
#include "devices.h"
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index 76d93a2..f09526f 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -33,6 +33,7 @@
#include <linux/regulator/max1586.h>
#include <linux/spi/ads7846.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/usb/gpio_vbus.h>
#include <mach/hardware.h>
@@ -43,7 +44,6 @@
#include <mach/hx4700.h>
#include <plat/i2c.h>
#include <mach/irda.h>
-#include <mach/pxa2xx_spi.h>
#include <video/platform_lcd.h>
#include <video/w100fb.h>
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index d51ee3d..3ab6fd3 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -24,7 +24,7 @@
#include <mach/mxm8x10.h>
#include <linux/spi/spi.h>
-#include <mach/pxa2xx_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/can/platform/mcp251x.h>
#include "generic.h"
diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h b/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
deleted file mode 100644
index b87cecd..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
+++ /dev/null
@@ -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_*/
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 41aa89e..8051925 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/smc91x.h>
#include <linux/i2c.h>
#include <linux/leds.h>
@@ -42,7 +43,6 @@
#include <mach/pxa300.h>
#include <mach/pxafb.h>
#include <mach/mmc.h>
-#include <mach/pxa2xx_spi.h>
#include <plat/pxa27x_keypad.h>
#include <mach/littleton.h>
#include <plat/i2c.h>
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 1499493..4a3fe45 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -25,7 +25,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
-#include <mach/pxa2xx_spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <asm/setup.h>
#include <asm/memory.h>
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index c77e8f3..a5596f9 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -25,12 +25,12 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/spi.h>
#include <linux/spi/max7301.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/pxa27x.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/pcm027.h>
#include "generic.h"
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 93a191c..c05eee3 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/mtd/sharpsl.h>
#include <mach/hardware.h>
@@ -43,7 +44,6 @@
#include <mach/irda.h>
#include <mach/poodle.h>
#include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
#include <plat/i2c.h>
#include <asm/hardware/scoop.h>
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index f736119..4fd5572 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -23,7 +23,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.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/input/matrix_keypad.h>
#include <linux/regulator/machine.h>
@@ -41,7 +41,6 @@
#include <mach/mmc.h>
#include <mach/ohci.h>
#include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/spitz.h>
#include <mach/sharpsl_pm.h>
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 738adc1..325f6ac 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -46,10 +46,10 @@
#include <plat/i2c.h>
#include <mach/mmc.h>
#include <mach/udc.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/pxa27x-udc.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/mfd/da903x.h>
#include <linux/sht15.h>
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 0ee1df4..7b5765d 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -32,6 +32,7 @@
#include <linux/gpio.h>
#include <linux/pda_power.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/input/matrix_keypad.h>
#include <asm/setup.h>
@@ -44,7 +45,6 @@
#include <mach/mmc.h>
#include <mach/udc.h>
#include <mach/tosa_bt.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/audio.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 565d062..bdb02a0 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -40,7 +40,6 @@
#include <asm/mach/flash.h>
#include <mach/pxa27x.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/trizeps4.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index fefde98..1b8b71b 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -20,6 +20,7 @@
#include <linux/z2_battery.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/libertas_spi.h>
#include <linux/spi/lms283gf05.h>
#include <linux/power_supply.h>
@@ -38,7 +39,6 @@
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <plat/pxa27x_keypad.h>
-#include <mach/pxa2xx_spi.h>
#include <plat/i2c.h>
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index dea46a2..f5c9f30 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -20,6 +20,7 @@
#include <linux/dm9000.h>
#include <linux/mmc/host.h>
#include <linux/spi/spi.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
@@ -41,7 +42,6 @@
#include <mach/pxa27x-udc.h>
#include <mach/udc.h>
#include <mach/pxafb.h>
-#include <mach/pxa2xx_spi.h>
#include <mach/mfp-pxa27x.h>
#include <mach/pm.h>
#include <mach/audio.h>
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index c6357e5..58b7980 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -28,11 +28,11 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <mach/hardware.h>
-#include <plat/ssp.h>
static DEFINE_MUTEX(ssp_lock);
static LIST_HEAD(ssp_list);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 6efac5f..1906840 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -270,12 +270,15 @@ config SPI_PPC4xx
config SPI_PXA2XX
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
- 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
tristate "Samsung S3C24XX series SPI"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 7ec375b..3a42463 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
+obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index e76b1af..9592883 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -23,11 +23,11 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
-#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -35,9 +35,6 @@
#include <asm/irq.h>
#include <asm/delay.h>
-#include <mach/dma.h>
-#include <plat/ssp.h>
-#include <mach/pxa2xx_spi.h>
MODULE_AUTHOR("Stephen Street");
MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
@@ -46,8 +43,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define MAX_BUSES 3
-#define RX_THRESH_DFLT 8
-#define TX_THRESH_DFLT 8
#define TIMOUT_DFLT 1000
#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
@@ -168,7 +163,10 @@ struct chip_data {
u8 enable_dma;
u8 bits_per_word;
u32 speed_hz;
- int gpio_cs;
+ union {
+ int gpio_cs;
+ unsigned int frm;
+ };
int gpio_cs_inverted;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
@@ -181,6 +179,11 @@ static void cs_assert(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
+ if (drv_data->ssp_type == CE4100_SSP) {
+ write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
+ return;
+ }
+
if (chip->cs_control) {
chip->cs_control(PXA2XX_CS_ASSERT);
return;
@@ -194,6 +197,9 @@ static void cs_deassert(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
+ if (drv_data->ssp_type == CE4100_SSP)
+ return;
+
if (chip->cs_control) {
chip->cs_control(PXA2XX_CS_DEASSERT);
return;
@@ -203,6 +209,25 @@ static void cs_deassert(struct driver_data *drv_data)
gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
}
+static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
+{
+ void __iomem *reg = drv_data->ioaddr;
+
+ if (drv_data->ssp_type == CE4100_SSP)
+ val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
+
+ write_SSSR(val, reg);
+}
+
+static int pxa25x_ssp_comp(struct driver_data *drv_data)
+{
+ if (drv_data->ssp_type == PXA25x_SSP)
+ return 1;
+ if (drv_data->ssp_type == CE4100_SSP)
+ return 1;
+ return 0;
+}
+
static int flush(struct driver_data *drv_data)
{
unsigned long limit = loops_per_jiffy << 1;
@@ -214,7 +239,7 @@ static int flush(struct driver_data *drv_data)
read_SSDR(reg);
}
} while ((read_SSSR(reg) & SSSR_BSY) && --limit);
- write_SSSR(SSSR_ROR, reg);
+ write_SSSR_CS(drv_data, SSSR_ROR);
return limit;
}
@@ -224,7 +249,7 @@ static int null_writer(struct driver_data *drv_data)
void __iomem *reg = drv_data->ioaddr;
u8 n_bytes = drv_data->n_bytes;
- if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
|| (drv_data->tx == drv_data->tx_end))
return 0;
@@ -252,7 +277,7 @@ static int u8_writer(struct driver_data *drv_data)
{
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))
return 0;
@@ -279,7 +304,7 @@ static int u16_writer(struct driver_data *drv_data)
{
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))
return 0;
@@ -306,7 +331,7 @@ static int u32_writer(struct driver_data *drv_data)
{
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))
return 0;
@@ -507,9 +532,9 @@ static void dma_error_stop(struct driver_data *drv_data, const char *msg)
/* Stop and reset */
DCSR(drv_data->rx_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);
- if (drv_data->ssp_type != PXA25x_SSP)
+ if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
flush(drv_data);
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*/
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->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
* dma_transfer_complete */
- if (drv_data->ssp_type != PXA25x_SSP)
+ if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
/* finish this transfer, start the next */
@@ -635,14 +660,26 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
return IRQ_NONE;
}
+static void reset_sccr1(struct driver_data *drv_data)
+{
+ void __iomem *reg = drv_data->ioaddr;
+ struct chip_data *chip = drv_data->cur_chip;
+ u32 sccr1_reg;
+
+ sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
+ sccr1_reg &= ~SSCR1_RFT;
+ sccr1_reg |= chip->threshold;
+ write_SSCR1(sccr1_reg, reg);
+}
+
static void int_error_stop(struct driver_data *drv_data, const char* msg)
{
void __iomem *reg = drv_data->ioaddr;
/* Stop and reset SSP */
- write_SSSR(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);
flush(drv_data);
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;
/* 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);
/* 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) {
- 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 */
@@ -742,14 +789,26 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
{
struct driver_data *drv_data = dev_id;
void __iomem *reg = drv_data->ioaddr;
+ u32 sccr1_reg = read_SSCR1(reg);
+ u32 mask = drv_data->mask_sr;
+ u32 status;
+
+ status = read_SSSR(reg);
+
+ /* Ignore possible writes if we don't need to write */
+ if (!(sccr1_reg & SSCR1_TIE))
+ mask &= ~SSSR_TFS;
+
+ if (!(status & mask))
+ return IRQ_NONE;
if (!drv_data->cur_msg) {
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
- if (drv_data->ssp_type != PXA25x_SSP)
+ if (!pxa25x_ssp_comp(drv_data))
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 "
"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);
- if (ssp->type == PXA25x_SSP)
+ if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
else
return ((ssp_clk / rate - 1) & 0xfff) << 8;
@@ -1088,7 +1147,7 @@ static void pump_transfers(unsigned long data)
/* Clear status */
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 */
@@ -1098,7 +1157,7 @@ static void pump_transfers(unsigned long data)
/* stop the SSP, and update the other bits */
write_SSCR0(cr0 & ~SSCR0_SSE, reg);
- if (drv_data->ssp_type != PXA25x_SSP)
+ if (!pxa25x_ssp_comp(drv_data))
write_SSTO(chip->timeout, reg);
/* first set CR1 without interrupt and service enables */
write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
@@ -1106,7 +1165,7 @@ static void pump_transfers(unsigned long data)
write_SSCR0(cr0, reg);
} else {
- if (drv_data->ssp_type != PXA25x_SSP)
+ if (!pxa25x_ssp_comp(drv_data))
write_SSTO(chip->timeout, reg);
}
@@ -1233,14 +1292,13 @@ static int setup(struct spi_device *spi)
uint tx_thres = TX_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)) {
dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
"b/w not 4-32 for type non-PXA25x_SSP\n",
drv_data->ssp_type, spi->bits_per_word);
return -EINVAL;
- }
- else if (drv_data->ssp_type == PXA25x_SSP
+ } else if (pxa25x_ssp_comp(drv_data)
&& (spi->bits_per_word < 4
|| spi->bits_per_word > 16)) {
dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
@@ -1259,7 +1317,17 @@ static int setup(struct spi_device *spi)
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->timeout = TIMOUT_DFLT;
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);
/* 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",
clk_get_rate(ssp->clk)
/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
@@ -1350,23 +1418,27 @@ static int setup(struct spi_device *spi)
spi_set_ctldata(spi, chip);
+ if (drv_data->ssp_type == CE4100_SSP)
+ return 0;
+
return setup_cs(spi, chip, chip_info);
}
static void cleanup(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);
+ struct driver_data *drv_data = spi_master_get_devdata(spi->master);
if (!chip)
return;
- if (gpio_is_valid(chip->gpio_cs))
+ if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
gpio_free(chip->gpio_cs);
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);
spin_lock_init(&drv_data->lock);
@@ -1454,7 +1526,7 @@ static int destroy_queue(struct driver_data *drv_data)
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 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->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: */
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->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->dma_cr1 = 0;
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;
}
- 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) {
dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
goto out_error_master_alloc;
@@ -1561,7 +1638,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
| SSCR0_Motorola
| SSCR0_DataSize(8),
drv_data->ioaddr);
- if (drv_data->ssp_type != PXA25x_SSP)
+ if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, drv_data->ioaddr);
write_SSPSP(0, drv_data->ioaddr);
@@ -1723,13 +1800,14 @@ static struct platform_driver driver = {
.pm = &pxa2xx_spi_pm_ops,
#endif
},
+ .probe = pxa2xx_spi_probe,
.remove = pxa2xx_spi_remove,
.shutdown = pxa2xx_spi_shutdown,
};
static int __init pxa2xx_spi_init(void)
{
- return platform_driver_probe(&driver, pxa2xx_spi_probe);
+ return platform_driver_register(&driver);
}
subsys_initcall(pxa2xx_spi_init);
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
new file mode 100644
index 0000000..351d8a375
--- /dev/null
+++ b/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>");
diff --git a/arch/arm/plat-pxa/include/plat/ssp.h b/include/linux/pxa2xx_ssp.h
index fe43150..2f691e4 100644
--- a/arch/arm/plat-pxa/include/plat/ssp.h
+++ b/include/linux/pxa2xx_ssp.h
@@ -1,5 +1,5 @@
/*
- * ssp.h
+ * pxa2xx_ssp.h
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
*
@@ -16,8 +16,8 @@
* 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/io.h>
@@ -71,11 +71,8 @@
#define SSCR1_SPO (1 << 3) /* Motorola SPI SSPSCLK polarity setting */
#define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */
#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_RNE (1 << 3) /* Receive FIFO Not Empty */
#define SSSR_BSY (1 << 4) /* SSP Busy */
@@ -83,6 +80,31 @@
#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */
#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 */
#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */
@@ -139,6 +161,7 @@ enum pxa_ssp_type {
PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
PXA27x_SSP,
PXA168_SSP,
+ CE4100_SSP,
};
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);
void pxa_ssp_free(struct ssp_device *);
-#endif /* __ASM_ARCH_SSP_H */
+#endif
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
new file mode 100644
index 0000000..d3e1075
--- /dev/null
+++ b/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
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index b439eee..8ad93ee 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/pxa2xx_ssp.h>
#include <asm/irq.h>
@@ -33,7 +34,6 @@
#include <mach/hardware.h>
#include <mach/dma.h>
#include <mach/audio.h>
-#include <plat/ssp.h>
#include "../../arm/pxa2xx-pcm.h"
#include "pxa-ssp.h"
OpenPOWER on IntegriCloud