Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / arch / arm / mach-sa1100 / h3600.c
blobdd875ba0b55944639105f860c4064b4ca25b3ca2
1 /*
2 * Hardware definitions for Compaq iPAQ H3xxx Handheld Computers
4 * Copyright 2000,1 Compaq Computer Corporation.
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.
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.
14 * Author: Jamey Hicks.
16 * History:
18 * 2001-10-?? Andrew Christian Added support for iPAQ H3800
19 * and abstracted EGPIO interface.
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/serial_core.h>
29 #include <asm/irq.h>
30 #include <asm/hardware.h>
31 #include <asm/mach-types.h>
32 #include <asm/setup.h>
34 #include <asm/mach/irq.h>
35 #include <asm/mach/arch.h>
36 #include <asm/mach/map.h>
37 #include <asm/mach/serial_sa1100.h>
39 #include <asm/arch/h3600.h>
41 #if defined (CONFIG_SA1100_H3600) || defined (CONFIG_SA1100_H3100)
42 #include <asm/arch/h3600_gpio.h>
43 #endif
45 #ifdef CONFIG_SA1100_H3800
46 #include <asm/arch/h3600_asic.h>
47 #endif
49 #include "generic.h"
51 struct ipaq_model_ops ipaq_model_ops;
52 EXPORT_SYMBOL(ipaq_model_ops);
54 static void msleep(unsigned int msec)
56 current->state = TASK_INTERRUPTIBLE;
57 schedule_timeout((msec * HZ + 999) / 1000);
61 * low-level UART features
64 static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
66 if (port->mapbase == _Ser3UTCR0) {
67 if (mctrl & TIOCM_RTS)
68 GPCR = GPIO_H3600_COM_RTS;
69 else
70 GPSR = GPIO_H3600_COM_RTS;
74 static u_int h3600_uart_get_mctrl(struct uart_port *port)
76 u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
78 if (port->mapbase == _Ser3UTCR0) {
79 int gplr = GPLR;
80 /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
81 if (gplr & GPIO_H3600_COM_DCD)
82 ret &= ~TIOCM_CD;
83 if (gplr & GPIO_H3600_COM_CTS)
84 ret &= ~TIOCM_CTS;
87 return ret;
90 static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
92 if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */
93 assign_h3600_egpio(IPAQ_EGPIO_IR_ON, !state);
94 } else if (port->mapbase == _Ser3UTCR0) {
95 assign_h3600_egpio(IPAQ_EGPIO_RS232_ON, !state);
100 * Enable/Disable wake up events for this serial port.
101 * Obviously, we only support this on the normal COM port.
103 static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
105 int err = -EINVAL;
107 if (port->mapbase == _Ser3UTCR0) {
108 if (enable)
109 PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */
110 else
111 PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
112 err = 0;
114 return err;
117 static struct sa1100_port_fns h3600_port_fns __initdata = {
118 .set_mctrl = h3600_uart_set_mctrl,
119 .get_mctrl = h3600_uart_get_mctrl,
120 .pm = h3600_uart_pm,
121 .set_wake = h3600_uart_set_wake,
125 * helper for sa1100fb
127 static void h3xxx_lcd_power(int enable)
129 assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER, enable);
132 static struct map_desc h3600_io_desc[] __initdata = {
133 /* virtual physical length type */
134 { H3600_BANK_2_VIRT, SA1100_CS2_PHYS, 0x02800000, MT_DEVICE }, /* static memory bank 2 CS#2 */
135 { H3600_BANK_4_VIRT, SA1100_CS4_PHYS, 0x00800000, MT_DEVICE }, /* static memory bank 4 CS#4 */
136 { H3600_EGPIO_VIRT, H3600_EGPIO_PHYS, 0x01000000, MT_DEVICE }, /* EGPIO 0 CS#5 */
140 * Common map_io initialization
143 static void __init h3xxx_map_io(void)
145 sa1100_map_io();
146 iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
148 sa1100_register_uart_fns(&h3600_port_fns);
149 sa1100_register_uart(0, 3); /* Common serial port */
150 // sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
152 /* Ensure those pins are outputs and driving low */
153 PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
154 PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
156 /* Configure suspend conditions */
157 PGSR = 0;
158 PWER = PWER_GPIO0 | PWER_RTC;
159 PCFR = PCFR_OPDE;
160 PSDR = 0;
162 sa1100fb_lcd_power = h3xxx_lcd_power;
165 static __inline__ void do_blank(int setp)
167 if (ipaq_model_ops.blank_callback)
168 ipaq_model_ops.blank_callback(1-setp);
171 /************************* H3100 *************************/
173 #ifdef CONFIG_SA1100_H3100
175 #define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
176 static unsigned int h3100_egpio = 0;
178 static void h3100_control_egpio(enum ipaq_egpio_type x, int setp)
180 unsigned int egpio = 0;
181 long gpio = 0;
182 unsigned long flags;
184 switch (x) {
185 case IPAQ_EGPIO_LCD_POWER:
186 egpio |= EGPIO_H3600_LCD_ON;
187 gpio |= GPIO_H3100_LCD_3V_ON;
188 do_blank(setp);
189 break;
190 case IPAQ_EGPIO_LCD_ENABLE:
191 break;
192 case IPAQ_EGPIO_CODEC_NRESET:
193 egpio |= EGPIO_H3600_CODEC_NRESET;
194 break;
195 case IPAQ_EGPIO_AUDIO_ON:
196 gpio |= GPIO_H3100_AUD_PWR_ON
197 | GPIO_H3100_AUD_ON;
198 break;
199 case IPAQ_EGPIO_QMUTE:
200 gpio |= GPIO_H3100_QMUTE;
201 break;
202 case IPAQ_EGPIO_OPT_NVRAM_ON:
203 egpio |= EGPIO_H3600_OPT_NVRAM_ON;
204 break;
205 case IPAQ_EGPIO_OPT_ON:
206 egpio |= EGPIO_H3600_OPT_ON;
207 break;
208 case IPAQ_EGPIO_CARD_RESET:
209 egpio |= EGPIO_H3600_CARD_RESET;
210 break;
211 case IPAQ_EGPIO_OPT_RESET:
212 egpio |= EGPIO_H3600_OPT_RESET;
213 break;
214 case IPAQ_EGPIO_IR_ON:
215 gpio |= GPIO_H3100_IR_ON;
216 break;
217 case IPAQ_EGPIO_IR_FSEL:
218 gpio |= GPIO_H3100_IR_FSEL;
219 break;
220 case IPAQ_EGPIO_RS232_ON:
221 egpio |= EGPIO_H3600_RS232_ON;
222 break;
223 case IPAQ_EGPIO_VPP_ON:
224 egpio |= EGPIO_H3600_VPP_ON;
225 break;
228 if (egpio || gpio) {
229 local_irq_save(flags);
230 if (setp) {
231 h3100_egpio |= egpio;
232 GPSR = gpio;
233 } else {
234 h3100_egpio &= ~egpio;
235 GPCR = gpio;
237 H3100_EGPIO = h3100_egpio;
238 local_irq_restore(flags);
242 static unsigned long h3100_read_egpio(void)
244 return h3100_egpio;
247 static int h3100_pm_callback(int req)
249 if (ipaq_model_ops.pm_callback_aux)
250 return ipaq_model_ops.pm_callback_aux(req);
251 return 0;
254 static struct ipaq_model_ops h3100_model_ops __initdata = {
255 .generic_name = "3100",
256 .control = h3100_control_egpio,
257 .read = h3100_read_egpio,
258 .pm_callback = h3100_pm_callback
261 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
262 | GPIO_H3100_GPIO3 \
263 | GPIO_H3100_QMUTE \
264 | GPIO_H3100_LCD_3V_ON \
265 | GPIO_H3100_AUD_ON \
266 | GPIO_H3100_AUD_PWR_ON \
267 | GPIO_H3100_IR_ON \
268 | GPIO_H3100_IR_FSEL)
270 static void __init h3100_map_io(void)
272 h3xxx_map_io();
274 /* Initialize h3100-specific values here */
275 GPCR = 0x0fffffff; /* All outputs are set low by default */
276 GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
277 GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
278 GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
279 H3100_DIRECT_EGPIO;
281 /* Older bootldrs put GPIO2-9 in alternate mode on the
282 assumption that they are used for video */
283 GAFR &= ~H3100_DIRECT_EGPIO;
285 H3100_EGPIO = h3100_egpio;
286 ipaq_model_ops = h3100_model_ops;
289 MACHINE_START(H3100, "Compaq iPAQ H3100")
290 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
291 BOOT_PARAMS(0xc0000100)
292 MAPIO(h3100_map_io)
293 INITIRQ(sa1100_init_irq)
294 MACHINE_END
296 #endif /* CONFIG_SA1100_H3100 */
298 /************************* H3600 *************************/
300 #ifdef CONFIG_SA1100_H3600
302 #define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
303 static unsigned int h3600_egpio = EGPIO_H3600_RS232_ON;
305 static void h3600_control_egpio(enum ipaq_egpio_type x, int setp)
307 unsigned int egpio = 0;
308 unsigned long flags;
310 switch (x) {
311 case IPAQ_EGPIO_LCD_POWER:
312 egpio |= EGPIO_H3600_LCD_ON |
313 EGPIO_H3600_LCD_PCI |
314 EGPIO_H3600_LCD_5V_ON |
315 EGPIO_H3600_LVDD_ON;
316 do_blank(setp);
317 break;
318 case IPAQ_EGPIO_LCD_ENABLE:
319 break;
320 case IPAQ_EGPIO_CODEC_NRESET:
321 egpio |= EGPIO_H3600_CODEC_NRESET;
322 break;
323 case IPAQ_EGPIO_AUDIO_ON:
324 egpio |= EGPIO_H3600_AUD_AMP_ON |
325 EGPIO_H3600_AUD_PWR_ON;
326 break;
327 case IPAQ_EGPIO_QMUTE:
328 egpio |= EGPIO_H3600_QMUTE;
329 break;
330 case IPAQ_EGPIO_OPT_NVRAM_ON:
331 egpio |= EGPIO_H3600_OPT_NVRAM_ON;
332 break;
333 case IPAQ_EGPIO_OPT_ON:
334 egpio |= EGPIO_H3600_OPT_ON;
335 break;
336 case IPAQ_EGPIO_CARD_RESET:
337 egpio |= EGPIO_H3600_CARD_RESET;
338 break;
339 case IPAQ_EGPIO_OPT_RESET:
340 egpio |= EGPIO_H3600_OPT_RESET;
341 break;
342 case IPAQ_EGPIO_IR_ON:
343 egpio |= EGPIO_H3600_IR_ON;
344 break;
345 case IPAQ_EGPIO_IR_FSEL:
346 egpio |= EGPIO_H3600_IR_FSEL;
347 break;
348 case IPAQ_EGPIO_RS232_ON:
349 egpio |= EGPIO_H3600_RS232_ON;
350 break;
351 case IPAQ_EGPIO_VPP_ON:
352 egpio |= EGPIO_H3600_VPP_ON;
353 break;
356 if (egpio) {
357 local_irq_save(flags);
358 if (setp)
359 h3600_egpio |= egpio;
360 else
361 h3600_egpio &= ~egpio;
362 H3600_EGPIO = h3600_egpio;
363 local_irq_restore(flags);
367 static unsigned long h3600_read_egpio(void)
369 return h3600_egpio;
372 static int h3600_pm_callback(int req)
374 if (ipaq_model_ops.pm_callback_aux)
375 return ipaq_model_ops.pm_callback_aux(req);
376 return 0;
379 static struct ipaq_model_ops h3600_model_ops __initdata = {
380 .generic_name = "3600",
381 .control = h3600_control_egpio,
382 .read = h3600_read_egpio,
383 .pm_callback = h3600_pm_callback
386 static void __init h3600_map_io(void)
388 h3xxx_map_io();
390 /* Initialize h3600-specific values here */
392 GPCR = 0x0fffffff; /* All outputs are set low by default */
393 GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
394 GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
395 GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
396 GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
397 GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
399 H3600_EGPIO = h3600_egpio; /* Maintains across sleep? */
400 ipaq_model_ops = h3600_model_ops;
403 MACHINE_START(H3600, "Compaq iPAQ H3600")
404 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
405 BOOT_PARAMS(0xc0000100)
406 MAPIO(h3600_map_io)
407 INITIRQ(sa1100_init_irq)
408 MACHINE_END
410 #endif /* CONFIG_SA1100_H3600 */
412 #ifdef CONFIG_SA1100_H3800
414 #define SET_ASIC1(x) \
415 do {if (setp) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
417 #define SET_ASIC2(x) \
418 do {if (setp) { H3800_ASIC2_GPIOPIOD |= (x); } else { H3800_ASIC2_GPIOPIOD &= ~(x); }} while(0)
420 #define CLEAR_ASIC1(x) \
421 do {if (setp) { H3800_ASIC1_GPIO_OUT &= ~(x); } else { H3800_ASIC1_GPIO_OUT |= (x); }} while(0)
423 #define CLEAR_ASIC2(x) \
424 do {if (setp) { H3800_ASIC2_GPIOPIOD &= ~(x); } else { H3800_ASIC2_GPIOPIOD |= (x); }} while(0)
428 On screen enable, we get
430 h3800_video_power_on(1)
431 LCD controller starts
432 h3800_video_lcd_enable(1)
434 On screen disable, we get
436 h3800_video_lcd_enable(0)
437 LCD controller stops
438 h3800_video_power_on(0)
442 static void h3800_video_power_on(int setp)
444 if (setp) {
445 H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_ON;
446 msleep(30);
447 H3800_ASIC1_GPIO_OUT |= GPIO1_VGL_ON;
448 msleep(5);
449 H3800_ASIC1_GPIO_OUT |= GPIO1_VGH_ON;
450 msleep(50);
451 H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_5V_ON;
452 msleep(5);
453 } else {
454 msleep(5);
455 H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_5V_ON;
456 msleep(50);
457 H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGL_ON;
458 msleep(5);
459 H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGH_ON;
460 msleep(100);
461 H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_ON;
465 static void h3800_video_lcd_enable(int setp)
467 if (setp) {
468 msleep(17); // Wait one from before turning on
469 H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_PCI;
470 } else {
471 H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_PCI;
472 msleep(30); // Wait before turning off
477 static void h3800_control_egpio(enum ipaq_egpio_type x, int setp)
479 switch (x) {
480 case IPAQ_EGPIO_LCD_POWER:
481 h3800_video_power_on(setp);
482 break;
483 case IPAQ_EGPIO_LCD_ENABLE:
484 h3800_video_lcd_enable(setp);
485 break;
486 case IPAQ_EGPIO_CODEC_NRESET:
487 case IPAQ_EGPIO_AUDIO_ON:
488 case IPAQ_EGPIO_QMUTE:
489 printk(__FUNCTION__ ": error - should not be called\n");
490 break;
491 case IPAQ_EGPIO_OPT_NVRAM_ON:
492 SET_ASIC2(GPIO2_OPT_ON_NVRAM);
493 break;
494 case IPAQ_EGPIO_OPT_ON:
495 SET_ASIC2(GPIO2_OPT_ON);
496 break;
497 case IPAQ_EGPIO_CARD_RESET:
498 SET_ASIC2(GPIO2_OPT_PCM_RESET);
499 break;
500 case IPAQ_EGPIO_OPT_RESET:
501 SET_ASIC2(GPIO2_OPT_RESET);
502 break;
503 case IPAQ_EGPIO_IR_ON:
504 CLEAR_ASIC1(GPIO1_IR_ON_N);
505 break;
506 case IPAQ_EGPIO_IR_FSEL:
507 break;
508 case IPAQ_EGPIO_RS232_ON:
509 SET_ASIC1(GPIO1_RS232_ON);
510 break;
511 case IPAQ_EGPIO_VPP_ON:
512 H3800_ASIC2_FlashWP_VPP_ON = setp;
513 break;
517 static unsigned long h3800_read_egpio(void)
519 return H3800_ASIC1_GPIO_OUT | (H3800_ASIC2_GPIOPIOD << 16);
522 /* We need to fix ASIC2 GPIO over suspend/resume. At the moment,
523 it doesn't appear that ASIC1 GPIO has the same problem */
525 static int h3800_pm_callback(int req)
527 static u16 asic1_data;
528 static u16 asic2_data;
529 int result = 0;
531 printk(__FUNCTION__ " %d\n", req);
533 switch (req) {
534 case PM_RESUME:
535 MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000; /* Set MSC2 correctly */
537 H3800_ASIC2_GPIOPIOD = asic2_data;
538 H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
539 | GPIO2_SD_DETECT
540 | GPIO2_EAR_IN_N
541 | GPIO2_USB_DETECT_N
542 | GPIO2_SD_CON_SLT;
544 H3800_ASIC1_GPIO_OUT = asic1_data;
546 if (ipaq_model_ops.pm_callback_aux)
547 result = ipaq_model_ops.pm_callback_aux(req);
548 break;
550 case PM_SUSPEND:
551 if (ipaq_model_ops.pm_callback_aux &&
552 ((result = ipaq_model_ops.pm_callback_aux(req)) != 0))
553 return result;
555 asic1_data = H3800_ASIC1_GPIO_OUT;
556 asic2_data = H3800_ASIC2_GPIOPIOD;
557 break;
558 default:
559 printk(__FUNCTION__ ": unrecognized PM callback\n");
560 break;
562 return result;
565 static struct ipaq_model_ops h3800_model_ops __initdata = {
566 .generic_name = "3800",
567 .control = h3800_control_egpio,
568 .read = h3800_read_egpio,
569 .pm_callback = h3800_pm_callback
572 #define MAX_ASIC_ISR_LOOPS 20
574 /* The order of these is important - see #include <asm/arch/irqs.h> */
575 static u32 kpio_irq_mask[] = {
576 KPIO_KEY_ALL,
577 KPIO_SPI_INT,
578 KPIO_OWM_INT,
579 KPIO_ADC_INT,
580 KPIO_UART_0_INT,
581 KPIO_UART_1_INT,
582 KPIO_TIMER_0_INT,
583 KPIO_TIMER_1_INT,
584 KPIO_TIMER_2_INT
587 static u32 gpio_irq_mask[] = {
588 GPIO2_PEN_IRQ,
589 GPIO2_SD_DETECT,
590 GPIO2_EAR_IN_N,
591 GPIO2_USB_DETECT_N,
592 GPIO2_SD_CON_SLT,
595 static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
597 int i;
599 if (0) printk(__FUNCTION__ ": interrupt received\n");
601 desc->chip->ack(irq);
603 for (i = 0; i < MAX_ASIC_ISR_LOOPS && (GPLR & GPIO_H3800_ASIC); i++) {
604 u32 irq;
605 int j;
607 /* KPIO */
608 irq = H3800_ASIC2_KPIINTFLAG;
609 if (0) printk(__FUNCTION__" KPIO 0x%08X\n", irq);
610 for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
611 if (irq & kpio_irq_mask[j])
612 do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j, regs);
614 /* GPIO2 */
615 irq = H3800_ASIC2_GPIINTFLAG;
616 if (0) printk(__FUNCTION__" GPIO 0x%08X\n", irq);
617 for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
618 if (irq & gpio_irq_mask[j])
619 do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j , regs);
622 if (i >= MAX_ASIC_ISR_LOOPS)
623 printk(__FUNCTION__ ": interrupt processing overrun\n");
625 /* For level-based interrupts */
626 desc->chip->unmask(irq);
630 static struct irqaction h3800_irq = {
631 .name = "h3800_asic",
632 .handler = h3800_IRQ_demux,
633 .flags = SA_INTERRUPT,
636 u32 kpio_int_shadow = 0;
639 /* mask_ack <- IRQ is first serviced.
640 mask <- IRQ is disabled.
641 unmask <- IRQ is enabled
643 The INTCLR registers are poorly documented. I believe that writing
644 a "1" to the register clears the specific interrupt, but the documentation
645 indicates writing a "0" clears the interrupt. In any case, they shouldn't
646 be read (that's the INTFLAG register)
649 static void h3800_mask_ack_kpio_irq(unsigned int irq)
651 u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
652 kpio_int_shadow &= ~mask;
653 H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
654 H3800_ASIC2_KPIINTCLR = mask;
657 static void h3800_mask_kpio_irq(unsigned int irq)
659 u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
660 kpio_int_shadow &= ~mask;
661 H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
664 static void h3800_unmask_kpio_irq(unsigned int irq)
666 u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
667 kpio_int_shadow |= mask;
668 H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
671 static void h3800_mask_ack_gpio_irq(unsigned int irq)
673 u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
674 H3800_ASIC2_GPIINTSTAT &= ~mask;
675 H3800_ASIC2_GPIINTCLR = mask;
678 static void h3800_mask_gpio_irq(unsigned int irq)
680 u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
681 H3800_ASIC2_GPIINTSTAT &= ~mask;
684 static void h3800_unmask_gpio_irq(unsigned int irq)
686 u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
687 H3800_ASIC2_GPIINTSTAT |= mask;
690 static void __init h3800_init_irq(void)
692 int i;
694 /* Initialize standard IRQs */
695 sa1100_init_irq();
697 /* Disable all IRQs and set up clock */
698 H3800_ASIC2_KPIINTSTAT = 0; /* Disable all interrupts */
699 H3800_ASIC2_GPIINTSTAT = 0;
701 H3800_ASIC2_KPIINTCLR = 0; /* Clear all KPIO interrupts */
702 H3800_ASIC2_GPIINTCLR = 0; /* Clear all GPIO interrupts */
704 // H3800_ASIC2_KPIINTCLR = 0xffff; /* Clear all KPIO interrupts */
705 // H3800_ASIC2_GPIINTCLR = 0xffff; /* Clear all GPIO interrupts */
707 H3800_ASIC2_CLOCK_Enable |= ASIC2_CLOCK_EX0; /* 32 kHZ crystal on */
708 H3800_ASIC2_INTR_ClockPrescale |= ASIC2_INTCPS_SET;
709 H3800_ASIC2_INTR_ClockPrescale = ASIC2_INTCPS_CPS(0x0e) | ASIC2_INTCPS_SET;
710 H3800_ASIC2_INTR_TimerSet = 1;
712 #if 0
713 for (i = 0; i < H3800_KPIO_IRQ_COUNT; i++) {
714 int irq = i + H3800_KPIO_IRQ_START;
715 irq_desc[irq].valid = 1;
716 irq_desc[irq].probe_ok = 1;
717 set_irq_chip(irq, &h3800_kpio_irqchip);
720 for (i = 0; i < H3800_GPIO_IRQ_COUNT; i++) {
721 int irq = i + H3800_GPIO_IRQ_START;
722 irq_desc[irq].valid = 1;
723 irq_desc[irq].probe_ok = 1;
724 set_irq_chip(irq, &h3800_gpio_irqchip);
726 #endif
727 set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING);
728 set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux);
732 #define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */
734 static void __init h3800_map_io(void)
736 h3xxx_map_io();
738 /* Add wakeup on AC plug/unplug */
739 PWER |= PWER_GPIO12;
741 /* Initialize h3800-specific values here */
742 GPCR = 0x0fffffff; /* All outputs are set low by default */
743 GAFR = GPIO_H3800_CLK_OUT |
744 GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
745 GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
746 GPDR = GPIO_H3800_CLK_OUT |
747 GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
748 GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
749 GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
750 GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
751 TUCR = TUCR_3_6864MHz; /* Seems to be used only for the Bluetooth UART */
753 /* Fix the memory bus */
754 MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000;
756 /* Set up ASIC #1 */
757 H3800_ASIC1_GPIO_DIR = ASIC1_OUTPUTS; /* All outputs */
758 H3800_ASIC1_GPIO_MASK = ASIC1_OUTPUTS; /* No interrupts */
759 H3800_ASIC1_GPIO_SLEEP_MASK = ASIC1_OUTPUTS;
760 H3800_ASIC1_GPIO_SLEEP_DIR = ASIC1_OUTPUTS;
761 H3800_ASIC1_GPIO_SLEEP_OUT = GPIO1_EAR_ON_N;
762 H3800_ASIC1_GPIO_BATT_FAULT_DIR = ASIC1_OUTPUTS;
763 H3800_ASIC1_GPIO_BATT_FAULT_OUT = GPIO1_EAR_ON_N;
765 H3800_ASIC1_GPIO_OUT = GPIO1_IR_ON_N
766 | GPIO1_RS232_ON
767 | GPIO1_EAR_ON_N;
769 /* Set up ASIC #2 */
770 H3800_ASIC2_GPIOPIOD = GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
771 H3800_ASIC2_GPOBFSTAT = GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
773 H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
774 | GPIO2_SD_DETECT
775 | GPIO2_EAR_IN_N
776 | GPIO2_USB_DETECT_N
777 | GPIO2_SD_CON_SLT;
779 /* TODO : Set sleep states & battery fault states */
781 /* Clear VPP Enable */
782 H3800_ASIC2_FlashWP_VPP_ON = 0;
783 ipaq_model_ops = h3800_model_ops;
786 MACHINE_START(H3800, "Compaq iPAQ H3800")
787 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
788 BOOT_PARAMS(0xc0000100)
789 MAPIO(h3800_map_io)
790 INITIRQ(h3800_init_irq)
791 MACHINE_END
793 #endif /* CONFIG_SA1100_H3800 */