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",
97 static struct mtd_partition h3xxx_partitions
[] = {
99 .name
= "H3XXX boot firmware",
102 .mask_flags
= MTD_WRITEABLE
, /* force read-only */
104 .name
= "H3XXX rootfs",
105 .size
= MTDPART_SIZ_FULL
,
106 .offset
= 0x00040000,
110 static void h3xxx_set_vpp(int vpp
)
112 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON
, vpp
);
115 static struct flash_platform_data h3xxx_flash_data
= {
116 .map_name
= "cfi_probe",
117 .set_vpp
= h3xxx_set_vpp
,
118 .parts
= h3xxx_partitions
,
119 .nr_parts
= ARRAY_SIZE(h3xxx_partitions
),
122 static struct resource h3xxx_flash_resource
= {
123 .start
= SA1100_CS0_PHYS
,
124 .end
= SA1100_CS0_PHYS
+ SZ_32M
- 1,
125 .flags
= IORESOURCE_MEM
,
132 static void h3xxx_uart_set_mctrl(struct uart_port
*port
, u_int mctrl
)
134 if (port
->mapbase
== _Ser3UTCR0
) {
135 gpio_set_value(H3XXX_GPIO_COM_RTS
, !(mctrl
& TIOCM_RTS
));
139 static u_int
h3xxx_uart_get_mctrl(struct uart_port
*port
)
141 u_int ret
= TIOCM_CD
| TIOCM_CTS
| TIOCM_DSR
;
143 if (port
->mapbase
== _Ser3UTCR0
) {
145 * DCD and CTS bits are inverted in GPLR by RS232 transceiver
147 if (gpio_get_value(H3XXX_GPIO_COM_DCD
))
149 if (gpio_get_value(H3XXX_GPIO_COM_CTS
))
156 static void h3xxx_uart_pm(struct uart_port
*port
, u_int state
, u_int oldstate
)
158 if (port
->mapbase
== _Ser2UTCR0
) { /* TODO: REMOVE THIS */
159 assign_h3600_egpio(IPAQ_EGPIO_IR_ON
, !state
);
160 } else if (port
->mapbase
== _Ser3UTCR0
) {
161 assign_h3600_egpio(IPAQ_EGPIO_RS232_ON
, !state
);
166 * Enable/Disable wake up events for this serial port.
167 * Obviously, we only support this on the normal COM port.
169 static int h3xxx_uart_set_wake(struct uart_port
*port
, u_int enable
)
173 if (port
->mapbase
== _Ser3UTCR0
) {
175 PWER
|= PWER_GPIO23
| PWER_GPIO25
; /* DCD and CTS */
177 PWER
&= ~(PWER_GPIO23
| PWER_GPIO25
); /* DCD and CTS */
183 static struct sa1100_port_fns h3xxx_port_fns __initdata
= {
184 .set_mctrl
= h3xxx_uart_set_mctrl
,
185 .get_mctrl
= h3xxx_uart_get_mctrl
,
187 .set_wake
= h3xxx_uart_set_wake
,
191 static void __init
h3xxx_mach_init(void)
193 sa1100_register_uart_fns(&h3xxx_port_fns
);
194 sa11x0_register_mtd(&h3xxx_flash_data
, &h3xxx_flash_resource
, 1);
198 * helper for sa1100fb
200 static void h3xxx_lcd_power(int enable
)
202 assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER
, enable
);
205 static struct map_desc h3600_io_desc
[] __initdata
= {
206 { /* static memory bank 2 CS#2 */
207 .virtual = H3600_BANK_2_VIRT
,
208 .pfn
= __phys_to_pfn(SA1100_CS2_PHYS
),
209 .length
= 0x02800000,
211 }, { /* static memory bank 4 CS#4 */
212 .virtual = H3600_BANK_4_VIRT
,
213 .pfn
= __phys_to_pfn(SA1100_CS4_PHYS
),
214 .length
= 0x00800000,
216 }, { /* EGPIO 0 CS#5 */
217 .virtual = H3600_EGPIO_VIRT
,
218 .pfn
= __phys_to_pfn(H3600_EGPIO_PHYS
),
219 .length
= 0x01000000,
225 * Common map_io initialization
228 static void __init
h3xxx_map_io(void)
231 iotable_init(h3600_io_desc
, ARRAY_SIZE(h3600_io_desc
));
233 sa1100_register_uart(0, 3); /* Common serial port */
234 // sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
236 /* Ensure those pins are outputs and driving low */
237 PPDR
|= PPC_TXD4
| PPC_SCLK
| PPC_SFRM
;
238 PPSR
&= ~(PPC_TXD4
| PPC_SCLK
| PPC_SFRM
);
240 /* Configure suspend conditions */
246 sa1100fb_lcd_power
= h3xxx_lcd_power
;
249 /************************* H3100 *************************/
251 #ifdef CONFIG_SA1100_H3100
253 #define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
254 static unsigned int h3100_egpio
= 0;
256 static void h3100_control_egpio(enum ipaq_egpio_type x
, int setp
)
258 unsigned int egpio
= 0;
263 case IPAQ_EGPIO_LCD_POWER
:
264 egpio
|= EGPIO_H3600_LCD_ON
;
265 gpio
|= GPIO_H3100_LCD_3V_ON
;
267 case IPAQ_EGPIO_LCD_ENABLE
:
269 case IPAQ_EGPIO_CODEC_NRESET
:
270 egpio
|= EGPIO_H3600_CODEC_NRESET
;
272 case IPAQ_EGPIO_AUDIO_ON
:
273 gpio
|= GPIO_H3100_AUD_PWR_ON
276 case IPAQ_EGPIO_QMUTE
:
277 gpio
|= GPIO_H3100_QMUTE
;
279 case IPAQ_EGPIO_OPT_NVRAM_ON
:
280 egpio
|= EGPIO_H3600_OPT_NVRAM_ON
;
282 case IPAQ_EGPIO_OPT_ON
:
283 egpio
|= EGPIO_H3600_OPT_ON
;
285 case IPAQ_EGPIO_CARD_RESET
:
286 egpio
|= EGPIO_H3600_CARD_RESET
;
288 case IPAQ_EGPIO_OPT_RESET
:
289 egpio
|= EGPIO_H3600_OPT_RESET
;
291 case IPAQ_EGPIO_IR_ON
:
292 gpio
|= GPIO_H3100_IR_ON
;
294 case IPAQ_EGPIO_IR_FSEL
:
295 gpio
|= GPIO_H3100_IR_FSEL
;
297 case IPAQ_EGPIO_RS232_ON
:
298 egpio
|= EGPIO_H3600_RS232_ON
;
300 case IPAQ_EGPIO_VPP_ON
:
301 egpio
|= EGPIO_H3600_VPP_ON
;
306 local_irq_save(flags
);
308 h3100_egpio
|= egpio
;
311 h3100_egpio
&= ~egpio
;
314 H3100_EGPIO
= h3100_egpio
;
315 local_irq_restore(flags
);
319 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
322 | GPIO_H3100_LCD_3V_ON \
323 | GPIO_H3100_AUD_ON \
324 | GPIO_H3100_AUD_PWR_ON \
326 | GPIO_H3100_IR_FSEL)
328 static void __init
h3100_map_io(void)
332 /* Initialize h3100-specific values here */
333 GPCR
= 0x0fffffff; /* All outputs are set low by default */
334 GPDR
= GPIO_H3600_L3_CLOCK
|
335 GPIO_H3600_L3_MODE
| GPIO_H3600_L3_DATA
|
336 GPIO_H3600_CLK_SET1
| GPIO_H3600_CLK_SET0
|
339 /* Older bootldrs put GPIO2-9 in alternate mode on the
340 assumption that they are used for video */
341 GAFR
&= ~H3100_DIRECT_EGPIO
;
343 H3100_EGPIO
= h3100_egpio
;
344 assign_h3600_egpio
= h3100_control_egpio
;
348 * This turns the IRDA power on or off on the Compaq H3100
350 static int h3100_irda_set_power(struct device
*dev
, unsigned int state
)
352 gpio_set_value(H3100_GPIO_IR_ON
, state
);
356 static void h3100_irda_set_speed(struct device
*dev
, unsigned int speed
)
358 gpio_set_value(H3100_GPIO_IR_FSEL
, !(speed
< 4000000));
361 static struct irda_platform_data h3100_irda_data
= {
362 .set_power
= h3100_irda_set_power
,
363 .set_speed
= h3100_irda_set_speed
,
366 static struct gpio_default_state h3100_default_gpio
[] = {
367 { H3100_GPIO_IR_ON
, GPIO_MODE_OUT0
, "IrDA power" },
368 { H3100_GPIO_IR_FSEL
, GPIO_MODE_OUT0
, "IrDA fsel" },
369 { H3XXX_GPIO_COM_DCD
, GPIO_MODE_IN
, "COM DCD" },
370 { H3XXX_GPIO_COM_CTS
, GPIO_MODE_IN
, "COM CTS" },
371 { H3XXX_GPIO_COM_RTS
, GPIO_MODE_OUT0
, "COM RTS" },
374 static void __init
h3100_mach_init(void)
376 h3xxx_init_gpio(h3100_default_gpio
, ARRAY_SIZE(h3100_default_gpio
));
378 sa11x0_register_irda(&h3100_irda_data
);
381 MACHINE_START(H3100
, "Compaq iPAQ H3100")
382 .phys_io
= 0x80000000,
383 .io_pg_offst
= ((0xf8000000) >> 18) & 0xfffc,
384 .boot_params
= 0xc0000100,
385 .map_io
= h3100_map_io
,
386 .init_irq
= sa1100_init_irq
,
387 .timer
= &sa1100_timer
,
388 .init_machine
= h3100_mach_init
,
391 #endif /* CONFIG_SA1100_H3100 */
393 /************************* H3600 *************************/
395 #ifdef CONFIG_SA1100_H3600
397 #define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
398 static unsigned int h3600_egpio
= EGPIO_H3600_RS232_ON
;
400 static void h3600_control_egpio(enum ipaq_egpio_type x
, int setp
)
402 unsigned int egpio
= 0;
406 case IPAQ_EGPIO_LCD_POWER
:
407 egpio
|= EGPIO_H3600_LCD_ON
|
408 EGPIO_H3600_LCD_PCI
|
409 EGPIO_H3600_LCD_5V_ON
|
412 case IPAQ_EGPIO_LCD_ENABLE
:
414 case IPAQ_EGPIO_CODEC_NRESET
:
415 egpio
|= EGPIO_H3600_CODEC_NRESET
;
417 case IPAQ_EGPIO_AUDIO_ON
:
418 egpio
|= EGPIO_H3600_AUD_AMP_ON
|
419 EGPIO_H3600_AUD_PWR_ON
;
421 case IPAQ_EGPIO_QMUTE
:
422 egpio
|= EGPIO_H3600_QMUTE
;
424 case IPAQ_EGPIO_OPT_NVRAM_ON
:
425 egpio
|= EGPIO_H3600_OPT_NVRAM_ON
;
427 case IPAQ_EGPIO_OPT_ON
:
428 egpio
|= EGPIO_H3600_OPT_ON
;
430 case IPAQ_EGPIO_CARD_RESET
:
431 egpio
|= EGPIO_H3600_CARD_RESET
;
433 case IPAQ_EGPIO_OPT_RESET
:
434 egpio
|= EGPIO_H3600_OPT_RESET
;
436 case IPAQ_EGPIO_IR_ON
:
437 egpio
|= EGPIO_H3600_IR_ON
;
439 case IPAQ_EGPIO_IR_FSEL
:
440 egpio
|= EGPIO_H3600_IR_FSEL
;
442 case IPAQ_EGPIO_RS232_ON
:
443 egpio
|= EGPIO_H3600_RS232_ON
;
445 case IPAQ_EGPIO_VPP_ON
:
446 egpio
|= EGPIO_H3600_VPP_ON
;
451 local_irq_save(flags
);
453 h3600_egpio
|= egpio
;
455 h3600_egpio
&= ~egpio
;
456 H3600_EGPIO
= h3600_egpio
;
457 local_irq_restore(flags
);
461 static void __init
h3600_map_io(void)
465 /* Initialize h3600-specific values here */
467 GPCR
= 0x0fffffff; /* All outputs are set low by default */
468 GPDR
= GPIO_H3600_L3_CLOCK
|
469 GPIO_H3600_L3_MODE
| GPIO_H3600_L3_DATA
|
470 GPIO_H3600_CLK_SET1
| GPIO_H3600_CLK_SET0
|
471 GPIO_LDD15
| GPIO_LDD14
| GPIO_LDD13
| GPIO_LDD12
|
472 GPIO_LDD11
| GPIO_LDD10
| GPIO_LDD9
| GPIO_LDD8
;
474 H3600_EGPIO
= h3600_egpio
; /* Maintains across sleep? */
475 assign_h3600_egpio
= h3600_control_egpio
;
479 * This turns the IRDA power on or off on the Compaq H3600
481 static int h3600_irda_set_power(struct device
*dev
, unsigned int state
)
483 assign_h3600_egpio(IPAQ_EGPIO_IR_ON
, state
);
487 static void h3600_irda_set_speed(struct device
*dev
, unsigned int speed
)
489 assign_h3600_egpio(IPAQ_EGPIO_IR_FSEL
, !(speed
< 4000000));
492 static struct irda_platform_data h3600_irda_data
= {
493 .set_power
= h3600_irda_set_power
,
494 .set_speed
= h3600_irda_set_speed
,
497 static struct gpio_default_state h3600_default_gpio
[] = {
498 { H3XXX_GPIO_COM_DCD
, GPIO_MODE_IN
, "COM DCD" },
499 { H3XXX_GPIO_COM_CTS
, GPIO_MODE_IN
, "COM CTS" },
500 { H3XXX_GPIO_COM_RTS
, GPIO_MODE_OUT0
, "COM RTS" },
503 static void __init
h3600_mach_init(void)
505 h3xxx_init_gpio(h3600_default_gpio
, ARRAY_SIZE(h3600_default_gpio
));
507 sa11x0_register_irda(&h3600_irda_data
);
510 MACHINE_START(H3600
, "Compaq iPAQ H3600")
511 .phys_io
= 0x80000000,
512 .io_pg_offst
= ((0xf8000000) >> 18) & 0xfffc,
513 .boot_params
= 0xc0000100,
514 .map_io
= h3600_map_io
,
515 .init_irq
= sa1100_init_irq
,
516 .timer
= &sa1100_timer
,
517 .init_machine
= h3600_mach_init
,
520 #endif /* CONFIG_SA1100_H3600 */