ARM: iPAQ: convert H3100 IrDA to use generic gpio support
[safe/jmp/linux-2.6] / arch / arm / mach-sa1100 / h3600.c
1 /*
2  * Hardware definitions for Compaq iPAQ H3xxx Handheld Computers
3  *
4  * Copyright 2000,1 Compaq Computer Corporation.
5  *
6  * Use consistent with the GNU GPL is permitted,
7  * provided that this copyright notice is
8  * preserved in its entirety in all copies and derived works.
9  *
10  * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
11  * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
12  * FITNESS FOR ANY PARTICULAR PURPOSE.
13  *
14  * Author: Jamey Hicks.
15  *
16  * History:
17  *
18  * 2001-10-??   Andrew Christian   Added support for iPAQ H3800
19  *                                 and abstracted EGPIO interface.
20  *
21  */
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/tty.h>
26 #include <linux/pm.h>
27 #include <linux/device.h>
28 #include <linux/mtd/mtd.h>
29 #include <linux/mtd/partitions.h>
30 #include <linux/serial_core.h>
31 #include <linux/gpio.h>
32
33 #include <asm/irq.h>
34 #include <mach/hardware.h>
35 #include <asm/mach-types.h>
36 #include <asm/setup.h>
37
38 #include <asm/mach/irq.h>
39 #include <asm/mach/arch.h>
40 #include <asm/mach/flash.h>
41 #include <asm/mach/irda.h>
42 #include <asm/mach/map.h>
43 #include <asm/mach/serial_sa1100.h>
44
45 #include <mach/h3600.h>
46 #include <mach/h3600_gpio.h>
47
48 #include "generic.h"
49
50 void (*assign_h3600_egpio)(enum ipaq_egpio_type x, int level);
51 EXPORT_SYMBOL(assign_h3600_egpio);
52
53 struct gpio_default_state {
54         int gpio;
55         int mode;
56         const char *name;
57 };
58
59 #define GPIO_MODE_IN    -1
60 #define GPIO_MODE_OUT0  0
61 #define GPIO_MODE_OUT1  1
62
63 static void h3xxx_init_gpio(struct gpio_default_state *s, size_t n)
64 {
65         while (n--) {
66                 const char *name = s->name;
67                 int err;
68
69                 if (!name)
70                         name = "[init]";
71                 err = gpio_request(s->gpio, name);
72                 if (err) {
73                         printk(KERN_ERR "gpio%u: unable to request: %d\n",
74                                 s->gpio, err);
75                         continue;
76                 }
77                 if (s->mode >= 0) {
78                         err = gpio_direction_output(s->gpio, s->mode);
79                 } else {
80                         err = gpio_direction_input(s->gpio);
81                 }
82                 if (err) {
83                         printk(KERN_ERR "gpio%u: unable to set direction: %d\n",
84                                 s->gpio, err);
85                         continue;
86                 }
87                 if (!s->name)
88                         gpio_free(s->gpio);
89                 s++;
90         }
91 }
92
93
94 static struct mtd_partition h3xxx_partitions[] = {
95         {
96                 .name           = "H3XXX boot firmware",
97                 .size           = 0x00040000,
98                 .offset         = 0,
99                 .mask_flags     = MTD_WRITEABLE,  /* force read-only */
100         }, {
101                 .name           = "H3XXX rootfs",
102                 .size           = MTDPART_SIZ_FULL,
103                 .offset         = 0x00040000,
104         }
105 };
106
107 static void h3xxx_set_vpp(int vpp)
108 {
109         assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
110 }
111
112 static struct flash_platform_data h3xxx_flash_data = {
113         .map_name       = "cfi_probe",
114         .set_vpp        = h3xxx_set_vpp,
115         .parts          = h3xxx_partitions,
116         .nr_parts       = ARRAY_SIZE(h3xxx_partitions),
117 };
118
119 static struct resource h3xxx_flash_resource = {
120         .start          = SA1100_CS0_PHYS,
121         .end            = SA1100_CS0_PHYS + SZ_32M - 1,
122         .flags          = IORESOURCE_MEM,
123 };
124
125 static void h3xxx_mach_init(void)
126 {
127         sa11x0_register_mtd(&h3xxx_flash_data, &h3xxx_flash_resource, 1);
128 }
129
130 /*
131  * low-level UART features
132  */
133
134 static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
135 {
136         if (port->mapbase == _Ser3UTCR0) {
137                 if (mctrl & TIOCM_RTS)
138                         GPCR = GPIO_H3600_COM_RTS;
139                 else
140                         GPSR = GPIO_H3600_COM_RTS;
141         }
142 }
143
144 static u_int h3600_uart_get_mctrl(struct uart_port *port)
145 {
146         u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
147
148         if (port->mapbase == _Ser3UTCR0) {
149                 int gplr = GPLR;
150                 /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
151                 if (gplr & GPIO_H3600_COM_DCD)
152                         ret &= ~TIOCM_CD;
153                 if (gplr & GPIO_H3600_COM_CTS)
154                         ret &= ~TIOCM_CTS;
155         }
156
157         return ret;
158 }
159
160 static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
161 {
162         if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */
163                 assign_h3600_egpio(IPAQ_EGPIO_IR_ON, !state);
164         } else if (port->mapbase == _Ser3UTCR0) {
165                 assign_h3600_egpio(IPAQ_EGPIO_RS232_ON, !state);
166         }
167 }
168
169 /*
170  * Enable/Disable wake up events for this serial port.
171  * Obviously, we only support this on the normal COM port.
172  */
173 static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
174 {
175         int err = -EINVAL;
176
177         if (port->mapbase == _Ser3UTCR0) {
178                 if (enable)
179                         PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */
180                 else
181                         PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
182                 err = 0;
183         }
184         return err;
185 }
186
187 static struct sa1100_port_fns h3600_port_fns __initdata = {
188         .set_mctrl      = h3600_uart_set_mctrl,
189         .get_mctrl      = h3600_uart_get_mctrl,
190         .pm             = h3600_uart_pm,
191         .set_wake       = h3600_uart_set_wake,
192 };
193
194 /*
195  * helper for sa1100fb
196  */
197 static void h3xxx_lcd_power(int enable)
198 {
199         assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER, enable);
200 }
201
202 static struct map_desc h3600_io_desc[] __initdata = {
203         {       /* static memory bank 2  CS#2 */
204                 .virtual        =  H3600_BANK_2_VIRT,
205                 .pfn            = __phys_to_pfn(SA1100_CS2_PHYS),
206                 .length         = 0x02800000,
207                 .type           = MT_DEVICE
208         }, {    /* static memory bank 4  CS#4 */
209                 .virtual        =  H3600_BANK_4_VIRT,
210                 .pfn            = __phys_to_pfn(SA1100_CS4_PHYS),
211                 .length         = 0x00800000,
212                 .type           = MT_DEVICE
213         }, {    /* EGPIO 0              CS#5 */
214                 .virtual        =  H3600_EGPIO_VIRT,
215                 .pfn            = __phys_to_pfn(H3600_EGPIO_PHYS),
216                 .length         = 0x01000000,
217                 .type           = MT_DEVICE
218         }
219 };
220
221 /*
222  * Common map_io initialization
223  */
224
225 static void __init h3xxx_map_io(void)
226 {
227         sa1100_map_io();
228         iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
229
230         sa1100_register_uart_fns(&h3600_port_fns);
231         sa1100_register_uart(0, 3); /* Common serial port */
232 //      sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
233
234         /* Ensure those pins are outputs and driving low  */
235         PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
236         PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
237
238         /* Configure suspend conditions */
239         PGSR = 0;
240         PWER = PWER_GPIO0 | PWER_RTC;
241         PCFR = PCFR_OPDE;
242         PSDR = 0;
243
244         sa1100fb_lcd_power = h3xxx_lcd_power;
245 }
246
247 /************************* H3100 *************************/
248
249 #ifdef CONFIG_SA1100_H3100
250
251 #define H3100_EGPIO     (*(volatile unsigned int *)H3600_EGPIO_VIRT)
252 static unsigned int h3100_egpio = 0;
253
254 static void h3100_control_egpio(enum ipaq_egpio_type x, int setp)
255 {
256         unsigned int egpio = 0;
257         long         gpio = 0;
258         unsigned long flags;
259
260         switch (x) {
261         case IPAQ_EGPIO_LCD_POWER:
262                 egpio |= EGPIO_H3600_LCD_ON;
263                 gpio  |= GPIO_H3100_LCD_3V_ON;
264                 break;
265         case IPAQ_EGPIO_LCD_ENABLE:
266                 break;
267         case IPAQ_EGPIO_CODEC_NRESET:
268                 egpio |= EGPIO_H3600_CODEC_NRESET;
269                 break;
270         case IPAQ_EGPIO_AUDIO_ON:
271                 gpio |= GPIO_H3100_AUD_PWR_ON
272                         | GPIO_H3100_AUD_ON;
273                 break;
274         case IPAQ_EGPIO_QMUTE:
275                 gpio |= GPIO_H3100_QMUTE;
276                 break;
277         case IPAQ_EGPIO_OPT_NVRAM_ON:
278                 egpio |= EGPIO_H3600_OPT_NVRAM_ON;
279                 break;
280         case IPAQ_EGPIO_OPT_ON:
281                 egpio |= EGPIO_H3600_OPT_ON;
282                 break;
283         case IPAQ_EGPIO_CARD_RESET:
284                 egpio |= EGPIO_H3600_CARD_RESET;
285                 break;
286         case IPAQ_EGPIO_OPT_RESET:
287                 egpio |= EGPIO_H3600_OPT_RESET;
288                 break;
289         case IPAQ_EGPIO_IR_ON:
290                 gpio |= GPIO_H3100_IR_ON;
291                 break;
292         case IPAQ_EGPIO_IR_FSEL:
293                 gpio |= GPIO_H3100_IR_FSEL;
294                 break;
295         case IPAQ_EGPIO_RS232_ON:
296                 egpio |= EGPIO_H3600_RS232_ON;
297                 break;
298         case IPAQ_EGPIO_VPP_ON:
299                 egpio |= EGPIO_H3600_VPP_ON;
300                 break;
301         }
302
303         if (egpio || gpio) {
304                 local_irq_save(flags);
305                 if (setp) {
306                         h3100_egpio |= egpio;
307                         GPSR = gpio;
308                 } else {
309                         h3100_egpio &= ~egpio;
310                         GPCR = gpio;
311                 }
312                 H3100_EGPIO = h3100_egpio;
313                 local_irq_restore(flags);
314         }
315 }
316
317 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON      \
318                           | GPIO_H3100_GPIO3      \
319                           | GPIO_H3100_QMUTE      \
320                           | GPIO_H3100_LCD_3V_ON  \
321                           | GPIO_H3100_AUD_ON     \
322                           | GPIO_H3100_AUD_PWR_ON \
323                           | GPIO_H3100_IR_ON      \
324                           | GPIO_H3100_IR_FSEL)
325
326 static void __init h3100_map_io(void)
327 {
328         h3xxx_map_io();
329
330         /* Initialize h3100-specific values here */
331         GPCR = 0x0fffffff;       /* All outputs are set low by default */
332         GPDR = GPIO_H3600_COM_RTS  | GPIO_H3600_L3_CLOCK |
333                GPIO_H3600_L3_MODE  | GPIO_H3600_L3_DATA  |
334                GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
335                H3100_DIRECT_EGPIO;
336
337         /* Older bootldrs put GPIO2-9 in alternate mode on the
338            assumption that they are used for video */
339         GAFR &= ~H3100_DIRECT_EGPIO;
340
341         H3100_EGPIO = h3100_egpio;
342         assign_h3600_egpio = h3100_control_egpio;
343 }
344
345 /*
346  * This turns the IRDA power on or off on the Compaq H3100
347  */
348 static int h3100_irda_set_power(struct device *dev, unsigned int state)
349 {
350         gpio_set_value(H3100_GPIO_IR_ON, state);
351         return 0;
352 }
353
354 static void h3100_irda_set_speed(struct device *dev, unsigned int speed)
355 {
356         gpio_set_value(H3100_GPIO_IR_FSEL, !(speed < 4000000));
357 }
358
359 static struct irda_platform_data h3100_irda_data = {
360         .set_power      = h3100_irda_set_power,
361         .set_speed      = h3100_irda_set_speed,
362 };
363
364 static struct gpio_default_state h3100_default_gpio[] = {
365         { H3100_GPIO_IR_ON,     GPIO_MODE_OUT0, "IrDA power" },
366         { H3100_GPIO_IR_FSEL,   GPIO_MODE_OUT0, "IrDA fsel" },
367 };
368
369 static void h3100_mach_init(void)
370 {
371         h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio));
372         h3xxx_mach_init();
373         sa11x0_register_irda(&h3100_irda_data);
374 }
375
376 MACHINE_START(H3100, "Compaq iPAQ H3100")
377         .phys_io        = 0x80000000,
378         .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
379         .boot_params    = 0xc0000100,
380         .map_io         = h3100_map_io,
381         .init_irq       = sa1100_init_irq,
382         .timer          = &sa1100_timer,
383         .init_machine   = h3100_mach_init,
384 MACHINE_END
385
386 #endif /* CONFIG_SA1100_H3100 */
387
388 /************************* H3600 *************************/
389
390 #ifdef CONFIG_SA1100_H3600
391
392 #define H3600_EGPIO     (*(volatile unsigned int *)H3600_EGPIO_VIRT)
393 static unsigned int h3600_egpio = EGPIO_H3600_RS232_ON;
394
395 static void h3600_control_egpio(enum ipaq_egpio_type x, int setp)
396 {
397         unsigned int egpio = 0;
398         unsigned long flags;
399
400         switch (x) {
401         case IPAQ_EGPIO_LCD_POWER:
402                 egpio |= EGPIO_H3600_LCD_ON |
403                          EGPIO_H3600_LCD_PCI |
404                          EGPIO_H3600_LCD_5V_ON |
405                          EGPIO_H3600_LVDD_ON;
406                 break;
407         case IPAQ_EGPIO_LCD_ENABLE:
408                 break;
409         case IPAQ_EGPIO_CODEC_NRESET:
410                 egpio |= EGPIO_H3600_CODEC_NRESET;
411                 break;
412         case IPAQ_EGPIO_AUDIO_ON:
413                 egpio |= EGPIO_H3600_AUD_AMP_ON |
414                          EGPIO_H3600_AUD_PWR_ON;
415                 break;
416         case IPAQ_EGPIO_QMUTE:
417                 egpio |= EGPIO_H3600_QMUTE;
418                 break;
419         case IPAQ_EGPIO_OPT_NVRAM_ON:
420                 egpio |= EGPIO_H3600_OPT_NVRAM_ON;
421                 break;
422         case IPAQ_EGPIO_OPT_ON:
423                 egpio |= EGPIO_H3600_OPT_ON;
424                 break;
425         case IPAQ_EGPIO_CARD_RESET:
426                 egpio |= EGPIO_H3600_CARD_RESET;
427                 break;
428         case IPAQ_EGPIO_OPT_RESET:
429                 egpio |= EGPIO_H3600_OPT_RESET;
430                 break;
431         case IPAQ_EGPIO_IR_ON:
432                 egpio |= EGPIO_H3600_IR_ON;
433                 break;
434         case IPAQ_EGPIO_IR_FSEL:
435                 egpio |= EGPIO_H3600_IR_FSEL;
436                 break;
437         case IPAQ_EGPIO_RS232_ON:
438                 egpio |= EGPIO_H3600_RS232_ON;
439                 break;
440         case IPAQ_EGPIO_VPP_ON:
441                 egpio |= EGPIO_H3600_VPP_ON;
442                 break;
443         }
444
445         if (egpio) {
446                 local_irq_save(flags);
447                 if (setp)
448                         h3600_egpio |= egpio;
449                 else
450                         h3600_egpio &= ~egpio;
451                 H3600_EGPIO = h3600_egpio;
452                 local_irq_restore(flags);
453         }
454 }
455
456 static void __init h3600_map_io(void)
457 {
458         h3xxx_map_io();
459
460         /* Initialize h3600-specific values here */
461
462         GPCR = 0x0fffffff;       /* All outputs are set low by default */
463         GPDR = GPIO_H3600_COM_RTS  | GPIO_H3600_L3_CLOCK |
464                GPIO_H3600_L3_MODE  | GPIO_H3600_L3_DATA  |
465                GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
466                GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
467                GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
468
469         H3600_EGPIO = h3600_egpio;         /* Maintains across sleep? */
470         assign_h3600_egpio = h3600_control_egpio;
471 }
472
473 /*
474  * This turns the IRDA power on or off on the Compaq H3600
475  */
476 static int h3600_irda_set_power(struct device *dev, unsigned int state)
477 {
478         assign_h3600_egpio(IPAQ_EGPIO_IR_ON, state);
479         return 0;
480 }
481
482 static void h3600_irda_set_speed(struct device *dev, unsigned int speed)
483 {
484         assign_h3600_egpio(IPAQ_EGPIO_IR_FSEL, !(speed < 4000000));
485 }
486
487 static struct irda_platform_data h3600_irda_data = {
488         .set_power      = h3600_irda_set_power,
489         .set_speed      = h3600_irda_set_speed,
490 };
491
492 static void h3600_mach_init(void)
493 {
494         h3xxx_mach_init();
495         sa11x0_register_irda(&h3600_irda_data);
496 }
497
498 MACHINE_START(H3600, "Compaq iPAQ H3600")
499         .phys_io        = 0x80000000,
500         .io_pg_offst    = ((0xf8000000) >> 18) & 0xfffc,
501         .boot_params    = 0xc0000100,
502         .map_io         = h3600_map_io,
503         .init_irq       = sa1100_init_irq,
504         .timer          = &sa1100_timer,
505         .init_machine   = h3600_mach_init,
506 MACHINE_END
507
508 #endif /* CONFIG_SA1100_H3600 */
509