diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-12-29 01:05:14 -0700 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-29 01:05:50 -0700 |
commit | 94a544a4e8d05a027613443c529c399c39cc3371 (patch) | |
tree | edada38e93a958a918b5826eaef173b1b92079d1 | |
parent | 496a2e360a34e1f41c336d23947f800216cb9bdf (diff) | |
parent | 21486af0f34d03b813b023d7a2b887b329f60486 (diff) |
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
27 files changed, 547 insertions, 138 deletions
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx index 6bb916d57c95..68a4fe3818a1 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 f1a7703d771b..93f59f877fc6 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 a9926bb75922..b88d601a8090 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 821229acabe6..3b8dcac2b8fb 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 aaa1166df964..c4f9c715be73 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 ed0dbfdb22ed..b20b944c337c 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 76d93a25bab6..f09526f52152 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 d51ee3d25e70..3ab6fd369584 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 b87cecd9bbdc..000000000000 --- 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 41aa89e35772..8051925d457c 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 1499493cd070..4a3fe450c20f 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 c77e8f30a439..a5596f9b17bc 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 93a191c889df..c05eee326234 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 f736119f1ebf..4fd5572f6995 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 738adc1773fd..325f6ac6b591 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 0ee1df49606d..7b5765dacbd9 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 565d062f51d5..bdb02a0ae1b7 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 fefde9848d82..1b8b71b3c719 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 dea46a2d089b..f5c9f3032c31 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 c6357e554aba..58b79809d20c 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 6efac5fd439d..1906840c1113 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 7ec375b6c0c3..3a42463c92a4 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 e76b1afafe07..95928833855b 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 000000000000..351d8a375b57 --- /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 fe43150690ed..2f691e4e6222 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 000000000000..d3e1075f7b60 --- /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 b439eee462cb..8ad93ee2e92b 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" |