merge of '0dc157d146c11b00a52d985950481dd2a8c370de'
[vuplus_openembedded] / packages / linux / linux-rp-2.6.26 / collie.patch
1 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
2 index c7ad324..daa2e0a 100644
3 --- a/arch/arm/Kconfig
4 +++ b/arch/arm/Kconfig
5 @@ -998,7 +998,7 @@ config CPU_FREQ_SA1100
6  
7  config CPU_FREQ_SA1110
8         bool
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)
11         default y
12  
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 {
19  
20  static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
21  
22 -static spinlock_t dma_list_lock;
23 +static  DEFINE_SPINLOCK(dma_list_lock);
24  
25  
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);
36  
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
46  
47 +config MCP_COLLIE_TS
48 +       tristate "Touchscreen collie support"
49 +       depends on MCP_UCB1200 && INPUT && !MCP_UCB1200_TS
50 +        ---help---
51 +         Driver for touchscreen on collie - sharp sl-5500.
52 +
53  endmenu
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
62 -
63 +obj-$(CONFIG_MCP_COLLIE_TS)     += collie-ts.o
64  ifeq ($(CONFIG_SA1100_ASSABET),y)
65  obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-assabet.o
66  endif
67 diff --git a/drivers/mfd/collie-ts.c b/drivers/mfd/collie-ts.c
68 new file mode 100644
69 index 0000000..ddde5fc
70 --- /dev/null
71 +++ b/drivers/mfd/collie-ts.c
72 @@ -0,0 +1,449 @@
73 +/*
74 + *  Touchscreen driver for UCB1x00-based touchscreens
75 + *
76 + *  Copyright (C) 2001 Russell King, All Rights Reserved.
77 + *  Copyright (C) 2005 Pavel Machek
78 + *
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.
82 + *
83 + * 21-Jan-2002 <jco@ict.es> :
84 + *
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.
91 + */
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>
106 +
107 +#include <asm/dma.h>
108 +#include <asm/semaphore.h>
109 +#include <asm/arch/collie.h>
110 +#include <asm/mach-types.h>
111 +
112 +#include "ucb1x00.h"
113 +
114 +struct ucb1x00_ts {
115 +       struct input_dev        *idev;
116 +       struct ucb1x00          *ucb;
117 +
118 +       wait_queue_head_t       irq_wait;
119 +       struct task_struct      *rtask;
120 +       u16                     x_res;
121 +       u16                     y_res;
122 +
123 +       unsigned int            adcsync:1;
124 +};
125 +
126 +static int adcsync;
127 +
128 +/**********************************
129 +
130 +     ................
131 +     .              . = 340
132 +     .              .
133 +     .             ^.
134 +     .             ^.
135 +     .             ^.
136 +     .             ^.
137 +     .              .
138 +     .             X. = 10
139 +     .  <<<<<<<<  Y .
140 +     ................
141 +     .   Sharp    =200
142 +     .              .
143 +     .  -   O    -  .
144 +     .              .
145 +     ................
146 +
147 +**********************************/
148 +
149 +
150 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
151 +{
152 +       struct input_dev *idev = ts->idev;
153 +
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);
158 +       input_sync(idev);
159 +}
160 +
161 +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
162 +{
163 +       struct input_dev *idev = ts->idev;
164 +
165 +       input_report_abs(idev, ABS_PRESSURE, 0);
166 +        input_report_key(idev, BTN_TOUCH, 0);
167 +       input_sync(idev);
168 +}
169 +
170 +/*
171 + * Switch to interrupt mode. This set touchscreen to interrupt 
172 + * mode, so that chip is able to send interrupt.
173 + */
174 +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
175 +{
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);
180 +}
181 +
182 +/*
183 + * Switch to pressure mode, and read pressure.  We don't need to wait
184 + * here, since both plates are being driven.
185 + *
186 + * set_read_pressure() in sharp code
187 + */
188 +static inline void ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
189 +{
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);
194 +
195 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
196 +                         UCB_ADC_INP_AD2 | 
197 +                         UCB_ADC_SYNC_ENA);
198 +       udelay(100);
199 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
200 +                         UCB_ADC_INP_AD2 | 
201 +                         UCB_ADC_SYNC_ENA | UCB_ADC_START);
202 +}
203 +
204 +/*
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.
209 + */
210 +static inline void ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
211 +{
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);
216 +
217 +
218 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
219 +                         UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA);
220 +       udelay(100);
221 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
222 +                         UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA | 
223 +                         UCB_ADC_START);
224 +}
225 +
226 +/*
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.
231 + */
232 +static inline void ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
233 +{
234 +       ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
235 +
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);
239 +
240 +
241 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
242 +                         UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA);
243 +       udelay(100);
244 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
245 +                         UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA | 
246 +                         UCB_ADC_START);
247 +}
248 +
249 +/*
250 + * Switch to X plate resistance mode.  Set MX to ground, PX to
251 + * supply.  Measure current.
252 + */
253 +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
254 +{
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);
259 +}
260 +
261 +/*
262 + * Switch to Y plate resistance mode.  Set MY to ground, PY to
263 + * supply.  Measure current.
264 + */
265 +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
266 +{
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);
271 +}
272 +
273 +/*
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).
277 + */
278 +static int ucb1x00_thread(void *_ts)
279 +{
280 +       struct ucb1x00_ts *ts = _ts;
281 +       struct task_struct *tsk = current;
282 +       DECLARE_WAITQUEUE(wait, tsk);
283 +       int state;
284 +
285 +       /*
286 +        * We could run as a real-time thread.  However, thus far
287 +        * this doesn't seem to be necessary.
288 +        */
289 +
290 +       add_wait_queue(&ts->irq_wait, &wait);   
291 +
292 +       while (!kthread_should_stop()) {
293 +               unsigned int data[3];
294 +                       
295 +               for (state=0; state<3; state++) {
296 +                       
297 +                       ucb1x00_adc_enable(ts->ucb);
298 +                       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING);
299 +                       switch (state) {
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);
303 +                                       break;
304 +                               case 0: ucb1x00_ts_read_ypos(ts);
305 +                                       break;
306 +                               case 1: ucb1x00_ts_read_xpos(ts);
307 +                                       break;
308 +                       }
309 +                       /* wait for adc */
310 +                       try_to_freeze();
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);
315 +               }       
316 +               
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);
324 +                       try_to_freeze();
325 +                       schedule_timeout(1000 * HZ);
326 +                       ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
327 +                       ucb1x00_enable(ts->ucb);
328 +               } else {        
329 +                       ucb1x00_ts_evt_add(ts, data[2], data[1], data[0]);
330 +               }
331 +               ucb1x00_disable(ts->ucb);
332 +               msleep(20);
333 +               ucb1x00_enable(ts->ucb);
334 +       }
335 +
336 +       remove_wait_queue(&ts->irq_wait, &wait);
337 +
338 +       ts->rtask = NULL;
339 +       return 0;
340 +}
341 +
342 +/*
343 + * We only detect touch screen _touches_ with this interrupt
344 + * handler, and even then we just schedule our task.
345 + */
346 +static void ucb1x00_ts_irq(int idx, void *id)
347 +{
348 +       struct ucb1x00_ts *ts = id;
349 +       wake_up(&ts->irq_wait);
350 +}
351 +
352 +static void ucb1x00_adc_irq(int idx, void *id)
353 +{
354 +       struct ucb1x00_ts *ts = id;
355 +       wake_up(&ts->irq_wait);
356 +}
357 +
358 +static int ucb1x00_ts_open(struct input_dev *idev)
359 +{
360 +       struct ucb1x00_ts *ts = input_get_drvdata(idev);
361 +       int ret = 0;
362 +
363 +       BUG_ON(ts->rtask);
364 +
365 +       init_waitqueue_head(&ts->irq_wait);
366 +       
367 +       ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
368 +       if (ret < 0)
369 +               return ret;
370 +       
371 +       ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_ADC, ucb1x00_adc_irq, ts);
372 +       if (ret < 0) {
373 +               ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
374 +               return ret;
375 +       }
376 +
377 +       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
378 +       
379 +       /*
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.
382 +        */
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);
387 +
388 +       if (machine_is_collie()) {
389 +               ucb1x00_io_set_dir(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
390 +       }
391 +
392 +       ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
393 +       if (!IS_ERR(ts->rtask)) {
394 +               ret = 0;
395 +       } else {
396 +               ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
397 +               ts->rtask = NULL;
398 +               ret = -EFAULT;
399 +       }
400 +       
401 +       return ret;
402 +}
403 +
404 +/*
405 + * Release touchscreen resources.  Disable IRQs.
406 + */
407 +static void ucb1x00_ts_close(struct input_dev *idev)
408 +{
409 +       struct ucb1x00_ts *ts = input_get_drvdata(idev);
410 +
411 +       if (ts->rtask)
412 +               kthread_stop(ts->rtask);
413 +
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);
419 +}
420 +
421 +#ifdef CONFIG_PM
422 +static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
423 +{
424 +       struct ucb1x00_ts *ts = dev->priv;
425 +
426 +       if (ts->rtask != NULL) {
427 +               /*
428 +                * Restart the TS thread to ensure the
429 +                * TS interrupt mode is set up again
430 +                * after sleep.
431 +                */
432 +               wake_up(&ts->irq_wait);
433 +       }
434 +       return 0;
435 +}
436 +#else
437 +#define ucb1x00_ts_resume NULL
438 +#endif
439 +
440 +
441 +/*
442 + * Initialisation.
443 + */
444 +static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
445 +{
446 +       struct ucb1x00_ts *ts;
447 +       struct input_dev *idev;
448 +       int err;
449 +
450 +       ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
451 +       idev = input_allocate_device();
452 +       if (!ts || !idev) {
453 +               err = -ENOMEM;
454 +               goto fail;
455 +       }
456 +
457 +       ts->ucb = dev->ucb;
458 +       ts->idev = idev;
459 +       ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
460 +
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;
466 +
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);
471 +
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);
475 +
476 +
477 +       err = input_register_device(idev);
478 +       if (err)
479 +               goto fail;
480 +
481 +       dev->priv = ts;
482 +
483 +       return 0;
484 +
485 + fail:
486 +       input_free_device(idev);
487 +       kfree(ts);
488 +       return err;
489 +}
490 +
491 +static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
492 +{
493 +       struct ucb1x00_ts *ts = dev->priv;
494 +
495 +       input_unregister_device(ts->idev);
496 +       kfree(ts);
497 +}
498 +
499 +static struct ucb1x00_driver ucb1x00_ts_driver = {
500 +       .add            = ucb1x00_ts_add,
501 +       .remove         = ucb1x00_ts_remove,
502 +       .resume         = ucb1x00_ts_resume,
503 +};
504 +
505 +static int __init ucb1x00_ts_init(void)
506 +{
507 +       return ucb1x00_register_driver(&ucb1x00_ts_driver);
508 +}
509 +
510 +static void __exit ucb1x00_ts_exit(void)
511 +{
512 +       ucb1x00_unregister_driver(&ucb1x00_ts_driver);
513 +}
514 +
515 +module_param(adcsync, int, 0444);
516 +module_init(ucb1x00_ts_init);
517 +module_exit(ucb1x00_ts_exit);
518 +
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
526 @@ -34,7 +34,10 @@
527  #define UCB_IE_TCLIP           (1 << 14)
528  #define UCB_IE_ACLIP           (1 << 15)
529  
530 +/* UCB1200 irqs */
531 +#define UCB_IRQ_ADC            11
532  #define UCB_IRQ_TSPX           12
533 +#define UCB_IRQ_TSMX           13
534  
535  #define UCB_TC_A       0x05
536  #define UCB_TC_A_LOOP          (1 << 7)        /* UCB1200 */
537 diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
538 index c7d5a52..215bec2 100644
539 --- a/drivers/mtd/maps/sa1100-flash.c
540 +++ b/drivers/mtd/maps/sa1100-flash.c
541 @@ -210,6 +210,12 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
542                 goto err;
543         }
544         subdev->mtd->owner = THIS_MODULE;
545 +       
546 +#ifdef CONFIG_SA1100_COLLIE
547 +       /* collie flash starts locked */
548 +        if (subdev->mtd->unlock)
549 +                subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size - 0xc0000);
550 +#endif
551  
552         printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
553                 "%d-bit\n", phys, subdev->mtd->size >> 20,
554 diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
555 index 3b4e55c..0ae741d 100644
556 --- a/drivers/net/wireless/hostap/hostap_cs.c
557 +++ b/drivers/net/wireless/hostap/hostap_cs.c
558 @@ -35,7 +35,7 @@ static int ignore_cis_vcc;
559  module_param(ignore_cis_vcc, int, 0444);
560  MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
561  
562 -
563 +int activar=0;
564  /* struct local_info::hw_priv */
565  struct hostap_cs_priv {
566         dev_node_t node;
567 @@ -499,11 +499,13 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev)
568  
569         PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
570         p_dev->conf.IntType = INT_MEMORY_AND_IO;
571 -
572 +       
573 +       activar=0;
574         ret = prism2_config(p_dev);
575         if (ret) {
576                 PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
577         }
578 +       activar=1;
579  
580         return ret;
581  }
582 diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
583 index 13d5882..6f24d66 100644
584 --- a/drivers/net/wireless/hostap/hostap_hw.c
585 +++ b/drivers/net/wireless/hostap/hostap_hw.c
586 @@ -54,6 +54,7 @@
587  #include "hostap.h"
588  #include "hostap_ap.h"
589  
590 +extern int activar;
591  
592  /* #define final_version */
593  
594 @@ -1497,6 +1498,8 @@ static int prism2_hw_config(struct net_device *dev, int initial)
595         if (local->hw_downloading)
596                 return 1;
597  
598 +       activar=1;
599 +
600         if (prism2_hw_init(dev, initial)) {
601                 return local->no_pri ? 0 : 1;
602         }
603 @@ -2628,8 +2631,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
604         int events = 0;
605         u16 ev;
606  
607 -       iface = netdev_priv(dev);
608 -       local = iface->local;
609 +
610 +       // Todos los parametros de entrada son correctos (no son nulos). De momento esta es la unica forma que conozco de detectar el problema.
611 +       if (!activar) {
612 +               printk("hostap_hw.c: INTERRUPT BEFORE DEVICE INIT!\n");
613 +               return IRQ_HANDLED;
614 +       }
615 +
616 +       iface = netdev_priv(dev);
617 +       local = iface->local;
618  
619         prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
620  
621 diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
622 index 3a874fc..df58aa3 100644
623 --- a/drivers/net/wireless/hostap/hostap_pci.c
624 +++ b/drivers/net/wireless/hostap/hostap_pci.c
625 @@ -19,6 +19,7 @@
626  
627  #include "hostap_wlan.h"
628  
629 +int activar=1;
630  
631  static char *dev_info = "hostap_pci";
632  
633 diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
634 index cbf15d7..4475174 100644
635 --- a/drivers/net/wireless/hostap/hostap_plx.c
636 +++ b/drivers/net/wireless/hostap/hostap_plx.c
637 @@ -21,7 +21,7 @@
638  #include <asm/io.h>
639  
640  #include "hostap_wlan.h"
641 -
642 +int activar=1;
643  
644  static char *dev_info = "hostap_plx";
645  
646 diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
647 index c5b2a44..eecbe8c 100644
648 --- a/drivers/pcmcia/sa1100_generic.c
649 +++ b/drivers/pcmcia/sa1100_generic.c
650 @@ -81,13 +81,14 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev)
651         return ret;
652  }
653  
654 -static struct device_driver sa11x0_pcmcia_driver = {
655 -       .probe          = sa11x0_drv_pcmcia_probe,
656 -       .remove         = soc_common_drv_pcmcia_remove,
657 -       .name           = "sa11x0-pcmcia",
658 -       .bus            = &platform_bus_type,
659 -       .suspend        = pcmcia_socket_dev_suspend,
660 -       .resume         = pcmcia_socket_dev_resume,
661 +static struct platform_driver sa11x0_pcmcia_driver = {
662 +       .driver         = {
663 +               .name   = "sa11x0-pcmcia",
664 +               .probe  = sa11x0_drv_pcmcia_probe,
665 +               .remove = soc_common_drv_pcmcia_remove,
666 +               .suspend= pcmcia_socket_dev_suspend,
667 +               .resume = pcmcia_socket_dev_resume,
668 +       },
669  };
670  
671  /* sa11x0_pcmcia_init()
672 @@ -100,7 +101,7 @@ static struct device_driver sa11x0_pcmcia_driver = {
673   */
674  static int __init sa11x0_pcmcia_init(void)
675  {
676 -       return driver_register(&sa11x0_pcmcia_driver);
677 +       return platform_driver_register(&sa11x0_pcmcia_driver);
678  }
679  
680  /* sa11x0_pcmcia_exit()
681 @@ -110,7 +111,7 @@ static int __init sa11x0_pcmcia_init(void)
682   */
683  static void __exit sa11x0_pcmcia_exit(void)
684  {
685 -       driver_unregister(&sa11x0_pcmcia_driver);
686 +       platform_driver_unregister(&sa11x0_pcmcia_driver);
687  }
688  
689  MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
690 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
691 index 66ec5d8..aba38d7 100644
692 --- a/drivers/spi/Kconfig
693 +++ b/drivers/spi/Kconfig
694 @@ -123,6 +123,10 @@ config SPI_MPC52xx_PSC
695           This enables using the Freescale MPC52xx Programmable Serial
696           Controller in master SPI mode.
697  
698 +config SPI_LOCOMO
699 +       tristate "Locomo SPI master"
700 +       depends on SPI_MASTER && SHARP_LOCOMO && EXPERIMENTAL
701 +
702  config SPI_MPC83xx
703         tristate "Freescale MPC83xx/QUICC Engine SPI controller"
704         depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
705 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
706 index 7fca043..b89992b 100644
707 --- a/drivers/spi/Makefile
708 +++ b/drivers/spi/Makefile
709 @@ -28,6 +28,7 @@ obj-$(CONFIG_SPI_S3C24XX)             += spi_s3c24xx.o
710  obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
711  obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
712  obj-$(CONFIG_SPI_SH_SCI)               += spi_sh_sci.o
713 +obj-$(CONFIG_SPI_LOCOMO)                += locomo_spi.o
714  #      ... add above this line ...
715  
716  # SPI protocol drivers (device/link on bus)
717 diff --git a/drivers/spi/locomo_spi.c b/drivers/spi/locomo_spi.c
718 new file mode 100644
719 index 0000000..d3a4bd9
720 --- /dev/null
721 +++ b/drivers/spi/locomo_spi.c
722 @@ -0,0 +1,1097 @@
723 +#include <asm/io.h>
724 +#include <asm/irq.h>
725 +#include <linux/module.h>
726 +#include <linux/init.h>
727 +#include <linux/device.h>
728 +#include <linux/stat.h>
729 +#include <linux/delay.h>
730 +#include <linux/wait.h>
731 +#include <linux/interrupt.h>
732 +#include <asm/hardware/locomo.h>
733 +#include <asm/errno.h>
734 +#include <linux/mmc/host.h>
735 +#include <linux/spi/spi.h>
736 +#include <linux/spi/mmc_spi.h>
737 +#include <linux/workqueue.h>
738 +#include <linux/spinlock.h>
739 +#include <linux/list.h>
740 +#include "locomo_spi.h"
741 +static struct locomospi_dev * spidev;
742 +static struct work_struct transfer_wq;
743 +int  delay;
744 +
745 +char* transtxbuf=(char*)NULL;
746 +char* transrxbuf=(char*)NULL;
747 +int transfercount=0, transfersize=0;
748 +static DECLARE_WAIT_QUEUE_HEAD(transferqueue);
749 +/* MMC_SPI functions *********************************************************/
750 +
751 +static int locomommcspi_init(struct device *dev, irqreturn_t (*isr)(int, void*), void *mmc)
752 +{
753 +       int result;
754 +       result=request_irq(IRQ_LOCOMO_CARDDETECT, isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "locomo-spi",  mmc);
755 +       return result;
756 +}
757 +
758 +static void locomommcspi_exit(struct device *dev, void* mmc)
759 +{
760 +       free_irq(IRQ_LOCOMO_CARDDETECT, mmc);
761 +}
762 +
763 +static int locomommcspi_getro(struct device *dev)
764 +{
765 +       return locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT) > 0 ? 1 : 0;
766 +}
767 +
768 +static void locomommcspi_setpower(struct device *dev, unsigned int mask)
769 +{
770 +       if(!mask && spidev->card_power)
771 +               locomospi_power(0);
772 +       else if( !spidev->card_power )
773 +               locomospi_power(1);
774 +
775 +}
776 +
777 +
778 +static struct mmc_spi_platform_data colliemmc ={
779 +       .init           = locomommcspi_init,
780 +       .exit           = locomommcspi_exit,
781 +       .detect_delay   = 200,
782 +       .get_ro         = locomommcspi_getro,
783 +       .ocr_mask       = MMC_VDD_32_33 | MMC_VDD_33_34,
784 +       .setpower       = locomommcspi_setpower,
785 +       .powerup_msecs  = 200,
786 +};
787 +
788 +/* Utility function **********************************************************/
789 +
790 +static void locomospi_power(int on)
791 +{
792 +       locomo_gpio_write(spidev->ldev->dev.parent, LOCOMO_GPIO_CARD_POWER, on);
793 +       spidev->card_power=on;
794 +       printk(KERN_DEBUG "locomospi: power %d\n",on);
795 +}
796 +
797 +static void locomospi_setclock(unsigned int div, unsigned int clock)
798 +{
799 +       u16 r = ioread16(spidev->base+LOCOMO_SPIMD);
800 +       div &= 0x7;
801 +       clock &= 0x3;
802 +       if(clock != spidev->clock_base || div != spidev->clock_div){
803 +               r &= ~(LOCOMO_SPI_XSEL  | LOCOMO_SPI_CLKSEL | LOCOMO_SPI_XEN);
804 +               iowrite16(r,spidev->base+LOCOMO_SPIMD);
805 +               r |=  (div | (clock <<3) | LOCOMO_SPI_XEN);
806 +               iowrite16(r,spidev->base+LOCOMO_SPIMD);
807 +               spidev->clock_div = div;
808 +               spidev->clock_base = clock;
809 +               udelay(300);
810 +       }
811 +
812 +}
813 +// returns 1 if card ist present, 0 otherwise
814 +static int locomospi_carddetect()
815 +{
816 +       return (locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1;
817 +}
818 +
819 +static void locomospi_setcs(int high)
820 +{
821 +       u16 r;
822 +       printk(KERN_DEBUG "locomospi: cs %d\n",high);
823 +       r = ioread16(spidev->base + LOCOMO_SPICT);
824 +       if(high)
825 +               r |= LOCOMO_SPI_CS;
826 +       else
827 +               r &= ~LOCOMO_SPI_CS;
828 +       iowrite16(r, spidev->base + LOCOMO_SPICT);
829 +}
830 +
831 +static void locomospi_reg_open()
832 +{
833 +       u16 r;
834 +       spidev->clock_div = DIV_64;
835 +       spidev->clock_base = CLOCK_18MHZ;
836 +       locomospi_power(1);
837 +       msleep(100);
838 +//     iowrite16( 0xec00 | (CLOCK_18MHZ <<3)|DIV_64, spidev->base+LOCOMO_SPIMD);
839 +       iowrite16( LOCOMO_SPI_MSB1ST | LOCOMO_SPI_DOSTAT | LOCOMO_SPI_RCPOL | LOCOMO_SPI_TCPOL 
840 +                       |(CLOCK_18MHZ <<3) | DIV_64, spidev->base+LOCOMO_SPIMD);
841 +//     if(locomospi_carddetect()){
842 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
843 +               r |= LOCOMO_SPI_XON;
844 +               iowrite16( r, spidev->base+LOCOMO_SPIMD);
845 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
846 +               r |= LOCOMO_SPI_XEN;
847 +               iowrite16( r, spidev->base+LOCOMO_SPIMD);
848 +//     }
849 +       iowrite16( LOCOMO_SPI_CS, spidev->base+LOCOMO_SPICT);
850 +       r = ioread16(spidev->base+LOCOMO_SPICT);
851 +       r |= (LOCOMO_SPI_CEN | LOCOMO_SPI_RXUEN | LOCOMO_SPI_ALIGNEN);
852 +       iowrite16( r, spidev->base+LOCOMO_SPICT);
853 +       udelay(200);
854 +       r = ioread16(spidev->base+LOCOMO_SPICT);
855 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
856 +       r = ioread16(spidev->base+LOCOMO_SPICT);
857 +       r &= ~LOCOMO_SPI_CS;
858 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
859 +}
860 +
861 +static void locomospi_reg_release()
862 +{
863 +       u16 r;
864 +       r = ioread16(spidev->base+LOCOMO_SPICT);
865 +       r &= ~LOCOMO_SPI_CEN;
866 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
867 +       r = ioread16(spidev->base+LOCOMO_SPIMD);
868 +       r &= ~LOCOMO_SPI_XEN;
869 +       iowrite16(r, spidev->base+LOCOMO_SPIMD);
870 +       r = ioread16(spidev->base+LOCOMO_SPIMD);
871 +       r &= ~LOCOMO_SPI_XON;
872 +       iowrite16(r, spidev->base+LOCOMO_SPIMD);
873 +       r = ioread16(spidev->base+LOCOMO_SPICT);
874 +       r |= LOCOMO_SPI_XEN;
875 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
876 +       locomospi_power(0);
877 +}
878 +#if 0
879 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
880 +{
881 +       u16 r = ioread16(spidev->base+LOCOMO_SPICT);
882 +       r |= LOCOMO_SPI_ALIGNEN;
883 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
884 +       printk(KERN_DEBUG "locomospi: %d bytes to prozess\n",size);
885 +       /* initialize global vars for isr */
886 +       transfercount=0; transfersize=size; 
887 +       transtxbuf=txbuffer; transrxbuf=rxbuffer;
888 +
889 +       /* start transmit and go sleep  isr will wake us*/
890 +       enable_irq(IRQ_LOCOMO_SPI_TEND);
891 +       iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD);
892 +       wait_event(transferqueue, transfercount >= transfersize);
893 +       disable_irq(IRQ_LOCOMO_SPI_TEND);
894 +       transrxbuf=NULL; transtxbuf=NULL;
895 +       
896 +       r = ioread16(spidev->base+LOCOMO_SPICT);
897 +       r &= ~LOCOMO_SPI_ALIGNEN;
898 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
899 +       int i;
900 +       for(i=0; i< size; i++)
901 +               printk(KERN_DEBUG "locomospi: sent: %x  received: %x \n",txbuffer[i], rxbuffer[i]);
902 +       
903 +       
904 +       return size;
905 +}
906 +
907 +
908 +static int tx(const char* txbuffer, int size)
909 +{
910 +       printk(KERN_DEBUG "locomospi: %d bytes to send\n",size);
911 +       /* initialize global vars for isr */
912 +       transfercount=0; transfersize=size; 
913 +       transtxbuf=txbuffer; 
914 +
915 +       /* start transmit and go sleep  isr will wake us*/
916 +       enable_irq(IRQ_LOCOMO_SPI_RFW);
917 +       iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD);
918 +       wait_event(transferqueue, transfercount >= transfersize);
919 +       disable_irq(IRQ_LOCOMO_SPI_RFW);
920 +       transtxbuf=NULL;
921 +       
922 +       int i;
923 +       for(i=0; i< size; i++)
924 +               printk(KERN_DEBUG "locomospi: sent: %x\n",txbuffer[i]);
925 +       
926 +       
927 +       return size;
928 +}
929 +
930 +static int rx(char* rxbuffer, int size)
931 +{
932 +       printk(KERN_DEBUG "locomospi: %d bytes to read\n",size);
933 +       /* initialize global vars for isr */
934 +       transfercount=0; transfersize=size; 
935 +       transrxbuf=rxbuffer;
936 +
937 +       /* start transmit and go sleep  isr will wake us*/
938 +       enable_irq(IRQ_LOCOMO_SPI_RFR);
939 +       rxbuffer[0]=ioread8(spidev->base+LOCOMO_SPIRD);
940 +       wait_event(transferqueue, transfercount >= transfersize);
941 +       disable_irq(IRQ_LOCOMO_SPI_RFR);
942 +       transrxbuf=NULL;
943 +       
944 +       int i;
945 +       for(i=0; i< size; i++)
946 +               printk(KERN_DEBUG "locomospi: received: %x \n", rxbuffer[i]);
947 +       
948 +       
949 +       return size;
950 +}
951 +
952 +#else
953 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
954 +{
955 +       int i=0,j=0;
956 +       int wait;
957 +       u16 r;
958 +/*     char * txback = kmalloc(size * sizeof(char), GFP_KERNEL);
959 +       memcpy(txback, txbuffer, size); 
960 +*/     
961 +       if(spidev->clock_div == 4)
962 +               wait = 0x10000;
963 +       else
964 +               wait = 8;
965 +       
966 +//     printk(KERN_DEBUG "locomospi: txrx %d bytes to prozess\n",size);
967 +       
968 +//     r = ioread16(spidev->base+LOCOMO_SPICT);
969 +//     r |= LOCOMO_SPI_ALIGNEN;
970 +//     iowrite16(r, spidev->base+LOCOMO_SPICT);
971 +       //discard first bogus byte
972 +
973 +       ioread8(spidev->base+LOCOMO_SPIRD);
974 +       for(i=0; i<size; i++){
975 +               for(j=0; j <= wait; j++){
976 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)
977 +                               break;
978 +               }
979 +               iowrite8(txbuffer[i], spidev->base+LOCOMO_SPITD);
980 +               ndelay(delay);
981 +               
982 +               for(j=0; j <= wait; j++){
983 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
984 +                               break;
985 +               }
986 +               rxbuffer[i] = ioread8(spidev->base+LOCOMO_SPIRD);
987 +               ndelay(delay);
988 +       }
989 +//     r = ioread16(spidev->base+LOCOMO_SPICT);
990 +//     r &= ~LOCOMO_SPI_ALIGNEN;
991 +//     iowrite16(r, spidev->base+LOCOMO_SPICT);
992 +       
993 +/*     for(j=0; j< size; j++)
994 +               printk(KERN_DEBUG "locomospi: sent: %x  received: %x \n",txback[j], rxbuffer[j]);
995 +       
996 +       kfree(txback);  
997 +*/     return i;
998 +}
999 +
1000 +static int tx(const char* buffer, int size)
1001 +{
1002 +       int i=0,j=0;
1003 +       int wait;
1004 +       u16 r;
1005 +       if(spidev->clock_div == 4)
1006 +               wait = 0x10000;
1007 +       else
1008 +               wait = 8;
1009 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1010 +       r &= ~LOCOMO_SPI_ALIGNEN;
1011 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1012 +
1013 +//     printk(KERN_DEBUG "locomospi: tx %d bytes to transmit\n",size);
1014 +       for(i=0; i<size; i++){
1015 +               for(j=0; j <= wait; j++){
1016 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)
1017 +                               break;
1018 +               }
1019 +               iowrite8(buffer[i], spidev->base+LOCOMO_SPITD);
1020 +               ndelay(delay);
1021 +       }
1022 +
1023 +       for(j=0; j <= wait; j++){
1024 +               if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_TEND)
1025 +                       break;
1026 +       }
1027 +       
1028 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1029 +       r |= LOCOMO_SPI_ALIGNEN;
1030 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1031 +       
1032 +//     for(j=0; j< size; j++)
1033 +//             printk(KERN_DEBUG "locomospi: sent: %x \n", buffer[j]);
1034 +//     printk(KERN_DEBUG "locomospi: tx %d bytes transmitted\n",i);
1035 +       return i;
1036 +}
1037 +
1038 +static int rx(char* buffer, int size)
1039 +{
1040 +       int i,j;
1041 +       int wait;
1042 +       u16 r;  
1043 +       printk(KERN_DEBUG "locomospi: rx %d bytes to receive\n",size);
1044 +       if(spidev->clock_div == 4)
1045 +               wait = 0x10000;
1046 +       else
1047 +               wait = 8;
1048 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1049 +       r &= ~LOCOMO_SPI_ALIGNEN;
1050 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1051 +
1052 +       for(i=0; i<size; i++){
1053 +
1054 +               for(j=0; j <= wait; j++){
1055 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
1056 +                               break;
1057 +               }
1058 +               buffer[i]= ioread8(spidev->base+LOCOMO_SPIRD);
1059 +               ndelay(delay);
1060 +       }
1061 +       
1062 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1063 +       r |= LOCOMO_SPI_ALIGNEN;
1064 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1065 +       
1066 +       for(j=0; j< size; j++)
1067 +               printk(KERN_DEBUG "locomospi: received: %x \n", buffer[j]);
1068 +       printk(KERN_DEBUG "locomospi: rx %d bytes received\n",i);
1069 +       return i;
1070 +}
1071 +#endif
1072 +/*
1073 +static irqreturn_t locomospi_rwready(int irq, void *dev_id)
1074 +{
1075 +       struct locomospi_dev* dev=(struct locomospi_dev*) dev_id;
1076 +//     dev_dbg(&spidev->sdev->dev, "IRQ: %d\n", irq);
1077 +//     printk(KERN_DEBUG "locomospi: IRQ: %d\n", irq);
1078 +       wake_up_interruptible(&dev->waitqueue);
1079 +       return IRQ_HANDLED;
1080 +}
1081 +*/
1082 +static irqreturn_t locomospi_testisr(int irq, void *dev_id)
1083 +{
1084 +       char *buf="";
1085 +       switch(irq){
1086 +               case IRQ_LOCOMO_SPI_RFR: buf="RFR";
1087 +                                        break;
1088 +               case IRQ_LOCOMO_SPI_RFW: buf="RFW";
1089 +                                        break;
1090 +               case IRQ_LOCOMO_SPI_REND:buf="REND";
1091 +                                        break;
1092 +               case IRQ_LOCOMO_SPI_TEND:buf="TEND";
1093 +                                        break;
1094 +               case IRQ_LOCOMO_CARDDETECT:
1095 +                                        buf="CARD_DETECT";
1096 +                                        break;
1097 +               default:                return IRQ_NONE;
1098 +       }
1099 +       printk(KERN_DEBUG "locomospi: IRQ: %s\n",buf);
1100 +//     dev_dbg(&spidev->sdev->dev, "IRQ: %s\n",buf);
1101 +       return IRQ_HANDLED;
1102 +}
1103 +static irqreturn_t locomospi_txrxisr(int irq, void *dev_id)
1104 +{
1105 +       if(transfercount < transfersize){
1106 +               transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1107 +               iowrite8(transtxbuf[transfercount], spidev->base+LOCOMO_SPITD);                 
1108 +       }
1109 +       else{
1110 +               /* transfer complete. wake up txrx */
1111 +               wake_up(&transferqueue);
1112 +       }
1113 +       return IRQ_HANDLED;     
1114 +}      
1115 +
1116 +static irqreturn_t locomospi_txisr(int irq, void *dev_id)
1117 +{
1118 +       if(transfercount < transfersize){
1119 +               iowrite8(transtxbuf[transfercount++], spidev->base+LOCOMO_SPITD);               
1120 +       }
1121 +       else{
1122 +               /* transfer complete. wake up txrx */
1123 +               wake_up(&transferqueue);
1124 +       }
1125 +       return IRQ_HANDLED;     
1126 +}      
1127 +
1128 +static irqreturn_t locomospi_rxisr(int irq, void *dev_id)
1129 +{
1130 +       if(transfercount < transfersize){
1131 +               transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1132 +       }
1133 +       else{
1134 +               /* transfer complete. wake up txrx */
1135 +               wake_up(&transferqueue);
1136 +       }
1137 +       return IRQ_HANDLED;     
1138 +}      
1139 +
1140 +static void locomospi_clock(unsigned int Hz)
1141 +{
1142 +       u16 r;
1143 +       printk(KERN_DEBUG "locomospi: changing clock to: %d\n", Hz);
1144 +       if(Hz == 0){
1145 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1146 +               r &= ~LOCOMO_SPI_XON;
1147 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1148 +       }
1149 +       else if(Hz >= 24576000){
1150 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1151 +               r |= LOCOMO_SPI_XON;
1152 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1153 +               locomospi_setclock(DIV_1, CLOCK_25MHZ);
1154 +               delay=41;
1155 +       }
1156 +       else if(Hz >= 22579200){
1157 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1158 +               r |= LOCOMO_SPI_XON;
1159 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1160 +               locomospi_setclock(DIV_1, CLOCK_22MHZ);
1161 +               delay=45;
1162 +       }
1163 +       else if(Hz >= 18432000){
1164 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1165 +               r |= LOCOMO_SPI_XON;
1166 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1167 +               locomospi_setclock(DIV_1, CLOCK_18MHZ);
1168 +               delay=55;
1169 +       }
1170 +       else if(Hz >= 12288000){
1171 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1172 +               r |= LOCOMO_SPI_XON;
1173 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1174 +               locomospi_setclock(DIV_2, CLOCK_25MHZ);
1175 +               delay=82;
1176 +       }
1177 +       else if(Hz >= 11289600){
1178 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1179 +               r |= LOCOMO_SPI_XON;
1180 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1181 +               locomospi_setclock(DIV_2, CLOCK_22MHZ);
1182 +               delay=89;
1183 +       }
1184 +       else if(Hz >= 9216000){
1185 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1186 +               r |= LOCOMO_SPI_XON;
1187 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1188 +               locomospi_setclock(DIV_2, CLOCK_18MHZ);
1189 +               delay=110;
1190 +       }
1191 +       else if(Hz >= 6144000){
1192 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1193 +               r |= LOCOMO_SPI_XON;
1194 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1195 +               locomospi_setclock(DIV_4, CLOCK_25MHZ);
1196 +               delay=164;
1197 +       }
1198 +       else if(Hz >= 5644800){
1199 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1200 +               r |= LOCOMO_SPI_XON;
1201 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1202 +               locomospi_setclock(DIV_4, CLOCK_22MHZ);
1203 +               delay=178;
1204 +       }
1205 +       else if(Hz >= 4608000){
1206 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1207 +               r |= LOCOMO_SPI_XON;
1208 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1209 +               locomospi_setclock(DIV_4, CLOCK_18MHZ);
1210 +               delay=218;
1211 +       }
1212 +       else if(Hz >= 3072000){
1213 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1214 +               r |= LOCOMO_SPI_XON;
1215 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1216 +               locomospi_setclock(DIV_8, CLOCK_25MHZ);
1217 +               delay=327;
1218 +       }
1219 +       else if(Hz >= 2822400){
1220 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1221 +               r |= LOCOMO_SPI_XON;
1222 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1223 +               locomospi_setclock(DIV_8, CLOCK_22MHZ);
1224 +               delay=355;
1225 +       }
1226 +       else if(Hz >= 2304000){
1227 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1228 +               r |= LOCOMO_SPI_XON;
1229 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1230 +               locomospi_setclock(DIV_8, CLOCK_18MHZ);
1231 +               delay=435;
1232 +       }
1233 +       else if(Hz >= 384000){
1234 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1235 +               r |= LOCOMO_SPI_XON;
1236 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1237 +               locomospi_setclock(DIV_64, CLOCK_25MHZ);
1238 +               delay=2605;
1239 +       }
1240 +       else if(Hz >= 352800){
1241 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1242 +               r |= LOCOMO_SPI_XON;
1243 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1244 +               locomospi_setclock(DIV_64, CLOCK_22MHZ);
1245 +               delay=2834;
1246 +       }
1247 +       else{ /* set to 288 KHz */
1248 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1249 +               r |= LOCOMO_SPI_XON;
1250 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1251 +               locomospi_setclock(DIV_64, CLOCK_18MHZ);
1252 +               delay=3473;
1253 +       }
1254 +       spidev->clock = Hz;
1255 +}
1256 +
1257 +/* sysfs attributes used for debug *******************************************/
1258 +
1259 +/* SPI registers */
1260 +ssize_t locomospi_showspimd(struct device_driver *drv, char *buf)
1261 +{
1262 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIMD));
1263 +}
1264 +
1265 +ssize_t locomospi_storespimd(struct device_driver *drv, const char *buf, size_t count)
1266 +{
1267 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIMD);
1268 +       return count;
1269 +}
1270 +static DRIVER_ATTR(spimd, S_IWUSR | S_IRUGO, locomospi_showspimd, locomospi_storespimd);
1271 +
1272 +ssize_t locomospi_showspict(struct device_driver *drv, char *buf)
1273 +{
1274 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPICT));
1275 +}
1276 +
1277 +ssize_t locomospi_storespict(struct device_driver *drv, const char *buf, size_t count)
1278 +{
1279 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPICT);
1280 +       return count;
1281 +}
1282 +static DRIVER_ATTR(spict, S_IWUSR | S_IRUGO, locomospi_showspict, locomospi_storespict);
1283 +
1284 +ssize_t locomospi_showspist(struct device_driver *drv, char *buf)
1285 +{
1286 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIST));
1287 +}
1288 +
1289 +ssize_t locomospi_storespist(struct device_driver *drv, const char *buf, size_t count)
1290 +{
1291 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIST);
1292 +       return count;
1293 +}
1294 +static DRIVER_ATTR(spist, S_IWUSR | S_IRUGO, locomospi_showspist, locomospi_storespist);
1295 +
1296 +ssize_t locomospi_showspitd(struct device_driver *drv, char *buf)
1297 +{
1298 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITD));
1299 +}
1300 +
1301 +ssize_t locomospi_storespitd(struct device_driver *drv, const char *buf, size_t count)
1302 +{
1303 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITD);
1304 +       return count;
1305 +}
1306 +static DRIVER_ATTR(spitd, S_IWUSR | S_IRUGO, locomospi_showspitd, locomospi_storespitd);
1307 +
1308 +ssize_t locomospi_showspird(struct device_driver *drv, char *buf)
1309 +{
1310 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRD));
1311 +}
1312 +
1313 +ssize_t locomospi_storespird(struct device_driver *drv, const char *buf, size_t count)
1314 +{
1315 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRD);
1316 +       return count;
1317 +}
1318 +static DRIVER_ATTR(spird, S_IWUSR | S_IRUGO, locomospi_showspird, locomospi_storespird);
1319 +
1320 +ssize_t locomospi_showspits(struct device_driver *drv, char *buf)
1321 +{
1322 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITS));
1323 +}
1324 +
1325 +ssize_t locomospi_storespits(struct device_driver *drv, const char *buf, size_t count)
1326 +{
1327 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITS);
1328 +       return count;
1329 +}
1330 +static DRIVER_ATTR(spits, S_IWUSR | S_IRUGO, locomospi_showspits, locomospi_storespits);
1331 +
1332 +ssize_t locomospi_showspirs(struct device_driver *drv, char *buf)
1333 +{
1334 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRS));
1335 +}
1336 +
1337 +ssize_t locomospi_storespirs(struct device_driver *drv, const char *buf, size_t count)
1338 +{
1339 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRS);
1340 +       return count;
1341 +}
1342 +static DRIVER_ATTR(spirs, S_IWUSR | S_IRUGO, locomospi_showspirs, locomospi_storespirs);
1343 +
1344 +/* MMC Card status */
1345 +
1346 +ssize_t locomospi_showpower(struct device_driver *drv, char *buf)
1347 +{
1348 +       return sprintf(buf, "%d\n", spidev->card_power);
1349 +}
1350 +
1351 +ssize_t locomospi_storepower(struct device_driver *drv, const char *buf, size_t count)
1352 +{
1353 +       locomospi_power(simple_strtoul(buf, NULL, 10));
1354 +       return count;
1355 +}
1356 +static DRIVER_ATTR(cardpower, S_IWUSR | S_IRUGO, locomospi_showpower, locomospi_storepower);
1357 +
1358 +ssize_t locomospi_detectcard(struct device_driver *drv, char *buf)
1359 +{
1360 +       return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1);
1361 +}
1362 +static DRIVER_ATTR(carddetect, S_IRUGO, locomospi_detectcard, NULL);
1363 +
1364 +ssize_t locomospi_writeprotect(struct device_driver *drv, char *buf)
1365 +{
1366 +       return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT)>0)?1:0);
1367 +}
1368 +static DRIVER_ATTR(cardwriteprotect, S_IRUGO, locomospi_writeprotect, NULL);
1369 +
1370 +
1371 +ssize_t locomospi_showclock(struct device_driver *drv, char *buf)
1372 +{
1373 +       return sprintf(buf, "%d\n", spidev->clock);
1374 +}
1375 +
1376 +ssize_t locomospi_storeclock(struct device_driver *drv, const char *buf, size_t count)
1377 +{
1378 +       locomospi_clock(simple_strtoul(buf, NULL, 10));
1379 +       return count;
1380 +}
1381 +static DRIVER_ATTR(clock, S_IWUSR | S_IRUGO, locomospi_showclock, locomospi_storeclock);
1382 +
1383 +/* debug */
1384 +ssize_t locomospi_showdelay(struct device_driver *drv, char *buf)
1385 +{
1386 +       return sprintf(buf, "%d\n", delay);
1387 +}
1388 +
1389 +ssize_t locomospi_storedelay(struct device_driver *drv, const char *buf, size_t count)
1390 +{
1391 +       delay=simple_strtoul(buf,NULL,10);
1392 +       return count;
1393 +}
1394 +static DRIVER_ATTR(delay, S_IWUSR | S_IRUGO, locomospi_showdelay, locomospi_storedelay);
1395 +
1396 +ssize_t locomospi_reset(struct device_driver *drv, const char *buf, size_t count)
1397 +{
1398 +       int choice = simple_strtoul(buf, NULL, 10);
1399 +       char   buff[100];
1400 +       u16 r; 
1401 +       switch(choice){
1402 +               case 0: locomospi_reg_release();
1403 +                       schedule_timeout(2*HZ);
1404 +                       locomospi_reg_open();
1405 +                       break;
1406 +               case 1: {
1407 +                               char b1[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
1408 +                               char b2[] = "\xff\x40\x00\x00\x00\x00\x95\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
1409 +                               locomospi_setcs(1);
1410 +                               txrx(b1,b1,17);
1411 +                               locomospi_setcs(0);
1412 +                               txrx(b2,b2,18);
1413 +
1414 +                       }
1415 +                       break;
1416 +               case 2: locomospi_setcs(1);
1417 +                       txrx("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",buff,18);
1418 +                       locomospi_setcs(0);
1419 +                       txrx("\xff\x40\x00\x00\x00\x00\x95\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",buff,17);
1420 +                       break;
1421 +               case 3: 
1422 +                       r = ioread16(spidev->base+LOCOMO_SPIMD);
1423 +                       r |= LOCOMO_SPI_LOOPBACK;
1424 +                       iowrite16(r, spidev->base+LOCOMO_SPIMD);
1425 +                       txrx("X",buff,1);
1426 +                       txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
1427 +                       txrx("Y",buff,1);
1428 +                       udelay(100);
1429 +                       txrx("Z",buff,1);
1430 +                       schedule_timeout(HZ);   
1431 +                       txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
1432 +                       
1433 +                       r = ioread16(spidev->base+LOCOMO_SPIMD);
1434 +                       r &= ~LOCOMO_SPI_LOOPBACK;
1435 +                       iowrite16(r, spidev->base+LOCOMO_SPIMD);
1436 +                       break;
1437 +               default: /* do nothing */;
1438 +       }
1439 +       return count;
1440 +}
1441 +static DRIVER_ATTR(reset, S_IWUSR, NULL, locomospi_reset);
1442 +
1443 +typedef struct locomo_reg_entry {
1444 +        u32 addr;
1445 +        char* name;
1446 +} locomo_reg_entry_t;
1447 +#define LCM     (sizeof(locomo_regs)/sizeof(locomo_reg_entry_t))
1448 +static locomo_reg_entry_t locomo_regs[] =
1449 +{
1450 +/*      { addr,    name,     description } */
1451 +        { 0x00, "VER" },
1452 +        { 0x04, "ST" },
1453 +        { 0x08, "C32K" },
1454 +        { 0x0C, "ICR" },
1455 +        { 0x10, "MCSX0" },
1456 +        { 0x14, "MCSX1" },
1457 +        { 0x18, "MCSX2" },
1458 +        { 0x1C, "MCSX3" },
1459 +        { 0x20, "ASD" },
1460 +        { 0x28, "HSD" },
1461 +        { 0x2C, "HSC" },
1462 +        { 0x30, "TADC" },
1463 +        { 0x38, "TC" },
1464 +        { 0x3C, "CPSD" },
1465 +        { 0x40, "KIB" },
1466 +        { 0x44, "KSC" },
1467 +        { 0x48, "KCMD" },
1468 +        { 0x4C, "KIC" },
1469 +        { 0x54, "ACC" },
1470 +        { 0x60, "SPIMD" },
1471 +        { 0x64, "SPICT" },
1472 +        { 0x68, "SPIST" },
1473 +        { 0x70, "SPIIS" },
1474 +        { 0x74, "SPIWE" },
1475 +        { 0x78, "SPIIE" },
1476 +        { 0x7C, "SPIIR" },
1477 +        { 0x80, "SPITD" },
1478 +        { 0x84, "SPIRD" },
1479 +        { 0x88, "SPITS" },
1480 +        { 0x8C, "SPIRS" },
1481 +        { 0x90, "GPD" },
1482 +        { 0x94, "GPE" },
1483 +        { 0x98, "GPL" },
1484 +        { 0x9C, "GPO" },
1485 +        { 0xa0, "GRIE" },
1486 +        { 0xa4, "GFIE" },
1487 +        { 0xa8, "GIS" },
1488 +        { 0xac, "GWE" },
1489 +        { 0xb0, "GIE" },
1490 +        { 0xb4, "GIR" },
1491 +        { 0xc8, "ALC" },
1492 +        { 0xcc, "ALR" },
1493 +        { 0xd0, "PAIF" },
1494 +        { 0xd8, "LTC" },
1495 +        { 0xdc, "LTINT" },
1496 +        { 0xe0, "DAC" },
1497 +        { 0xe8, "LPT0" },
1498 +        { 0xec, "LPT1" },
1499 +        { 0xfc, "TCR" },
1500 +};
1501 +
1502 +static ssize_t lcm_show(struct device *dev, struct device_attribute *attr, char *buf)
1503 +{
1504 +       int base = spidev->base - LOCOMO_SPI; 
1505 +       char b[4000]="";
1506 +       char c[30];
1507 +       int i;
1508 +       for(i=0; i<LCM; i++){
1509 +               sprintf(c,"%s:\t\t 0x%x\n",locomo_regs[i].name, ioread16(base + locomo_regs[i].addr));
1510 +               strcat(b,c);
1511 +       }
1512 +       return sprintf(buf,"%s",b);
1513 +}
1514 +
1515 +static DRIVER_ATTR(regs, 0444, lcm_show, NULL);
1516 +
1517 +
1518 +/* SPI functions *************************************************************/
1519 +
1520 +static void locomospi_do_transfer(struct work_struct *wrk)
1521 +{
1522 +       struct list_head *mptr, *tptr, *mptr2;
1523 +       struct spi_transfer *entry;
1524 +       struct spi_message *msg;
1525 +
1526 +       list_for_each_safe(mptr, mptr2, &spidev->message_list){
1527 +               msg = list_entry(mptr, struct spi_message, queue);
1528 +
1529 +               msg->status = 0;
1530 +               msg->actual_length = 0;
1531 +               list_for_each(tptr, &msg->transfers){
1532 +                       entry = list_entry(tptr, struct spi_transfer, transfer_list);
1533 +                       if(entry->tx_buf && entry->rx_buf){ //duplex
1534 +                               txrx((char*) entry->tx_buf, (char*) entry->rx_buf, entry->len);                         
1535 +                               msg->actual_length += entry->len;
1536 +                       } else if(entry->tx_buf && !entry->rx_buf){ //write
1537 +                               tx((char*) entry->tx_buf, entry->len);
1538 +                               msg->actual_length += entry->len;
1539 +                       } else if(!entry->tx_buf && entry->rx_buf){ //read
1540 +                               rx((char*) entry->rx_buf, entry->len);
1541 +                               msg->actual_length += entry->len;
1542 +                       } else if(!entry->tx_buf && !entry->rx_buf){ //error
1543 +                               dev_err(&spidev->sdev->dev, "do_transfer: no buffers allocated\n");
1544 +                               msg->status = -EFAULT;
1545 +                       }
1546 +               }
1547 +               spin_lock(&spidev->message_lock);
1548 +               list_del(mptr);
1549 +               spin_unlock(&spidev->message_lock);
1550 +               msg->complete(msg->context);
1551 +       }
1552 +}
1553 +
1554 +static int locomospi_setup(struct spi_device *spi)
1555 +{
1556 +       if((spi->mode & SPI_CS_HIGH) != (spidev->spimode & SPI_CS_HIGH)) 
1557 +               locomospi_setcs(spi->mode & SPI_CS_HIGH ? 1 : 0 );
1558 +       if(spidev->clock != spi->max_speed_hz){
1559 +               locomospi_clock(spi->max_speed_hz);
1560 +       }
1561 +       spidev->spimode = spi->mode;
1562 +
1563 +       return 0;
1564 +}
1565 +
1566 +static int locomospi_transfer(struct spi_device *spi, struct spi_message *msg)
1567 +{
1568 +
1569 +       spin_lock(&spidev->message_lock);
1570 +       list_add_tail(&msg->queue, &spidev->message_list);
1571 +       spin_unlock(&spidev->message_lock);
1572 +       schedule_work(&transfer_wq);
1573 +       return 0;
1574 +}
1575 +
1576 +static struct locomo_driver locomo_spi_driver = {
1577 +       .drv = {
1578 +               .name = "locomo-spi",
1579 +       },
1580 +       .devid  = LOCOMO_DEVID_SPI,
1581 +       .probe  = locomospi_probe,
1582 +       .remove = locomospi_remove,
1583 +#ifdef CONFIG_PM
1584 +       .suspend = locomospi_suspend,
1585 +       .resume = locomospi_resume,
1586 +#endif
1587 +};
1588 +
1589 +static struct spi_board_info board = {
1590 +       .modalias       = "mmc_spi",
1591 +       .platform_data  = (void*) &colliemmc,
1592 +       .controller_data= NULL,
1593 +       .irq            = 0,
1594 +       .max_speed_hz   = 25000000,
1595 +       .bus_num        = 0,
1596 +       .chip_select    = 0,
1597 +       .mode           = 0,
1598 +};
1599 +
1600 +#ifdef CONFIG_PM
1601 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state)
1602 +{
1603 +       disable_irq(IRQ_LOCOMO_CARDDETECT);
1604 +       return 0;
1605 +}
1606 +
1607 +static int locomospi_resume(struct locomo_dev *dev)
1608 +{
1609 +       enable_irq(IRQ_LOCOMO_CARDDETECT);
1610 +       return 0;
1611 +}
1612 +#endif
1613 +
1614 +static int locomospi_probe(struct locomo_dev *dev)
1615 +{
1616 +       int result=0;
1617 +       printk(KERN_DEBUG "Collie MMC over SPI Driver\n");
1618 +       spidev=kmalloc(sizeof(struct locomospi_dev),GFP_KERNEL);
1619 +       if(!spidev){
1620 +               return -ENOMEM;
1621 +       }
1622 +       spidev->ldev = dev;
1623 +       spidev->card_power = 1;
1624 +       spidev->spimode = 0;
1625 +
1626 +       if(!request_mem_region((unsigned long) dev->mapbase, dev->length, LOCOMO_DRIVER_NAME(dev))) {
1627 +               dev_err(&dev->dev, " Can't aquire access to io memory\n");
1628 +               return -EBUSY;
1629 +       }
1630 +       spidev->base=(unsigned long) dev->mapbase;
1631 +       locomospi_reg_open();
1632 +
1633 +       locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_POWER, 0);
1634 +       locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_DETECT, 1);
1635 +       locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_WRITE_PROT, 1);
1636 +
1637 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardpower);
1638 +       if(result){
1639 +               dev_err(&dev->dev, "error creating driver attribute\n");
1640 +               goto region;
1641 +       }
1642 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_carddetect);
1643 +       if(result){
1644 +               dev_err(&dev->dev,"error creating driver attribute\n");
1645 +               goto region;
1646 +       }
1647 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardwriteprotect);
1648 +       if(result){
1649 +               dev_err(&dev->dev, "error creating driver attribute\n");
1650 +               goto region;
1651 +       }
1652 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spimd);
1653 +       if(result){
1654 +               dev_err(&dev->dev, "error creating driver attribute\n");
1655 +               goto region;
1656 +       }
1657 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spict);
1658 +       if(result){
1659 +               dev_err(&dev->dev, "error creating driver attribute\n");
1660 +               goto region;
1661 +       }
1662 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spist);
1663 +       if(result){
1664 +               dev_err(&dev->dev, "error creating driver attribute\n");
1665 +               goto region;
1666 +       }
1667 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spitd);
1668 +       if(result){
1669 +               dev_err(&dev->dev, "error creating driver attribute\n");
1670 +               goto region;
1671 +       }
1672 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spird);
1673 +       if(result){
1674 +               dev_err(&dev->dev, "error creating driver attribute\n");
1675 +               goto region;
1676 +       }
1677 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spits);
1678 +       if(result){
1679 +               dev_err(&dev->dev, "error creating driver attribute\n");
1680 +               goto region;
1681 +       }
1682 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spirs);
1683 +       if(result){
1684 +               dev_err(&dev->dev, "error creating driver attribute\n");
1685 +               goto region;
1686 +       }
1687 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_clock);
1688 +       if(result){
1689 +               dev_err(&dev->dev, "error creating driver attribute\n");
1690 +               goto region;
1691 +       }
1692 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_delay);
1693 +       if(result){
1694 +               dev_err(&dev->dev, "error creating driver attribute\n");
1695 +               goto region;
1696 +       }
1697 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_reset);
1698 +       if(result){
1699 +               dev_err(&dev->dev, "error creating driver attribute\n");
1700 +               goto region;
1701 +       }
1702 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_regs);
1703 +        if(result){
1704 +                dev_err(&dev->dev, "error creating driver attribute\n");
1705 +                goto region;
1706 +        }
1707 +       INIT_WORK(&transfer_wq, locomospi_do_transfer);
1708 +       INIT_LIST_HEAD(&spidev->message_list);
1709 +       spin_lock_init(&spidev->message_lock);
1710 +       init_waitqueue_head(&spidev->waitqueue);
1711 +       spidev->master=spi_alloc_master(&dev->dev,0);
1712 +       if(!spidev->master){
1713 +               result=-ENOMEM;
1714 +               goto region;
1715 +       }
1716 +       spidev->master->bus_num = 0;
1717 +       spidev->master->num_chipselect = 1;
1718 +       spidev->master->setup = locomospi_setup;
1719 +       spidev->master->transfer = locomospi_transfer;
1720 +       spidev->sdev = spi_new_device(spidev->master, &board);
1721 +       if(!spidev->sdev){
1722 +               dev_err(&dev->dev, "failed to register spi device\n");
1723 +               result = -EINVAL;
1724 +               goto master;
1725 +       }
1726 +/*     result=request_irq(IRQ_LOCOMO_SPI_RFR, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1727 +       if(result) {
1728 +               dev_err(&dev->dev, "Could not get IRQ: RFR\n");
1729 +               goto regdev;
1730 +       }
1731 +       //disable_irq(IRQ_LOCOMO_SPI_RFR);
1732 +*//*   result=request_irq(IRQ_LOCOMO_SPI_RFW, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1733 +       if(result) {
1734 +               dev_err(&dev->dev, "Could not get IRQ: RFW\n");
1735 +               goto irq1;
1736 +       }
1737 +       //disable_irq(IRQ_LOCOMO_SPI_RFW);
1738 +*//*   result=request_irq(IRQ_LOCOMO_SPI_REND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1739 +       if(result) {
1740 +               dev_err(&dev->dev, "Could not get IRQ: REND\n");
1741 +               goto irq2;
1742 +       }
1743 +*//*   result=request_irq(IRQ_LOCOMO_SPI_TEND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
1744 +       if(result) {
1745 +               dev_err(&dev->dev, "Could not get IRQ: TEND\n");
1746 +               goto irq3;
1747 +       }
1748 +       //disable_irq(IRQ_LOCOMO_SPI_TEND);     
1749 +*/     spidev->workqueue = create_singlethread_workqueue("locomo-spi");
1750 +       if(!spidev->workqueue){
1751 +               dev_err(&dev->dev, "failed to create workqueue\n");
1752 +               goto irq4;
1753 +       }
1754 +       result=spi_register_master(spidev->master);
1755 +       if(result){
1756 +               dev_err(&dev->dev, "failed to register spimaster\n");
1757 +               goto wq;
1758 +       }
1759 +       return 0;
1760 +wq:
1761 +       destroy_workqueue(spidev->workqueue);
1762 +irq4:
1763 +//     free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
1764 +irq3:
1765 +//     free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
1766 +irq2:
1767 +//     free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
1768 +irq1:
1769 +//     free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
1770 +regdev:
1771 +       spi_unregister_device(spidev->sdev);
1772 +master:
1773 +       spi_master_put(spidev->master);
1774 +region:
1775 +       release_mem_region((unsigned long) dev->mapbase, dev->length);
1776 +       kfree(spidev);
1777 +       return result;
1778 +
1779 +}
1780 +
1781 +static int locomospi_remove(struct locomo_dev *dev)
1782 +{
1783 +       spi_unregister_device(spidev->sdev);
1784 +       spi_unregister_master(spidev->master);
1785 +       destroy_workqueue(spidev->workqueue);
1786 +       locomospi_reg_release();
1787 +//     free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
1788 +//     free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
1789 +//     free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
1790 +//     free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
1791 +       spi_master_put(spidev->master);
1792 +       release_mem_region((unsigned long) dev->mapbase, dev->length);
1793 +       kfree(spidev);
1794 +       return 0;
1795 +}
1796 +
1797 +
1798 +
1799 +static int __init locomospi_init(void)
1800 +{
1801 +       int ret = locomo_driver_register(&locomo_spi_driver);
1802 +       if (ret)
1803 +               return ret;
1804 +
1805 +
1806 +       return 0;
1807 +}
1808 +
1809 +static void __exit locomospi_exit(void)
1810 +{
1811 +       locomo_driver_unregister(&locomo_spi_driver);
1812 +}
1813 +
1814 +module_init(locomospi_init);
1815 +module_exit(locomospi_exit);
1816 +
1817 +MODULE_AUTHOR("Thomas Kunze thommy@tabao.de");
1818 +MODULE_DESCRIPTION("Collie mmc driver");
1819 +MODULE_LICENSE("GPL");
1820 diff --git a/drivers/spi/locomo_spi.h b/drivers/spi/locomo_spi.h
1821 new file mode 100644
1822 index 0000000..7e1c0ce
1823 --- /dev/null
1824 +++ b/drivers/spi/locomo_spi.h
1825 @@ -0,0 +1,75 @@
1826 +#include <asm/hardware/locomo.h>
1827 +#ifndef __LOCOMO_SPI_H__
1828 +#define __LOCOMO_SPI_H__
1829 +
1830 +/* locomo-spi status register LOCOMO_SPIST */
1831 +#define LOCOMO_SPI_TEND (1 << 3)        /* Transfer end bit */
1832 +#define LOCOMO_SPI_REND (1 << 2)        /* Receive end bit */
1833 +#define LOCOMO_SPI_RFW  (1 << 1)        /* write buffer bit */
1834 +#define LOCOMO_SPI_RFR  (1)             /* read buffer bit */
1835 +
1836 +/* locomo-spi mode register LOCOMO_SPIMD */
1837 +#define LOCOMO_SPI_LOOPBACK (1 << 15)  /* loopback tx to rx    */
1838 +#define LOCOMO_SPI_MSB1ST   (1 << 14)  /* send MSB first       */
1839 +#define LOCOMO_SPI_DOSTAT   (1 << 13)  /* transmit line is idle high */
1840 +#define LOCOMO_SPI_TCPOL    (1 << 11)  /* transmit CPOL (maybe affects CPHA too) */
1841 +#define LOCOMO_SPI_RCPOL    (1 << 10)  /* receive CPOL (maybe affects CPHA too) */
1842 +#define        LOCOMO_SPI_TDINV    (1 << 9)    /* invert transmit line */
1843 +#define LOCOMO_SPI_RDINV    (1 << 8)   /* invert receive line */
1844 +#define LOCOMO_SPI_XON     (1 << 7)    /* enable spi controller clock */
1845 +#define LOCOMO_SPI_XEN     (1 << 6)    /* clock bit write enable xon must be off, wait 300 us before xon->1 */ 
1846 +#define LOCOMO_SPI_XSEL            0x0018      /* clock select                 */
1847 +#define CLOCK_18MHZ        0           /* 18,432 MHz clock     */
1848 +#define CLOCK_22MHZ        1           /* 22,5792 MHz clock    */
1849 +#define CLOCK_25MHZ        2           /* 24,576 MHz clock     */
1850 +#define LOCOMO_SPI_CLKSEL   0x7        
1851 +#define DIV_1              0           /* don't divide clock   */
1852 +#define DIV_2              1           /* divide clock by two  */
1853 +#define DIV_4              2           /* divide clock by four */
1854 +#define DIV_8              3           /* divide clock by eight*/
1855 +#define DIV_64             4           /* divide clock by 64 */
1856 +
1857 +/* locomo-spi control register LOCOMO_SPICT */
1858 +#define LOCOMO_SPI_CRC16_7_B   (1 << 15)       /* 0: crc16 1: crc7 */
1859 +#define LOCOMO_SPI_CRCRX_TX_B  (1 << 14)
1860 +#define LOCOMO_SPI_CRCRESET_B  (1 << 13)
1861 +#define LOCOMO_SPI_CEN         (1 << 7)        /* ?? enable */
1862 +#define LOCOMO_SPI_CS          (1 << 6)        /* chip select */
1863 +#define LOCOMO_SPI_UNIT16      (1 << 5)        /* 0: 8 bit units, 1: 16 bit unit */
1864 +#define LOCOMO_SPI_ALIGNEN     (1 << 2)        /* align transfer enable */
1865 +#define LOCOMO_SPI_RXWEN       (1 << 1)        /* continous receive */
1866 +#define LOCOMO_SPI_RXUEN       (1 << 0)        /* aligned receive */
1867 +
1868 +#define IRQ_LOCOMO_CARDDETECT  IRQ_LOCOMO_GPIO13
1869 +
1870 +
1871 +struct locomospi_dev {
1872 +       struct locomo_dev *ldev;
1873 +       struct spi_master *master;
1874 +       struct spi_device *sdev;
1875 +       int card_power;
1876 +       int clock_base;
1877 +       int clock_div;
1878 +       int clock;
1879 +       unsigned long base;
1880 +       u8 spimode;
1881 +       wait_queue_head_t waitqueue;
1882 +       struct workqueue_struct *workqueue;
1883 +       struct list_head message_list;
1884 +       spinlock_t message_lock;
1885 +};
1886 +
1887 +
1888 +static irqreturn_t     locomospi_cardisr(int, void*);
1889 +static int     locomospi_probe(struct locomo_dev*);
1890 +static int     locomospi_remove(struct locomo_dev*);
1891 +static int     locomospi_carddetect(void);
1892 +static void    locomospi_reg_open(void);
1893 +static void    locomospi_reg_release(void);
1894 +static int     tx(const char*, int);
1895 +static int     rx(char *, int);
1896 +static void    locomospi_power(int on);
1897 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state);
1898 +static int locomospi_resume(struct locomo_dev *dev);
1899 +static void locomospi_setcs(int high);
1900 +#endif