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.
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>
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>
34 #include <mach/hardware.h>
35 #include <asm/mach-types.h>
36 #include <asm/setup.h>
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>
45 #include <mach/h3600.h>
46 #include <mach/h3600_gpio.h>
50 void (*assign_h3600_egpio
)(enum ipaq_egpio_type x
, int level
);
51 EXPORT_SYMBOL(assign_h3600_egpio
);
53 struct gpio_default_state
{
59 #define GPIO_MODE_IN -1
60 #define GPIO_MODE_OUT0 0
61 #define GPIO_MODE_OUT1 1
63 static void h3xxx_init_gpio(struct gpio_default_state
*s
, size_t n
)
66 const char *name
= s
->name
;
71 err
= gpio_request(s
->gpio
, name
);
73 printk(KERN_ERR
"gpio%u: unable to request: %d\n",
78 err
= gpio_direction_output(s
->gpio
, s
->mode
);
80 err
= gpio_direction_input(s
->gpio
);
83 printk(KERN_ERR
"gpio%u: unable to set direction: %d\n",
94 static struct mtd_partition h3xxx_partitions
[] = {
96 .name
= "H3XXX boot firmware",
99 .mask_flags
= MTD_WRITEABLE
, /* force read-only */
101 .name
= "H3XXX rootfs",
102 .size
= MTDPART_SIZ_FULL
,
103 .offset
= 0x00040000,
107 static void h3xxx_set_vpp(int vpp
)
109 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON
, vpp
);
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
),
119 static struct resource h3xxx_flash_resource
= {
120 .start
= SA1100_CS0_PHYS
,
121 .end
= SA1100_CS0_PHYS
+ SZ_32M
- 1,
122 .flags
= IORESOURCE_MEM
,
125 static void h3xxx_mach_init(void)
127 sa11x0_register_mtd(&h3xxx_flash_data
, &h3xxx_flash_resource
, 1);
131 * low-level UART features
134 static void h3600_uart_set_mctrl(struct uart_port
*port
, u_int mctrl
)
136 if (port
->mapbase
== _Ser3UTCR0
) {
137 if (mctrl
& TIOCM_RTS
)
138 GPCR
= GPIO_H3600_COM_RTS
;
140 GPSR
= GPIO_H3600_COM_RTS
;
144 static u_int
h3600_uart_get_mctrl(struct uart_port
*port
)
146 u_int ret
= TIOCM_CD
| TIOCM_CTS
| TIOCM_DSR
;
148 if (port
->mapbase
== _Ser3UTCR0
) {
150 /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
151 if (gplr
& GPIO_H3600_COM_DCD
)
153 if (gplr
& GPIO_H3600_COM_CTS
)
160 static void h3600_uart_pm(struct uart_port
*port
, u_int state
, u_int oldstate
)
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
);
170 * Enable/Disable wake up events for this serial port.
171 * Obviously, we only support this on the normal COM port.
173 static int h3600_uart_set_wake(struct uart_port
*port
, u_int enable
)
177 if (port
->mapbase
== _Ser3UTCR0
) {
179 PWER
|= PWER_GPIO23
| PWER_GPIO25
; /* DCD and CTS */
181 PWER
&= ~(PWER_GPIO23
| PWER_GPIO25
); /* DCD and CTS */
187 static struct sa1100_port_fns h3600_port_fns __initdata
= {
188 .set_mctrl
= h3600_uart_set_mctrl
,
189 .get_mctrl
= h3600_uart_get_mctrl
,
191 .set_wake
= h3600_uart_set_wake
,
195 * helper for sa1100fb
197 static void h3xxx_lcd_power(int enable
)
199 assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER
, enable
);
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,
208 }, { /* static memory bank 4 CS#4 */
209 .virtual = H3600_BANK_4_VIRT
,
210 .pfn
= __phys_to_pfn(SA1100_CS4_PHYS
),
211 .length
= 0x00800000,
213 }, { /* EGPIO 0 CS#5 */
214 .virtual = H3600_EGPIO_VIRT
,
215 .pfn
= __phys_to_pfn(H3600_EGPIO_PHYS
),
216 .length
= 0x01000000,
222 * Common map_io initialization
225 static void __init
h3xxx_map_io(void)
228 iotable_init(h3600_io_desc
, ARRAY_SIZE(h3600_io_desc
));
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 */
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
);
238 /* Configure suspend conditions */
240 PWER
= PWER_GPIO0
| PWER_RTC
;
244 sa1100fb_lcd_power
= h3xxx_lcd_power
;
247 /************************* H3100 *************************/
249 #ifdef CONFIG_SA1100_H3100
251 #define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
252 static unsigned int h3100_egpio
= 0;
254 static void h3100_control_egpio(enum ipaq_egpio_type x
, int setp
)
256 unsigned int egpio
= 0;
261 case IPAQ_EGPIO_LCD_POWER
:
262 egpio
|= EGPIO_H3600_LCD_ON
;
263 gpio
|= GPIO_H3100_LCD_3V_ON
;
265 case IPAQ_EGPIO_LCD_ENABLE
:
267 case IPAQ_EGPIO_CODEC_NRESET
:
268 egpio
|= EGPIO_H3600_CODEC_NRESET
;
270 case IPAQ_EGPIO_AUDIO_ON
:
271 gpio
|= GPIO_H3100_AUD_PWR_ON
274 case IPAQ_EGPIO_QMUTE
:
275 gpio
|= GPIO_H3100_QMUTE
;
277 case IPAQ_EGPIO_OPT_NVRAM_ON
:
278 egpio
|= EGPIO_H3600_OPT_NVRAM_ON
;
280 case IPAQ_EGPIO_OPT_ON
:
281 egpio
|= EGPIO_H3600_OPT_ON
;
283 case IPAQ_EGPIO_CARD_RESET
:
284 egpio
|= EGPIO_H3600_CARD_RESET
;
286 case IPAQ_EGPIO_OPT_RESET
:
287 egpio
|= EGPIO_H3600_OPT_RESET
;
289 case IPAQ_EGPIO_IR_ON
:
290 gpio
|= GPIO_H3100_IR_ON
;
292 case IPAQ_EGPIO_IR_FSEL
:
293 gpio
|= GPIO_H3100_IR_FSEL
;
295 case IPAQ_EGPIO_RS232_ON
:
296 egpio
|= EGPIO_H3600_RS232_ON
;
298 case IPAQ_EGPIO_VPP_ON
:
299 egpio
|= EGPIO_H3600_VPP_ON
;
304 local_irq_save(flags
);
306 h3100_egpio
|= egpio
;
309 h3100_egpio
&= ~egpio
;
312 H3100_EGPIO
= h3100_egpio
;
313 local_irq_restore(flags
);
317 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
320 | GPIO_H3100_LCD_3V_ON \
321 | GPIO_H3100_AUD_ON \
322 | GPIO_H3100_AUD_PWR_ON \
324 | GPIO_H3100_IR_FSEL)
326 static void __init
h3100_map_io(void)
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
|
337 /* Older bootldrs put GPIO2-9 in alternate mode on the
338 assumption that they are used for video */
339 GAFR
&= ~H3100_DIRECT_EGPIO
;
341 H3100_EGPIO
= h3100_egpio
;
342 assign_h3600_egpio
= h3100_control_egpio
;
346 * This turns the IRDA power on or off on the Compaq H3100
348 static int h3100_irda_set_power(struct device
*dev
, unsigned int state
)
350 gpio_set_value(H3100_GPIO_IR_ON
, state
);
354 static void h3100_irda_set_speed(struct device
*dev
, unsigned int speed
)
356 gpio_set_value(H3100_GPIO_IR_FSEL
, !(speed
< 4000000));
359 static struct irda_platform_data h3100_irda_data
= {
360 .set_power
= h3100_irda_set_power
,
361 .set_speed
= h3100_irda_set_speed
,
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" },
369 static void h3100_mach_init(void)
371 h3xxx_init_gpio(h3100_default_gpio
, ARRAY_SIZE(h3100_default_gpio
));
373 sa11x0_register_irda(&h3100_irda_data
);
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
,
386 #endif /* CONFIG_SA1100_H3100 */
388 /************************* H3600 *************************/
390 #ifdef CONFIG_SA1100_H3600
392 #define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
393 static unsigned int h3600_egpio
= EGPIO_H3600_RS232_ON
;
395 static void h3600_control_egpio(enum ipaq_egpio_type x
, int setp
)
397 unsigned int egpio
= 0;
401 case IPAQ_EGPIO_LCD_POWER
:
402 egpio
|= EGPIO_H3600_LCD_ON
|
403 EGPIO_H3600_LCD_PCI
|
404 EGPIO_H3600_LCD_5V_ON
|
407 case IPAQ_EGPIO_LCD_ENABLE
:
409 case IPAQ_EGPIO_CODEC_NRESET
:
410 egpio
|= EGPIO_H3600_CODEC_NRESET
;
412 case IPAQ_EGPIO_AUDIO_ON
:
413 egpio
|= EGPIO_H3600_AUD_AMP_ON
|
414 EGPIO_H3600_AUD_PWR_ON
;
416 case IPAQ_EGPIO_QMUTE
:
417 egpio
|= EGPIO_H3600_QMUTE
;
419 case IPAQ_EGPIO_OPT_NVRAM_ON
:
420 egpio
|= EGPIO_H3600_OPT_NVRAM_ON
;
422 case IPAQ_EGPIO_OPT_ON
:
423 egpio
|= EGPIO_H3600_OPT_ON
;
425 case IPAQ_EGPIO_CARD_RESET
:
426 egpio
|= EGPIO_H3600_CARD_RESET
;
428 case IPAQ_EGPIO_OPT_RESET
:
429 egpio
|= EGPIO_H3600_OPT_RESET
;
431 case IPAQ_EGPIO_IR_ON
:
432 egpio
|= EGPIO_H3600_IR_ON
;
434 case IPAQ_EGPIO_IR_FSEL
:
435 egpio
|= EGPIO_H3600_IR_FSEL
;
437 case IPAQ_EGPIO_RS232_ON
:
438 egpio
|= EGPIO_H3600_RS232_ON
;
440 case IPAQ_EGPIO_VPP_ON
:
441 egpio
|= EGPIO_H3600_VPP_ON
;
446 local_irq_save(flags
);
448 h3600_egpio
|= egpio
;
450 h3600_egpio
&= ~egpio
;
451 H3600_EGPIO
= h3600_egpio
;
452 local_irq_restore(flags
);
456 static void __init
h3600_map_io(void)
460 /* Initialize h3600-specific values here */
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
;
469 H3600_EGPIO
= h3600_egpio
; /* Maintains across sleep? */
470 assign_h3600_egpio
= h3600_control_egpio
;
474 * This turns the IRDA power on or off on the Compaq H3600
476 static int h3600_irda_set_power(struct device
*dev
, unsigned int state
)
478 assign_h3600_egpio(IPAQ_EGPIO_IR_ON
, state
);
482 static void h3600_irda_set_speed(struct device
*dev
, unsigned int speed
)
484 assign_h3600_egpio(IPAQ_EGPIO_IR_FSEL
, !(speed
< 4000000));
487 static struct irda_platform_data h3600_irda_data
= {
488 .set_power
= h3600_irda_set_power
,
489 .set_speed
= h3600_irda_set_speed
,
492 static void h3600_mach_init(void)
495 sa11x0_register_irda(&h3600_irda_data
);
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
,
508 #endif /* CONFIG_SA1100_H3600 */