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
9 - depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
10 + depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3 || SA1100_COLLIE)
13 config CPU_FREQ_INTEGRATOR
14 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
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
33 static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
35 -static spinlock_t dma_list_lock;
36 +static DEFINE_SPINLOCK(dma_list_lock);
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
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);
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
57 tristate "Touchscreen interface support"
58 depends on MCP_UCB1200 && INPUT
61 + tristate "Touchscreen collie support"
62 + depends on MCP_UCB1200 && INPUT && !MCP_UCB1200_TS
64 + Driver for touchscreen on collie - sharp sl-5500.
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
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
76 +obj-$(CONFIG_MCP_COLLIE_TS) += collie-ts.o
77 ifeq ($(CONFIG_SA1100_ASSABET),y)
78 obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
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
86 + * Touchscreen driver for UCB1x00-based touchscreens
88 + * Copyright (C) 2001 Russell King, All Rights Reserved.
89 + * Copyright (C) 2005 Pavel Machek
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.
95 + * 21-Jan-2002 <jco@ict.es> :
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.
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>
120 +#include <asm/dma.h>
121 +#include <asm/arch/collie.h>
122 +#include <asm/mach-types.h>
124 +#include "ucb1x00.h"
127 + struct input_dev *idev;
128 + struct ucb1x00 *ucb;
130 + wait_queue_head_t irq_wait;
131 + struct task_struct *rtask;
135 + unsigned int adcsync:1;
140 +/**********************************
159 +**********************************/
162 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
164 + struct input_dev *idev = ts->idev;
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);
173 +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
175 + struct input_dev *idev = ts->idev;
177 + input_report_abs(idev, ABS_PRESSURE, 0);
178 + input_report_key(idev, BTN_TOUCH, 0);
183 + * Switch to interrupt mode. This set touchscreen to interrupt
184 + * mode, so that chip is able to send interrupt.
186 +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
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);
195 + * Switch to pressure mode, and read pressure. We don't need to wait
196 + * here, since both plates are being driven.
198 + * set_read_pressure() in sharp code
200 +static inline void ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
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);
207 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
211 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
213 + UCB_ADC_SYNC_ENA | UCB_ADC_START);
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.
222 +static inline void ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
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);
230 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
231 + UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA);
233 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
234 + UCB_ADC_INP_TSPY | UCB_ADC_SYNC_ENA |
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.
244 +static inline void ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
246 + ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
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);
253 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
254 + UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA);
256 + ucb1x00_reg_write(ts->ucb, UCB_ADC_CR, ts->ucb->adc_cr |
257 + UCB_ADC_INP_TSPX | UCB_ADC_SYNC_ENA |
262 + * Switch to X plate resistance mode. Set MX to ground, PX to
263 + * supply. Measure current.
265 +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
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);
274 + * Switch to Y plate resistance mode. Set MY to ground, PY to
275 + * supply. Measure current.
277 +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
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);
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).
290 +static int ucb1x00_thread(void *_ts)
292 + struct ucb1x00_ts *ts = _ts;
293 + struct task_struct *tsk = current;
294 + DECLARE_WAITQUEUE(wait, tsk);
298 + * We could run as a real-time thread. However, thus far
299 + * this doesn't seem to be necessary.
302 + add_wait_queue(&ts->irq_wait, &wait);
304 + while (!kthread_should_stop()) {
305 + unsigned int data[3];
307 + for (state=0; state<3; state++) {
309 + ucb1x00_adc_enable(ts->ucb);
310 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_ADC, UCB_FALLING);
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);
316 + case 0: ucb1x00_ts_read_ypos(ts);
318 + case 1: ucb1x00_ts_read_xpos(ts);
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);
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);
337 + schedule_timeout(1000 * HZ);
338 + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
339 + ucb1x00_enable(ts->ucb);
341 + ucb1x00_ts_evt_add(ts, data[2], data[1], data[0]);
343 + ucb1x00_disable(ts->ucb);
345 + ucb1x00_enable(ts->ucb);
348 + remove_wait_queue(&ts->irq_wait, &wait);
355 + * We only detect touch screen _touches_ with this interrupt
356 + * handler, and even then we just schedule our task.
358 +static void ucb1x00_ts_irq(int idx, void *id)
360 + struct ucb1x00_ts *ts = id;
361 + wake_up(&ts->irq_wait);
364 +static void ucb1x00_adc_irq(int idx, void *id)
366 + struct ucb1x00_ts *ts = id;
367 + wake_up(&ts->irq_wait);
370 +static int ucb1x00_ts_open(struct input_dev *idev)
372 + struct ucb1x00_ts *ts = input_get_drvdata(idev);
377 + init_waitqueue_head(&ts->irq_wait);
379 + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
383 + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_ADC, ucb1x00_adc_irq, ts);
385 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
389 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_RISING);
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.
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);
400 + if (machine_is_collie()) {
401 + ucb1x00_io_set_dir(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
404 + ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
405 + if (!IS_ERR(ts->rtask)) {
408 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
417 + * Release touchscreen resources. Disable IRQs.
419 +static void ucb1x00_ts_close(struct input_dev *idev)
421 + struct ucb1x00_ts *ts = input_get_drvdata(idev);
424 + kthread_stop(ts->rtask);
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);
434 +static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
436 + struct ucb1x00_ts *ts = dev->priv;
438 + if (ts->rtask != NULL) {
440 + * Restart the TS thread to ensure the
441 + * TS interrupt mode is set up again
444 + wake_up(&ts->irq_wait);
449 +#define ucb1x00_ts_resume NULL
456 +static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
458 + struct ucb1x00_ts *ts;
459 + struct input_dev *idev;
462 + ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
463 + idev = input_allocate_device();
464 + if (!ts || !idev) {
469 + ts->ucb = dev->ucb;
471 + ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
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;
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);
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);
489 + err = input_register_device(idev);
498 + input_free_device(idev);
503 +static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
505 + struct ucb1x00_ts *ts = dev->priv;
507 + input_unregister_device(ts->idev);
511 +static struct ucb1x00_driver ucb1x00_ts_driver = {
512 + .add = ucb1x00_ts_add,
513 + .remove = ucb1x00_ts_remove,
514 + .resume = ucb1x00_ts_resume,
517 +static int __init ucb1x00_ts_init(void)
519 + return ucb1x00_register_driver(&ucb1x00_ts_driver);
522 +static void __exit ucb1x00_ts_exit(void)
524 + ucb1x00_unregister_driver(&ucb1x00_ts_driver);
527 +module_param(adcsync, int, 0444);
528 +module_init(ucb1x00_ts_init);
529 +module_exit(ucb1x00_ts_exit);
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
539 #define UCB_IE_TCLIP (1 << 14)
540 #define UCB_IE_ACLIP (1 << 15)
543 +#define UCB_IRQ_ADC 11
544 #define UCB_IRQ_TSPX 12
545 +#define UCB_IRQ_TSMX 13
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
554 used for XIP purposes. If you're not sure what this is all about
558 + tristate "pre-CFI Sharp chip support"
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.
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
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
583 + * MTD chip driver for pre-CFI Sharp flash chips
585 + * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
586 + * 2000,2001 Lineo, Inc.
588 + * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
590 + * Devices supported:
591 + * LH28F016SCT Symmetrical block flash memory, 2Mx8
592 + * LH28F008SCT Symmetrical block flash memory, 1Mx8
595 + * http://www.sharpmeg.com/datasheets/memic/flashcmp/
596 + * http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
600 + * This driver only supports 4x1 arrangement of chips.
601 + * Not tested on anything but PowerPC.
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>
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
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
642 +#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
644 +#define BLOCK_MASK 0xfffe0000
646 +/* Configuration options */
648 +#define AUTOUNLOCK /* automatically unlocks blocks before erasing */
650 +static struct mtd_info *sharp_probe(struct map_info *);
652 +static int sharp_probe_map(struct map_info *map, struct mtd_info *mtd);
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);
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);
669 +static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
670 + unsigned long adr);
675 + struct flchip *chip;
679 + struct flchip chips[1];
682 +static void sharp_destroy(struct mtd_info *mtd);
684 +static struct mtd_chip_driver sharp_chipdrv = {
685 + .probe = sharp_probe,
686 + .destroy = sharp_destroy,
688 + .module = THIS_MODULE
691 +static void sharp_udelay(unsigned long i) {
692 + if (in_interrupt()) {
699 +static struct mtd_info *sharp_probe(struct map_info *map)
701 + struct mtd_info *mtd = NULL;
702 + struct sharp_info *sharp = NULL;
705 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
709 + sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
715 + width = sharp_probe_map(map,mtd);
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;
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);
743 + map->fldrv = &sharp_chipdrv;
744 + map->fldrv_priv = sharp;
746 + __module_get(THIS_MODULE);
750 +static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
753 + map_cmd.x[0] = cmd;
754 + map_write(map, map_cmd, adr);
757 +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
759 + map_word tmp, read0, read4;
760 + unsigned long base = 0;
763 + tmp = map_read(map, base+0);
765 + sharp_send_cmd(map, CMD_READ_ID, base+0);
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]){
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;
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;
787 + /* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
788 + mtd->erasesize = 0x10000 * width / 2;
789 + mtd->size = 0x800000 * width / 2;
792 + printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
793 + read0.x[0], read4.x[0]);
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);
800 + printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
801 + read0.x[0], read4.x[0]);
807 +/* This function returns with the chip->mutex lock held. */
808 +static int sharp_wait(struct map_info *map, struct flchip *chip)
811 + unsigned long timeo = jiffies + HZ;
812 + DECLARE_WAITQUEUE(wait, current);
816 + spin_lock_bh(chip->mutex);
818 + switch (chip->state) {
820 + sharp_send_cmd(map, CMD_READ_STATUS, adr);
821 + chip->state = FL_STATUS;
823 + status = map_read(map, adr);
824 + if ((status.x[0] & SR_READY) == SR_READY)
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");
834 + set_current_state(TASK_INTERRUPTIBLE);
835 + add_wait_queue(&chip->wq, &wait);
837 + spin_unlock_bh(chip->mutex);
841 + set_current_state(TASK_RUNNING);
842 + remove_wait_queue(&chip->wq, &wait);
844 + if(signal_pending(current))
847 + timeo = jiffies + HZ;
852 + sharp_send_cmd(map, CMD_RESET, adr);
854 + chip->state = FL_READY;
859 +static void sharp_release(struct flchip *chip)
861 + wake_up(&chip->wq);
862 + spin_unlock_bh(chip->mutex);
865 +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
866 + size_t *retlen, u_char *buf)
868 + struct map_info *map = mtd->priv;
869 + struct sharp_info *sharp = map->fldrv_priv;
874 + chipnum = (from >> sharp->chipshift);
875 + ofs = from & ((1 << sharp->chipshift)-1);
880 + unsigned long thislen;
882 + if(chipnum>=sharp->numchips)
886 + if(ofs+thislen >= (1<<sharp->chipshift))
887 + thislen = (1<<sharp->chipshift) - ofs;
889 + ret = sharp_wait(map,&sharp->chips[chipnum]);
893 + map_copy_from(map,buf,ofs,thislen);
895 + sharp_release(&sharp->chips[chipnum]);
897 + *retlen += thislen;
907 +static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
908 + size_t *retlen, const u_char *buf)
910 + struct map_info *map = mtd->priv;
911 + struct sharp_info *sharp = map->fldrv_priv;
916 + union { u32 l; unsigned char uc[4]; } tbuf;
921 + tbuf.l = 0xffffffff;
922 + chipnum = to >> sharp->chipshift;
923 + ofs = to & ((1<<sharp->chipshift)-1);
926 + for(i=ofs&3;i<4 && len;i++){
933 + sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
942 +static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
943 + unsigned long adr, __u32 datum)
948 + map_word data, status;
951 + ret = sharp_wait(map,chip);
955 + for (try=0; try<10; try++) {
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);
963 + chip->state = FL_WRITING;
964 + timeo = jiffies + (HZ/2);
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)
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);
982 + printk("sharp: timed out writing\n");
985 + if (!(status.x[0] & SR_ERRORS))
988 + printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
990 + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
992 + sharp_send_cmd(map, CMD_RESET, adr);
993 + chip->state = FL_READY;
995 + sharp_release(chip);
1000 +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
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;
1007 + if(instr->addr & (mtd->erasesize - 1))
1009 + if(instr->len & (mtd->erasesize - 1))
1011 + if(instr->len + instr->addr > mtd->size)
1014 + chipnum = instr->addr >> sharp->chipshift;
1015 + adr = instr->addr & ((1<<sharp->chipshift)-1);
1019 + ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
1020 + if(ret)return ret;
1022 + if (adr >= 0xfe0000) {
1023 + adr += mtd->erasesize / 8;
1024 + len -= mtd->erasesize / 8;
1026 + adr += mtd->erasesize;
1027 + len -= mtd->erasesize;
1029 + if(adr >> sharp->chipshift){
1032 + if(chipnum>=sharp->numchips)
1037 + instr->state = MTD_ERASE_DONE;
1038 + mtd_erase_callback(instr);
1043 +static inline int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
1044 + unsigned long adr)
1047 + unsigned long timeo;
1049 + DECLARE_WAITQUEUE(wait, current);
1051 + sharp_send_cmd(map, CMD_READ_STATUS, adr);
1052 + status = map_read(map, adr);
1054 + timeo = jiffies + HZ * 10;
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) {
1063 + set_current_state(TASK_INTERRUPTIBLE);
1064 + add_wait_queue(&chip->wq, &wait);
1066 + spin_unlock_bh(chip->mutex);
1068 + schedule_timeout(1);
1071 + spin_lock_bh(chip->mutex);
1073 + remove_wait_queue(&chip->wq, &wait);
1074 + set_current_state(TASK_RUNNING);
1081 +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
1082 + unsigned long adr)
1087 + ret = sharp_wait(map,chip);
1092 + /* This seems like a good place to do an unlock */
1093 + sharp_unlock_oneblock(map,chip,adr);
1096 + sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
1097 + sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
1099 + chip->state = FL_ERASING;
1101 + ret = sharp_do_wait_for_ready(map,chip,adr);
1103 + spin_unlock_bh(chip->mutex);
1107 + sharp_send_cmd(map, CMD_READ_STATUS, adr);
1108 + status = map_read(map, adr);
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);
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);
1120 + sharp_release(chip);
1126 +static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
1127 + unsigned long adr)
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);
1134 + sharp_do_wait_for_ready(map,chip,adr);
1136 + status = map_read(map, adr);
1138 + if (!(status.x[0] & SR_ERRORS)) {
1139 + sharp_send_cmd(map, CMD_RESET, adr);
1140 + chip->state = FL_READY;
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);
1149 +static void sharp_sync(struct mtd_info *mtd)
1153 +static int sharp_suspend(struct mtd_info *mtd)
1155 + struct map_info *map = mtd->priv;
1156 + struct sharp_info *sharp = map->fldrv_priv;
1158 + struct flchip *chip;
1161 + for (i = 0; !ret && i < sharp->numchips; i++) {
1162 + chip = &sharp->chips[i];
1163 + ret = sharp_wait(map,chip);
1168 + chip->state = FL_PM_SUSPENDED;
1169 + spin_unlock_bh(chip->mutex);
1175 +static void sharp_resume(struct mtd_info *mtd)
1177 + struct map_info *map = mtd->priv;
1178 + struct sharp_info *sharp = map->fldrv_priv;
1180 + struct flchip *chip;
1182 + for (i = 0; i < sharp->numchips; i++) {
1183 + chip = &sharp->chips[i];
1185 + spin_lock_bh(chip->mutex);
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);
1194 + spin_unlock_bh(chip->mutex);
1198 +static void sharp_destroy(struct mtd_info *mtd)
1200 + struct map_info *map = mtd->priv;
1201 + struct sharp_info *sharp = map->fldrv_priv;
1206 +static int __init sharp_probe_init(void)
1208 + printk("MTD Sharp chip driver <ds@lineo.com>\n");
1210 + register_mtd_chip_driver(&sharp_chipdrv);
1215 +static void __exit sharp_probe_exit(void)
1217 + unregister_mtd_chip_driver(&sharp_chipdrv);
1220 +module_init(sharp_probe_init);
1221 +module_exit(sharp_probe_exit);
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
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
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 @@
1247 subdev->mtd->owner = THIS_MODULE;
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);
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
1262 module_param(ignore_cis_vcc, int, 0444);
1263 MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
1267 /* struct local_info::hw_priv */
1268 struct hostap_cs_priv {
1270 @@ -499,11 +499,13 @@
1272 PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
1273 p_dev->conf.IntType = INT_MEMORY_AND_IO;
1277 ret = prism2_config(p_dev);
1279 PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
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
1291 #include "hostap_ap.h"
1293 +extern int activar;
1295 /* #define final_version */
1297 @@ -1534,6 +1535,8 @@
1298 if (local->hw_downloading)
1303 if (prism2_hw_init(dev, initial)) {
1304 return local->no_pri ? 0 : 1;
1306 @@ -2665,8 +2668,15 @@
1310 - iface = netdev_priv(dev);
1311 - local = iface->local;
1313 + // Todos los parametros de entrada son correctos (no son nulos). De momento esta es la unica forma que conozco de detectar el problema.
1315 + printk("hostap_hw.c: INTERRUPT BEFORE DEVICE INIT!\n");
1316 + return IRQ_HANDLED;
1319 + iface = netdev_priv(dev);
1320 + local = iface->local;
1322 if(dev->base_addr == 0)
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
1330 #include "hostap_wlan.h"
1334 static char *dev_info = "hostap_pci";
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
1343 #include "hostap_wlan.h"
1347 static char *dev_info = "hostap_plx";
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
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 = {
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,
1374 /* sa11x0_pcmcia_init()
1377 static int __init sa11x0_pcmcia_init(void)
1379 - return driver_register(&sa11x0_pcmcia_driver);
1380 + return platform_driver_register(&sa11x0_pcmcia_driver);
1383 /* sa11x0_pcmcia_exit()
1386 static void __exit sa11x0_pcmcia_exit(void)
1388 - driver_unregister(&sa11x0_pcmcia_driver);
1389 + platform_driver_unregister(&sa11x0_pcmcia_driver);
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.
1402 + tristate "Locomo SPI master"
1403 + depends on SPI_MASTER && SHARP_LOCOMO && EXPERIMENTAL
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
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 ...
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
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;
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 *********************************************************/
1453 +static int locomommcspi_init(struct device *dev, irqreturn_t (*isr)(int, void*), void *mmc)
1456 + result=request_irq(IRQ_LOCOMO_CARDDETECT, isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "locomo-spi", mmc);
1460 +static void locomommcspi_exit(struct device *dev, void* mmc)
1462 + free_irq(IRQ_LOCOMO_CARDDETECT, mmc);
1465 +static int locomommcspi_getro(struct device *dev)
1467 + return locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT) > 0 ? 1 : 0;
1470 +static void locomommcspi_setpower(struct device *dev, unsigned int mask)
1472 + if(!mask && spidev->card_power)
1473 + locomospi_power(0);
1474 + else if( !spidev->card_power )
1475 + locomospi_power(1);
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,
1490 +/* Utility function **********************************************************/
1492 +static void locomospi_power(int on)
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);
1499 +static void locomospi_setclock(unsigned int div, unsigned int clock)
1501 + u16 r = ioread16(spidev->base+LOCOMO_SPIMD);
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;
1515 +// returns 1 if card ist present, 0 otherwise
1516 +static int locomospi_carddetect()
1518 + return (locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1;
1521 +static void locomospi_setcs(int high)
1524 + printk(KERN_DEBUG "locomospi: cs %d\n",high);
1525 + r = ioread16(spidev->base + LOCOMO_SPICT);
1527 + r |= LOCOMO_SPI_CS;
1529 + r &= ~LOCOMO_SPI_CS;
1530 + iowrite16(r, spidev->base + LOCOMO_SPICT);
1533 +static void locomospi_reg_open()
1536 + spidev->clock_div = DIV_64;
1537 + spidev->clock_base = CLOCK_18MHZ;
1538 + locomospi_power(1);
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);
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);
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);
1563 +static void locomospi_reg_release()
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);
1581 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
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;
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;
1598 + r = ioread16(spidev->base+LOCOMO_SPICT);
1599 + r &= ~LOCOMO_SPI_ALIGNEN;
1600 + iowrite16(r, spidev->base+LOCOMO_SPICT);
1602 + for(i=0; i< size; i++)
1603 + printk(KERN_DEBUG "locomospi: sent: %x received: %x \n",txbuffer[i], rxbuffer[i]);
1610 +static int tx(const char* txbuffer, int size)
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;
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);
1625 + for(i=0; i< size; i++)
1626 + printk(KERN_DEBUG "locomospi: sent: %x\n",txbuffer[i]);
1632 +static int rx(char* rxbuffer, int size)
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;
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);
1647 + for(i=0; i< size; i++)
1648 + printk(KERN_DEBUG "locomospi: received: %x \n", rxbuffer[i]);
1655 +static int txrx(const char* txbuffer, char* rxbuffer, int size)
1660 +/* char * txback = kmalloc(size * sizeof(char), GFP_KERNEL);
1661 + memcpy(txback, txbuffer, size);
1663 + if(spidev->clock_div == 4)
1668 +// printk(KERN_DEBUG "locomospi: txrx %d bytes to prozess\n",size);
1670 +// r = ioread16(spidev->base+LOCOMO_SPICT);
1671 +// r |= LOCOMO_SPI_ALIGNEN;
1672 +// iowrite16(r, spidev->base+LOCOMO_SPICT);
1673 + //discard first bogus byte
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)
1681 + iowrite8(txbuffer[i], spidev->base+LOCOMO_SPITD);
1684 + for(j=0; j <= wait; j++){
1685 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
1688 + rxbuffer[i] = ioread8(spidev->base+LOCOMO_SPIRD);
1691 +// r = ioread16(spidev->base+LOCOMO_SPICT);
1692 +// r &= ~LOCOMO_SPI_ALIGNEN;
1693 +// iowrite16(r, spidev->base+LOCOMO_SPICT);
1695 +/* for(j=0; j< size; j++)
1696 + printk(KERN_DEBUG "locomospi: sent: %x received: %x \n",txback[j], rxbuffer[j]);
1702 +static int tx(const char* buffer, int size)
1707 + if(spidev->clock_div == 4)
1711 + r = ioread16(spidev->base+LOCOMO_SPICT);
1712 + r &= ~LOCOMO_SPI_ALIGNEN;
1713 + iowrite16(r, spidev->base+LOCOMO_SPICT);
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)
1721 + iowrite8(buffer[i], spidev->base+LOCOMO_SPITD);
1725 + for(j=0; j <= wait; j++){
1726 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_TEND)
1730 + r = ioread16(spidev->base+LOCOMO_SPICT);
1731 + r |= LOCOMO_SPI_ALIGNEN;
1732 + iowrite16(r, spidev->base+LOCOMO_SPICT);
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);
1740 +static int rx(char* buffer, int size)
1745 + printk(KERN_DEBUG "locomospi: rx %d bytes to receive\n",size);
1746 + if(spidev->clock_div == 4)
1750 + r = ioread16(spidev->base+LOCOMO_SPICT);
1751 + r &= ~LOCOMO_SPI_ALIGNEN;
1752 + iowrite16(r, spidev->base+LOCOMO_SPICT);
1754 + for(i=0; i<size; i++){
1756 + for(j=0; j <= wait; j++){
1757 + if(ioread16(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)
1760 + buffer[i]= ioread8(spidev->base+LOCOMO_SPIRD);
1764 + r = ioread16(spidev->base+LOCOMO_SPICT);
1765 + r |= LOCOMO_SPI_ALIGNEN;
1766 + iowrite16(r, spidev->base+LOCOMO_SPICT);
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);
1775 +static irqreturn_t locomospi_rwready(int irq, void *dev_id)
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;
1784 +static irqreturn_t locomospi_testisr(int irq, void *dev_id)
1788 + case IRQ_LOCOMO_SPI_RFR: buf="RFR";
1790 + case IRQ_LOCOMO_SPI_RFW: buf="RFW";
1792 + case IRQ_LOCOMO_SPI_REND:buf="REND";
1794 + case IRQ_LOCOMO_SPI_TEND:buf="TEND";
1796 + case IRQ_LOCOMO_CARDDETECT:
1797 + buf="CARD_DETECT";
1799 + default: return IRQ_NONE;
1801 + printk(KERN_DEBUG "locomospi: IRQ: %s\n",buf);
1802 +// dev_dbg(&spidev->sdev->dev, "IRQ: %s\n",buf);
1803 + return IRQ_HANDLED;
1805 +static irqreturn_t locomospi_txrxisr(int irq, void *dev_id)
1807 + if(transfercount < transfersize){
1808 + transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1809 + iowrite8(transtxbuf[transfercount], spidev->base+LOCOMO_SPITD);
1812 + /* transfer complete. wake up txrx */
1813 + wake_up(&transferqueue);
1815 + return IRQ_HANDLED;
1818 +static irqreturn_t locomospi_txisr(int irq, void *dev_id)
1820 + if(transfercount < transfersize){
1821 + iowrite8(transtxbuf[transfercount++], spidev->base+LOCOMO_SPITD);
1824 + /* transfer complete. wake up txrx */
1825 + wake_up(&transferqueue);
1827 + return IRQ_HANDLED;
1830 +static irqreturn_t locomospi_rxisr(int irq, void *dev_id)
1832 + if(transfercount < transfersize){
1833 + transrxbuf[transfercount++] = ioread8(spidev->base+LOCOMO_SPIRD);
1836 + /* transfer complete. wake up txrx */
1837 + wake_up(&transferqueue);
1839 + return IRQ_HANDLED;
1842 +static void locomospi_clock(unsigned int Hz)
1845 + printk(KERN_DEBUG "locomospi: changing clock to: %d\n", Hz);
1847 + r = ioread16(spidev->base+LOCOMO_SPIMD);
1848 + r &= ~LOCOMO_SPI_XON;
1849 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1956 + spidev->clock = Hz;
1959 +/* sysfs attributes used for debug *******************************************/
1961 +/* SPI registers */
1962 +ssize_t locomospi_showspimd(struct device_driver *drv, char *buf)
1964 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIMD));
1967 +ssize_t locomospi_storespimd(struct device_driver *drv, const char *buf, size_t count)
1969 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIMD);
1972 +static DRIVER_ATTR(spimd, S_IWUSR | S_IRUGO, locomospi_showspimd, locomospi_storespimd);
1974 +ssize_t locomospi_showspict(struct device_driver *drv, char *buf)
1976 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPICT));
1979 +ssize_t locomospi_storespict(struct device_driver *drv, const char *buf, size_t count)
1981 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPICT);
1984 +static DRIVER_ATTR(spict, S_IWUSR | S_IRUGO, locomospi_showspict, locomospi_storespict);
1986 +ssize_t locomospi_showspist(struct device_driver *drv, char *buf)
1988 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIST));
1991 +ssize_t locomospi_storespist(struct device_driver *drv, const char *buf, size_t count)
1993 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIST);
1996 +static DRIVER_ATTR(spist, S_IWUSR | S_IRUGO, locomospi_showspist, locomospi_storespist);
1998 +ssize_t locomospi_showspitd(struct device_driver *drv, char *buf)
2000 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITD));
2003 +ssize_t locomospi_storespitd(struct device_driver *drv, const char *buf, size_t count)
2005 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITD);
2008 +static DRIVER_ATTR(spitd, S_IWUSR | S_IRUGO, locomospi_showspitd, locomospi_storespitd);
2010 +ssize_t locomospi_showspird(struct device_driver *drv, char *buf)
2012 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRD));
2015 +ssize_t locomospi_storespird(struct device_driver *drv, const char *buf, size_t count)
2017 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRD);
2020 +static DRIVER_ATTR(spird, S_IWUSR | S_IRUGO, locomospi_showspird, locomospi_storespird);
2022 +ssize_t locomospi_showspits(struct device_driver *drv, char *buf)
2024 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPITS));
2027 +ssize_t locomospi_storespits(struct device_driver *drv, const char *buf, size_t count)
2029 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITS);
2032 +static DRIVER_ATTR(spits, S_IWUSR | S_IRUGO, locomospi_showspits, locomospi_storespits);
2034 +ssize_t locomospi_showspirs(struct device_driver *drv, char *buf)
2036 + return sprintf(buf, "0x%x\n", ioread16(spidev->base+LOCOMO_SPIRS));
2039 +ssize_t locomospi_storespirs(struct device_driver *drv, const char *buf, size_t count)
2041 + iowrite16(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRS);
2044 +static DRIVER_ATTR(spirs, S_IWUSR | S_IRUGO, locomospi_showspirs, locomospi_storespirs);
2046 +/* MMC Card status */
2048 +ssize_t locomospi_showpower(struct device_driver *drv, char *buf)
2050 + return sprintf(buf, "%d\n", spidev->card_power);
2053 +ssize_t locomospi_storepower(struct device_driver *drv, const char *buf, size_t count)
2055 + locomospi_power(simple_strtoul(buf, NULL, 10));
2058 +static DRIVER_ATTR(cardpower, S_IWUSR | S_IRUGO, locomospi_showpower, locomospi_storepower);
2060 +ssize_t locomospi_detectcard(struct device_driver *drv, char *buf)
2062 + return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1);
2064 +static DRIVER_ATTR(carddetect, S_IRUGO, locomospi_detectcard, NULL);
2066 +ssize_t locomospi_writeprotect(struct device_driver *drv, char *buf)
2068 + return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROT)>0)?1:0);
2070 +static DRIVER_ATTR(cardwriteprotect, S_IRUGO, locomospi_writeprotect, NULL);
2073 +ssize_t locomospi_showclock(struct device_driver *drv, char *buf)
2075 + return sprintf(buf, "%d\n", spidev->clock);
2078 +ssize_t locomospi_storeclock(struct device_driver *drv, const char *buf, size_t count)
2080 + locomospi_clock(simple_strtoul(buf, NULL, 10));
2083 +static DRIVER_ATTR(clock, S_IWUSR | S_IRUGO, locomospi_showclock, locomospi_storeclock);
2086 +ssize_t locomospi_showdelay(struct device_driver *drv, char *buf)
2088 + return sprintf(buf, "%d\n", delay);
2091 +ssize_t locomospi_storedelay(struct device_driver *drv, const char *buf, size_t count)
2093 + delay=simple_strtoul(buf,NULL,10);
2096 +static DRIVER_ATTR(delay, S_IWUSR | S_IRUGO, locomospi_showdelay, locomospi_storedelay);
2098 +ssize_t locomospi_reset(struct device_driver *drv, const char *buf, size_t count)
2100 + int choice = simple_strtoul(buf, NULL, 10);
2104 + case 0: locomospi_reg_release();
2105 + schedule_timeout(2*HZ);
2106 + locomospi_reg_open();
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);
2113 + locomospi_setcs(0);
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);
2124 + r = ioread16(spidev->base+LOCOMO_SPIMD);
2125 + r |= LOCOMO_SPI_LOOPBACK;
2126 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
2128 + txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
2132 + schedule_timeout(HZ);
2133 + txrx("abcdefghijklmnopqrstuvwxyz1234567890",buff,36);
2135 + r = ioread16(spidev->base+LOCOMO_SPIMD);
2136 + r &= ~LOCOMO_SPI_LOOPBACK;
2137 + iowrite16(r, spidev->base+LOCOMO_SPIMD);
2139 + default: /* do nothing */;
2143 +static DRIVER_ATTR(reset, S_IWUSR, NULL, locomospi_reset);
2145 +typedef struct locomo_reg_entry {
2148 +} locomo_reg_entry_t;
2149 +#define LCM (sizeof(locomo_regs)/sizeof(locomo_reg_entry_t))
2150 +static locomo_reg_entry_t locomo_regs[] =
2152 +/* { addr, name, description } */
2157 + { 0x10, "MCSX0" },
2158 + { 0x14, "MCSX1" },
2159 + { 0x18, "MCSX2" },
2160 + { 0x1C, "MCSX3" },
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" },
2197 + { 0xdc, "LTINT" },
2204 +static ssize_t lcm_show(struct device *dev, struct device_attribute *attr, char *buf)
2206 + int base = spidev->base - LOCOMO_SPI;
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));
2214 + return sprintf(buf,"%s",b);
2217 +static DRIVER_ATTR(regs, 0444, lcm_show, NULL);
2220 +/* SPI functions *************************************************************/
2222 +static void locomospi_do_transfer(struct work_struct *wrk)
2224 + struct list_head *mptr, *tptr, *mptr2;
2225 + struct spi_transfer *entry;
2226 + struct spi_message *msg;
2228 + list_for_each_safe(mptr, mptr2, &spidev->message_list){
2229 + msg = list_entry(mptr, struct spi_message, queue);
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;
2249 + spin_lock(&spidev->message_lock);
2251 + spin_unlock(&spidev->message_lock);
2252 + msg->complete(msg->context);
2256 +static int locomospi_setup(struct spi_device *spi)
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);
2263 + spidev->spimode = spi->mode;
2268 +static int locomospi_transfer(struct spi_device *spi, struct spi_message *msg)
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);
2278 +static struct locomo_driver locomo_spi_driver = {
2280 + .name = "locomo-spi",
2282 + .devid = LOCOMO_DEVID_SPI,
2283 + .probe = locomospi_probe,
2284 + .remove = locomospi_remove,
2286 + .suspend = locomospi_suspend,
2287 + .resume = locomospi_resume,
2291 +static struct spi_board_info board = {
2292 + .modalias = "mmc_spi",
2293 + .platform_data = (void*) &colliemmc,
2294 + .controller_data= NULL,
2296 + .max_speed_hz = 25000000,
2303 +static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state)
2305 + disable_irq(IRQ_LOCOMO_CARDDETECT);
2309 +static int locomospi_resume(struct locomo_dev *dev)
2311 + enable_irq(IRQ_LOCOMO_CARDDETECT);
2316 +static int locomospi_probe(struct locomo_dev *dev)
2319 + printk(KERN_DEBUG "Collie MMC over SPI Driver\n");
2320 + spidev=kmalloc(sizeof(struct locomospi_dev),GFP_KERNEL);
2324 + spidev->ldev = dev;
2325 + spidev->card_power = 1;
2326 + spidev->spimode = 0;
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");
2332 + spidev->base=(unsigned long) dev->mapbase;
2333 + locomospi_reg_open();
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);
2339 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardpower);
2341 + dev_err(&dev->dev, "error creating driver attribute\n");
2344 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_carddetect);
2346 + dev_err(&dev->dev,"error creating driver attribute\n");
2349 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardwriteprotect);
2351 + dev_err(&dev->dev, "error creating driver attribute\n");
2354 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spimd);
2356 + dev_err(&dev->dev, "error creating driver attribute\n");
2359 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spict);
2361 + dev_err(&dev->dev, "error creating driver attribute\n");
2364 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spist);
2366 + dev_err(&dev->dev, "error creating driver attribute\n");
2369 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spitd);
2371 + dev_err(&dev->dev, "error creating driver attribute\n");
2374 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spird);
2376 + dev_err(&dev->dev, "error creating driver attribute\n");
2379 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spits);
2381 + dev_err(&dev->dev, "error creating driver attribute\n");
2384 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spirs);
2386 + dev_err(&dev->dev, "error creating driver attribute\n");
2389 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_clock);
2391 + dev_err(&dev->dev, "error creating driver attribute\n");
2394 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_delay);
2396 + dev_err(&dev->dev, "error creating driver attribute\n");
2399 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_reset);
2401 + dev_err(&dev->dev, "error creating driver attribute\n");
2404 + result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_regs);
2406 + dev_err(&dev->dev, "error creating driver attribute\n");
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){
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");
2428 +/* result=request_irq(IRQ_LOCOMO_SPI_RFR, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2430 + dev_err(&dev->dev, "Could not get IRQ: RFR\n");
2433 + //disable_irq(IRQ_LOCOMO_SPI_RFR);
2434 +*//* result=request_irq(IRQ_LOCOMO_SPI_RFW, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2436 + dev_err(&dev->dev, "Could not get IRQ: RFW\n");
2439 + //disable_irq(IRQ_LOCOMO_SPI_RFW);
2440 +*//* result=request_irq(IRQ_LOCOMO_SPI_REND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2442 + dev_err(&dev->dev, "Could not get IRQ: REND\n");
2445 +*//* result=request_irq(IRQ_LOCOMO_SPI_TEND, locomospi_testisr, IRQF_SHARED, "locomo-spi", (void*) spidev);
2447 + dev_err(&dev->dev, "Could not get IRQ: TEND\n");
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");
2456 + result=spi_register_master(spidev->master);
2458 + dev_err(&dev->dev, "failed to register spimaster\n");
2463 + destroy_workqueue(spidev->workqueue);
2465 +// free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev);
2467 +// free_irq(IRQ_LOCOMO_SPI_REND, (void*) spidev);
2469 +// free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev);
2471 +// free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev);
2473 + spi_unregister_device(spidev->sdev);
2475 + spi_master_put(spidev->master);
2477 + release_mem_region((unsigned long) dev->mapbase, dev->length);
2483 +static int locomospi_remove(struct locomo_dev *dev)
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);
2501 +static int __init locomospi_init(void)
2503 + int ret = locomo_driver_register(&locomo_spi_driver);
2511 +static void __exit locomospi_exit(void)
2513 + locomo_driver_unregister(&locomo_spi_driver);
2516 +module_init(locomospi_init);
2517 +module_exit(locomospi_exit);
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
2527 +#include <asm/hardware/locomo.h>
2528 +#ifndef __LOCOMO_SPI_H__
2529 +#define __LOCOMO_SPI_H__
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 */
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 */
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 */
2569 +#define IRQ_LOCOMO_CARDDETECT IRQ_LOCOMO_GPIO13
2572 +struct locomospi_dev {
2573 + struct locomo_dev *ldev;
2574 + struct spi_master *master;
2575 + struct spi_device *sdev;
2580 + unsigned long base;
2582 + wait_queue_head_t waitqueue;
2583 + struct workqueue_struct *workqueue;
2584 + struct list_head message_list;
2585 + spinlock_t message_lock;
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);