summaryrefslogtreecommitdiff
path: root/packages/linux/linux-ezx/pxa-spi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-ezx/pxa-spi.patch')
-rw-r--r--packages/linux/linux-ezx/pxa-spi.patch1041
1 files changed, 0 insertions, 1041 deletions
diff --git a/packages/linux/linux-ezx/pxa-spi.patch b/packages/linux/linux-ezx/pxa-spi.patch
deleted file mode 100644
index c0f66a8246..0000000000
--- a/packages/linux/linux-ezx/pxa-spi.patch
+++ /dev/null
@@ -1,1041 +0,0 @@
-Index: linux-2.6.16.5-ezx/arch/arm/mach-pxa/ezx-pcap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16.5-ezx/arch/arm/mach-pxa/ezx-pcap.c 2006-05-04 00:38:11.000000000 +0200
-@@ -0,0 +1,344 @@
-+/* Driver for Motorola PCAP2 as present in EZX phones
-+ *
-+ * This is both a SPI device driver for PCAP itself, as well as
-+ * an IRQ demultiplexer for handling PCAP generated events such as
-+ * headphone jack sense by downstream drivers.
-+ *
-+ * (C) 2006 by Harald Welte <laforge@openezx.org>
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/spi/spi.h>
-+
-+#include <asm/arch/ezx-pcap.h>
-+
-+/* lowlevel functions for register access */
-+
-+static struct {
-+ struct spi_transfer transfer;
-+ u_int32_t rx_buf;
-+ u_int32_t tx_buf;
-+ spinlock_t lock; /* lock protecting transfer + buffers */
-+} pcap_spi;
-+
-+
-+int ezx_pcap_write(u_int8_t reg_num, u_int32_t value)
-+{
-+ int ret;
-+ u_int32_t frame;
-+ value &= SSP_PCAP_REGISTER_VALUE_MASK;
-+
-+ spin_lock(&pcap_spi.lock);
-+
-+ pcap_spi.tx_buf = value | SSP_PCAP_REGISTER_WRITE_OP_BIT
-+ |(reg_num<<SSP_PCAP_REGISTER_ADDRESS_SHIFT);
-+
-+ /* we need to disable IRQ_GPIO1 because it's hardirq handler will
-+ * in turn want to use SPI to get the real interrupt source */
-+ irq_disable(IRQ_GPIO1);
-+ ret = spi_sync_nosleep_x(pcap_spi_dev, &pcap_spi.transfer);
-+ irq_enable(IRQ_GPIO1);
-+
-+ spin_unlock(&pcap_spi.lock);
-+
-+ return ret;
-+
-+}
-+EXPORT_SYMBOL_GPL(ezx_pcap_write);
-+
-+int ezx_pcap_read(u_int8_t reg_num, u_int32_t *value)
-+{
-+ int ret;
-+ u_int32_t frame;
-+ value &= SSP_PCAP_REGISTER_VALUE_MASK;
-+
-+ spin_lock(&pcap_spi.lock);
-+
-+
-+ pcap_spi.tx_buf = SSP_PCAP_REGISTER_READ_OP_BIT
-+ | (reg_num<<SSP_PCAP_REGISTER_ADDRESS_SHIFT);
-+
-+ /* we need to disable IRQ_GPIO1 because it's hardirq handler will
-+ * in turn want to use SPI to get the real interrupt source */
-+ irq_disable(IRQ_GPIO1);
-+ ret = spi_sync_nosleep_x(pcap_spi_dev, &pcap_spi.transfer);
-+ irq_enable(IRQ_GPIO1)
-+
-+ if (ret >= 0)
-+ *value = pcap_spi.transfer.rx_buf;
-+
-+ spin_unlock(&pcap_spi.lock);
-+
-+ return ret;
-+
-+}
-+EXPORT_SYMBOL_GPL(ezx_pcap_read);
-+
-+int ezx_pcap_bit_set(u_int32_t sspPcapBit, u_int8_t to)
-+{
-+ u_int32_t sspPcapRegisterBitValue;
-+ int ret;
-+ u_int8_t reg_num = (sspPcapBit & SSP_PCAP_REGISTER_ADDRESS_MASK)
-+ >> SSP_PCAP_REGISTER_ADDRESS_SHIFT;
-+
-+ if (reg_num == SSP_PCAP_ADJ_ISR_REGISTER)
-+ ssp_pcap_registerValue[reg_num] = 0;
-+
-+ sspPcapRegisterBitValue = (sspPcapBit & SSP_PCAP_REGISTER_VALUE_MASK);
-+
-+ if (to == 0)
-+ ssp_pcap_registerValue[sspPcapRegister] |= sspPcapRegisterBitValue;
-+ else
-+ ssp_pcap_registerValue[sspPcapRegister] &= ~sspPcapRegisterBitValue;
-+
-+ /* should care the return value */
-+ return ezx_pcap_write(num_reg, ssp_pcap_registerValue[num_reg]);
-+}
-+EXPORT_SYMBOL_GPL(ezx_pcap_bit_set);
-+
-+int ezx_pcap_read_bit(u_int32_t bit)
-+{
-+ int ret;
-+ u_int32_t tmp;
-+ u_int8_t reg_num = (bit & SSP_PCAP_REGISTER_ADDRESS_MASK)
-+ >> SSP_PCAP_REGISTER_ADDRESS_SHIFT;
-+
-+ ret = ezx_pcap_read(reg_num, &tmp);
-+ if (ret < 0)
-+ return ret;
-+
-+ return tmp & (bit & SSP_PCAP_REGISTER_VALUE_MASK);
-+}
-+EXPORT_SYMBOL_GPL(ezx_pcap_read_bit);
-+
-+static int ezx_pcap_init(void)
-+{
-+ /* initialize our transfer structure */
-+ memset(&pcap_spi, 0, sizeof(pcap_spi));
-+ pcap_spi.transfer.tx_buf = &pcap_spi.tx_buf;
-+ pcap_spi.transfer.rx_buf = &pcap_spi.rx_buf;
-+ pcap_spi.transfer.len = 4;
-+
-+ /* FIXME: resolve the spi_master and configure it apropriately */
-+
-+ /* initialize registers */
-+ /* FIXME: this should be board-level, not chip-level */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_ISR_USB4VI, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_USB4VM, 0);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_ISR_USB1VI, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_MSR_USB1VM, 0);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL, 1);
-+#ifdef FIXME
-+ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL3);
-+ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL3);
-+#endif
-+
-+ /* set SW1 sleep to keep SW1 1.3v in sync mode */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW1_MODE10, 0);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW1_MODE11, 0);
-+ /* SW1 active in sync mode */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW1_MODE00, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW1_MODE01, 0);
-+ /* at SW1 -core voltage to 1.30V */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW10_DVS, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW11_DVS, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW12_DVS, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_SW13_DVS, 0);
-+
-+ /* when STANDY2 PIN ACTIVE (high) set V3-- sram V8 -- pll off */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V3_STBY, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V3_LOWPWR, 0);
-+
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V8_STBY, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V8_LOWPWR, 0);
-+
-+ /* when STANDY2 PIN ACTIVE (high) set V4-- lcd only for e680 V6 ---
-+ * camera for e680 */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V4_STBY, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V4_LOWPWR, 1);
-+
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V6_STBY, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_VREG2_V6_LOWPWR, 0);
-+
-+ /* set Vc to low power mode when AP sleep */
-+ //SSP_PCAP_bit_set( SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_VC_STBY);
-+
-+ /* set VAUX2 to voltage 2.775V and low power mode when AP sleep */
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_1, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_0, 0);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_VAUX2_STBY, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_LOWPWR_CTRL_VAUX2_LOWPWR, 1);
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN, 1);
-+
-+#ifdef FIXME
-+ PGSR(GPIO34_TXENB) |= GPIO_bit(GPIO34_TXENB);
-+ if(SSP_PCAP_BIT_ONE == SSP_PCAP_get_bit_from_PCAP(SSP_PCAP_ADJ_BIT_PSTAT_USBDET_4V ))
-+ {
-+ accessory_bus_detect_handler(ACCESSORY_DEVICE_USB_PORT,ACCESSORY_DEVICE_STATUS_ATTACHED,NULL);
-+ }
-+ else
-+ {
-+ accessory_bus_detect_handler(ACCESSORY_DEVICE_USB_PORT,ACCESSORY_DEVICE_STATUS_DETACHED,NULL);
-+ }
-+#endif
-+ return 0;
-+}
-+
-+int ezx_pcap_vibrator_level()
-+{
-+ /* FIXME */
-+}
-+EXPORT_SYMBOL_GPL(ezx_pcap_vibrator_level);
-+
-+
-+/* MMC/SD specific functions */
-+
-+int ezx_pcap_mmcsd_power(int on)
-+{
-+ if (on)
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN, 1);
-+ else
-+ ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_AUX_VREG_VAUX2_EN, 0);
-+}
-+EXPORT_SYMBOL_GPL(ezx_pcap_mmcsd_power);
-+
-+/* IRQ Handling */
-+
-+/* Array indexed by BIT POSITION of PCAP register, returns IRQ number */
-+static unsigned int pcap2irq[] = {
-+ 0 = EZX_IRQ_ADCDONE,
-+ 1 = EZX_IRQ_TS,
-+ [7] = EZX_IRQ_USB4V,
-+ [10] = EZX_IRQ_USB1V,
-+ [12] = EZX_IRQ_MIC,
-+ [13] = EZX_IRQ_HEADJACK,
-+};
-+
-+/* Array indexed by IRQ NUMBER, returns PCAP absolute value */
-+static unsigned int irq2pcap[] = {
-+ [EZX_IRQ_ADCDONE] = SSP_PCAP_ADJ_BIT_ISR_ADCDONE2I,
-+ [EZX_IRQ_TS] = SSP_PCAP_ADJ_BIT_ISR_TSI,
-+ [EZX_IRQ_USB4V] = SSP_PCAP_ADJ_BIT_ISR_USB4VI,
-+ [EZX_IRQ_USB1V] = SSP_PCAP_ADJ_BIT_ISR_USB1VI,
-+ [EZX_IRQ_HEADJACK] = SSP_PCAP_ADJ_BIT_ISR_A1I,
-+ [EZX_IRQ_MIC] = SSP_PCAP_ADJ_BIT_ISR_MB2I,
-+};
-+
-+static void pcap_ack_irq(unsigned int irq)
-+{
-+ ezx_pcap_write(SSP_PCAP_ADJ_ISR_REGISTER, irq2pcap[irq]);
-+}
-+
-+static void pcap_mask_irq(unsigned int irq)
-+{
-+ ezx_pcap_write(SSP_PCAP_ADJ_MSR_REGISTER, irq2pcap[irq]);
-+}
-+
-+static void pcap_unmask_irq(unsigned int irq)
-+{
-+ u_int32_t tmp;
-+
-+ /* this needs to be atomic... but we're not on SMP so it is */
-+ ezx_pcap_read(SSP_PCAP_ADJ_MSR_REGISTER, &tmp);
-+ tmp &= ~irq2pcap[irq];
-+ ezx_pcap_write(SSP_PCAP_ADJ_MSR_REGISTER, tmp);
-+}
-+
-+static struct irqchip pcap_chip = {
-+ .ack = pcap_ack_irq,
-+ .mask = pcap_mask_irq,
-+ .unmask = pcap_unmask_irq,
-+};
-+
-+/* handler for interrupt received from PCAP via GPIO */
-+static void pcap_irq_demux_handler(unsigned int irq, struct irqdesc *desc,
-+ struct pt_regs *regs)
-+{
-+ int i;
-+ u_int32_t reg;
-+
-+ ezx_pcap_read(SSP_PCAP_ADJ_ISR_REGISTER, &reg);
-+
-+ for (i = 0; i < ARRAY_SIZE(pcap2irq); i++) {
-+ unsigned int irq = pcap2irq[i];
-+ if (irq == 0)
-+ continue;
-+ if (reg & (1 << i))
-+ desc_handle_irq(irq, desc, regs);
-+ }
-+}
-+
-+
-+/* SPI protocol driver initialization */
-+
-+static int __devinit ezx_pcap_probe(struct spi_device *spi)
-+{
-+ unsigned int ret, irq;
-+ struct ezx_pcap *chip;
-+
-+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-+ if (!chip)
-+ return ENOMEM;
-+
-+ dev_set_drvdata(&spi->dev, chip);
-+
-+ ret = ezx_pcap_init();
-+ if (ret < 0)
-+ return ret;
-+
-+ /* set up interrupt demultiplexing code for PCAP2 irqs */
-+ for (irq = EZX_IRQ(0); irq <= EZX_IRQ(5); irq++) {
-+ set_irq_chip(irq, &pcap_chip);
-+ set_irq_handler(irq, do_edge_IRQ);
-+ set_irq_flags(irq, IRQF_VALID);
-+ }
-+
-+ set_irq_chained_handler(IRQ_GPIO1, pcap_irq_demux_handler);
-+
-+ return 0;
-+}
-+
-+static void __devexit ezx_pcap_remove(struct spi_device *spi)
-+{
-+ /* remove interrupt demultiplexing code for PCAP2 irqs */
-+ set_irq_chained_handler(IRQ_GPIO1, NULL);
-+
-+ for (irq = EZX_IRQ(0); irq <= EZX_IRQ(5); irq++) {
-+ set_irq_chip(irq, NULL);
-+ set_irq_handler(irq, NULL);
-+ set_irq_flags(irq, 0);
-+ }
-+ // kfree
-+}
-+
-+static struct spi_driver ezx_pcap_driver = {
-+ .driver = {
-+ .name = "ezx-pcap",
-+ .bus = &spi_bus_type,
-+ .owner = THIS_MODULE,
-+ },
-+
-+ .probe = ezx_pcap_probe,
-+ .remove = __devexit_p(ezx_pcap_remove),
-+}
-+
-+
-+static int __init pcap_init(void)
-+{
-+ return spi_register_driver(&ezx_pcap_driver);
-+}
-+
-+static void __exit pcap_fini(void)
-+{
-+ spi_unregister_driver(&ezx_pcap_driver);
-+}
-+
-+module_init(pcap_init);
-+module_exit(pcap_fini);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
-+MODULE_DESCRIPTION("SPI Driver for Motorola PCAP2");
-+
-Index: linux-2.6.16.5-ezx/arch/arm/mach-pxa/ezx.c
-===================================================================
---- linux-2.6.16.5-ezx.orig/arch/arm/mach-pxa/ezx.c 2006-05-03 14:41:58.000000000 +0200
-+++ linux-2.6.16.5-ezx/arch/arm/mach-pxa/ezx.c 2006-05-03 14:49:25.000000000 +0200
-@@ -492,17 +492,61 @@
-
- /* touch screen */
-
-+/* SPI master devices */
-
--/* SSP device */
-+static int ezx_spi_init(unsigned int num)
-+{
-+ switch (num) {
-+ case 1:
-+ pxa_gpio_mode(GPIO24_SFRM_MD);
-+ pxa_gpio_mode(GPIO25_STXD_MD);
-+ pxa_gpio_mode(GPIO26_SRXD_MD);
-+ pxa_gpio_mode(GPIO29_SCLK_MD);
-+ break;
-+ case 2:
-+ pxa_gpio_mode(GPIO22_SCLK2_MD);
-+ pxa_gpio_mode(GPIO37_SFRM2_MD);
-+ pxa_gpio_mode(GPIO38_STXD2_MD);
-+ pxa_gpio_mode(GPIO88_SRXD2_MD);
-+ break;
-+ case 3:
-+ pxa_gpio_mode(GPIO52_SCLK3_MD);
-+ pxa_gpio_mode(GPIO83_SFRM3_MD);
-+ pxa_gpio_mode(GPIO81_STXD3_MD);
-+ pxa_gpio_mode(GPIO89_SRXD3_MD);
-+ break;
-+ default:
-+ return -ENODEV;
-+ }
-
--static struct platform_device ezx_ssp_pcap_device = {
-- .name = "ezx-ssp-pcap",
-- .dev = {
-- //.parent = ,
-- },
-- .id = -1,
-+ return 0;
-+}
-+
-+static struct pxa_spi_data {
-+ .init = &ezx_spi_init,
- };
-
-+/* SPI/SSP controller devices */
-+
-+static struct spi_board_info spi_board_info[] __initdata = {
-+ {
-+ .modalias = "ezx-pcap",
-+ .mode = SPI_MODE_0,
-+ .max_speed_hz = /* FIXME */,
-+ .bus_num = 1,
-+ .irq = IRQ_GPIO1,
-+ }, {
-+ .modalias = "ezx-snd",
-+ .mode = SPI_MODE_0,
-+ .max_speed_hz = /* FIXME */,
-+ .bus_num = 2,
-+ }, {
-+ .modalias = "ezx-snd",
-+ .mode = SPI_MODE_0,
-+ .max_speed_hz = /* FIXME */,
-+ .bus_num = 3,
-+ },
-+}
-
- static int step = FIRST_STEP;
- void handshake(void)
-@@ -704,7 +748,7 @@
-
- static struct platform_device *devices[] __initdata = {
- &ezx_bp_device,
-- &ezx_ssp_pcap_device,
-+ //&ezx_ssp_pcap_device,
- };
-
- static void __init
-@@ -806,6 +850,14 @@
- #endif
-
- platform_add_devices(devices, ARRAY_SIZE(devices));
-+
-+ /* register all three SPI busses */
-+ pxa_register_spi(1, &pxa_spi_data);
-+ //pxa_register_spi(2, &pxa_spi_data);
-+ //pxa_register_spi(3, &pxa_spi_data);
-+
-+ /* register information about SPI slaves attached to SPI */
-+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
- }
-
- MACHINE_START(EZX, "Motorola Ezx Platform")
-Index: linux-2.6.16.5-ezx/arch/arm/mach-pxa/spi.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.16.5-ezx/arch/arm/mach-pxa/spi.c 2006-05-04 00:40:25.000000000 +0200
-@@ -0,0 +1,486 @@
-+#include <linux/config.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/workqueue.h>
-+#include <linux/platform_device.h>
-+
-+#include <linux/spi/spi.h>
-+
-+#include <asm/arch/pxa-regs.h>
-+
-+/* board-specific data for one SPI controller */
-+struct pxa_spi_data {
-+ int (init)(unsigned int n);
-+};
-+
-+/* */
-+struct pxa_master {
-+ struct workqueue_struct *workqueue;
-+ struct work_struct work;
-+
-+ atomic_t busy;
-+ spinlock_t lock;
-+ struct list_head queue;
-+
-+ struct spi_master *master;
-+
-+ int port;
-+};
-+
-+static void ssp_enable(unsigned int port)
-+{
-+ SSCR0_P(port) &= ~SSCR0_SSE;
-+}
-+
-+static void ssp_disable(unsigned int port)
-+{
-+ SSCR0_P(port) |= SSCR0_SSE;
-+}
-+
-+/* low level utility functions, mainly copied from arch/arm/mach-pxa/ssp.c */
-+static int ssp_config(unsigned int port, u_int32_t mode, u_int32_t flags,
-+ u_int32_t psp_flags, u_int32_t speed)
-+{
-+ SSCR0_P(port) = (dev->speed | dev->mode);
-+ SSCR1_P(port) = dev->flags;
-+ SSPSP_P(port) = dev->psp_flags;
-+
-+ return 0;
-+}
-+
-+static int ssp_write_word(struct ssp_dev *dev, u32 data)
-+{
-+ while (!(SSSR_P(dev->port) & SSSR_TNF))
-+ cpu_relax();
-+
-+ SSDR_P(dev->port) = data;
-+
-+ return 0;
-+}
-+
-+static u_int32_t ssp_read_word(struct ssp_dev *dev)
-+{
-+ while (!(SSSR_P(dev->port) & SSSR_RNE))
-+ cpu_relax();
-+
-+ return SSDR_P(dev->port);
-+}
-+
-+static irqreturn_t pxa_spi_interrupt(int irq, void *dev_id,
-+ struct pt_regs *regs)
-+{
-+ struct spi_master *master = (struct spi_master *) dev_id;
-+ struct pxa_master *pm = master->private;
-+ unsigned int status = SSSR_P(pm->port);
-+
-+ SSSR_P(dev->port) = status; /* clear status bits */
-+
-+ if (status & SSSR_ROR)
-+ pritnk(KERN_WARNING "SPI(%d): receiver overrun\n", pm->port);
-+ if (status & SSSR_TUR)
-+ printk(KERN_WARNING "SPI(%d): transmitter underrun\n",
-+ pm->port);
-+
-+ if (status & SSSR_BCE)
-+ printk(KERN_WARNING "SPI(%d): bit count error\n", pm->port);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int pxa_spi_setup(struct spi_device *spi)
-+{
-+ struct pxa_master *pm;
-+ u_int32_t mode, flags, div;
-+
-+ if (!spi->max_speed_hz)
-+ return -EINVAL;
-+
-+ if (spi->bits_per_word < 4 ||
-+ spi->bits_per_word > 32)
-+ return -EINVAL;
-+
-+ if (!spi->bits_per_word)
-+ spi->bits_per_word = 8;
-+
-+ pm = spi_master_get_devdata(spi->master);
-+
-+ mode = SSCR0_Motorola; /* SPI, FIXME: other modes such as SSP! */
-+ flags = 0;
-+
-+ /* clock phase and polarity */
-+ if (spi->mode & SPI_CPHA)
-+ flags |= SSCR1_SPH;
-+ if (spi->mode & SPI_CPOL)
-+ flags |= SSCR1_SPO;
-+
-+ /* word size */
-+ mode |= (spi->bits_per_word & 0xf);
-+ if (spi->bits_per_word > 16)
-+ mode |= SSCR0_EDSS;
-+
-+#define PXA27x_SPI_CLOCK (13*1000*1000)
-+ div = PXA27x_SPI_CLOCK / spi->max_speed_hz;
-+
-+ return ssp_config(pm->port, mode, flags, 0, SSCR0_SerClkDiv(div));
-+}
-+
-+/* just add an SPI transfer to the workqueue */
-+static int pxa_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-+{
-+ struct pxa_master *pm;
-+ unsigned long flags;
-+
-+ pm = spi_master_get_devdata(spi->master);
-+
-+ spin_lock_irqsave(&pm->lock, flags);
-+
-+ list_add_tail(&m->queue, &pm->queue);
-+ queue_work(pm->workqueue, &pm->work);
-+
-+ spin_unlock_irqrestore(&pm->lock, flags);
-+}
-+
-+/* the actualy workqueue dequeueing workhorse */
-+static void pxa_spi_work(void *_pxa_master)
-+{
-+ struct pxa_master *pm = _pxa_master;
-+ unsigned long flags;
-+
-+ spn_lock_irqsave(&pm->lock, flags);
-+ atomic_inc(&pm->busy);
-+
-+ while (!list_empty(&pm->queue)) {
-+ struct spi_message *m;
-+ struct spi_device *spi;
-+ struct spi_transfer *t = NULL;
-+ int status;
-+
-+ m = container_of(pm->queue.next, struct spi_message, queue);
-+ list_del_init(&m->queue);
-+ spin_unlock_irqrestore(&pm->lock, flags);
-+
-+ spi = m->spi;
-+ cs_change = 1;
-+
-+ list_for_each_entry(t, &m->transfers, transfer_list) {
-+
-+#ifdef LATER
-+ if (cs_change) {
-+ pm->chipselect(spi, BITBANG_CS_ACTIVE);
-+ }
-+ cs_change = t->cs_change;
-+#endif
-+
-+ if (!t->tx_buf && !t->rx_buf && t->len) {
-+ status = -EINVAL;
-+ break;
-+ }
-+
-+ if (t->len) {
-+ if (!m->is_dma_mapped)
-+ t->rx_dma = t->tx_dma = 0;
-+ status = pxa_spi_transfer_x(t);
-+ }
-+ if (status != t->len) {
-+ if (status > 0)
-+ status = -EMSGSIZE;
-+ break;
-+ }
-+ m->actual_length += status;
-+ status = 0;
-+
-+ if (t->delay_usecs)
-+ udelay(t->delay_usecs);
-+
-+ if (!cs_change)
-+ continue;
-+ if (t->transfer_list.next == &m->transfers)
-+ break;
-+
-+#ifdef LATER
-+ pm->chipselect(spi, BITBANG_CS_INACTIVE);
-+#endif
-+ }
-+
-+ m->status = status;
-+ m->complete(m->context);
-+
-+#ifdef LATER
-+ if (!(status == 0 && cs_change))
-+ pm->chipselect(spi, BITBANG_CS_INACTIVE);
-+#endif
-+
-+ spin_lock_irqsave(&pm->lock, flags);
-+ }
-+ atomic_dec(&pm->busy);
-+ spin_unlock_irqrestore(&pm->lock, flags);
-+}
-+
-+/* actually transfer a given message */
-+static int pxa_spi_transfer_x(struct spi_device *spi, struct spi_transfer *t)
-+{
-+ struct spi_master *master = spi->master;
-+ struct pxa_master *pm = spi_master_get_devdata(master);
-+ unsigned int i, n;
-+
-+ ssp_enable(pm->port);
-+
-+ /* calculate number of bytes per fifo-write/read */
-+ n = spi->bits_per_word / 8;
-+ if (spi->bits_per_word % 8)
-+ n++;
-+
-+ /* FIXME: What about endianness? */
-+ for (i = 0; i < t->len; i += n) {
-+ u_int32_t tx, rx;
-+ if (n == 1) {
-+ tx = t->tx_buf[i];
-+ ssp_write_word(pm->port, tx);
-+ rx = ssp_read_word(pm->port);
-+ t->rx_buf[i] = rx & 0xff
-+ t->rx_buf[i+1] = rx >> 8;
-+ } else if (n == 3) {
-+ tx = t->tx_buf[i] | t->tx_buf[i+1] << 8 | t->tx_buf[i+2] << 16;
-+ ssp_write_word(pm->port, tx);
-+ rx = ssp_read_word(pm->port);
-+ t->rx_buf[i] = rx & 0xff;
-+ t->rx_buf[i+1] = rx >> 8;
-+ t->rx_buf[i+2] = rx >> 16;
-+ } else {
-+ tx = t->tx_buf[i] | t->tx_buf[i+1] << 8;
-+ tx |= t->tx_buf[i+2] << 16 | t->tx_buf[i+3] << 24;
-+ ssp_write_word(pm->port, tx);
-+ rx = ssp_read_word(pm->port);
-+ t->rx_buf[i] = rx & 0xff;
-+ t->rx_buf[i+1] = rx >> 8;
-+ t->rx_buf[i+2] = rx >> 16;
-+ t->rx_buf[i+3] = rx >> 24;
-+ }
-+ }
-+ ssp_disable(pm->port);
-+
-+ return 0;
-+}
-+
-+static int pxa_spi_cleanup(struct spi_device *spi)
-+{
-+ //FIXME;
-+ return 0;
-+}
-+
-+/* non-standard really-synchronous non-sleeping SPI handling */
-+int spi_sync_xfer_nosleep(struct spi_device *spi, struct spi_transfer *x)
-+{
-+ return pxa_spi_trasnfer_x(spi, x);
-+}
-+EXPORT_SYMBOL_GPL(spi_sync_xfer_nosleep);
-+
-+void pxa_spi_probe(struct platform_device *pdev)
-+{
-+ struct resource *mem_res;
-+ struct pxa_master *pm;
-+ struct spi_master *master;
-+ int ret = -ENOMEM;
-+
-+ pm = kzalloc(sizeof(*pm), GFP_KERNEL);
-+ if (!pm)
-+ return err;
-+
-+ master = spi_alloc_master(&pdev->dev, sizeof(*pp));
-+ if (!master)
-+ goto out_pm;
-+
-+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!mem_res) {
-+ ret = -EINVAL;
-+ goto out_mem;
-+ }
-+
-+ /* request register memory region */
-+ if (!request_mem_region(mem_res->start, mem_res->end - mem_res->start,
-+ "pxa-spi")) {
-+ ret = -EBUSY;
-+ goto out_master;
-+ }
-+
-+ if (!request_irq(platform_get_irq(pdev, 0), pxa_spi_interrupt,
-+ 0, "pxa-spi", master)) {
-+ ret = -EBUSY;
-+ goto out_mem;
-+ }
-+
-+ pm->master = master;
-+ /* FIXME: this is still PXA27x specific */
-+ switch (mem_res->start) {
-+ case SSCR0_1:
-+ pm->port = 1;
-+ break;
-+ case SSCR0_2:
-+ pm->port = 2;
-+ break;
-+ case SSCR0_3:
-+ pm->port = 3;
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ goto out_irq;
-+ }
-+ INIT_WORK(&pm->work, pxa_spi_work, pm);
-+ spin_lock_init(&pm->lock);
-+ INIT_LIST_HEAD(&pm->queue);
-+
-+ pm->workqueue = create_singlethread_workqueue(
-+ master->cdev.dev->bus_id);
-+ if (!pm->workqueue) {
-+ ret = -EBUSY;
-+ goto out_irq;
-+ }
-+
-+ master->cleanup = &pxa_spi_cleanup;
-+ master->setup = &pxa_spi_setup;
-+ master->transfer = &pxa_spi_transfer;
-+ master->transfer_nosleep = &spi_sync_xfer_nosleep;
-+ master->private = pm;
-+
-+ /* FIXME: this is still PXA27x specific */
-+ if (pm->port == 1)
-+ pxa_set_cken(CKEN23_SSP1);
-+ else if (pm->port == 2)
-+ pxa_set_cken(CKEN3_SSP2);
-+ else
-+ pxa_set_cken(CKEN4_SSP3);
-+
-+ ret = spi_register_master(master);
-+ if (ret < 0)
-+ goto out_workqueue;
-+
-+ platform_set_drvdata(pdev, pm);
-+
-+ return 0;
-+
-+out_workqueue:
-+ destroy_workqueue(pm->workqueue);
-+out_irq:
-+ free_irq(platform_get_irq(pdev, 0));
-+out_mem:
-+ release_mem_region(mem_res->start, mem_res->end-mem_res->start);
-+out_master:
-+ spi_free_master(master);
-+out_pm:
-+ kfree(pm);
-+
-+ return ret;
-+}
-+
-+void pxa_spi_remove()
-+{
-+}
-+
-+static struct platform_driver pxa_spi_driver = {
-+ .probe = pxa_spi_probe,
-+ .remove = pxa_spi_remove,
-+ .driver = {
-+ .name = "pxa-spi",
-+ },
-+};
-+
-+static int __init pxa_spi_init(void)
-+{
-+ return platform_driver_register(&pxa_spi_driver);
-+}
-+
-+static void __exit pxa_spi_fini(void)
-+{
-+ platform_driver_unregister(&pxa_spi_driver);
-+}
-+
-+module_init(pxa_spi_init);
-+module_exit(pxa_spi_fini);
-+
-+/* SPI/SSP master (controller) platform devices, registered by board-level init
-+ * code calling pxa_register_spi() */
-+
-+/* FIXME: this is still PXA27x specific */
-+static struct resource pxa_spi1_resources[] = {
-+ {
-+ .start = SSCR0_1,
-+ .end = SSACD_1,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = IRQ_SSP,
-+ .end = IRQ_SSP,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+static struct resource pxa_spi2_resources[] = {
-+ {
-+ .start = SSCR0_2,
-+ .end = SSACD_2,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = IRQ_SSP2,
-+ .end = IRQ_SSP2,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+static struct resource pxa_spi3_resources[] = {
-+ {
-+ .start = SSCR0_3,
-+ .end = SSACD_3,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = IRQ_SSP3,
-+ .end = IRQ_SSP3,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device pxa_spi_devices[] = {
-+ {
-+ .name = "pxa-spi",
-+ .dev = {
-+ },
-+ .id = -1,
-+ .resources = pxa_spi1_resources,
-+ .num_resourcs = ARRAY_SIZE(pxa_spi1_resources),
-+ },{
-+ .name = "pxa-spi",
-+ .dev = {
-+ },
-+ .id = -1,
-+ .resources = pxa_spi2_resources,
-+ .num_resources = ARRAY_SIZE(pxa_spi2_resources),
-+ },{
-+ .name = "pxa-spi",
-+ .dev = {
-+ },
-+ .id = -1;
-+ .resources = pxa_spi3_resources,
-+ .num_resources = ARRAY_SIZE(pxa_spi3_resources),
-+ },
-+};
-+
-+void pxa_register_spi(unsigned int n, struct pxa_spi_data *pdata)
-+{
-+ if (n < 1 || n > 3) {
-+ printk(KERN_WARN, "Board init code tries to use non-"
-+ "existing SPI Bus %u\n", n);
-+ return;
-+ }
-+
-+ /* n = 1..3, we need 0..2 */
-+ n--;
-+
-+ pxa_spi_devices[n]->dev.platform_data = pdata;
-+ register_platform_device(&pxa_spi_devices[n]);
-+
-+ /* Setup GPIO alternate functions */
-+ if (pdata->init)
-+ pdata->init(n);
-+}
-+EXPORT_SYMBOL_GPL(pxa_register_spi);
-+
-+MODULE_DESCRIPTION("New PXA SPI/SSP driver");
-+MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
-+MODULE_LICENSE("GPL");
-Index: linux-2.6.16.5-ezx/include/asm-arm/arch-pxa/irqs.h
-===================================================================
---- linux-2.6.16.5-ezx.orig/include/asm-arm/arch-pxa/irqs.h 2006-05-03 14:41:58.000000000 +0200
-+++ linux-2.6.16.5-ezx/include/asm-arm/arch-pxa/irqs.h 2006-05-03 14:42:00.000000000 +0200
-@@ -217,3 +217,12 @@
- #define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1)
- #define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2)
- #define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3)
-+
-+/* EZX Interrupts (CONFIG_EZX) */
-+#define EZX_IRQ(x) (IRQ_BOARD_START + (x))
-+#define EZX_IRQ_ADCDONE EZX_IRQ(0) /* PCAP */
-+#define EZX_IRQ_TSM EZX_IRQ(1) /* PCAP */
-+#define EZX_IRQ_USB4V EZX_IRQ(2) /* PCAP */
-+#define EZZ_IRQ_USB1V EZX_IRQ(3) /* PCAP */
-+#define EZX_IRQ_HEADJACK EZX_IRQ(4) /* PCAP */
-+#define EZX_IRQ_MIC EZX_IRQ(5) /* PCAP */
-Index: linux-2.6.16.5-ezx/include/asm/arch/pxa-regs.h
-===================================================================
---- linux-2.6.16.5-ezx.orig/include/asm/arch/pxa-regs.h 2006-05-03 14:41:58.000000000 +0200
-+++ linux-2.6.16.5-ezx/include/asm/arch/pxa-regs.h 2006-05-03 14:42:01.000000000 +0200
-@@ -1374,6 +1374,7 @@
- #define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN)
- #define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN)
- #define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN)
-+#define GPIO22_SCLK2_MD (22 | GPIO_ALT_FN_3_IN)
- #define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT)
- #define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT)
- #define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT)
-@@ -1384,6 +1385,7 @@
- #define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT)
- #define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN)
- #define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN)
-+#define GPIO29_SCLK_MD (29 | GPIO_ALT_FN_3_IN)
- #define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT)
- #define GPIO30_USB_P3_2 (30 | GPIO_ALT_FN_3_OUT)
- #define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT)
-@@ -1402,7 +1404,9 @@
- #define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN)
- #define GPIO36_USB_P2_4_MD (36 | GPIO_ALT_FN_1_OUT)
- #define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN)
-+#define GPIO37_SFRM2_MD (37 | GPIO_ALT_FN_2_IN)
- #define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN)
-+#define GPIO38_STXD2_MD (38 | GPIO_ALT_FN_2_OUT)
- #define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT)
- #define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT)
- #define GPIO39_USB_P2_6_MD (39 | GPIO_ALT_FN_1_OUT)
-@@ -1432,6 +1436,7 @@
- #define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT)
- #define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT)
- #define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT)
-+#define GPIO52_SCLK3_MD (52 | GPIO_ALT_FN_2_OUT)
- #define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT)
- #define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT)
- #define GPIO53_FFRXD_MD (53 | GPIO_ALT_FN_1_IN)
-@@ -1477,13 +1482,17 @@
- #define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT)
- #define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT)
- #define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN)
-+#define GPIO81_STXD3_MD (81 | GPIO_ALT_FN_1_OUT)
- #define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT)
- #define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN)
- #define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT)
- #define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN)
-+#define GPIO83_SFRM3_MD (83 | GPIO_ALT_FN_1_IN)
- #define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT)
- #define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN)
- #define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT)
-+#define GPIO88_SRXD2_MD (88 | GPIO_ALT_FN_2_IN)
-+#define GPIO90_SRXD3_MD (89 | GPIO_ALT_FN_1_IN)
- #define GPIO90_USB_P3_5 (90 | GPIO_ALT_FN_2_IN)
- #define GPIO91_USB_P3_1 (91 | GPIO_ALT_FN_2_IN)
- #define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT)
-Index: linux-2.6.16.5-ezx/include/linux/spi/spi.h
-===================================================================
---- linux-2.6.16.5-ezx.orig/include/linux/spi/spi.h 2006-05-03 15:11:08.000000000 +0200
-+++ linux-2.6.16.5-ezx/include/linux/spi/spi.h 2006-05-04 00:38:42.000000000 +0200
-@@ -205,6 +205,9 @@
- int (*transfer)(struct spi_device *spi,
- struct spi_message *mesg);
-
-+ /* bidirectional bulk transfer, synchronous, non-sleeping */
-+ int (*transfer_nosleep)(struct spi_device *spi,
-+ struct spi_message *mesg);
- /* called on release() to free memory provided by spi_master */
- void (*cleanup)(const struct spi_device *spi);
- };
-@@ -485,6 +488,16 @@
- return spi->master->transfer(spi, message);
- }
-
-+static inline int
-+spi_sync_nosleep(struct spi_device *spi, struct spi_message *msg)
-+{
-+ if (!spi->master->transfer_nosleep)
-+ return -EIO;
-+
-+ msg->spi = master;
-+ return spi->master->transfer_nosleep(spi, message);
-+}
-+
- /*---------------------------------------------------------------------------*/
-
- /* All these synchronous SPI transfer routines are utilities layered