linux-kexecboot: use hacked sharp-flash driver
[vuplus_openembedded] / packages / kexecboot / linux-kexecboot-2.6.26 / collie.patch
1 Index: linux-2.6.26/arch/arm/Kconfig
2 ===================================================================
3 --- linux-2.6.26.orig/arch/arm/Kconfig  2008-07-13 23:51:29.000000000 +0200
4 +++ linux-2.6.26/arch/arm/Kconfig       2008-10-17 18:15:31.391792839 +0200
5 @@ -967,7 +967,7 @@
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 Index: linux-2.6.26/arch/arm/mach-sa1100/collie.c
15 ===================================================================
16 --- linux-2.6.26.orig/arch/arm/mach-sa1100/collie.c     2008-07-13 23:51:29.000000000 +0200
17 +++ linux-2.6.26/arch/arm/mach-sa1100/collie.c  2008-10-17 18:15:31.391792839 +0200
18 @@ -206,7 +206,7 @@
19  }
20  
21  static struct flash_platform_data collie_flash_data = {
22 -       .map_name       = "cfi_probe",
23 +       .map_name       = "sharp",
24         .set_vpp        = collie_set_vpp,
25         .parts          = collie_partitions,
26         .nr_parts       = ARRAY_SIZE(collie_partitions),
27 Index: linux-2.6.26/arch/arm/mach-sa1100/dma.c
28 ===================================================================
29 --- linux-2.6.26.orig/arch/arm/mach-sa1100/dma.c        2008-07-13 23:51:29.000000000 +0200
30 +++ linux-2.6.26/arch/arm/mach-sa1100/dma.c     2008-10-17 18:15:31.399789199 +0200
31 @@ -39,7 +39,7 @@
32  
33  static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
34  
35 -static spinlock_t dma_list_lock;
36 +static  DEFINE_SPINLOCK(dma_list_lock);
37  
38  
39  static irqreturn_t dma_irq_handler(int irq, void *dev_id)
40 Index: linux-2.6.26/drivers/input/keyboard/locomokbd.c
41 ===================================================================
42 --- linux-2.6.26.orig/drivers/input/keyboard/locomokbd.c        2008-10-17 18:13:16.000000000 +0200
43 +++ linux-2.6.26/drivers/input/keyboard/locomokbd.c     2008-10-17 18:15:31.403791239 +0200
44 @@ -272,6 +272,7 @@
45         for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
46                 set_bit(locomokbd->keycode[i], input_dev->keybit);
47         clear_bit(0, input_dev->keybit);
48 +       locomo_writel(0, locomokbd->base + LOCOMO_KSC);
49  
50         /* attempt to get the interrupt */
51         err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
52 Index: linux-2.6.26/drivers/mfd/Kconfig
53 ===================================================================
54 --- linux-2.6.26.orig/drivers/mfd/Kconfig       2008-10-17 18:13:21.000000000 +0200
55 +++ linux-2.6.26/drivers/mfd/Kconfig    2008-10-17 18:15:31.403791239 +0200
56 @@ -77,4 +77,10 @@
57         tristate "Touchscreen interface support"
58         depends on MCP_UCB1200 && INPUT
59  
60 +config MCP_COLLIE_TS
61 +       tristate "Touchscreen collie support"
62 +       depends on MCP_UCB1200 && INPUT && !MCP_UCB1200_TS
63 +        ---help---
64 +         Driver for touchscreen on collie - sharp sl-5500.
65 +
66  endmenu
67 Index: linux-2.6.26/drivers/mfd/Makefile
68 ===================================================================
69 --- linux-2.6.26.orig/drivers/mfd/Makefile      2008-10-17 18:13:21.000000000 +0200
70 +++ linux-2.6.26/drivers/mfd/Makefile   2008-10-17 18:15:31.407791679 +0200
71 @@ -14,7 +14,7 @@
72  obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
73  obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-core.o
74  obj-$(CONFIG_MCP_UCB1200_TS)   += ucb1x00-ts.o
75 -
76 +obj-$(CONFIG_MCP_COLLIE_TS)     += collie-ts.o
77  ifeq ($(CONFIG_SA1100_ASSABET),y)
78  obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-assabet.o
79  endif
80 Index: linux-2.6.26/drivers/mfd/collie-ts.c
81 ===================================================================
82 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
83 +++ linux-2.6.26/drivers/mfd/collie-ts.c        2008-10-17 18:15:31.415790559 +0200
84 @@ -0,0 +1,449 @@
85 +/*
86 + *  Touchscreen driver for UCB1x00-based touchscreens
87 + *
88 + *  Copyright (C) 2001 Russell King, All Rights Reserved.
89 + *  Copyright (C) 2005 Pavel Machek
90 + *
91 + * This program is free software; you can redistribute it and/or modify
92 + * it under the terms of the GNU General Public License version 2 as
93 + * published by the Free Software Foundation.
94 + *
95 + * 21-Jan-2002 <jco@ict.es> :
96 + *
97 + * Added support for synchronous A/D mode. This mode is useful to
98 + * avoid noise induced in the touchpanel by the LCD, provided that
99 + * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
100 + * It is important to note that the signal connected to the ADCSYNC
101 + * pin should provide pulses even when the LCD is blanked, otherwise
102 + * a pen touch needed to unblank the LCD will never be read.
103 + */
104 +#include <linux/module.h>
105 +#include <linux/moduleparam.h>
106 +#include <linux/init.h>
107 +#include <linux/smp.h>
108 +#include <linux/smp_lock.h>
109 +#include <linux/sched.h>
110 +#include <linux/completion.h>
111 +#include <linux/delay.h>
112 +#include <linux/string.h>
113 +#include <linux/input.h>
114 +#include <linux/device.h>
115 +#include <linux/freezer.h>
116 +#include <linux/slab.h>
117 +#include <linux/kthread.h>
118 +#include <linux/semaphore.h>
119 +
120 +#include <asm/dma.h>
121 +#include <asm/arch/collie.h>
122 +#include <asm/mach-types.h>
123 +
124 +#include "ucb1x00.h"
125 +
126 +struct ucb1x00_ts {
127 +       struct input_dev        *idev;
128 +       struct ucb1x00          *ucb;
129 +
130 +       wait_queue_head_t       irq_wait;
131 +       struct task_struct      *rtask;
132 +       u16                     x_res;
133 +       u16                     y_res;
134 +
135 +       unsigned int            adcsync:1;
136 +};
137 +
138 +static int adcsync;
139 +
140 +/**********************************
141 +
142 +     ................
143 +     .              . = 340
144 +     .              .
145 +     .             ^.
146 +     .             ^.
147 +     .             ^.
148 +     .             ^.
149 +     .              .
150 +     .             X. = 10
151 +     .  <<<<<<<<  Y .
152 +     ................
153 +     .   Sharp    =200
154 +     .              .
155 +     .  -   O    -  .
156 +     .              .
157 +     ................
158 +
159 +**********************************/
160 +
161 +
162 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
163 +{
164 +       struct input_dev *idev = ts->idev;
165 +
166 +       input_report_abs(idev, ABS_X, x);
167 +       input_report_abs(idev, ABS_Y, y);
168 +       input_report_abs(idev, ABS_PRESSURE, pressure);
169 +        input_report_key(idev, BTN_TOUCH, 1);
170 +       input_sync(idev);
171 +}
172 +
173 +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
174 +{
175 +       struct input_dev *idev = ts->idev;
176 +
177 +       input_report_abs(idev, ABS_PRESSURE, 0);
178 +        input_report_key(idev, BTN_TOUCH, 0);
179 +       input_sync(idev);
180 +}
181 +
182 +/*
183 + * Switch to interrupt mode. This set touchscreen to interrupt 
184 + * mode, so that chip is able to send interrupt.
185 + */
186 +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
187 +{
188 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
189 +                       UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
190 +                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
191 +                       UCB_TS_CR_MODE_INT);
192 +}
193 +
194 +/*
195 + * Switch to pressure mode, and read pressure.  We don't need to wait
196 + * here, since both plates are being driven.
197 + *
198 + * set_read_pressure() in sharp code
199 + */
200 +static inline void ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
201 +{
202 +       ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
203 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
204 +                         UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
205 +                         UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
206 +
207 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
208 +                         UCB_ADC_INP_AD2 | 
209 +                         UCB_ADC_SYNC_ENA);
210 +       udelay(100);
211 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
212 +                         UCB_ADC_INP_AD2 | 
213 +                         UCB_ADC_SYNC_ENA | UCB_ADC_START);
214 +}
215 +
216 +/*
217 + * Switch to X position mode and measure Y plate.  We switch the plate
218 + * configuration in pressure mode, then switch to position mode.  This
219 + * gives a faster response time.  Even so, we need to wait about 55us
220 + * for things to stabilise.
221 + */
222 +static inline void ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
223 +{
224 +       ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
225 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
226 +                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
227 +                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
228 +
229 +
230 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
231 +                         UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA);
232 +       udelay(100);
233 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
234 +                         UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA | 
235 +                         UCB_ADC_START);
236 +}
237 +
238 +/*
239 + * Switch to Y position mode and measure X plate.  We switch the plate
240 + * configuration in pressure mode, then switch to position mode.  This
241 + * gives a faster response time.  Even so, we need to wait about 55us
242 + * for things to stabilise.
243 + */
244 +static inline void ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
245 +{
246 +       ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
247 +
248 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
249 +                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
250 +                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
251 +
252 +
253 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr | 
254 +                         UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA);
255 +       udelay(100);
256 +       ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
257 +                         UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA | 
258 +                         UCB_ADC_START);
259 +}
260 +
261 +/*
262 + * Switch to X plate resistance mode.  Set MX to ground, PX to
263 + * supply.  Measure current.
264 + */
265 +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
266 +{
267 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
268 +                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_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 + * Switch to Y plate resistance mode.  Set MY to ground, PY to
275 + * supply.  Measure current.
276 + */
277 +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
278 +{
279 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
280 +                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
281 +                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
282 +       return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
283 +}
284 +
285 +/*
286 + * This is a RT kernel thread that handles the ADC accesses
287 + * (mainly so we can use semaphores in the UCB1200 core code
288 + * to serialise accesses to the ADC).
289 + */
290 +static int ucb1x00_thread(void *_ts)
291 +{
292 +       struct ucb1x00_ts *ts = _ts;
293 +       struct task_struct *tsk = current;
294 +       DECLARE_WAITQUEUE(wait, tsk);
295 +       int state;
296 +
297 +       /*
298 +        * We could run as a real-time thread.  However, thus far
299 +        * this doesn't seem to be necessary.
300 +        */
301 +
302 +       add_wait_queue(&ts->irq_wait, &wait);   
303 +
304 +       while (!kthread_should_stop()) {
305 +               unsigned int data[3];
306 +                       
307 +               for (state=0; state<3; state++) {
308 +                       
309 +                       ucb1x00_adc_enable(ts->ucb);
310 +                       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING);
311 +                       switch (state) {
312 +                       /* Order matters here; last measurement seems to be more noisy then the
313 +                          rest, and we care about pressure least */
314 +                               case 2: ucb1x00_ts_read_pressure(ts);
315 +                                       break;
316 +                               case 0: ucb1x00_ts_read_ypos(ts);
317 +                                       break;
318 +                               case 1: ucb1x00_ts_read_xpos(ts);
319 +                                       break;
320 +                       }
321 +                       /* wait for adc */
322 +                       try_to_freeze();
323 +                       schedule_timeout(1000 * HZ);
324 +                       ucb1x00_disable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING);
325 +                       data[state] = UCB_ADC_DAT(ucb1x00_reg_read(ts->ucb, UCB_ADC_DATA));
326 +                       ucb1x00_adc_disable(ts->ucb);
327 +               }       
328 +               
329 +               /* If not pressed any more, try to sleep! */
330 +               if (data[2] < 300) {
331 +                       set_task_state(tsk, TASK_INTERRUPTIBLE);
332 +                       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
333 +                       ucb1x00_ts_mode_int(ts);
334 +                       ucb1x00_disable(ts->ucb);
335 +                       ucb1x00_ts_event_release(ts);
336 +                       try_to_freeze();
337 +                       schedule_timeout(1000 * HZ);
338 +                       ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
339 +                       ucb1x00_enable(ts->ucb);
340 +               } else {        
341 +                       ucb1x00_ts_evt_add(ts, data[2], data[1], data[0]);
342 +               }
343 +               ucb1x00_disable(ts->ucb);
344 +               msleep(20);
345 +               ucb1x00_enable(ts->ucb);
346 +       }
347 +
348 +       remove_wait_queue(&ts->irq_wait, &wait);
349 +
350 +       ts->rtask = NULL;
351 +       return 0;
352 +}
353 +
354 +/*
355 + * We only detect touch screen _touches_ with this interrupt
356 + * handler, and even then we just schedule our task.
357 + */
358 +static void ucb1x00_ts_irq(int idx, void *id)
359 +{
360 +       struct ucb1x00_ts *ts = id;
361 +       wake_up(&ts->irq_wait);
362 +}
363 +
364 +static void ucb1x00_adc_irq(int idx, void *id)
365 +{
366 +       struct ucb1x00_ts *ts = id;
367 +       wake_up(&ts->irq_wait);
368 +}
369 +
370 +static int ucb1x00_ts_open(struct input_dev *idev)
371 +{
372 +       struct ucb1x00_ts *ts = input_get_drvdata(idev);
373 +       int ret = 0;
374 +
375 +       BUG_ON(ts->rtask);
376 +
377 +       init_waitqueue_head(&ts->irq_wait);
378 +       
379 +       ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
380 +       if (ret < 0)
381 +               return ret;
382 +       
383 +       ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_ADC, ucb1x00_adc_irq, ts);
384 +       if (ret < 0) {
385 +               ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
386 +               return ret;
387 +       }
388 +
389 +       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
390 +       
391 +       /*
392 +        * If we do this at all, we should allow the user to
393 +        * measure and read the X and Y resistance at any time.
394 +        */
395 +       ucb1x00_adc_enable(ts->ucb);
396 +       ts->x_res = ucb1x00_ts_read_xres(ts);
397 +       ts->y_res = ucb1x00_ts_read_yres(ts);
398 +       ucb1x00_adc_disable(ts->ucb);
399 +
400 +       if (machine_is_collie()) {
401 +               ucb1x00_io_set_dir(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
402 +       }
403 +
404 +       ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
405 +       if (!IS_ERR(ts->rtask)) {
406 +               ret = 0;
407 +       } else {
408 +               ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
409 +               ts->rtask = NULL;
410 +               ret = -EFAULT;
411 +       }
412 +       
413 +       return ret;
414 +}
415 +
416 +/*
417 + * Release touchscreen resources.  Disable IRQs.
418 + */
419 +static void ucb1x00_ts_close(struct input_dev *idev)
420 +{
421 +       struct ucb1x00_ts *ts = input_get_drvdata(idev);
422 +
423 +       if (ts->rtask)
424 +               kthread_stop(ts->rtask);
425 +
426 +       ucb1x00_enable(ts->ucb);
427 +       ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
428 +       ucb1x00_free_irq(ts->ucb, UCB_IRQ_ADC, ts);
429 +       ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
430 +       ucb1x00_disable(ts->ucb);
431 +}
432 +
433 +#ifdef CONFIG_PM
434 +static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
435 +{
436 +       struct ucb1x00_ts *ts = dev->priv;
437 +
438 +       if (ts->rtask != NULL) {
439 +               /*
440 +                * Restart the TS thread to ensure the
441 +                * TS interrupt mode is set up again
442 +                * after sleep.
443 +                */
444 +               wake_up(&ts->irq_wait);
445 +       }
446 +       return 0;
447 +}
448 +#else
449 +#define ucb1x00_ts_resume NULL
450 +#endif
451 +
452 +
453 +/*
454 + * Initialisation.
455 + */
456 +static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
457 +{
458 +       struct ucb1x00_ts *ts;
459 +       struct input_dev *idev;
460 +       int err;
461 +
462 +       ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
463 +       idev = input_allocate_device();
464 +       if (!ts || !idev) {
465 +               err = -ENOMEM;
466 +               goto fail;
467 +       }
468 +
469 +       ts->ucb = dev->ucb;
470 +       ts->idev = idev;
471 +       ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
472 +
473 +       input_set_drvdata(idev, ts);
474 +       idev->name       = "Touchscreen panel";
475 +       idev->id.product = ts->ucb->id;
476 +       idev->open       = ucb1x00_ts_open;
477 +       idev->close      = ucb1x00_ts_close;
478 +
479 +       __set_bit(EV_ABS, idev->evbit);
480 +       __set_bit(ABS_X, idev->absbit);
481 +       __set_bit(ABS_Y, idev->absbit);
482 +       __set_bit(ABS_PRESSURE, idev->absbit);
483 +
484 +        input_set_abs_params(ts->idev, ABS_X, 0, 450, 0, 0);
485 +        input_set_abs_params(ts->idev, ABS_Y, 200, 800, 0, 0);
486 +        input_set_abs_params(ts->idev, ABS_PRESSURE, 400, 800, 0, 0);
487 +
488 +
489 +       err = input_register_device(idev);
490 +       if (err)
491 +               goto fail;
492 +
493 +       dev->priv = ts;
494 +
495 +       return 0;
496 +
497 + fail:
498 +       input_free_device(idev);
499 +       kfree(ts);
500 +       return err;
501 +}
502 +
503 +static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
504 +{
505 +       struct ucb1x00_ts *ts = dev->priv;
506 +
507 +       input_unregister_device(ts->idev);
508 +       kfree(ts);
509 +}
510 +
511 +static struct ucb1x00_driver ucb1x00_ts_driver = {
512 +       .add            = ucb1x00_ts_add,
513 +       .remove         = ucb1x00_ts_remove,
514 +       .resume         = ucb1x00_ts_resume,
515 +};
516 +
517 +static int __init ucb1x00_ts_init(void)
518 +{
519 +       return ucb1x00_register_driver(&ucb1x00_ts_driver);
520 +}
521 +
522 +static void __exit ucb1x00_ts_exit(void)
523 +{
524 +       ucb1x00_unregister_driver(&ucb1x00_ts_driver);
525 +}
526 +
527 +module_param(adcsync, int, 0444);
528 +module_init(ucb1x00_ts_init);
529 +module_exit(ucb1x00_ts_exit);
530 +
531 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
532 +MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
533 +MODULE_LICENSE("GPL");
534 Index: linux-2.6.26/drivers/mfd/ucb1x00.h
535 ===================================================================
536 --- linux-2.6.26.orig/drivers/mfd/ucb1x00.h     2008-07-13 23:51:29.000000000 +0200
537 +++ linux-2.6.26/drivers/mfd/ucb1x00.h  2008-10-17 18:15:31.415790559 +0200
538 @@ -34,7 +34,10 @@
539  #define UCB_IE_TCLIP           (1 << 14)
540  #define UCB_IE_ACLIP           (1 << 15)
541  
542 +/* UCB1200 irqs */
543 +#define UCB_IRQ_ADC            11
544  #define UCB_IRQ_TSPX           12
545 +#define UCB_IRQ_TSMX           13
546  
547  #define UCB_TC_A       0x05
548  #define UCB_TC_A_LOOP          (1 << 7)        /* UCB1200 */
549 Index: linux-2.6.26/drivers/mtd/chips/Kconfig
550 ===================================================================
551 --- linux-2.6.26.orig/drivers/mtd/chips/Kconfig 2008-07-13 23:51:29.000000000 +0200
552 +++ linux-2.6.26/drivers/mtd/chips/Kconfig      2008-10-17 18:15:31.419791479 +0200
553 @@ -239,5 +239,13 @@
554           used for XIP purposes.  If you're not sure what this is all about
555           then say N.
556  
557 +config MTD_SHARP
558 +        tristate "pre-CFI Sharp chip support"
559 +        depends on MTD
560 +        help
561 +          This option enables support for flash chips using Sharp-compatible
562 +          commands, including some which are not CFI-compatible and hence
563 +          cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
564 +
565  endmenu
566  
567 Index: linux-2.6.26/drivers/mtd/chips/Makefile
568 ===================================================================
569 --- linux-2.6.26.orig/drivers/mtd/chips/Makefile        2008-07-13 23:51:29.000000000 +0200
570 +++ linux-2.6.26/drivers/mtd/chips/Makefile     2008-10-17 18:15:31.419791479 +0200
571 @@ -12,4 +12,5 @@
572  obj-$(CONFIG_MTD_JEDECPROBE)   += jedec_probe.o
573  obj-$(CONFIG_MTD_RAM)          += map_ram.o
574  obj-$(CONFIG_MTD_ROM)          += map_rom.o
575 +obj-$(CONFIG_MTD_SHARP)         += sharp.o
576  obj-$(CONFIG_MTD_ABSENT)       += map_absent.o
577 Index: linux-2.6.26/drivers/mtd/chips/sharp.c
578 ===================================================================
579 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
580 +++ linux-2.6.26/drivers/mtd/chips/sharp.c      2008-10-17 18:15:31.423790399 +0200
581 @@ -0,0 +1,645 @@
582 +/*
583 + * MTD chip driver for pre-CFI Sharp flash chips
584 + *
585 + * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
586 + *           2000,2001 Lineo, Inc.
587 + *
588 + * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
589 + *
590 + * Devices supported:
591 + *   LH28F016SCT Symmetrical block flash memory, 2Mx8
592 + *   LH28F008SCT Symmetrical block flash memory, 1Mx8
593 + *
594 + * Documentation:
595 + *   http://www.sharpmeg.com/datasheets/memic/flashcmp/
596 + *   http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
597 + *   016sctl9.pdf
598 + *
599 + * Limitations:
600 + *   This driver only supports 4x1 arrangement of chips.
601 + *   Not tested on anything but PowerPC.
602 + */
603 +
604 +#include <linux/kernel.h>
605 +#include <linux/module.h>
606 +#include <linux/types.h>
607 +#include <linux/sched.h>
608 +#include <linux/errno.h>
609 +#include <linux/init.h>
610 +#include <linux/interrupt.h>
611 +#include <linux/mtd/map.h>
612 +#include <linux/mtd/mtd.h>
613 +#include <linux/mtd/cfi.h>
614 +#include <linux/delay.h>
615 +#include <linux/init.h>
616 +
617 +#define CMD_RESET              0xffffffff
618 +#define CMD_READ_ID            0x90909090
619 +#define CMD_READ_STATUS                0x70707070
620 +#define CMD_CLEAR_STATUS       0x50505050
621 +#define CMD_BLOCK_ERASE_1      0x20202020
622 +#define CMD_BLOCK_ERASE_2      0xd0d0d0d0
623 +#define CMD_BYTE_WRITE         0x40404040
624 +#define CMD_SUSPEND            0xb0b0b0b0
625 +#define CMD_RESUME             0xd0d0d0d0
626 +#define CMD_SET_BLOCK_LOCK_1   0x60606060
627 +#define CMD_SET_BLOCK_LOCK_2   0x01010101
628 +#define CMD_SET_MASTER_LOCK_1  0x60606060
629 +#define CMD_SET_MASTER_LOCK_2  0xf1f1f1f1
630 +#define CMD_CLEAR_BLOCK_LOCKS_1        0x60606060
631 +#define CMD_CLEAR_BLOCK_LOCKS_2        0xd0d0d0d0
632 +
633 +#define SR_READY               0x80808080 // 1 = ready
634 +#define SR_ERASE_SUSPEND       0x40404040 // 1 = block erase suspended
635 +#define SR_ERROR_ERASE         0x20202020 // 1 = error in block erase or clear lock bits
636 +#define SR_ERROR_WRITE         0x10101010 // 1 = error in byte write or set lock bit
637 +#define        SR_VPP                  0x08080808 // 1 = Vpp is low
638 +#define SR_WRITE_SUSPEND       0x04040404 // 1 = byte write suspended
639 +#define SR_PROTECT             0x02020202 // 1 = lock bit set
640 +#define SR_RESERVED            0x01010101
641 +
642 +#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
643 +
644 +#define BLOCK_MASK             0xfffe0000
645 +
646 +/* Configuration options */
647 +
648 +#define AUTOUNLOCK  /* automatically unlocks blocks before erasing */
649 +
650 +static struct mtd_info *sharp_probe(struct map_info *);
651 +
652 +static int sharp_probe_map(struct map_info *map, struct mtd_info *mtd);
653 +
654 +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
655 +       size_t *retlen, u_char *buf);
656 +static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
657 +       size_t *retlen, const u_char *buf);
658 +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
659 +static void sharp_sync(struct mtd_info *mtd);
660 +static int sharp_suspend(struct mtd_info *mtd);
661 +static void sharp_resume(struct mtd_info *mtd);
662 +static void sharp_destroy(struct mtd_info *mtd);
663 +
664 +static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
665 +       unsigned long adr, __u32 datum);
666 +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
667 +       unsigned long adr);
668 +#ifdef AUTOUNLOCK
669 +static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
670 +       unsigned long adr);
671 +#endif
672 +
673 +
674 +struct sharp_info{
675 +       struct flchip *chip;
676 +       int bogus;
677 +       int chipshift;
678 +       int numchips;
679 +       struct flchip chips[1];
680 +};
681 +
682 +static void sharp_destroy(struct mtd_info *mtd);
683 +
684 +static struct mtd_chip_driver sharp_chipdrv = {
685 +       .probe          = sharp_probe,
686 +       .destroy        = sharp_destroy,
687 +       .name           = "sharp",
688 +       .module         = THIS_MODULE
689 +};
690 +
691 +static void sharp_udelay(unsigned long i) {
692 +       if (in_interrupt()) {
693 +               udelay(i);
694 +       } else {
695 +               schedule();
696 +       }
697 +}
698 +
699 +static struct mtd_info *sharp_probe(struct map_info *map)
700 +{
701 +       struct mtd_info *mtd = NULL;
702 +       struct sharp_info *sharp = NULL;
703 +       int width;
704 +
705 +       mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
706 +       if(!mtd)
707 +               return NULL;
708 +
709 +       sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
710 +       if(!sharp) {
711 +               kfree(mtd);
712 +               return NULL;
713 +       }
714 +
715 +       width = sharp_probe_map(map,mtd);
716 +       if(!width){
717 +               kfree(mtd);
718 +               kfree(sharp);
719 +               return NULL;
720 +       }
721 +
722 +       mtd->priv = map;
723 +       mtd->type = MTD_NORFLASH;
724 +       mtd->erase = sharp_erase;
725 +       mtd->read = sharp_read;
726 +       mtd->write = sharp_write;
727 +       mtd->sync = sharp_sync;
728 +       mtd->suspend = sharp_suspend;
729 +       mtd->resume = sharp_resume;
730 +       mtd->flags = MTD_CAP_NORFLASH;
731 +       mtd->writesize = 1;
732 +       mtd->name = map->name;
733 +
734 +       sharp->chipshift = 24;
735 +       sharp->numchips = 1;
736 +       sharp->chips[0].start = 0;
737 +       sharp->chips[0].state = FL_READY;
738 +       sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
739 +       sharp->chips[0].word_write_time = 0;
740 +       init_waitqueue_head(&sharp->chips[0].wq);
741 +       spin_lock_init(&sharp->chips[0]._spinlock);
742 +
743 +       map->fldrv = &sharp_chipdrv;
744 +       map->fldrv_priv = sharp;
745 +
746 +       __module_get(THIS_MODULE);
747 +       return mtd;
748 +}
749 +
750 +static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
751 +{
752 +       map_word map_cmd;
753 +       map_cmd.x[0] = cmd;
754 +       map_write(map, map_cmd, adr);
755 +}
756 +
757 +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
758 +{
759 +       map_word tmp, read0, read4;
760 +       unsigned long base = 0;
761 +       int width = 4;
762 +
763 +       tmp = map_read(map, base+0);
764 +
765 +       sharp_send_cmd(map, CMD_READ_ID, base+0);
766 +
767 +       read0 = map_read(map, base+0);
768 +       read4 = map_read(map, base+4);
769 +       if (read0.x[0] == 0x00b000b0) {
770 +               printk("Sharp chip, %lx, %lx, width = %d\n", read0.x[0], read4.x[0], width);
771 +               /* Prints b000b0, b000b0, width = 4 on collie */
772 +               switch(read4.x[0]){
773 +               case 0xaaaaaaaa:
774 +               case 0xa0a0a0a0:
775 +                       /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
776 +                       /* a0 - LH28F016SCT-Z4  2Mx8, 32 64k blocks*/
777 +                       mtd->erasesize = 0x10000 * width;
778 +                       mtd->size = 0x200000 * width;
779 +                       return width;
780 +               case 0xa6a6a6a6:
781 +                       /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
782 +                       /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
783 +                       mtd->erasesize = 0x10000 * width;
784 +                       mtd->size = 0x100000 * width;
785 +                       return width;
786 +               case 0x00b000b0:
787 +                       /* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
788 +                       mtd->erasesize = 0x10000 * width / 2;
789 +                       mtd->size = 0x800000 * width / 2;
790 +                       return width;
791 +               default:
792 +                       printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
793 +                               read0.x[0], read4.x[0]);
794 +               }
795 +       } else if ((map_read(map, base+0).x[0] == CMD_READ_ID)){
796 +               /* RAM, probably */
797 +               printk("Looks like RAM\n");
798 +               map_write(map, tmp, base+0);
799 +       }else{
800 +               printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
801 +                       read0.x[0], read4.x[0]);
802 +       }
803 +
804 +       return 0;
805 +}
806 +
807 +/* This function returns with the chip->mutex lock held. */
808 +static int sharp_wait(struct map_info *map, struct flchip *chip)
809 +{
810 +       map_word status;
811 +       unsigned long timeo = jiffies + HZ;
812 +       DECLARE_WAITQUEUE(wait, current);
813 +       int adr = 0;
814 +
815 +retry:
816 +       spin_lock_bh(chip->mutex);
817 +
818 +       switch (chip->state) {
819 +       case FL_READY:
820 +               sharp_send_cmd(map, CMD_READ_STATUS, adr);
821 +               chip->state = FL_STATUS;
822 +       case FL_STATUS:
823 +               status = map_read(map, adr);
824 +               if ((status.x[0] & SR_READY) == SR_READY)
825 +                       break;
826 +               spin_unlock_bh(chip->mutex);
827 +               if (time_after(jiffies, timeo)) {
828 +                       printk("Waiting for chip to be ready timed out in erase\n");
829 +                       return -EIO;
830 +               }
831 +               sharp_udelay(1);
832 +               goto retry;
833 +       default:
834 +               set_current_state(TASK_INTERRUPTIBLE);
835 +               add_wait_queue(&chip->wq, &wait);
836 +
837 +               spin_unlock_bh(chip->mutex);
838 +
839 +               sharp_udelay(1);
840 +
841 +               set_current_state(TASK_RUNNING);
842 +               remove_wait_queue(&chip->wq, &wait);
843 +
844 +               if(signal_pending(current))
845 +                       return -EINTR;
846 +
847 +               timeo = jiffies + HZ;
848 +
849 +               goto retry;
850 +       }
851 +
852 +       sharp_send_cmd(map, CMD_RESET, adr);
853 +
854 +       chip->state = FL_READY;
855 +
856 +       return 0;
857 +}
858 +
859 +static void sharp_release(struct flchip *chip)
860 +{
861 +       wake_up(&chip->wq);
862 +       spin_unlock_bh(chip->mutex);
863 +}
864 +
865 +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
866 +       size_t *retlen, u_char *buf)
867 +{
868 +       struct map_info *map = mtd->priv;
869 +       struct sharp_info *sharp = map->fldrv_priv;
870 +       int chipnum;
871 +       int ret = 0;
872 +       int ofs = 0;
873 +
874 +       chipnum = (from >> sharp->chipshift);
875 +       ofs = from & ((1 << sharp->chipshift)-1);
876 +
877 +       *retlen = 0;
878 +
879 +       while(len){
880 +               unsigned long thislen;
881 +
882 +               if(chipnum>=sharp->numchips)
883 +                       break;
884 +
885 +               thislen = len;
886 +               if(ofs+thislen >= (1<<sharp->chipshift))
887 +                       thislen = (1<<sharp->chipshift) - ofs;
888 +
889 +               ret = sharp_wait(map,&sharp->chips[chipnum]);
890 +               if(ret<0)
891 +                       break;
892 +
893 +               map_copy_from(map,buf,ofs,thislen);
894 +
895 +               sharp_release(&sharp->chips[chipnum]);
896 +
897 +               *retlen += thislen;
898 +               len -= thislen;
899 +               buf += thislen;
900 +
901 +               ofs = 0;
902 +               chipnum++;
903 +       }
904 +       return ret;
905 +}
906 +
907 +static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
908 +       size_t *retlen, const u_char *buf)
909 +{
910 +       struct map_info *map = mtd->priv;
911 +       struct sharp_info *sharp = map->fldrv_priv;
912 +       int ret = 0;
913 +       int i,j;
914 +       int chipnum;
915 +       unsigned long ofs;
916 +       union { u32 l; unsigned char uc[4]; } tbuf;
917 +
918 +       *retlen = 0;
919 +
920 +       while(len){
921 +               tbuf.l = 0xffffffff;
922 +               chipnum = to >> sharp->chipshift;
923 +               ofs = to & ((1<<sharp->chipshift)-1);
924 +
925 +               j=0;
926 +               for(i=ofs&3;i<4 && len;i++){
927 +                       tbuf.uc[i] = *buf;
928 +                       buf++;
929 +                       to++;
930 +                       len--;
931 +                       j++;
932 +               }
933 +               sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
934 +               if(ret<0)
935 +                       return ret;
936 +               (*retlen)+=j;
937 +       }
938 +
939 +       return 0;
940 +}
941 +
942 +static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
943 +       unsigned long adr, __u32 datum)
944 +{
945 +       int ret;
946 +       int try;
947 +       int i;
948 +       map_word data, status;
949 +
950 +       status.x[0] = 0;
951 +       ret = sharp_wait(map,chip);
952 +       if (ret < 0)
953 +               return ret;
954 +
955 +       for (try=0; try<10; try++) {
956 +               long timeo;
957 +
958 +               sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
959 +               /* cpu_to_le32 -> hack to fix the writel be->le conversion */
960 +               data.x[0] = cpu_to_le32(datum);
961 +               map_write(map, data, adr);
962 +
963 +               chip->state = FL_WRITING;
964 +               timeo = jiffies + (HZ/2);
965 +
966 +               sharp_send_cmd(map, CMD_READ_STATUS, adr);
967 +               for(i=0;i<100;i++){
968 +                       status = map_read(map, adr);
969 +                       if((status.x[0] & SR_READY) == SR_READY)
970 +                               break;
971 +               }
972 +#ifdef AUTOUNLOCK
973 +               if (status.x[0] & SR_PROTECT) { /* lock block */
974 +                       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
975 +                       sharp_unlock_oneblock(map,chip,adr);
976 +                       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
977 +                       sharp_send_cmd(map, CMD_RESET, adr);
978 +                       continue;
979 +               }
980 +#endif
981 +               if(i==100){
982 +                       printk("sharp: timed out writing\n");
983 +               }
984 +
985 +               if (!(status.x[0] & SR_ERRORS))
986 +                       break;
987 +
988 +               printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
989 +
990 +               sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
991 +       }
992 +       sharp_send_cmd(map, CMD_RESET, adr);
993 +       chip->state = FL_READY;
994 +
995 +       sharp_release(chip);
996 +
997 +       return 0;
998 +}
999 +
1000 +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
1001 +{
1002 +       struct map_info *map = mtd->priv;
1003 +       struct sharp_info *sharp = map->fldrv_priv;
1004 +       unsigned long adr,len;
1005 +       int chipnum, ret=0;
1006 +
1007 +       if(instr->addr & (mtd->erasesize - 1))
1008 +               return -EINVAL;
1009 +       if(instr->len & (mtd->erasesize - 1))
1010 +               return -EINVAL;
1011 +       if(instr->len + instr->addr > mtd->size)
1012 +               return -EINVAL;
1013 +
1014 +       chipnum = instr->addr >> sharp->chipshift;
1015 +       adr = instr->addr & ((1<<sharp->chipshift)-1);
1016 +       len = instr->len;
1017 +
1018 +       while(len){
1019 +               ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
1020 +               if(ret)return ret;
1021 +
1022 +               if (adr >= 0xfe0000) {
1023 +                       adr += mtd->erasesize / 8;
1024 +                       len -= mtd->erasesize / 8;
1025 +               } else {
1026 +                       adr += mtd->erasesize;
1027 +                       len -= mtd->erasesize;
1028 +               }
1029 +               if(adr >> sharp->chipshift){
1030 +                       adr = 0;
1031 +                       chipnum++;
1032 +                       if(chipnum>=sharp->numchips)
1033 +                               break;
1034 +               }
1035 +       }
1036 +
1037 +       instr->state = MTD_ERASE_DONE;
1038 +       mtd_erase_callback(instr);
1039 +
1040 +       return 0;
1041 +}
1042 +
1043 +static inline int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
1044 +       unsigned long adr)
1045 +{
1046 +       int ret;
1047 +       unsigned long timeo;
1048 +       map_word status;
1049 +       DECLARE_WAITQUEUE(wait, current);
1050 +
1051 +       sharp_send_cmd(map, CMD_READ_STATUS, adr);
1052 +       status = map_read(map, adr);
1053 +
1054 +       timeo = jiffies + HZ * 10;
1055 +
1056 +       while (time_before(jiffies, timeo)) {
1057 +               sharp_send_cmd(map, CMD_READ_STATUS, adr);
1058 +               status = map_read(map, adr);
1059 +               if ((status.x[0] & SR_READY) == SR_READY) {
1060 +                       ret = 0;
1061 +                       goto out;
1062 +               }
1063 +               set_current_state(TASK_INTERRUPTIBLE);
1064 +               add_wait_queue(&chip->wq, &wait);
1065 +
1066 +               spin_unlock_bh(chip->mutex);
1067 +
1068 +               schedule_timeout(1);
1069 +               schedule();
1070 +
1071 +               spin_lock_bh(chip->mutex);
1072 +
1073 +               remove_wait_queue(&chip->wq, &wait);
1074 +               set_current_state(TASK_RUNNING);
1075 +       }
1076 +       ret = -ETIME;
1077 +out:
1078 +       return ret;
1079 +}
1080 +
1081 +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
1082 +       unsigned long adr)
1083 +{
1084 +       int ret;
1085 +       map_word status;
1086 +
1087 +       ret = sharp_wait(map,chip);
1088 +       if (ret < 0)
1089 +               return ret;
1090 +
1091 +#ifdef AUTOUNLOCK
1092 +       /* This seems like a good place to do an unlock */
1093 +       sharp_unlock_oneblock(map,chip,adr);
1094 +#endif
1095 +
1096 +       sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
1097 +       sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
1098 +
1099 +       chip->state = FL_ERASING;
1100 +
1101 +       ret = sharp_do_wait_for_ready(map,chip,adr);
1102 +       if(ret<0) {
1103 +               spin_unlock_bh(chip->mutex);
1104 +               return ret;
1105 +       }
1106 +
1107 +       sharp_send_cmd(map, CMD_READ_STATUS, adr);
1108 +       status = map_read(map, adr);
1109 +
1110 +       if (!(status.x[0] & SR_ERRORS)) {
1111 +               sharp_send_cmd(map, CMD_RESET, adr);
1112 +               chip->state = FL_READY;
1113 +               spin_unlock_bh(chip->mutex);
1114 +               return 0;
1115 +       }
1116 +
1117 +       printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
1118 +       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
1119 +
1120 +       sharp_release(chip);
1121 +
1122 +       return -EIO;
1123 +}
1124 +
1125 +#ifdef AUTOUNLOCK
1126 +static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
1127 +       unsigned long adr)
1128 +{
1129 +       map_word status;
1130 +
1131 +       sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr & BLOCK_MASK);
1132 +       sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr & BLOCK_MASK);
1133 +
1134 +       sharp_do_wait_for_ready(map,chip,adr);
1135 +
1136 +       status = map_read(map, adr);
1137 +
1138 +       if (!(status.x[0] & SR_ERRORS)) {
1139 +               sharp_send_cmd(map, CMD_RESET, adr);
1140 +               chip->state = FL_READY;
1141 +               return;
1142 +       }
1143 +
1144 +       printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
1145 +       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
1146 +}
1147 +#endif
1148 +
1149 +static void sharp_sync(struct mtd_info *mtd)
1150 +{
1151 +}
1152 +
1153 +static int sharp_suspend(struct mtd_info *mtd)
1154 +{
1155 +       struct map_info *map = mtd->priv;
1156 +       struct sharp_info *sharp = map->fldrv_priv;
1157 +       int i;
1158 +       struct flchip *chip;
1159 +       int ret = 0;
1160 +
1161 +       for (i = 0; !ret && i < sharp->numchips; i++) {
1162 +               chip = &sharp->chips[i];
1163 +               ret = sharp_wait(map,chip);
1164 +
1165 +               if (ret) {
1166 +                       ret = -EAGAIN;
1167 +               } else {
1168 +                       chip->state = FL_PM_SUSPENDED;
1169 +                       spin_unlock_bh(chip->mutex);
1170 +               }
1171 +       }
1172 +       return ret;
1173 +}
1174 +
1175 +static void sharp_resume(struct mtd_info *mtd)
1176 +{
1177 +       struct map_info *map = mtd->priv;
1178 +       struct sharp_info *sharp = map->fldrv_priv;
1179 +       int i;
1180 +       struct flchip *chip;
1181 +
1182 +       for (i = 0; i < sharp->numchips; i++) {
1183 +               chip = &sharp->chips[i];
1184 +
1185 +               spin_lock_bh(chip->mutex);
1186 +
1187 +               if (chip->state == FL_PM_SUSPENDED) {
1188 +                       /* We need to force it back to a known state */
1189 +                       sharp_send_cmd(map, CMD_RESET, chip->start);
1190 +                       chip->state = FL_READY;
1191 +                       wake_up(&chip->wq);
1192 +               }
1193 +
1194 +               spin_unlock_bh(chip->mutex);
1195 +       }
1196 +}
1197 +
1198 +static void sharp_destroy(struct mtd_info *mtd)
1199 +{
1200 +       struct map_info *map = mtd->priv;
1201 +       struct sharp_info *sharp = map->fldrv_priv;
1202 +
1203 +       kfree(sharp);
1204 +}
1205 +
1206 +static int __init sharp_probe_init(void)
1207 +{
1208 +       printk("MTD Sharp chip driver <ds@lineo.com>\n");
1209 +
1210 +       register_mtd_chip_driver(&sharp_chipdrv);
1211 +
1212 +       return 0;
1213 +}
1214 +
1215 +static void __exit sharp_probe_exit(void)
1216 +{
1217 +       unregister_mtd_chip_driver(&sharp_chipdrv);
1218 +}
1219 +
1220 +module_init(sharp_probe_init);
1221 +module_exit(sharp_probe_exit);
1222 +
1223 +
1224 +MODULE_LICENSE("GPL");
1225 +MODULE_AUTHOR("David Schleef <ds@schleef.org>");
1226 +MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");
1227 Index: linux-2.6.26/drivers/mtd/maps/Kconfig
1228 ===================================================================
1229 --- linux-2.6.26.orig/drivers/mtd/maps/Kconfig  2008-07-13 23:51:29.000000000 +0200
1230 +++ linux-2.6.26/drivers/mtd/maps/Kconfig       2008-10-17 18:15:31.431789839 +0200
1231 @@ -392,7 +392,7 @@
1232  
1233  config MTD_SA1100
1234         tristate "CFI Flash device mapped on StrongARM SA11x0"
1235 -       depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
1236 +       depends on (MTD_CFI || MTD_SHARP) && ARCH_SA1100 && MTD_PARTITIONS
1237         help
1238           This enables access to the flash chips on most platforms based on
1239           the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
1240 Index: linux-2.6.26/drivers/mtd/maps/sa1100-flash.c
1241 ===================================================================
1242 --- linux-2.6.26.orig/drivers/mtd/maps/sa1100-flash.c   2008-07-13 23:51:29.000000000 +0200
1243 +++ linux-2.6.26/drivers/mtd/maps/sa1100-flash.c        2008-10-17 18:15:31.431789839 +0200
1244 @@ -210,6 +210,12 @@
1245                 goto err;
1246         }
1247         subdev->mtd->owner = THIS_MODULE;
1248 +       
1249 +#ifdef CONFIG_SA1100_COLLIE
1250 +       /* collie flash starts locked */
1251 +//      if (subdev->mtd->unlock)
1252 +//              subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size - 0xc0000);
1253 +#endif
1254  
1255         printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
1256                 "%d-bit\n", phys, subdev->mtd->size >> 20,
1257 Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_cs.c
1258 ===================================================================
1259 --- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_cs.c   2008-07-13 23:51:29.000000000 +0200
1260 +++ linux-2.6.26/drivers/net/wireless/hostap/hostap_cs.c        2008-10-17 18:15:31.435790279 +0200
1261 @@ -35,7 +35,7 @@
1262  module_param(ignore_cis_vcc, int, 0444);
1263  MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
1264  
1265 -
1266 +int activar=0;
1267  /* struct local_info::hw_priv */
1268  struct hostap_cs_priv {
1269         dev_node_t node;
1270 @@ -499,11 +499,13 @@
1271  
1272         PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
1273         p_dev->conf.IntType = INT_MEMORY_AND_IO;
1274 -
1275 +       
1276 +       activar=0;
1277         ret = prism2_config(p_dev);
1278         if (ret) {
1279                 PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
1280         }
1281 +       activar=1;
1282  
1283         return ret;
1284  }
1285 Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_hw.c
1286 ===================================================================
1287 --- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_hw.c   2008-10-17 18:13:21.000000000 +0200
1288 +++ linux-2.6.26/drivers/net/wireless/hostap/hostap_hw.c        2008-10-17 18:15:31.443789719 +0200
1289 @@ -54,6 +54,7 @@
1290  #include "hostap.h"
1291  #include "hostap_ap.h"
1292  
1293 +extern int activar;
1294  
1295  /* #define final_version */
1296  
1297 @@ -1534,6 +1535,8 @@
1298         if (local->hw_downloading)
1299                 return 1;
1300  
1301 +       activar=1;
1302 +
1303         if (prism2_hw_init(dev, initial)) {
1304                 return local->no_pri ? 0 : 1;
1305         }
1306 @@ -2665,8 +2668,15 @@
1307         int events = 0;
1308         u16 ev;
1309  
1310 -       iface = netdev_priv(dev);
1311 -       local = iface->local;
1312 +
1313 +       // Todos los parametros de entrada son correctos (no son nulos). De momento esta es la unica forma que conozco de detectar el problema.
1314 +       if (!activar) {
1315 +               printk("hostap_hw.c: INTERRUPT BEFORE DEVICE INIT!\n");
1316 +               return IRQ_HANDLED;
1317 +       }
1318 +
1319 +       iface = netdev_priv(dev);
1320 +       local = iface->local;
1321  
1322         if(dev->base_addr == 0)
1323         {
1324 Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_pci.c
1325 ===================================================================
1326 --- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_pci.c  2008-10-17 18:13:18.000000000 +0200
1327 +++ linux-2.6.26/drivers/net/wireless/hostap/hostap_pci.c       2008-10-17 18:15:31.447790279 +0200
1328 @@ -19,6 +19,7 @@
1329  
1330  #include "hostap_wlan.h"
1331  
1332 +int activar=1;
1333  
1334  static char *dev_info = "hostap_pci";
1335  
1336 Index: linux-2.6.26/drivers/net/wireless/hostap/hostap_plx.c
1337 ===================================================================
1338 --- linux-2.6.26.orig/drivers/net/wireless/hostap/hostap_plx.c  2008-10-17 18:13:18.000000000 +0200
1339 +++ linux-2.6.26/drivers/net/wireless/hostap/hostap_plx.c       2008-10-17 18:15:31.451790719 +0200
1340 @@ -21,7 +21,7 @@
1341  #include <asm/io.h>
1342  
1343  #include "hostap_wlan.h"
1344 -
1345 +int activar=1;
1346  
1347  static char *dev_info = "hostap_plx";
1348  
1349 Index: linux-2.6.26/drivers/pcmcia/sa1100_generic.c
1350 ===================================================================
1351 --- linux-2.6.26.orig/drivers/pcmcia/sa1100_generic.c   2008-07-13 23:51:29.000000000 +0200
1352 +++ linux-2.6.26/drivers/pcmcia/sa1100_generic.c        2008-10-17 18:15:31.459789719 +0200
1353 @@ -81,13 +81,14 @@
1354         return ret;
1355  }
1356  
1357 -static struct device_driver sa11x0_pcmcia_driver = {
1358 -       .probe          = sa11x0_drv_pcmcia_probe,
1359 -       .remove         = soc_common_drv_pcmcia_remove,
1360 -       .name           = "sa11x0-pcmcia",
1361 -       .bus            = &platform_bus_type,
1362 -       .suspend        = pcmcia_socket_dev_suspend,
1363 -       .resume         = pcmcia_socket_dev_resume,
1364 +static struct platform_driver sa11x0_pcmcia_driver = {
1365 +       .driver         = {
1366 +               .name   = "sa11x0-pcmcia",
1367 +               .probe  = sa11x0_drv_pcmcia_probe,
1368 +               .remove = soc_common_drv_pcmcia_remove,
1369 +               .suspend= pcmcia_socket_dev_suspend,
1370 +               .resume = pcmcia_socket_dev_resume,
1371 +       },
1372  };
1373  
1374  /* sa11x0_pcmcia_init()
1375 @@ -100,7 +101,7 @@
1376   */
1377  static int __init sa11x0_pcmcia_init(void)
1378  {
1379 -       return driver_register(&sa11x0_pcmcia_driver);
1380 +       return platform_driver_register(&sa11x0_pcmcia_driver);
1381  }
1382  
1383  /* sa11x0_pcmcia_exit()
1384 @@ -110,7 +111,7 @@
1385   */
1386  static void __exit sa11x0_pcmcia_exit(void)
1387  {
1388 -       driver_unregister(&sa11x0_pcmcia_driver);
1389 +       platform_driver_unregister(&sa11x0_pcmcia_driver);
1390  }
1391  
1392  MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
1393 Index: linux-2.6.26/drivers/spi/Kconfig
1394 ===================================================================
1395 --- linux-2.6.26.orig/drivers/spi/Kconfig       2008-07-13 23:51:29.000000000 +0200
1396 +++ linux-2.6.26/drivers/spi/Kconfig    2008-10-17 18:15:31.463790519 +0200
1397 @@ -123,6 +123,10 @@
1398           This enables using the Freescale MPC52xx Programmable Serial
1399           Controller in master SPI mode.
1400  
1401 +config SPI_LOCOMO
1402 +       tristate "Locomo SPI master"
1403 +       depends on SPI_MASTER && SHARP_LOCOMO && EXPERIMENTAL
1404 +
1405  config SPI_MPC83xx
1406         tristate "Freescale MPC83xx/QUICC Engine SPI controller"
1407         depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
1408 Index: linux-2.6.26/drivers/spi/Makefile
1409 ===================================================================
1410 --- linux-2.6.26.orig/drivers/spi/Makefile      2008-07-13 23:51:29.000000000 +0200
1411 +++ linux-2.6.26/drivers/spi/Makefile   2008-10-17 18:15:31.463790519 +0200
1412 @@ -28,6 +28,7 @@
1413  obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
1414  obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
1415  obj-$(CONFIG_SPI_SH_SCI)               += spi_sh_sci.o
1416 +obj-$(CONFIG_SPI_LOCOMO)                += locomo_spi.o
1417  #      ... add above this line ...
1418  
1419  # SPI protocol drivers (device/link on bus)
1420 Index: linux-2.6.26/drivers/spi/locomo_spi.c
1421 ===================================================================
1422 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1423 +++ linux-2.6.26/drivers/spi/locomo_spi.c       2008-10-17 18:15:31.471790439 +0200
1424 @@ -0,0 +1,1097 @@
1425 +#include <asm/io.h>
1426 +#include <asm/irq.h>
1427 +#include <linux/module.h>
1428 +#include <linux/init.h>
1429 +#include <linux/device.h>
1430 +#include <linux/stat.h>
1431 +#include <linux/delay.h>
1432 +#include <linux/wait.h>
1433 +#include <linux/interrupt.h>
1434 +#include <asm/hardware/locomo.h>
1435 +#include <asm/errno.h>
1436 +#include <linux/mmc/host.h>
1437 +#include <linux/spi/spi.h>
1438 +#include <linux/spi/mmc_spi.h>
1439 +#include <linux/workqueue.h>
1440 +#include <linux/spinlock.h>
1441 +#include <linux/list.h>
1442 +#include "locomo_spi.h"
1443 +static struct locomospi_dev * spidev;
1444 +static struct work_struct transfer_wq;
1445 +int  delay;
1446 +
1447 +char* transtxbuf=(char*)NULL;
1448 +char* transrxbuf=(char*)NULL;
1449 +int transfercount=0, transfersize=0;
1450 +static DECLARE_WAIT_QUEUE_HEAD(transferqueue);
1451 +/* MMC_SPI functions *********************************************************/
1452 +
1453 +static int locomommcspi_init(struct device *dev, irqreturn_t (*isr)(int, void*), void *mmc)
1454 +{
1455 +       int result;
1456 +       result=request_irq(IRQ_LOCOMO_CARDDETECT, isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "locomo-spi",  mmc);
1457 +       return result;
1458 +}
1459 +
1460 +static void locomommcspi_exit(struct device *dev, void* mmc)
1461 +{
1462 +       free_irq(IRQ_LOCOMO_CARDDETECT, mmc);
1463 +}
1464 +
1465 +static int locomommcspi_getro(struct device *dev)
1466 +{
1467 +       return locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT) > 0 ? 1 : 0;
1468 +}
1469 +
1470 +static void locomommcspi_setpower(struct device *dev, unsigned int mask)
1471 +{
1472 +       if(!mask && spidev->card_power)
1473 +               locomospi_power(0);
1474 +       else if( !spidev->card_power )
1475 +               locomospi_power(1);
1476 +
1477 +}
1478 +
1479 +
1480 +static struct mmc_spi_platform_data colliemmc ={
1481 +       .init           = locomommcspi_init,
1482 +       .exit           = locomommcspi_exit,
1483 +       .detect_delay   = 200,
1484 +       .get_ro         = locomommcspi_getro,
1485 +       .ocr_mask       = MMC_VDD_32_33 | MMC_VDD_33_34,
1486 +       .setpower       = locomommcspi_setpower,
1487 +       .powerup_msecs  = 200,
1488 +};
1489 +
1490 +/* Utility function **********************************************************/
1491 +
1492 +static void locomospi_power(int on)
1493 +{
1494 +       locomo_gpio_write(spidev->ldev->dev.parent, LOCOMO_GPIO_CARD_POWER, on);
1495 +       spidev->card_power=on;
1496 +       printk(KERN_DEBUG "locomospi: power %d\n",on);
1497 +}
1498 +
1499 +static void locomospi_setclock(unsigned int div, unsigned int clock)
1500 +{
1501 +       u16 r = ioread16(spidev->base+LOCOMO_SPIMD);
1502 +       div &= 0x7;
1503 +       clock &= 0x3;
1504 +       if(clock != spidev->clock_base || div != spidev->clock_div){
1505 +               r &= ~(LOCOMO_SPI_XSEL  | LOCOMO_SPI_CLKSEL | LOCOMO_SPI_XEN);
1506 +               iowrite16(r,spidev->base+LOCOMO_SPIMD);
1507 +               r |=  (div | (clock <<3) | LOCOMO_SPI_XEN);
1508 +               iowrite16(r,spidev->base+LOCOMO_SPIMD);
1509 +               spidev->clock_div = div;
1510 +               spidev->clock_base = clock;
1511 +               udelay(300);
1512 +       }
1513 +
1514 +}
1515 +// returns 1 if card ist present, 0 otherwise
1516 +static int locomospi_carddetect()
1517 +{
1518 +       return (locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1;
1519 +}
1520 +
1521 +static void locomospi_setcs(int high)
1522 +{
1523 +       u16 r;
1524 +       printk(KERN_DEBUG "locomospi: cs %d\n",high);
1525 +       r = ioread16(spidev->base + LOCOMO_SPICT);
1526 +       if(high)
1527 +               r |= LOCOMO_SPI_CS;
1528 +       else
1529 +               r &= ~LOCOMO_SPI_CS;
1530 +       iowrite16(r, spidev->base + LOCOMO_SPICT);
1531 +}
1532 +
1533 +static void locomospi_reg_open()
1534 +{
1535 +       u16 r;
1536 +       spidev->clock_div = DIV_64;
1537 +       spidev->clock_base = CLOCK_18MHZ;
1538 +       locomospi_power(1);
1539 +       msleep(100);
1540 +//     iowrite16( 0xec00 | (CLOCK_18MHZ <<3)|DIV_64, spidev->base+LOCOMO_SPIMD);
1541 +       iowrite16( LOCOMO_SPI_MSB1ST | LOCOMO_SPI_DOSTAT | LOCOMO_SPI_RCPOL | LOCOMO_SPI_TCPOL 
1542 +                       |(CLOCK_18MHZ <<3) | DIV_64, spidev->base+LOCOMO_SPIMD);
1543 +//     if(locomospi_carddetect()){
1544 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1545 +               r |= LOCOMO_SPI_XON;
1546 +               iowrite16( r, spidev->base+LOCOMO_SPIMD);
1547 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1548 +               r |= LOCOMO_SPI_XEN;
1549 +               iowrite16( r, spidev->base+LOCOMO_SPIMD);
1550 +//     }
1551 +       iowrite16( LOCOMO_SPI_CS, spidev->base+LOCOMO_SPICT);
1552 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1553 +       r |= (LOCOMO_SPI_CEN | LOCOMO_SPI_RXUEN | LOCOMO_SPI_ALIGNEN);
1554 +       iowrite16( r, spidev->base+LOCOMO_SPICT);
1555 +       udelay(200);
1556 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1557 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1558 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1559 +       r &= ~LOCOMO_SPI_CS;
1560 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1561 +}
1562 +
1563 +static void locomospi_reg_release()
1564 +{
1565 +       u16 r;
1566 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1567 +       r &= ~LOCOMO_SPI_CEN;
1568 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1569 +       r = ioread16(spidev->base+LOCOMO_SPIMD);
1570 +       r &= ~LOCOMO_SPI_XEN;
1571 +       iowrite16(r, spidev->base+LOCOMO_SPIMD);
1572 +       r = ioread16(spidev->base+LOCOMO_SPIMD);
1573 +       r &= ~LOCOMO_SPI_XON;
1574 +       iowrite16(r, spidev->base+LOCOMO_SPIMD);
1575 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1576 +       r |= LOCOMO_SPI_XEN;
1577 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1578 +       locomospi_power(0);
1579 +}
1580 +#if 0
1581 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
1582 +{
1583 +       u16 r = ioread16(spidev->base+LOCOMO_SPICT);
1584 +       r |= LOCOMO_SPI_ALIGNEN;
1585 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1586 +       printk(KERN_DEBUG "locomospi: %d bytes to prozess\n",size);
1587 +       /* initialize global vars for isr */
1588 +       transfercount=0; transfersize=size; 
1589 +       transtxbuf=txbuffer; transrxbuf=rxbuffer;
1590 +
1591 +       /* start transmit and go sleep  isr will wake us*/
1592 +       enable_irq(IRQ_LOCOMO_SPI_TEND);
1593 +       iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD);
1594 +       wait_event(transferqueue, transfercount >= transfersize);
1595 +       disable_irq(IRQ_LOCOMO_SPI_TEND);
1596 +       transrxbuf=NULL; transtxbuf=NULL;
1597 +       
1598 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1599 +       r &= ~LOCOMO_SPI_ALIGNEN;
1600 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1601 +       int i;
1602 +       for(i=0; i< size; i++)
1603 +               printk(KERN_DEBUG "locomospi: sent: %x  received: %x \n",txbuffer[i], rxbuffer[i]);
1604 +       
1605 +       
1606 +       return size;
1607 +}
1608 +
1609 +
1610 +static int tx(const char* txbuffer, int size)
1611 +{
1612 +       printk(KERN_DEBUG "locomospi: %d bytes to send\n",size);
1613 +       /* initialize global vars for isr */
1614 +       transfercount=0; transfersize=size; 
1615 +       transtxbuf=txbuffer; 
1616 +
1617 +       /* start transmit and go sleep  isr will wake us*/
1618 +       enable_irq(IRQ_LOCOMO_SPI_RFW);
1619 +       iowrite8(txbuffer[0], spidev->base+LOCOMO_SPITD);
1620 +       wait_event(transferqueue, transfercount >= transfersize);
1621 +       disable_irq(IRQ_LOCOMO_SPI_RFW);
1622 +       transtxbuf=NULL;
1623 +       
1624 +       int i;
1625 +       for(i=0; i< size; i++)
1626 +               printk(KERN_DEBUG "locomospi: sent: %x\n",txbuffer[i]);
1627 +       
1628 +       
1629 +       return size;
1630 +}
1631 +
1632 +static int rx(char* rxbuffer, int size)
1633 +{
1634 +       printk(KERN_DEBUG "locomospi: %d bytes to read\n",size);
1635 +       /* initialize global vars for isr */
1636 +       transfercount=0; transfersize=size; 
1637 +       transrxbuf=rxbuffer;
1638 +
1639 +       /* start transmit and go sleep  isr will wake us*/
1640 +       enable_irq(IRQ_LOCOMO_SPI_RFR);
1641 +       rxbuffer[0]=ioread8(spidev->base+LOCOMO_SPIRD);
1642 +       wait_event(transferqueue, transfercount >= transfersize);
1643 +       disable_irq(IRQ_LOCOMO_SPI_RFR);
1644 +       transrxbuf=NULL;
1645 +       
1646 +       int i;
1647 +       for(i=0; i< size; i++)
1648 +               printk(KERN_DEBUG "locomospi: received: %x \n", rxbuffer[i]);
1649 +       
1650 +       
1651 +       return size;
1652 +}
1653 +
1654 +#else
1655 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
1656 +{
1657 +       int i=0,j=0;
1658 +       int wait;
1659 +       u16 r;
1660 +/*     char * txback = kmalloc(size * sizeof(char), GFP_KERNEL);
1661 +       memcpy(txback, txbuffer, size); 
1662 +*/     
1663 +       if(spidev->clock_div == 4)
1664 +               wait = 0x10000;
1665 +       else
1666 +               wait = 8;
1667 +       
1668 +//     printk(KERN_DEBUG "locomospi: txrx %d bytes to prozess\n",size);
1669 +       
1670 +//     r = ioread16(spidev->base+LOCOMO_SPICT);
1671 +//     r |= LOCOMO_SPI_ALIGNEN;
1672 +//     iowrite16(r, spidev->base+LOCOMO_SPICT);
1673 +       //discard first bogus byte
1674 +
1675 +       ioread8(spidev->base+LOCOMO_SPIRD);
1676 +       for(i=0; i<size; i++){
1677 +               for(j=0; j <= wait; j++){
1678 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)
1679 +                               break;
1680 +               }
1681 +               iowrite8(txbuffer[i], spidev->base+LOCOMO_SPITD);
1682 +               ndelay(delay);
1683 +               
1684 +               for(j=0; j <= wait; j++){
1685 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
1686 +                               break;
1687 +               }
1688 +               rxbuffer[i] = ioread8(spidev->base+LOCOMO_SPIRD);
1689 +               ndelay(delay);
1690 +       }
1691 +//     r = ioread16(spidev->base+LOCOMO_SPICT);
1692 +//     r &= ~LOCOMO_SPI_ALIGNEN;
1693 +//     iowrite16(r, spidev->base+LOCOMO_SPICT);
1694 +       
1695 +/*     for(j=0; j< size; j++)
1696 +               printk(KERN_DEBUG "locomospi: sent: %x  received: %x \n",txback[j], rxbuffer[j]);
1697 +       
1698 +       kfree(txback);  
1699 +*/     return i;
1700 +}
1701 +
1702 +static int tx(const char* buffer, int size)
1703 +{
1704 +       int i=0,j=0;
1705 +       int wait;
1706 +       u16 r;
1707 +       if(spidev->clock_div == 4)
1708 +               wait = 0x10000;
1709 +       else
1710 +               wait = 8;
1711 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1712 +       r &= ~LOCOMO_SPI_ALIGNEN;
1713 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1714 +
1715 +//     printk(KERN_DEBUG "locomospi: tx %d bytes to transmit\n",size);
1716 +       for(i=0; i<size; i++){
1717 +               for(j=0; j <= wait; j++){
1718 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)
1719 +                               break;
1720 +               }
1721 +               iowrite8(buffer[i], spidev->base+LOCOMO_SPITD);
1722 +               ndelay(delay);
1723 +       }
1724 +
1725 +       for(j=0; j <= wait; j++){
1726 +               if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_TEND)
1727 +                       break;
1728 +       }
1729 +       
1730 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1731 +       r |= LOCOMO_SPI_ALIGNEN;
1732 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1733 +       
1734 +//     for(j=0; j< size; j++)
1735 +//             printk(KERN_DEBUG "locomospi: sent: %x \n", buffer[j]);
1736 +//     printk(KERN_DEBUG "locomospi: tx %d bytes transmitted\n",i);
1737 +       return i;
1738 +}
1739 +
1740 +static int rx(char* buffer, int size)
1741 +{
1742 +       int i,j;
1743 +       int wait;
1744 +       u16 r;  
1745 +       printk(KERN_DEBUG "locomospi: rx %d bytes to receive\n",size);
1746 +       if(spidev->clock_div == 4)
1747 +               wait = 0x10000;
1748 +       else
1749 +               wait = 8;
1750 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1751 +       r &= ~LOCOMO_SPI_ALIGNEN;
1752 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1753 +
1754 +       for(i=0; i<size; i++){
1755 +
1756 +               for(j=0; j <= wait; j++){
1757 +                       if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
1758 +                               break;
1759 +               }
1760 +               buffer[i]= ioread8(spidev->base+LOCOMO_SPIRD);
1761 +               ndelay(delay);
1762 +       }
1763 +       
1764 +       r = ioread16(spidev->base+LOCOMO_SPICT);
1765 +       r |= LOCOMO_SPI_ALIGNEN;
1766 +       iowrite16(r, spidev->base+LOCOMO_SPICT);
1767 +       
1768 +       for(j=0; j< size; j++)
1769 +               printk(KERN_DEBUG "locomospi: received: %x \n", buffer[j]);
1770 +       printk(KERN_DEBUG "locomospi: rx %d bytes received\n",i);
1771 +       return i;
1772 +}
1773 +#endif
1774 +/*
1775 +static irqreturn_t locomospi_rwready(int irq, void *dev_id)
1776 +{
1777 +       struct locomospi_dev* dev=(struct locomospi_dev*) dev_id;
1778 +//     dev_dbg(&spidev->sdev->dev, "IRQ: %d\n", irq);
1779 +//     printk(KERN_DEBUG "locomospi: IRQ: %d\n", irq);
1780 +       wake_up_interruptible(&dev->waitqueue);
1781 +       return IRQ_HANDLED;
1782 +}
1783 +*/
1784 +static irqreturn_t locomospi_testisr(int irq, void *dev_id)
1785 +{
1786 +       char *buf="";
1787 +       switch(irq){
1788 +               case IRQ_LOCOMO_SPI_RFR: buf="RFR";
1789 +                                        break;
1790 +               case IRQ_LOCOMO_SPI_RFW: buf="RFW";
1791 +                                        break;
1792 +               case IRQ_LOCOMO_SPI_REND:buf="REND";
1793 +                                        break;
1794 +               case IRQ_LOCOMO_SPI_TEND:buf="TEND";
1795 +                                        break;
1796 +               case IRQ_LOCOMO_CARDDETECT:
1797 +                                        buf="CARD_DETECT";
1798 +                                        break;
1799 +               default:                return IRQ_NONE;
1800 +       }
1801 +       printk(KERN_DEBUG "locomospi: IRQ: %s\n",buf);
1802 +//     dev_dbg(&spidev->sdev->dev, "IRQ: %s\n",buf);
1803 +       return IRQ_HANDLED;
1804 +}
1805 +static irqreturn_t locomospi_txrxisr(int irq, void *dev_id)
1806 +{
1807 +       if(transfercount < transfersize){
1808 +               transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1809 +               iowrite8(transtxbuf[transfercount], spidev->base+LOCOMO_SPITD);                 
1810 +       }
1811 +       else{
1812 +               /* transfer complete. wake up txrx */
1813 +               wake_up(&transferqueue);
1814 +       }
1815 +       return IRQ_HANDLED;     
1816 +}      
1817 +
1818 +static irqreturn_t locomospi_txisr(int irq, void *dev_id)
1819 +{
1820 +       if(transfercount < transfersize){
1821 +               iowrite8(transtxbuf[transfercount++], spidev->base+LOCOMO_SPITD);               
1822 +       }
1823 +       else{
1824 +               /* transfer complete. wake up txrx */
1825 +               wake_up(&transferqueue);
1826 +       }
1827 +       return IRQ_HANDLED;     
1828 +}      
1829 +
1830 +static irqreturn_t locomospi_rxisr(int irq, void *dev_id)
1831 +{
1832 +       if(transfercount < transfersize){
1833 +               transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1834 +       }
1835 +       else{
1836 +               /* transfer complete. wake up txrx */
1837 +               wake_up(&transferqueue);
1838 +       }
1839 +       return IRQ_HANDLED;     
1840 +}      
1841 +
1842 +static void locomospi_clock(unsigned int Hz)
1843 +{
1844 +       u16 r;
1845 +       printk(KERN_DEBUG "locomospi: changing clock to: %d\n", Hz);
1846 +       if(Hz == 0){
1847 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1848 +               r &= ~LOCOMO_SPI_XON;
1849 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1850 +       }
1851 +       else if(Hz >= 24576000){
1852 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1853 +               r |= LOCOMO_SPI_XON;
1854 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1855 +               locomospi_setclock(DIV_1, CLOCK_25MHZ);
1856 +               delay=41;
1857 +       }
1858 +       else if(Hz >= 22579200){
1859 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1860 +               r |= LOCOMO_SPI_XON;
1861 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1862 +               locomospi_setclock(DIV_1, CLOCK_22MHZ);
1863 +               delay=45;
1864 +       }
1865 +       else if(Hz >= 18432000){
1866 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1867 +               r |= LOCOMO_SPI_XON;
1868 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1869 +               locomospi_setclock(DIV_1, CLOCK_18MHZ);
1870 +               delay=55;
1871 +       }
1872 +       else if(Hz >= 12288000){
1873 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1874 +               r |= LOCOMO_SPI_XON;
1875 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1876 +               locomospi_setclock(DIV_2, CLOCK_25MHZ);
1877 +               delay=82;
1878 +       }
1879 +       else if(Hz >= 11289600){
1880 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1881 +               r |= LOCOMO_SPI_XON;
1882 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1883 +               locomospi_setclock(DIV_2, CLOCK_22MHZ);
1884 +               delay=89;
1885 +       }
1886 +       else if(Hz >= 9216000){
1887 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1888 +               r |= LOCOMO_SPI_XON;
1889 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1890 +               locomospi_setclock(DIV_2, CLOCK_18MHZ);
1891 +               delay=110;
1892 +       }
1893 +       else if(Hz >= 6144000){
1894 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1895 +               r |= LOCOMO_SPI_XON;
1896 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1897 +               locomospi_setclock(DIV_4, CLOCK_25MHZ);
1898 +               delay=164;
1899 +       }
1900 +       else if(Hz >= 5644800){
1901 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1902 +               r |= LOCOMO_SPI_XON;
1903 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1904 +               locomospi_setclock(DIV_4, CLOCK_22MHZ);
1905 +               delay=178;
1906 +       }
1907 +       else if(Hz >= 4608000){
1908 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1909 +               r |= LOCOMO_SPI_XON;
1910 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1911 +               locomospi_setclock(DIV_4, CLOCK_18MHZ);
1912 +               delay=218;
1913 +       }
1914 +       else if(Hz >= 3072000){
1915 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1916 +               r |= LOCOMO_SPI_XON;
1917 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1918 +               locomospi_setclock(DIV_8, CLOCK_25MHZ);
1919 +               delay=327;
1920 +       }
1921 +       else if(Hz >= 2822400){
1922 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1923 +               r |= LOCOMO_SPI_XON;
1924 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1925 +               locomospi_setclock(DIV_8, CLOCK_22MHZ);
1926 +               delay=355;
1927 +       }
1928 +       else if(Hz >= 2304000){
1929 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1930 +               r |= LOCOMO_SPI_XON;
1931 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1932 +               locomospi_setclock(DIV_8, CLOCK_18MHZ);
1933 +               delay=435;
1934 +       }
1935 +       else if(Hz >= 384000){
1936 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1937 +               r |= LOCOMO_SPI_XON;
1938 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1939 +               locomospi_setclock(DIV_64, CLOCK_25MHZ);
1940 +               delay=2605;
1941 +       }
1942 +       else if(Hz >= 352800){
1943 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1944 +               r |= LOCOMO_SPI_XON;
1945 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1946 +               locomospi_setclock(DIV_64, CLOCK_22MHZ);
1947 +               delay=2834;
1948 +       }
1949 +       else{ /* set to 288 KHz */
1950 +               r = ioread16(spidev->base+LOCOMO_SPIMD);
1951 +               r |= LOCOMO_SPI_XON;
1952 +               iowrite16(r, spidev->base+LOCOMO_SPIMD);
1953 +               locomospi_setclock(DIV_64, CLOCK_18MHZ);
1954 +               delay=3473;
1955 +       }
1956 +       spidev->clock = Hz;
1957 +}
1958 +
1959 +/* sysfs attributes used for debug *******************************************/
1960 +
1961 +/* SPI registers */
1962 +ssize_t locomospi_showspimd(struct device_driver *drv, char *buf)
1963 +{
1964 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIMD));
1965 +}
1966 +
1967 +ssize_t locomospi_storespimd(struct device_driver *drv, const char *buf, size_t count)
1968 +{
1969 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIMD);
1970 +       return count;
1971 +}
1972 +static DRIVER_ATTR(spimd, S_IWUSR | S_IRUGO, locomospi_showspimd, locomospi_storespimd);
1973 +
1974 +ssize_t locomospi_showspict(struct device_driver *drv, char *buf)
1975 +{
1976 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPICT));
1977 +}
1978 +
1979 +ssize_t locomospi_storespict(struct device_driver *drv, const char *buf, size_t count)
1980 +{
1981 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPICT);
1982 +       return count;
1983 +}
1984 +static DRIVER_ATTR(spict, S_IWUSR | S_IRUGO, locomospi_showspict, locomospi_storespict);
1985 +
1986 +ssize_t locomospi_showspist(struct device_driver *drv, char *buf)
1987 +{
1988 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIST));
1989 +}
1990 +
1991 +ssize_t locomospi_storespist(struct device_driver *drv, const char *buf, size_t count)
1992 +{
1993 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIST);
1994 +       return count;
1995 +}
1996 +static DRIVER_ATTR(spist, S_IWUSR | S_IRUGO, locomospi_showspist, locomospi_storespist);
1997 +
1998 +ssize_t locomospi_showspitd(struct device_driver *drv, char *buf)
1999 +{
2000 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITD));
2001 +}
2002 +
2003 +ssize_t locomospi_storespitd(struct device_driver *drv, const char *buf, size_t count)
2004 +{
2005 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITD);
2006 +       return count;
2007 +}
2008 +static DRIVER_ATTR(spitd, S_IWUSR | S_IRUGO, locomospi_showspitd, locomospi_storespitd);
2009 +
2010 +ssize_t locomospi_showspird(struct device_driver *drv, char *buf)
2011 +{
2012 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRD));
2013 +}
2014 +
2015 +ssize_t locomospi_storespird(struct device_driver *drv, const char *buf, size_t count)
2016 +{
2017 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRD);
2018 +       return count;
2019 +}
2020 +static DRIVER_ATTR(spird, S_IWUSR | S_IRUGO, locomospi_showspird, locomospi_storespird);
2021 +
2022 +ssize_t locomospi_showspits(struct device_driver *drv, char *buf)
2023 +{
2024 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITS));
2025 +}
2026 +
2027 +ssize_t locomospi_storespits(struct device_driver *drv, const char *buf, size_t count)
2028 +{
2029 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITS);
2030 +       return count;
2031 +}
2032 +static DRIVER_ATTR(spits, S_IWUSR | S_IRUGO, locomospi_showspits, locomospi_storespits);
2033 +
2034 +ssize_t locomospi_showspirs(struct device_driver *drv, char *buf)
2035 +{
2036 +       return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRS));
2037 +}
2038 +
2039 +ssize_t locomospi_storespirs(struct device_driver *drv, const char *buf, size_t count)
2040 +{
2041 +       iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRS);
2042 +       return count;
2043 +}
2044 +static DRIVER_ATTR(spirs, S_IWUSR | S_IRUGO, locomospi_showspirs, locomospi_storespirs);
2045 +
2046 +/* MMC Card status */
2047 +
2048 +ssize_t locomospi_showpower(struct device_driver *drv, char *buf)
2049 +{
2050 +       return sprintf(buf, "%d\n", spidev->card_power);
2051 +}
2052 +
2053 +ssize_t locomospi_storepower(struct device_driver *drv, const char *buf, size_t count)
2054 +{
2055 +       locomospi_power(simple_strtoul(buf, NULL, 10));
2056 +       return count;
2057 +}
2058 +static DRIVER_ATTR(cardpower, S_IWUSR | S_IRUGO, locomospi_showpower, locomospi_storepower);
2059 +
2060 +ssize_t locomospi_detectcard(struct device_driver *drv, char *buf)
2061 +{
2062 +       return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1);
2063 +}
2064 +static DRIVER_ATTR(carddetect, S_IRUGO, locomospi_detectcard, NULL);
2065 +
2066 +ssize_t locomospi_writeprotect(struct device_driver *drv, char *buf)
2067 +{
2068 +       return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT)>0)?1:0);
2069 +}
2070 +static DRIVER_ATTR(cardwriteprotect, S_IRUGO, locomospi_writeprotect, NULL);
2071 +
2072 +
2073 +ssize_t locomospi_showclock(struct device_driver *drv, char *buf)
2074 +{
2075 +       return sprintf(buf, "%d\n", spidev->clock);
2076 +}
2077 +
2078 +ssize_t locomospi_storeclock(struct device_driver *drv, const char *buf, size_t count)
2079 +{
2080 +       locomospi_clock(simple_strtoul(buf, NULL, 10));
2081 +       return count;
2082 +}
2083 +static DRIVER_ATTR(clock, S_IWUSR | S_IRUGO, locomospi_showclock, locomospi_storeclock);
2084 +
2085 +/* debug */
2086 +ssize_t locomospi_showdelay(struct device_driver *drv, char *buf)
2087 +{
2088 +       return sprintf(buf, "%d\n", delay);
2089 +}
2090 +
2091 +ssize_t locomospi_storedelay(struct device_driver *drv, const char *buf, size_t count)
2092 +{
2093 +       delay=simple_strtoul(buf,NULL,10);
2094 +       return count;
2095 +}
2096 +static DRIVER_ATTR(delay, S_IWUSR | S_IRUGO, locomospi_showdelay, locomospi_storedelay);
2097 +
2098 +ssize_t locomospi_reset(struct device_driver *drv, const char *buf, size_t count)
2099 +{
2100 +       int choice = simple_strtoul(buf, NULL, 10);
2101 +       char   buff[100];
2102 +       u16 r; 
2103 +       switch(choice){
2104 +               case 0: locomospi_reg_release();
2105 +                       schedule_timeout(2*HZ);
2106 +                       locomospi_reg_open();
2107 +                       break;
2108 +               case 1: {
2109 +                               char b1[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
2110 +                               char b2[] = "\xff\x40\x00\x00\x00\x00\x95\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
2111 +                               locomospi_setcs(1);
2112 +                               txrx(b1,b1,17);
2113 +                               locomospi_setcs(0);
2114 +                               txrx(b2,b2,18);
2115 +
2116 +                       }
2117 +                       break;
2118 +               case 2: locomospi_setcs(1);
2119 +                       txrx("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",buff,18);
2120 +                       locomospi_setcs(0);
2121 +                       txrx("\xff\x40\x00\x00\x00\x00\x95\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",buff,17);
2122 +                       break;
2123 +               case 3: 
2124 +                       r = ioread16(spidev->base+LOCOMO_SPIMD);
2125 +                       r |= LOCOMO_SPI_LOOPBACK;
2126 +                       iowrite16(r, spidev->base+LOCOMO_SPIMD);
2127 +                       txrx("X",buff,1);
2128 +                       txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
2129 +                       txrx("Y",buff,1);
2130 +                       udelay(100);
2131 +                       txrx("Z",buff,1);
2132 +                       schedule_timeout(HZ);   
2133 +                       txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
2134 +                       
2135 +                       r = ioread16(spidev->base+LOCOMO_SPIMD);
2136 +                       r &= ~LOCOMO_SPI_LOOPBACK;
2137 +                       iowrite16(r, spidev->base+LOCOMO_SPIMD);
2138 +                       break;
2139 +               default: /* do nothing */;
2140 +       }
2141 +       return count;
2142 +}
2143 +static DRIVER_ATTR(reset, S_IWUSR, NULL, locomospi_reset);
2144 +
2145 +typedef struct locomo_reg_entry {
2146 +        u32 addr;
2147 +        char* name;
2148 +} locomo_reg_entry_t;
2149 +#define LCM     (sizeof(locomo_regs)/sizeof(locomo_reg_entry_t))
2150 +static locomo_reg_entry_t locomo_regs[] =
2151 +{
2152 +/*      { addr,    name,     description } */
2153 +        { 0x00, "VER" },
2154 +        { 0x04, "ST" },
2155 +        { 0x08, "C32K" },
2156 +        { 0x0C, "ICR" },
2157 +        { 0x10, "MCSX0" },
2158 +        { 0x14, "MCSX1" },
2159 +        { 0x18, "MCSX2" },
2160 +        { 0x1C, "MCSX3" },
2161 +        { 0x20, "ASD" },
2162 +        { 0x28, "HSD" },
2163 +        { 0x2C, "HSC" },
2164 +        { 0x30, "TADC" },
2165 +        { 0x38, "TC" },
2166 +        { 0x3C, "CPSD" },
2167 +        { 0x40, "KIB" },
2168 +        { 0x44, "KSC" },
2169 +        { 0x48, "KCMD" },
2170 +        { 0x4C, "KIC" },
2171 +        { 0x54, "ACC" },
2172 +        { 0x60, "SPIMD" },
2173 +        { 0x64, "SPICT" },
2174 +        { 0x68, "SPIST" },
2175 +        { 0x70, "SPIIS" },
2176 +        { 0x74, "SPIWE" },
2177 +        { 0x78, "SPIIE" },
2178 +        { 0x7C, "SPIIR" },
2179 +        { 0x80, "SPITD" },
2180 +        { 0x84, "SPIRD" },
2181 +        { 0x88, "SPITS" },
2182 +        { 0x8C, "SPIRS" },
2183 +        { 0x90, "GPD" },
2184 +        { 0x94, "GPE" },
2185 +        { 0x98, "GPL" },
2186 +        { 0x9C, "GPO" },
2187 +        { 0xa0, "GRIE" },
2188 +        { 0xa4, "GFIE" },
2189 +        { 0xa8, "GIS" },
2190 +        { 0xac, "GWE" },
2191 +        { 0xb0, "GIE" },
2192 +        { 0xb4, "GIR" },
2193 +        { 0xc8, "ALC" },
2194 +        { 0xcc, "ALR" },
2195 +        { 0xd0, "PAIF" },
2196 +        { 0xd8, "LTC" },
2197 +        { 0xdc, "LTINT" },
2198 +        { 0xe0, "DAC" },
2199 +        { 0xe8, "LPT0" },
2200 +        { 0xec, "LPT1" },
2201 +        { 0xfc, "TCR" },
2202 +};
2203 +
2204 +static ssize_t lcm_show(struct device *dev, struct device_attribute *attr, char *buf)
2205 +{
2206 +       int base = spidev->base - LOCOMO_SPI; 
2207 +       char b[4000]="";
2208 +       char c[30];
2209 +       int i;
2210 +       for(i=0; i<LCM; i++){
2211 +               sprintf(c,"%s:\t\t 0x%x\n",locomo_regs[i].name, ioread16(base + locomo_regs[i].addr));
2212 +               strcat(b,c);
2213 +       }
2214 +       return sprintf(buf,"%s",b);
2215 +}
2216 +
2217 +static DRIVER_ATTR(regs, 0444, lcm_show, NULL);
2218 +
2219 +
2220 +/* SPI functions *************************************************************/
2221 +
2222 +static void locomospi_do_transfer(struct work_struct *wrk)
2223 +{
2224 +       struct list_head *mptr, *tptr, *mptr2;
2225 +       struct spi_transfer *entry;
2226 +       struct spi_message *msg;
2227 +
2228 +       list_for_each_safe(mptr, mptr2, &spidev->message_list){
2229 +               msg = list_entry(mptr, struct spi_message, queue);
2230 +
2231 +               msg->status = 0;
2232 +               msg->actual_length = 0;
2233 +               list_for_each(tptr, &msg->transfers){
2234 +                       entry = list_entry(tptr, struct spi_transfer, transfer_list);
2235 +                       if(entry->tx_buf && entry->rx_buf){ //duplex
2236 +                               txrx((char*) entry->tx_buf, (char*) entry->rx_buf, entry->len);                         
2237 +                               msg->actual_length += entry->len;
2238 +                       } else if(entry->tx_buf && !entry->rx_buf){ //write
2239 +                               tx((char*) entry->tx_buf, entry->len);
2240 +                               msg->actual_length += entry->len;
2241 +                       } else if(!entry->tx_buf && entry->rx_buf){ //read
2242 +                               rx((char*) entry->rx_buf, entry->len);
2243 +                               msg->actual_length += entry->len;
2244 +                       } else if(!entry->tx_buf && !entry->rx_buf){ //error
2245 +                               dev_err(&spidev->sdev->dev, "do_transfer: no buffers allocated\n");
2246 +                               msg->status = -EFAULT;
2247 +                       }
2248 +               }
2249 +               spin_lock(&spidev->message_lock);
2250 +               list_del(mptr);
2251 +               spin_unlock(&spidev->message_lock);
2252 +               msg->complete(msg->context);
2253 +       }
2254 +}
2255 +
2256 +static int locomospi_setup(struct spi_device *spi)
2257 +{
2258 +       if((spi->mode & SPI_CS_HIGH) != (spidev->spimode & SPI_CS_HIGH)) 
2259 +               locomospi_setcs(spi->mode & SPI_CS_HIGH ? 1 : 0 );
2260 +       if(spidev->clock != spi->max_speed_hz){
2261 +               locomospi_clock(spi->max_speed_hz);
2262 +       }
2263 +       spidev->spimode = spi->mode;
2264 +
2265 +       return 0;
2266 +}
2267 +
2268 +static int locomospi_transfer(struct spi_device *spi, struct spi_message *msg)
2269 +{
2270 +
2271 +       spin_lock(&spidev->message_lock);
2272 +       list_add_tail(&msg->queue, &spidev->message_list);
2273 +       spin_unlock(&spidev->message_lock);
2274 +       schedule_work(&transfer_wq);
2275 +       return 0;
2276 +}
2277 +
2278 +static struct locomo_driver locomo_spi_driver = {
2279 +       .drv = {
2280 +               .name = "locomo-spi",
2281 +       },
2282 +       .devid  = LOCOMO_DEVID_SPI,
2283 +       .probe  = locomospi_probe,
2284 +       .remove = locomospi_remove,
2285 +#ifdef CONFIG_PM
2286 +       .suspend = locomospi_suspend,
2287 +       .resume = locomospi_resume,
2288 +#endif
2289 +};
2290 +
2291 +static struct spi_board_info board = {
2292 +       .modalias       = "mmc_spi",
2293 +       .platform_data  = (void*) &colliemmc,
2294 +       .controller_data= NULL,
2295 +       .irq            = 0,
2296 +       .max_speed_hz   = 25000000,
2297 +       .bus_num        = 0,
2298 +       .chip_select    = 0,
2299 +       .mode           = 0,
2300 +};
2301 +
2302 +#ifdef CONFIG_PM
2303 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state)
2304 +{
2305 +       disable_irq(IRQ_LOCOMO_CARDDETECT);
2306 +       return 0;
2307 +}
2308 +
2309 +static int locomospi_resume(struct locomo_dev *dev)
2310 +{
2311 +       enable_irq(IRQ_LOCOMO_CARDDETECT);
2312 +       return 0;
2313 +}
2314 +#endif
2315 +
2316 +static int locomospi_probe(struct locomo_dev *dev)
2317 +{
2318 +       int result=0;
2319 +       printk(KERN_DEBUG "Collie MMC over SPI Driver\n");
2320 +       spidev=kmalloc(sizeof(struct locomospi_dev),GFP_KERNEL);
2321 +       if(!spidev){
2322 +               return -ENOMEM;
2323 +       }
2324 +       spidev->ldev = dev;
2325 +       spidev->card_power = 1;
2326 +       spidev->spimode = 0;
2327 +
2328 +       if(!request_mem_region((unsigned long) dev->mapbase, dev->length, LOCOMO_DRIVER_NAME(dev))) {
2329 +               dev_err(&dev->dev, " Can't aquire access to io memory\n");
2330 +               return -EBUSY;
2331 +       }
2332 +       spidev->base=(unsigned long) dev->mapbase;
2333 +       locomospi_reg_open();
2334 +
2335 +       locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_POWER, 0);
2336 +       locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_DETECT, 1);
2337 +       locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_WRITE_PROT, 1);
2338 +
2339 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardpower);
2340 +       if(result){
2341 +               dev_err(&dev->dev, "error creating driver attribute\n");
2342 +               goto region;
2343 +       }
2344 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_carddetect);
2345 +       if(result){
2346 +               dev_err(&dev->dev,"error creating driver attribute\n");
2347 +               goto region;
2348 +       }
2349 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardwriteprotect);
2350 +       if(result){
2351 +               dev_err(&dev->dev, "error creating driver attribute\n");
2352 +               goto region;
2353 +       }
2354 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spimd);
2355 +       if(result){
2356 +               dev_err(&dev->dev, "error creating driver attribute\n");
2357 +               goto region;
2358 +       }
2359 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spict);
2360 +       if(result){
2361 +               dev_err(&dev->dev, "error creating driver attribute\n");
2362 +               goto region;
2363 +       }
2364 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spist);
2365 +       if(result){
2366 +               dev_err(&dev->dev, "error creating driver attribute\n");
2367 +               goto region;
2368 +       }
2369 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spitd);
2370 +       if(result){
2371 +               dev_err(&dev->dev, "error creating driver attribute\n");
2372 +               goto region;
2373 +       }
2374 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spird);
2375 +       if(result){
2376 +               dev_err(&dev->dev, "error creating driver attribute\n");
2377 +               goto region;
2378 +       }
2379 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spits);
2380 +       if(result){
2381 +               dev_err(&dev->dev, "error creating driver attribute\n");
2382 +               goto region;
2383 +       }
2384 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spirs);
2385 +       if(result){
2386 +               dev_err(&dev->dev, "error creating driver attribute\n");
2387 +               goto region;
2388 +       }
2389 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_clock);
2390 +       if(result){
2391 +               dev_err(&dev->dev, "error creating driver attribute\n");
2392 +               goto region;
2393 +       }
2394 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_delay);
2395 +       if(result){
2396 +               dev_err(&dev->dev, "error creating driver attribute\n");
2397 +               goto region;
2398 +       }
2399 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_reset);
2400 +       if(result){
2401 +               dev_err(&dev->dev, "error creating driver attribute\n");
2402 +               goto region;
2403 +       }
2404 +       result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_regs);
2405 +        if(result){
2406 +                dev_err(&dev->dev, "error creating driver attribute\n");
2407 +                goto region;
2408 +        }
2409 +       INIT_WORK(&transfer_wq, locomospi_do_transfer);
2410 +       INIT_LIST_HEAD(&spidev->message_list);
2411 +       spin_lock_init(&spidev->message_lock);
2412 +       init_waitqueue_head(&spidev->waitqueue);
2413 +       spidev->master=spi_alloc_master(&dev->dev,0);
2414 +       if(!spidev->master){
2415 +               result=-ENOMEM;
2416 +               goto region;
2417 +       }
2418 +       spidev->master->bus_num = 0;
2419 +       spidev->master->num_chipselect = 1;
2420 +       spidev->master->setup = locomospi_setup;
2421 +       spidev->master->transfer = locomospi_transfer;
2422 +       spidev->sdev = spi_new_device(spidev->master, &board);
2423 +       if(!spidev->sdev){
2424 +               dev_err(&dev->dev, "failed to register spi device\n");
2425 +               result = -EINVAL;
2426 +               goto master;
2427 +       }
2428 +/*     result=request_irq(IRQ_LOCOMO_SPI_RFR, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2429 +       if(result) {
2430 +               dev_err(&dev->dev, "Could not get IRQ: RFR\n");
2431 +               goto regdev;
2432 +       }
2433 +       //disable_irq(IRQ_LOCOMO_SPI_RFR);
2434 +*//*   result=request_irq(IRQ_LOCOMO_SPI_RFW, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2435 +       if(result) {
2436 +               dev_err(&dev->dev, "Could not get IRQ: RFW\n");
2437 +               goto irq1;
2438 +       }
2439 +       //disable_irq(IRQ_LOCOMO_SPI_RFW);
2440 +*//*   result=request_irq(IRQ_LOCOMO_SPI_REND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2441 +       if(result) {
2442 +               dev_err(&dev->dev, "Could not get IRQ: REND\n");
2443 +               goto irq2;
2444 +       }
2445 +*//*   result=request_irq(IRQ_LOCOMO_SPI_TEND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2446 +       if(result) {
2447 +               dev_err(&dev->dev, "Could not get IRQ: TEND\n");
2448 +               goto irq3;
2449 +       }
2450 +       //disable_irq(IRQ_LOCOMO_SPI_TEND);     
2451 +*/     spidev->workqueue = create_singlethread_workqueue("locomo-spi");
2452 +       if(!spidev->workqueue){
2453 +               dev_err(&dev->dev, "failed to create workqueue\n");
2454 +               goto irq4;
2455 +       }
2456 +       result=spi_register_master(spidev->master);
2457 +       if(result){
2458 +               dev_err(&dev->dev, "failed to register spimaster\n");
2459 +               goto wq;
2460 +       }
2461 +       return 0;
2462 +wq:
2463 +       destroy_workqueue(spidev->workqueue);
2464 +irq4:
2465 +//     free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
2466 +irq3:
2467 +//     free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
2468 +irq2:
2469 +//     free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
2470 +irq1:
2471 +//     free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
2472 +regdev:
2473 +       spi_unregister_device(spidev->sdev);
2474 +master:
2475 +       spi_master_put(spidev->master);
2476 +region:
2477 +       release_mem_region((unsigned long) dev->mapbase, dev->length);
2478 +       kfree(spidev);
2479 +       return result;
2480 +
2481 +}
2482 +
2483 +static int locomospi_remove(struct locomo_dev *dev)
2484 +{
2485 +       spi_unregister_device(spidev->sdev);
2486 +       spi_unregister_master(spidev->master);
2487 +       destroy_workqueue(spidev->workqueue);
2488 +       locomospi_reg_release();
2489 +//     free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
2490 +//     free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
2491 +//     free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
2492 +//     free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
2493 +       spi_master_put(spidev->master);
2494 +       release_mem_region((unsigned long) dev->mapbase, dev->length);
2495 +       kfree(spidev);
2496 +       return 0;
2497 +}
2498 +
2499 +
2500 +
2501 +static int __init locomospi_init(void)
2502 +{
2503 +       int ret = locomo_driver_register(&locomo_spi_driver);
2504 +       if (ret)
2505 +               return ret;
2506 +
2507 +
2508 +       return 0;
2509 +}
2510 +
2511 +static void __exit locomospi_exit(void)
2512 +{
2513 +       locomo_driver_unregister(&locomo_spi_driver);
2514 +}
2515 +
2516 +module_init(locomospi_init);
2517 +module_exit(locomospi_exit);
2518 +
2519 +MODULE_AUTHOR("Thomas Kunze thommy@tabao.de");
2520 +MODULE_DESCRIPTION("Collie mmc driver");
2521 +MODULE_LICENSE("GPL");
2522 Index: linux-2.6.26/drivers/spi/locomo_spi.h
2523 ===================================================================
2524 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
2525 +++ linux-2.6.26/drivers/spi/locomo_spi.h       2008-10-17 18:15:31.471790439 +0200
2526 @@ -0,0 +1,75 @@
2527 +#include <asm/hardware/locomo.h>
2528 +#ifndef __LOCOMO_SPI_H__
2529 +#define __LOCOMO_SPI_H__
2530 +
2531 +/* locomo-spi status register LOCOMO_SPIST */
2532 +#define LOCOMO_SPI_TEND (1 << 3)        /* Transfer end bit */
2533 +#define LOCOMO_SPI_REND (1 << 2)        /* Receive end bit */
2534 +#define LOCOMO_SPI_RFW  (1 << 1)        /* write buffer bit */
2535 +#define LOCOMO_SPI_RFR  (1)             /* read buffer bit */
2536 +
2537 +/* locomo-spi mode register LOCOMO_SPIMD */
2538 +#define LOCOMO_SPI_LOOPBACK (1 << 15)  /* loopback tx to rx    */
2539 +#define LOCOMO_SPI_MSB1ST   (1 << 14)  /* send MSB first       */
2540 +#define LOCOMO_SPI_DOSTAT   (1 << 13)  /* transmit line is idle high */
2541 +#define LOCOMO_SPI_TCPOL    (1 << 11)  /* transmit CPOL (maybe affects CPHA too) */
2542 +#define LOCOMO_SPI_RCPOL    (1 << 10)  /* receive CPOL (maybe affects CPHA too) */
2543 +#define        LOCOMO_SPI_TDINV    (1 << 9)    /* invert transmit line */
2544 +#define LOCOMO_SPI_RDINV    (1 << 8)   /* invert receive line */
2545 +#define LOCOMO_SPI_XON     (1 << 7)    /* enable spi controller clock */
2546 +#define LOCOMO_SPI_XEN     (1 << 6)    /* clock bit write enable xon must be off, wait 300 us before xon->1 */ 
2547 +#define LOCOMO_SPI_XSEL            0x0018      /* clock select                 */
2548 +#define CLOCK_18MHZ        0           /* 18,432 MHz clock     */
2549 +#define CLOCK_22MHZ        1           /* 22,5792 MHz clock    */
2550 +#define CLOCK_25MHZ        2           /* 24,576 MHz clock     */
2551 +#define LOCOMO_SPI_CLKSEL   0x7        
2552 +#define DIV_1              0           /* don't divide clock   */
2553 +#define DIV_2              1           /* divide clock by two  */
2554 +#define DIV_4              2           /* divide clock by four */
2555 +#define DIV_8              3           /* divide clock by eight*/
2556 +#define DIV_64             4           /* divide clock by 64 */
2557 +
2558 +/* locomo-spi control register LOCOMO_SPICT */
2559 +#define LOCOMO_SPI_CRC16_7_B   (1 << 15)       /* 0: crc16 1: crc7 */
2560 +#define LOCOMO_SPI_CRCRX_TX_B  (1 << 14)
2561 +#define LOCOMO_SPI_CRCRESET_B  (1 << 13)
2562 +#define LOCOMO_SPI_CEN         (1 << 7)        /* ?? enable */
2563 +#define LOCOMO_SPI_CS          (1 << 6)        /* chip select */
2564 +#define LOCOMO_SPI_UNIT16      (1 << 5)        /* 0: 8 bit units, 1: 16 bit unit */
2565 +#define LOCOMO_SPI_ALIGNEN     (1 << 2)        /* align transfer enable */
2566 +#define LOCOMO_SPI_RXWEN       (1 << 1)        /* continous receive */
2567 +#define LOCOMO_SPI_RXUEN       (1 << 0)        /* aligned receive */
2568 +
2569 +#define IRQ_LOCOMO_CARDDETECT  IRQ_LOCOMO_GPIO13
2570 +
2571 +
2572 +struct locomospi_dev {
2573 +       struct locomo_dev *ldev;
2574 +       struct spi_master *master;
2575 +       struct spi_device *sdev;
2576 +       int card_power;
2577 +       int clock_base;
2578 +       int clock_div;
2579 +       int clock;
2580 +       unsigned long base;
2581 +       u8 spimode;
2582 +       wait_queue_head_t waitqueue;
2583 +       struct workqueue_struct *workqueue;
2584 +       struct list_head message_list;
2585 +       spinlock_t message_lock;
2586 +};
2587 +
2588 +
2589 +static irqreturn_t     locomospi_cardisr(int, void*);
2590 +static int     locomospi_probe(struct locomo_dev*);
2591 +static int     locomospi_remove(struct locomo_dev*);
2592 +static int     locomospi_carddetect(void);
2593 +static void    locomospi_reg_open(void);
2594 +static void    locomospi_reg_release(void);
2595 +static int     tx(const char*, int);
2596 +static int     rx(char *, int);
2597 +static void    locomospi_power(int on);
2598 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state);
2599 +static int locomospi_resume(struct locomo_dev *dev);
2600 +static void locomospi_setcs(int high);
2601 +#endif