initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / arm / mach-sa1100 / h3600.c
blob54ab444524018d3953a3871d6e3a92acb358402e
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/config.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/kernel.h>
26 #include <linux/tty.h>
27 #include <linux/pm.h>
28 #include <linux/serial_core.h>
30 #include <asm/irq.h>
31 #include <asm/hardware.h>
32 #include <asm/mach-types.h>
33 #include <asm/setup.h>
35 #include <asm/mach/irq.h>
36 #include <asm/mach/arch.h>
37 #include <asm/mach/map.h>
38 #include <asm/mach/serial_sa1100.h>
40 #include <asm/arch/h3600.h>
42 #if defined (CONFIG_SA1100_H3600) || defined (CONFIG_SA1100_H3100)
43 #include <asm/arch/h3600_gpio.h>
44 #endif
46 #ifdef CONFIG_SA1100_H3800
47 #include <asm/arch/h3600_asic.h>
48 #endif
50 #include "generic.h"
52 struct ipaq_model_ops ipaq_model_ops;
53 EXPORT_SYMBOL(ipaq_model_ops);
56 * low-level UART features
59 static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
61 if (port->mapbase == _Ser3UTCR0) {
62 if (mctrl & TIOCM_RTS)
63 GPCR = GPIO_H3600_COM_RTS;
64 else
65 GPSR = GPIO_H3600_COM_RTS;
69 static u_int h3600_uart_get_mctrl(struct uart_port *port)
71 u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
73 if (port->mapbase == _Ser3UTCR0) {
74 int gplr = GPLR;
75 /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
76 if (gplr & GPIO_H3600_COM_DCD)
77 ret &= ~TIOCM_CD;
78 if (gplr & GPIO_H3600_COM_CTS)
79 ret &= ~TIOCM_CTS;
82 return ret;
85 static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
87 if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */
88 assign_h3600_egpio(IPAQ_EGPIO_IR_ON, !state);
89 } else if (port->mapbase == _Ser3UTCR0) {
90 assign_h3600_egpio(IPAQ_EGPIO_RS232_ON, !state);
95 * Enable/Disable wake up events for this serial port.
96 * Obviously, we only support this on the normal COM port.
98 static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
100 int err = -EINVAL;
102 if (port->mapbase == _Ser3UTCR0) {
103 if (enable)
104 PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */
105 else
106 PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
107 err = 0;
109 return err;
112 static struct sa1100_port_fns h3600_port_fns __initdata = {
113 .set_mctrl = h3600_uart_set_mctrl,
114 .get_mctrl = h3600_uart_get_mctrl,
115 .pm = h3600_uart_pm,
116 .set_wake = h3600_uart_set_wake,
120 * helper for sa1100fb
122 static void h3xxx_lcd_power(int enable)
124 assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER, enable);
127 static struct map_desc h3600_io_desc[] __initdata = {
128 /* virtual physical length type */
129 { H3600_BANK_2_VIRT, SA1100_CS2_PHYS, 0x02800000, MT_DEVICE }, /* static memory bank 2 CS#2 */
130 { H3600_BANK_4_VIRT, SA1100_CS4_PHYS, 0x00800000, MT_DEVICE }, /* static memory bank 4 CS#4 */
131 { H3600_EGPIO_VIRT, H3600_EGPIO_PHYS, 0x01000000, MT_DEVICE }, /* EGPIO 0 CS#5 */
135 * Common map_io initialization
138 static void __init h3xxx_map_io(void)
140 sa1100_map_io();
141 iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
143 sa1100_register_uart_fns(&h3600_port_fns);
144 sa1100_register_uart(0, 3); /* Common serial port */
145 // sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
147 /* Ensure those pins are outputs and driving low */
148 PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
149 PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
151 /* Configure suspend conditions */
152 PGSR = 0;
153 PWER = PWER_GPIO0 | PWER_RTC;
154 PCFR = PCFR_OPDE;
155 PSDR = 0;
157 sa1100fb_lcd_power = h3xxx_lcd_power;
160 static __inline__ void do_blank(int setp)
162 if (ipaq_model_ops.blank_callback)
163 ipaq_model_ops.blank_callback(1-setp);
166 /************************* H3100 *************************/
168 #ifdef CONFIG_SA1100_H3100
170 #define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
171 static unsigned int h3100_egpio = 0;
173 static void h3100_control_egpio(enum ipaq_egpio_type x, int setp)
175 unsigned int egpio = 0;
176 long gpio = 0;
177 unsigned long flags;
179 switch (x) {
180 case IPAQ_EGPIO_LCD_POWER:
181 egpio |= EGPIO_H3600_LCD_ON;
182 gpio |= GPIO_H3100_LCD_3V_ON;
183 do_blank(setp);
184 break;
185 case IPAQ_EGPIO_LCD_ENABLE:
186 break;
187 case IPAQ_EGPIO_CODEC_NRESET:
188 egpio |= EGPIO_H3600_CODEC_NRESET;
189 break;
190 case IPAQ_EGPIO_AUDIO_ON:
191 gpio |= GPIO_H3100_AUD_PWR_ON
192 | GPIO_H3100_AUD_ON;
193 break;
194 case IPAQ_EGPIO_QMUTE:
195 gpio |= GPIO_H3100_QMUTE;
196 break;
197 case IPAQ_EGPIO_OPT_NVRAM_ON:
198 egpio |= EGPIO_H3600_OPT_NVRAM_ON;
199 break;
200 case IPAQ_EGPIO_OPT_ON:
201 egpio |= EGPIO_H3600_OPT_ON;
202 break;
203 case IPAQ_EGPIO_CARD_RESET:
204 egpio |= EGPIO_H3600_CARD_RESET;
205 break;
206 case IPAQ_EGPIO_OPT_RESET:
207 egpio |= EGPIO_H3600_OPT_RESET;
208 break;
209 case IPAQ_EGPIO_IR_ON:
210 gpio |= GPIO_H3100_IR_ON;
211 break;
212 case IPAQ_EGPIO_IR_FSEL:
213 gpio |= GPIO_H3100_IR_FSEL;
214 break;
215 case IPAQ_EGPIO_RS232_ON:
216 egpio |= EGPIO_H3600_RS232_ON;
217 break;
218 case IPAQ_EGPIO_VPP_ON:
219 egpio |= EGPIO_H3600_VPP_ON;
220 break;
223 if (egpio || gpio) {
224 local_irq_save(flags);
225 if (setp) {
226 h3100_egpio |= egpio;
227 GPSR = gpio;
228 } else {
229 h3100_egpio &= ~egpio;
230 GPCR = gpio;
232 H3100_EGPIO = h3100_egpio;
233 local_irq_restore(flags);
237 static unsigned long h3100_read_egpio(void)
239 return h3100_egpio;
242 static int h3100_pm_callback(int req)
244 if (ipaq_model_ops.pm_callback_aux)
245 return ipaq_model_ops.pm_callback_aux(req);
246 return 0;
249 static struct ipaq_model_ops h3100_model_ops __initdata = {
250 .generic_name = "3100",
251 .control = h3100_control_egpio,
252 .read = h3100_read_egpio,
253 .pm_callback = h3100_pm_callback
256 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
257 | GPIO_H3100_GPIO3 \
258 | GPIO_H3100_QMUTE \
259 | GPIO_H3100_LCD_3V_ON \
260 | GPIO_H3100_AUD_ON \
261 | GPIO_H3100_AUD_PWR_ON \
262 | GPIO_H3100_IR_ON \
263 | GPIO_H3100_IR_FSEL)
265 static void __init h3100_map_io(void)
267 h3xxx_map_io();
269 /* Initialize h3100-specific values here */
270 GPCR = 0x0fffffff; /* All outputs are set low by default */
271 GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
272 GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
273 GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
274 H3100_DIRECT_EGPIO;
276 /* Older bootldrs put GPIO2-9 in alternate mode on the
277 assumption that they are used for video */
278 GAFR &= ~H3100_DIRECT_EGPIO;
280 H3100_EGPIO = h3100_egpio;
281 ipaq_model_ops = h3100_model_ops;
284 MACHINE_START(H3100, "Compaq iPAQ H3100")
285 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
286 BOOT_PARAMS(0xc0000100)
287 MAPIO(h3100_map_io)
288 INITIRQ(sa1100_init_irq)
289 INITTIME(sa1100_init_time)
290 MACHINE_END
292 #endif /* CONFIG_SA1100_H3100 */
294 /************************* H3600 *************************/
296 #ifdef CONFIG_SA1100_H3600
298 #define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
299 static unsigned int h3600_egpio = EGPIO_H3600_RS232_ON;
301 static void h3600_control_egpio(enum ipaq_egpio_type x, int setp)
303 unsigned int egpio = 0;
304 unsigned long flags;
306 switch (x) {
307 case IPAQ_EGPIO_LCD_POWER:
308 egpio |= EGPIO_H3600_LCD_ON |
309 EGPIO_H3600_LCD_PCI |
310 EGPIO_H3600_LCD_5V_ON |
311 EGPIO_H3600_LVDD_ON;
312 do_blank(setp);
313 break;
314 case IPAQ_EGPIO_LCD_ENABLE:
315 break;
316 case IPAQ_EGPIO_CODEC_NRESET:
317 egpio |= EGPIO_H3600_CODEC_NRESET;
318 break;
319 case IPAQ_EGPIO_AUDIO_ON:
320 egpio |= EGPIO_H3600_AUD_AMP_ON |
321 EGPIO_H3600_AUD_PWR_ON;
322 break;
323 case IPAQ_EGPIO_QMUTE:
324 egpio |= EGPIO_H3600_QMUTE;
325 break;
326 case IPAQ_EGPIO_OPT_NVRAM_ON:
327 egpio |= EGPIO_H3600_OPT_NVRAM_ON;
328 break;
329 case IPAQ_EGPIO_OPT_ON:
330 egpio |= EGPIO_H3600_OPT_ON;
331 break;
332 case IPAQ_EGPIO_CARD_RESET:
333 egpio |= EGPIO_H3600_CARD_RESET;
334 break;
335 case IPAQ_EGPIO_OPT_RESET:
336 egpio |= EGPIO_H3600_OPT_RESET;
337 break;
338 case IPAQ_EGPIO_IR_ON:
339 egpio |= EGPIO_H3600_IR_ON;
340 break;
341 case IPAQ_EGPIO_IR_FSEL:
342 egpio |= EGPIO_H3600_IR_FSEL;
343 break;
344 case IPAQ_EGPIO_RS232_ON:
345 egpio |= EGPIO_H3600_RS232_ON;
346 break;
347 case IPAQ_EGPIO_VPP_ON:
348 egpio |= EGPIO_H3600_VPP_ON;
349 break;
352 if (egpio) {
353 local_irq_save(flags);
354 if (setp)
355 h3600_egpio |= egpio;
356 else
357 h3600_egpio &= ~egpio;
358 H3600_EGPIO = h3600_egpio;
359 local_irq_restore(flags);
363 static unsigned long h3600_read_egpio(void)
365 return h3600_egpio;
368 static int h3600_pm_callback(int req)
370 if (ipaq_model_ops.pm_callback_aux)
371 return ipaq_model_ops.pm_callback_aux(req);
372 return 0;
375 static struct ipaq_model_ops h3600_model_ops __initdata = {
376 .generic_name = "3600",
377 .control = h3600_control_egpio,
378 .read = h3600_read_egpio,
379 .pm_callback = h3600_pm_callback
382 static void __init h3600_map_io(void)
384 h3xxx_map_io();
386 /* Initialize h3600-specific values here */
388 GPCR = 0x0fffffff; /* All outputs are set low by default */
389 GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
390 GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
391 GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
392 GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
393 GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
395 H3600_EGPIO = h3600_egpio; /* Maintains across sleep? */
396 ipaq_model_ops = h3600_model_ops;
399 MACHINE_START(H3600, "Compaq iPAQ H3600")
400 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
401 BOOT_PARAMS(0xc0000100)
402 MAPIO(h3600_map_io)
403 INITIRQ(sa1100_init_irq)
404 INITTIME(sa1100_init_time)
405 MACHINE_END
407 #endif /* CONFIG_SA1100_H3600 */
409 #ifdef CONFIG_SA1100_H3800
411 #define SET_ASIC1(x) \
412 do {if (setp) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
414 #define SET_ASIC2(x) \
415 do {if (setp) { H3800_ASIC2_GPIOPIOD |= (x); } else { H3800_ASIC2_GPIOPIOD &= ~(x); }} while(0)
417 #define CLEAR_ASIC1(x) \
418 do {if (setp) { H3800_ASIC1_GPIO_OUT &= ~(x); } else { H3800_ASIC1_GPIO_OUT |= (x); }} while(0)
420 #define CLEAR_ASIC2(x) \
421 do {if (setp) { H3800_ASIC2_GPIOPIOD &= ~(x); } else { H3800_ASIC2_GPIOPIOD |= (x); }} while(0)
425 On screen enable, we get
427 h3800_video_power_on(1)
428 LCD controller starts
429 h3800_video_lcd_enable(1)
431 On screen disable, we get
433 h3800_video_lcd_enable(0)
434 LCD controller stops
435 h3800_video_power_on(0)
439 static void h3800_video_power_on(int setp)
441 if (setp) {
442 H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_ON;
443 msleep(30);
444 H3800_ASIC1_GPIO_OUT |= GPIO1_VGL_ON;
445 msleep(5);
446 H3800_ASIC1_GPIO_OUT |= GPIO1_VGH_ON;
447 msleep(50);
448 H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_5V_ON;
449 msleep(5);
450 } else {
451 msleep(5);
452 H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_5V_ON;
453 msleep(50);
454 H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGL_ON;
455 msleep(5);
456 H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGH_ON;
457 msleep(100);
458 H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_ON;
462 static void h3800_video_lcd_enable(int setp)
464 if (setp) {
465 msleep(17); // Wait one from before turning on
466 H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_PCI;
467 } else {
468 H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_PCI;
469 msleep(30); // Wait before turning off
474 static void h3800_control_egpio(enum ipaq_egpio_type x, int setp)
476 switch (x) {
477 case IPAQ_EGPIO_LCD_POWER:
478 h3800_video_power_on(setp);
479 break;
480 case IPAQ_EGPIO_LCD_ENABLE:
481 h3800_video_lcd_enable(setp);
482 break;
483 case IPAQ_EGPIO_CODEC_NRESET:
484 case IPAQ_EGPIO_AUDIO_ON:
485 case IPAQ_EGPIO_QMUTE:
486 printk("%s: error - should not be called\n", __FUNCTION__);
487 break;
488 case IPAQ_EGPIO_OPT_NVRAM_ON:
489 SET_ASIC2(GPIO2_OPT_ON_NVRAM);
490 break;
491 case IPAQ_EGPIO_OPT_ON:
492 SET_ASIC2(GPIO2_OPT_ON);
493 break;
494 case IPAQ_EGPIO_CARD_RESET:
495 SET_ASIC2(GPIO2_OPT_PCM_RESET);
496 break;
497 case IPAQ_EGPIO_OPT_RESET:
498 SET_ASIC2(GPIO2_OPT_RESET);
499 break;
500 case IPAQ_EGPIO_IR_ON:
501 CLEAR_ASIC1(GPIO1_IR_ON_N);
502 break;
503 case IPAQ_EGPIO_IR_FSEL:
504 break;
505 case IPAQ_EGPIO_RS232_ON:
506 SET_ASIC1(GPIO1_RS232_ON);
507 break;
508 case IPAQ_EGPIO_VPP_ON:
509 H3800_ASIC2_FlashWP_VPP_ON = setp;
510 break;
514 static unsigned long h3800_read_egpio(void)
516 return H3800_ASIC1_GPIO_OUT | (H3800_ASIC2_GPIOPIOD << 16);
519 /* We need to fix ASIC2 GPIO over suspend/resume. At the moment,
520 it doesn't appear that ASIC1 GPIO has the same problem */
522 static int h3800_pm_callback(int req)
524 static u16 asic1_data;
525 static u16 asic2_data;
526 int result = 0;
528 printk("%s %d\n", __FUNCTION__, req);
530 switch (req) {
531 case PM_RESUME:
532 MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000; /* Set MSC2 correctly */
534 H3800_ASIC2_GPIOPIOD = asic2_data;
535 H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
536 | GPIO2_SD_DETECT
537 | GPIO2_EAR_IN_N
538 | GPIO2_USB_DETECT_N
539 | GPIO2_SD_CON_SLT;
541 H3800_ASIC1_GPIO_OUT = asic1_data;
543 if (ipaq_model_ops.pm_callback_aux)
544 result = ipaq_model_ops.pm_callback_aux(req);
545 break;
547 case PM_SUSPEND:
548 if (ipaq_model_ops.pm_callback_aux &&
549 ((result = ipaq_model_ops.pm_callback_aux(req)) != 0))
550 return result;
552 asic1_data = H3800_ASIC1_GPIO_OUT;
553 asic2_data = H3800_ASIC2_GPIOPIOD;
554 break;
555 default:
556 printk("%s: unrecognized PM callback\n", __FUNCTION__);
557 break;
559 return result;
562 static struct ipaq_model_ops h3800_model_ops __initdata = {
563 .generic_name = "3800",
564 .control = h3800_control_egpio,
565 .read = h3800_read_egpio,
566 .pm_callback = h3800_pm_callback
569 #define MAX_ASIC_ISR_LOOPS 20
571 /* The order of these is important - see #include <asm/arch/irqs.h> */
572 static u32 kpio_irq_mask[] = {
573 KPIO_KEY_ALL,
574 KPIO_SPI_INT,
575 KPIO_OWM_INT,
576 KPIO_ADC_INT,
577 KPIO_UART_0_INT,
578 KPIO_UART_1_INT,
579 KPIO_TIMER_0_INT,
580 KPIO_TIMER_1_INT,
581 KPIO_TIMER_2_INT
584 static u32 gpio_irq_mask[] = {
585 GPIO2_PEN_IRQ,
586 GPIO2_SD_DETECT,
587 GPIO2_EAR_IN_N,
588 GPIO2_USB_DETECT_N,
589 GPIO2_SD_CON_SLT,
592 static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
594 int i;
596 if (0) printk("%s: interrupt received\n", __FUNCTION__);
598 desc->chip->ack(irq);
600 for (i = 0; i < MAX_ASIC_ISR_LOOPS && (GPLR & GPIO_H3800_ASIC); i++) {
601 u32 irq;
602 int j;
604 /* KPIO */
605 irq = H3800_ASIC2_KPIINTFLAG;
606 if (0) printk("%s KPIO 0x%08X\n", __FUNCTION__, irq);
607 for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
608 if (irq & kpio_irq_mask[j])
609 do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j, regs);
611 /* GPIO2 */
612 irq = H3800_ASIC2_GPIINTFLAG;
613 if (0) printk("%s GPIO 0x%08X\n", __FUNCTION__, irq);
614 for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
615 if (irq & gpio_irq_mask[j])
616 do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j , regs);
619 if (i >= MAX_ASIC_ISR_LOOPS)
620 printk("%s: interrupt processing overrun\n", __FUNCTION__);
622 /* For level-based interrupts */
623 desc->chip->unmask(irq);
627 static struct irqaction h3800_irq = {
628 .name = "h3800_asic",
629 .handler = h3800_IRQ_demux,
630 .flags = SA_INTERRUPT,
633 u32 kpio_int_shadow = 0;
636 /* mask_ack <- IRQ is first serviced.
637 mask <- IRQ is disabled.
638 unmask <- IRQ is enabled
640 The INTCLR registers are poorly documented. I believe that writing
641 a "1" to the register clears the specific interrupt, but the documentation
642 indicates writing a "0" clears the interrupt. In any case, they shouldn't
643 be read (that's the INTFLAG register)
646 static void h3800_mask_ack_kpio_irq(unsigned int irq)
648 u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
649 kpio_int_shadow &= ~mask;
650 H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
651 H3800_ASIC2_KPIINTCLR = mask;
654 static void h3800_mask_kpio_irq(unsigned int irq)
656 u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
657 kpio_int_shadow &= ~mask;
658 H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
661 static void h3800_unmask_kpio_irq(unsigned int irq)
663 u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
664 kpio_int_shadow |= mask;
665 H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
668 static void h3800_mask_ack_gpio_irq(unsigned int irq)
670 u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
671 H3800_ASIC2_GPIINTSTAT &= ~mask;
672 H3800_ASIC2_GPIINTCLR = mask;
675 static void h3800_mask_gpio_irq(unsigned int irq)
677 u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
678 H3800_ASIC2_GPIINTSTAT &= ~mask;
681 static void h3800_unmask_gpio_irq(unsigned int irq)
683 u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
684 H3800_ASIC2_GPIINTSTAT |= mask;
687 static void __init h3800_init_irq(void)
689 int i;
691 /* Initialize standard IRQs */
692 sa1100_init_irq();
694 /* Disable all IRQs and set up clock */
695 H3800_ASIC2_KPIINTSTAT = 0; /* Disable all interrupts */
696 H3800_ASIC2_GPIINTSTAT = 0;
698 H3800_ASIC2_KPIINTCLR = 0; /* Clear all KPIO interrupts */
699 H3800_ASIC2_GPIINTCLR = 0; /* Clear all GPIO interrupts */
701 // H3800_ASIC2_KPIINTCLR = 0xffff; /* Clear all KPIO interrupts */
702 // H3800_ASIC2_GPIINTCLR = 0xffff; /* Clear all GPIO interrupts */
704 H3800_ASIC2_CLOCK_Enable |= ASIC2_CLOCK_EX0; /* 32 kHZ crystal on */
705 H3800_ASIC2_INTR_ClockPrescale |= ASIC2_INTCPS_SET;
706 H3800_ASIC2_INTR_ClockPrescale = ASIC2_INTCPS_CPS(0x0e) | ASIC2_INTCPS_SET;
707 H3800_ASIC2_INTR_TimerSet = 1;
709 #if 0
710 for (i = 0; i < H3800_KPIO_IRQ_COUNT; i++) {
711 int irq = i + H3800_KPIO_IRQ_START;
712 irq_desc[irq].valid = 1;
713 irq_desc[irq].probe_ok = 1;
714 set_irq_chip(irq, &h3800_kpio_irqchip);
717 for (i = 0; i < H3800_GPIO_IRQ_COUNT; i++) {
718 int irq = i + H3800_GPIO_IRQ_START;
719 irq_desc[irq].valid = 1;
720 irq_desc[irq].probe_ok = 1;
721 set_irq_chip(irq, &h3800_gpio_irqchip);
723 #endif
724 set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING);
725 set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux);
729 #define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */
731 static void __init h3800_map_io(void)
733 h3xxx_map_io();
735 /* Add wakeup on AC plug/unplug */
736 PWER |= PWER_GPIO12;
738 /* Initialize h3800-specific values here */
739 GPCR = 0x0fffffff; /* All outputs are set low by default */
740 GAFR = GPIO_H3800_CLK_OUT |
741 GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
742 GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
743 GPDR = GPIO_H3800_CLK_OUT |
744 GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
745 GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
746 GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
747 GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
748 TUCR = TUCR_3_6864MHz; /* Seems to be used only for the Bluetooth UART */
750 /* Fix the memory bus */
751 MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000;
753 /* Set up ASIC #1 */
754 H3800_ASIC1_GPIO_DIR = ASIC1_OUTPUTS; /* All outputs */
755 H3800_ASIC1_GPIO_MASK = ASIC1_OUTPUTS; /* No interrupts */
756 H3800_ASIC1_GPIO_SLEEP_MASK = ASIC1_OUTPUTS;
757 H3800_ASIC1_GPIO_SLEEP_DIR = ASIC1_OUTPUTS;
758 H3800_ASIC1_GPIO_SLEEP_OUT = GPIO1_EAR_ON_N;
759 H3800_ASIC1_GPIO_BATT_FAULT_DIR = ASIC1_OUTPUTS;
760 H3800_ASIC1_GPIO_BATT_FAULT_OUT = GPIO1_EAR_ON_N;
762 H3800_ASIC1_GPIO_OUT = GPIO1_IR_ON_N
763 | GPIO1_RS232_ON
764 | GPIO1_EAR_ON_N;
766 /* Set up ASIC #2 */
767 H3800_ASIC2_GPIOPIOD = GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
768 H3800_ASIC2_GPOBFSTAT = GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
770 H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
771 | GPIO2_SD_DETECT
772 | GPIO2_EAR_IN_N
773 | GPIO2_USB_DETECT_N
774 | GPIO2_SD_CON_SLT;
776 /* TODO : Set sleep states & battery fault states */
778 /* Clear VPP Enable */
779 H3800_ASIC2_FlashWP_VPP_ON = 0;
780 ipaq_model_ops = h3800_model_ops;
783 MACHINE_START(H3800, "Compaq iPAQ H3800")
784 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
785 BOOT_PARAMS(0xc0000100)
786 MAPIO(h3800_map_io)
787 INITIRQ(h3800_init_irq)
788 INITTIME(sa1100_init_time)
789 MACHINE_END
791 #endif /* CONFIG_SA1100_H3800 */