2 * Hardware definitions for HP iPAQ Handheld Computers
4 * Copyright 2000-2003 Hewlett-Packard Company.
5 * Copyright 2004, 2005 Phil Blundell
7 * Use consistent with the GNU GPL is permitted,
8 * provided that this copyright notice is
9 * preserved in its entirety in all copies and derived works.
11 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
12 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
13 * FITNESS FOR ANY PARTICULAR PURPOSE.
15 * Author: Jamey Hicks.
19 * 2002-08-23 Jamey Hicks GPIO and IRQ support for iPAQ H5400
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/kernel.h>
26 #include <linux/tty.h>
27 #include <linux/sched.h>
28 #include <linux/interrupt.h>
30 #include <linux/bootmem.h>
31 #include <linux/delay.h>
32 #include <linux/platform_device.h>
34 #include <../drivers/video/pxafb.h>
35 #include <linux/input.h>
36 #include <linux/input_pda.h>
39 #include <asm/mach-types.h>
40 #include <asm/hardware.h>
41 #include <asm/setup.h>
43 #include <asm/mach/irq.h>
44 #include <asm/mach/arch.h>
45 #include <asm/mach/map.h>
46 #include <asm/arch/h5400-gpio.h>
47 #include <asm/arch/h5400-asic.h>
48 #include <asm/arch/h5400-init.h>
49 #include <asm/arch/ipaq.h>
50 #include <asm/arch/udc.h>
52 #include <asm/arch/pxa-regs.h>
53 #include <asm/arch/serial.h>
54 #include <asm/hardware/gpio_keys.h>
55 #include <asm/arch/pxa-dmabounce.h>
56 #include <asm/arch/irq.h>
57 #include <asm/types.h>
58 #include <asm/hardware/samcop_base.h>
60 #include "../generic.h"
62 /***********************************************************************************/
64 /***********************************************************************************/
68 static void h5400_control_egpio( enum ipaq_egpio_type x
, int setp
)
72 case IPAQ_EGPIO_RS232_ON
:
73 SET_H5400_GPIO (POWER_RS232_N
, !setp
);
77 printk("%s: unhandled ipaq gpio=%d\n", __FUNCTION__
, x
);
81 static void h5400_set_led (enum led_color color
, int duty_time
, int cycle_time
)
83 static const u8 h5400_lednum
[5] = { 4, 0, 1, 2, 3 };
84 static unsigned long led_state
;
88 lednum
= h5400_lednum
[color
];
89 ledvalue
= duty_time
? 0x3 | (duty_time
<< 4) | (cycle_time
<< 12) : 0;
91 local_irq_save (flags
);
93 /* Clock needs to be left enabled if any LEDs are flashing */
94 if (duty_time
&& (duty_time
< cycle_time
))
95 led_state
|= 1 << lednum
;
97 led_state
&= ~1 << lednum
;
99 H5400_ASIC_CPM_ClockControl
|= H5400_ASIC_CPM_CLKCON_LED_CLKEN
;
101 H5400_ASIC_LED_CONTROL(lednum
) = ledvalue
;
104 H5400_ASIC_CPM_ClockControl
&= ~H5400_ASIC_CPM_CLKCON_LED_CLKEN
;
106 local_irq_restore (flags
);
111 /****************************************************************************
112 * Bluetooth functions and data structures
113 ****************************************************************************/
115 /* We need a little magic function switching here to keep samcop_base as
119 void (*h5400_set_samcop_gpio_b
) (struct device
*dev
, u32 mask
, u32 bits
);
120 EXPORT_SYMBOL(h5400_set_samcop_gpio_b
);
123 h5400_set_gpio_b (struct device
*dev
, u32 mask
, u32 bits
)
125 if (h5400_set_samcop_gpio_b
)
126 h5400_set_samcop_gpio_b(dev
, mask
, bits
);
129 static void h5400_bluetooth_power(int on
)
132 /* apply reset. The chip requires that the reset pins go
133 * high 2ms after voltage is applied to VCC and IOVCC. So it
134 * is driven low now before we set the power pins. It
135 * is assumed that the reset pins are tied together
136 * on the h5[1,4,5]xx handhelds. */
137 SET_H5400_GPIO(BT_M_RESET
, !on
);
139 /* Select the 'operating environment' pins to run/normal mode.
140 * Setting these pins to ENV_0 = 0 and ENV_1 = 1 would put the
141 * In-System-Programming (ISP) mode. In theory that would
142 * allow the host computer to rewrite the firmware.
144 SET_H5400_GPIO(BT_ENV_0
, on
);
145 SET_H5400_GPIO(BT_ENV_1
, on
);
146 /* configure power pins */
147 h5400_set_gpio_b(&h5400_samcop
.dev
,
148 SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON
,
149 SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON
);
150 SET_H5400_GPIO(BT_2V8_N
, !on
);
151 /* A 2ms delay between voltage application and reset driven
152 * high is a requirement of the power-on cycle of the device.
155 SET_H5400_GPIO(BT_M_RESET
, on
);
157 h5400_set_gpio_b(&h5400_samcop
.dev
,
158 SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON
,
159 ~SAMCOP_GPIO_GPB_BLUETOOTH_3V0_ON
);
160 SET_H5400_GPIO(BT_2V8_N
, !on
);
164 static void h5400_btuart_configure(int state
)
167 case PXA_UART_CFG_PRE_STARTUP
:
168 pxa_gpio_mode(GPIO42_BTRXD_MD
);
169 pxa_gpio_mode(GPIO43_BTTXD_MD
);
170 pxa_gpio_mode(GPIO44_BTCTS_MD
);
171 pxa_gpio_mode(GPIO45_BTRTS_MD
);
172 h5400_bluetooth_power(1);
175 case PXA_UART_CFG_PRE_SHUTDOWN
:
176 h5400_bluetooth_power(0);
184 static void h5400_hwuart_configure(int state
)
187 case PXA_UART_CFG_PRE_STARTUP
:
188 pxa_gpio_mode(GPIO42_HWRXD_MD
);
189 pxa_gpio_mode(GPIO43_HWTXD_MD
);
190 pxa_gpio_mode(GPIO44_HWCTS_MD
);
191 pxa_gpio_mode(GPIO45_HWRTS_MD
);
192 h5400_bluetooth_power(1);
195 case PXA_UART_CFG_PRE_SHUTDOWN
:
196 h5400_bluetooth_power(0);
204 static struct platform_pxa_serial_funcs h5400_btuart_funcs
= {
205 .configure
= h5400_btuart_configure
,
208 static struct platform_pxa_serial_funcs h5400_hwuart_funcs
= {
209 .configure
= h5400_hwuart_configure
,
212 static __inline__
void
215 /* fix CS0 for h5400 flash. */
216 /* fix CS1 for MediaQ chip. select 16-bit bus and vlio. */
217 /* fix CS5 for SAMCOP. */
225 MDREFR
|= 0x02080000;
229 static int h5400_pm_callback( int req
)
232 static int gpio_0
, gpio_1
, gpio_2
; /* PXA GPIOs */
234 printk("%s: %d\n", __FUNCTION__
, req
);
238 /* bootldr will have screwed up MSCs, so set them right again */
242 H5400_ASIC_GPIO_GPA_DAT
= gpio_a
;
243 H5400_ASIC_GPIO_GPB_DAT
= gpio_b
;
254 if ( ipaq_model_ops
.pm_callback_aux
)
255 result
= ipaq_model_ops
.pm_callback_aux(req
);
261 if ( ipaq_model_ops
.pm_callback_aux
&&
262 ((result
= ipaq_model_ops
.pm_callback_aux(req
)) != 0))
267 gpio_a
= H5400_ASIC_GPIO_GPA_DAT
;
268 gpio_b
= H5400_ASIC_GPIO_GPB_DAT
;
277 printk("%s: unrecognized PM callback\n", __FUNCTION__
);
284 /***********************************************************************************/
286 /***********************************************************************************/
290 /***********************************************************************************/
292 /***********************************************************************************/
294 static short h5400_gpio_modes
[] __initdata
= {
295 GPIO_NR_H5400_POWER_BUTTON
| GPIO_IN
, /* GPIO0 */
296 GPIO_NR_H5400_RESET_BUTTON_N
| GPIO_IN
, /* GPIO1 */
297 GPIO_NR_H5400_OPT_INT
| GPIO_IN
, /* GPIO2 */
298 GPIO_NR_H5400_BACKUP_POWER
| GPIO_IN
, /* GPIO3 */ /* XXX should be an output? */
299 GPIO_NR_H5400_ACTION_BUTTON
| GPIO_IN
, /* GPIO4 */
300 GPIO_NR_H5400_COM_DCD_SOMETHING
| GPIO_IN
, /* GPIO5 */
301 6 | GPIO_IN
, /* GPIO6 NC */
302 GPIO_NR_H5400_RESET_BUTTON_AGAIN_N
| GPIO_IN
, /* GPIO7 */
303 8 | GPIO_OUT
, /* GPIO8 NC */
304 GPIO_NR_H5400_RSO_N
| GPIO_IN
, /* GPIO9 BATT_FAULT */
305 GPIO_NR_H5400_ASIC_INT_N
| GPIO_IN
, /* GPIO10 */
306 GPIO_NR_H5400_BT_ENV_0
| GPIO_OUT
, /* GPIO11 */
307 GPIO12_32KHz_MD
| GPIO_OUT
, /* GPIO12 NC */
308 GPIO_NR_H5400_BT_ENV_1
| GPIO_OUT
, /* GPIO13 */
309 GPIO_NR_H5400_BT_WU
| GPIO_IN
, /* GPIO14 */
310 GPIO15_nCS_1_MD
, /* GPIO15 */
311 16 | GPIO_OUT
, /* GPIO16 NC */
312 17 | GPIO_OUT
, /* GPIO17 NC */
314 22 | GPIO_OUT
, /* GPIO22 NC */
316 GPIO_NR_H5400_OPT_SPI_CS_N
| GPIO_OUT
,
319 27 | GPIO_OUT
, /* GPIO27 NC */
334 GPIO_NR_H5400_IRDA_SD
| GPIO_OUT
, /* GPIO58 */
335 59 | GPIO_OUT
, /* GPIO59 XXX docs say "usb charge on" input */
336 GPIO_NR_H5400_POWER_SD_N
| GPIO_OUT
, /* GPIO60 XXX not really active low? */
337 GPIO_NR_H5400_POWER_RS232_N
| GPIO_OUT
| GPIO_DFLT_HIGH
,
338 GPIO_NR_H5400_POWER_ACCEL_N
| GPIO_OUT
| GPIO_DFLT_HIGH
,
339 63 | GPIO_OUT
, /* GPIO63 NC */
340 GPIO_NR_H5400_OPT_NVRAM
| GPIO_OUT
,
341 GPIO_NR_H5400_CHG_EN
| GPIO_OUT
,
342 GPIO_NR_H5400_USB_PULLUP
| GPIO_OUT
,
343 GPIO_NR_H5400_BT_2V8_N
| GPIO_OUT
| GPIO_DFLT_HIGH
,
344 GPIO_NR_H5400_EXT_CHG_RATE
| GPIO_OUT
,
345 69 | GPIO_OUT
, /* GPIO69 NC */
346 GPIO_NR_H5400_CIR_RESET
| GPIO_OUT
,
347 GPIO_NR_H5400_POWER_LIGHT_SENSOR_N
| GPIO_OUT
| GPIO_DFLT_HIGH
,
348 GPIO_NR_H5400_BT_M_RESET
| GPIO_OUT
,
349 GPIO_NR_H5400_STD_CHG_RATE
| GPIO_OUT
,
350 GPIO_NR_H5400_SD_WP_N
| GPIO_IN
, /* GPIO74 XXX docs say output */
351 GPIO_NR_H5400_MOTOR_ON_N
| GPIO_OUT
| GPIO_DFLT_HIGH
,
352 GPIO_NR_H5400_HEADPHONE_DETECT
| GPIO_IN
,
353 GPIO_NR_H5400_USB_CHG_RATE
| GPIO_OUT
,
359 static void __init
h5400_map_io(void)
366 /* Configure power management stuff. */
367 PWER
= PWER_GPIO0
| PWER_RTC
;
368 PFER
= PWER_GPIO0
| PWER_RTC
;
374 h5400_asic_write_register (H5400_ASIC_CPM_ClockControl
, H5400_ASIC_CPM_CLKCON_LED_CLKEN
);
375 h5400_asic_write_register (H5400_ASIC_LED_LEDPS
, 0xf42400); /* 4Hz */
377 H5400_ASIC_SET_BIT (H5400_ASIC_CPM_ClockControl
, H5400_ASIC_CPM_CLKCON_GPIO_CLKEN
);
378 H5400_ASIC_SET_BIT (H5400_ASIC_GPIO_GPA_CON2
, 0x16);
381 for (i
= 0; i
< ARRAY_SIZE(h5400_gpio_modes
); i
++) {
382 int mode
= h5400_gpio_modes
[i
];
387 /* Does not currently work */
388 /* Add wakeup on AC plug/unplug */
394 /* Set sleep states for PXA GPIOs */
395 PGSR0
= GPSRx_SleepValue
;
396 PGSR1
= GPSRy_SleepValue
;
397 PGSR2
= GPSRz_SleepValue
;
399 /* hook up btuart & hwuart and power bluetooth */
400 /* The h54xx has pxa-250, so it gets btuart */
401 /* and h51xx and h55xx have pxa-255, so they get hwuart */
402 cpuid
= read_cpuid(CPUID_ID
);
403 if (((cpuid
>> 4) & 0xfff) == 0x2d0) {
404 hwuart_device
.dev
.platform_data
= &h5400_hwuart_funcs
;
406 btuart_device
.dev
.platform_data
= &h5400_btuart_funcs
;
410 /* ------------------- */
413 h5400_udc_is_connected (void)
419 h5400_udc_command (int cmd
)
423 case PXA2XX_UDC_CMD_DISCONNECT
:
424 GPCR(GPIO_NR_H5400_USB_PULLUP
) |= GPIO_bit(GPIO_NR_H5400_USB_PULLUP
);
425 GPDR(GPIO_NR_H5400_USB_PULLUP
) &= ~GPIO_bit(GPIO_NR_H5400_USB_PULLUP
);
427 case PXA2XX_UDC_CMD_CONNECT
:
428 GPDR(GPIO_NR_H5400_USB_PULLUP
) |= GPIO_bit(GPIO_NR_H5400_USB_PULLUP
);
429 GPSR(GPIO_NR_H5400_USB_PULLUP
) |= GPIO_bit(GPIO_NR_H5400_USB_PULLUP
);
432 printk("_udc_control: unknown command!\n");
437 static struct pxa2xx_udc_mach_info h5400_udc_mach_info
= {
438 .udc_is_connected
= h5400_udc_is_connected
,
439 .udc_command
= h5400_udc_command
,
442 /* ------------------- */
444 static struct resource samcop_resources
[] = {
446 .start
= H5400_SAMCOP_BASE
,
447 .end
= H5400_SAMCOP_BASE
+ 0x00ffffff,
448 .flags
= IORESOURCE_MEM
,
451 .start
= IRQ_GPIO_H5400_ASIC_INT
,
452 .flags
= IORESOURCE_IRQ
,
456 static struct samcop_platform_data samcop_platform_data
= {
457 .clocksleep
= SAMCOP_CPM_CLKSLEEP_UCLK_ON
,
458 .pllcontrol
= 0x60002, /* value from wince via bootblaster */
461 struct platform_device h5400_samcop
= {
464 .num_resources
= ARRAY_SIZE(samcop_resources
),
465 .resource
= samcop_resources
,
467 .platform_data
= &samcop_platform_data
,
470 EXPORT_SYMBOL(h5400_samcop
);
472 static struct gpio_keys_button h5400_button_table
[] = {
473 { _KEY_POWER
, GPIO_NR_H5400_POWER_BUTTON
, 1 },
476 static struct gpio_keys_platform_data h5400_pxa_keys_data
= {
477 .buttons
= h5400_button_table
,
478 .nbuttons
= ARRAY_SIZE(h5400_button_table
),
481 static struct platform_device h5400_pxa_keys
= {
484 .platform_data
= &h5400_pxa_keys_data
,
491 platform_device_register (&h5400_samcop
);
492 platform_device_register (&h5400_pxa_keys
);
493 pxa_set_udc_info (&h5400_udc_mach_info
);
496 MACHINE_START(H5400
, "HP iPAQ H5400")
497 .phys_io
= 0x40000000,
498 .io_pg_offst
= (io_p2v(0x40000000) >> 18) & 0xfffc,
499 .boot_params
= 0xa0000100,
500 .map_io
= h5400_map_io
,
501 .init_irq
= pxa_init_irq
,
503 .init_machine
= h5400_init
,