2 * Hardware definitions for HP iPAQ Handheld Computers
4 * Copyright 2000-2004 Hewlett-Packard Company.
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 * See http://cvs.handhelds.org/cgi-bin/viewcvs.cgi/linux/kernel26/arch/arm/mach-pxa/h2200.c
17 * for the history of changes.
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/kernel.h>
23 #include <linux/notifier.h>
24 #include <linux/tty.h>
25 #include <linux/sched.h>
26 #include <linux/interrupt.h>
28 #include <linux/bootmem.h>
29 #include <linux/delay.h>
30 #include <linux/device.h>
31 #include <linux/platform_device.h>
32 #include <linux/lcd.h>
33 #include <linux/backlight.h>
36 #include <asm/types.h>
38 #include <asm/mach-types.h>
39 #include <asm/hardware.h>
40 #include <asm/setup.h>
42 #include <asm/arch/irq.h>
43 #include <asm/arch/irda.h>
44 #include <asm/arch/udc.h>
45 #include <asm/arch/pxa-regs.h>
47 #include <asm/mach/irq.h>
48 #include <asm/mach/arch.h>
49 #include <asm/mach/map.h>
51 #include <asm/hardware/gpio_keys.h>
52 #include <asm/hardware/hamcop_base.h>
53 #include <asm/hardware/ipaq-hamcop.h>
54 #include <asm/arch/serial.h>
55 #include <asm/arch/h2200-asic.h>
56 #include <asm/arch/h2200-gpio.h>
57 #include <asm/arch/h2200-irqs.h>
58 #include <asm/arch/h2200-init.h>
60 #include "../generic.h"
63 /***************************************************************************/
65 /***************************************************************************/
67 void (*h2200_led_hook
) (struct device
*dev
, int led_num
, int duty_time
,
69 EXPORT_SYMBOL(h2200_led_hook
);
72 h2200_set_led (int led_num
, int duty_time
, int cycle_time
)
75 h2200_led_hook(&h2200_hamcop
.dev
, led_num
, duty_time
, cycle_time
);
77 EXPORT_SYMBOL(h2200_set_led
);
79 /***************************************************************************/
81 /***************************************************************************/
83 /* XXX What are CIR_RESET and CIR_POWER_ON for? */
84 static void h2200_irda_transceiver_mode(struct device
*dev
, int mode
)
88 local_irq_save(flags
);
91 SET_H2200_GPIO_N(IR_ON
, 0);
93 SET_H2200_GPIO_N(IR_ON
, 1);
95 local_irq_restore(flags
);
99 static struct pxaficp_platform_data h2200_ficp_platform_data
= {
100 .transceiver_cap
= IR_SIRMODE
| IR_OFF
,
101 .transceiver_mode
= h2200_irda_transceiver_mode
,
104 /* Uncomment the following line to get serial console via SIR work from
105 * the very early booting stage. This is not useful for end-user.
107 // #define EARLY_SIR_CONSOLE
109 #define IR_TRANSCEIVER_ON \
110 SET_H2200_GPIO_N(IR_ON, 1);
112 #define IR_TRANSCEIVER_OFF \
113 SET_H2200_GPIO_N(IR_ON, 0);
117 h2200_irda_configure(int state
)
119 /* Switch STUART RX/TX pins to SIR */
120 pxa_gpio_mode(GPIO46_STRXD_MD
);
121 pxa_gpio_mode(GPIO47_STTXD_MD
);
122 /* make sure FIR ICP is off */
127 case PXA_UART_CFG_POST_STARTUP
: /* post UART enable */
128 /* configure STUART to for SIR */
129 STISR
= STISR_XMODE
| STISR_RCVEIR
| STISR_RXPL
;
133 case PXA_UART_CFG_POST_SHUTDOWN
: /* UART disabled */
144 h2200_irda_set_txrx(int txrx
)
146 unsigned old_stisr
= STISR
;
147 unsigned new_stisr
= old_stisr
;
149 if (txrx
& PXA_SERIAL_TX
) {
150 /* Ignore RX if TX is set */
151 txrx
&= PXA_SERIAL_TX
;
152 new_stisr
|= STISR_XMITIR
;
154 new_stisr
&= ~STISR_XMITIR
;
156 if (txrx
& PXA_SERIAL_RX
)
157 new_stisr
|= STISR_RCVEIR
;
159 new_stisr
&= ~STISR_RCVEIR
;
161 if (new_stisr
!= old_stisr
) {
162 while (!(STLSR
& LSR_TEMT
)) ;
170 h2200_irda_get_txrx(void)
172 return ((STISR
& STISR_XMITIR
) ? PXA_SERIAL_TX
: 0) |
173 ((STISR
& STISR_RCVEIR
) ? PXA_SERIAL_RX
: 0);
176 static struct platform_pxa_serial_funcs h2200_irda_funcs
= {
177 .configure
= h2200_irda_configure
,
178 .set_txrx
= h2200_irda_set_txrx
,
179 .get_txrx
= h2200_irda_get_txrx
,
183 /***************************************************************************/
185 /***************************************************************************/
187 static void h2200_bluetooth_power(int on
)
190 /* Power-up and reset the Zeevo. */
191 SET_H2200_GPIO(BT_POWER_ON
, 0); /* Make sure it's off. */
192 SET_H2200_GPIO(BT_RESET_N
, 1); /* Deassert reset. */
194 SET_H2200_GPIO(BT_POWER_ON
, 1); /* Power on. */
196 /* XXX This seems too long, but anything shorter makes
199 h2200_set_led(2, 1, 31);
201 /* Turn off the Zeevo. */
202 /* XXX Assert reset? */
203 SET_H2200_GPIO(BT_POWER_ON
, 0);
204 h2200_set_led(2, 0, 0);
209 h2200_btuart_configure(int state
)
213 case PXA_UART_CFG_PRE_STARTUP
: /* pre UART enable */
214 pxa_gpio_mode(GPIO42_BTRXD_MD
);
215 pxa_gpio_mode(GPIO43_BTTXD_MD
);
216 pxa_gpio_mode(GPIO44_BTCTS_MD
);
217 pxa_gpio_mode(GPIO45_BTRTS_MD
);
218 h2200_bluetooth_power(1);
221 case PXA_UART_CFG_POST_SHUTDOWN
: /* post UART disable */
222 h2200_bluetooth_power(0);
231 h2200_hwuart_configure(int state
)
235 case PXA_UART_CFG_PRE_STARTUP
: /* post UART enable */
236 pxa_gpio_mode(GPIO42_HWRXD_MD
);
237 pxa_gpio_mode(GPIO43_HWTXD_MD
);
238 pxa_gpio_mode(GPIO44_HWCTS_MD
);
239 pxa_gpio_mode(GPIO45_HWRTS_MD
);
240 h2200_bluetooth_power(1);
243 case PXA_UART_CFG_POST_SHUTDOWN
: /* post UART disable */
244 h2200_bluetooth_power(0);
253 static struct platform_pxa_serial_funcs h2200_btuart_funcs
= {
254 .configure
= h2200_btuart_configure
,
257 static struct platform_pxa_serial_funcs h2200_hwuart_funcs
= {
258 .configure
= h2200_hwuart_configure
,
261 /***************************************************************************/
263 /***************************************************************************/
265 static void check_serial_cable (void)
267 #warning check_serial_cable really needs a userland API, as opposed to being handled by the kernel.
268 // XXX: Should this be handled better?
269 int connected
= 1; //GET_H2200_GPIO(RS232_DCD);
270 /* Toggle rs232 transceiver power according to connected status */
271 SET_H2200_GPIO(RS232_ON
, connected
);
272 /* Toggle rs232 vs CIR IC connected to FFUART. XXX: Should be connected == 0, but forcing on to prevent apps using the serial port from screwing up. */
273 /* Should we make apps explicitly request CIR? */
274 SET_H2200_GPIO_N(RS232_CIR
, 0);
277 static void __init
h2200_map_io(void)
281 /* Configure power management stuff. */
282 PWER
= PWER_GPIO0
| PWER_GPIO12
| PWER_GPIO13
| PWER_RTC
;
283 PFER
= PWER_GPIO0
| PWER_GPIO12
| PWER_GPIO13
| PWER_RTC
;
284 PRER
= PWER_GPIO0
| PWER_GPIO12
| PWER_GPIO13
;
288 /* Configure power management stuff. */
289 PGSR0
= GPSRx_SleepValue
;
290 PGSR1
= GPSRy_SleepValue
;
291 PGSR2
= GPSRz_SleepValue
;
293 /* Set up GPIO direction and alternate function registers */
294 GAFR0_L
= GAFR0x_InitValue
;
295 GAFR0_U
= GAFR1x_InitValue
;
296 GAFR1_L
= GAFR0y_InitValue
;
297 GAFR1_U
= GAFR1y_InitValue
;
298 GAFR2_L
= GAFR0z_InitValue
;
299 GAFR2_U
= GAFR1z_InitValue
;
301 GPDR0
= GPDRx_InitValue
;
302 GPDR1
= GPDRy_InitValue
;
303 GPDR2
= GPDRz_InitValue
;
305 GPSR0
= GPSRx_InitValue
;
306 GPSR1
= GPSRy_InitValue
;
307 GPSR2
= GPSRz_InitValue
;
309 GPCR0
= ~GPSRx_InitValue
;
310 GPCR1
= ~GPSRy_InitValue
;
311 GPCR2
= ~GPSRz_InitValue
;
320 check_serial_cable ();
322 btuart_device
.dev
.platform_data
= &h2200_btuart_funcs
;
323 stuart_device
.dev
.platform_data
= &h2200_irda_funcs
;
324 hwuart_device
.dev
.platform_data
= &h2200_hwuart_funcs
;
326 #ifdef EARLY_SIR_CONSOLE
327 h2200_irda_configure (NULL
, 1);
328 h2200_irda_set_txrx (NULL
, PXA_SERIAL_TX
);
332 /* ------------------- */
334 static irqreturn_t
h2200_serial_cable (int irq
, void *dev_id
, struct pt_regs
*regs
)
336 check_serial_cable ();
340 static int h2200_late_init (void)
342 if (!machine_is_h2200 ())
345 request_irq (H2200_IRQ(RS232_DCD
), &h2200_serial_cable
,
346 0, "Serial cable", NULL
);
347 set_irq_type (H2200_IRQ(RS232_DCD
), IRQT_BOTHEDGE
);
350 device_initcall (h2200_late_init
);
352 /* ------------------- */
355 h2200_udc_is_connected (void)
357 return GET_H2200_GPIO(USB_DETECT_N
) ? 0 : 1;
361 h2200_udc_command (int cmd
)
365 case PXA2XX_UDC_CMD_DISCONNECT
:
366 SET_H2200_GPIO_N(USB_PULL_UP
, 0);
368 case PXA2XX_UDC_CMD_CONNECT
:
369 SET_H2200_GPIO_N(USB_PULL_UP
, 1);
372 printk("_udc_control: unknown command!\n");
377 static struct pxa2xx_udc_mach_info h2200_udc_mach_info
= {
378 .udc_is_connected
= h2200_udc_is_connected
,
379 .udc_command
= h2200_udc_command
,
382 /* ------------------- */
384 static struct resource hamcop_resources
[] = {
386 .start
= H2200_HAMCOP_BASE
,
387 .end
= H2200_HAMCOP_BASE
+ 0x00ffffff,
388 .flags
= IORESOURCE_MEM
,
391 .start
= IRQ_GPIO_H2200_ASIC_INT
,
392 .end
= IRQ_GPIO_H2200_ASIC_INT
,
393 .flags
= IORESOURCE_IRQ
,
397 static struct hamcop_platform_data hamcop_platform_data
= {
398 .clocksleep
= HAMCOP_CPM_CLKSLEEP_XTCON
| HAMCOP_CPM_CLKSLEEP_UCLK_ON
|
399 HAMCOP_CPM_CLKSLEEP_CLKSEL
,
400 .pllcontrol
= 0xd15e, /* value from wince via haret */
403 struct platform_device h2200_hamcop
= {
406 .num_resources
= ARRAY_SIZE(hamcop_resources
),
407 .resource
= hamcop_resources
,
409 .platform_data
= &hamcop_platform_data
,
412 EXPORT_SYMBOL(h2200_hamcop
);
415 static struct gpio_keys_button h2200_button_table
[] = {
416 { KEY_POWER
, GPIO_NR_H2200_POWER_ON_N
, 1 },
419 static struct gpio_keys_platform_data h2200_gpio_keys_data
= {
420 .buttons
= h2200_button_table
,
421 .nbuttons
= ARRAY_SIZE(h2200_button_table
),
424 static struct platform_device h2200_gpio_keys
= {
427 .platform_data
= &h2200_gpio_keys_data
,
431 static struct platform_device h2200_battery
= {
432 .name
= "h2200 battery",
435 .parent
= &h2200_hamcop
.dev
,
439 static struct platform_device h2200_buttons
= {
440 .name
= "h2200 buttons",
443 .parent
= &h2200_hamcop
.dev
,
451 platform_device_register(&h2200_hamcop
);
452 platform_device_register(&h2200_gpio_keys
);
453 platform_device_register(&h2200_battery
);
454 platform_device_register(&h2200_buttons
);
455 pxa_set_udc_info (&h2200_udc_mach_info
);
456 pxa_set_ficp_info(&h2200_ficp_platform_data
);
459 MACHINE_START(H2200
, "HP iPAQ H2200")
460 /* Maintainer: HP Labs, Cambridge Research Labs */
461 .phys_io
= 0x40000000,
462 .io_pg_offst
= (io_p2v(0x40000000) >> 18) & 0xfffc,
463 .boot_params
= 0xa0000100,
464 .map_io
= h2200_map_io
,
465 .init_irq
= pxa_init_irq
,
467 .init_machine
= h2200_init
,