http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / kernel / linux / arch / arm / mach-sa1100 / stork.c
1 /*
2  * linux/arch/arm/mach-sa1100/stork.c
3  *
4  *     Copyright (C) 2001 Ken Gordon
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/tty.h>
15 #include <linux/delay.h>
16
17 #include <asm/hardware.h>
18 #include <asm/setup.h>
19 #include <asm/keyboard.h>
20
21 #include <asm/mach/arch.h>
22 #include <asm/mach/map.h>
23 #include <asm/mach/serial_sa1100.h>
24 #include <linux/serial_core.h>
25
26 #include "generic.h"
27
28
29 #define STORK_VM_BASE_CS1 0xf0000000            /* where we get mapped (virtual) */
30 #define STORK_VM_OFF_CS1 0x08000000             /* where we started mapping (physical) */
31 #define STORK_VM_ADJUST_CS1 (STORK_VM_BASE_CS1-STORK_VM_OFF_CS1) /* add to the phys to get virt */
32
33 #define STORK_VM_BASE_CS2 0xf1000000            /* where we get mapped (virtual) */
34 #define STORK_VM_OFF_CS2  0x10000000             /* where we started mapping (physical) */
35 #define STORK_VM_ADJUST_CS2 (STORK_VM_BASE_CS2-STORK_VM_OFF_CS2) /* add to the phys to get virt */
36
37 static int debug = 0;
38
39 static int storkLatchA = 0;
40 static int storkLatchB = 0;
41 static int storkLCDCPLD[4] = { 0, 0, 0, 0};
42
43 int
44 storkSetLatchA(int bits)
45 {
46     int ret = storkLatchA;
47     volatile unsigned int *latch = (unsigned int *)(STORK_LATCH_A_ADDR+STORK_VM_ADJUST_CS1);
48
49     storkLatchA |= bits;
50     *latch = storkLatchA;
51     return ret;
52 }
53
54 int
55 storkClearLatchA(int bits)
56 {
57     int ret = storkLatchA;
58     volatile unsigned int *latch = (unsigned int *)(STORK_LATCH_A_ADDR+STORK_VM_ADJUST_CS1);
59
60     storkLatchA &= ~bits;
61     *latch = storkLatchA;
62     return ret;
63 }
64
65 int
66 storkSetLCDCPLD(int which, int bits)
67 {
68     int ret = storkLCDCPLD[which];
69     volatile unsigned int *latch = (unsigned int *)(STORK_LCDCPLD_BASE_ADDR+STORK_VM_ADJUST_CS2 + 0x20*which);
70
71     storkLCDCPLD[which] |= bits;
72     *latch = storkLCDCPLD[which];
73     return ret;
74 }
75
76
77 /* NB we don't shadow these 'cos there is no relation between the data written and the data read */
78 /* ie the read registers are read only and the write registers write only */
79
80 int
81 storkGetLCDCPLD(int which)
82 {
83     volatile unsigned int *latch = (unsigned int *)(STORK_LCDCPLD_BASE_ADDR+STORK_VM_ADJUST_CS2 + 0x20*which);
84     return *latch;
85 }
86
87 int
88 storkClearLCDCPLD(int which, int bits)
89 {
90     int ret = storkLCDCPLD[which];
91     volatile unsigned int *latch = (unsigned int *)(STORK_LCDCPLD_BASE_ADDR+STORK_VM_ADJUST_CS2 + 0x20*which);
92
93     storkLCDCPLD[which] &= ~bits;
94     *latch = storkLCDCPLD[which];
95     return ret;
96 }
97
98 int
99 storkSetLatchB(int bits)
100 {
101     int ret = storkLatchB;
102     char buf[100];
103
104     volatile unsigned int *latch = (unsigned int *)(STORK_LATCH_B_ADDR+STORK_VM_ADJUST_CS1);
105     sprintf(buf, "%s: bits %04x\n", __FUNCTION__, bits);
106     if (debug) printk(buf);
107
108     storkLatchB |= bits;
109     *latch = storkLatchB;
110     return ret;
111 }
112
113 int
114 storkClearLatchB(int bits)
115 {
116     int ret = storkLatchB;
117     char buf[100];
118
119     volatile unsigned int *latch = (unsigned int *)(STORK_LATCH_B_ADDR+STORK_VM_ADJUST_CS1);
120     sprintf(buf, "%s: bits %04x\n", __FUNCTION__, bits);
121     if (debug) printk(buf);
122
123     storkLatchB &= ~bits;
124     *latch = storkLatchB;
125     return ret;
126 }
127
128 void
129 storkSetGPIO(int bits)
130 {
131     char buf[100];
132
133     sprintf(buf, "%s: bits %04x\n", __FUNCTION__, bits);
134     if (debug) printk(buf);
135     GPSR = bits;
136 }
137
138 void
139 storkClearGPIO(int bits)
140 {
141     char buf[100];
142
143     sprintf(buf, "%s: bits %04x\n", __FUNCTION__, bits);
144     if (debug) printk(buf);
145     GPCR = bits;
146 }
147
148 int
149 storkGetGPIO()
150 {
151     char buf[100];
152
153     int bits = GPLR;
154
155     sprintf(buf, "%s: bits %04x\n", __FUNCTION__, bits);
156     if (debug) printk(buf);
157
158     return bits;
159 }
160
161 /* this will return the current state of the hardware ANDED with the given bits
162    so NE => at least one bit was set, but maybe not all of them! */
163
164 int
165 storkTestGPIO(int bits)
166 {
167     int val = storkGetGPIO();
168     char buf[100];
169
170     sprintf(buf, "%s: bits %04x val %04x\n", __FUNCTION__, bits, val);
171     if (debug) printk(buf);
172
173     return (val & bits);
174 }
175
176 /* NB the touch screen and the d to a use the same data and clock out pins */
177
178 static void storkClockTS(void)
179 {
180     storkSetLatchB(STORK_TOUCH_SCREEN_DCLK);
181     udelay(10);                  /* hmm wait 200ns (min) - ok this ought to be udelay(1) but that doesn't get */
182                                  /* consistent values so I'm using 10 (urgh) */
183     storkClearLatchB(STORK_TOUCH_SCREEN_DCLK);
184     udelay(10);
185 }
186
187
188 int                             /* there is always a 12 bit read after the write! */
189 storkClockByteToTS(int byte)
190 {
191     int timeout = 10000;   /* stuff is meant to happen in 60ns */
192     int bit;
193     int result = 0;
194
195     if (debug) printk("storkClockByteToTS: %02x\n", byte);
196
197     storkClearLatchB(STORK_TOUCH_SCREEN_CS);  /* slect touch screen */
198
199     while (timeout-- > 0)
200         if (storkTestGPIO(GPIO_STORK_TOUCH_SCREEN_BUSY) == 0)
201             break;
202
203     if (timeout < 0) {
204         printk("storkClockBitToTS: GPIO_STORK_TOUCH_SCREEN_BUSY didn't go low!\n\r");
205 /* ignore error for now        return; */
206     }
207
208 /* clock out the given byte */
209
210     for (bit = 0x80; bit > 0; bit = bit >> 1) {
211
212         if ((bit & byte) == 0)
213             storkClearLatchB(STORK_TOUCH_SCREEN_DIN);
214         else
215             storkSetLatchB(STORK_TOUCH_SCREEN_DIN);
216
217         storkClockTS();
218     }
219
220     storkClockTS();  /* will be busy for at a clock  (at least) */
221
222     for (timeout = 10000; timeout >= 0; timeout--)
223         if (storkTestGPIO(GPIO_STORK_TOUCH_SCREEN_BUSY) == 0)
224             break;
225
226     if (timeout < 0) {
227         printk("storkClockBitToTS: 2nd GPIO_STORK_TOUCH_SCREEN_BUSY didn't go low!\n\r");
228 /* ignore error for now        return; */
229     }
230
231 /* clock in the result */
232
233     for (bit = 0x0800; bit > 0; bit = bit >> 1) {
234
235         if (storkTestGPIO(GPIO_STORK_TOUCH_SCREEN_DATA))
236             result |= bit;
237
238         storkClockTS();
239     }
240
241     storkSetLatchB(STORK_TOUCH_SCREEN_CS);  /* unselect touch screen */
242
243     return result;
244 }
245
246 void
247 storkClockShortToDtoA(int word)
248 {
249     int bit;
250
251     storkClearLatchB(STORK_DA_CS);  /* select D to A */
252
253 /* clock out the given byte */
254
255     for (bit = 0x8000; bit > 0; bit = bit >> 1) {
256
257         if ((bit & word) == 0)
258             storkClearLatchB(STORK_TOUCH_SCREEN_DIN);
259         else
260             storkSetLatchB(STORK_TOUCH_SCREEN_DIN);
261
262         storkClockTS();
263     }
264
265     storkSetLatchB(STORK_DA_CS);  /* unselect D to A */
266
267 /* set DTOA#_LOAD low then high (min 20ns) to transfer value to D to A */
268     storkClearLatchB(STORK_DA_LD);
269     storkSetLatchB(STORK_DA_LD);
270 }
271
272
273
274 void
275 storkInitTSandDtoA(void)
276 {
277     storkClearLatchB(STORK_TOUCH_SCREEN_DCLK | STORK_TOUCH_SCREEN_DIN);
278     storkSetLatchB(STORK_TOUCH_SCREEN_CS | STORK_DA_CS | STORK_DA_LD);
279     storkClockByteToTS(0xE2);           /* turn on the reference */
280     storkClockShortToDtoA(0x8D00);      /* turn on the contrast */
281     storkClockShortToDtoA(0x0A00);      /* turn on the brightness */
282 }
283
284 static void stork_lcd_power(int on)
285 {
286         if (on) {
287                 storkSetLCDCPLD(0, 1);
288                 storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
289         } else {
290                 storkSetLCDCPLD(0, 0);
291                 storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
292         }
293 }
294
295 struct map_desc stork_io_desc[] __initdata = {
296  /* virtual     physical    length      type */
297   { STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, MT_DEVICE }, /* EGPIO 0 */
298   { 0xf1000000, 0x10000000, 0x02800000, MT_DEVICE }, /* static memory bank 2 */
299   { 0xf3800000, 0x40000000, 0x00800000, MT_DEVICE }  /* static memory bank 4 */
300 };
301
302 int __init
303 stork_map_io(void)
304 {
305     sa1100_map_io();
306     iotable_init(stork_io_desc, ARRAY_SIZE(stork_io_desc));
307
308     sa1100_register_uart(0, 1); /* com port */
309     sa1100_register_uart(1, 2);
310     sa1100_register_uart(2, 3);
311
312     printk("Stork driver initing latches\r\n");
313
314     storkClearLatchB(STORK_RED_LED);    /* let's have the red LED on please */
315     storkSetLatchB(STORK_YELLOW_LED);
316     storkSetLatchB(STORK_GREEN_LED);
317     storkSetLatchA(STORK_BATTERY_CHARGER_ON);
318     storkSetLatchA(STORK_LCD_5V_POWER_ON);
319     storkSetLatchA(STORK_LCD_3V3_POWER_ON);
320
321     storkInitTSandDtoA();
322
323     sa1100fb_lcd_power = stork_lcd_power;
324
325     return 0;
326 }
327
328
329 MACHINE_START(STORK, "Stork Technologies prototype")
330         BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
331         BOOT_PARAMS(0xc0000100)
332         MAPIO(stork_map_io)
333         INITIRQ(sa1100_init_irq)
334         INITTIME(sa1100_init_time)
335 MACHINE_END
336
337
338 EXPORT_SYMBOL(storkTestGPIO);
339 EXPORT_SYMBOL(storkSetGPIO);
340 EXPORT_SYMBOL(storkClearGPIO);
341 EXPORT_SYMBOL(storkSetLatchA);
342 EXPORT_SYMBOL(storkClearLatchA);
343 EXPORT_SYMBOL(storkSetLatchB);
344 EXPORT_SYMBOL(storkClearLatchB);
345 EXPORT_SYMBOL(storkClockByteToTS);
346 EXPORT_SYMBOL(storkClockShortToDtoA);
347 EXPORT_SYMBOL(storkGetLCDCPLD);
348 EXPORT_SYMBOL(storkSetLCDCPLD);