hh.org updates
[hh.org.git] / arch / arm / mach-pxa / h2200 / h2200.c
bloba6cdbe0b9a83747d392318b7b6548f552dad4269
1 /*
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>
27 #include <linux/pm.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>
34 #include <linux/fb.h>
36 #include <asm/types.h>
37 #include <asm/irq.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 /***************************************************************************/
64 /* LED hook */
65 /***************************************************************************/
67 void (*h2200_led_hook) (struct device *dev, int led_num, int duty_time,
68 int cycle_time);
69 EXPORT_SYMBOL(h2200_led_hook);
71 void
72 h2200_set_led (int led_num, int duty_time, int cycle_time)
74 if (h2200_led_hook)
75 h2200_led_hook(&h2200_hamcop.dev, led_num, duty_time, cycle_time);
77 EXPORT_SYMBOL(h2200_set_led);
79 /***************************************************************************/
80 /* IRDA */
81 /***************************************************************************/
83 /* XXX What are CIR_RESET and CIR_POWER_ON for? */
84 static void h2200_irda_transceiver_mode(struct device *dev, int mode)
86 unsigned long flags;
88 local_irq_save(flags);
90 if (mode & IR_OFF)
91 SET_H2200_GPIO_N(IR_ON, 0);
92 else
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);
116 static void
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 */
123 ICCR0 = 0;
125 switch (state) {
127 case PXA_UART_CFG_POST_STARTUP: /* post UART enable */
128 /* configure STUART to for SIR */
129 STISR = STISR_XMODE | STISR_RCVEIR | STISR_RXPL;
130 IR_TRANSCEIVER_ON;
131 break;
133 case PXA_UART_CFG_POST_SHUTDOWN: /* UART disabled */
134 STISR = 0;
135 IR_TRANSCEIVER_OFF;
136 break;
138 default:
139 break;
143 static void
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;
153 } else
154 new_stisr &= ~STISR_XMITIR;
156 if (txrx & PXA_SERIAL_RX)
157 new_stisr |= STISR_RCVEIR;
158 else
159 new_stisr &= ~STISR_RCVEIR;
161 if (new_stisr != old_stisr) {
162 while (!(STLSR & LSR_TEMT)) ;
163 IR_TRANSCEIVER_OFF;
164 STISR = new_stisr;
165 IR_TRANSCEIVER_ON;
169 static int
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 /***************************************************************************/
184 /* Bluetooth */
185 /***************************************************************************/
187 static void h2200_bluetooth_power(int on)
189 if (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. */
193 mdelay(5);
194 SET_H2200_GPIO(BT_POWER_ON, 1); /* Power on. */
196 /* XXX This seems too long, but anything shorter makes
197 * hcid not work. */
198 msleep(2000);
199 h2200_set_led(2, 1, 31);
200 } else {
201 /* Turn off the Zeevo. */
202 /* XXX Assert reset? */
203 SET_H2200_GPIO(BT_POWER_ON, 0);
204 h2200_set_led(2, 0, 0);
208 static void
209 h2200_btuart_configure(int state)
211 switch (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);
219 break;
221 case PXA_UART_CFG_POST_SHUTDOWN: /* post UART disable */
222 h2200_bluetooth_power(0);
223 break;
225 default:
226 break;
230 static void
231 h2200_hwuart_configure(int state)
233 switch (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);
241 break;
243 case PXA_UART_CFG_POST_SHUTDOWN: /* post UART disable */
244 h2200_bluetooth_power(0);
245 break;
247 default:
248 break;
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 /***************************************************************************/
262 /* Initialisation */
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)
279 pxa_map_io ();
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;
285 PCFR = PCFR_OPDE;
286 CKEN = CKEN6_FFUART;
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;
313 MSC0 = 0x246c7ffc;
314 (void)MSC0;
315 MSC1 = 0x7ff07ff0;
316 (void)MSC1;
317 MSC2 = 0x7ff07ff0;
318 (void)MSC2;
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);
329 #endif
332 /* ------------------- */
334 static irqreturn_t h2200_serial_cable (int irq, void *dev_id, struct pt_regs *regs)
336 check_serial_cable ();
337 return IRQ_HANDLED;
340 static int h2200_late_init (void)
342 if (!machine_is_h2200 ())
343 return 0;
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);
348 return 0;
350 device_initcall (h2200_late_init);
352 /* ------------------- */
354 static int
355 h2200_udc_is_connected (void)
357 return GET_H2200_GPIO(USB_DETECT_N) ? 0 : 1;
360 static void
361 h2200_udc_command (int cmd)
363 switch (cmd)
365 case PXA2XX_UDC_CMD_DISCONNECT:
366 SET_H2200_GPIO_N(USB_PULL_UP, 0);
367 break;
368 case PXA2XX_UDC_CMD_CONNECT:
369 SET_H2200_GPIO_N(USB_PULL_UP, 1);
370 break;
371 default:
372 printk("_udc_control: unknown command!\n");
373 break;
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[] = {
385 [0] = {
386 .start = H2200_HAMCOP_BASE,
387 .end = H2200_HAMCOP_BASE + 0x00ffffff,
388 .flags = IORESOURCE_MEM,
390 [1] = {
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 = {
404 .name = "hamcop",
405 .id = -1,
406 .num_resources = ARRAY_SIZE(hamcop_resources),
407 .resource = hamcop_resources,
408 .dev = {
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 = {
425 .name = "gpio-keys",
426 .dev = {
427 .platform_data = &h2200_gpio_keys_data,
431 static struct platform_device h2200_battery = {
432 .name = "h2200 battery",
433 .id = -1,
434 .dev = {
435 .parent = &h2200_hamcop.dev,
439 static struct platform_device h2200_buttons = {
440 .name = "h2200 buttons",
441 .id = -1,
442 .dev = {
443 .parent = &h2200_hamcop.dev,
448 static void __init
449 h2200_init (void)
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,
466 .timer = &pxa_timer,
467 .init_machine = h2200_init,
468 MACHINE_END