hh.org updates
[hh.org.git] / arch / arm / mach-pxa / htcuniversal / htcuniversal_core.c
blob6f60c55481004e9bb2e5546dc716bae627d1e067
1 /* Core Hardware driver for Hx4700 (Serial, ASIC3, EGPIOs)
3 * Copyright (c) 2005 SDG Systems, LLC
5 * 2005-03-29 Todd Blumer Converted basic structure to support hx4700
6 * 2005-04-30 Todd Blumer Add IRDA code from H2200
7 */
9 #include <linux/module.h>
10 #include <linux/version.h>
11 #include <linux/interrupt.h>
12 #include <linux/platform_device.h>
13 #include <linux/delay.h>
14 #include <linux/pm.h>
15 #include <linux/irq.h>
17 #include <asm/io.h>
18 #include <asm/mach/irq.h>
19 #include <asm/arch/pxa-regs.h>
20 #include <asm/arch/pxa-pm_ll.h>
21 #include <asm/arch/htcuniversal-gpio.h>
22 #include <asm/arch/htcuniversal-asic.h>
24 #include <linux/soc/asic3_base.h>
25 #include <asm/hardware/ipaq-asic3.h>
27 volatile u_int16_t *egpios;
28 u_int16_t egpio_reg;
30 static int htc_bootloader = 0; /* Is the stock HTC bootloader installed? */
33 * may make sense to put egpios elsewhere, but they're here now
34 * since they share some of the same address space with the TI WLAN
36 * EGPIO register is write-only
39 void
40 htcuniversal_egpio_enable( u_int16_t bits )
42 unsigned long flags;
44 local_irq_save(flags);
46 egpio_reg |= bits;
47 *egpios = egpio_reg;
49 local_irq_restore(flags);
51 EXPORT_SYMBOL(htcuniversal_egpio_enable);
53 void
54 htcuniversal_egpio_disable( u_int16_t bits )
56 unsigned long flags;
58 local_irq_save(flags);
60 egpio_reg &= ~bits;
61 *egpios = egpio_reg;
63 local_irq_restore(flags);
65 EXPORT_SYMBOL(htcuniversal_egpio_disable);
67 #ifdef CONFIG_PM
69 void htcuniversal_ll_pm_init(void);
71 static int htcuniversal_suspend(struct platform_device *dev, pm_message_t state)
73 /* Turn off external clocks here, because htcuniversal_power and asic3_mmc
74 * scared to do so to not hurt each other. (-5 mA) */
75 #if 0
76 asic3_set_clock_cdex(&htcuniversal_asic3.dev,
77 CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1, 0 | 0);
78 #endif
79 /* 0x20c2 is HTC clock value
80 * CLOCK_CDEX_SOURCE 2
81 * CLOCK_CDEX_SPI 0
82 * CLOCK_CDEX_OWM 0
84 * CLOCK_CDEX_PWM0 0
85 * CLOCK_CDEX_PWM1 0
86 * CLOCK_CDEX_LED0 1
87 * CLOCK_CDEX_LED1 1
89 * CLOCK_CDEX_LED2 0
90 * CLOCK_CDEX_SD_HOST 0
91 * CLOCK_CDEX_SD_BUS 0
92 * CLOCK_CDEX_SMBUS 0
94 * CLOCK_CDEX_CONTROL_CX 0
95 * CLOCK_CDEX_EX0 1
96 * CLOCK_CDEX_EX1 0
97 * */
98 asic3_set_clock_cdex(&htcuniversal_asic3.dev, 0xffff, CLOCK_CDEX_SOURCE
99 |CLOCK_CDEX_LED0
100 |CLOCK_CDEX_LED1
101 |CLOCK_CDEX_LED2
102 |CLOCK_CDEX_EX0
103 |CLOCK_CDEX_EX1);
105 *egpios = 0; /* turn off all egpio power */
107 /* Wake up enable. */
108 PWER = PWER_GPIO0
109 | PWER_GPIO1 /* reset */
110 | PWER_GPIO9 /* USB */
111 | PWER_GPIO10 /* AC on USB */
112 | PWER_GPIO14 /* ASIC3 mux */
113 | PWER_RTC;
114 /* Wake up on falling edge. */
115 PFER = PWER_GPIO0
116 | PWER_GPIO1
117 | PWER_GPIO9
118 | PWER_GPIO10
119 | PWER_GPIO14;
121 /* Wake up on rising edge. */
122 PRER = PWER_GPIO0
123 | PWER_GPIO1
124 | PWER_GPIO9
125 | PWER_GPIO10;
126 /* 3.6864 MHz oscillator power-down enable */
127 PCFR = PCFR_OPDE | PCFR_PI2CEN | PCFR_GPROD | PCFR_GPR_EN;
129 PGSR0 = 0x09088004;
130 PGSR1 = 0x00020002;
131 PGSR2 = 0x8001c000;
132 PGSR3 = 0x00106284;
134 PSLR = 0xcc000000;
136 #if 0
138 * If we're using bootldr and not the stock HTC bootloader,
139 * we want to wake up periodically to see if the charge is full while
140 * it is suspended. We do this with the OS timer 4 in the pxa270.
142 if (!htc_bootloader) {
143 OMCR4 = 0x4b; /* Periodic, self-resetting, 1-second timer */
144 OSMR4 = 5; /* Wake up bootldr after x seconds so it can
145 figure out what to do with the LEDs. */
146 OIER |= 0x10; /* Enable interrupt source for Timer 4 */
147 OSCR4 = 0; /* This starts the timer */
149 #endif
151 asic3_set_extcf_select(&htcuniversal_asic3.dev, ASIC3_EXTCF_OWM_EN, 0);
153 return 0;
156 static int htcuniversal_resume(struct platform_device *dev)
158 htcuniversal_egpio_enable(0);
160 return 0;
162 #else
163 # define htcuniversal_suspend NULL
164 # define htcuniversal_resume NULL
165 #endif
167 static int
168 htcuniversal_core_probe( struct platform_device *dev )
171 printk( KERN_NOTICE "HTC Universal Core Hardware Driver\n" );
173 egpios = (volatile u_int16_t *)ioremap_nocache(HTCUNIVERSAL_EGPIO_BASE, sizeof *egpios );
174 if (!egpios)
175 return -ENODEV;
176 else
177 printk( KERN_NOTICE "HTC Universal Core: egpio at phy=0x%8.8x is at virt=0x%p\n",
178 HTCUNIVERSAL_EGPIO_BASE, egpios );
180 #if 0
182 u32 *bootldr;
183 int i;
185 /* Is the stock HTC bootloader installed? */
187 bootldr = (u32 *) ioremap(PXA_CS0_PHYS, 1024 * 1024);
188 i = 0x000414dc / 4;
190 if (bootldr[i] == 0xe59f1360 && /* ldr r1, [pc, #864] ; power base */
191 bootldr[i+1] == 0xe5914008 && /* ldr r4, [r1, #8] ; PSPR */
192 bootldr[i+2] == 0xe1320004) { /* teq r2, r4 */
194 printk("Stock HTC bootloader detected\n");
195 htc_bootloader = 1;
196 pxa_pm_set_ll_ops(&htcuniversal_ll_pm_ops);
199 iounmap(bootldr);
200 #else
202 printk("Using stock HTC first stage bootloader\n");
203 htc_bootloader = 1;
205 htcuniversal_ll_pm_init();
207 #endif
208 return 0;
211 static int
212 htcuniversal_core_remove( struct platform_device *dev )
215 if (egpios != NULL)
216 iounmap( (void *)egpios );
218 return 0;
221 static struct platform_driver htcuniversal_core_driver = {
222 .driver = {
223 .name = "htcuniversal_core",
225 .probe = htcuniversal_core_probe,
226 .remove = htcuniversal_core_remove,
227 .suspend = htcuniversal_suspend,
228 .resume = htcuniversal_resume,
231 static int __init
232 htcuniversal_core_init( void )
234 return platform_driver_register( &htcuniversal_core_driver );
238 static void __exit
239 htcuniversal_core_exit( void )
241 platform_driver_unregister( &htcuniversal_core_driver );
244 module_init( htcuniversal_core_init );
245 module_exit( htcuniversal_core_exit );
247 MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
248 MODULE_DESCRIPTION("HTC Universal Core Hardware Driver");
249 MODULE_LICENSE("GPL");
251 /* vim600: set noexpandtab sw=8 ts=8 :*/