1 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
2 index c7ad324..daa2e0a 100644
5 @@ -998,7 +998,7 @@ config CPU_FREQ_SA1100
9 - depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
10 + depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3 || SA1100_COLLIE)
13 config CPU_FREQ_INTEGRATOR
14 diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c
15 index e508028..36f726c 100644
16 --- a/arch/arm/mach-sa1100/dma.c
17 +++ b/arch/arm/mach-sa1100/dma.c
18 @@ -39,7 +39,7 @@ typedef struct {
20 static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
22 -static spinlock_t dma_list_lock;
23 +static DEFINE_SPINLOCK(dma_list_lock);
26 static irqreturn_t dma_irq_handler(int irq, void *dev_id)
27 diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
28 index 9caed30..79e19bf 100644
29 --- a/drivers/input/keyboard/locomokbd.c
30 +++ b/drivers/input/keyboard/locomokbd.c
31 @@ -265,6 +265,7 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev)
32 for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
33 set_bit(locomokbd->keycode[i], input_dev->keybit);
34 clear_bit(0, input_dev->keybit);
35 + locomo_writel(0, locomokbd->base + LOCOMO_KSC);
37 /* attempt to get the interrupt */
38 err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
39 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
40 index 9f93c29..33fc5d6 100644
41 --- a/drivers/mfd/Kconfig
42 +++ b/drivers/mfd/Kconfig
43 @@ -72,4 +72,10 @@ config MCP_UCB1200_TS
44 tristate "Touchscreen interface support"
45 depends on MCP_UCB1200 && INPUT
48 + tristate "Touchscreen collie support"
49 + depends on MCP_UCB1200 && INPUT && !MCP_UCB1200_TS
51 + Driver for touchscreen on collie - sharp sl-5500.
54 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
55 index 33daa2f..0885ccd 100644
56 --- a/drivers/mfd/Makefile
57 +++ b/drivers/mfd/Makefile
58 @@ -16,7 +16,7 @@ obj-$(CONFIG_MCP) += mcp-core.o
59 obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
60 obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
61 obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
63 +obj-$(CONFIG_MCP_COLLIE_TS) += collie-ts.o
64 ifeq ($(CONFIG_SA1100_ASSABET),y)
65 obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
67 diff --git a/drivers/mfd/collie-ts.c b/drivers/mfd/collie-ts.c
69 index 0000000..ddde5fc
71 +++ b/drivers/mfd/collie-ts.c
74 + * Touchscreen driver for UCB1x00-based touchscreens
76 + * Copyright (C) 2001 Russell King, All Rights Reserved.
77 + * Copyright (C) 2005 Pavel Machek
79 + * This program is free software; you can redistribute it and/or modify
80 + * it under the terms of the GNU General Public License version 2 as
81 + * published by the Free Software Foundation.
83 + * 21-Jan-2002 <jco@ict.es> :
85 + * Added support for synchronous A/D mode. This mode is useful to
86 + * avoid noise induced in the touchpanel by the LCD, provided that
87 + * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
88 + * It is important to note that the signal connected to the ADCSYNC
89 + * pin should provide pulses even when the LCD is blanked, otherwise
90 + * a pen touch needed to unblank the LCD will never be read.
92 +#include <linux/module.h>
93 +#include <linux/moduleparam.h>
94 +#include <linux/init.h>
95 +#include <linux/smp.h>
96 +#include <linux/smp_lock.h>
97 +#include <linux/sched.h>
98 +#include <linux/completion.h>
99 +#include <linux/delay.h>
100 +#include <linux/string.h>
101 +#include <linux/input.h>
102 +#include <linux/device.h>
103 +#include <linux/freezer.h>
104 +#include <linux/slab.h>
105 +#include <linux/kthread.h>
107 +#include <asm/dma.h>
108 +#include <asm/semaphore.h>
109 +#include <asm/arch/collie.h>
110 +#include <asm/mach-types.h>
112 +#include "ucb1x00.h"
115 + struct input_dev *idev;
116 + struct ucb1x00 *ucb;
118 + wait_queue_head_t irq_wait;
119 + struct task_struct *rtask;
123 + unsigned int adcsync:1;
128 +/**********************************
147 +**********************************/
150 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
152 + struct input_dev *idev = ts->idev;
154 + input_report_abs(idev, ABS_X, x);
155 + input_report_abs(idev, ABS_Y, y);
156 + input_report_abs(idev, ABS_PRESSURE, pressure);
157 + input_report_key(idev, BTN_TOUCH, 1);
161 +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
163 + struct input_dev *idev = ts->idev;
165 + input_report_abs(idev, ABS_PRESSURE, 0);
166 + input_report_key(idev, BTN_TOUCH, 0);
171 + * Switch to interrupt mode. This set touchscreen to interrupt
172 + * mode, so that chip is able to send interrupt.
174 +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
176 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
177 + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
178 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
179 + UCB_TS_CR_MODE_INT);
183 + * Switch to pressure mode, and read pressure. We don't need to wait
184 + * here, since both plates are being driven.
186 + * set_read_pressure() in sharp code
188 +static inline void ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
190 + ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
191 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
192 + UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
193 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
195 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
199 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
201 + UCB_ADC_SYNC_ENA | UCB_ADC_START);
205 + * Switch to X position mode and measure Y plate. We switch the plate
206 + * configuration in pressure mode, then switch to position mode. This
207 + * gives a faster response time. Even so, we need to wait about 55us
208 + * for things to stabilise.
210 +static inline void ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
212 + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
213 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
214 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
215 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
218 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
219 + UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA);
221 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
222 + UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA |
227 + * Switch to Y position mode and measure X plate. We switch the plate
228 + * configuration in pressure mode, then switch to position mode. This
229 + * gives a faster response time. Even so, we need to wait about 55us
230 + * for things to stabilise.
232 +static inline void ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
234 + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
236 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
237 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
238 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
241 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
242 + UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA);
244 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
245 + UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA |
250 + * Switch to X plate resistance mode. Set MX to ground, PX to
251 + * supply. Measure current.
253 +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
255 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
256 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
257 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
258 + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
262 + * Switch to Y plate resistance mode. Set MY to ground, PY to
263 + * supply. Measure current.
265 +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
267 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
268 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
269 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
270 + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
274 + * This is a RT kernel thread that handles the ADC accesses
275 + * (mainly so we can use semaphores in the UCB1200 core code
276 + * to serialise accesses to the ADC).
278 +static int ucb1x00_thread(void *_ts)
280 + struct ucb1x00_ts *ts = _ts;
281 + struct task_struct *tsk = current;
282 + DECLARE_WAITQUEUE(wait, tsk);
286 + * We could run as a real-time thread. However, thus far
287 + * this doesn't seem to be necessary.
290 + add_wait_queue(&ts->irq_wait, &wait);
292 + while (!kthread_should_stop()) {
293 + unsigned int data[3];
295 + for (state=0; state<3; state++) {
297 + ucb1x00_adc_enable(ts->ucb);
298 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING);
300 + /* Order matters here; last measurement seems to be more noisy then the
301 + rest, and we care about pressure least */
302 + case 2: ucb1x00_ts_read_pressure(ts);
304 + case 0: ucb1x00_ts_read_ypos(ts);
306 + case 1: ucb1x00_ts_read_xpos(ts);
311 + schedule_timeout(1000 * HZ);
312 + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING);
313 + data[state] = UCB_ADC_DAT(ucb1x00_reg_read(ts->ucb, UCB_ADC_DATA));
314 + ucb1x00_adc_disable(ts->ucb);
317 + /* If not pressed any more, try to sleep! */
318 + if (data[2] < 300) {
319 + set_task_state(tsk, TASK_INTERRUPTIBLE);
320 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
321 + ucb1x00_ts_mode_int(ts);
322 + ucb1x00_disable(ts->ucb);
323 + ucb1x00_ts_event_release(ts);
325 + schedule_timeout(1000 * HZ);
326 + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
327 + ucb1x00_enable(ts->ucb);
329 + ucb1x00_ts_evt_add(ts, data[2], data[1], data[0]);
331 + ucb1x00_disable(ts->ucb);
333 + ucb1x00_enable(ts->ucb);
336 + remove_wait_queue(&ts->irq_wait, &wait);
343 + * We only detect touch screen _touches_ with this interrupt
344 + * handler, and even then we just schedule our task.
346 +static void ucb1x00_ts_irq(int idx, void *id)
348 + struct ucb1x00_ts *ts = id;
349 + wake_up(&ts->irq_wait);
352 +static void ucb1x00_adc_irq(int idx, void *id)
354 + struct ucb1x00_ts *ts = id;
355 + wake_up(&ts->irq_wait);
358 +static int ucb1x00_ts_open(struct input_dev *idev)
360 + struct ucb1x00_ts *ts = input_get_drvdata(idev);
365 + init_waitqueue_head(&ts->irq_wait);
367 + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
371 + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_ADC, ucb1x00_adc_irq, ts);
373 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
377 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
380 + * If we do this at all, we should allow the user to
381 + * measure and read the X and Y resistance at any time.
383 + ucb1x00_adc_enable(ts->ucb);
384 + ts->x_res = ucb1x00_ts_read_xres(ts);
385 + ts->y_res = ucb1x00_ts_read_yres(ts);
386 + ucb1x00_adc_disable(ts->ucb);
388 + if (machine_is_collie()) {
389 + ucb1x00_io_set_dir(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
392 + ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
393 + if (!IS_ERR(ts->rtask)) {
396 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
405 + * Release touchscreen resources. Disable IRQs.
407 +static void ucb1x00_ts_close(struct input_dev *idev)
409 + struct ucb1x00_ts *ts = input_get_drvdata(idev);
412 + kthread_stop(ts->rtask);
414 + ucb1x00_enable(ts->ucb);
415 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
416 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_ADC, ts);
417 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
418 + ucb1x00_disable(ts->ucb);
422 +static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
424 + struct ucb1x00_ts *ts = dev->priv;
426 + if (ts->rtask != NULL) {
428 + * Restart the TS thread to ensure the
429 + * TS interrupt mode is set up again
432 + wake_up(&ts->irq_wait);
437 +#define ucb1x00_ts_resume NULL
444 +static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
446 + struct ucb1x00_ts *ts;
447 + struct input_dev *idev;
450 + ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
451 + idev = input_allocate_device();
452 + if (!ts || !idev) {
457 + ts->ucb = dev->ucb;
459 + ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
461 + input_set_drvdata(idev, ts);
462 + idev->name = "Touchscreen panel";
463 + idev->id.product = ts->ucb->id;
464 + idev->open = ucb1x00_ts_open;
465 + idev->close = ucb1x00_ts_close;
467 + __set_bit(EV_ABS, idev->evbit);
468 + __set_bit(ABS_X, idev->absbit);
469 + __set_bit(ABS_Y, idev->absbit);
470 + __set_bit(ABS_PRESSURE, idev->absbit);
472 + input_set_abs_params(ts->idev, ABS_X, 0, 450, 0, 0);
473 + input_set_abs_params(ts->idev, ABS_Y, 200, 800, 0, 0);
474 + input_set_abs_params(ts->idev, ABS_PRESSURE, 400, 800, 0, 0);
477 + err = input_register_device(idev);
486 + input_free_device(idev);
491 +static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
493 + struct ucb1x00_ts *ts = dev->priv;
495 + input_unregister_device(ts->idev);
499 +static struct ucb1x00_driver ucb1x00_ts_driver = {
500 + .add = ucb1x00_ts_add,
501 + .remove = ucb1x00_ts_remove,
502 + .resume = ucb1x00_ts_resume,
505 +static int __init ucb1x00_ts_init(void)
507 + return ucb1x00_register_driver(&ucb1x00_ts_driver);
510 +static void __exit ucb1x00_ts_exit(void)
512 + ucb1x00_unregister_driver(&ucb1x00_ts_driver);
515 +module_param(adcsync, int, 0444);
516 +module_init(ucb1x00_ts_init);
517 +module_exit(ucb1x00_ts_exit);
519 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
520 +MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
521 +MODULE_LICENSE("GPL");
522 diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
523 index a8ad8a0..137b043 100644
524 --- a/drivers/mfd/ucb1x00.h
525 +++ b/drivers/mfd/ucb1x00.h
527 #define UCB_IE_TCLIP (1 << 14)
528 #define UCB_IE_ACLIP (1 << 15)
531 +#define UCB_IRQ_ADC 11
532 #define UCB_IRQ_TSPX 12
533 +#define UCB_IRQ_TSMX 13
535 #define UCB_TC_A 0x05
536 #define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
537 diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
538 index 3b4e55c..0ae741d 100644
539 --- a/drivers/net/wireless/hostap/hostap_cs.c
540 +++ b/drivers/net/wireless/hostap/hostap_cs.c
541 @@ -35,7 +35,7 @@ static int ignore_cis_vcc;
542 module_param(ignore_cis_vcc, int, 0444);
543 MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
547 /* struct local_info::hw_priv */
548 struct hostap_cs_priv {
550 @@ -499,11 +499,13 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev)
552 PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
553 p_dev->conf.IntType = INT_MEMORY_AND_IO;
557 ret = prism2_config(p_dev);
559 PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
565 diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
566 index 13d5882..6f24d66 100644
567 --- a/drivers/net/wireless/hostap/hostap_hw.c
568 +++ b/drivers/net/wireless/hostap/hostap_hw.c
571 #include "hostap_ap.h"
575 /* #define final_version */
577 @@ -1497,6 +1498,8 @@ static int prism2_hw_config(struct net_device *dev, int initial)
578 if (local->hw_downloading)
583 if (prism2_hw_init(dev, initial)) {
584 return local->no_pri ? 0 : 1;
586 @@ -2628,8 +2631,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
590 - iface = netdev_priv(dev);
591 - local = iface->local;
593 + // Todos los parametros de entrada son correctos (no son nulos). De momento esta es la unica forma que conozco de detectar el problema.
595 + printk("hostap_hw.c: INTERRUPT BEFORE DEVICE INIT!\n");
596 + return IRQ_HANDLED;
599 + iface = netdev_priv(dev);
600 + local = iface->local;
602 prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
604 diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
605 index 3a874fc..df58aa3 100644
606 --- a/drivers/net/wireless/hostap/hostap_pci.c
607 +++ b/drivers/net/wireless/hostap/hostap_pci.c
610 #include "hostap_wlan.h"
614 static char *dev_info = "hostap_pci";
616 diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
617 index cbf15d7..4475174 100644
618 --- a/drivers/net/wireless/hostap/hostap_plx.c
619 +++ b/drivers/net/wireless/hostap/hostap_plx.c
623 #include "hostap_wlan.h"
627 static char *dev_info = "hostap_plx";
629 diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
630 index c5b2a44..eecbe8c 100644
631 --- a/drivers/pcmcia/sa1100_generic.c
632 +++ b/drivers/pcmcia/sa1100_generic.c
633 @@ -81,13 +81,14 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev)
637 -static struct device_driver sa11x0_pcmcia_driver = {
638 - .probe = sa11x0_drv_pcmcia_probe,
639 - .remove = soc_common_drv_pcmcia_remove,
640 - .name = "sa11x0-pcmcia",
641 - .bus = &platform_bus_type,
642 - .suspend = pcmcia_socket_dev_suspend,
643 - .resume = pcmcia_socket_dev_resume,
644 +static struct platform_driver sa11x0_pcmcia_driver = {
646 + .name = "sa11x0-pcmcia",
647 + .probe = sa11x0_drv_pcmcia_probe,
648 + .remove = soc_common_drv_pcmcia_remove,
649 + .suspend= pcmcia_socket_dev_suspend,
650 + .resume = pcmcia_socket_dev_resume,
654 /* sa11x0_pcmcia_init()
655 @@ -100,7 +101,7 @@ static struct device_driver sa11x0_pcmcia_driver = {
657 static int __init sa11x0_pcmcia_init(void)
659 - return driver_register(&sa11x0_pcmcia_driver);
660 + return platform_driver_register(&sa11x0_pcmcia_driver);
663 /* sa11x0_pcmcia_exit()
664 @@ -110,7 +111,7 @@ static int __init sa11x0_pcmcia_init(void)
666 static void __exit sa11x0_pcmcia_exit(void)
668 - driver_unregister(&sa11x0_pcmcia_driver);
669 + platform_driver_unregister(&sa11x0_pcmcia_driver);
672 MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
673 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
674 index 66ec5d8..aba38d7 100644
675 --- a/drivers/spi/Kconfig
676 +++ b/drivers/spi/Kconfig
677 @@ -123,6 +123,10 @@ config SPI_MPC52xx_PSC
678 This enables using the Freescale MPC52xx Programmable Serial
679 Controller in master SPI mode.
682 + tristate "Locomo SPI master"
683 + depends on SPI_MASTER && SHARP_LOCOMO && EXPERIMENTAL
686 tristate "Freescale MPC83xx/QUICC Engine SPI controller"
687 depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
688 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
689 index 7fca043..b89992b 100644
690 --- a/drivers/spi/Makefile
691 +++ b/drivers/spi/Makefile
692 @@ -28,6 +28,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
693 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
694 obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
695 obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
696 +obj-$(CONFIG_SPI_LOCOMO) += locomo_spi.o
697 # ... add above this line ...
699 # SPI protocol drivers (device/link on bus)
700 diff --git a/drivers/spi/locomo_spi.c b/drivers/spi/locomo_spi.c
702 index 0000000..d3a4bd9
704 +++ b/drivers/spi/locomo_spi.c
707 +#include <asm/irq.h>
708 +#include <linux/module.h>
709 +#include <linux/init.h>
710 +#include <linux/device.h>
711 +#include <linux/stat.h>
712 +#include <linux/delay.h>
713 +#include <linux/wait.h>
714 +#include <linux/interrupt.h>
715 +#include <asm/hardware/locomo.h>
716 +#include <asm/errno.h>
717 +#include <linux/mmc/host.h>
718 +#include <linux/spi/spi.h>
719 +#include <linux/spi/mmc_spi.h>
720 +#include <linux/workqueue.h>
721 +#include <linux/spinlock.h>
722 +#include <linux/list.h>
723 +#include "locomo_spi.h"
724 +static struct locomospi_dev * spidev;
725 +static struct work_struct transfer_wq;
728 +char* transtxbuf=(char*)NULL;
729 +char* transrxbuf=(char*)NULL;
730 +int transfercount=0, transfersize=0;
731 +static DECLARE_WAIT_QUEUE_HEAD(transferqueue);
732 +/* MMC_SPI functions *********************************************************/
734 +static int locomommcspi_init(struct device *dev, irqreturn_t (*isr)(int, void*), void *mmc)
737 + result=request_irq(IRQ_LOCOMO_CARDDETECT, isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "locomo-spi", mmc);
741 +static void locomommcspi_exit(struct device *dev, void* mmc)
743 + free_irq(IRQ_LOCOMO_CARDDETECT, mmc);
746 +static int locomommcspi_getro(struct device *dev)
748 + return locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT) > 0 ? 1 : 0;
751 +static void locomommcspi_setpower(struct device *dev, unsigned int mask)
753 + if(!mask && spidev->card_power)
754 + locomospi_power(0);
755 + else if( !spidev->card_power )
756 + locomospi_power(1);
761 +static struct mmc_spi_platform_data colliemmc ={
762 + .init = locomommcspi_init,
763 + .exit = locomommcspi_exit,
764 + .detect_delay = 200,
765 + .get_ro = locomommcspi_getro,
766 + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
767 + .setpower = locomommcspi_setpower,
768 + .powerup_msecs = 200,
771 +/* Utility function **********************************************************/
773 +static void locomospi_power(int on)
775 + locomo_gpio_write(spidev->ldev->dev.parent, LOCOMO_GPIO_CARD_POWER, on);
776 + spidev->card_power=on;
777 + printk(KERN_DEBUG "locomospi: power %d\n",on);
780 +static void locomospi_setclock(unsigned int div, unsigned int clock)
782 + u16 r = ioread16(spidev->base+LOCOMO_SPIMD);
785 + if(clock != spidev->clock_base || div != spidev->clock_div){
786 + r &= ~(LOCOMO_SPI_XSEL | LOCOMO_SPI_CLKSEL | LOCOMO_SPI_XEN);
787 + iowrite16(r,spidev->base+LOCOMO_SPIMD);
788 + r |= (div | (clock <<3) | LOCOMO_SPI_XEN);
789 + iowrite16(r,spidev->base+LOCOMO_SPIMD);
790 + spidev->clock_div = div;
791 + spidev->clock_base = clock;
796 +// returns 1 if card ist present, 0 otherwise
797 +static int locomospi_carddetect()
799 + return (locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1;
802 +static void locomospi_setcs(int high)
805 + printk(KERN_DEBUG "locomospi: cs %d\n",high);
806 + r = ioread16(spidev->base + LOCOMO_SPICT);
808 + r |= LOCOMO_SPI_CS;
810 + r &= ~LOCOMO_SPI_CS;
811 + iowrite16(r, spidev->base + LOCOMO_SPICT);
814 +static void locomospi_reg_open()
817 + spidev->clock_div = DIV_64;
818 + spidev->clock_base = CLOCK_18MHZ;
819 + locomospi_power(1);
821 +// iowrite16( 0xec00 | (CLOCK_18MHZ <<3)|DIV_64, spidev->base+LOCOMO_SPIMD);
822 + iowrite16( LOCOMO_SPI_MSB1ST | LOCOMO_SPI_DOSTAT | LOCOMO_SPI_RCPOL | LOCOMO_SPI_TCPOL
823 + |(CLOCK_18MHZ <<3) | DIV_64, spidev->base+LOCOMO_SPIMD);
824 +// if(locomospi_carddetect()){
825 + r = ioread16(spidev->base+LOCOMO_SPIMD);
826 + r |= LOCOMO_SPI_XON;
827 + iowrite16( r, spidev->base+LOCOMO_SPIMD);
828 + r = ioread16(spidev->base+LOCOMO_SPIMD);
829 + r |= LOCOMO_SPI_XEN;
830 + iowrite16( r, spidev->base+LOCOMO_SPIMD);
832 + iowrite16( LOCOMO_SPI_CS, spidev->base+LOCOMO_SPICT);
833 + r = ioread16(spidev->base+LOCOMO_SPICT);
834 + r |= (LOCOMO_SPI_CEN | LOCOMO_SPI_RXUEN | LOCOMO_SPI_ALIGNEN);
835 + iowrite16( r, spidev->base+LOCOMO_SPICT);
837 + r = ioread16(spidev->base+LOCOMO_SPICT);
838 + iowrite16(r, spidev->base+LOCOMO_SPICT);
839 + r = ioread16(spidev->base+LOCOMO_SPICT);
840 + r &= ~LOCOMO_SPI_CS;
841 + iowrite16(r, spidev->base+LOCOMO_SPICT);
844 +static void locomospi_reg_release()
847 + r = ioread16(spidev->base+LOCOMO_SPICT);
848 + r &= ~LOCOMO_SPI_CEN;
849 + iowrite16(r, spidev->base+LOCOMO_SPICT);
850 + r = ioread16(spidev->base+LOCOMO_SPIMD);
851 + r &= ~LOCOMO_SPI_XEN;
852 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
853 + r = ioread16(spidev->base+LOCOMO_SPIMD);
854 + r &= ~LOCOMO_SPI_XON;
855 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
856 + r = ioread16(spidev->base+LOCOMO_SPICT);
857 + r |= LOCOMO_SPI_XEN;
858 + iowrite16(r, spidev->base+LOCOMO_SPICT);
859 + locomospi_power(0);
862 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
864 + u16 r = ioread16(spidev->base+LOCOMO_SPICT);
865 + r |= LOCOMO_SPI_ALIGNEN;
866 + iowrite16(r, spidev->base+LOCOMO_SPICT);
867 + printk(KERN_DEBUG "locomospi: %d bytes to prozess\n",size);
868 + /* initialize global vars for isr */
869 + transfercount=0; transfersize=size;
870 + transtxbuf=txbuffer; transrxbuf=rxbuffer;
872 + /* start transmit and go sleep isr will wake us*/
873 + enable_irq(IRQ_LOCOMO_SPI_TEND);
874 + iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD);
875 + wait_event(transferqueue, transfercount >= transfersize);
876 + disable_irq(IRQ_LOCOMO_SPI_TEND);
877 + transrxbuf=NULL; transtxbuf=NULL;
879 + r = ioread16(spidev->base+LOCOMO_SPICT);
880 + r &= ~LOCOMO_SPI_ALIGNEN;
881 + iowrite16(r, spidev->base+LOCOMO_SPICT);
883 + for(i=0; i< size; i++)
884 + printk(KERN_DEBUG "locomospi: sent: %x received: %x \n",txbuffer[i], rxbuffer[i]);
891 +static int tx(const char* txbuffer, int size)
893 + printk(KERN_DEBUG "locomospi: %d bytes to send\n",size);
894 + /* initialize global vars for isr */
895 + transfercount=0; transfersize=size;
896 + transtxbuf=txbuffer;
898 + /* start transmit and go sleep isr will wake us*/
899 + enable_irq(IRQ_LOCOMO_SPI_RFW);
900 + iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD);
901 + wait_event(transferqueue, transfercount >= transfersize);
902 + disable_irq(IRQ_LOCOMO_SPI_RFW);
906 + for(i=0; i< size; i++)
907 + printk(KERN_DEBUG "locomospi: sent: %x\n",txbuffer[i]);
913 +static int rx(char* rxbuffer, int size)
915 + printk(KERN_DEBUG "locomospi: %d bytes to read\n",size);
916 + /* initialize global vars for isr */
917 + transfercount=0; transfersize=size;
918 + transrxbuf=rxbuffer;
920 + /* start transmit and go sleep isr will wake us*/
921 + enable_irq(IRQ_LOCOMO_SPI_RFR);
922 + rxbuffer[0]=ioread8(spidev->base+LOCOMO_SPIRD);
923 + wait_event(transferqueue, transfercount >= transfersize);
924 + disable_irq(IRQ_LOCOMO_SPI_RFR);
928 + for(i=0; i< size; i++)
929 + printk(KERN_DEBUG "locomospi: received: %x \n", rxbuffer[i]);
936 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
941 +/* char * txback = kmalloc(size * sizeof(char), GFP_KERNEL);
942 + memcpy(txback, txbuffer, size);
944 + if(spidev->clock_div == 4)
949 +// printk(KERN_DEBUG "locomospi: txrx %d bytes to prozess\n",size);
951 +// r = ioread16(spidev->base+LOCOMO_SPICT);
952 +// r |= LOCOMO_SPI_ALIGNEN;
953 +// iowrite16(r, spidev->base+LOCOMO_SPICT);
954 + //discard first bogus byte
956 + ioread8(spidev->base+LOCOMO_SPIRD);
957 + for(i=0; i<size; i++){
958 + for(j=0; j <= wait; j++){
959 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)
962 + iowrite8(txbuffer[i], spidev->base+LOCOMO_SPITD);
965 + for(j=0; j <= wait; j++){
966 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
969 + rxbuffer[i] = ioread8(spidev->base+LOCOMO_SPIRD);
972 +// r = ioread16(spidev->base+LOCOMO_SPICT);
973 +// r &= ~LOCOMO_SPI_ALIGNEN;
974 +// iowrite16(r, spidev->base+LOCOMO_SPICT);
976 +/* for(j=0; j< size; j++)
977 + printk(KERN_DEBUG "locomospi: sent: %x received: %x \n",txback[j], rxbuffer[j]);
983 +static int tx(const char* buffer, int size)
988 + if(spidev->clock_div == 4)
992 + r = ioread16(spidev->base+LOCOMO_SPICT);
993 + r &= ~LOCOMO_SPI_ALIGNEN;
994 + iowrite16(r, spidev->base+LOCOMO_SPICT);
996 +// printk(KERN_DEBUG "locomospi: tx %d bytes to transmit\n",size);
997 + for(i=0; i<size; i++){
998 + for(j=0; j <= wait; j++){
999 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)
1002 + iowrite8(buffer[i], spidev->base+LOCOMO_SPITD);
1006 + for(j=0; j <= wait; j++){
1007 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_TEND)
1011 + r = ioread16(spidev->base+LOCOMO_SPICT);
1012 + r |= LOCOMO_SPI_ALIGNEN;
1013 + iowrite16(r, spidev->base+LOCOMO_SPICT);
1015 +// for(j=0; j< size; j++)
1016 +// printk(KERN_DEBUG "locomospi: sent: %x \n", buffer[j]);
1017 +// printk(KERN_DEBUG "locomospi: tx %d bytes transmitted\n",i);
1021 +static int rx(char* buffer, int size)
1026 + printk(KERN_DEBUG "locomospi: rx %d bytes to receive\n",size);
1027 + if(spidev->clock_div == 4)
1031 + r = ioread16(spidev->base+LOCOMO_SPICT);
1032 + r &= ~LOCOMO_SPI_ALIGNEN;
1033 + iowrite16(r, spidev->base+LOCOMO_SPICT);
1035 + for(i=0; i<size; i++){
1037 + for(j=0; j <= wait; j++){
1038 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
1041 + buffer[i]= ioread8(spidev->base+LOCOMO_SPIRD);
1045 + r = ioread16(spidev->base+LOCOMO_SPICT);
1046 + r |= LOCOMO_SPI_ALIGNEN;
1047 + iowrite16(r, spidev->base+LOCOMO_SPICT);
1049 + for(j=0; j< size; j++)
1050 + printk(KERN_DEBUG "locomospi: received: %x \n", buffer[j]);
1051 + printk(KERN_DEBUG "locomospi: rx %d bytes received\n",i);
1056 +static irqreturn_t locomospi_rwready(int irq, void *dev_id)
1058 + struct locomospi_dev* dev=(struct locomospi_dev*) dev_id;
1059 +// dev_dbg(&spidev->sdev->dev, "IRQ: %d\n", irq);
1060 +// printk(KERN_DEBUG "locomospi: IRQ: %d\n", irq);
1061 + wake_up_interruptible(&dev->waitqueue);
1062 + return IRQ_HANDLED;
1065 +static irqreturn_t locomospi_testisr(int irq, void *dev_id)
1069 + case IRQ_LOCOMO_SPI_RFR: buf="RFR";
1071 + case IRQ_LOCOMO_SPI_RFW: buf="RFW";
1073 + case IRQ_LOCOMO_SPI_REND:buf="REND";
1075 + case IRQ_LOCOMO_SPI_TEND:buf="TEND";
1077 + case IRQ_LOCOMO_CARDDETECT:
1078 + buf="CARD_DETECT";
1080 + default: return IRQ_NONE;
1082 + printk(KERN_DEBUG "locomospi: IRQ: %s\n",buf);
1083 +// dev_dbg(&spidev->sdev->dev, "IRQ: %s\n",buf);
1084 + return IRQ_HANDLED;
1086 +static irqreturn_t locomospi_txrxisr(int irq, void *dev_id)
1088 + if(transfercount < transfersize){
1089 + transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1090 + iowrite8(transtxbuf[transfercount], spidev->base+LOCOMO_SPITD);
1093 + /* transfer complete. wake up txrx */
1094 + wake_up(&transferqueue);
1096 + return IRQ_HANDLED;
1099 +static irqreturn_t locomospi_txisr(int irq, void *dev_id)
1101 + if(transfercount < transfersize){
1102 + iowrite8(transtxbuf[transfercount++], spidev->base+LOCOMO_SPITD);
1105 + /* transfer complete. wake up txrx */
1106 + wake_up(&transferqueue);
1108 + return IRQ_HANDLED;
1111 +static irqreturn_t locomospi_rxisr(int irq, void *dev_id)
1113 + if(transfercount < transfersize){
1114 + transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1117 + /* transfer complete. wake up txrx */
1118 + wake_up(&transferqueue);
1120 + return IRQ_HANDLED;
1123 +static void locomospi_clock(unsigned int Hz)
1126 + printk(KERN_DEBUG "locomospi: changing clock to: %d\n", Hz);
1128 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1129 + r &= ~LOCOMO_SPI_XON;
1130 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1132 + else if(Hz >= 24576000){
1133 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1134 + r |= LOCOMO_SPI_XON;
1135 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1136 + locomospi_setclock(DIV_1, CLOCK_25MHZ);
1139 + else if(Hz >= 22579200){
1140 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1141 + r |= LOCOMO_SPI_XON;
1142 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1143 + locomospi_setclock(DIV_1, CLOCK_22MHZ);
1146 + else if(Hz >= 18432000){
1147 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1148 + r |= LOCOMO_SPI_XON;
1149 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1150 + locomospi_setclock(DIV_1, CLOCK_18MHZ);
1153 + else if(Hz >= 12288000){
1154 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1155 + r |= LOCOMO_SPI_XON;
1156 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1157 + locomospi_setclock(DIV_2, CLOCK_25MHZ);
1160 + else if(Hz >= 11289600){
1161 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1162 + r |= LOCOMO_SPI_XON;
1163 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1164 + locomospi_setclock(DIV_2, CLOCK_22MHZ);
1167 + else if(Hz >= 9216000){
1168 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1169 + r |= LOCOMO_SPI_XON;
1170 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1171 + locomospi_setclock(DIV_2, CLOCK_18MHZ);
1174 + else if(Hz >= 6144000){
1175 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1176 + r |= LOCOMO_SPI_XON;
1177 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1178 + locomospi_setclock(DIV_4, CLOCK_25MHZ);
1181 + else if(Hz >= 5644800){
1182 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1183 + r |= LOCOMO_SPI_XON;
1184 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1185 + locomospi_setclock(DIV_4, CLOCK_22MHZ);
1188 + else if(Hz >= 4608000){
1189 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1190 + r |= LOCOMO_SPI_XON;
1191 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1192 + locomospi_setclock(DIV_4, CLOCK_18MHZ);
1195 + else if(Hz >= 3072000){
1196 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1197 + r |= LOCOMO_SPI_XON;
1198 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1199 + locomospi_setclock(DIV_8, CLOCK_25MHZ);
1202 + else if(Hz >= 2822400){
1203 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1204 + r |= LOCOMO_SPI_XON;
1205 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1206 + locomospi_setclock(DIV_8, CLOCK_22MHZ);
1209 + else if(Hz >= 2304000){
1210 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1211 + r |= LOCOMO_SPI_XON;
1212 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1213 + locomospi_setclock(DIV_8, CLOCK_18MHZ);
1216 + else if(Hz >= 384000){
1217 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1218 + r |= LOCOMO_SPI_XON;
1219 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1220 + locomospi_setclock(DIV_64, CLOCK_25MHZ);
1223 + else if(Hz >= 352800){
1224 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1225 + r |= LOCOMO_SPI_XON;
1226 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1227 + locomospi_setclock(DIV_64, CLOCK_22MHZ);
1230 + else{ /* set to 288 KHz */
1231 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1232 + r |= LOCOMO_SPI_XON;
1233 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1234 + locomospi_setclock(DIV_64, CLOCK_18MHZ);
1237 + spidev->clock = Hz;
1240 +/* sysfs attributes used for debug *******************************************/
1242 +/* SPI registers */
1243 +ssize_t locomospi_showspimd(struct device_driver *drv, char *buf)
1245 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIMD));
1248 +ssize_t locomospi_storespimd(struct device_driver *drv, const char *buf, size_t count)
1250 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIMD);
1253 +static DRIVER_ATTR(spimd, S_IWUSR | S_IRUGO, locomospi_showspimd, locomospi_storespimd);
1255 +ssize_t locomospi_showspict(struct device_driver *drv, char *buf)
1257 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPICT));
1260 +ssize_t locomospi_storespict(struct device_driver *drv, const char *buf, size_t count)
1262 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPICT);
1265 +static DRIVER_ATTR(spict, S_IWUSR | S_IRUGO, locomospi_showspict, locomospi_storespict);
1267 +ssize_t locomospi_showspist(struct device_driver *drv, char *buf)
1269 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIST));
1272 +ssize_t locomospi_storespist(struct device_driver *drv, const char *buf, size_t count)
1274 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIST);
1277 +static DRIVER_ATTR(spist, S_IWUSR | S_IRUGO, locomospi_showspist, locomospi_storespist);
1279 +ssize_t locomospi_showspitd(struct device_driver *drv, char *buf)
1281 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITD));
1284 +ssize_t locomospi_storespitd(struct device_driver *drv, const char *buf, size_t count)
1286 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITD);
1289 +static DRIVER_ATTR(spitd, S_IWUSR | S_IRUGO, locomospi_showspitd, locomospi_storespitd);
1291 +ssize_t locomospi_showspird(struct device_driver *drv, char *buf)
1293 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRD));
1296 +ssize_t locomospi_storespird(struct device_driver *drv, const char *buf, size_t count)
1298 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRD);
1301 +static DRIVER_ATTR(spird, S_IWUSR | S_IRUGO, locomospi_showspird, locomospi_storespird);
1303 +ssize_t locomospi_showspits(struct device_driver *drv, char *buf)
1305 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITS));
1308 +ssize_t locomospi_storespits(struct device_driver *drv, const char *buf, size_t count)
1310 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITS);
1313 +static DRIVER_ATTR(spits, S_IWUSR | S_IRUGO, locomospi_showspits, locomospi_storespits);
1315 +ssize_t locomospi_showspirs(struct device_driver *drv, char *buf)
1317 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRS));
1320 +ssize_t locomospi_storespirs(struct device_driver *drv, const char *buf, size_t count)
1322 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRS);
1325 +static DRIVER_ATTR(spirs, S_IWUSR | S_IRUGO, locomospi_showspirs, locomospi_storespirs);
1327 +/* MMC Card status */
1329 +ssize_t locomospi_showpower(struct device_driver *drv, char *buf)
1331 + return sprintf(buf, "%d\n", spidev->card_power);
1334 +ssize_t locomospi_storepower(struct device_driver *drv, const char *buf, size_t count)
1336 + locomospi_power(simple_strtoul(buf, NULL, 10));
1339 +static DRIVER_ATTR(cardpower, S_IWUSR | S_IRUGO, locomospi_showpower, locomospi_storepower);
1341 +ssize_t locomospi_detectcard(struct device_driver *drv, char *buf)
1343 + return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1);
1345 +static DRIVER_ATTR(carddetect, S_IRUGO, locomospi_detectcard, NULL);
1347 +ssize_t locomospi_writeprotect(struct device_driver *drv, char *buf)
1349 + return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT)>0)?1:0);
1351 +static DRIVER_ATTR(cardwriteprotect, S_IRUGO, locomospi_writeprotect, NULL);
1354 +ssize_t locomospi_showclock(struct device_driver *drv, char *buf)
1356 + return sprintf(buf, "%d\n", spidev->clock);
1359 +ssize_t locomospi_storeclock(struct device_driver *drv, const char *buf, size_t count)
1361 + locomospi_clock(simple_strtoul(buf, NULL, 10));
1364 +static DRIVER_ATTR(clock, S_IWUSR | S_IRUGO, locomospi_showclock, locomospi_storeclock);
1367 +ssize_t locomospi_showdelay(struct device_driver *drv, char *buf)
1369 + return sprintf(buf, "%d\n", delay);
1372 +ssize_t locomospi_storedelay(struct device_driver *drv, const char *buf, size_t count)
1374 + delay=simple_strtoul(buf,NULL,10);
1377 +static DRIVER_ATTR(delay, S_IWUSR | S_IRUGO, locomospi_showdelay, locomospi_storedelay);
1379 +ssize_t locomospi_reset(struct device_driver *drv, const char *buf, size_t count)
1381 + int choice = simple_strtoul(buf, NULL, 10);
1385 + case 0: locomospi_reg_release();
1386 + schedule_timeout(2*HZ);
1387 + locomospi_reg_open();
1390 + char b1[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
1391 + char b2[] = "\xff\x40\x00\x00\x00\x00\x95\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
1392 + locomospi_setcs(1);
1394 + locomospi_setcs(0);
1399 + case 2: locomospi_setcs(1);
1400 + txrx("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",buff,18);
1401 + locomospi_setcs(0);
1402 + txrx("\xff\x40\x00\x00\x00\x00\x95\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",buff,17);
1405 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1406 + r |= LOCOMO_SPI_LOOPBACK;
1407 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1409 + txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
1413 + schedule_timeout(HZ);
1414 + txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
1416 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1417 + r &= ~LOCOMO_SPI_LOOPBACK;
1418 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
1420 + default: /* do nothing */;
1424 +static DRIVER_ATTR(reset, S_IWUSR, NULL, locomospi_reset);
1426 +typedef struct locomo_reg_entry {
1429 +} locomo_reg_entry_t;
1430 +#define LCM (sizeof(locomo_regs)/sizeof(locomo_reg_entry_t))
1431 +static locomo_reg_entry_t locomo_regs[] =
1433 +/* { addr, name, description } */
1438 + { 0x10, "MCSX0" },
1439 + { 0x14, "MCSX1" },
1440 + { 0x18, "MCSX2" },
1441 + { 0x1C, "MCSX3" },
1453 + { 0x60, "SPIMD" },
1454 + { 0x64, "SPICT" },
1455 + { 0x68, "SPIST" },
1456 + { 0x70, "SPIIS" },
1457 + { 0x74, "SPIWE" },
1458 + { 0x78, "SPIIE" },
1459 + { 0x7C, "SPIIR" },
1460 + { 0x80, "SPITD" },
1461 + { 0x84, "SPIRD" },
1462 + { 0x88, "SPITS" },
1463 + { 0x8C, "SPIRS" },
1478 + { 0xdc, "LTINT" },
1485 +static ssize_t lcm_show(struct device *dev, struct device_attribute *attr, char *buf)
1487 + int base = spidev->base - LOCOMO_SPI;
1491 + for(i=0; i<LCM; i++){
1492 + sprintf(c,"%s:\t\t 0x%x\n",locomo_regs[i].name, ioread16(base + locomo_regs[i].addr));
1495 + return sprintf(buf,"%s",b);
1498 +static DRIVER_ATTR(regs, 0444, lcm_show, NULL);
1501 +/* SPI functions *************************************************************/
1503 +static void locomospi_do_transfer(struct work_struct *wrk)
1505 + struct list_head *mptr, *tptr, *mptr2;
1506 + struct spi_transfer *entry;
1507 + struct spi_message *msg;
1509 + list_for_each_safe(mptr, mptr2, &spidev->message_list){
1510 + msg = list_entry(mptr, struct spi_message, queue);
1513 + msg->actual_length = 0;
1514 + list_for_each(tptr, &msg->transfers){
1515 + entry = list_entry(tptr, struct spi_transfer, transfer_list);
1516 + if(entry->tx_buf && entry->rx_buf){ //duplex
1517 + txrx((char*) entry->tx_buf, (char*) entry->rx_buf, entry->len);
1518 + msg->actual_length += entry->len;
1519 + } else if(entry->tx_buf && !entry->rx_buf){ //write
1520 + tx((char*) entry->tx_buf, entry->len);
1521 + msg->actual_length += entry->len;
1522 + } else if(!entry->tx_buf && entry->rx_buf){ //read
1523 + rx((char*) entry->rx_buf, entry->len);
1524 + msg->actual_length += entry->len;
1525 + } else if(!entry->tx_buf && !entry->rx_buf){ //error
1526 + dev_err(&spidev->sdev->dev, "do_transfer: no buffers allocated\n");
1527 + msg->status = -EFAULT;
1530 + spin_lock(&spidev->message_lock);
1532 + spin_unlock(&spidev->message_lock);
1533 + msg->complete(msg->context);
1537 +static int locomospi_setup(struct spi_device *spi)
1539 + if((spi->mode & SPI_CS_HIGH) != (spidev->spimode & SPI_CS_HIGH))
1540 + locomospi_setcs(spi->mode & SPI_CS_HIGH ? 1 : 0 );
1541 + if(spidev->clock != spi->max_speed_hz){
1542 + locomospi_clock(spi->max_speed_hz);
1544 + spidev->spimode = spi->mode;
1549 +static int locomospi_transfer(struct spi_device *spi, struct spi_message *msg)
1552 + spin_lock(&spidev->message_lock);
1553 + list_add_tail(&msg->queue, &spidev->message_list);
1554 + spin_unlock(&spidev->message_lock);
1555 + schedule_work(&transfer_wq);
1559 +static struct locomo_driver locomo_spi_driver = {
1561 + .name = "locomo-spi",
1563 + .devid = LOCOMO_DEVID_SPI,
1564 + .probe = locomospi_probe,
1565 + .remove = locomospi_remove,
1567 + .suspend = locomospi_suspend,
1568 + .resume = locomospi_resume,
1572 +static struct spi_board_info board = {
1573 + .modalias = "mmc_spi",
1574 + .platform_data = (void*) &colliemmc,
1575 + .controller_data= NULL,
1577 + .max_speed_hz = 25000000,
1584 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state)
1586 + disable_irq(IRQ_LOCOMO_CARDDETECT);
1590 +static int locomospi_resume(struct locomo_dev *dev)
1592 + enable_irq(IRQ_LOCOMO_CARDDETECT);
1597 +static int locomospi_probe(struct locomo_dev *dev)
1600 + printk(KERN_DEBUG "Collie MMC over SPI Driver\n");
1601 + spidev=kmalloc(sizeof(struct locomospi_dev),GFP_KERNEL);
1605 + spidev->ldev = dev;
1606 + spidev->card_power = 1;
1607 + spidev->spimode = 0;
1609 + if(!request_mem_region((unsigned long) dev->mapbase, dev->length, LOCOMO_DRIVER_NAME(dev))) {
1610 + dev_err(&dev->dev, " Can't aquire access to io memory\n");
1613 + spidev->base=(unsigned long) dev->mapbase;
1614 + locomospi_reg_open();
1616 + locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_POWER, 0);
1617 + locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_DETECT, 1);
1618 + locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_WRITE_PROT, 1);
1620 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardpower);
1622 + dev_err(&dev->dev, "error creating driver attribute\n");
1625 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_carddetect);
1627 + dev_err(&dev->dev,"error creating driver attribute\n");
1630 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardwriteprotect);
1632 + dev_err(&dev->dev, "error creating driver attribute\n");
1635 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spimd);
1637 + dev_err(&dev->dev, "error creating driver attribute\n");
1640 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spict);
1642 + dev_err(&dev->dev, "error creating driver attribute\n");
1645 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spist);
1647 + dev_err(&dev->dev, "error creating driver attribute\n");
1650 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spitd);
1652 + dev_err(&dev->dev, "error creating driver attribute\n");
1655 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spird);
1657 + dev_err(&dev->dev, "error creating driver attribute\n");
1660 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spits);
1662 + dev_err(&dev->dev, "error creating driver attribute\n");
1665 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spirs);
1667 + dev_err(&dev->dev, "error creating driver attribute\n");
1670 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_clock);
1672 + dev_err(&dev->dev, "error creating driver attribute\n");
1675 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_delay);
1677 + dev_err(&dev->dev, "error creating driver attribute\n");
1680 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_reset);
1682 + dev_err(&dev->dev, "error creating driver attribute\n");
1685 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_regs);
1687 + dev_err(&dev->dev, "error creating driver attribute\n");
1690 + INIT_WORK(&transfer_wq, locomospi_do_transfer);
1691 + INIT_LIST_HEAD(&spidev->message_list);
1692 + spin_lock_init(&spidev->message_lock);
1693 + init_waitqueue_head(&spidev->waitqueue);
1694 + spidev->master=spi_alloc_master(&dev->dev,0);
1695 + if(!spidev->master){
1699 + spidev->master->bus_num = 0;
1700 + spidev->master->num_chipselect = 1;
1701 + spidev->master->setup = locomospi_setup;
1702 + spidev->master->transfer = locomospi_transfer;
1703 + spidev->sdev = spi_new_device(spidev->master, &board);
1704 + if(!spidev->sdev){
1705 + dev_err(&dev->dev, "failed to register spi device\n");
1709 +/* result=request_irq(IRQ_LOCOMO_SPI_RFR, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1711 + dev_err(&dev->dev, "Could not get IRQ: RFR\n");
1714 + //disable_irq(IRQ_LOCOMO_SPI_RFR);
1715 +*//* result=request_irq(IRQ_LOCOMO_SPI_RFW, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1717 + dev_err(&dev->dev, "Could not get IRQ: RFW\n");
1720 + //disable_irq(IRQ_LOCOMO_SPI_RFW);
1721 +*//* result=request_irq(IRQ_LOCOMO_SPI_REND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1723 + dev_err(&dev->dev, "Could not get IRQ: REND\n");
1726 +*//* result=request_irq(IRQ_LOCOMO_SPI_TEND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1728 + dev_err(&dev->dev, "Could not get IRQ: TEND\n");
1731 + //disable_irq(IRQ_LOCOMO_SPI_TEND);
1732 +*/ spidev->workqueue = create_singlethread_workqueue("locomo-spi");
1733 + if(!spidev->workqueue){
1734 + dev_err(&dev->dev, "failed to create workqueue\n");
1737 + result=spi_register_master(spidev->master);
1739 + dev_err(&dev->dev, "failed to register spimaster\n");
1744 + destroy_workqueue(spidev->workqueue);
1746 +// free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
1748 +// free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
1750 +// free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
1752 +// free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
1754 + spi_unregister_device(spidev->sdev);
1756 + spi_master_put(spidev->master);
1758 + release_mem_region((unsigned long) dev->mapbase, dev->length);
1764 +static int locomospi_remove(struct locomo_dev *dev)
1766 + spi_unregister_device(spidev->sdev);
1767 + spi_unregister_master(spidev->master);
1768 + destroy_workqueue(spidev->workqueue);
1769 + locomospi_reg_release();
1770 +// free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
1771 +// free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
1772 +// free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
1773 +// free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
1774 + spi_master_put(spidev->master);
1775 + release_mem_region((unsigned long) dev->mapbase, dev->length);
1782 +static int __init locomospi_init(void)
1784 + int ret = locomo_driver_register(&locomo_spi_driver);
1792 +static void __exit locomospi_exit(void)
1794 + locomo_driver_unregister(&locomo_spi_driver);
1797 +module_init(locomospi_init);
1798 +module_exit(locomospi_exit);
1800 +MODULE_AUTHOR("Thomas Kunze thommy@tabao.de");
1801 +MODULE_DESCRIPTION("Collie mmc driver");
1802 +MODULE_LICENSE("GPL");
1803 diff --git a/drivers/spi/locomo_spi.h b/drivers/spi/locomo_spi.h
1804 new file mode 100644
1805 index 0000000..7e1c0ce
1807 +++ b/drivers/spi/locomo_spi.h
1809 +#include <asm/hardware/locomo.h>
1810 +#ifndef __LOCOMO_SPI_H__
1811 +#define __LOCOMO_SPI_H__
1813 +/* locomo-spi status register LOCOMO_SPIST */
1814 +#define LOCOMO_SPI_TEND (1 << 3) /* Transfer end bit */
1815 +#define LOCOMO_SPI_REND (1 << 2) /* Receive end bit */
1816 +#define LOCOMO_SPI_RFW (1 << 1) /* write buffer bit */
1817 +#define LOCOMO_SPI_RFR (1) /* read buffer bit */
1819 +/* locomo-spi mode register LOCOMO_SPIMD */
1820 +#define LOCOMO_SPI_LOOPBACK (1 << 15) /* loopback tx to rx */
1821 +#define LOCOMO_SPI_MSB1ST (1 << 14) /* send MSB first */
1822 +#define LOCOMO_SPI_DOSTAT (1 << 13) /* transmit line is idle high */
1823 +#define LOCOMO_SPI_TCPOL (1 << 11) /* transmit CPOL (maybe affects CPHA too) */
1824 +#define LOCOMO_SPI_RCPOL (1 << 10) /* receive CPOL (maybe affects CPHA too) */
1825 +#define LOCOMO_SPI_TDINV (1 << 9) /* invert transmit line */
1826 +#define LOCOMO_SPI_RDINV (1 << 8) /* invert receive line */
1827 +#define LOCOMO_SPI_XON (1 << 7) /* enable spi controller clock */
1828 +#define LOCOMO_SPI_XEN (1 << 6) /* clock bit write enable xon must be off, wait 300 us before xon->1 */
1829 +#define LOCOMO_SPI_XSEL 0x0018 /* clock select */
1830 +#define CLOCK_18MHZ 0 /* 18,432 MHz clock */
1831 +#define CLOCK_22MHZ 1 /* 22,5792 MHz clock */
1832 +#define CLOCK_25MHZ 2 /* 24,576 MHz clock */
1833 +#define LOCOMO_SPI_CLKSEL 0x7
1834 +#define DIV_1 0 /* don't divide clock */
1835 +#define DIV_2 1 /* divide clock by two */
1836 +#define DIV_4 2 /* divide clock by four */
1837 +#define DIV_8 3 /* divide clock by eight*/
1838 +#define DIV_64 4 /* divide clock by 64 */
1840 +/* locomo-spi control register LOCOMO_SPICT */
1841 +#define LOCOMO_SPI_CRC16_7_B (1 << 15) /* 0: crc16 1: crc7 */
1842 +#define LOCOMO_SPI_CRCRX_TX_B (1 << 14)
1843 +#define LOCOMO_SPI_CRCRESET_B (1 << 13)
1844 +#define LOCOMO_SPI_CEN (1 << 7) /* ?? enable */
1845 +#define LOCOMO_SPI_CS (1 << 6) /* chip select */
1846 +#define LOCOMO_SPI_UNIT16 (1 << 5) /* 0: 8 bit units, 1: 16 bit unit */
1847 +#define LOCOMO_SPI_ALIGNEN (1 << 2) /* align transfer enable */
1848 +#define LOCOMO_SPI_RXWEN (1 << 1) /* continous receive */
1849 +#define LOCOMO_SPI_RXUEN (1 << 0) /* aligned receive */
1851 +#define IRQ_LOCOMO_CARDDETECT IRQ_LOCOMO_GPIO13
1854 +struct locomospi_dev {
1855 + struct locomo_dev *ldev;
1856 + struct spi_master *master;
1857 + struct spi_device *sdev;
1862 + unsigned long base;
1864 + wait_queue_head_t waitqueue;
1865 + struct workqueue_struct *workqueue;
1866 + struct list_head message_list;
1867 + spinlock_t message_lock;
1871 +static irqreturn_t locomospi_cardisr(int, void*);
1872 +static int locomospi_probe(struct locomo_dev*);
1873 +static int locomospi_remove(struct locomo_dev*);
1874 +static int locomospi_carddetect(void);
1875 +static void locomospi_reg_open(void);
1876 +static void locomospi_reg_release(void);
1877 +static int tx(const char*, int);
1878 +static int rx(char *, int);
1879 +static void locomospi_power(int on);
1880 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state);
1881 +static int locomospi_resume(struct locomo_dev *dev);
1882 +static void locomospi_setcs(int high);