diff options
| -rw-r--r-- | packages/linux/linux-rp-2.6.26/collie.patch | 1883 | ||||
| -rw-r--r-- | packages/linux/linux-rp-2.6.26/collie_keymap.patch | 420 | ||||
| -rw-r--r-- | packages/linux/linux-rp-2.6.26/defconfig-collie | 1236 | ||||
| -rw-r--r-- | packages/linux/linux-rp-2.6.26/initramfs-config-collie | 810 | ||||
| -rw-r--r-- | packages/linux/linux-rp.inc | 1 | ||||
| -rw-r--r-- | packages/linux/linux-rp_2.6.24.bb | 2 | ||||
| -rw-r--r-- | packages/linux/linux-rp_2.6.26.bb | 23 |
7 files changed, 3929 insertions, 446 deletions
diff --git a/packages/linux/linux-rp-2.6.26/collie.patch b/packages/linux/linux-rp-2.6.26/collie.patch new file mode 100644 index 0000000000..00b7d881a5 --- /dev/null +++ b/packages/linux/linux-rp-2.6.26/collie.patch @@ -0,0 +1,1883 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index c7ad324..daa2e0a 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -998,7 +998,7 @@ config CPU_FREQ_SA1100 + + config CPU_FREQ_SA1110 + bool +- depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) ++ depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3 || SA1100_COLLIE) + default y + + config CPU_FREQ_INTEGRATOR +diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c +index e508028..36f726c 100644 +--- a/arch/arm/mach-sa1100/dma.c ++++ b/arch/arm/mach-sa1100/dma.c +@@ -39,7 +39,7 @@ typedef struct { + + static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS]; + +-static spinlock_t dma_list_lock; ++static DEFINE_SPINLOCK(dma_list_lock); + + + static irqreturn_t dma_irq_handler(int irq, void *dev_id) +diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c +index 9caed30..79e19bf 100644 +--- a/drivers/input/keyboard/locomokbd.c ++++ b/drivers/input/keyboard/locomokbd.c +@@ -265,6 +265,7 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) + for (i = 0; i < LOCOMOKBD_NUMKEYS; i++) + set_bit(locomokbd->keycode[i], input_dev->keybit); + clear_bit(0, input_dev->keybit); ++ locomo_writel(0, locomokbd->base + LOCOMO_KSC); + + /* attempt to get the interrupt */ + err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd); +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 9f93c29..33fc5d6 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -72,4 +72,10 @@ config MCP_UCB1200_TS + tristate "Touchscreen interface support" + depends on MCP_UCB1200 && INPUT + ++config MCP_COLLIE_TS ++ tristate "Touchscreen collie support" ++ depends on MCP_UCB1200 && INPUT && !MCP_UCB1200_TS ++ ---help--- ++ Driver for touchscreen on collie - sharp sl-5500. ++ + endmenu +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 33daa2f..0885ccd 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -16,7 +16,7 @@ obj-$(CONFIG_MCP) += mcp-core.o + obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o + obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o + obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o +- ++obj-$(CONFIG_MCP_COLLIE_TS) += collie-ts.o + ifeq ($(CONFIG_SA1100_ASSABET),y) + obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o + endif +diff --git a/drivers/mfd/collie-ts.c b/drivers/mfd/collie-ts.c +new file mode 100644 +index 0000000..ddde5fc +--- /dev/null ++++ b/drivers/mfd/collie-ts.c +@@ -0,0 +1,449 @@ ++/* ++ * Touchscreen driver for UCB1x00-based touchscreens ++ * ++ * Copyright (C) 2001 Russell King, All Rights Reserved. ++ * Copyright (C) 2005 Pavel Machek ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * 21-Jan-2002 <jco@ict.es> : ++ * ++ * Added support for synchronous A/D mode. This mode is useful to ++ * avoid noise induced in the touchpanel by the LCD, provided that ++ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin. ++ * It is important to note that the signal connected to the ADCSYNC ++ * pin should provide pulses even when the LCD is blanked, otherwise ++ * a pen touch needed to unblank the LCD will never be read. ++ */ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/smp.h> ++#include <linux/smp_lock.h> ++#include <linux/sched.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/string.h> ++#include <linux/input.h> ++#include <linux/device.h> ++#include <linux/freezer.h> ++#include <linux/slab.h> ++#include <linux/kthread.h> ++ ++#include <asm/dma.h> ++#include <asm/semaphore.h> ++#include <asm/arch/collie.h> ++#include <asm/mach-types.h> ++ ++#include "ucb1x00.h" ++ ++struct ucb1x00_ts { ++ struct input_dev *idev; ++ struct ucb1x00 *ucb; ++ ++ wait_queue_head_t irq_wait; ++ struct task_struct *rtask; ++ u16 x_res; ++ u16 y_res; ++ ++ unsigned int adcsync:1; ++}; ++ ++static int adcsync; ++ ++/********************************** ++ ++ ................ ++ . . = 340 ++ . . ++ . ^. ++ . ^. ++ . ^. ++ . ^. ++ . . ++ . X. = 10 ++ . <<<<<<<< Y . ++ ................ ++ . Sharp =200 ++ . . ++ . - O - . ++ . . ++ ................ ++ ++**********************************/ ++ ++ ++static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) ++{ ++ struct input_dev *idev = ts->idev; ++ ++ input_report_abs(idev, ABS_X, x); ++ input_report_abs(idev, ABS_Y, y); ++ input_report_abs(idev, ABS_PRESSURE, pressure); ++ input_report_key(idev, BTN_TOUCH, 1); ++ input_sync(idev); ++} ++ ++static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) ++{ ++ struct input_dev *idev = ts->idev; ++ ++ input_report_abs(idev, ABS_PRESSURE, 0); ++ input_report_key(idev, BTN_TOUCH, 0); ++ input_sync(idev); ++} ++ ++/* ++ * Switch to interrupt mode. This set touchscreen to interrupt ++ * mode, so that chip is able to send interrupt. ++ */ ++static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts) ++{ ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, ++ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | ++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | ++ UCB_TS_CR_MODE_INT); ++} ++ ++/* ++ * Switch to pressure mode, and read pressure. We don't need to wait ++ * here, since both plates are being driven. ++ * ++ * set_read_pressure() in sharp code ++ */ ++static inline void ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) ++{ ++ ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0); ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, ++ UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW | ++ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); ++ ++ ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | ++ UCB_ADC_INP_AD2 | ++ UCB_ADC_SYNC_ENA); ++ udelay(100); ++ ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | ++ UCB_ADC_INP_AD2 | ++ UCB_ADC_SYNC_ENA | UCB_ADC_START); ++} ++ ++/* ++ * Switch to X position mode and measure Y plate. We switch the plate ++ * configuration in pressure mode, then switch to position mode. This ++ * gives a faster response time. Even so, we need to wait about 55us ++ * for things to stabilise. ++ */ ++static inline void ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) ++{ ++ ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, ++ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | ++ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); ++ ++ ++ ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | ++ UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA); ++ udelay(100); ++ ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | ++ UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA | ++ UCB_ADC_START); ++} ++ ++/* ++ * Switch to Y position mode and measure X plate. We switch the plate ++ * configuration in pressure mode, then switch to position mode. This ++ * gives a faster response time. Even so, we need to wait about 55us ++ * for things to stabilise. ++ */ ++static inline void ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) ++{ ++ ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); ++ ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, ++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | ++ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); ++ ++ ++ ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | ++ UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA); ++ udelay(100); ++ ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | ++ UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA | ++ UCB_ADC_START); ++} ++ ++/* ++ * Switch to X plate resistance mode. Set MX to ground, PX to ++ * supply. Measure current. ++ */ ++static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts) ++{ ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, ++ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | ++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); ++ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); ++} ++ ++/* ++ * Switch to Y plate resistance mode. Set MY to ground, PY to ++ * supply. Measure current. ++ */ ++static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts) ++{ ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, ++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | ++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); ++ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); ++} ++ ++/* ++ * This is a RT kernel thread that handles the ADC accesses ++ * (mainly so we can use semaphores in the UCB1200 core code ++ * to serialise accesses to the ADC). ++ */ ++static int ucb1x00_thread(void *_ts) ++{ ++ struct ucb1x00_ts *ts = _ts; ++ struct task_struct *tsk = current; ++ DECLARE_WAITQUEUE(wait, tsk); ++ int state; ++ ++ /* ++ * We could run as a real-time thread. However, thus far ++ * this doesn't seem to be necessary. ++ */ ++ ++ add_wait_queue(&ts->irq_wait, &wait); ++ ++ while (!kthread_should_stop()) { ++ unsigned int data[3]; ++ ++ for (state=0; state<3; state++) { ++ ++ ucb1x00_adc_enable(ts->ucb); ++ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING); ++ switch (state) { ++ /* Order matters here; last measurement seems to be more noisy then the ++ rest, and we care about pressure least */ ++ case 2: ucb1x00_ts_read_pressure(ts); ++ break; ++ case 0: ucb1x00_ts_read_ypos(ts); ++ break; ++ case 1: ucb1x00_ts_read_xpos(ts); ++ break; ++ } ++ /* wait for adc */ ++ try_to_freeze(); ++ schedule_timeout(1000 * HZ); ++ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING); ++ data[state] = UCB_ADC_DAT(ucb1x00_reg_read(ts->ucb, UCB_ADC_DATA)); ++ ucb1x00_adc_disable(ts->ucb); ++ } ++ ++ /* If not pressed any more, try to sleep! */ ++ if (data[2] < 300) { ++ set_task_state(tsk, TASK_INTERRUPTIBLE); ++ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING); ++ ucb1x00_ts_mode_int(ts); ++ ucb1x00_disable(ts->ucb); ++ ucb1x00_ts_event_release(ts); ++ try_to_freeze(); ++ schedule_timeout(1000 * HZ); ++ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING); ++ ucb1x00_enable(ts->ucb); ++ } else { ++ ucb1x00_ts_evt_add(ts, data[2], data[1], data[0]); ++ } ++ ucb1x00_disable(ts->ucb); ++ msleep(20); ++ ucb1x00_enable(ts->ucb); ++ } ++ ++ remove_wait_queue(&ts->irq_wait, &wait); ++ ++ ts->rtask = NULL; ++ return 0; ++} ++ ++/* ++ * We only detect touch screen _touches_ with this interrupt ++ * handler, and even then we just schedule our task. ++ */ ++static void ucb1x00_ts_irq(int idx, void *id) ++{ ++ struct ucb1x00_ts *ts = id; ++ wake_up(&ts->irq_wait); ++} ++ ++static void ucb1x00_adc_irq(int idx, void *id) ++{ ++ struct ucb1x00_ts *ts = id; ++ wake_up(&ts->irq_wait); ++} ++ ++static int ucb1x00_ts_open(struct input_dev *idev) ++{ ++ struct ucb1x00_ts *ts = input_get_drvdata(idev); ++ int ret = 0; ++ ++ BUG_ON(ts->rtask); ++ ++ init_waitqueue_head(&ts->irq_wait); ++ ++ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); ++ if (ret < 0) ++ return ret; ++ ++ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_ADC, ucb1x00_adc_irq, ts); ++ if (ret < 0) { ++ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); ++ return ret; ++ } ++ ++ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING); ++ ++ /* ++ * If we do this at all, we should allow the user to ++ * measure and read the X and Y resistance at any time. ++ */ ++ ucb1x00_adc_enable(ts->ucb); ++ ts->x_res = ucb1x00_ts_read_xres(ts); ++ ts->y_res = ucb1x00_ts_read_yres(ts); ++ ucb1x00_adc_disable(ts->ucb); ++ ++ if (machine_is_collie()) { ++ ucb1x00_io_set_dir(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); ++ } ++ ++ ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd"); ++ if (!IS_ERR(ts->rtask)) { ++ ret = 0; ++ } else { ++ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); ++ ts->rtask = NULL; ++ ret = -EFAULT; ++ } ++ ++ return ret; ++} ++ ++/* ++ * Release touchscreen resources. Disable IRQs. ++ */ ++static void ucb1x00_ts_close(struct input_dev *idev) ++{ ++ struct ucb1x00_ts *ts = input_get_drvdata(idev); ++ ++ if (ts->rtask) ++ kthread_stop(ts->rtask); ++ ++ ucb1x00_enable(ts->ucb); ++ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); ++ ucb1x00_free_irq(ts->ucb, UCB_IRQ_ADC, ts); ++ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); ++ ucb1x00_disable(ts->ucb); ++} ++ ++#ifdef CONFIG_PM ++static int ucb1x00_ts_resume(struct ucb1x00_dev *dev) ++{ ++ struct ucb1x00_ts *ts = dev->priv; ++ ++ if (ts->rtask != NULL) { ++ /* ++ * Restart the TS thread to ensure the ++ * TS interrupt mode is set up again ++ * after sleep. ++ */ ++ wake_up(&ts->irq_wait); ++ } ++ return 0; ++} ++#else ++#define ucb1x00_ts_resume NULL ++#endif ++ ++ ++/* ++ * Initialisation. ++ */ ++static int ucb1x00_ts_add(struct ucb1x00_dev *dev) ++{ ++ struct ucb1x00_ts *ts; ++ struct input_dev *idev; ++ int err; ++ ++ ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL); ++ idev = input_allocate_device(); ++ if (!ts || !idev) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ ts->ucb = dev->ucb; ++ ts->idev = idev; ++ ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; ++ ++ input_set_drvdata(idev, ts); ++ idev->name = "Touchscreen panel"; ++ idev->id.product = ts->ucb->id; ++ idev->open = ucb1x00_ts_open; ++ idev->close = ucb1x00_ts_close; ++ ++ __set_bit(EV_ABS, idev->evbit); ++ __set_bit(ABS_X, idev->absbit); ++ __set_bit(ABS_Y, idev->absbit); ++ __set_bit(ABS_PRESSURE, idev->absbit); ++ ++ input_set_abs_params(ts->idev, ABS_X, 0, 450, 0, 0); ++ input_set_abs_params(ts->idev, ABS_Y, 200, 800, 0, 0); ++ input_set_abs_params(ts->idev, ABS_PRESSURE, 400, 800, 0, 0); ++ ++ ++ err = input_register_device(idev); ++ if (err) ++ goto fail; ++ ++ dev->priv = ts; ++ ++ return 0; ++ ++ fail: ++ input_free_device(idev); ++ kfree(ts); ++ return err; ++} ++ ++static void ucb1x00_ts_remove(struct ucb1x00_dev *dev) ++{ ++ struct ucb1x00_ts *ts = dev->priv; ++ ++ input_unregister_device(ts->idev); ++ kfree(ts); ++} ++ ++static struct ucb1x00_driver ucb1x00_ts_driver = { ++ .add = ucb1x00_ts_add, ++ .remove = ucb1x00_ts_remove, ++ .resume = ucb1x00_ts_resume, ++}; ++ ++static int __init ucb1x00_ts_init(void) ++{ ++ return ucb1x00_register_driver(&ucb1x00_ts_driver); ++} ++ ++static void __exit ucb1x00_ts_exit(void) ++{ ++ ucb1x00_unregister_driver(&ucb1x00_ts_driver); ++} ++ ++module_param(adcsync, int, 0444); ++module_init(ucb1x00_ts_init); ++module_exit(ucb1x00_ts_exit); ++ ++MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); ++MODULE_DESCRIPTION("UCB1x00 touchscreen driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h +index a8ad8a0..137b043 100644 +--- a/drivers/mfd/ucb1x00.h ++++ b/drivers/mfd/ucb1x00.h +@@ -34,7 +34,10 @@ + #define UCB_IE_TCLIP (1 << 14) + #define UCB_IE_ACLIP (1 << 15) + ++/* UCB1200 irqs */ ++#define UCB_IRQ_ADC 11 + #define UCB_IRQ_TSPX 12 ++#define UCB_IRQ_TSMX 13 + + #define UCB_TC_A 0x05 + #define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ +diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c +index 3b4e55c..0ae741d 100644 +--- a/drivers/net/wireless/hostap/hostap_cs.c ++++ b/drivers/net/wireless/hostap/hostap_cs.c +@@ -35,7 +35,7 @@ static int ignore_cis_vcc; + module_param(ignore_cis_vcc, int, 0444); + MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); + +- ++int activar=0; + /* struct local_info::hw_priv */ + struct hostap_cs_priv { + dev_node_t node; +@@ -499,11 +499,13 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev) + + PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); + p_dev->conf.IntType = INT_MEMORY_AND_IO; +- ++ ++ activar=0; + ret = prism2_config(p_dev); + if (ret) { + PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); + } ++ activar=1; + + return ret; + } +diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c +index 13d5882..6f24d66 100644 +--- a/drivers/net/wireless/hostap/hostap_hw.c ++++ b/drivers/net/wireless/hostap/hostap_hw.c +@@ -54,6 +54,7 @@ + #include "hostap.h" + #include "hostap_ap.h" + ++extern int activar; + + /* #define final_version */ + +@@ -1497,6 +1498,8 @@ static int prism2_hw_config(struct net_device *dev, int initial) + if (local->hw_downloading) + return 1; + ++ activar=1; ++ + if (prism2_hw_init(dev, initial)) { + return local->no_pri ? 0 : 1; + } +@@ -2628,8 +2631,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) + int events = 0; + u16 ev; + +- iface = netdev_priv(dev); +- local = iface->local; ++ ++ // Todos los parametros de entrada son correctos (no son nulos). De momento esta es la unica forma que conozco de detectar el problema. ++ if (!activar) { ++ printk("hostap_hw.c: INTERRUPT BEFORE DEVICE INIT!\n"); ++ return IRQ_HANDLED; ++ } ++ ++ iface = netdev_priv(dev); ++ local = iface->local; + + prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); + +diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c +index 3a874fc..df58aa3 100644 +--- a/drivers/net/wireless/hostap/hostap_pci.c ++++ b/drivers/net/wireless/hostap/hostap_pci.c +@@ -19,6 +19,7 @@ + + #include "hostap_wlan.h" + ++int activar=1; + + static char *dev_info = "hostap_pci"; + +diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c +index cbf15d7..4475174 100644 +--- a/drivers/net/wireless/hostap/hostap_plx.c ++++ b/drivers/net/wireless/hostap/hostap_plx.c +@@ -21,7 +21,7 @@ + #include <asm/io.h> + + #include "hostap_wlan.h" +- ++int activar=1; + + static char *dev_info = "hostap_plx"; + +diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c +index c5b2a44..eecbe8c 100644 +--- a/drivers/pcmcia/sa1100_generic.c ++++ b/drivers/pcmcia/sa1100_generic.c +@@ -81,13 +81,14 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev) + return ret; + } + +-static struct device_driver sa11x0_pcmcia_driver = { +- .probe = sa11x0_drv_pcmcia_probe, +- .remove = soc_common_drv_pcmcia_remove, +- .name = "sa11x0-pcmcia", +- .bus = &platform_bus_type, +- .suspend = pcmcia_socket_dev_suspend, +- .resume = pcmcia_socket_dev_resume, ++static struct platform_driver sa11x0_pcmcia_driver = { ++ .driver = { ++ .name = "sa11x0-pcmcia", ++ .probe = sa11x0_drv_pcmcia_probe, ++ .remove = soc_common_drv_pcmcia_remove, ++ .suspend= pcmcia_socket_dev_suspend, ++ .resume = pcmcia_socket_dev_resume, ++ }, + }; + + /* sa11x0_pcmcia_init() +@@ -100,7 +101,7 @@ static struct device_driver sa11x0_pcmcia_driver = { + */ + static int __init sa11x0_pcmcia_init(void) + { +- return driver_register(&sa11x0_pcmcia_driver); ++ return platform_driver_register(&sa11x0_pcmcia_driver); + } + + /* sa11x0_pcmcia_exit() +@@ -110,7 +111,7 @@ static int __init sa11x0_pcmcia_init(void) + */ + static void __exit sa11x0_pcmcia_exit(void) + { +- driver_unregister(&sa11x0_pcmcia_driver); ++ platform_driver_unregister(&sa11x0_pcmcia_driver); + } + + MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>"); +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 66ec5d8..aba38d7 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -123,6 +123,10 @@ config SPI_MPC52xx_PSC + This enables using the Freescale MPC52xx Programmable Serial + Controller in master SPI mode. + ++config SPI_LOCOMO ++ tristate "Locomo SPI master" ++ depends on SPI_MASTER && SHARP_LOCOMO && EXPERIMENTAL ++ + config SPI_MPC83xx + tristate "Freescale MPC83xx/QUICC Engine SPI controller" + depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 7fca043..b89992b 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o + obj-$(CONFIG_SPI_TXX9) += spi_txx9.o + obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o + obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o ++obj-$(CONFIG_SPI_LOCOMO) += locomo_spi.o + # ... add above this line ... + + # SPI protocol drivers (device/link on bus) +diff --git a/drivers/spi/locomo_spi.c b/drivers/spi/locomo_spi.c +new file mode 100644 +index 0000000..d3a4bd9 +--- /dev/null ++++ b/drivers/spi/locomo_spi.c +@@ -0,0 +1,1097 @@ ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/stat.h> ++#include <linux/delay.h> ++#include <linux/wait.h> ++#include <linux/interrupt.h> ++#include <asm/hardware/locomo.h> ++#include <asm/errno.h> ++#include <linux/mmc/host.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/mmc_spi.h> ++#include <linux/workqueue.h> ++#include <linux/spinlock.h> ++#include <linux/list.h> ++#include "locomo_spi.h" ++static struct locomospi_dev * spidev; ++static struct work_struct transfer_wq; ++int delay; ++ ++char* transtxbuf=(char*)NULL; ++char* transrxbuf=(char*)NULL; ++int transfercount=0, transfersize=0; ++static DECLARE_WAIT_QUEUE_HEAD(transferqueue); ++/* MMC_SPI functions *********************************************************/ ++ ++static int locomommcspi_init(struct device *dev, irqreturn_t (*isr)(int, void*), void *mmc) ++{ ++ int result; ++ result=request_irq(IRQ_LOCOMO_CARDDETECT, isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "locomo-spi", mmc); ++ return result; ++} ++ ++static void locomommcspi_exit(struct device *dev, void* mmc) ++{ ++ free_irq(IRQ_LOCOMO_CARDDETECT, mmc); ++} ++ ++static int locomommcspi_getro(struct device *dev) ++{ ++ return locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT) > 0 ? 1 : 0; ++} ++ ++static void locomommcspi_setpower(struct device *dev, unsigned int mask) ++{ ++ if(!mask && spidev->card_power) ++ locomospi_power(0); ++ else if( !spidev->card_power ) ++ locomospi_power(1); ++ ++} ++ ++ ++static struct mmc_spi_platform_data colliemmc ={ ++ .init = locomommcspi_init, ++ .exit = locomommcspi_exit, ++ .detect_delay = 200, ++ .get_ro = locomommcspi_getro, ++ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, ++ .setpower = locomommcspi_setpower, ++ .powerup_msecs = 200, ++}; ++ ++/* Utility function **********************************************************/ ++ ++static void locomospi_power(int on) ++{ ++ locomo_gpio_write(spidev->ldev->dev.parent, LOCOMO_GPIO_CARD_POWER, on); ++ spidev->card_power=on; ++ printk(KERN_DEBUG "locomospi: power %d\n",on); ++} ++ ++static void locomospi_setclock(unsigned int div, unsigned int clock) ++{ ++ u16 r = ioread16(spidev->base+LOCOMO_SPIMD); ++ div &= 0x7; ++ clock &= 0x3; ++ if(clock != spidev->clock_base || div != spidev->clock_div){ ++ r &= ~(LOCOMO_SPI_XSEL | LOCOMO_SPI_CLKSEL | LOCOMO_SPI_XEN); ++ iowrite16(r,spidev->base+LOCOMO_SPIMD); ++ r |= (div | (clock <<3) | LOCOMO_SPI_XEN); ++ iowrite16(r,spidev->base+LOCOMO_SPIMD); ++ spidev->clock_div = div; ++ spidev->clock_base = clock; ++ udelay(300); ++ } ++ ++} ++// returns 1 if card ist present, 0 otherwise ++static int locomospi_carddetect() ++{ ++ return (locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1; ++} ++ ++static void locomospi_setcs(int high) ++{ ++ u16 r; ++ printk(KERN_DEBUG "locomospi: cs %d\n",high); ++ r = ioread16(spidev->base + LOCOMO_SPICT); ++ if(high) ++ r |= LOCOMO_SPI_CS; ++ else ++ r &= ~LOCOMO_SPI_CS; ++ iowrite16(r, spidev->base + LOCOMO_SPICT); ++} ++ ++static void locomospi_reg_open() ++{ ++ u16 r; ++ spidev->clock_div = DIV_64; ++ spidev->clock_base = CLOCK_18MHZ; ++ locomospi_power(1); ++ msleep(100); ++// iowrite16( 0xec00 | (CLOCK_18MHZ <<3)|DIV_64, spidev->base+LOCOMO_SPIMD); ++ iowrite16( LOCOMO_SPI_MSB1ST | LOCOMO_SPI_DOSTAT | LOCOMO_SPI_RCPOL | LOCOMO_SPI_TCPOL ++ |(CLOCK_18MHZ <<3) | DIV_64, spidev->base+LOCOMO_SPIMD); ++// if(locomospi_carddetect()){ ++ r = ioread16(spidev->base+LOCOMO_SPIMD); ++ r |= LOCOMO_SPI_XON; ++ iowrite16( r, spidev->base+LOCOMO_SPIMD); ++ r = ioread16(spidev->base+LOCOMO_SPIMD); ++ r |= LOCOMO_SPI_XEN; ++ iowrite16( r, spidev->base+LOCOMO_SPIMD); ++// } ++ iowrite16( LOCOMO_SPI_CS, spidev->base+LOCOMO_SPICT); ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r |= (LOCOMO_SPI_CEN | LOCOMO_SPI_RXUEN | LOCOMO_SPI_ALIGNEN); ++ iowrite16( r, spidev->base+LOCOMO_SPICT); ++ udelay(200); ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r &= ~LOCOMO_SPI_CS; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++} ++ ++static void locomospi_reg_release() ++{ ++ u16 r; ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r &= ~LOCOMO_SPI_CEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ r = ioread16(spidev->base+LOCOMO_SPIMD); ++ r &= ~LOCOMO_SPI_XEN; ++ iowrite16(r, spidev->base+LOCOMO_SPIMD); ++ r = ioread16(spidev->base+LOCOMO_SPIMD); ++ r &= ~LOCOMO_SPI_XON; ++ iowrite16(r, spidev->base+LOCOMO_SPIMD); ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r |= LOCOMO_SPI_XEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ locomospi_power(0); ++} ++#if 0 ++static int txrx(const char* txbuffer, char* rxbuffer, int size) ++{ ++ u16 r = ioread16(spidev->base+LOCOMO_SPICT); ++ r |= LOCOMO_SPI_ALIGNEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ printk(KERN_DEBUG "locomospi: %d bytes to prozess\n",size); ++ /* initialize global vars for isr */ ++ transfercount=0; transfersize=size; ++ transtxbuf=txbuffer; transrxbuf=rxbuffer; ++ ++ /* start transmit and go sleep isr will wake us*/ ++ enable_irq(IRQ_LOCOMO_SPI_TEND); ++ iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD); ++ wait_event(transferqueue, transfercount >= transfersize); ++ disable_irq(IRQ_LOCOMO_SPI_TEND); ++ transrxbuf=NULL; transtxbuf=NULL; ++ ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r &= ~LOCOMO_SPI_ALIGNEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ int i; ++ for(i=0; i< size; i++) ++ printk(KERN_DEBUG "locomospi: sent: %x received: %x \n",txbuffer[i], rxbuffer[i]); ++ ++ ++ return size; ++} ++ ++ ++static int tx(const char* txbuffer, int size) ++{ ++ printk(KERN_DEBUG "locomospi: %d bytes to send\n",size); ++ /* initialize global vars for isr */ ++ transfercount=0; transfersize=size; ++ transtxbuf=txbuffer; ++ ++ /* start transmit and go sleep isr will wake us*/ ++ enable_irq(IRQ_LOCOMO_SPI_RFW); ++ iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD); ++ wait_event(transferqueue, transfercount >= transfersize); ++ disable_irq(IRQ_LOCOMO_SPI_RFW); ++ transtxbuf=NULL; ++ ++ int i; ++ for(i=0; i< size; i++) ++ printk(KERN_DEBUG "locomospi: sent: %x\n",txbuffer[i]); ++ ++ ++ return size; ++} ++ ++static int rx(char* rxbuffer, int size) ++{ ++ printk(KERN_DEBUG "locomospi: %d bytes to read\n",size); ++ /* initialize global vars for isr */ ++ transfercount=0; transfersize=size; ++ transrxbuf=rxbuffer; ++ ++ /* start transmit and go sleep isr will wake us*/ ++ enable_irq(IRQ_LOCOMO_SPI_RFR); ++ rxbuffer[0]=ioread8(spidev->base+LOCOMO_SPIRD); ++ wait_event(transferqueue, transfercount >= transfersize); ++ disable_irq(IRQ_LOCOMO_SPI_RFR); ++ transrxbuf=NULL; ++ ++ int i; ++ for(i=0; i< size; i++) ++ printk(KERN_DEBUG "locomospi: received: %x \n", rxbuffer[i]); ++ ++ ++ return size; ++} ++ ++#else ++static int txrx(const char* txbuffer, char* rxbuffer, int size) ++{ ++ int i=0,j=0; ++ int wait; ++ u16 r; ++/* char * txback = kmalloc(size * sizeof(char), GFP_KERNEL); ++ memcpy(txback, txbuffer, size); ++*/ ++ if(spidev->clock_div == 4) ++ wait = 0x10000; ++ else ++ wait = 8; ++ ++// printk(KERN_DEBUG "locomospi: txrx %d bytes to prozess\n",size); ++ ++// r = ioread16(spidev->base+LOCOMO_SPICT); ++// r |= LOCOMO_SPI_ALIGNEN; ++// iowrite16(r, spidev->base+LOCOMO_SPICT); ++ //discard first bogus byte ++ ++ ioread8(spidev->base+LOCOMO_SPIRD); ++ for(i=0; i<size; i++){ ++ for(j=0; j <= wait; j++){ ++ if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW) ++ break; ++ } ++ iowrite8(txbuffer[i], spidev->base+LOCOMO_SPITD); ++ ndelay(delay); ++ ++ for(j=0; j <= wait; j++){ ++ if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR) ++ break; ++ } ++ rxbuffer[i] = ioread8(spidev->base+LOCOMO_SPIRD); ++ ndelay(delay); ++ } ++// r = ioread16(spidev->base+LOCOMO_SPICT); ++// r &= ~LOCOMO_SPI_ALIGNEN; ++// iowrite16(r, spidev->base+LOCOMO_SPICT); ++ ++/* for(j=0; j< size; j++) ++ printk(KERN_DEBUG "locomospi: sent: %x received: %x \n",txback[j], rxbuffer[j]); ++ ++ kfree(txback); ++*/ return i; ++} ++ ++static int tx(const char* buffer, int size) ++{ ++ int i=0,j=0; ++ int wait; ++ u16 r; ++ if(spidev->clock_div == 4) ++ wait = 0x10000; ++ else ++ wait = 8; ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r &= ~LOCOMO_SPI_ALIGNEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ ++// printk(KERN_DEBUG "locomospi: tx %d bytes to transmit\n",size); ++ for(i=0; i<size; i++){ ++ for(j=0; j <= wait; j++){ ++ if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW) ++ break; ++ } ++ iowrite8(buffer[i], spidev->base+LOCOMO_SPITD); ++ ndelay(delay); ++ } ++ ++ for(j=0; j <= wait; j++){ ++ if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_TEND) ++ break; ++ } ++ ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r |= LOCOMO_SPI_ALIGNEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ ++// for(j=0; j< size; j++) ++// printk(KERN_DEBUG "locomospi: sent: %x \n", buffer[j]); ++// printk(KERN_DEBUG "locomospi: tx %d bytes transmitted\n",i); ++ return i; ++} ++ ++static int rx(char* buffer, int size) ++{ ++ int i,j; ++ int wait; ++ u16 r; ++ printk(KERN_DEBUG "locomospi: rx %d bytes to receive\n",size); ++ if(spidev->clock_div == 4) ++ wait = 0x10000; ++ else ++ wait = 8; ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r &= ~LOCOMO_SPI_ALIGNEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ ++ for(i=0; i<size; i++){ ++ ++ for(j=0; j <= wait; j++){ ++ if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR) ++ break; ++ } ++ buffer[i]= ioread8(spidev->base+LOCOMO_SPIRD); ++ ndelay(delay); ++ } ++ ++ r = ioread16(spidev->base+LOCOMO_SPICT); ++ r |= LOCOMO_SPI_ALIGNEN; ++ iowrite16(r, spidev->base+LOCOMO_SPICT); ++ ++ for(j=0; j< size; j++) ++ printk(KERN_DEBUG "locomospi: received: %x \n", buffer[j]); ++ printk(KERN_DEBUG "locomospi: rx %d bytes received\n",i); ++ return i; ++} ++#endif ++/* ++static irqreturn_t locomospi_rwready(int irq, void *dev_id) ++{ ++ struct locomospi_dev* dev=(struct locomospi_dev*) dev_id; ++// dev_dbg(&spidev->sdev->dev, "IRQ: %d\n", irq); ++// printk(KERN_DEBUG "locomospi: IRQ: %d\n", irq); ++ wake_up_interruptible(&dev->waitqueue); ++ return IRQ_HANDLED; ++} ++*/ ++static irqreturn_t locomospi_testisr(int irq, void *dev_id) ++{ ++ char *buf=""; ++ switch(irq){ ++ case IRQ_LOCOMO_SPI_RFR: buf="RFR"; ++ break; ++ case IRQ_LOCOMO_SPI_RFW: buf="RFW"; ++ break; ++ case IRQ_LOCOMO_SPI_REND:buf="REND"; ++ break; ++ case IRQ_LOCOMO_SPI_TEND:buf="TEND"; ++ break; ++ case IRQ_LOCOMO_CARDDETECT: ++ buf="CARD_DETECT"; ++ break; ++ default: return IRQ_NONE; ++ } ++ printk(KERN_DEBUG "locomospi: IRQ: %s\n",buf); ++// dev_dbg(&spidev->sdev->dev, "IRQ: %s\n",buf); ++ return IRQ_HANDLED; ++} ++static irqreturn_t locomospi_txrxisr(int irq, void *dev_id) ++{ ++ if(transfercount < transfersize){ ++ transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD); ++ iowrite8(transtxbuf[transfercount], spidev->base+LOCOMO_SPITD); ++ } ++ else{ ++ /* transfer complete. wake up txrx */ ++ wake_up(&transferqueue); ++ } ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t locomospi_txisr(int irq, void *dev_id) ++{ ++ if(transfercount < transfersize){ ++ iowrite8(transtxbuf[transfercount++], spidev->base+LOCOMO_SPITD); ++ } ++ else{ ++ /* transfer complete. wake up txrx */ ++ wake_up(&transferqueue); ++ } + |
