summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-rp-2.6.23/htcuni.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-rp-2.6.23/htcuni.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-rp-2.6.23/htcuni.patch8044
1 files changed, 8044 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-rp-2.6.23/htcuni.patch b/meta/recipes-kernel/linux/linux-rp-2.6.23/htcuni.patch
new file mode 100644
index 0000000000..4d746749c5
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-rp-2.6.23/htcuni.patch
@@ -0,0 +1,8044 @@
1---
2 arch/arm/Kconfig | 2
3 arch/arm/mach-pxa/Kconfig | 89 +
4 arch/arm/mach-pxa/Makefile | 1
5 arch/arm/mach-pxa/corgi.c | 3
6 arch/arm/mach-pxa/generic.c | 13
7 arch/arm/mach-pxa/htcuniversal/Makefile | 19
8 arch/arm/mach-pxa/htcuniversal/htcuniversal.c | 468 +++++
9 arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c | 917 +++++++++++
10 arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h | 65
11 arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c | 143 +
12 arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c | 61
13 arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c | 135 +
14 arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h | 17
15 arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c | 87 +
16 arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c | 226 ++
17 arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c | 212 ++
18 arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c | 167 ++
19 arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h | 16
20 arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c | 69
21 arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c | 97 +
22 arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c | 490 ++++++
23 arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c | 71
24 arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h | 20
25 arch/arm/mach-pxa/spitz.c | 2
26 drivers/input/keyboard/Kconfig | 7
27 drivers/input/keyboard/Makefile | 2
28 drivers/input/keyboard/asic3_keys.c | 131 +
29 drivers/leds/Kconfig | 7
30 drivers/leds/Makefile | 1
31 drivers/leds/leds-asic3.c | 189 ++
32 drivers/mfd/Kconfig | 10
33 drivers/mfd/Makefile | 2
34 drivers/mfd/asic3_base.c | 1208 +++++++++++++++
35 drivers/mfd/soc-core.c | 106 +
36 drivers/mfd/soc-core.h | 30
37 drivers/mmc/host/Kconfig | 6
38 drivers/mmc/host/Makefile | 2
39 drivers/mmc/host/asic3_mmc.c | 900 +++++++++++
40 drivers/mmc/host/asic3_mmc.h | 25
41 drivers/serial/pxa.c | 22
42 drivers/video/backlight/Kconfig | 2
43 drivers/video/backlight/corgi_bl.c | 4
44 include/asm-arm/arch-pxa/clock.h | 27
45 include/asm-arm/arch-pxa/htcuniversal-asic.h | 213 ++
46 include/asm-arm/arch-pxa/htcuniversal-gpio.h | 220 ++
47 include/asm-arm/arch-pxa/htcuniversal-init.h | 14
48 include/asm-arm/arch-pxa/htcuniversal.h | 3
49 include/asm-arm/arch-pxa/irqs.h | 2
50 include/asm-arm/arch-pxa/pxa-pm_ll.h | 6
51 include/asm-arm/arch-pxa/pxa-regs.h | 2
52 include/asm-arm/arch-pxa/serial.h | 78
53 include/asm-arm/arch-pxa/sharpsl.h | 6
54 include/asm-arm/hardware/asic3_keys.h | 18
55 include/asm-arm/hardware/asic3_leds.h | 34
56 include/asm-arm/hardware/ipaq-asic3.h | 602 +++++++
57 include/linux/backlight.h | 7
58 include/linux/gpiodev.h | 44
59 include/linux/input_pda.h | 47
60 include/linux/ioport.h | 1
61 include/linux/soc/asic3_base.h | 104 +
62 include/linux/soc/tmio_mmc.h | 17
63 61 files changed, 7475 insertions(+), 14 deletions(-)
64
65Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile
66===================================================================
67--- /dev/null 1970-01-01 00:00:00.000000000 +0000
68+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile 2007-09-11 12:53:37.000000000 +0200
69@@ -0,0 +1,19 @@
70+#
71+# Makefile for HTC Universal
72+#
73+
74+snd-htcuniversal-ak4641-objs := htcuniversal_ak4641.o
75+
76+obj-$(CONFIG_MACH_HTCUNIVERSAL) += htcuniversal.o
77+obj-$(CONFIG_HTCUNIVERSAL_CORE) += htcuniversal_core.o
78+obj-$(CONFIG_HTCUNIVERSAL_POWER) += htcuniversal_power2.o
79+obj-$(CONFIG_HTCUNIVERSAL_LCD) += htcuniversal_lcd.o
80+obj-$(CONFIG_HTCUNIVERSAL_BACKLIGHT) += htcuniversal_bl.o
81+obj-$(CONFIG_HTCUNIVERSAL_TS2) += htcuniversal_ts2.o
82+obj-$(CONFIG_HTCUNIVERSAL_BUTTONS) += htcuniversal_buttons.o
83+obj-$(CONFIG_HTCUNIVERSAL_BLUETOOTH) += htcuniversal_bt.o
84+obj-$(CONFIG_HTCUNIVERSAL_PHONE) += htcuniversal_phone.o
85+obj-$(CONFIG_HTCUNIVERSAL_ASIC3_LEDS) += htcuniversal_asic3_leds.o
86+obj-$(CONFIG_HTCUNIVERSAL_UDC) += htcuniversal_udc.o
87+
88+obj-$(CONFIG_HTCUNIVERSAL_AK4641) += htcuniversal_ak4641.o
89Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
90===================================================================
91--- /dev/null 1970-01-01 00:00:00.000000000 +0000
92+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c 2007-09-11 12:53:37.000000000 +0200
93@@ -0,0 +1,468 @@
94+/*
95+ * Hardware definitions for HTC Universal
96+ *
97+ * Copyright (c) 2006 Oleg Gusev
98+ *
99+ * Use consistent with the GNU GPL is permitted,
100+ * provided that this copyright notice is
101+ * preserved in its entirety in all copies and derived works.
102+ *
103+ */
104+
105+#include <linux/kernel.h>
106+#include <linux/init.h>
107+#include <linux/platform_device.h>
108+#include <linux/irq.h>
109+#include <linux/input.h>
110+#include <linux/gpio_keys.h>
111+#include <linux/soc/asic3_base.h>
112+
113+#include <asm/mach-types.h>
114+#include <asm/hardware.h>
115+#include <asm/setup.h>
116+
117+#include <asm/mach/irq.h>
118+#include <asm/mach/arch.h>
119+
120+#include <asm/arch/bitfield.h>
121+#include <asm/arch/pxa-regs.h>
122+#include <asm/arch/serial.h>
123+#include <asm/arch/pxa27x_keyboard.h>
124+#include <asm/arch/pxafb.h>
125+#include <asm/arch/irda.h>
126+#include <asm/arch/ohci.h>
127+
128+#include <asm/arch/htcuniversal.h>
129+#include <asm/arch/htcuniversal-gpio.h>
130+#include <asm/arch/htcuniversal-init.h>
131+#include <asm/arch/htcuniversal-asic.h>
132+
133+#include <asm/hardware/ipaq-asic3.h>
134+
135+#include "../generic.h"
136+
137+#include "htcuniversal_bt.h"
138+#include "htcuniversal_phone.h"
139+#include "tsc2046_ts.h"
140+
141+/*
142+ * IRDA
143+ */
144+
145+static void htcuniversal_irda_transceiver_mode(struct device *dev, int mode)
146+{
147+ /* */
148+}
149+
150+static struct pxaficp_platform_data htcuniversal_ficp_platform_data = {
151+ .transceiver_cap = IR_SIRMODE | IR_FIRMODE,
152+ .transceiver_mode = htcuniversal_irda_transceiver_mode,
153+};
154+
155+/*
156+ * Bluetooth - Relies on other loadable modules, like ASIC3 and Core,
157+ * so make the calls indirectly through pointers. Requires that the
158+ * htcuniversal_bt module be loaded before any attempt to use
159+ * bluetooth (obviously).
160+ */
161+
162+static struct htcuniversal_bt_funcs bt_funcs;
163+
164+static void
165+htcuniversal_bt_configure( int state )
166+{
167+ if (bt_funcs.configure != NULL)
168+ bt_funcs.configure( state );
169+}
170+
171+static struct htcuniversal_phone_funcs phone_funcs;
172+
173+static void
174+htcuniversal_phone_configure( int state )
175+{
176+ if (phone_funcs.configure != NULL)
177+ phone_funcs.configure( state );
178+}
179+
180+//void htcuniversal_ll_pm_init(void);
181+
182+extern struct platform_device htcuniversal_bl;
183+static struct platform_device htcuniversal_lcd = { .name = "htcuniversal_lcd", };
184+//static struct platform_device htcuniversal_kbd = { .name = "htcuniversal_kbd", };
185+static struct platform_device htcuniversal_buttons = { .name = "htcuniversal_buttons", };
186+//static struct platform_device htcuniversal_ts = { .name = "htcuniversal_ts", };
187+//static struct platform_device htcuniversal_bt = { .name = "htcuniversal_bt", };
188+//static struct platform_device htcuniversal_phone = { .name = "htcuniversal_phone", };
189+static struct platform_device htcuniversal_power = { .name = "htcuniversal_power", };
190+static struct platform_device htcuniversal_udc = { .name = "htcuniversal_udc", };
191+
192+static struct tsc2046_mach_info htcuniversal_ts_platform_data = {
193+ .port = 1,
194+ .clock = CKEN_SSP1,
195+ .pwrbit_X = 1,
196+ .pwrbit_Y = 1,
197+ .irq = 0 /* asic3 irq */
198+};
199+
200+static struct platform_device htcuniversal_ts = {
201+ .name = "htcuniversal_ts",
202+ .dev = {
203+ .platform_data = &htcuniversal_ts_platform_data,
204+ },
205+};
206+
207+
208+/* Bluetooth */
209+
210+static struct platform_device htcuniversal_bt = {
211+ .name = "htcuniversal_bt",
212+ .id = -1,
213+ .dev = {
214+ .platform_data = &bt_funcs,
215+ },
216+};
217+
218+static struct platform_device htcuniversal_phone = {
219+ .name = "htcuniversal_phone",
220+ .id = -1,
221+ .dev = {
222+ .platform_data = &phone_funcs,
223+ },
224+};
225+
226+/* PXA2xx Keys */
227+
228+static struct gpio_keys_button htcuniversal_button_table[] = {
229+ { KEY_POWER, GPIO_NR_HTCUNIVERSAL_KEY_ON_N, 1 },
230+};
231+
232+static struct gpio_keys_platform_data htcuniversal_pxa_keys_data = {
233+ .buttons = htcuniversal_button_table,
234+ .nbuttons = ARRAY_SIZE(htcuniversal_button_table),
235+};
236+
237+static struct platform_device htcuniversal_pxa_keys = {
238+ .name = "gpio-keys",
239+ .dev = {
240+ .platform_data = &htcuniversal_pxa_keys_data,
241+ },
242+ .id = -1,
243+};
244+
245+/****************************************************************
246+ * Keyboard
247+ ****************************************************************/
248+
249+static struct pxa27x_keyboard_platform_data htcuniversal_kbd = {
250+ .nr_rows = 8,
251+ .nr_cols = 8,
252+ .keycodes = {
253+ {
254+ /* row 0 */
255+ KEY_ENTER,
256+ KEY_MINUS,
257+ KEY_ESC,
258+ KEY_1,
259+ KEY_TAB,
260+ KEY_CAPSLOCK,
261+ KEY_LEFTSHIFT,
262+ KEY_RIGHTALT, /* Fn */
263+ }, { /* row 1 */
264+ KEY_COMMA,
265+ KEY_EQUAL,
266+ KEY_F1,
267+ KEY_2,
268+ KEY_Q,
269+ KEY_A,
270+ KEY_Z,
271+ KEY_LEFTCTRL,
272+ }, { /* row 2 */
273+ KEY_UP,
274+ KEY_I,
275+ KEY_F2,
276+ KEY_3,
277+ KEY_W,
278+ KEY_S,
279+ KEY_X,
280+ KEY_F6,
281+ }, { /* row 3 */
282+ KEY_DOT,
283+ KEY_O,
284+ KEY_F3,
285+ KEY_4,
286+ KEY_E,
287+ KEY_D,
288+ KEY_C,
289+ KEY_LEFTALT,
290+ }, { /* row 4 */
291+ KEY_F9,
292+ KEY_P,
293+ KEY_F4,
294+ KEY_5,
295+ KEY_R,
296+ KEY_F,
297+ KEY_V,
298+ KEY_SPACE,
299+ }, { /* row 5 */
300+ KEY_RIGHT,
301+ KEY_BACKSPACE,
302+ KEY_F5,
303+ KEY_6,
304+ KEY_T,
305+ KEY_G,
306+ KEY_B,
307+ KEY_F7,
308+ }, { /* row 6 */
309+ KEY_F9,
310+ KEY_K,
311+ KEY_9,
312+ KEY_7,
313+ KEY_Y,
314+ KEY_H,
315+ KEY_N,
316+ KEY_LEFT,
317+ }, { /* row 7 */
318+ KEY_F10,
319+ KEY_L,
320+ KEY_0,
321+ KEY_8,
322+ KEY_U,
323+ KEY_J,
324+ KEY_M,
325+ KEY_DOWN,
326+ },
327+ },
328+ .gpio_modes = {
329+ GPIO_NR_HTCUNIVERSAL_KP_MKIN0_MD,
330+ GPIO_NR_HTCUNIVERSAL_KP_MKIN1_MD,
331+ GPIO_NR_HTCUNIVERSAL_KP_MKIN2_MD,
332+ GPIO_NR_HTCUNIVERSAL_KP_MKIN3_MD,
333+ GPIO_NR_HTCUNIVERSAL_KP_MKIN4_MD,
334+ GPIO_NR_HTCUNIVERSAL_KP_MKIN5_MD,
335+ GPIO_NR_HTCUNIVERSAL_KP_MKIN6_MD,
336+ GPIO_NR_HTCUNIVERSAL_KP_MKIN7_MD,
337+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT0_MD,
338+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT1_MD,
339+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT2_MD,
340+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT3_MD,
341+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT4_MD,
342+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT5_MD,
343+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT6_MD,
344+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT7_MD,
345+ },
346+};
347+
348+static struct platform_device htcuniversal_pxa_keyboard = {
349+ .name = "pxa27x-keyboard",
350+ .id = -1,
351+ .dev = {
352+ .platform_data = &htcuniversal_kbd,
353+ },
354+};
355+/* Core Hardware Functions */
356+
357+struct platform_device htcuniversal_core = {
358+ .name = "htcuniversal_core",
359+ .id = 0,
360+ .dev = {
361+ .platform_data = NULL,
362+ },
363+};
364+
365+static struct platform_device *devices[] __initdata = {
366+ &htcuniversal_core,
367+// &htcuniversal_flash,
368+ &htcuniversal_pxa_keyboard,
369+ &htcuniversal_pxa_keys,
370+};
371+
372+static struct platform_device *htcuniversal_asic3_devices[] __initdata = {
373+ &htcuniversal_lcd,
374+#ifdef CONFIG_HTCUNIVERSAL_BACKLIGHT
375+ &htcuniversal_bl,
376+#endif
377+ &htcuniversal_buttons,
378+ &htcuniversal_ts,
379+ &htcuniversal_bt,
380+ &htcuniversal_phone,
381+ &htcuniversal_power,
382+ &htcuniversal_udc,
383+};
384+
385+static struct asic3_platform_data htcuniversal_asic3_platform_data = {
386+
387+ /* Setting ASIC3 GPIO registers to the below initialization states
388+ * HTC Universal asic3 information:
389+ * http://wiki.xda-developers.com/index.php?pagename=UniversalASIC3
390+ * http://wiki.xda-developers.com/index.php?pagename=ASIC3
391+ *
392+ * dir: Direction of the GPIO pin. 0: input, 1: output.
393+ * If unknown, set as output to avoid power consuming floating input nodes
394+ * init: Initial state of the GPIO bits
395+ *
396+ * These registers are configured as they are on Wince.
397+ */
398+ .gpio_a = {
399+ .dir = (1<<GPIOA_LCD_PWR5_ON) |
400+ (1<<GPIOA_FLASHLIGHT) |
401+ (1<<GPIOA_UNKNOWN9) |
402+ (1<<GPIOA_SPK_PWR2_ON) |
403+ (1<<GPIOA_UNKNOWN4) |
404+ (1<<GPIOA_EARPHONE_PWR_ON)|
405+ (1<<GPIOA_AUDIO_PWR_ON) |
406+ (1<<GPIOA_SPK_PWR1_ON) |
407+ (1<<GPIOA_I2C_EN),
408+ .init = (1<<GPIOA_LCD_PWR5_ON) |
409+ (1<<GPIOA_I2C_EN),
410+ .sleep_out = 0x0000,
411+ .batt_fault_out = 0x0000,
412+ .alt_function = 0x0000,
413+ .sleep_conf = 0x000c,
414+ },
415+ .gpio_b = {
416+ .dir = 0xc142,
417+ .init = 0x8842, // TODO: 0x0900
418+ .sleep_out = 0x0000,
419+ .batt_fault_out = 0x0000,
420+ .alt_function = 0x0000,
421+ .sleep_conf = 0x000c,
422+ },
423+ .gpio_c = {
424+ .dir = 0xc7e7,
425+ .init = 0xc6e0, // TODO: 0x8000
426+ .sleep_out = 0x0000,
427+ .batt_fault_out = 0x0000,
428+ .alt_function = 0x0007, // GPIOC_LED_RED | GPIOC_LED_GREEN | GPIOC_LED_BLUE
429+ .sleep_conf = 0x000c,
430+ },
431+ .gpio_d = {
432+ .dir = 0xffc0,
433+ .init = 0x7840, // TODO: 0x0000
434+ .sleep_out = 0x0000,
435+ .batt_fault_out = 0x0000,
436+ .alt_function = 0x0000,
437+ .sleep_conf = 0x0008,
438+ },
439+ .bus_shift = 1,
440+ .irq_base = HTCUNIVERSAL_ASIC3_IRQ_BASE,
441+
442+ .child_platform_devs = htcuniversal_asic3_devices,
443+ .num_child_platform_devs = ARRAY_SIZE(htcuniversal_asic3_devices),
444+};
445+
446+static struct resource htcuniversal_asic3_resources[] = {
447+ [0] = {
448+ .start = HTCUNIVERSAL_ASIC3_GPIO_PHYS,
449+ .end = HTCUNIVERSAL_ASIC3_GPIO_PHYS + IPAQ_ASIC3_MAP_SIZE,
450+ .flags = IORESOURCE_MEM,
451+ },
452+ [1] = {
453+ .start = HTCUNIVERSAL_IRQ(ASIC3_EXT_INT),
454+ .end = HTCUNIVERSAL_IRQ(ASIC3_EXT_INT),
455+ .flags = IORESOURCE_IRQ,
456+ },
457+ [2] = {
458+ .start = HTCUNIVERSAL_ASIC3_MMC_PHYS,
459+ .end = HTCUNIVERSAL_ASIC3_MMC_PHYS + IPAQ_ASIC3_MAP_SIZE,
460+ .flags = IORESOURCE_MEM,
461+ },
462+ [3] = {
463+ .start = HTCUNIVERSAL_IRQ(ASIC3_SDIO_INT_N),
464+ .flags = IORESOURCE_IRQ,
465+ },
466+};
467+
468+struct platform_device htcuniversal_asic3 = {
469+ .name = "asic3",
470+ .id = 0,
471+ .num_resources = ARRAY_SIZE(htcuniversal_asic3_resources),
472+ .resource = htcuniversal_asic3_resources,
473+ .dev = { .platform_data = &htcuniversal_asic3_platform_data, },
474+};
475+EXPORT_SYMBOL(htcuniversal_asic3);
476+
477+static struct pxafb_mode_info htcuniversal_lcd_modes[] = {
478+{
479+ .pixclock = 96153,
480+ .xres = 480,
481+ .yres = 640,
482+ .bpp = 16,
483+ .hsync_len = 4,
484+ .vsync_len = 1,
485+ .left_margin = 20,
486+ .right_margin = 8,
487+ .upper_margin = 7,
488+ .lower_margin = 8,
489+
490+// .sync = FB_SYNC_HOR_LOW_ACT|FB_SYNC_VERT_LOW_ACT,
491+
492+},
493+};
494+
495+static struct pxafb_mach_info sony_acx526akm = {
496+ .modes = htcuniversal_lcd_modes,
497+ .num_modes = ARRAY_SIZE(htcuniversal_lcd_modes),
498+
499+ /* fixme: use constants defined in pxafb.h */
500+ .lccr0 = 0x00000080,
501+ .lccr3 = 0x00400000,
502+// .lccr4 = 0x80000000,
503+};
504+
505+static void __init htcuniversal_init_irq(void)
506+{
507+ pxa27x_init_irq();
508+}
509+
510+static struct platform_pxa_serial_funcs htcuniversal_pxa_bt_funcs = {
511+ .configure = htcuniversal_bt_configure,
512+};
513+static struct platform_pxa_serial_funcs htcuniversal_pxa_phone_funcs = {
514+ .configure = htcuniversal_phone_configure,
515+};
516+
517+/* USB OHCI */
518+
519+static int htcuniversal_ohci_init(struct device *dev)
520+{
521+ /* missing GPIO setup here */
522+
523+ /* got the value from wince */
524+ UHCHR=UHCHR_CGR;
525+
526+ return 0;
527+}
528+
529+static struct pxaohci_platform_data htcuniversal_ohci_platform_data = {
530+ .port_mode = PMM_PERPORT_MODE,
531+ .init = htcuniversal_ohci_init,
532+};
533+
534+static void __init htcuniversal_map_io(void)
535+{
536+ pxa_map_io();
537+
538+ pxa_set_btuart_info(&htcuniversal_pxa_bt_funcs);
539+ pxa_set_ffuart_info(&htcuniversal_pxa_phone_funcs);
540+}
541+
542+static void __init htcuniversal_init(void)
543+{
544+ set_pxa_fb_info(&sony_acx526akm);
545+
546+ platform_device_register(&htcuniversal_asic3);
547+ platform_add_devices(devices, ARRAY_SIZE(devices) );
548+ pxa_set_ficp_info(&htcuniversal_ficp_platform_data);
549+ pxa_set_ohci_info(&htcuniversal_ohci_platform_data);
550+}
551+
552+MACHINE_START(HTCUNIVERSAL, "HTC Universal")
553+ /* Maintainer xanadux.org */
554+ .phys_io = 0x40000000,
555+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
556+ .boot_params = 0xa0000100,
557+ .map_io = htcuniversal_map_io,
558+ .init_irq = htcuniversal_init_irq,
559+ .init_machine = htcuniversal_init,
560+ .timer = &pxa_timer,
561+MACHINE_END
562Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c
563===================================================================
564--- /dev/null 1970-01-01 00:00:00.000000000 +0000
565+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c 2007-09-11 12:53:37.000000000 +0200
566@@ -0,0 +1,917 @@
567+/*
568+ * Audio support for codec Asahi Kasei AK4641
569+ *
570+ * This program is free software; you can redistribute it and/or modify
571+ * it under the terms of the GNU General Public License version 2 as
572+ * published by the Free Software Foundation.
573+ *
574+ * Copyright (c) 2006 Giorgio Padrin <giorgio@mandarinlogiq.org>
575+ *
576+ * History:
577+ *
578+ * 2006-03 Written -- Giorgio Padrin
579+ * 2006-09 Test and debug on machine (HP hx4700) -- Elshin Roman <roxmail@list.ru>
580+ *
581+ * AK4641 codec device driver
582+ *
583+ * Copyright (c) 2005 SDG Systems, LLC
584+ *
585+ * Based on code:
586+ * Copyright (c) 2002 Hewlett-Packard Company
587+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
588+ * Copyright (c) 2000 Lernout & Hauspie Speech Products, N.V.
589+ *
590+ * This program is free software; you can redistribute it and/or
591+ * modify it under the terms of the GNU General Public License.
592+ */
593+
594+#include <sound/driver.h>
595+
596+#include <linux/module.h>
597+#include <linux/init.h>
598+#include <linux/types.h>
599+#include <linux/string.h>
600+#include <linux/slab.h>
601+#include <linux/errno.h>
602+#include <linux/ioctl.h>
603+#include <linux/delay.h>
604+#include <linux/i2c.h>
605+
606+#include <sound/core.h>
607+#include <sound/control.h>
608+#include <sound/initval.h>
609+#include <sound/info.h>
610+
611+#include "htcuniversal_ak4641.h"
612+
613+/* Registers */
614+#define R_PM1 0x00
615+#define R_PM2 0x01
616+#define R_SEL1 0x02
617+#define R_SEL2 0x03
618+#define R_MODE1 0x04
619+#define R_MODE2 0x05
620+#define R_DAC 0x06
621+#define R_MIC 0x07
622+#define REG_TIMER 0x08
623+#define REG_ALC1 0x09
624+#define REG_ALC2 0x0a
625+#define R_PGA 0x0b
626+#define R_ATTL 0x0c
627+#define R_ATTR 0x0d
628+#define REG_VOL 0x0e
629+#define R_STATUS 0x0f
630+#define REG_EQLO 0x10
631+#define REG_EQMID 0x11
632+#define REG_EQHI 0x12
633+#define REG_BTIF 0x13
634+
635+/* Register flags */
636+/* REG_PWR1 */
637+#define R_PM1_PMADC 0x01
638+#define R_PM1_PMMIC 0x02
639+#define REG_PWR1_PMAUX 0x04
640+#define REG_PWR1_PMMO 0x08
641+#define R_PM1_PMLO 0x10
642+/* unused 0x20 */
643+/* unused 0x40 */
644+#define R_PM1_PMVCM 0x80
645+
646+/* REG_PWR2 */
647+#define R_PM2_PMDAC 0x01
648+/* unused 0x02 */
649+/* unused 0x04 */
650+#define R_PM2_PMMO2 0x08
651+#define REG_PWR2_MCKAC 0x10
652+/* unused 0x20 */
653+/* unused 0x40 */
654+#define R_PM2_MCKPD 0x80
655+
656+/* REG_SEL1 */
657+#define R_SEL1_PSMO2 0x01
658+/* unused 0x02 */
659+/* unused 0x04 */
660+/* unused 0x08 */
661+#define REG_SEL1_MICM 0x10
662+#define REG_SEL1_DACM 0x20
663+#define REG_SEL1_PSMO 0x40
664+#define REG_SEL1_MOGN 0x80
665+
666+/* REG_SEL2 */
667+#define R_SEL2_PSLOR 0x01
668+#define R_SEL2_PSLOL 0x02
669+#define REG_SEL2_AUXSI 0x04
670+/* unused 0x08 */
671+#define REG_SEL2_MICL 0x10
672+#define REG_SEL2_AUXL 0x20
673+/* unused 0x40 */
674+#define R_SEL2_DACL 0x80
675+
676+/* REG_MODE1 */
677+#define REG_MODE1_DIF0 0x01
678+#define REG_MODE1_DIF1 0x02
679+/* unused 0x04 */
680+/* unused 0x08 */
681+/* unused 0x10 */
682+/* unused 0x20 */
683+/* unused 0x40 */
684+/* unused 0x80 */
685+
686+/* REG_MODE2 */
687+/* unused 0x01 */
688+#define REG_MODE2_LOOP 0x02
689+#define REG_MODE2_HPM 0x04
690+/* unused 0x08 */
691+/* unused 0x10 */
692+#define REG_MODE2_MCK0 0x20
693+#define REG_MODE2_MCK1 0x40
694+/* unused 0x80 */
695+
696+/* REG_DAC */
697+#define REG_DAC_DEM0 0x01
698+#define REG_DAC_DEM1 0x02
699+#define REG_DAC_EQ 0x04
700+/* unused 0x08 */
701+#define R_DAC_DATTC 0x10
702+#define R_DAC_SMUTE 0x20
703+#define REG_DAC_TM 0x40
704+/* unused 0x80 */
705+
706+/* REG_MIC */
707+#define R_MIC_MGAIN 0x01
708+#define R_MIC_MSEL 0x02
709+#define R_MIC_MICAD 0x04
710+#define R_MIC_MPWRI 0x08
711+#define R_MIC_MPWRE 0x10
712+#define REG_MIC_AUXAD 0x20
713+/* unused 0x40 */
714+/* unused 0x80 */
715+
716+/* REG_TIMER */
717+
718+#define REG_TIMER_LTM0 0x01
719+#define REG_TIMER_LTM1 0x02
720+#define REG_TIMER_WTM0 0x04
721+#define REG_TIMER_WTM1 0x08
722+#define REG_TIMER_ZTM0 0x10
723+#define REG_TIMER_ZTM1 0x20
724+/* unused 0x40 */
725+/* unused 0x80 */
726+
727+#define REG_ALC1_LMTH 0x01
728+#define REG_ALC1_RATT 0x02
729+#define REG_ALC1_LMAT0 0x04
730+#define REG_ALC1_LMAT1 0x08
731+#define REG_ALC1_ZELM 0x10
732+#define REG_ALC1_ALC1 0x20
733+/* unused 0x40 */
734+/* unused 0x80 */
735+
736+/* REG_ALC2 */
737+
738+/* REG_PGA */
739+
740+/* REG_ATTL */
741+
742+/* REG_ATTR */
743+
744+/* REG_VOL */
745+#define REG_VOL_ATTM 0x80
746+
747+/* REG_STATUS */
748+#define R_STATUS_DTMIC 0x01
749+
750+/* REG_EQ controls use 4 bits for each of 5 EQ levels */
751+
752+/* Bluetooth not yet implemented */
753+#define REG_BTIF_PMAD2 0x01
754+#define REG_BTIF_PMDA2 0x02
755+#define REG_BTIF_PMBIF 0x04
756+#define REG_BTIF_ADC2 0x08
757+#define REG_BTIF_DAC2 0x10
758+#define REG_BTIF_BTFMT0 0x20
759+#define REG_BTIF_BTFMT1 0x40
760+/* unused 0x80 */
761+
762+/* begin {{ I2C }} */
763+
764+static struct i2c_driver snd_ak4641_i2c_driver = {
765+ .driver = {
766+ .name = "ak4641-i2c"
767+ },
768+};
769+
770+static int snd_ak4641_i2c_init(void)
771+{
772+ return i2c_add_driver(&snd_ak4641_i2c_driver);
773+}
774+
775+static void snd_ak4641_i2c_free(void)
776+{
777+ i2c_del_driver(&snd_ak4641_i2c_driver);
778+}
779+
780+static inline int snd_ak4641_i2c_probe(struct snd_ak4641 *ak)
781+{
782+ if (ak->i2c_client.adapter == NULL) return -EINVAL;
783+ ak->i2c_client.addr = 0x12;
784+ if (i2c_smbus_xfer(ak->i2c_client.adapter, ak->i2c_client.addr,
785+ 0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0)
786+ return -ENODEV;
787+ else return 0;
788+}
789+
790+static int snd_ak4641_i2c_attach(struct snd_ak4641 *ak)
791+{
792+ int ret = 0;
793+ if ((ret = snd_ak4641_i2c_probe(ak)) < 0) return ret;
794+ snprintf(ak->i2c_client.name, sizeof(ak->i2c_client.name),
795+ "ak4641-i2c at %d-%04x",
796+ i2c_adapter_id(ak->i2c_client.adapter), ak->i2c_client.addr);
797+ return i2c_attach_client(&ak->i2c_client);
798+}
799+
800+static void snd_ak4641_i2c_detach(struct snd_ak4641 *ak)
801+{
802+ i2c_detach_client(&ak->i2c_client);
803+}
804+
805+/* end {{ I2C }} */
806+
807+
808+/* begin {{ Registers & Cache Ops }} */
809+
810+static int snd_ak4641_hwsync(struct snd_ak4641 *ak, int read, u8 reg)
811+{
812+ struct i2c_msg msgs[2];
813+ u8 buf[2];
814+ int ret;
815+
816+ snd_assert(reg < ARRAY_SIZE(ak->regs), return -EINVAL);
817+
818+ /* setup i2c msgs */
819+ msgs[0].addr = ak->i2c_client.addr;
820+ msgs[0].flags = 0;
821+ msgs[0].buf = buf;
822+ if (!read)
823+ msgs[0].len = 2;
824+ else {
825+ msgs[1].flags = I2C_M_RD;
826+ msgs[1].addr = msgs[0].addr;
827+ msgs[1].buf = msgs[0].buf + 1;
828+ msgs[0].len = 1;
829+ msgs[1].len = 1;
830+ }
831+
832+ buf[0] = reg;
833+
834+ /* regs[reg] -> buffer, on write */
835+ if (!read) buf[1] = ak->regs[reg];
836+
837+ /* i2c transfer */
838+ ret = i2c_transfer(ak->i2c_client.adapter, msgs, read ? 2 : 1);
839+ if (ret != (read ? 2 : 1)) return ret; /* transfer error */ //@@ error ret < 0, or not ?
840+
841+ /* regs[reg] <- buffer, on read */
842+ if (read) ak->regs[reg] = buf[1];
843+
844+ return 0;
845+}
846+
847+static inline int snd_ak4641_hwsync_read(struct snd_ak4641 *ak, u8 reg)
848+{
849+ return snd_ak4641_hwsync(ak, 1, reg);
850+}
851+
852+static inline int snd_ak4641_hwsync_write(struct snd_ak4641 *ak, u8 reg)
853+{
854+ return snd_ak4641_hwsync(ak, 0, reg);
855+}
856+
857+static int snd_ak4641_hwsync_read_all(struct snd_ak4641 *ak)
858+{
859+ u8 reg;
860+ for (reg = 0; reg < ARRAY_SIZE(ak->regs); reg++)
861+ if (snd_ak4641_hwsync_read(ak, reg) < 0) return -1;
862+ return 0;
863+}
864+
865+static int snd_ak4641_hwsync_write_all(struct snd_ak4641 *ak)
866+{
867+ u8 reg;
868+ for (reg = 0; reg < ARRAY_SIZE(ak->regs); reg++)
869+ if (snd_ak4641_hwsync_write(ak, reg) < 0) return -1;
870+ return 0;
871+}
872+
873+static int snd_ak4641_reg_changed(struct snd_ak4641 *ak, u8 reg)
874+{
875+ if ((reg != R_PGA && ak->powered_on) ||
876+ (reg == R_PGA && (ak->regs[R_PM1] & R_PM1_PMMIC)))
877+ return snd_ak4641_hwsync_write(ak, reg);
878+ return 0;
879+}
880+
881+/* end {{ Registers & Cache Ops }}*/
882+
883+
884+static inline void snd_ak4641_lock(struct snd_ak4641 *ak)
885+{
886+ down(&ak->sem);
887+}
888+
889+static inline void snd_ak4641_unlock(struct snd_ak4641 *ak)
890+{
891+ up(&ak->sem);
892+}
893+
894+#define WRITE_MASK(i, val, mask) (((i) & ~(mask)) | ((val) & (mask)))
895+
896+
897+/* begin {{ Controls }} */
898+
899+#define INV_RANGE(val, mask) \
900+ (~(val) & (mask))
901+
902+/*-begin----------------------------------------------------------*/
903+static int snd_ak4641_actl_playback_volume_info(struct snd_kcontrol *kcontrol,
904+ struct snd_ctl_elem_info *uinfo)
905+{
906+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
907+ uinfo->count = 2;
908+ uinfo->value.integer.min = 0;
909+ uinfo->value.integer.max = 0xff;
910+ return 0;
911+}
912+
913+static int snd_ak4641_actl_playback_volume_get(struct snd_kcontrol *kcontrol,
914+ struct snd_ctl_elem_value *ucontrol)
915+{
916+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
917+
918+ snd_ak4641_lock(ak);
919+ ucontrol->value.integer.value[0] = INV_RANGE(ak->regs[R_ATTL], 0xff);
920+ ucontrol->value.integer.value[1] = INV_RANGE(ak->regs[R_ATTR], 0xff);
921+ snd_ak4641_unlock(ak);
922+ return 0;
923+}
924+
925+static int snd_ak4641_actl_playback_volume_put(struct snd_kcontrol *kcontrol,
926+ struct snd_ctl_elem_value *ucontrol)
927+{
928+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
929+
930+ snd_ak4641_lock(ak);
931+ ak->regs[R_ATTL] = INV_RANGE(ucontrol->value.integer.value[0], 0xff);
932+ ak->regs[R_ATTR] = INV_RANGE(ucontrol->value.integer.value[1], 0xff);
933+ snd_ak4641_reg_changed(ak, R_ATTL);
934+ snd_ak4641_reg_changed(ak, R_ATTR);
935+ snd_ak4641_unlock(ak);
936+ return 0;
937+}
938+/*-end------------------------------------------------------------*/
939+
940+/*-begin----------------------------------------------------------*/
941+static int snd_ak4641_actl_mic_gain_info(struct snd_kcontrol *kcontrol,
942+ struct snd_ctl_elem_info *uinfo)
943+{
944+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
945+ uinfo->count = 1;
946+ uinfo->value.integer.min = 0;
947+ uinfo->value.integer.max = 0x7f;
948+ return 0;
949+}
950+
951+static int snd_ak4641_actl_mic_gain_get(struct snd_kcontrol *kcontrol,
952+ struct snd_ctl_elem_value *ucontrol)
953+{
954+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
955+
956+ ucontrol->value.integer.value[0] = ak->regs[R_PGA];
957+ return 0;
958+}
959+
960+static int snd_ak4641_actl_mic_gain_put(struct snd_kcontrol *kcontrol,
961+ struct snd_ctl_elem_value *ucontrol)
962+{
963+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
964+
965+ snd_ak4641_lock(ak);
966+ ak->regs[R_PGA] = ucontrol->value.integer.value[0];
967+ snd_ak4641_reg_changed(ak, R_PGA);
968+ snd_ak4641_unlock(ak);
969+ return 0;
970+}
971+/*-end------------------------------------------------------------*/
972+
973+#define ACTL(ctl_name, _name) \
974+static struct snd_kcontrol_new snd_ak4641_actl_ ## ctl_name = \
975+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = _name, \
976+ .info = snd_ak4641_actl_ ## ctl_name ## _info, \
977+ .get = snd_ak4641_actl_ ## ctl_name ## _get, .put = snd_ak4641_actl_ ## ctl_name ## _put };
978+
979+ACTL(playback_volume, "Master Playback Volume")
980+ACTL(mic_gain, "Mic Capture Gain")
981+
982+struct snd_ak4641_uctl_bool {
983+ int (*get) (struct snd_ak4641 *uda);
984+ int (*set) (struct snd_ak4641 *uda, int on);
985+};
986+
987+static int snd_ak4641_actl_bool_info(struct snd_kcontrol *kcontrol,
988+ struct snd_ctl_elem_info *uinfo)
989+{
990+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
991+ uinfo->count = 1;
992+ return 0;
993+}
994+
995+static int snd_ak4641_actl_bool_get(struct snd_kcontrol *kcontrol,
996+ struct snd_ctl_elem_value *ucontrol)
997+{
998+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
999+ struct snd_ak4641_uctl_bool *uctl =
1000+ (struct snd_ak4641_uctl_bool *) kcontrol->private_value;
1001+
1002+ ucontrol->value.integer.value[0] = uctl->get(ak);
1003+ return 0;
1004+}
1005+
1006+static int snd_ak4641_actl_bool_put(struct snd_kcontrol *kcontrol,
1007+ struct snd_ctl_elem_value *ucontrol)
1008+{
1009+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
1010+ struct snd_ak4641_uctl_bool *uctl =
1011+ (struct snd_ak4641_uctl_bool *) kcontrol->private_value;
1012+
1013+ return uctl->set(ak, ucontrol->value.integer.value[0]);
1014+}
1015+
1016+/*-begin----------------------------------------------------------*/
1017+static int snd_ak4641_uctl_playback_switch_get(struct snd_ak4641 *ak)
1018+{
1019+ return (ak->regs[R_DAC] & R_DAC_SMUTE) == 0x00;
1020+}
1021+
1022+static int snd_ak4641_uctl_playback_switch_set(struct snd_ak4641 *ak, int on)
1023+{
1024+ snd_ak4641_lock(ak);
1025+ ak->regs[R_DAC] = WRITE_MASK(ak->regs[R_DAC],
1026+ on ? 0x00 : R_DAC_SMUTE, R_DAC_SMUTE);
1027+ snd_ak4641_reg_changed(ak, R_DAC);
1028+ snd_ak4641_unlock(ak);
1029+ return 0;
1030+}
1031+/*-end------------------------------------------------------------*/
1032+
1033+/*-begin----------------------------------------------------------*/
1034+static int snd_ak4641_uctl_mic_boost_get(struct snd_ak4641 *ak)
1035+{
1036+ return (ak->regs[R_MIC] & R_MIC_MGAIN) == R_MIC_MGAIN;
1037+}
1038+
1039+static int snd_ak4641_uctl_mic_boost_set(struct snd_ak4641 *ak, int on)
1040+{
1041+ snd_ak4641_lock(ak);
1042+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC],
1043+ on ? R_MIC_MGAIN : 0x00, R_MIC_MGAIN);
1044+ snd_ak4641_reg_changed(ak, R_MIC);
1045+ snd_ak4641_unlock(ak);
1046+ return 0;
1047+}
1048+/*-end------------------------------------------------------------*/
1049+
1050+/*-begin----------------------------------------------------------*/
1051+static int snd_ak4641_uctl_mono_out_get(struct snd_ak4641 *ak)
1052+{
1053+ printk("mono_out status 0x%8.8x -> 0x%8.8x\n",ak->regs[R_SEL1], ak->regs[R_SEL1] & REG_SEL1_PSMO);
1054+ return (ak->regs[R_SEL1] & REG_SEL1_PSMO) == REG_SEL1_PSMO;
1055+}
1056+
1057+static int snd_ak4641_uctl_mono_out_set(struct snd_ak4641 *ak, int on)
1058+{
1059+ printk("phone mic enable called. on=%d\n",on);
1060+ snd_ak4641_lock(ak);
1061+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], on ? R_PM1_PMMIC : 0x00, R_PM1_PMMIC);
1062+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], on ? REG_PWR1_PMMO : 0x00, REG_PWR1_PMMO);
1063+ snd_ak4641_reg_changed(ak, R_PM1);
1064+
1065+ snd_ak4641_hwsync_write(ak, R_PGA); /* mic PGA gain is reset when PMMIC = 0 */
1066+
1067+ /* internal mic */
1068+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], on ? R_MIC_MPWRI : 0x0, R_MIC_MPWRI);
1069+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], 0x0, R_MIC_MSEL);
1070+ snd_ak4641_hwsync_write(ak, R_MIC);
1071+
1072+// ak->regs[REG_BTIF] = WRITE_MASK(ak->regs[REG_BTIF], 0x0, REG_BTIF_DAC2);
1073+// snd_ak4641_hwsync_write(ak, REG_BTIF);
1074+ /* */
1075+// ak->regs[REG_VOL] = WRITE_MASK(ak->regs[REG_VOL], on ? REG_VOL_ATTM : 0x00, REG_VOL_ATTM);
1076+// ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_MOGN : 0x00, REG_SEL1_MOGN);
1077+ ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_MICM : 0x00, REG_SEL1_MICM);
1078+ ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_PSMO : 0x00, REG_SEL1_PSMO);
1079+ snd_ak4641_reg_changed(ak, R_SEL1);
1080+ snd_ak4641_unlock(ak);
1081+ return 0;
1082+}
1083+/*-end------------------------------------------------------------*/
1084+
1085+#define ACTL_BOOL(ctl_name, _name) \
1086+static struct snd_ak4641_uctl_bool snd_ak4641_actl_ ## ctl_name ## _pvalue = \
1087+{ .get = snd_ak4641_uctl_ ## ctl_name ## _get, \
1088+ .set = snd_ak4641_uctl_ ## ctl_name ## _set }; \
1089+static struct snd_kcontrol_new snd_ak4641_actl_ ## ctl_name = \
1090+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = _name, .info = snd_ak4641_actl_bool_info, \
1091+ .get = snd_ak4641_actl_bool_get, .put = snd_ak4641_actl_bool_put, \
1092+ .private_value = (unsigned long) &snd_ak4641_actl_ ## ctl_name ## _pvalue };
1093+
1094+ACTL_BOOL(playback_switch, "Master Playback Switch")
1095+ACTL_BOOL(mic_boost, "Mic Boost (+20dB)")
1096+ACTL_BOOL(mono_out, "Phone mic enable")
1097+
1098+static void snd_ak4641_headphone_on(struct snd_ak4641 *ak, int on);
1099+static void snd_ak4641_speaker_on(struct snd_ak4641 *ak, int on);
1100+static void snd_ak4641_select_mic(struct snd_ak4641 *ak);
1101+
1102+void snd_ak4641_hp_connected(struct snd_ak4641 *ak, int connected)
1103+{
1104+ snd_ak4641_lock(ak);
1105+ if (connected != ak->hp_connected) {
1106+ ak->hp_connected = connected;
1107+
1108+ /* headphone or speaker, on playback */
1109+ if (ak->playback_on) {
1110+ if (connected) {
1111+ snd_ak4641_headphone_on(ak, 1);
1112+ snd_ak4641_speaker_on(ak, 0);
1113+ } else {
1114+ snd_ak4641_speaker_on(ak, 1);
1115+ snd_ak4641_headphone_on(ak, 0);
1116+ }
1117+ }
1118+
1119+ /* headset or internal mic, on capture */
1120+ if (ak->capture_on)
1121+ snd_ak4641_select_mic(ak);
1122+ }
1123+ snd_ak4641_unlock(ak);
1124+}
1125+
1126+/* end {{ Controls }} */
1127+
1128+
1129+/* begin {{ Headphone Detected Notification }} */
1130+
1131+static void snd_ak4641_hp_detected_w_fn(void *p)
1132+{
1133+ struct snd_ak4641 *ak = (struct snd_ak4641 *)p;
1134+
1135+ snd_ak4641_hp_connected(ak, ak->hp_detected.detected);
1136+}
1137+
1138+void snd_ak4641_hp_detected(struct snd_ak4641 *ak, int detected)
1139+{
1140+ if (detected != ak->hp_detected.detected) {
1141+ ak->hp_detected.detected = detected;
1142+ queue_work(ak->hp_detected.wq, &ak->hp_detected.w);
1143+ }
1144+}
1145+
1146+static int snd_ak4641_hp_detected_init(struct snd_ak4641 *ak)
1147+{
1148+ INIT_WORK(&ak->hp_detected.w, snd_ak4641_hp_detected_w_fn);
1149+ ak->hp_detected.detected = ak->hp_connected;
1150+ ak->hp_detected.wq = create_singlethread_workqueue("ak4641");
1151+ if (ak->hp_detected.wq) return 0;
1152+ else return -1;
1153+}
1154+
1155+static void snd_ak4641_hp_detected_free(struct snd_ak4641 *ak)
1156+{
1157+ destroy_workqueue(ak->hp_detected.wq);
1158+}
1159+
1160+/* end {{ Headphone Detected Notification }} */
1161+
1162+
1163+/* begin {{ Codec Control }} */
1164+
1165+static void snd_ak4641_headphone_on(struct snd_ak4641 *ak, int on)
1166+{
1167+ if (on) {
1168+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO);
1169+ snd_ak4641_hwsync_write(ak, R_PM1);
1170+ ak->headphone_out_on(1);
1171+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
1172+ R_SEL2_PSLOL | R_SEL2_PSLOR,
1173+ R_SEL2_PSLOL | R_SEL2_PSLOR);
1174+ snd_ak4641_hwsync_write(ak, R_SEL2);
1175+ } else {
1176+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
1177+ 0x00, R_SEL2_PSLOL | R_SEL2_PSLOR);
1178+ snd_ak4641_hwsync_write(ak, R_SEL2);
1179+ ak->headphone_out_on(0);
1180+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO);
1181+ snd_ak4641_hwsync_write(ak, R_PM1);
1182+ }
1183+}
1184+
1185+static void snd_ak4641_speaker_on(struct snd_ak4641 *ak, int on)
1186+{
1187+ if (on) {
1188+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO);
1189+ snd_ak4641_hwsync_write(ak, R_PM1);
1190+ ak->speaker_out_on(1);
1191+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
1192+ R_SEL2_PSLOL | R_SEL2_PSLOR,
1193+ R_SEL2_PSLOL | R_SEL2_PSLOR);
1194+ snd_ak4641_hwsync_write(ak, R_SEL2);
1195+ } else {
1196+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
1197+ 0x00, R_SEL2_PSLOL | R_SEL2_PSLOR);
1198+ snd_ak4641_hwsync_write(ak, R_SEL2);
1199+ ak->speaker_out_on(0);
1200+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO);
1201+ snd_ak4641_hwsync_write(ak, R_PM1);
1202+ }
1203+}
1204+
1205+static inline int snd_ak4641_power_on(struct snd_ak4641 *ak)
1206+{
1207+ ak->reset_pin(1);
1208+ ak->power_on_chip(1);
1209+ msleep(1);
1210+ ak->reset_pin(0);
1211+ ak->powered_on = 1;
1212+ return 0;
1213+}
1214+
1215+static inline int snd_ak4641_power_off(struct snd_ak4641 *ak)
1216+{
1217+ ak->powered_on = 0;
1218+ ak->power_on_chip(0);
1219+ return 0;
1220+}
1221+
1222+static inline void snd_ak4641_headphone_out_on(struct snd_ak4641 *ak, int on)
1223+{
1224+ if (ak->headphone_out_on) ak->headphone_out_on(on);
1225+}
1226+
1227+static inline void snd_ak4641_speaker_out_on(struct snd_ak4641 *ak, int on)
1228+{
1229+ if (ak->speaker_out_on) ak->speaker_out_on(on);
1230+}
1231+
1232+static int snd_ak4641_playback_on(struct snd_ak4641 *ak)
1233+{
1234+ if (ak->playback_on) return 0;
1235+
1236+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2],
1237+ R_PM2_PMDAC, R_PM2_MCKPD | R_PM2_PMDAC);
1238+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO);
1239+ snd_ak4641_hwsync_write(ak, R_PM2);
1240+ snd_ak4641_hwsync_write(ak, R_PM1);
1241+ if (ak->hp_connected) snd_ak4641_headphone_on(ak, 1);
1242+ else snd_ak4641_speaker_on(ak, 1);
1243+
1244+ ak->playback_on = 1;
1245+
1246+ return 0;
1247+}
1248+
1249+static int snd_ak4641_playback_off(struct snd_ak4641 *ak)
1250+{
1251+ if (!ak->playback_on) return 0;
1252+
1253+ ak->playback_on = 0;
1254+
1255+ if (ak->hp_connected) snd_ak4641_headphone_on(ak, 0);
1256+ else snd_ak4641_speaker_on(ak, 0);
1257+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO);
1258+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2],
1259+ (!ak->capture_on ? R_PM2_MCKPD : 0x00) | R_PM2_PMDAC,
1260+ R_PM2_MCKPD | R_PM2_PMDAC);
1261+ snd_ak4641_hwsync_write(ak, R_PM1);
1262+ snd_ak4641_hwsync_write(ak, R_PM2);
1263+
1264+ return 0;
1265+}
1266+
1267+static void snd_ak4641_select_mic(struct snd_ak4641 *ak)
1268+{
1269+ int mic = 0;
1270+ u8 r_mic;
1271+
1272+ if (ak->hp_connected) {
1273+ /* check headset mic */
1274+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], R_MIC_MPWRE, R_MIC_MPWRE);
1275+ snd_ak4641_hwsync_write(ak, R_MIC);
1276+ snd_ak4641_hwsync_read(ak, R_STATUS);
1277+ mic = (ak->regs[R_STATUS] & R_STATUS_DTMIC) == R_STATUS_DTMIC;
1278+
1279+ printk("htcuniversal_ak4641_select_mic: mic=%d\n",mic);
1280+
1281+ r_mic = WRITE_MASK(ak->regs[R_MIC],
1282+ R_MIC_MSEL | (ak->capture_on ? R_MIC_MPWRE : 0x00),
1283+ R_MIC_MSEL | R_MIC_MPWRI | R_MIC_MPWRE);
1284+ }
1285+ else
1286+ r_mic = WRITE_MASK(ak->regs[R_MIC],
1287+ 0x00 | (ak->capture_on ? R_MIC_MPWRI : 0x00),
1288+ R_MIC_MSEL | R_MIC_MPWRI | R_MIC_MPWRE);
1289+
1290+ if (r_mic != ak->regs[R_MIC]) {
1291+ ak->regs[R_MIC] = r_mic;
1292+ snd_ak4641_hwsync_write(ak, R_MIC);
1293+ }
1294+}
1295+
1296+static int snd_ak4641_capture_on(struct snd_ak4641 *ak)
1297+{
1298+ if (ak->capture_on) return 0;
1299+
1300+ if (!ak->playback_on) {
1301+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], 0x00, R_PM2_MCKPD);
1302+ snd_ak4641_hwsync_write(ak, R_PM2);
1303+ }
1304+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMMIC | R_PM1_PMADC,
1305+ R_PM1_PMMIC | R_PM1_PMADC);
1306+ snd_ak4641_hwsync_write(ak, R_PM1);
1307+ snd_ak4641_hwsync_write(ak, R_PGA); /* mic PGA gain is reset when PMMIC = 0 */
1308+
1309+ ak->capture_on = 1;
1310+
1311+ snd_ak4641_select_mic(ak);
1312+
1313+ msleep(47); /* accounts for ADC init cycle, time enough for fs >= 44.1 kHz */
1314+
1315+ return 0;
1316+}
1317+
1318+static int snd_ak4641_capture_off(struct snd_ak4641 *ak)
1319+{
1320+ if (!ak->capture_on) return 0;
1321+
1322+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC],
1323+ 0x00, R_MIC_MPWRI | R_MIC_MPWRE | R_MIC_MSEL);
1324+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMMIC | R_PM1_PMADC);
1325+ snd_ak4641_hwsync_write(ak, R_MIC);
1326+ snd_ak4641_hwsync_write(ak, R_PM1);
1327+ if (!ak->playback_on) {
1328+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], R_PM2_MCKPD, R_PM2_MCKPD);
1329+ snd_ak4641_hwsync_write(ak, R_PM2);
1330+ }
1331+
1332+ ak->capture_on = 0;
1333+
1334+ return 0;
1335+}
1336+
1337+int snd_ak4641_open_stream(struct snd_ak4641 *ak, int stream)
1338+{
1339+ snd_ak4641_lock(ak);
1340+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1341+ ak->playback_stream_opened = 1;
1342+ snd_ak4641_playback_on(ak);
1343+ } else {
1344+ ak->capture_stream_opened = 1;
1345+ snd_ak4641_capture_on(ak);
1346+ }
1347+ snd_ak4641_unlock(ak);
1348+ return 0;
1349+}
1350+
1351+int snd_ak4641_close_stream(struct snd_ak4641 *ak, int stream)
1352+{
1353+ snd_ak4641_lock(ak);
1354+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1355+ ak->playback_stream_opened = 0;
1356+ snd_ak4641_playback_off(ak);
1357+ } else {
1358+ ak->capture_stream_opened = 0;
1359+ snd_ak4641_capture_off(ak);
1360+ }
1361+ snd_ak4641_unlock(ak);
1362+ return 0;
1363+}
1364+
1365+static int snd_ak4641_init_regs(struct snd_ak4641 *ak)
1366+{
1367+ snd_ak4641_hwsync_read_all(ak);
1368+
1369+ //@@ MEMO: add some configs
1370+
1371+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMVCM, R_PM1_PMVCM);
1372+ ak->regs[R_DAC] = WRITE_MASK(ak->regs[R_DAC], 0x00, R_DAC_DATTC);
1373+ snd_ak4641_hwsync_write(ak, R_PM1);
1374+ snd_ak4641_hwsync_write(ak, R_DAC);
1375+
1376+ return 0;
1377+}
1378+
1379+int snd_ak4641_suspend(struct snd_ak4641 *ak, pm_message_t state)
1380+{
1381+ snd_ak4641_lock(ak);
1382+ if (ak->playback_on) snd_ak4641_playback_off(ak);
1383+ if (ak->capture_on) snd_ak4641_capture_off(ak);
1384+ snd_ak4641_power_off(ak);
1385+ snd_ak4641_unlock(ak);
1386+ return 0;
1387+}
1388+
1389+int snd_ak4641_resume(struct snd_ak4641 *ak)
1390+{
1391+ snd_ak4641_lock(ak);
1392+ snd_ak4641_power_on(ak);
1393+ snd_ak4641_hwsync_write_all(ak);
1394+ if (ak->playback_stream_opened) snd_ak4641_playback_on(ak);
1395+ if (ak->capture_stream_opened) snd_ak4641_capture_on(ak);
1396+ snd_ak4641_unlock(ak);
1397+ return 0;
1398+}
1399+
1400+static void snd_ak4641_init_ak(struct snd_ak4641 *ak)
1401+{
1402+ init_MUTEX(&ak->sem);
1403+ ak->i2c_client.driver = &snd_ak4641_i2c_driver;
1404+}
1405+
1406+int snd_ak4641_activate(struct snd_ak4641 *ak)
1407+{
1408+ int ret = 0;
1409+
1410+ snd_ak4641_init_ak(ak);
1411+ snd_ak4641_lock(ak);
1412+ snd_ak4641_power_on(ak);
1413+ if ((ret = snd_ak4641_i2c_attach(ak)) < 0)
1414+ goto failed_i2c_attach;
1415+ snd_ak4641_init_regs(ak);
1416+ if ((ret = snd_ak4641_hp_detected_init(ak)) < 0)
1417+ goto failed_hp_detected_init;
1418+ snd_ak4641_unlock(ak);
1419+ return 0;
1420+
1421+ failed_hp_detected_init:
1422+ snd_ak4641_i2c_detach(ak);
1423+ failed_i2c_attach:
1424+ snd_ak4641_power_off(ak);
1425+ snd_ak4641_unlock(ak);
1426+ return ret;
1427+}
1428+
1429+void snd_ak4641_deactivate(struct snd_ak4641 *ak)
1430+{
1431+ snd_ak4641_lock(ak);
1432+ snd_ak4641_hp_detected_free(ak);
1433+ snd_ak4641_i2c_detach(ak);
1434+ snd_ak4641_power_off(ak);
1435+ snd_ak4641_unlock(ak);
1436+}
1437+
1438+int snd_ak4641_add_mixer_controls(struct snd_ak4641 *ak, struct snd_card *card)
1439+{
1440+ snd_ak4641_lock(ak);
1441+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_playback_volume, ak));
1442+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_playback_switch, ak));
1443+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mic_gain, ak));
1444+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mic_boost, ak));
1445+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mono_out, ak));
1446+ snd_ak4641_unlock(ak);
1447+ return 0;
1448+}
1449+
1450+/* end {{ Codec Control }} */
1451+
1452+
1453+/* begin {{ Module }} */
1454+
1455+static int __init snd_ak4641_module_on_load(void)
1456+{
1457+ snd_ak4641_i2c_init();
1458+ return 0;
1459+}
1460+
1461+static void __exit snd_ak4641_module_on_unload(void)
1462+{
1463+ snd_ak4641_i2c_free();
1464+}
1465+
1466+module_init(snd_ak4641_module_on_load);
1467+module_exit(snd_ak4641_module_on_unload);
1468+
1469+EXPORT_SYMBOL(snd_ak4641_activate);
1470+EXPORT_SYMBOL(snd_ak4641_deactivate);
1471+EXPORT_SYMBOL(snd_ak4641_add_mixer_controls);
1472+EXPORT_SYMBOL(snd_ak4641_open_stream);
1473+EXPORT_SYMBOL(snd_ak4641_close_stream);
1474+EXPORT_SYMBOL(snd_ak4641_suspend);
1475+EXPORT_SYMBOL(snd_ak4641_resume);
1476+EXPORT_SYMBOL(snd_ak4641_hp_connected);
1477+EXPORT_SYMBOL(snd_ak4641_hp_detected);
1478+
1479+MODULE_AUTHOR("Giorgio Padrin");
1480+MODULE_DESCRIPTION("Audio support for codec Asahi Kasei AK4641");
1481+MODULE_LICENSE("GPL");
1482+
1483+/* end {{ Module }} */
1484Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h
1485===================================================================
1486--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1487+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h 2007-09-11 12:53:37.000000000 +0200
1488@@ -0,0 +1,65 @@
1489+/*
1490+ * Audio support for codec Asahi Kasei AK4641
1491+ *
1492+ * This program is free software; you can redistribute it and/or modify
1493+ * it under the terms of the GNU General Public License version 2 as
1494+ * published by the Free Software Foundation.
1495+ *
1496+ * Copyright (c) 2006 Giorgio Padrin <giorgio@mandarinlogiq.org>
1497+ */
1498+
1499+#ifndef __SOUND_AK4641_H
1500+#define __SOUND_AK4641_H
1501+
1502+#include <linux/i2c.h>
1503+
1504+struct snd_ak4641 {
1505+ struct semaphore sem;
1506+
1507+ u8 regs[0x14]; /* registers cache */
1508+
1509+ unsigned int
1510+ powered_on:1,
1511+ playback_on:1,
1512+ playback_stream_opened:1,
1513+ capture_on:1,
1514+ capture_stream_opened:1;
1515+
1516+ unsigned int
1517+ hp_connected:1;
1518+
1519+ /* -- configuration (to fill before activation) -- */
1520+ void (*power_on_chip)(int on);
1521+ void (*reset_pin)(int on);
1522+ void (*headphone_out_on)(int on);
1523+ void (*speaker_out_on)(int on);
1524+
1525+ struct i2c_client i2c_client; /* to fill .adapter */
1526+ /* ----------------------------------------------- */
1527+
1528+ struct {
1529+ int detected;
1530+ struct workqueue_struct *wq;
1531+ struct work_struct w;
1532+ } hp_detected;
1533+};
1534+
1535+
1536+/* Note: opening, closing, suspending and resuming a stream
1537+ * require the clocks (MCLK and I2S ones) running
1538+ */
1539+
1540+/* don't forget to specify I2C adapter in i2c_client field */
1541+int snd_ak4641_activate(struct snd_ak4641 *ak);
1542+
1543+void snd_ak4641_deactivate(struct snd_ak4641 *ak);
1544+int snd_ak4641_add_mixer_controls(struct snd_ak4641 *ak, struct snd_card *card);
1545+int snd_ak4641_open_stream(struct snd_ak4641 *ak, int stream);
1546+int snd_ak4641_close_stream(struct snd_ak4641 *ak, int stream);
1547+int snd_ak4641_suspend(struct snd_ak4641 *ak, pm_message_t state);
1548+int snd_ak4641_resume(struct snd_ak4641 *ak);
1549+
1550+void snd_ak4641_hp_connected(struct snd_ak4641 *ak, int connected); /* non atomic context */
1551+void snd_ak4641_hp_detected(struct snd_ak4641 *ak, int detected); /* atomic context */
1552+
1553+#endif /* __SOUND_AK4641_H */
1554Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c
1555===================================================================
1556--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1557+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c 2007-09-11 12:53:37.000000000 +0200
1558@@ -0,0 +1,143 @@
1559+/*
1560+ * LEDs support for the HP iPaq hx4700
1561+ *
1562+ * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru>
1563+ *
1564+ * This file is subject to the terms and conditions of the GNU General Public
1565+ * License. See the file COPYING in the main directory of this archive for
1566+ * more details.
1567+ *
1568+ */
1569+
1570+#include <linux/kernel.h>
1571+#include <linux/init.h>
1572+#include <linux/platform_device.h>
1573+#include <linux/leds.h>
1574+#include <linux/soc/asic3_base.h>
1575+
1576+#include <asm/hardware/ipaq-asic3.h>
1577+#include <asm/mach-types.h>
1578+#include <asm/hardware/asic3_leds.h>
1579+#include <asm/arch/htcuniversal-asic.h>
1580+
1581+//FIXME
1582+//DEFINE_LED_TRIGGER_SHARED_GLOBAL(htcuniversal_radio_trig);
1583+//EXPORT_LED_TRIGGER_SHARED(htcuniversal_radio_trig);
1584+
1585+static struct asic3_led htcuniversal_leds[] = {
1586+ {
1587+ .led_cdev = {
1588+ .name = "htcuniversal:red",
1589+ .default_trigger = "htcuniversal-charging",
1590+ },
1591+ .hw_num = 2,
1592+
1593+ },
1594+ {
1595+ .led_cdev = {
1596+ .name = "htcuniversal:green",
1597+ .default_trigger = "htcuniversal-chargefull",
1598+ },
1599+ .hw_num = 1,
1600+ },
1601+ {
1602+ .led_cdev = {
1603+ .name = "htcuniversal:wifi-bt",
1604+ .default_trigger = "htcuniversal-radio",
1605+ },
1606+ .hw_num = 0,
1607+ },
1608+ {
1609+ .led_cdev = {
1610+ .name = "htcuniversal:phonebuttons",
1611+ .default_trigger = "htcuniversal-phonebuttons",
1612+ },
1613+ .hw_num = -1,
1614+ .gpio_num = ('D'-'A')*16+GPIOD_BL_KEYP_PWR_ON,
1615+ },
1616+ {
1617+ .led_cdev = {
1618+ .name = "htcuniversal:vibra",
1619+ .default_trigger = "htcuniversal-vibra",
1620+ },
1621+ .hw_num = -1,
1622+ .gpio_num = ('D'-'A')*16+GPIOD_VIBRA_PWR_ON,
1623+ },
1624+ {
1625+ .led_cdev = {
1626+ .name = "htcuniversal:flashlight1",
1627+ .default_trigger = "htcuniversal-flashlight1",
1628+ },
1629+ .hw_num = -1,
1630+ .gpio_num = ('A'-'A')*16+GPIOA_FLASHLIGHT,
1631+ },
1632+ {
1633+ .led_cdev = {
1634+ .name = "htcuniversal:kbdbacklight",
1635+ .default_trigger = "htcuniversal-kbdbacklight",
1636+ },
1637+ .hw_num = -1,
1638+ .gpio_num = ('D'-'A')*16+GPIOD_BL_KEYB_PWR_ON,
1639+ },
1640+};
1641+
1642+void htcuniversal_leds_release(struct device *dev)
1643+{
1644+ return;
1645+}
1646+
1647+static
1648+struct asic3_leds_machinfo htcuniversal_leds_machinfo = {
1649+ .num_leds = ARRAY_SIZE(htcuniversal_leds),
1650+ .leds = htcuniversal_leds,
1651+ .asic3_pdev = &htcuniversal_asic3,
1652+};
1653+
1654+static
1655+struct platform_device htcuniversal_leds_pdev = {
1656+ .name = "asic3-leds",
1657+ .dev = {
1658+ .platform_data = &htcuniversal_leds_machinfo,
1659+ .release = htcuniversal_leds_release,
1660+ },
1661+};
1662+
1663+static
1664+int __init htcuniversal_leds_init(void)
1665+{
1666+ int ret;
1667+ printk("htcuniversal LEDs Driver\n");
1668+// led_trigger_register_shared("htcuniversal-radio", &htcuniversal_radio_trig);
1669+
1670+ ret = asic3_leds_register();
1671+ if (ret) goto asic3_leds_failed;
1672+
1673+ ret = platform_device_register(&htcuniversal_leds_pdev);
1674+ if (ret) goto platform_device_failed;
1675+
1676+ goto success;
1677+
1678+platform_device_failed:
1679+ asic3_leds_unregister();
1680+asic3_leds_failed:
1681+// led_trigger_unregister_shared(htcuniversal_radio_trig);
1682+ printk("htcuniversal LEDs Driver failed to init");
1683+success:
1684+ return ret;
1685+}
1686+
1687+static
1688+void __exit htcuniversal_leds_exit(void)
1689+{
1690+// led_trigger_unregister_shared(htcuniversal_radio_trig);
1691+ platform_device_unregister(&htcuniversal_leds_pdev);
1692+ asic3_leds_unregister();
1693+ return;
1694+}
1695+
1696+module_init(htcuniversal_leds_init);
1697+module_exit(htcuniversal_leds_exit);
1698+
1699+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
1700+MODULE_DESCRIPTION("htcuniversal LEDs driver");
1701+MODULE_LICENSE("GPL");
1702Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c
1703===================================================================
1704--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1705+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c 2007-09-11 12:53:37.000000000 +0200
1706@@ -0,0 +1,61 @@
1707+/*
1708+ * Use consistent with the GNU GPL is permitted,
1709+ * provided that this copyright notice is
1710+ * preserved in its entirety in all copies and derived works.
1711+ *
1712+ * Copyright (C) 2006 Paul Sokolosvky
1713+ * Based on code from older versions of htcuniversal_lcd.c
1714+ *
1715+ */
1716+
1717+#include <linux/types.h>
1718+#include <linux/platform_device.h>
1719+#include <asm/arch/hardware.h> /* for pxa-regs.h (__REG) */
1720+#include <asm/arch/pxa-regs.h>
1721+#include <asm/mach-types.h> /* machine_is_htcuniversal */
1722+//#include <linux/corgi_bl.h>
1723+#include <linux/backlight.h>
1724+#include <linux/err.h>
1725+
1726+#include <asm/arch/htcuniversal-gpio.h>
1727+#include <asm/arch/htcuniversal-asic.h>
1728+#include <asm/hardware/ipaq-asic3.h>
1729+#include <linux/soc/asic3_base.h>
1730+
1731+#define HTCUNIVERSAL_MAX_INTENSITY 0xc7
1732+
1733+static void htcuniversal_set_bl_intensity(int intensity)
1734+{
1735+ PWM_CTRL1 = 1; /* pre-scaler */
1736+ PWM_PWDUTY1 = intensity; /* duty cycle */
1737+ PWM_PERVAL1 = HTCUNIVERSAL_MAX_INTENSITY+1; /* period */
1738+
1739+ if (intensity > 0) {
1740+ pxa_set_cken(CKEN_PWM1, 1);
1741+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev,
1742+ (1<<GPIOD_FL_PWR_ON), (1<<GPIOD_FL_PWR_ON));
1743+ } else {
1744+ pxa_set_cken(CKEN_PWM1, 0);
1745+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev,
1746+ (1<<GPIOD_FL_PWR_ON), 0);
1747+ }
1748+}
1749+
1750+
1751+static struct generic_bl_info htcuniversal_bl_machinfo = {
1752+ .default_intensity = HTCUNIVERSAL_MAX_INTENSITY / 4,
1753+ .limit_mask = 0xff,
1754+ .max_intensity = HTCUNIVERSAL_MAX_INTENSITY,
1755+ .set_bl_intensity = htcuniversal_set_bl_intensity,
1756+};
1757+
1758+struct platform_device htcuniversal_bl = {
1759+ .name = "corgi-bl",
1760+ .dev = {
1761+ .platform_data = &htcuniversal_bl_machinfo,
1762+ },
1763+};
1764+
1765+MODULE_AUTHOR("Paul Sokolovsky <pmiscml@gmail.com>");
1766+MODULE_DESCRIPTION("Backlight driver for HTC Universal");
1767+MODULE_LICENSE("GPL");
1768Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c
1769===================================================================
1770--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1771+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c 2007-09-11 12:53:37.000000000 +0200
1772@@ -0,0 +1,135 @@
1773+/* Bluetooth interface driver for TI BRF6150 on HX4700
1774+ *
1775+ * Copyright (c) 2005 SDG Systems, LLC
1776+ *
1777+ * 2005-04-21 Todd Blumer Created.
1778+ */
1779+
1780+#include <linux/module.h>
1781+#include <linux/kernel.h>
1782+#include <linux/delay.h>
1783+#include <linux/platform_device.h>
1784+#include <linux/soc/asic3_base.h>
1785+
1786+#include <asm/hardware.h>
1787+#include <asm/arch/serial.h>
1788+#include <asm/hardware/ipaq-asic3.h>
1789+#include <asm/arch/htcuniversal-gpio.h>
1790+#include <asm/arch/htcuniversal-asic.h>
1791+
1792+#include "htcuniversal_bt.h"
1793+
1794+static uint use_led=1;
1795+
1796+static void
1797+htcuniversal_bt_configure( int state )
1798+{
1799+ int tries;
1800+
1801+ printk( KERN_NOTICE "htcuniversal configure bluetooth: %d\n", state );
1802+ switch (state) {
1803+
1804+ case PXA_UART_CFG_PRE_STARTUP:
1805+ break;
1806+
1807+ case PXA_UART_CFG_POST_STARTUP:
1808+ /* pre-serial-up hardware configuration */
1809+ htcuniversal_egpio_enable(1<<EGPIO5_BT_3V3_ON);
1810+ mdelay(50);
1811+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_PWR_ON, 1<<GPIOC_BT_PWR_ON);
1812+ mdelay(10);
1813+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_RESET, 0);
1814+ mdelay(10);
1815+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_RESET, 1<<GPIOC_BT_RESET);
1816+ mdelay(10);
1817+
1818+ /*
1819+ * BRF6150's RTS goes low when firmware is ready
1820+ * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
1821+ */
1822+ tries = 0;
1823+ do {
1824+ mdelay(10);
1825+ } while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
1826+ if (use_led) {
1827+// htcuniversal_set_led(2, 16, 16);
1828+ }
1829+ break;
1830+
1831+ case PXA_UART_CFG_PRE_SHUTDOWN:
1832+ htcuniversal_egpio_disable(1<<EGPIO5_BT_3V3_ON );
1833+ mdelay(50);
1834+// htcuniversal_clear_led(2);
1835+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_PWR_ON, 0);
1836+ break;
1837+
1838+ default:
1839+ break;
1840+ }
1841+}
1842+
1843+
1844+static int
1845+htcuniversal_bt_probe( struct platform_device *dev )
1846+{
1847+ struct htcuniversal_bt_funcs *funcs = dev->dev.platform_data;
1848+
1849+ /* configure bluetooth UART */
1850+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_RXD_MD );
1851+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_TXD_MD );
1852+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_UART_CTS_MD );
1853+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_UART_RTS_MD );
1854+
1855+ funcs->configure = htcuniversal_bt_configure;
1856+
1857+ /* Make sure the LED is off */
1858+// htcuniversal_clear_led(2);
1859+
1860+ return 0;
1861+}
1862+
1863+static int
1864+htcuniversal_bt_remove( struct platform_device *dev )
1865+{
1866+ struct htcuniversal_bt_funcs *funcs = dev->dev.platform_data;
1867+
1868+ funcs->configure = NULL;
1869+
1870+ /* Make sure the LED is off */
1871+// htcuniversal_clear_led(2);
1872+
1873+ return 0;
1874+}
1875+
1876+static struct platform_driver bt_driver = {
1877+ .driver = {
1878+ .name = "htcuniversal_bt",
1879+ },
1880+ .probe = htcuniversal_bt_probe,
1881+ .remove = htcuniversal_bt_remove,
1882+};
1883+
1884+module_param(use_led, uint, 0);
1885+
1886+static int __init
1887+htcuniversal_bt_init( void )
1888+{
1889+ printk(KERN_NOTICE "htcuniversal Bluetooth Driver\n");
1890+ return platform_driver_register( &bt_driver );
1891+}
1892+
1893+static void __exit
1894+htcuniversal_bt_exit( void )
1895+{
1896+ platform_driver_unregister( &bt_driver );
1897+}
1898+
1899+module_init( htcuniversal_bt_init );
1900+module_exit( htcuniversal_bt_exit );
1901+
1902+MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
1903+MODULE_DESCRIPTION("HTC Universal Bluetooth Support Driver");
1904+MODULE_LICENSE("GPL");
1905+
1906+/* vim600: set noexpandtab sw=8 ts=8 :*/
1907+
1908Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h
1909===================================================================
1910--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1911+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h 2007-09-11 12:53:37.000000000 +0200
1912@@ -0,0 +1,17 @@
1913+/*
1914+ * Bluetooth support file for calling bluetooth configuration functions
1915+ *
1916+ * Copyright (c) 2005 SDG Systems, LLC
1917+ *
1918+ * 2005-06 Todd Blumer Initial Revision
1919+ */
1920+
1921+#ifndef _HTCUNIVERSAL_BT_H
1922+#define _HTCUNIVERSAL_BT_H
1923+
1924+struct htcuniversal_bt_funcs {
1925+ void (*configure) ( int state );
1926+};
1927+
1928+
1929+#endif
1930Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c
1931===================================================================
1932--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1933+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c 2007-09-11 12:53:37.000000000 +0200
1934@@ -0,0 +1,87 @@
1935+/*
1936+ * Buttons driver for HTC Universal
1937+ *
1938+ * This file is subject to the terms and conditions of the GNU General Public
1939+ * License.
1940+ *
1941+ * Copyright (C) 2005 Pawel Kolodziejski
1942+ * Copyright (C) 2003 Joshua Wise
1943+ *
1944+ */
1945+
1946+#include <linux/input.h>
1947+#include <linux/input_pda.h>
1948+#include <linux/module.h>
1949+#include <linux/init.h>
1950+#include <linux/interrupt.h>
1951+#include <linux/irq.h>
1952+#include <linux/platform_device.h>
1953+#include <linux/gpio_keys.h>
1954+#include <linux/soc/asic3_base.h>
1955+#include <asm/mach-types.h>
1956+#include <asm/hardware/asic3_keys.h>
1957+#include <asm/arch/htcuniversal-gpio.h>
1958+#include <asm/arch/htcuniversal-asic.h>
1959+
1960+static struct asic3_keys_button asic3_buttons[] = {
1961+//{KEY_SCREEN, ASIC3_GPIOA_IRQ_BASE+GPIOA_COVER_ROTATE_N, 1, "screen_cover", EV_SW},
1962+//{KEY_SWITCHVIDEOMODE, ASIC3_GPIOB_IRQ_BASE+GPIOB_CLAMSHELL_N, 1, "clamshell_rotate", EV_SW},
1963+//{KEY_KBDILLUMTOGGLE, ASIC3_GPIOB_IRQ_BASE+GPIOB_NIGHT_SENSOR, 1, "night_sensor", EV_SW},
1964+{SW_LID, ASIC3_GPIOA_IRQ_BASE+GPIOA_COVER_ROTATE_N, 1, "screen_cover", EV_SW},
1965+{SW_TABLET_MODE, ASIC3_GPIOB_IRQ_BASE+GPIOB_CLAMSHELL_N, 1, "clamshell_rotate", EV_SW},
1966+//{SW_NIGHT_SENSOR, ASIC3_GPIOB_IRQ_BASE+GPIOB_NIGHT_SENSOR, 1, "night_sensor", EV_SW},
1967+{KEY_F10, ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_BACKLIGHT_N, 1, "backlight_button"},
1968+{KEY_RECORD, ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_RECORD_N, 1, "record_button"},
1969+{KEY_CAMERA, ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_CAMERA_N, 1, "camera_button"},
1970+{KEY_VOLUMEDOWN, ASIC3_GPIOA_IRQ_BASE+GPIOA_VOL_UP_N, 1, "volume_slider_down"},
1971+{KEY_VOLUMEUP, ASIC3_GPIOA_IRQ_BASE+GPIOA_VOL_DOWN_N, 1, "volume_slider_up"},
1972+{KEY_KPENTER, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_OK_N, 1, "select"},
1973+{KEY_RIGHT, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_RIGHT_N, 1, "right"},
1974+{KEY_LEFT, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_LEFT_N, 1, "left"},
1975+{KEY_DOWN, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_DOWN_N, 1, "down"},
1976+{KEY_UP, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_UP_N, 1, "up"},
1977+};
1978+
1979+static struct asic3_keys_platform_data asic3_keys_data = {
1980+ .buttons = asic3_buttons,
1981+ .nbuttons = ARRAY_SIZE(asic3_buttons),
1982+ .asic3_dev = &htcuniversal_asic3.dev,
1983+};
1984+
1985+static struct platform_device htcuniversal_keys_asic3 = {
1986+ .name = "asic3-keys",
1987+ .dev = { .platform_data = &asic3_keys_data, }
1988+};
1989+
1990+static int __init htcuniversal_buttons_probe(struct platform_device *dev)
1991+{
1992+ platform_device_register(&htcuniversal_keys_asic3);
1993+ return 0;
1994+}
1995+
1996+static struct platform_driver htcuniversal_buttons_driver = {
1997+ .driver = {
1998+ .name = "htcuniversal_buttons",
1999+ },
2000+ .probe = htcuniversal_buttons_probe,
2001+};
2002+
2003+static int __init htcuniversal_buttons_init(void)
2004+{
2005+ if (!machine_is_htcuniversal())
2006+ return -ENODEV;
2007+
2008+ return platform_driver_register(&htcuniversal_buttons_driver);
2009+}
2010+
2011+static void __exit htcuniversal_buttons_exit(void)
2012+{
2013+ platform_driver_unregister(&htcuniversal_buttons_driver);
2014+}
2015+
2016+module_init(htcuniversal_buttons_init);
2017+module_exit(htcuniversal_buttons_exit);
2018+
2019+MODULE_AUTHOR ("Joshua Wise, Pawel Kolodziejski, Paul Sokolosvky");
2020+MODULE_DESCRIPTION ("Buttons support for HTC Universal");
2021+MODULE_LICENSE ("GPL");
2022Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c
2023===================================================================
2024--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2025+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c 2007-09-11 12:53:37.000000000 +0200
2026@@ -0,0 +1,226 @@
2027+/* Core Hardware driver for Hx4700 (Serial, ASIC3, EGPIOs)
2028+ *
2029+ * Copyright (c) 2005 SDG Systems, LLC
2030+ *
2031+ * 2005-03-29 Todd Blumer Converted basic structure to support hx4700
2032+ * 2005-04-30 Todd Blumer Add IRDA code from H2200
2033+ */
2034+
2035+#include <linux/module.h>
2036+#include <linux/version.h>
2037+#include <linux/interrupt.h>
2038+#include <linux/platform_device.h>
2039+#include <linux/delay.h>
2040+#include <linux/pm.h>
2041+#include <linux/irq.h>
2042+
2043+#include <asm/io.h>
2044+#include <asm/mach/irq.h>
2045+#include <asm/arch/pxa-regs.h>
2046+#include <asm/arch/pxa-pm_ll.h>
2047+#include <asm/arch/htcuniversal-gpio.h>
2048+#include <asm/arch/htcuniversal-asic.h>
2049+
2050+#include <linux/soc/asic3_base.h>
2051+#include <asm/hardware/ipaq-asic3.h>
2052+
2053+volatile u_int16_t *egpios;
2054+u_int16_t egpio_reg;
2055+
2056+static int htc_bootloader = 0; /* Is the stock HTC bootloader installed? */
2057+
2058+/*
2059+ * may make sense to put egpios elsewhere, but they're here now
2060+ * since they share some of the same address space with the TI WLAN
2061+ *
2062+ * EGPIO register is write-only
2063+ */
2064+
2065+void
2066+htcuniversal_egpio_enable( u_int16_t bits )
2067+{
2068+ unsigned long flags;
2069+
2070+ local_irq_save(flags);
2071+
2072+ egpio_reg |= bits;
2073+ *egpios = egpio_reg;
2074+
2075+ local_irq_restore(flags);
2076+}
2077+EXPORT_SYMBOL_GPL(htcuniversal_egpio_enable);
2078+
2079+void
2080+htcuniversal_egpio_disable( u_int16_t bits )
2081+{
2082+ unsigned long flags;
2083+
2084+ local_irq_save(flags);
2085+
2086+ egpio_reg &= ~bits;
2087+ *egpios = egpio_reg;
2088+
2089+ local_irq_restore(flags);
2090+}
2091+EXPORT_SYMBOL_GPL(htcuniversal_egpio_disable);
2092+
2093+#ifdef CONFIG_PM
2094+
2095+//void htcuniversal_ll_pm_init(void);
2096+
2097+static int htcuniversal_suspend(struct platform_device *dev, pm_message_t state)
2098+{
2099+ /* Turn off external clocks here, because htcuniversal_power and asic3_mmc
2100+ * scared to do so to not hurt each other. (-5 mA) */
2101+
2102+
2103+ /* 0x20c2 is HTC clock value
2104+ * CLOCK_CDEX_SOURCE 2
2105+ * CLOCK_CDEX_SPI 0
2106+ * CLOCK_CDEX_OWM 0
2107+ *
2108+ * CLOCK_CDEX_PWM0 0
2109+ * CLOCK_CDEX_PWM1 0
2110+ * CLOCK_CDEX_LED0 1
2111+ * CLOCK_CDEX_LED1 1
2112+ *
2113+ * CLOCK_CDEX_LED2 0
2114+ * CLOCK_CDEX_SD_HOST 0
2115+ * CLOCK_CDEX_SD_BUS 0
2116+ * CLOCK_CDEX_SMBUS 0
2117+ *
2118+ * CLOCK_CDEX_CONTROL_CX 0
2119+ * CLOCK_CDEX_EX0 1
2120+ * CLOCK_CDEX_EX1 0
2121+ * */
2122+ asic3_set_clock_cdex(&htcuniversal_asic3.dev, 0xffff, CLOCK_CDEX_SOURCE1
2123+ |CLOCK_CDEX_LED0
2124+ |CLOCK_CDEX_LED1
2125+ |CLOCK_CDEX_LED2
2126+ |CLOCK_CDEX_EX0
2127+ |CLOCK_CDEX_EX1);
2128+
2129+ *egpios = 0; /* turn off all egpio power */
2130+
2131+ /* Wake up enable. */
2132+ PWER = PWER_GPIO0
2133+ | PWER_GPIO1 /* reset */
2134+ | PWER_GPIO9 /* USB */
2135+ | PWER_GPIO10 /* AC on USB */
2136+ | PWER_GPIO14 /* ASIC3 mux */
2137+ | PWER_RTC;
2138+ /* Wake up on falling edge. */
2139+ PFER = PWER_GPIO0
2140+ | PWER_GPIO1
2141+ | PWER_GPIO9
2142+ | PWER_GPIO10
2143+ | PWER_GPIO14;
2144+
2145+ /* Wake up on rising edge. */
2146+ PRER = PWER_GPIO0
2147+ | PWER_GPIO1
2148+ | PWER_GPIO9
2149+ | PWER_GPIO10;
2150+ /* 3.6864 MHz oscillator power-down enable */
2151+ PCFR = PCFR_OPDE | PCFR_PI2CEN | PCFR_GPROD | PCFR_GPR_EN;
2152+
2153+ PGSR0 = 0x09088004;
2154+ PGSR1 = 0x00020002;
2155+ PGSR2 = 0x8001c000;
2156+ PGSR3 = 0x00106284;
2157+
2158+ PSLR = 0xcc000000;
2159+
2160+#if 0
2161+ /*
2162+ * If we're using bootldr and not the stock HTC bootloader,
2163+ * we want to wake up periodically to see if the charge is full while
2164+ * it is suspended. We do this with the OS timer 4 in the pxa270.
2165+ */
2166+ if (!htc_bootloader) {
2167+ OMCR4 = 0x4b; /* Periodic, self-resetting, 1-second timer */
2168+ OSMR4 = 5; /* Wake up bootldr after x seconds so it can
2169+ figure out what to do with the LEDs. */
2170+ OIER |= 0x10; /* Enable interrupt source for Timer 4 */
2171+ OSCR4 = 0; /* This starts the timer */
2172+ }
2173+#endif
2174+
2175+ asic3_set_extcf_select(&htcuniversal_asic3.dev, ASIC3_EXTCF_OWM_EN, 0);
2176+
2177+ return 0;
2178+}
2179+
2180+static int htcuniversal_resume(struct platform_device *dev)
2181+{
2182+ htcuniversal_egpio_enable(0);
2183+
2184+ return 0;
2185+}
2186+#else
2187+# define htcuniversal_suspend NULL
2188+# define htcuniversal_resume NULL
2189+#endif
2190+
2191+static int
2192+htcuniversal_core_probe( struct platform_device *dev )
2193+{
2194+
2195+ printk( KERN_NOTICE "HTC Universal Core Hardware Driver\n" );
2196+
2197+ egpios = (volatile u_int16_t *)ioremap_nocache(HTCUNIVERSAL_EGPIO_BASE, sizeof *egpios );
2198+ if (!egpios)
2199+ return -ENODEV;
2200+ else
2201+ printk( KERN_NOTICE "HTC Universal Core: egpio at phy=0x%8.8x is at virt=0x%p\n",
2202+ HTCUNIVERSAL_EGPIO_BASE, egpios );
2203+
2204+ printk("Using stock HTC first stage bootloader\n");
2205+ htc_bootloader = 1;
2206+
2207+// htcuniversal_ll_pm_init();
2208+
2209+ return 0;
2210+}
2211+
2212+static int
2213+htcuniversal_core_remove( struct platform_device *dev )
2214+{
2215+
2216+ if (egpios != NULL)
2217+ iounmap( (void *)egpios );
2218+
2219+ return 0;
2220+}
2221+
2222+static struct platform_driver htcuniversal_core_driver = {
2223+ .driver = {
2224+ .name = "htcuniversal_core",
2225+ },
2226+ .probe = htcuniversal_core_probe,
2227+ .remove = htcuniversal_core_remove,
2228+ .suspend = htcuniversal_suspend,
2229+ .resume = htcuniversal_resume,
2230+};
2231+
2232+static int __init
2233+htcuniversal_core_init( void )
2234+{
2235+ return platform_driver_register( &htcuniversal_core_driver );
2236+}
2237+
2238+
2239+static void __exit
2240+htcuniversal_core_exit( void )
2241+{
2242+ platform_driver_unregister( &htcuniversal_core_driver );
2243+}
2244+
2245+module_init( htcuniversal_core_init );
2246+module_exit( htcuniversal_core_exit );
2247+
2248+MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
2249+MODULE_DESCRIPTION("HTC Universal Core Hardware Driver");
2250+MODULE_LICENSE("GPL");
2251+
2252+/* vim600: set noexpandtab sw=8 ts=8 :*/
2253Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c
2254===================================================================
2255--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2256+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c 2007-09-11 12:53:37.000000000 +0200
2257@@ -0,0 +1,212 @@
2258+/*
2259+ * Use consistent with the GNU GPL is permitted,
2260+ * provided that this copyright notice is
2261+ * preserved in its entirety in all copies and derived works.
2262+ *
2263+ * History:
2264+ *
2265+ * 2004-03-01 Eddi De Pieri Adapted for htcuniversal using h3900_lcd.c
2266+ * 2004 Shawn Anderson Lcd hacking on htcuniversal
2267+ * see h3900_lcd.c for more history.
2268+ *
2269+ */
2270+
2271+#include <linux/types.h>
2272+#include <asm/arch/hardware.h> /* for pxa-regs.h (__REG) */
2273+#include <linux/platform_device.h>
2274+#include <asm/arch/pxa-regs.h> /* LCCR[0,1,2,3]* */
2275+#include <asm/arch/bitfield.h> /* for pxa-regs.h (Fld, etc) */
2276+#include <asm/arch/pxafb.h> /* pxafb_mach_info, set_pxa_fb_info */
2277+#include <asm/mach-types.h> /* machine_is_htcuniversal */
2278+#include <linux/lcd.h> /* lcd_device */
2279+#include <linux/err.h>
2280+#include <linux/delay.h>
2281+
2282+#include <asm/arch/htcuniversal-gpio.h>
2283+#include <asm/arch/htcuniversal-asic.h>
2284+#include <asm/hardware/ipaq-asic3.h>
2285+#include <linux/soc/asic3_base.h>
2286+
2287+static int saved_lcdpower=-1;
2288+
2289+static int powerup_lcd(void)
2290+{
2291+ printk( KERN_INFO "htcuniversal powerup_lcd: called\n");
2292+
2293+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0);
2294+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0);
2295+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0);
2296+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0);
2297+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0);
2298+#if 1
2299+ LCCR4|=LCCR4_PCDDIV;
2300+#endif
2301+ pxa_set_cken(CKEN_LCD, 0);
2302+
2303+ mdelay(100);
2304+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 1<<GPIOA_LCD_PWR5_ON);
2305+ mdelay(5);
2306+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 1<<GPIOB_LCD_PWR3_ON);
2307+ mdelay(2);
2308+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 1<<GPIOC_LCD_PWR1_ON);
2309+ mdelay(2);
2310+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 1<<GPIOC_LCD_PWR2_ON);
2311+ mdelay(20);
2312+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 1<<GPIOD_LCD_PWR4_ON);
2313+ mdelay(1);
2314+ pxa_set_cken(CKEN_LCD, 1);
2315+
2316+ SET_HTCUNIVERSAL_GPIO(LCD1,1);
2317+ SET_HTCUNIVERSAL_GPIO(LCD2,1);
2318+ return 0;
2319+}
2320+
2321+static int powerdown_lcd(void)
2322+{
2323+ printk( KERN_INFO "htcuniversal powerdown_lcd: called\n");
2324+
2325+#if 1
2326+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0);
2327+ mdelay(100);
2328+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0);
2329+ mdelay(10);
2330+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0);
2331+ mdelay(1);
2332+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0);
2333+ mdelay(1);
2334+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0);
2335+ pxa_set_cken(CKEN_LCD, 0);
2336+
2337+ SET_HTCUNIVERSAL_GPIO(LCD1,0);
2338+ SET_HTCUNIVERSAL_GPIO(LCD2,0);
2339+#else
2340+ pxa_set_cken(CKEN_LCD, 0);
2341+
2342+ SET_HTCUNIVERSAL_GPIO(LCD1,0);
2343+ SET_HTCUNIVERSAL_GPIO(LCD2,0);
2344+
2345+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0);
2346+ mdelay(100);
2347+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0);
2348+ mdelay(10);
2349+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0);
2350+ mdelay(1);
2351+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0);
2352+ mdelay(1);
2353+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0);
2354+#endif
2355+ return 0;
2356+}
2357+
2358+static int htcuniversal_lcd_set_power(struct lcd_device *lm, int power)
2359+{
2360+ /* Enable or disable power to the LCD (0: on; 4: off) */
2361+
2362+ if ( power < 1 ) {
2363+
2364+ powerup_lcd();
2365+
2366+ } else {
2367+
2368+ powerdown_lcd();
2369+
2370+ }
2371+
2372+ saved_lcdpower=power;
2373+
2374+ return 0;
2375+}
2376+
2377+static int htcuniversal_lcd_get_power(struct lcd_device *lm)
2378+{
2379+ /* Get the LCD panel power status (0: full on, 1..3: controller
2380+ * power on, flat panel power off, 4: full off) */
2381+
2382+ if (saved_lcdpower == -1)
2383+ {
2384+ htcuniversal_lcd_set_power(lm, 4);
2385+ saved_lcdpower=4;
2386+ }
2387+
2388+ return saved_lcdpower;
2389+}
2390+
2391+static struct lcd_ops htcuniversal_lcd_properties =
2392+{
2393+ .get_power = htcuniversal_lcd_get_power,
2394+ .set_power = htcuniversal_lcd_set_power,
2395+};
2396+
2397+static struct lcd_device *htcuniversal_lcd_dev;
2398+
2399+static int htcuniversal_lcd_probe(struct platform_device * dev)
2400+{
2401+ htcuniversal_lcd_dev = lcd_device_register("pxa2xx-fb", &dev->dev, NULL,
2402+ &htcuniversal_lcd_properties);
2403+ if (IS_ERR(htcuniversal_lcd_dev)) {
2404+ printk("htcuniversal_lcd_probe: error registering devices\n");
2405+ return -1;
2406+ }
2407+
2408+ return 0;
2409+}
2410+
2411+static int htcuniversal_lcd_remove(struct platform_device * dev)
2412+{
2413+ htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 4);
2414+ lcd_device_unregister(htcuniversal_lcd_dev);
2415+
2416+ return 0;
2417+}
2418+
2419+static int htcuniversal_lcd_suspend(struct platform_device * dev, pm_message_t state)
2420+{
2421+// printk("htcuniversal_lcd_suspend: called.\n");
2422+ htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 4);
2423+ return 0;
2424+}
2425+
2426+static int htcuniversal_lcd_resume(struct platform_device * dev)
2427+{
2428+// printk("htcuniversal_lcd_resume: called.\n");
2429+
2430+ /* */
2431+#if 1
2432+ LCCR4|=LCCR4_PCDDIV;
2433+#endif
2434+
2435+ htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 0);
2436+ return 0;
2437+}
2438+
2439+static struct platform_driver htcuniversal_lcd_driver = {
2440+ .driver = {
2441+ .name = "htcuniversal_lcd",
2442+ },
2443+ .probe = htcuniversal_lcd_probe,
2444+ .remove = htcuniversal_lcd_remove,
2445+ .suspend = htcuniversal_lcd_suspend,
2446+ .resume = htcuniversal_lcd_resume,
2447+};
2448+
2449+static int htcuniversal_lcd_init(void)
2450+{
2451+ if (!machine_is_htcuniversal())
2452+ return -ENODEV;
2453+
2454+ return platform_driver_register(&htcuniversal_lcd_driver);
2455+}
2456+
2457+static void htcuniversal_lcd_exit(void)
2458+{
2459+ lcd_device_unregister(htcuniversal_lcd_dev);
2460+ platform_driver_unregister(&htcuniversal_lcd_driver);
2461+}
2462+
2463+module_init(htcuniversal_lcd_init);
2464+module_exit(htcuniversal_lcd_exit);
2465+
2466+MODULE_AUTHOR("xanadux.org");
2467+MODULE_DESCRIPTION("Framebuffer driver for HTC Universal");
2468+MODULE_LICENSE("GPL");
2469+
2470Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c
2471===================================================================
2472--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2473+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c 2007-09-11 12:53:37.000000000 +0200
2474@@ -0,0 +1,167 @@
2475+
2476+/* Phone interface driver for Qualcomm MSM6250 on HTC Universal
2477+ *
2478+ * Copyright (c) 2005 SDG Systems, LLC
2479+ *
2480+ * 2005-04-21 Todd Blumer Created.
2481+ */
2482+
2483+#include <linux/module.h>
2484+#include <linux/kernel.h>
2485+#include <linux/delay.h>
2486+#include <linux/platform_device.h>
2487+#include <linux/soc/asic3_base.h>
2488+
2489+#include <asm/hardware.h>
2490+#include <asm/arch/serial.h>
2491+#include <asm/hardware/ipaq-asic3.h>
2492+#include <asm/arch/htcuniversal-gpio.h>
2493+#include <asm/arch/htcuniversal-asic.h>
2494+
2495+#include "htcuniversal_phone.h"
2496+
2497+static void phone_reset(void)
2498+{
2499+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_RESET2, 0);
2500+
2501+ SET_HTCUNIVERSAL_GPIO(PHONE_RESET,0);
2502+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0);
2503+ mdelay(1);
2504+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 1<<GPIOD_BB_RESET1);
2505+ mdelay(20);
2506+ SET_HTCUNIVERSAL_GPIO(PHONE_RESET,1);
2507+ mdelay(200);
2508+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0);
2509+}
2510+
2511+static void phone_off(void)
2512+{
2513+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 1<<GPIOD_BB_RESET1);
2514+ mdelay(2000);
2515+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0);
2516+
2517+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_RESET2, 1<<GPIOB_BB_RESET2);
2518+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0);
2519+}
2520+
2521+static void
2522+htcuniversal_phone_configure( int state )
2523+{
2524+ int tries;
2525+ unsigned short statusb;
2526+
2527+ printk( KERN_NOTICE "htcuniversal configure phone: %d\n", state );
2528+ switch (state) {
2529+
2530+ case PXA_UART_CFG_PRE_STARTUP:
2531+ break;
2532+
2533+ case PXA_UART_CFG_POST_STARTUP:
2534+ /* pre-serial-up hardware configuration */
2535+
2536+ SET_HTCUNIVERSAL_GPIO(PHONE_START,0); /* "bootloader" */
2537+ SET_HTCUNIVERSAL_GPIO(PHONE_UNKNOWN,0); /* not used */
2538+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0); /* PHONE_OFF */
2539+
2540+ phone_reset();
2541+
2542+ SET_HTCUNIVERSAL_GPIO(PHONE_START,1); /* phone */
2543+
2544+ phone_reset();
2545+
2546+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_READY, 0);
2547+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_UNKNOWN3, 0);
2548+
2549+ /*
2550+ */
2551+ tries = 0;
2552+ do {
2553+ mdelay(10);
2554+ statusb = asic3_get_gpio_status_b( &htcuniversal_asic3.dev );
2555+ } while ( (statusb & (1<<GPIOB_UMTS_DCD)) == 0 && tries++ < 200);
2556+
2557+ printk("UMTS_DCD tries=%d of 200\n",tries);
2558+
2559+ tries = 0;
2560+ do {
2561+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,1);
2562+ mdelay(10);
2563+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0);
2564+ mdelay(20);
2565+ statusb = asic3_get_gpio_status_b( &htcuniversal_asic3.dev );
2566+ } while ( (statusb & (1<<GPIOB_BB_READY)) == 0 && tries++ < 200);
2567+
2568+ printk("BB_READY tries=%d of 200\n",tries);
2569+
2570+ break;
2571+
2572+ case PXA_UART_CFG_PRE_SHUTDOWN:
2573+
2574+ phone_off();
2575+
2576+ break;
2577+
2578+ default:
2579+ break;
2580+ }
2581+}
2582+
2583+
2584+static int
2585+htcuniversal_phone_probe( struct platform_device *dev )
2586+{
2587+ struct htcuniversal_phone_funcs *funcs = dev->dev.platform_data;
2588+
2589+ /* configure phone UART */
2590+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_RXD_MD );
2591+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_TXD_MD );
2592+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS_MD );
2593+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS_MD );
2594+
2595+ funcs->configure = htcuniversal_phone_configure;
2596+
2597+ return 0;
2598+}
2599+
2600+static int
2601+htcuniversal_phone_remove( struct platform_device *dev )
2602+{
2603+ struct htcuniversal_phone_funcs *funcs = dev->dev.platform_data;
2604+
2605+ funcs->configure = NULL;
2606+
2607+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_READY, 1<<GPIOB_BB_READY);
2608+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_UNKNOWN3, 1<<GPIOB_BB_UNKNOWN3);
2609+
2610+ return 0;
2611+}
2612+
2613+static struct platform_driver phone_driver = {
2614+ .driver = {
2615+ .name = "htcuniversal_phone",
2616+ },
2617+ .probe = htcuniversal_phone_probe,
2618+ .remove = htcuniversal_phone_remove,
2619+};
2620+
2621+static int __init
2622+htcuniversal_phone_init( void )
2623+{
2624+ printk(KERN_NOTICE "htcuniversal Phone Driver\n");
2625+ return platform_driver_register( &phone_driver );
2626+}
2627+
2628+static void __exit
2629+htcuniversal_phone_exit( void )
2630+{
2631+ platform_driver_unregister( &phone_driver );
2632+}
2633+
2634+module_init( htcuniversal_phone_init );
2635+module_exit( htcuniversal_phone_exit );
2636+
2637+MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
2638+MODULE_DESCRIPTION("HTC Universal Phone Support Driver");
2639+MODULE_LICENSE("GPL");
2640+
2641+/* vim600: set noexpandtab sw=8 ts=8 :*/
2642Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h
2643===================================================================
2644--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2645+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h 2007-09-11 12:53:37.000000000 +0200
2646@@ -0,0 +1,16 @@
2647+/*
2648+ * Bluetooth support file for calling bluetooth configuration functions
2649+ *
2650+ * Copyright (c) 2005 SDG Systems, LLC
2651+ *
2652+ * 2005-06 Todd Blumer Initial Revision
2653+ */
2654+
2655+#ifndef _HTCUNIVERSAL_PHONE_H
2656+#define _HTCUNIVERSAL_PHONE_H
2657+
2658+struct htcuniversal_phone_funcs {
2659+ void (*configure) ( int state );
2660+};
2661+
2662+#endif
2663Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c
2664===================================================================
2665--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2666+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c 2007-09-11 12:53:37.000000000 +0200
2667@@ -0,0 +1,69 @@
2668+/*
2669+ * MyPal 716 power management support for the original HTC IPL in DoC G3
2670+ *
2671+ * Use consistent with the GNU GPL is permitted, provided that this
2672+ * copyright notice is preserved in its entirety in all copies and
2673+ * derived works.
2674+ *
2675+ * Copyright (C) 2005 Pawel Kolodziejski
2676+ *
2677+ */
2678+
2679+#include <linux/kernel.h>
2680+#include <linux/module.h>
2681+#include <linux/device.h>
2682+#include <linux/pm.h>
2683+
2684+#include <asm/mach-types.h>
2685+#include <asm/hardware.h>
2686+#include <asm/arch/pxa-regs.h>
2687+#include <asm/arch/pxa-pm_ll.h>
2688+
2689+#ifdef CONFIG_PM
2690+
2691+static u32 *addr_a0040000;
2692+static u32 *addr_a0040004;
2693+static u32 *addr_a0040008;
2694+static u32 *addr_a004000c;
2695+
2696+static u32 save_a0040000;
2697+static u32 save_a0040004;
2698+static u32 save_a0040008;
2699+static u32 save_a004000c;
2700+
2701+static void htcuniversal_pxa_ll_pm_suspend(unsigned long resume_addr)
2702+{
2703+ save_a0040000 = *addr_a0040000;
2704+ save_a0040004 = *addr_a0040004;
2705+ save_a0040008 = *addr_a0040008;
2706+ save_a004000c = *addr_a004000c;
2707+
2708+ /* jump to PSPR */
2709+ *addr_a0040000 = 0xe3a00101; // mov r0, #0x40000000
2710+ *addr_a0040004 = 0xe380060f; // orr r0, r0, #0x0f000000
2711+ *addr_a0040008 = 0xe3800008; // orr r0, r0, #8
2712+ *addr_a004000c = 0xe590f000; // ldr pc, [r0]
2713+}
2714+
2715+static void htcuniversal_pxa_ll_pm_resume(void)
2716+{
2717+ *addr_a0040000 = save_a0040000;
2718+ *addr_a0040004 = save_a0040004;
2719+ *addr_a0040008 = save_a0040008;
2720+ *addr_a004000c = save_a004000c;
2721+}
2722+
2723+static struct pxa_ll_pm_ops htcuniversal_ll_pm_ops = {
2724+ .suspend = htcuniversal_pxa_ll_pm_suspend,
2725+ .resume = htcuniversal_pxa_ll_pm_resume,
2726+};
2727+
2728+void htcuniversal_ll_pm_init(void) {
2729+ addr_a0040000 = phys_to_virt(0xa0040000);
2730+ addr_a0040004 = phys_to_virt(0xa0040004);
2731+ addr_a0040008 = phys_to_virt(0xa0040008);
2732+ addr_a004000c = phys_to_virt(0xa004000c);
2733+
2734+ pxa_pm_set_ll_ops(&htcuniversal_ll_pm_ops);
2735+}
2736+#endif /* CONFIG_PM */
2737Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c
2738===================================================================
2739--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2740+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c 2007-09-11 12:53:37.000000000 +0200
2741@@ -0,0 +1,97 @@
2742+/*
2743+ * pda_power driver for HTC Universal
2744+ *
2745+ * This program is free software; you can redistribute it and/or modify
2746+ * it under the terms of the GNU General Public License as published by
2747+ * the Free Software Foundation; either version 2 of the License, or (at
2748+ * your option) any later version.
2749+ *
2750+ */
2751+
2752+#include <linux/platform_device.h>
2753+#include <linux/module.h>
2754+#include <linux/pda_power.h>
2755+#include <linux/soc/asic3_base.h>
2756+
2757+#include <asm/mach-types.h>
2758+#include <asm/hardware.h>
2759+#include <asm/arch/htcuniversal-gpio.h>
2760+#include <asm/arch/htcuniversal-asic.h>
2761+
2762+static void charge_on(int flags)
2763+{
2764+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_CHARGE_EN, 0);
2765+}
2766+
2767+static int ac_on(void)
2768+{
2769+ return (GET_HTCUNIVERSAL_GPIO(POWER_DET) == 0);
2770+}
2771+
2772+static int usb_on(void)
2773+{
2774+ return (GET_HTCUNIVERSAL_GPIO(USB_DET) == 0);
2775+}
2776+
2777+static char *supplicants[] = {
2778+ "ds2760-battery.0", "backup-battery"
2779+};
2780+
2781+static struct pda_power_pdata power_pdata = {
2782+ .is_ac_online = ac_on,
2783+ .is_usb_online = usb_on,
2784+ .set_charge = charge_on,
2785+ .supplied_to = supplicants,
2786+ .num_supplicants = ARRAY_SIZE(supplicants),
2787+};
2788+
2789+static struct resource power_resources[] = {
2790+ [0] = {
2791+ .name = "ac",
2792+ .start = HTCUNIVERSAL_IRQ(POWER_DET),
2793+ .end = HTCUNIVERSAL_IRQ(POWER_DET),
2794+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
2795+ },
2796+ [1] = {
2797+ .name = "usb",
2798+ .start = HTCUNIVERSAL_IRQ(USB_DET),
2799+ .end = HTCUNIVERSAL_IRQ(USB_DET),
2800+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
2801+ },
2802+};
2803+
2804+static void dev_release(struct device *dev)
2805+{
2806+ return;
2807+}
2808+
2809+static struct platform_device power_dev =
2810+{
2811+ .name = "pda-power",
2812+ .id = -1,
2813+ .resource = power_resources,
2814+ .num_resources = ARRAY_SIZE(power_resources),
2815+ .dev =
2816+ {
2817+ .platform_data = &power_pdata,
2818+ .release = dev_release,
2819+ },
2820+};
2821+
2822+static int htcuniversal_power_init(void)
2823+{
2824+ return platform_device_register(&power_dev);
2825+}
2826+
2827+static void htcuniversal_power_exit(void)
2828+{
2829+ platform_device_unregister(&power_dev);
2830+
2831+ return;
2832+}
2833+
2834+module_init(htcuniversal_power_init);
2835+module_exit(htcuniversal_power_exit);
2836+
2837+MODULE_DESCRIPTION("Power driver for HTC Universal");
2838+MODULE_LICENSE("GPL");
2839Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c
2840===================================================================
2841--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2842+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c 2007-09-11 12:53:37.000000000 +0200
2843@@ -0,0 +1,490 @@
2844+/* Touch screen driver for the TI something-or-other
2845+ *
2846+ * Copyright © 2005 SDG Systems, LLC
2847+ *
2848+ * Based on code that was based on the SAMCOP driver.
2849+ * Copyright © 2003, 2004 Compaq Computer Corporation.
2850+ *
2851+ * Use consistent with the GNU GPL is permitted,
2852+ * provided that this copyright notice is
2853+ * preserved in its entirety in all copies and derived works.
2854+ *
2855+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
2856+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
2857+ * FITNESS FOR ANY PARTICULAR PURPOSE.
2858+ *
2859+ * Author: Keith Packard <keith.packard@hp.com>
2860+ * May 2003
2861+ *
2862+ * Updates:
2863+ *
2864+ * 2004-02-11 Michael Opdenacker Renamed names from samcop to shamcop,
2865+ * Goal:support HAMCOP and SAMCOP.
2866+ * 2004-02-14 Michael Opdenacker Temporary fix for device id handling
2867+ *
2868+ * 2005-02-18 Aric Blumer Converted basic structure to support hx4700
2869+ *
2870+ * 2005-06-07 Aric Blumer Added tssim device handling so we can
2871+ * hook in the fbvncserver.
2872+ */
2873+
2874+#include <linux/module.h>
2875+#include <linux/version.h>
2876+
2877+#include <linux/init.h>
2878+#include <linux/fs.h>
2879+#include <linux/cdev.h>
2880+#include <linux/interrupt.h>
2881+#include <linux/sched.h>
2882+#include <linux/pm.h>
2883+#include <linux/delay.h>
2884+#include <linux/input.h>
2885+#include <linux/platform_device.h>
2886+#include <linux/irq.h>
2887+
2888+#include <asm/arch/hardware.h>
2889+#include <asm/mach/irq.h>
2890+#include <asm/io.h>
2891+
2892+/* remove me */
2893+#include <asm/arch/pxa-regs.h>
2894+#include <asm/arch/htcuniversal-gpio.h>
2895+#include <asm/arch/htcuniversal-asic.h>
2896+#include <asm/mach-types.h>
2897+
2898+#include <asm/hardware/ipaq-asic3.h>
2899+#include <linux/soc/asic3_base.h>
2900+
2901+
2902+#include "tsc2046_ts.h"
2903+
2904+enum touchscreen_state {
2905+ STATE_WAIT_FOR_TOUCH, /* Waiting for a PEN interrupt */
2906+ STATE_SAMPLING /* Actively sampling ADC */
2907+};
2908+
2909+struct touchscreen_data {
2910+ enum touchscreen_state state;
2911+ struct timer_list timer;
2912+ int irq;
2913+ struct input_dev *input;
2914+ /* */
2915+ int port;
2916+ int clock;
2917+ int pwrbit_X;
2918+ int pwrbit_Y;
2919+ int (*pen_down)(void);
2920+};
2921+
2922+static unsigned long poll_sample_time = 10; /* Sample every 10 milliseconds */
2923+
2924+static struct touchscreen_data *ts_data;
2925+
2926+static int irqblock;
2927+
2928+module_param(poll_sample_time, ulong, 0644);
2929+MODULE_PARM_DESC(poll_sample_time, "Poll sample time");
2930+
2931+static inline void
2932+report_touchpanel(struct touchscreen_data *ts, int pressure, int x, int y)
2933+{
2934+ input_report_abs(ts->input, ABS_PRESSURE, pressure);
2935+ input_report_abs(ts->input, ABS_X, x);
2936+ input_report_abs(ts->input, ABS_Y, y);
2937+ input_sync(ts->input);
2938+}
2939+
2940+static void start_read(struct touchscreen_data *touch);
2941+
2942+static irqreturn_t
2943+pen_isr(int irq, void *irq_desc)
2944+{
2945+ struct touchscreen_data *ts = ts_data;
2946+
2947+ if(irq == ts->irq /* && !irqblock */) {
2948+ irqblock = 1;
2949+
2950+ /*
2951+ * Disable the pen interrupt. It's reenabled when the user lifts the
2952+ * pen.
2953+ */
2954+ disable_irq(ts->irq);
2955+
2956+ if (ts->state == STATE_WAIT_FOR_TOUCH) {
2957+ ts->state = STATE_SAMPLING;
2958+ start_read(ts);
2959+ } else {
2960+ /* Shouldn't happen */
2961+ printk(KERN_ERR "Unexpected ts interrupt\n");
2962+ }
2963+
2964+ }
2965+ return IRQ_HANDLED;
2966+}
2967+
2968+static void
2969+ssp_init(int port, int clock)
2970+{
2971+
2972+ pxa_set_cken(clock, 0);
2973+
2974+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_CLK_MD);
2975+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_FRM_MD);
2976+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DO_MD);
2977+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DI_MD);
2978+
2979+ SET_HTCUNIVERSAL_GPIO(SPI_FRM,1);
2980+
2981+ /* *** Set up the SPI Registers *** */
2982+ SSCR0_P(port) =
2983+ SSCR0_EDSS /* Extended Data Size Select */
2984+ | SSCR0_SerClkDiv(7) /* Serial Clock Rate */
2985+ /* Synchronous Serial Enable (Disable for now) */
2986+ | SSCR0_Motorola /* Motorola SPI Interface */
2987+ | SSCR0_DataSize(8) /* Data Size Select (24-bit) */
2988+ ;
2989+ SSCR1_P(port) = 0;
2990+ SSPSP_P(port) = 0;
2991+
2992+ /* Clear the Status */
2993+ SSSR_P(port) = SSSR_P(port) & 0x00fcfffc;
2994+
2995+ /* Now enable it */
2996+ SSCR0_P(port) =
2997+ SSCR0_EDSS /* Extended Data Size Select */
2998+ | SSCR0_SerClkDiv(7) /* Serial Clock Rate */
2999+ | SSCR0_SSE /* Synchronous Serial Enable */
3000+ | SSCR0_Motorola /* Motorola SPI Interface */
3001+ | SSCR0_DataSize(8) /* Data Size Select (24-bit) */
3002+ ;
3003+
3004+ pxa_set_cken(clock, 1);
3005+}
3006+
3007+static void
3008+start_read(struct touchscreen_data *touch)
3009+{
3010+ unsigned long inc = (poll_sample_time * HZ) / 1000;
3011+ int i;
3012+
3013+ /* Write here to the serial port. We request X and Y only for now.
3014+ * Then we have to wait for poll_sample_time before we read out the serial
3015+ * port. Then, when we read it out, we check to see if the pen is still
3016+ * down. If so, then we issue another request here.
3017+ */
3018+#define TS_SAMPLES 7
3019+
3020+ /*
3021+ * We do four samples for each, and throw out the highest and lowest, then
3022+ * average the other two.
3023+ */
3024+
3025+ for(i = 0; i < TS_SAMPLES; i++) {
3026+ while(!(SSSR_P(touch->port) & SSSR_TNF))
3027+ ;
3028+ /* It's not full. Write the command for X */
3029+ SSDR_P(touch->port) = (TSC2046_SAMPLE_X|(touch->pwrbit_X))<<16;
3030+ }
3031+
3032+ for(i = 0; i < TS_SAMPLES; i++) {
3033+ while(!(SSSR_P(touch->port) & SSSR_TNF))
3034+ ;
3035+ /* It's not full. Write the command for Y */
3036+ SSDR_P(touch->port) = (TSC2046_SAMPLE_Y|(touch->pwrbit_Y))<<16;
3037+ }
3038+
3039+ /*
3040+ * Enable the timer. We should get an interrupt, but we want keep a timer
3041+ * to ensure that we can detect missing data
3042+ */
3043+ mod_timer(&touch->timer, jiffies + inc);
3044+}
3045+
3046+static void
3047+ts_timer_callback(unsigned long data)
3048+{
3049+ struct touchscreen_data *ts = (struct touchscreen_data *)data;
3050+ int x, a[TS_SAMPLES], y;
3051+ static int oldx, oldy;
3052+ int ssrval;
3053+
3054+ /*
3055+ * Check here to see if there is anything in the SPI FIFO. If so,
3056+ * return it if there has been a change. If not, then we have a
3057+ * timeout. Generate an erro somehow.
3058+ */
3059+ ssrval = SSSR_P(ts->port);
3060+
3061+ if(ssrval & SSSR_RNE) { /* Look at Rx Not Empty bit */
3062+ int number_of_entries_in_fifo;
3063+
3064+ /* The FIFO is not emtpy. Good! Now make sure there are at least two
3065+ * entries. (Should be two exactly.) */
3066+
3067+ number_of_entries_in_fifo = ((ssrval >> 12) & 0xf) + 1;
3068+
3069+ if(number_of_entries_in_fifo < TS_SAMPLES * 2) {
3070+ /* Not ready yet. Come back later. */
3071+ unsigned long inc = (poll_sample_time * HZ) / 1000;
3072+ mod_timer(&ts->timer, jiffies + inc);
3073+ return;
3074+ }
3075+
3076+ if(number_of_entries_in_fifo == TS_SAMPLES * 2) {
3077+ int i, j;
3078+
3079+ for(i = 0; i < TS_SAMPLES; i++) {
3080+ a[i] = SSDR_P(ts->port);
3081+ }
3082+ /* Sort them (bubble) */
3083+ for(j = TS_SAMPLES - 1; j > 0; j--) {
3084+ for(i = 0; i < j; i++) {
3085+ if(a[i] > a[i + 1]) {
3086+ int tmp;
3087+ tmp = a[i+1];
3088+ a[i+1] = a[i];
3089+ a[i] = tmp;
3090+ }
3091+ }
3092+ }
3093+
3094+ /* Take the average of the middle two */
3095+ /* x = (a[TS_SAMPLES/2 - 1] + a[TS_SAMPLES/2] + a[TS_SAMPLES/2+1] + a[TS_SAMPLES/2+2]) >> 2; */
3096+ x = a[TS_SAMPLES/2];
3097+
3098+ for(i = 0; i < TS_SAMPLES; i++) {
3099+ a[i] = SSDR_P(ts->port);
3100+ }
3101+ /* Sort them (bubble) */
3102+ for(j = TS_SAMPLES - 1; j > 0; j--) {
3103+ for(i = 0; i < j; i++) {
3104+ if(a[i] > a[i + 1]) {
3105+ int tmp;
3106+ tmp = a[i+1];
3107+ a[i+1] = a[i];
3108+ a[i] = tmp;
3109+ }
3110+ }
3111+ }
3112+
3113+
3114+ /* Take the average of the middle two */
3115+ /* y = (a[TS_SAMPLES/2 - 1] + a[TS_SAMPLES/2] + a[TS_SAMPLES/2+1] + a[TS_SAMPLES/2+2]) >> 2; */
3116+ y = a[TS_SAMPLES/2];
3117+ } else {
3118+ /* We have an error! Too many entries. */
3119+ printk(KERN_ERR "TS: Expected %d entries. Got %d\n", TS_SAMPLES*2, number_of_entries_in_fifo);
3120+ /* Try to clear the FIFO */
3121+ while(number_of_entries_in_fifo--) {
3122+ (void)SSDR_P(ts->port);
3123+ }
3124+
3125+ if (ts->pen_down())
3126+ start_read(ts);
3127+
3128+ return;
3129+ }
3130+ } else {
3131+ /* Not ready yet. Come back later. */
3132+ unsigned long inc = (poll_sample_time * HZ) / 1000;
3133+ mod_timer(&ts->timer, jiffies + inc);
3134+ return;
3135+ }
3136+
3137+ /*
3138+ * Now we check to see if the pen is still down. If it is, then call
3139+ * start_read().
3140+ */
3141+ if (ts->pen_down())
3142+ {
3143+ /* Still down */
3144+ if(oldx != x || oldy != y) {
3145+ oldx = x;
3146+ oldy = y;
3147+ report_touchpanel(ts, 1, x, y);
3148+ }
3149+ start_read(ts);
3150+ } else {
3151+ /* Up */
3152+ report_touchpanel(ts, 0, 0, 0);
3153+ irqblock = 0;
3154+ ts->state = STATE_WAIT_FOR_TOUCH;
3155+ /* Re-enable pen down interrupt */
3156+ enable_irq(ts->irq);
3157+ }
3158+}
3159+
3160+static int pen_down(void)
3161+{
3162+ return ( asic3_get_gpio_status_a( &htcuniversal_asic3.dev ) & (1<<GPIOA_TOUCHSCREEN_N)) == 0 ;
3163+}
3164+
3165+static int
3166+ts_probe (struct platform_device *dev)
3167+{
3168+ int retval;
3169+ struct touchscreen_data *ts;
3170+ struct tsc2046_mach_info *mach = dev->dev.platform_data;
3171+
3172+ printk("htcuniversal: ts_probe\n");
3173+
3174+ ts = ts_data = kmalloc (sizeof (*ts), GFP_KERNEL);
3175+ if (ts == NULL) {
3176+ printk( KERN_NOTICE "htcuniversal_ts: unable to allocate memory\n" );
3177+ return -ENOMEM;
3178+ }
3179+ memset (ts, 0, sizeof (*ts));
3180+
3181+ ts->input = input_allocate_device();
3182+ if (ts->input == NULL) {
3183+ printk( KERN_NOTICE "htcuniversal_ts: unable to allocation touchscreen input\n" );
3184+ kfree(ts);
3185+ return -ENOMEM;
3186+ }
3187+ ts->input->evbit[0] = BIT(EV_ABS);
3188+ ts->input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
3189+ ts->input->absmin[ABS_X] = 0;
3190+ ts->input->absmax[ABS_X] = 32767;
3191+ ts->input->absmin[ABS_Y] = 0;
3192+ ts->input->absmax[ABS_Y] = 32767;
3193+ ts->input->absmin[ABS_PRESSURE] = 0;
3194+ ts->input->absmax[ABS_PRESSURE] = 1;
3195+
3196+ ts->input->name = "htcuniversal_ts";
3197+ ts->input->phys = "touchscreen/htcuniversal_ts";
3198+ ts->input->private = ts;
3199+
3200+ input_register_device(ts->input);
3201+
3202+ ts->timer.function = ts_timer_callback;
3203+ ts->timer.data = (unsigned long)ts;
3204+ ts->state = STATE_WAIT_FOR_TOUCH;
3205+ init_timer (&ts->timer);
3206+
3207+ platform_set_drvdata(dev, ts);
3208+
3209+ ts->port=-1;
3210+
3211+ if (mach) {
3212+ ts->port = mach->port;
3213+ ts->clock = mach->clock;
3214+ ts->pwrbit_X = mach->pwrbit_X;
3215+ ts->pwrbit_Y = mach->pwrbit_Y;
3216+
3217+ /* static irq */
3218+ if (mach->irq)
3219+ ts->irq = mach->irq;
3220+
3221+ if (mach->pen_down)
3222+ ts->pen_down=mach->pen_down;
3223+ }
3224+
3225+ if (ts->port == -1)
3226+ {
3227+ printk("tsc2046: your device is not supported by this driver\n");
3228+ return -ENODEV;
3229+ }
3230+
3231+ /* *** Initialize the SSP interface *** */
3232+ ssp_init(ts->port, ts->clock);
3233+
3234+ while(!(SSSR_P(ts->port) & SSSR_TNF))
3235+ ;
3236+ SSDR_P(ts->port) = (TSC2046_SAMPLE_X|(ts->pwrbit_X))<<16;
3237+
3238+ for(retval = 0; retval < 100; retval++) {
3239+ if(SSSR_P(ts->port) & SSSR_RNE) {
3240+ while(SSSR_P(ts->port) & SSSR_RNE) {
3241+ (void)SSDR_P(ts->port);
3242+ }
3243+ break;
3244+ }
3245+ mdelay(1);
3246+ }
3247+
3248+ if (machine_is_htcuniversal() )
3249+ {
3250+ ts->irq = asic3_irq_base( &htcuniversal_asic3.dev ) + ASIC3_GPIOA_IRQ_BASE + GPIOA_TOUCHSCREEN_N;
3251+ ts->pen_down=pen_down;
3252+ }
3253+
3254+ retval = request_irq(ts->irq, pen_isr, IRQF_DISABLED, "tsc2046_ts", ts);
3255+ if(retval) {
3256+ printk("Unable to get interrupt\n");
3257+ input_unregister_device (ts->input);
3258+ return -ENODEV;
3259+ }
3260+ set_irq_type(ts->irq, IRQ_TYPE_EDGE_FALLING);
3261+
3262+ return 0;
3263+}
3264+
3265+static int
3266+ts_remove (struct platform_device *dev)
3267+{
3268+ struct touchscreen_data *ts = platform_get_drvdata(dev);
3269+
3270+ input_unregister_device (ts->input);
3271+ del_timer_sync (&ts->timer);
3272+ free_irq (ts->irq, ts);
3273+ pxa_set_cken(ts->clock, 0);
3274+
3275+ kfree(ts);
3276+ return 0;
3277+}
3278+
3279+static int
3280+ts_suspend (struct platform_device *dev, pm_message_t state)
3281+{
3282+ struct touchscreen_data *ts = platform_get_drvdata(dev);
3283+
3284+ disable_irq(ts->irq);
3285+
3286+ printk("htcuniversal_ts2_suspend: called.\n");
3287+ return 0;
3288+}
3289+
3290+static int
3291+ts_resume (struct platform_device *dev)
3292+{
3293+ struct touchscreen_data *ts = platform_get_drvdata(dev);
3294+
3295+ ts->state = STATE_WAIT_FOR_TOUCH;
3296+ ssp_init(ts->port, ts->clock);
3297+ enable_irq(ts->irq);
3298+
3299+ printk("htcuniversal_ts2_resume: called.\n");
3300+ return 0;
3301+}
3302+
3303+static struct platform_driver ts_driver = {
3304+ .probe = ts_probe,
3305+ .remove = ts_remove,
3306+ .suspend = ts_suspend,
3307+ .resume = ts_resume,
3308+ .driver = {
3309+ .name = "htcuniversal_ts",
3310+ },
3311+};
3312+
3313+
3314+static int
3315+ts_module_init (void)
3316+{
3317+ printk(KERN_NOTICE "HTC Universal Touch Screen Driver\n");
3318+
3319+ return platform_driver_register(&ts_driver);
3320+}
3321+
3322+static void
3323+ts_module_cleanup (void)
3324+{
3325+ platform_driver_unregister (&ts_driver);
3326+}
3327+
3328+module_init(ts_module_init);
3329+module_exit(ts_module_cleanup);
3330+
3331+MODULE_LICENSE("GPL");
3332+MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");
3333+MODULE_DESCRIPTION("HTC Universal Touch Screen Driver");
3334Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c
3335===================================================================
3336--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3337+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c 2007-09-11 12:53:37.000000000 +0200
3338@@ -0,0 +1,71 @@
3339+
3340+/*
3341+ *
3342+ * htcuniversal_udc.c:
3343+ * htcuniversal specific code for the pxa27x usb device controller.
3344+ *
3345+ * Use consistent with the GNU GPL is permitted.
3346+ *
3347+ */
3348+
3349+#include <linux/module.h>
3350+#include <linux/init.h>
3351+#include <linux/platform_device.h>
3352+#include <asm/arch/hardware.h>
3353+#include <asm/arch/pxa-regs.h>
3354+#include <asm/arch/udc.h>
3355+#include <linux/soc/asic3_base.h>
3356+#include <asm/arch/htcuniversal-gpio.h>
3357+#include <asm/arch/htcuniversal-asic.h>
3358+
3359+static void htcuniversal_udc_command(int cmd)
3360+{
3361+ switch (cmd) {
3362+ case PXA2XX_UDC_CMD_DISCONNECT:
3363+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev,
3364+ 1<<GPIOB_USB_PUEN, 0);
3365+// SET_HTCUNIVERSAL_GPIO(USB_PUEN,0);
3366+ break;
3367+ case PXA2XX_UDC_CMD_CONNECT:
3368+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev,
3369+ 1<<GPIOB_USB_PUEN, 1<<GPIOB_USB_PUEN);
3370+// SET_HTCUNIVERSAL_GPIO(USB_PUEN,1);
3371+ break;
3372+ default:
3373+ printk("_udc_control: unknown command!\n");
3374+ break;
3375+ }
3376+}
3377+
3378+static int htcuniversal_udc_is_connected(void)
3379+{
3380+ return (GET_HTCUNIVERSAL_GPIO(USB_DET) != 0);
3381+}
3382+
3383+static struct pxa2xx_udc_mach_info htcuniversal_udc_info __initdata = {
3384+ .udc_is_connected = htcuniversal_udc_is_connected,
3385+ .udc_command = htcuniversal_udc_command,
3386+};
3387+
3388+static int htcuniversal_udc_probe(struct platform_device * dev)
3389+{
3390+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_USB_PUEN, 1<<GPIOB_USB_PUEN);
3391+
3392+ pxa_set_udc_info(&htcuniversal_udc_info);
3393+ return 0;
3394+}
3395+
3396+static struct platform_driver htcuniversal_udc_driver = {
3397+ .driver = {
3398+ .name = "htcuniversal_udc",
3399+ },
3400+ .probe = htcuniversal_udc_probe,
3401+};
3402+
3403+static int __init htcuniversal_udc_init(void)
3404+{
3405+ return platform_driver_register(&htcuniversal_udc_driver);
3406+}
3407+
3408+module_init(htcuniversal_udc_init);
3409+MODULE_LICENSE("GPL");
3410Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h
3411===================================================================
3412--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3413+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h 2007-09-11 12:53:37.000000000 +0200
3414@@ -0,0 +1,20 @@
3415+/*
3416+ * temporary TSC2046 touchscreen hack
3417+ */
3418+
3419+#ifndef _TSC2046_TS_H
3420+#define _TSC2046_TS_H
3421+
3422+struct tsc2046_mach_info {
3423+ int port;
3424+ int clock;
3425+ int pwrbit_X;
3426+ int pwrbit_Y;
3427+ int irq;
3428+ int (*pen_down)(void);
3429+};
3430+
3431+#define TSC2046_SAMPLE_X 0xd0
3432+#define TSC2046_SAMPLE_Y 0x90
3433+
3434+#endif
3435Index: linux-2.6.22/arch/arm/mach-pxa/Kconfig
3436===================================================================
3437--- linux-2.6.22.orig/arch/arm/mach-pxa/Kconfig 2007-09-11 12:53:33.000000000 +0200
3438+++ linux-2.6.22/arch/arm/mach-pxa/Kconfig 2007-09-11 12:53:37.000000000 +0200
3439@@ -50,6 +50,14 @@
3440 help
3441 This enables support for the HP iPAQ HX2750 handheld.
3442
3443+config MACH_HTCUNIVERSAL
3444+ bool "HTC Universal"
3445+ select PXA27x
3446+ help
3447+ Say Y here if you intend to run this kernel on a
3448+ HTC Universal. Currently there is only basic support
3449+ for this PDA.
3450+
3451 endchoice
3452
3453 if PXA_SHARPSL
3454@@ -84,6 +92,86 @@
3455
3456 endif
3457
3458+if MACH_HTCUNIVERSAL
3459+
3460+menu "HTC Universal support"
3461+
3462+config HTCUNIVERSAL_CORE
3463+ tristate "HTC Universal core"
3464+ depends on MACH_HTCUNIVERSAL
3465+ help
3466+ This selection enables HTC Universal core support.
3467+
3468+config HTCUNIVERSAL_UDC
3469+ bool "USB Device Controller support"
3470+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && USB_PXA27X
3471+ help
3472+ Enables HTC Universal specific USB detection
3473+
3474+config HTCUNIVERSAL_POWER
3475+ tristate "HTC Universal power"
3476+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3
3477+ help
3478+ This selection enables HTC Universal power monitoring
3479+ hardware support (through ASIC3).
3480+
3481+config HTCUNIVERSAL_BACKLIGHT
3482+ bool "HTC Universal Backlight"
3483+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && BACKLIGHT_CLASS_DEVICE
3484+ help
3485+ This driver provides support for changing power and brightness
3486+ on HTC Universal LCD backlight.
3487+
3488+config HTCUNIVERSAL_LCD
3489+ tristate "HTC Universal LCD"
3490+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && LCD_CLASS_DEVICE
3491+ help
3492+ This driver provides support for changing power and brightness
3493+ on HTC Universal LCD display.
3494+
3495+config HTCUNIVERSAL_TS2
3496+ tristate "HTC Universal Touchscreen (old)"
3497+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3
3498+ help
3499+ Enable support for the HTC Universal Touchscreen Panel.
3500+
3501+config HTCUNIVERSAL_BUTTONS
3502+ tristate "HTC Universal buttons support"
3503+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3
3504+
3505+config HTCUNIVERSAL_BLUETOOTH
3506+ tristate "HTC Universal Bluetooth"
3507+ depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
3508+ help
3509+ Enables support for the TI BRF6150 Bluetooth Module
3510+ in the HTC Universal.
3511+
3512+config HTCUNIVERSAL_ASIC3_LEDS
3513+ tristate "HTC Universal ASIC3 LED support"
3514+ select LEDS_ASIC3
3515+ depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
3516+ ---help---
3517+ Support for right (colors red+green+(amber)) and left (green+blue) led
3518+ Off/on hook keys LED backlight
3519+ Keyboard backlight
3520+ Vibra
3521+ Flashlight
3522+
3523+config HTCUNIVERSAL_PHONE
3524+ tristate "HTC Universal Phone"
3525+ depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
3526+ help
3527+ Enables support for the Qualcomm MSM6520 Phone Module
3528+ in the HTC Universal.
3529+
3530+config HTCUNIVERSAL_AK4641
3531+ depends on SND && I2C
3532+ tristate "AK4641 chipset support"
3533+
3534+endmenu
3535+
3536+endif
3537+
3538 endmenu
3539
3540 config MACH_POODLE
3541@@ -164,4 +252,3 @@
3542 depends on (PXA25x || PXA27x) && INPUT
3543
3544 endif
3545-
3546Index: linux-2.6.22/arch/arm/mach-pxa/Makefile
3547===================================================================
3548--- linux-2.6.22.orig/arch/arm/mach-pxa/Makefile 2007-09-11 12:53:33.000000000 +0200
3549+++ linux-2.6.22/arch/arm/mach-pxa/Makefile 2007-09-11 12:53:37.000000000 +0200
3550@@ -20,6 +20,7 @@
3551 obj-$(CONFIG_MACH_TOSA) += tosa.o
3552 obj-$(CONFIG_MACH_EM_X270) += em-x270.o
3553 obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o
3554+obj-$(CONFIG_MACH_HTCUNIVERSAL) += htcuniversal/
3555
3556 # Support for blinky lights
3557 led-y := leds.o
3558Index: linux-2.6.22/drivers/leds/Kconfig
3559===================================================================
3560--- linux-2.6.22.orig/drivers/leds/Kconfig 2007-09-11 12:53:14.000000000 +0200
3561+++ linux-2.6.22/drivers/leds/Kconfig 2007-09-11 12:53:37.000000000 +0200
3562@@ -101,6 +101,13 @@
3563 outputs. To be useful the particular board must have LEDs
3564 and they must be connected to the GPIO lines.
3565
3566+config LEDS_ASIC3
3567+ tristate "LED Support for the HTC ASIC3 chip"
3568+ depends LEDS_CLASS && HTC_ASIC3
3569+ help
3570+ This option enables support for the LEDs connected to the
3571+ HTC ASIC3 chip.
3572+
3573 comment "LED Triggers"
3574
3575 config LEDS_TRIGGERS
3576Index: linux-2.6.22/drivers/leds/leds-asic3.c
3577===================================================================
3578--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3579+++ linux-2.6.22/drivers/leds/leds-asic3.c 2007-09-11 12:53:37.000000000 +0200
3580@@ -0,0 +1,189 @@
3581+/*
3582+ * LEDs support for HTC ASIC3 devices.
3583+ *
3584+ * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru>
3585+ *
3586+ * This file is subject to the terms and conditions of the GNU General Public
3587+ * License. See the file COPYING in the main directory of this archive for
3588+ * more details.
3589+ *
3590+ */
3591+
3592+#include <linux/kernel.h>
3593+#include <linux/init.h>
3594+#include <linux/platform_device.h>
3595+#include <linux/leds.h>
3596+#include "leds.h"
3597+
3598+#include <asm/hardware/ipaq-asic3.h>
3599+#include <linux/soc/asic3_base.h>
3600+#include <asm/mach-types.h>
3601+#include <asm/hardware/asic3_leds.h>
3602+
3603+#ifdef DEBUG
3604+#define dbg(msg, ...) printk(msg, __VA_ARGS__)
3605+#else
3606+#define dbg(msg, ...)
3607+#endif
3608+
3609+static
3610+void asic3_leds_set(struct led_classdev *led_cdev, enum led_brightness b)
3611+{
3612+ struct asic3_led *led = container_of(led_cdev, struct asic3_led,
3613+ led_cdev);
3614+ struct asic3_leds_machinfo *machinfo = led->machinfo;
3615+ struct device *asic3_dev = &machinfo->asic3_pdev->dev;
3616+
3617+ dbg("%s:%s %d(%d)-%s %d\n", __FILE__, __FUNCTION__, led->hw_num,
3618+ led->gpio_num, led->led_cdev.name, b);
3619+
3620+ if (led->hw_num == -1) {
3621+ asic3_gpio_set_value(asic3_dev, led->gpio_num, b);
3622+ return;
3623+ }
3624+
3625+ if (b == LED_OFF) {
3626+ asic3_set_led(asic3_dev, led->hw_num, 0, 16, 6);
3627+ asic3_set_gpio_out_c(asic3_dev, led->hw_num, 0);
3628+ }
3629+ else {
3630+ asic3_set_gpio_out_c(asic3_dev, led->hw_num, led->hw_num);
3631+ #ifdef CONFIG_LEDS_TRIGGER_HWTIMER
3632+ if (led_cdev->trigger && led_cdev->trigger->is_led_supported &&
3633+ (led_cdev->trigger->is_led_supported(led_cdev) &
3634+ LED_SUPPORTS_HWTIMER)) {
3635+ struct hwtimer_data *td = led_cdev->trigger_data;
3636+ if (!td) return;
3637+ asic3_set_led(asic3_dev, led->hw_num, td->delay_on/8,
3638+ (td->delay_on + td->delay_off)/8, 6);
3639+ }
3640+ else
3641+ #endif
3642+ asic3_set_led(asic3_dev, led->hw_num, 16, 16, 6);
3643+ }
3644+
3645+ return;
3646+}
3647+
3648+static
3649+int asic3_leds_probe(struct platform_device *pdev)
3650+{
3651+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
3652+ struct asic3_led *leds = machinfo->leds;
3653+ int ret, i = 0;
3654+
3655+ dbg("%s:%s\n", __FILE__, __FUNCTION__);
3656+
3657+ // Turn on clocks early, for the case if trigger would enable
3658+ // led immediately after led_classdev_register().
3659+ asic3_set_clock_cdex(&machinfo->asic3_pdev->dev,
3660+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2,
3661+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2);
3662+
3663+ for (i = 0; i < machinfo->num_leds; i++) {
3664+ leds[i].machinfo = machinfo;
3665+ leds[i].led_cdev.brightness_set = asic3_leds_set;
3666+ ret = led_classdev_register(&pdev->dev, &leds[i].led_cdev);
3667+ if (ret) {
3668+ printk(KERN_ERR "Error: can't register %s led\n",
3669+ leds[i].led_cdev.name);
3670+ goto out_err;
3671+ }
3672+ }
3673+
3674+ return 0;
3675+
3676+out_err:
3677+ while (--i >= 0) led_classdev_unregister(&leds[i].led_cdev);
3678+
3679+ asic3_set_clock_cdex(&machinfo->asic3_pdev->dev,
3680+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2,
3681+ 0 | 0 | 0);
3682+
3683+ return ret;
3684+}
3685+
3686+static
3687+int asic3_leds_remove(struct platform_device *pdev)
3688+{
3689+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
3690+ struct asic3_led *leds = machinfo->leds;
3691+ int i = 0;
3692+
3693+ dbg("%s:%s\n", __FILE__, __FUNCTION__);
3694+
3695+ for (i = 0; i < machinfo->num_leds; i++)
3696+ led_classdev_unregister(&leds[i].led_cdev);
3697+
3698+ asic3_set_clock_cdex(&machinfo->asic3_pdev->dev,
3699+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2,
3700+ 0 | 0 | 0);
3701+
3702+ return 0;
3703+}
3704+
3705+#ifdef CONFIG_PM
3706+
3707+static
3708+int asic3_leds_suspend(struct platform_device *pdev, pm_message_t state)
3709+{
3710+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
3711+ struct asic3_led *leds = machinfo->leds;
3712+ int i = 0;
3713+
3714+ dbg("%s:%s\n", __FILE__, __FUNCTION__);
3715+
3716+ for (i = 0; i < machinfo->num_leds; i++)
3717+ led_classdev_suspend(&leds[i].led_cdev);
3718+
3719+ return 0;
3720+}
3721+
3722+static
3723+int asic3_leds_resume(struct platform_device *pdev)
3724+{
3725+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
3726+ struct asic3_led *leds = machinfo->leds;
3727+ int i = 0;
3728+
3729+ dbg("%s:%s\n", __FILE__, __FUNCTION__);
3730+
3731+ for (i = 0; i < machinfo->num_leds; i++)
3732+ led_classdev_resume(&leds[i].led_cdev);
3733+
3734+ return 0;
3735+}
3736+
3737+#endif
3738+
3739+static
3740+struct platform_driver asic3_leds_driver = {
3741+ .probe = asic3_leds_probe,
3742+ .remove = asic3_leds_remove,
3743+#ifdef CONFIG_PM
3744+ .suspend = asic3_leds_suspend,
3745+ .resume = asic3_leds_resume,
3746+#endif
3747+ .driver = {
3748+ .name = "asic3-leds",
3749+ },
3750+};
3751+
3752+int asic3_leds_register(void)
3753+{
3754+ dbg("%s:%s\n", __FILE__, __FUNCTION__);
3755+ return platform_driver_register(&asic3_leds_driver);
3756+}
3757+
3758+void asic3_leds_unregister(void)
3759+{
3760+ platform_driver_unregister(&asic3_leds_driver);
3761+ return;
3762+}
3763+
3764+EXPORT_SYMBOL_GPL(asic3_leds_register);
3765+EXPORT_SYMBOL_GPL(asic3_leds_unregister);
3766+
3767+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
3768+MODULE_DESCRIPTION("HTC ASIC3 LEDs driver");
3769+MODULE_LICENSE("GPL");
3770Index: linux-2.6.22/drivers/mfd/Kconfig
3771===================================================================
3772--- linux-2.6.22.orig/drivers/mfd/Kconfig 2007-09-11 12:53:30.000000000 +0200
3773+++ linux-2.6.22/drivers/mfd/Kconfig 2007-09-11 12:53:37.000000000 +0200
3774@@ -15,6 +15,16 @@
3775 interface. The device may be connected by PCI or local bus with
3776 varying functions enabled.
3777
3778+config HTC_ASIC3
3779+ tristate "HTC ASIC3 (iPAQ h1900/h3900/h4000/hx4700/rx3000) support"
3780+
3781+config HTC_ASIC3_DS1WM
3782+ bool "Support HTC ASIC3 builtin DS1WM block"
3783+ help
3784+ Choose Y here if you want to include support for ASIC3's builtin
3785+ W1 controller. Some devices do not use it, and yet other have
3786+ separate DS1WM controller. For them, choose N.
3787+
3788 endmenu
3789
3790 menu "Multimedia Capabilities Port drivers"
3791Index: linux-2.6.22/drivers/mfd/Makefile
3792===================================================================
3793--- linux-2.6.22.orig/drivers/mfd/Makefile 2007-09-11 12:53:30.000000000 +0200
3794+++ linux-2.6.22/drivers/mfd/Makefile 2007-09-11 12:53:37.000000000 +0200
3795@@ -2,6 +2,8 @@
3796 # Makefile for multifunction miscellaneous devices
3797 #
3798
3799+obj-$(CONFIG_HTC_ASIC3) += asic3_base.o soc-core.o
3800+
3801 obj-$(CONFIG_MFD_SM501) += sm501.o
3802
3803 obj-$(CONFIG_MCP) += mcp-core.o
3804Index: linux-2.6.22/drivers/mfd/asic3_base.c
3805===================================================================
3806--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3807+++ linux-2.6.22/drivers/mfd/asic3_base.c 2007-09-11 12:53:37.000000000 +0200
3808@@ -0,0 +1,1208 @@
3809+/*
3810+ * Driver interface to HTC "ASIC3"
3811+ *
3812+ * Copyright 2001 Compaq Computer Corporation.
3813+ * Copyright 2004-2005 Phil Blundell
3814+ *
3815+ * This program is free software; you can redistribute it and/or modify
3816+ * it under the terms of the GNU General Public License as published by
3817+ * the Free Software Foundation; either version 2 of the License, or
3818+ * (at your option) any later version.
3819+ *
3820+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
3821+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
3822+ * FITNESS FOR ANY PARTICULAR PURPOSE.
3823+ *
3824+ * Author: Andrew Christian
3825+ * <Andrew.Christian@compaq.com>
3826+ * October 2001
3827+ */
3828+
3829+#include <linux/module.h>
3830+#include <linux/version.h>
3831+#include <linux/platform_device.h>
3832+#include <linux/delay.h>
3833+#include <linux/init.h>
3834+#include <linux/irq.h>
3835+#include <linux/clk.h>
3836+#include <linux/ds1wm.h>
3837+#include <asm/arch/clock.h>
3838+
3839+#include <asm/hardware.h>
3840+#include <asm/irq.h>
3841+#include <asm/io.h>
3842+
3843+#include <asm/hardware/ipaq-asic3.h>
3844+#include <linux/soc/asic3_base.h>
3845+#include <linux/soc/tmio_mmc.h>
3846+#include "soc-core.h"
3847+
3848+
3849+struct asic3_data {
3850+ void *mapping;
3851+ unsigned int bus_shift;
3852+ int irq_base;
3853+ int irq_nr;
3854+
3855+ u16 irq_bothedge[4];
3856+ struct device *dev;
3857+
3858+ struct platform_device *mmc_dev;
3859+};
3860+
3861+static DEFINE_SPINLOCK(asic3_gpio_lock);
3862+
3863+static int asic3_remove(struct platform_device *dev);
3864+
3865+static inline unsigned long asic3_address(struct device *dev,
3866+ unsigned int reg)
3867+{
3868+ struct asic3_data *adata;
3869+
3870+ adata = (struct asic3_data *)dev->driver_data;
3871+
3872+ return (unsigned long)adata->mapping + (reg >> (2 - adata->bus_shift));
3873+}
3874+
3875+void asic3_write_register(struct device *dev, unsigned int reg, u32 value)
3876+{
3877+ __raw_writew(value, asic3_address(dev, reg));
3878+}
3879+EXPORT_SYMBOL(asic3_write_register);
3880+
3881+u32 asic3_read_register(struct device *dev, unsigned int reg)
3882+{
3883+ return __raw_readw(asic3_address(dev, reg));
3884+}
3885+EXPORT_SYMBOL(asic3_read_register);
3886+
3887+static inline void __asic3_write_register(struct asic3_data *asic,
3888+ unsigned int reg, u32 value)
3889+{
3890+ __raw_writew(value, (unsigned long)asic->mapping
3891+ + (reg >> (2 - asic->bus_shift)));
3892+}
3893+
3894+static inline u32 __asic3_read_register(struct asic3_data *asic,
3895+ unsigned int reg)
3896+{
3897+ return __raw_readw((unsigned long)asic->mapping
3898+ + (reg >> (2 - asic->bus_shift)));
3899+}
3900+
3901+#define ASIC3_GPIO_FN(get_fn_name, set_fn_name, REG) \
3902+u32 get_fn_name(struct device *dev) \
3903+{ \
3904+ return asic3_read_register(dev, REG); \
3905+} \
3906+EXPORT_SYMBOL(get_fn_name); \
3907+ \
3908+void set_fn_name(struct device *dev, u32 bits, u32 val) \
3909+{ \
3910+ unsigned long flags; \
3911+ \
3912+ spin_lock_irqsave(&asic3_gpio_lock, flags); \
3913+ val |= (asic3_read_register(dev, REG) & ~bits); \
3914+ asic3_write_register(dev, REG, val); \
3915+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); \
3916+} \
3917+EXPORT_SYMBOL(set_fn_name);
3918+
3919+#define ASIC3_GPIO_REGISTER(ACTION, action, fn, FN) \
3920+ ASIC3_GPIO_FN(asic3_get_gpio_ ## action ## _ ## fn , \
3921+ asic3_set_gpio_ ## action ## _ ## fn , \
3922+ _IPAQ_ASIC3_GPIO_ ## FN ## _Base \
3923+ + _IPAQ_ASIC3_GPIO_ ## ACTION )
3924+
3925+#define ASIC3_GPIO_FUNCTIONS(fn, FN) \
3926+ ASIC3_GPIO_REGISTER(Direction, dir, fn, FN) \
3927+ ASIC3_GPIO_REGISTER(Out, out, fn, FN) \
3928+ ASIC3_GPIO_REGISTER(SleepMask, sleepmask, fn, FN) \
3929+ ASIC3_GPIO_REGISTER(SleepOut, sleepout, fn, FN) \
3930+ ASIC3_GPIO_REGISTER(BattFaultOut, battfaultout, fn, FN) \
3931+ ASIC3_GPIO_REGISTER(AltFunction, alt_fn, fn, FN) \
3932+ ASIC3_GPIO_REGISTER(SleepConf, sleepconf, fn, FN) \
3933+ ASIC3_GPIO_REGISTER(Status, status, fn, FN)
3934+
3935+#if 0
3936+ ASIC3_GPIO_REGISTER(Mask, mask, fn, FN)
3937+ ASIC3_GPIO_REGISTER(TriggerType, trigtype, fn, FN)
3938+ ASIC3_GPIO_REGISTER(EdgeTrigger, rising, fn, FN)
3939+ ASIC3_GPIO_REGISTER(LevelTrigger, triglevel, fn, FN)
3940+ ASIC3_GPIO_REGISTER(IntStatus, intstatus, fn, FN)
3941+#endif
3942+
3943+ASIC3_GPIO_FUNCTIONS(a, A)
3944+ASIC3_GPIO_FUNCTIONS(b, B)
3945+ASIC3_GPIO_FUNCTIONS(c, C)
3946+ASIC3_GPIO_FUNCTIONS(d, D)
3947+
3948+int asic3_gpio_get_value(struct device *dev, unsigned gpio)
3949+{
3950+ u32 mask = ASIC3_GPIO_bit(gpio);
3951+ printk("%s(%d)\n", __FUNCTION__, gpio);
3952+ switch (gpio >> 4) {
3953+ case _IPAQ_ASIC3_GPIO_BANK_A:
3954+ return asic3_get_gpio_status_a(dev) & mask;
3955+ case _IPAQ_ASIC3_GPIO_BANK_B:
3956+ return asic3_get_gpio_status_b(dev) & mask;
3957+ case _IPAQ_ASIC3_GPIO_BANK_C:
3958+ return asic3_get_gpio_status_c(dev) & mask;
3959+ case _IPAQ_ASIC3_GPIO_BANK_D:
3960+ return asic3_get_gpio_status_d(dev) & mask;
3961+ }
3962+
3963+ printk(KERN_ERR "%s: invalid GPIO value 0x%x", __FUNCTION__, gpio);
3964+ return 0;
3965+}
3966+EXPORT_SYMBOL(asic3_gpio_get_value);
3967+
3968+void asic3_gpio_set_value(struct device *dev, unsigned gpio, int val)
3969+{
3970+ u32 mask = ASIC3_GPIO_bit(gpio);
3971+ u32 bitval = 0;
3972+ if (val) bitval = mask;
3973+ printk("%s(%d, %d)\n", __FUNCTION__, gpio, val);
3974+
3975+ switch (gpio >> 4) {
3976+ case _IPAQ_ASIC3_GPIO_BANK_A:
3977+ asic3_set_gpio_out_a(dev, mask, bitval);
3978+ return;
3979+ case _IPAQ_ASIC3_GPIO_BANK_B:
3980+ asic3_set_gpio_out_b(dev, mask, bitval);
3981+ return;
3982+ case _IPAQ_ASIC3_GPIO_BANK_C:
3983+ asic3_set_gpio_out_c(dev, mask, bitval);
3984+ return;
3985+ case _IPAQ_ASIC3_GPIO_BANK_D:
3986+ asic3_set_gpio_out_d(dev, mask, bitval);
3987+ return;
3988+ }
3989+
3990+ printk(KERN_ERR "%s: invalid GPIO value 0x%x", __FUNCTION__, gpio);
3991+}
3992+EXPORT_SYMBOL(asic3_gpio_set_value);
3993+
3994+int asic3_irq_base(struct device *dev)
3995+{
3996+ struct asic3_data *asic = dev->driver_data;
3997+
3998+ return asic->irq_base;
3999+}
4000+EXPORT_SYMBOL(asic3_irq_base);
4001+
4002+static int asic3_gpio_to_irq(struct device *dev, unsigned gpio)
4003+{
4004+ struct asic3_data *asic = dev->driver_data;
4005+ printk("%s(%d)\n", __FUNCTION__, gpio);
4006+
4007+ return asic->irq_base + gpio;
4008+}
4009+
4010+void asic3_set_led(struct device *dev, int led_num, int duty_time,
4011+ int cycle_time, int timebase)
4012+{
4013+ struct asic3_data *asic = dev->driver_data;
4014+ unsigned int led_base;
4015+
4016+ /* it's a macro thing: see #define _IPAQ_ASIC_LED_0_Base for why you
4017+ * can't substitute led_num in the macros below...
4018+ */
4019+
4020+ switch (led_num) {
4021+ case 0:
4022+ led_base = _IPAQ_ASIC3_LED_0_Base;
4023+ break;
4024+ case 1:
4025+ led_base = _IPAQ_ASIC3_LED_1_Base;
4026+ break;
4027+ case 2:
4028+ led_base = _IPAQ_ASIC3_LED_2_Base;
4029+ break;
4030+ default:
4031+ printk(KERN_ERR "%s: invalid led number %d", __FUNCTION__,
4032+ led_num);
4033+ return;
4034+ }
4035+
4036+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_TimeBase,
4037+ timebase | LED_EN);
4038+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_PeriodTime,
4039+ cycle_time);
4040+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_DutyTime,
4041+ 0);
4042+ udelay(20); /* asic voodoo - possibly need a whole duty cycle? */
4043+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_DutyTime,
4044+ duty_time);
4045+}
4046+EXPORT_SYMBOL(asic3_set_led);
4047+
4048+void asic3_set_clock_sel(struct device *dev, u32 bits, u32 val)
4049+{
4050+ struct asic3_data *asic = dev->driver_data;
4051+ unsigned long flags;
4052+ u32 v;
4053+
4054+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4055+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL));
4056+ v = (v & ~bits) | val;
4057+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), v);
4058+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4059+}
4060+EXPORT_SYMBOL(asic3_set_clock_sel);
4061+
4062+void asic3_set_clock_cdex(struct device *dev, u32 bits, u32 val)
4063+{
4064+ struct asic3_data *asic = dev->driver_data;
4065+ unsigned long flags;
4066+ u32 v;
4067+
4068+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4069+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX));
4070+ v = (v & ~bits) | val;
4071+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), v);
4072+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4073+}
4074+EXPORT_SYMBOL(asic3_set_clock_cdex);
4075+
4076+static void asic3_clock_cdex_enable(struct clk *clk)
4077+{
4078+ struct asic3_data *asic = (struct asic3_data *)clk->parent->ctrlbit;
4079+ unsigned long flags, val;
4080+
4081+ local_irq_save(flags);
4082+
4083+ val = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX));
4084+ val |= clk->ctrlbit;
4085+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), val);
4086+
4087+ local_irq_restore(flags);
4088+}
4089+
4090+static void asic3_clock_cdex_disable(struct clk *clk)
4091+{
4092+ struct asic3_data *asic = (struct asic3_data *)clk->parent->ctrlbit;
4093+ unsigned long flags, val;
4094+
4095+ local_irq_save(flags);
4096+
4097+ val = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX));
4098+ val &= ~clk->ctrlbit;
4099+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), val);
4100+
4101+ local_irq_restore(flags);
4102+}
4103+
4104+/* base clocks */
4105+
4106+static struct clk clk_g = {
4107+ .name = "gclk",
4108+ .rate = 0,
4109+ .parent = NULL,
4110+};
4111+
4112+/* clock definitions */
4113+
4114+static struct clk asic3_clocks[] = {
4115+ {
4116+ .name = "spi",
4117+ .id = -1,
4118+ .parent = &clk_g,
4119+ .enable = asic3_clock_cdex_enable,
4120+ .disable = asic3_clock_cdex_disable,
4121+ .ctrlbit = CLOCK_CDEX_SPI,
4122+ },
4123+#ifdef CONFIG_HTC_ASIC3_DS1WM
4124+ {
4125+ .name = "ds1wm",
4126+ .id = -1,
4127+ .rate = 5000000,
4128+ .parent = &clk_g,
4129+ .enable = asic3_clock_cdex_enable,
4130+ .disable = asic3_clock_cdex_disable,
4131+ .ctrlbit = CLOCK_CDEX_OWM,
4132+ },
4133+#endif
4134+ {
4135+ .name = "pwm0",
4136+ .id = -1,
4137+ .parent = &clk_g,
4138+ .enable = asic3_clock_cdex_enable,
4139+ .disable = asic3_clock_cdex_disable,
4140+ .ctrlbit = CLOCK_CDEX_PWM0,
4141+ },
4142+ {
4143+ .name = "pwm1",
4144+ .id = -1,
4145+ .parent = &clk_g,
4146+ .enable = asic3_clock_cdex_enable,
4147+ .disable = asic3_clock_cdex_disable,
4148+ .ctrlbit = CLOCK_CDEX_PWM1,
4149+ },
4150+ {
4151+ .name = "led0",
4152+ .id = -1,
4153+ .parent = &clk_g,
4154+ .enable = asic3_clock_cdex_enable,
4155+ .disable = asic3_clock_cdex_disable,
4156+ .ctrlbit = CLOCK_CDEX_LED0,
4157+ },
4158+ {
4159+ .name = "led1",
4160+ .id = -1,
4161+ .parent = &clk_g,
4162+ .enable = asic3_clock_cdex_enable,
4163+ .disable = asic3_clock_cdex_disable,
4164+ .ctrlbit = CLOCK_CDEX_LED1,
4165+ },
4166+ {
4167+ .name = "led2",
4168+ .id = -1,
4169+ .parent = &clk_g,
4170+ .enable = asic3_clock_cdex_enable,
4171+ .disable = asic3_clock_cdex_disable,
4172+ .ctrlbit = CLOCK_CDEX_LED2,
4173+ },
4174+ {
4175+ .name = "smbus",
4176+ .id = -1,
4177+ .parent = &clk_g,
4178+ .enable = asic3_clock_cdex_enable,
4179+ .disable = asic3_clock_cdex_disable,
4180+ .ctrlbit = CLOCK_CDEX_SMBUS,
4181+ },
4182+ {
4183+ .name = "ex0",
4184+ .id = -1,
4185+ .parent = &clk_g,
4186+ .enable = asic3_clock_cdex_enable,
4187+ .disable = asic3_clock_cdex_disable,
4188+ .ctrlbit = CLOCK_CDEX_EX0,
4189+ },
4190+ {
4191+ .name = "ex1",
4192+ .id = -1,
4193+ .parent = &clk_g,
4194+ .enable = asic3_clock_cdex_enable,
4195+ .disable = asic3_clock_cdex_disable,
4196+ .ctrlbit = CLOCK_CDEX_EX1,
4197+ },
4198+};
4199+
4200+void asic3_set_extcf_select(struct device *dev, u32 bits, u32 val)
4201+{
4202+ struct asic3_data *asic = dev->driver_data;
4203+ unsigned long flags;
4204+ u32 v;
4205+
4206+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4207+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Select));
4208+ v = (v & ~bits) | val;
4209+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Select), v);
4210+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4211+}
4212+EXPORT_SYMBOL(asic3_set_extcf_select);
4213+
4214+void asic3_set_extcf_reset(struct device *dev, u32 bits, u32 val)
4215+{
4216+ struct asic3_data *asic = dev->driver_data;
4217+ unsigned long flags;
4218+ u32 v;
4219+
4220+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4221+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Reset));
4222+ v = (v & ~bits) | val;
4223+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Reset), v);
4224+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4225+}
4226+EXPORT_SYMBOL(asic3_set_extcf_reset);
4227+
4228+void asic3_set_sdhwctrl(struct device *dev, u32 bits, u32 val)
4229+{
4230+ struct asic3_data *asic = dev->driver_data;
4231+ unsigned long flags;
4232+ u32 v;
4233+
4234+ spin_lock_irqsave (&asic3_gpio_lock, flags);
4235+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(SDHWCTRL, SDConf));
4236+ v = (v & ~bits) | val;
4237+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(SDHWCTRL, SDConf), v);
4238+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4239+}
4240+EXPORT_SYMBOL(asic3_set_sdhwctrl);
4241+
4242+
4243+#define MAX_ASIC_ISR_LOOPS 20
4244+#define _IPAQ_ASIC3_GPIO_Base_INCR \
4245+ (_IPAQ_ASIC3_GPIO_B_Base - _IPAQ_ASIC3_GPIO_A_Base)
4246+
4247+static inline void asic3_irq_flip_edge(struct asic3_data *asic,
4248+ u32 base, int bit)
4249+{
4250+ u16 edge = __asic3_read_register(asic,
4251+ base + _IPAQ_ASIC3_GPIO_EdgeTrigger);
4252+ edge ^= bit;
4253+ __asic3_write_register(asic,
4254+ base + _IPAQ_ASIC3_GPIO_EdgeTrigger, edge);
4255+}
4256+
4257+static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
4258+{
4259+ int iter;
4260+ struct asic3_data *asic;
4261+
4262+ /* Acknowledge the parrent (i.e. CPU's) IRQ */
4263+ desc->chip->ack(irq);
4264+
4265+ asic = desc->handler_data;
4266+
4267+ /* printk( KERN_NOTICE "asic3_irq_demux: irq=%d\n", irq ); */
4268+ for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
4269+ u32 status;
4270+ int bank;
4271+
4272+ status = __asic3_read_register(asic,
4273+ IPAQ_ASIC3_OFFSET(INTR, PIntStat));
4274+ /* Check all ten register bits */
4275+ if ((status & 0x3ff) == 0)
4276+ break;
4277+
4278+ /* Handle GPIO IRQs */
4279+ for (bank = 0; bank < 4; bank++) {
4280+ if (status & (1 << bank)) {
4281+ unsigned long base, i, istat;
4282+
4283+ base = _IPAQ_ASIC3_GPIO_A_Base
4284+ + bank * _IPAQ_ASIC3_GPIO_Base_INCR;
4285+ istat = __asic3_read_register(asic,
4286+ base + _IPAQ_ASIC3_GPIO_IntStatus);
4287+ /* IntStatus is write 0 to clear */
4288+ /* XXX could miss interrupts! */
4289+ __asic3_write_register(asic,
4290+ base + _IPAQ_ASIC3_GPIO_IntStatus, 0);
4291+
4292+ for (i = 0; i < 16; i++) {
4293+ int bit = (1 << i);
4294+ unsigned int irqnr;
4295+ if (!(istat & bit))
4296+ continue;
4297+
4298+ irqnr = asic->irq_base
4299+ + (16 * bank) + i;
4300+ desc = irq_desc + irqnr;
4301+ desc->handle_irq(irqnr, desc);
4302+ if (asic->irq_bothedge[bank] & bit) {
4303+ asic3_irq_flip_edge(asic, base,
4304+ bit);
4305+ }
4306+ }
4307+ }
4308+ }
4309+
4310+ /* Handle remaining IRQs in the status register */
4311+ {
4312+ int i;
4313+
4314+ for (i = ASIC3_LED0_IRQ; i <= ASIC3_OWM_IRQ; i++) {
4315+ /* They start at bit 4 and go up */
4316+ if (status & (1 << (i - ASIC3_LED0_IRQ + 4))) {
4317+ desc = irq_desc + asic->irq_base + i;
4318+ desc->handle_irq(asic->irq_base + i,
4319+ desc);
4320+ }
4321+ }
4322+ }
4323+
4324+ }
4325+
4326+ if (iter >= MAX_ASIC_ISR_LOOPS)
4327+ printk(KERN_ERR "%s: interrupt processing overrun\n",
4328+ __FUNCTION__);
4329+}
4330+
4331+static inline int asic3_irq_to_bank(struct asic3_data *asic, int irq)
4332+{
4333+ int n;
4334+
4335+ n = (irq - asic->irq_base) >> 4;
4336+
4337+ return (n * (_IPAQ_ASIC3_GPIO_B_Base - _IPAQ_ASIC3_GPIO_A_Base));
4338+}
4339+
4340+static inline int asic3_irq_to_index(struct asic3_data *asic, int irq)
4341+{
4342+ return (irq - asic->irq_base) & 15;
4343+}
4344+
4345+static void asic3_mask_gpio_irq(unsigned int irq)
4346+{
4347+ struct asic3_data *asic = get_irq_chip_data(irq);
4348+ u32 val, bank, index;
4349+ unsigned long flags;
4350+
4351+ bank = asic3_irq_to_bank(asic, irq);
4352+ index = asic3_irq_to_index(asic, irq);
4353+
4354+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4355+ val = __asic3_read_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask);
4356+ val |= 1 << index;
4357+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask, val);
4358+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4359+}
4360+
4361+static void asic3_mask_irq(unsigned int irq)
4362+{
4363+ struct asic3_data *asic = get_irq_chip_data(irq);
4364+ int regval;
4365+
4366+ if (irq < ASIC3_NR_GPIO_IRQS) {
4367+ printk(KERN_ERR "asic3_base: gpio mask attempt, irq %d\n",
4368+ irq);
4369+ return;
4370+ }
4371+
4372+ regval = __asic3_read_register(asic,
4373+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask);
4374+
4375+ switch (irq - asic->irq_base) {
4376+ case ASIC3_LED0_IRQ:
4377+ __asic3_write_register(asic,
4378+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4379+ regval & ~ASIC3_INTMASK_MASK0);
4380+ break;
4381+ case ASIC3_LED1_IRQ:
4382+ __asic3_write_register(asic,
4383+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4384+ regval & ~ASIC3_INTMASK_MASK1);
4385+ break;
4386+ case ASIC3_LED2_IRQ:
4387+ __asic3_write_register(asic,
4388+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4389+ regval & ~ASIC3_INTMASK_MASK2);
4390+ break;
4391+ case ASIC3_SPI_IRQ:
4392+ __asic3_write_register(asic,
4393+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4394+ regval & ~ASIC3_INTMASK_MASK3);
4395+ break;
4396+ case ASIC3_SMBUS_IRQ:
4397+ __asic3_write_register(asic,
4398+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4399+ regval & ~ASIC3_INTMASK_MASK4);
4400+ break;
4401+ case ASIC3_OWM_IRQ:
4402+ __asic3_write_register(asic,
4403+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4404+ regval & ~ASIC3_INTMASK_MASK5);
4405+ break;
4406+ default:
4407+ printk(KERN_ERR "asic3_base: bad non-gpio irq %d\n", irq);
4408+ break;
4409+ }
4410+}
4411+
4412+static void asic3_unmask_gpio_irq(unsigned int irq)
4413+{
4414+ struct asic3_data *asic = get_irq_chip_data(irq);
4415+ u32 val, bank, index;
4416+ unsigned long flags;
4417+
4418+ bank = asic3_irq_to_bank(asic, irq);
4419+ index = asic3_irq_to_index(asic, irq);
4420+
4421+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4422+ val = __asic3_read_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask);
4423+ val &= ~(1 << index);
4424+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask, val);
4425+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4426+}
4427+
4428+static void asic3_unmask_irq(unsigned int irq)
4429+{
4430+ struct asic3_data *asic = get_irq_chip_data(irq);
4431+ int regval;
4432+
4433+ if (irq < ASIC3_NR_GPIO_IRQS) {
4434+ printk(KERN_ERR "asic3_base: gpio unmask attempt, irq %d\n",
4435+ irq);
4436+ return;
4437+ }
4438+
4439+ regval = __asic3_read_register(asic,
4440+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask);
4441+
4442+ switch (irq - asic->irq_base) {
4443+ case ASIC3_LED0_IRQ:
4444+ __asic3_write_register(asic,
4445+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4446+ regval | ASIC3_INTMASK_MASK0);
4447+ break;
4448+ case ASIC3_LED1_IRQ:
4449+ __asic3_write_register(asic,
4450+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4451+ regval | ASIC3_INTMASK_MASK1);
4452+ break;
4453+ case ASIC3_LED2_IRQ:
4454+ __asic3_write_register(asic,
4455+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4456+ regval | ASIC3_INTMASK_MASK2);
4457+ break;
4458+ case ASIC3_SPI_IRQ:
4459+ __asic3_write_register(asic,
4460+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4461+ regval | ASIC3_INTMASK_MASK3);
4462+ break;
4463+ case ASIC3_SMBUS_IRQ:
4464+ __asic3_write_register(asic,
4465+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4466+ regval | ASIC3_INTMASK_MASK4);
4467+ break;
4468+ case ASIC3_OWM_IRQ:
4469+ __asic3_write_register(asic,
4470+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
4471+ regval | ASIC3_INTMASK_MASK5);
4472+ break;
4473+ default:
4474+ printk(KERN_ERR "asic3_base: bad non-gpio irq %d\n", irq);
4475+ break;
4476+ }
4477+}
4478+
4479+static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
4480+{
4481+ struct asic3_data *asic = get_irq_chip_data(irq);
4482+ u32 bank, index;
4483+ unsigned long flags;
4484+ u16 trigger, level, edge, bit;
4485+
4486+ bank = asic3_irq_to_bank(asic, irq);
4487+ index = asic3_irq_to_index(asic, irq);
4488+ bit = 1<<index;
4489+
4490+ spin_lock_irqsave(&asic3_gpio_lock, flags);
4491+ level = __asic3_read_register(asic,
4492+ bank + _IPAQ_ASIC3_GPIO_LevelTrigger);
4493+ edge = __asic3_read_register(asic,
4494+ bank + _IPAQ_ASIC3_GPIO_EdgeTrigger);
4495+ trigger = __asic3_read_register(asic,
4496+ bank + _IPAQ_ASIC3_GPIO_TriggerType);
4497+ asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit;
4498+
4499+ if (type == IRQT_RISING) {
4500+ trigger |= bit;
4501+ edge |= bit;
4502+ } else if (type == IRQT_FALLING) {
4503+ trigger |= bit;
4504+ edge &= ~bit;
4505+ } else if (type == IRQT_BOTHEDGE) {
4506+ trigger |= bit;
4507+ if (asic3_gpio_get_value(asic->dev, irq - asic->irq_base))
4508+ edge &= ~bit;
4509+ else
4510+ edge |= bit;
4511+ asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit;
4512+ } else if (type == IRQT_LOW) {
4513+ trigger &= ~bit;
4514+ level &= ~bit;
4515+ } else if (type == IRQT_HIGH) {
4516+ trigger &= ~bit;
4517+ level |= bit;
4518+ } else {
4519+ /*
4520+ * if type == IRQT_NOEDGE, we should mask interrupts, but
4521+ * be careful to not unmask them if mask was also called.
4522+ * Probably need internal state for mask.
4523+ */
4524+ printk(KERN_NOTICE "asic3: irq type not changed.\n");
4525+ }
4526+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_LevelTrigger,
4527+ level);
4528+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_EdgeTrigger,
4529+ edge);
4530+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_TriggerType,
4531+ trigger);
4532+ spin_unlock_irqrestore(&asic3_gpio_lock, flags);
4533+ return 0;
4534+}
4535+
4536+static struct irq_chip asic3_gpio_irq_chip = {
4537+ .name = "ASIC3-GPIO",
4538+ .ack = asic3_mask_gpio_irq,
4539+ .mask = asic3_mask_gpio_irq,
4540+ .unmask = asic3_unmask_gpio_irq,
4541+ .set_type = asic3_gpio_irq_type,
4542+};
4543+
4544+static struct irq_chip asic3_irq_chip = {
4545+ .name = "ASIC3",
4546+ .ack = asic3_mask_irq,
4547+ .mask = asic3_mask_irq,
4548+ .unmask = asic3_unmask_irq,
4549+};
4550+
4551+static void asic3_release(struct device *dev)
4552+{
4553+ struct platform_device *sdev = to_platform_device(dev);
4554+
4555+ kfree(sdev->resource);
4556+ kfree(sdev);
4557+}
4558+
4559+int asic3_register_mmc(struct device *dev)
4560+{
4561+ struct platform_device *sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
4562+ struct tmio_mmc_hwconfig *mmc_config = kmalloc(sizeof(*mmc_config),
4563+ GFP_KERNEL);
4564+ struct platform_device *pdev = to_platform_device(dev);
4565+ struct asic3_data *asic = dev->driver_data;
4566+ struct asic3_platform_data *asic3_pdata = dev->platform_data;
4567+ struct resource *res;
4568+ int rc;
4569+
4570+ if (sdev == NULL || mmc_config == NULL)
4571+ return -ENOMEM;
4572+
4573+ if (asic3_pdata->tmio_mmc_hwconfig) {
4574+ memcpy(mmc_config, asic3_pdata->tmio_mmc_hwconfig,
4575+ sizeof(*mmc_config));
4576+ } else {
4577+ memset(mmc_config, 0, sizeof(*mmc_config));
4578+ }
4579+ mmc_config->address_shift = asic->bus_shift;
4580+
4581+ sdev->id = -1;
4582+ sdev->name = "asic3_mmc";
4583+ sdev->dev.parent = dev;
4584+ sdev->num_resources = 2;
4585+ sdev->dev.platform_data = mmc_config;
4586+ sdev->dev.release = asic3_release;
4587+
4588+ res = kzalloc(sdev->num_resources * sizeof(struct resource),
4589+ GFP_KERNEL);
4590+ if (res == NULL) {
4591+ kfree(sdev);
4592+ kfree(mmc_config);
4593+ return -ENOMEM;
4594+ }
4595+ sdev->resource = res;
4596+
4597+ res[0].start = pdev->resource[2].start;
4598+ res[0].end = pdev->resource[2].end;
4599+ res[0].flags = IORESOURCE_MEM;
4600+ res[1].start = res[1].end = pdev->resource[3].start;
4601+ res[1].flags = IORESOURCE_IRQ;
4602+
4603+ rc = platform_device_register(sdev);
4604+ if (rc) {
4605+ printk(KERN_ERR "asic3_base: "
4606+ "Could not register asic3_mmc device\n");
4607+ kfree(res);
4608+ kfree(sdev);
4609+ return rc;
4610+ }
4611+
4612+ asic->mmc_dev = sdev;
4613+
4614+ return 0;
4615+}
4616+EXPORT_SYMBOL(asic3_register_mmc);
4617+
4618+int asic3_unregister_mmc(struct device *dev)
4619+{
4620+ struct asic3_data *asic = dev->driver_data;
4621+ platform_device_unregister(asic->mmc_dev);
4622+ asic->mmc_dev = 0;
4623+
4624+ return 0;
4625+}
4626+EXPORT_SYMBOL(asic3_unregister_mmc);
4627+
4628+#ifdef CONFIG_HTC_ASIC3_DS1WM
4629+/*
4630+ * DS1WM subdevice
4631+ */
4632+
4633+static void asic3_ds1wm_enable(struct platform_device *ds1wm_dev)
4634+{
4635+ struct device *dev = ds1wm_dev->dev.parent;
4636+
4637+ /* Turn on external clocks and the OWM clock */
4638+ asic3_set_clock_cdex(dev,
4639+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM,
4640+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM);
4641+
4642+ mdelay(1);
4643+
4644+ asic3_set_extcf_reset(dev, ASIC3_EXTCF_OWM_RESET,
4645+ ASIC3_EXTCF_OWM_RESET);
4646+ mdelay(1);
4647+ asic3_set_extcf_reset(dev, ASIC3_EXTCF_OWM_RESET, 0);
4648+ mdelay(1);
4649+
4650+ /* Clear OWM_SMB, set OWM_EN */
4651+ asic3_set_extcf_select(dev,
4652+ ASIC3_EXTCF_OWM_SMB | ASIC3_EXTCF_OWM_EN,
4653+ 0 | ASIC3_EXTCF_OWM_EN);
4654+
4655+ mdelay(1);
4656+}
4657+
4658+static void asic3_ds1wm_disable(struct platform_device *ds1wm_dev)
4659+{
4660+ struct device *dev = ds1wm_dev->dev.parent;
4661+
4662+ asic3_set_extcf_select(dev,
4663+ ASIC3_EXTCF_OWM_SMB | ASIC3_EXTCF_OWM_EN,
4664+ 0 | 0);
4665+
4666+ asic3_set_clock_cdex(dev,
4667+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM,
4668+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | 0);
4669+}
4670+
4671+
4672+static struct resource asic3_ds1wm_resources[] = {
4673+ {
4674+ .start = _IPAQ_ASIC3_OWM_Base,
4675+ .end = _IPAQ_ASIC3_OWM_Base + 0x14 - 1,
4676+ .flags = IORESOURCE_MEM,
4677+ },
4678+ {
4679+ .start = ASIC3_OWM_IRQ,
4680+ .end = ASIC3_OWM_IRQ,
4681+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
4682+ IORESOURCE_IRQ_SOC_SUBDEVICE,
4683+ },
4684+};
4685+
4686+static struct ds1wm_platform_data ds1wm_pd = {
4687+ .enable = asic3_ds1wm_enable,
4688+ .disable = asic3_ds1wm_disable,
4689+};
4690+#endif
4691+
4692+static struct soc_device_data asic3_blocks[] = {
4693+#ifdef CONFIG_HTC_ASIC3_DS1WM
4694+ {
4695+ .name = "ds1wm",
4696+ .res = asic3_ds1wm_resources,
4697+ .num_resources = ARRAY_SIZE(asic3_ds1wm_resources),
4698+ .hwconfig = &ds1wm_pd,
4699+ },
4700+#endif
4701+};
4702+
4703+static int asic3_probe(struct platform_device *pdev)
4704+{
4705+ struct asic3_platform_data *pdata = pdev->dev.platform_data;
4706+ struct asic3_data *asic;
4707+ struct device *dev = &pdev->dev;
4708+ unsigned long clksel;
4709+ int i, rc;
4710+
4711+ asic = kzalloc(sizeof(struct asic3_data), GFP_KERNEL);
4712+ if (!asic)
4713+ return -ENOMEM;
4714+
4715+ platform_set_drvdata(pdev, asic);
4716+ asic->dev = &pdev->dev;
4717+
4718+ asic->mapping = ioremap(pdev->resource[0].start, IPAQ_ASIC3_MAP_SIZE);
4719+ if (!asic->mapping) {
4720+ printk(KERN_ERR "asic3: couldn't ioremap ASIC3\n");
4721+ kfree (asic);
4722+ return -ENOMEM;
4723+ }
4724+
4725+ if (pdata && pdata->bus_shift)
4726+ asic->bus_shift = pdata->bus_shift;
4727+ else
4728+ asic->bus_shift = 2;
4729+
4730+ /* XXX: should get correct SD clock values from pdata struct */
4731+ clksel = 0;
4732+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), clksel);
4733+
4734+ /* Register ASIC3's clocks. */
4735+ clk_g.ctrlbit = (int)asic;
4736+
4737+ if (clk_register(&clk_g) < 0)
4738+ printk(KERN_ERR "asic3: failed to register ASIC3 gclk\n");
4739+
4740+ for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++) {
4741+ rc = clk_register(&asic3_clocks[i]);
4742+ if (rc < 0)
4743+ printk(KERN_ERR "asic3: "
4744+ "failed to register clock %s (%d)\n",
4745+ asic3_clocks[i].name, rc);
4746+ }
4747+
4748+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(A, Mask), 0xffff);
4749+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(B, Mask), 0xffff);
4750+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(C, Mask), 0xffff);
4751+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(D, Mask), 0xffff);
4752+
4753+ asic3_set_gpio_sleepmask_a(dev, 0xffff, 0xffff);
4754+ asic3_set_gpio_sleepmask_b(dev, 0xffff, 0xffff);
4755+ asic3_set_gpio_sleepmask_c(dev, 0xffff, 0xffff);
4756+ asic3_set_gpio_sleepmask_d(dev, 0xffff, 0xffff);
4757+
4758+ if (pdata) {
4759+ asic3_set_gpio_out_a(dev, 0xffff, pdata->gpio_a.init);
4760+ asic3_set_gpio_out_b(dev, 0xffff, pdata->gpio_b.init);
4761+ asic3_set_gpio_out_c(dev, 0xffff, pdata->gpio_c.init);
4762+ asic3_set_gpio_out_d(dev, 0xffff, pdata->gpio_d.init);
4763+
4764+ asic3_set_gpio_dir_a(dev, 0xffff, pdata->gpio_a.dir);
4765+ asic3_set_gpio_dir_b(dev, 0xffff, pdata->gpio_b.dir);
4766+ asic3_set_gpio_dir_c(dev, 0xffff, pdata->gpio_c.dir);
4767+ asic3_set_gpio_dir_d(dev, 0xffff, pdata->gpio_d.dir);
4768+
4769+ asic3_set_gpio_sleepmask_a(dev, 0xffff,
4770+ pdata->gpio_a.sleep_mask);
4771+ asic3_set_gpio_sleepmask_b(dev, 0xffff,
4772+ pdata->gpio_b.sleep_mask);
4773+ asic3_set_gpio_sleepmask_c(dev, 0xffff,
4774+ pdata->gpio_c.sleep_mask);
4775+ asic3_set_gpio_sleepmask_d(dev, 0xffff,
4776+ pdata->gpio_d.sleep_mask);
4777+
4778+ asic3_set_gpio_sleepout_a(dev, 0xffff,
4779+ pdata->gpio_a.sleep_out);
4780+ asic3_set_gpio_sleepout_b(dev, 0xffff,
4781+ pdata->gpio_b.sleep_out);
4782+ asic3_set_gpio_sleepout_c(dev, 0xffff,
4783+ pdata->gpio_c.sleep_out);
4784+ asic3_set_gpio_sleepout_d(dev, 0xffff,
4785+ pdata->gpio_d.sleep_out);
4786+
4787+ asic3_set_gpio_battfaultout_a(dev, 0xffff,
4788+ pdata->gpio_a.batt_fault_out);
4789+ asic3_set_gpio_battfaultout_b(dev, 0xffff,
4790+ pdata->gpio_b.batt_fault_out);
4791+ asic3_set_gpio_battfaultout_c(dev, 0xffff,
4792+ pdata->gpio_c.batt_fault_out);
4793+ asic3_set_gpio_battfaultout_d(dev, 0xffff,
4794+ pdata->gpio_d.batt_fault_out);
4795+
4796+ asic3_set_gpio_sleepconf_a(dev, 0xffff,
4797+ pdata->gpio_a.sleep_conf);
4798+ asic3_set_gpio_sleepconf_b(dev, 0xffff,
4799+ pdata->gpio_b.sleep_conf);
4800+ asic3_set_gpio_sleepconf_c(dev, 0xffff,
4801+ pdata->gpio_c.sleep_conf);
4802+ asic3_set_gpio_sleepconf_d(dev, 0xffff,
4803+ pdata->gpio_d.sleep_conf);
4804+
4805+ asic3_set_gpio_alt_fn_a(dev, 0xffff,
4806+ pdata->gpio_a.alt_function);
4807+ asic3_set_gpio_alt_fn_b(dev, 0xffff,
4808+ pdata->gpio_b.alt_function);
4809+ asic3_set_gpio_alt_fn_c(dev, 0xffff,
4810+ pdata->gpio_c.alt_function);
4811+ asic3_set_gpio_alt_fn_d(dev, 0xffff,
4812+ pdata->gpio_d.alt_function);
4813+ }
4814+
4815+ asic->irq_nr = -1;
4816+ asic->irq_base = -1;
4817+
4818+ if (pdev->num_resources > 1)
4819+ asic->irq_nr = pdev->resource[1].start;
4820+
4821+ if (asic->irq_nr != -1) {
4822+ unsigned int i;
4823+
4824+ if (!pdata->irq_base) {
4825+ printk(KERN_ERR "asic3: IRQ base not specified\n");
4826+ asic3_remove(pdev);
4827+ return -EINVAL;
4828+ }
4829+
4830+ asic->irq_base = pdata->irq_base;
4831+
4832+ /* turn on clock to IRQ controller */
4833+ clksel |= CLOCK_SEL_CX;
4834+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL),
4835+ clksel);
4836+
4837+ printk(KERN_INFO "asic3: using irq %d-%d on irq %d\n",
4838+ asic->irq_base, asic->irq_base + ASIC3_NR_IRQS - 1,
4839+ asic->irq_nr);
4840+
4841+ for (i = 0 ; i < ASIC3_NR_IRQS ; i++) {
4842+ int irq = i + asic->irq_base;
4843+ if (i < ASIC3_NR_GPIO_IRQS) {
4844+ set_irq_chip(irq, &asic3_gpio_irq_chip);
4845+ set_irq_chip_data(irq, asic);
4846+ set_irq_handler(irq, handle_level_irq);
4847+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
4848+ } else {
4849+ /* The remaining IRQs are not GPIO */
4850+ set_irq_chip(irq, &asic3_irq_chip);
4851+ set_irq_chip_data(irq, asic);
4852+ set_irq_handler(irq, handle_level_irq);
4853+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
4854+ }
4855+ }
4856+
4857+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask),
4858+ ASIC3_INTMASK_GINTMASK);
4859+
4860+ set_irq_chained_handler(asic->irq_nr, asic3_irq_demux);
4861+ set_irq_type(asic->irq_nr, IRQT_RISING);
4862+ set_irq_data(asic->irq_nr, asic);
4863+ }
4864+
4865+#ifdef CONFIG_HTC_ASIC3_DS1WM
4866+ ds1wm_pd.bus_shift = asic->bus_shift;
4867+#endif
4868+
4869+ pdata->gpiodev_ops.get = asic3_gpio_get_value;
4870+ pdata->gpiodev_ops.set = asic3_gpio_set_value;
4871+ pdata->gpiodev_ops.to_irq = asic3_gpio_to_irq;
4872+
4873+ soc_add_devices(pdev, asic3_blocks, ARRAY_SIZE(asic3_blocks),
4874+ &pdev->resource[0],
4875+ asic->bus_shift - ASIC3_DEFAULT_ADDR_SHIFT,
4876+ asic->irq_base);
4877+
4878+ if (pdev->num_resources > 2) {
4879+ int rc;
4880+ rc = asic3_register_mmc(dev);
4881+ if (rc) {
4882+ asic3_remove(pdev);
4883+ return rc;
4884+ }
4885+ }
4886+
4887+ if (pdata && pdata->num_child_platform_devs != 0)
4888+ platform_add_devices(pdata->child_platform_devs,
4889+ pdata->num_child_platform_devs);
4890+
4891+ return 0;
4892+}
4893+
4894+static int asic3_remove(struct platform_device *pdev)
4895+{
4896+ struct asic3_platform_data *pdata = pdev->dev.platform_data;
4897+ struct asic3_data *asic = platform_get_drvdata(pdev);
4898+ int i;
4899+
4900+ if (pdata && pdata->num_child_platform_devs != 0) {
4901+ for (i = 0; i < pdata->num_child_platform_devs; i++) {
4902+ platform_device_unregister(
4903+ pdata->child_platform_devs[i]);
4904+ }
4905+ }
4906+
4907+ if (asic->irq_nr != -1) {
4908+ unsigned int i;
4909+
4910+ for (i = 0 ; i < ASIC3_NR_IRQS ; i++) {
4911+ int irq = i + asic->irq_base;
4912+ set_irq_flags(irq, 0);
4913+ set_irq_handler (irq, NULL);
4914+ set_irq_chip (irq, NULL);
4915+ set_irq_chip_data(irq, NULL);
4916+ }
4917+
4918+ set_irq_chained_handler(asic->irq_nr, NULL);
4919+ }
4920+
4921+ if (asic->mmc_dev)
4922+ asic3_unregister_mmc(&pdev->dev);
4923+
4924+ for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++)
4925+ clk_unregister(&asic3_clocks[i]);
4926+ clk_unregister(&clk_g);
4927+
4928+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), 0);
4929+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask), 0);
4930+
4931+ iounmap(asic->mapping);
4932+
4933+ kfree(asic);
4934+
4935+ return 0;
4936+}
4937+
4938+static void asic3_shutdown(struct platform_device *pdev)
4939+{
4940+}
4941+
4942+#define ASIC3_SUSPEND_CDEX_MASK \
4943+ (CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2)
4944+static unsigned short suspend_cdex;
4945+
4946+static int asic3_suspend(struct platform_device *pdev, pm_message_t state)
4947+{
4948+ struct asic3_data *asic = platform_get_drvdata(pdev);
4949+ suspend_cdex = __asic3_read_register(asic,
4950+ _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX);
4951+ /* The LEDs are still active during suspend */
4952+ __asic3_write_register(asic,
4953+ _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX,
4954+ suspend_cdex & ASIC3_SUSPEND_CDEX_MASK);
4955+ return 0;
4956+}
4957+
4958+static int asic3_resume(struct platform_device *pdev)
4959+{
4960+ struct asic3_data *asic = platform_get_drvdata(pdev);
4961+ unsigned short intmask;
4962+
4963+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX),
4964+ suspend_cdex);
4965+
4966+ if (asic->irq_nr != -1) {
4967+ /* Toggle the interrupt mask to try to get ASIC3 to show
4968+ * the CPU an interrupt edge. For more details see the
4969+ * kernel-discuss thread around 13 June 2005 with the
4970+ * subject "asic3 suspend / resume". */
4971+ intmask = __asic3_read_register(asic,
4972+ IPAQ_ASIC3_OFFSET(INTR, IntMask));
4973+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask),
4974+ intmask & ~ASIC3_INTMASK_GINTMASK);
4975+ mdelay(1);
4976+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask),
4977+ intmask | ASIC3_INTMASK_GINTMASK);
4978+ }
4979+
4980+ return 0;
4981+}
4982+
4983+static struct platform_driver asic3_device_driver = {
4984+ .driver = {
4985+ .name = "asic3",
4986+ },
4987+ .probe = asic3_probe,
4988+ .remove = asic3_remove,
4989+ .suspend = asic3_suspend,
4990+ .resume = asic3_resume,
4991+ .shutdown = asic3_shutdown,
4992+};
4993+
4994+static int __init asic3_base_init(void)
4995+{
4996+ int retval = 0;
4997+ retval = platform_driver_register(&asic3_device_driver);
4998+ return retval;
4999+}
5000+
5001+static void __exit asic3_base_exit(void)
5002+{
5003+ platform_driver_unregister(&asic3_device_driver);
5004+}
5005+
5006+#ifdef MODULE
5007+module_init(asic3_base_init);
5008+#else /* start early for dependencies */
5009+subsys_initcall(asic3_base_init);
5010+#endif
5011+module_exit(asic3_base_exit);
5012+
5013+MODULE_LICENSE("GPL");
5014+MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
5015+MODULE_DESCRIPTION("Core driver for HTC ASIC3");
5016+MODULE_SUPPORTED_DEVICE("asic3");
5017Index: linux-2.6.22/drivers/mfd/soc-core.c
5018===================================================================
5019--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5020+++ linux-2.6.22/drivers/mfd/soc-core.c 2007-09-11 12:53:37.000000000 +0200
5021@@ -0,0 +1,106 @@
5022+/*
5023+ * drivers/soc/soc-core.c
5024+ *
5025+ * core SoC support
5026+ * Copyright (c) 2006 Ian Molton
5027+ *
5028+ * This program is free software; you can redistribute it and/or modify
5029+ * it under the terms of the GNU General Public License version 2 as
5030+ * published by the Free Software Foundation.
5031+ *
5032+ * This file contains functionality used by many SoC type devices.
5033+ *
5034+ * Created: 2006-11-28
5035+ *
5036+ */
5037+
5038+#include <linux/ioport.h>
5039+#include <linux/slab.h>
5040+#include <linux/kernel.h>
5041+#include <linux/platform_device.h>
5042+#include "soc-core.h"
5043+
5044+void soc_free_devices(struct platform_device *devices, int nr_devs)
5045+{
5046+ struct platform_device *dev = devices;
5047+ int i;
5048+
5049+ for (i = 0; i < nr_devs; i++) {
5050+ struct resource *res = dev->resource;
5051+ platform_device_unregister(dev++);
5052+ kfree(res);
5053+ }
5054+ kfree(devices);
5055+}
5056+EXPORT_SYMBOL_GPL(soc_free_devices);
5057+
5058+#define SIGNED_SHIFT(val, shift) ((shift) >= 0 ? ((val) << (shift)) : ((val) >> -(shift)))
5059+
5060+struct platform_device *soc_add_devices(struct platform_device *dev,
5061+ struct soc_device_data *soc, int nr_devs,
5062+ struct resource *mem,
5063+ int relative_addr_shift, int irq_base)
5064+{
5065+ struct platform_device *devices;
5066+ int i, r, base;
5067+
5068+ devices = kzalloc(nr_devs * sizeof(struct platform_device), GFP_KERNEL);
5069+ if (!devices)
5070+ return NULL;
5071+
5072+ for (i = 0; i < nr_devs; i++) {
5073+ struct platform_device *sdev = &devices[i];
5074+ struct soc_device_data *blk = &soc[i];
5075+ struct resource *res;
5076+
5077+ sdev->id = -1;
5078+ sdev->name = blk->name;
5079+
5080+ sdev->dev.parent = &dev->dev;
5081+ sdev->dev.platform_data = (void *)blk->hwconfig;
5082+ sdev->num_resources = blk->num_resources;
5083+
5084+ /* Allocate space for the subdevice resources */
5085+ res = kzalloc (blk->num_resources * sizeof (struct resource), GFP_KERNEL);
5086+ if (!res)
5087+ goto fail;
5088+
5089+ for (r = 0 ; r < blk->num_resources ; r++) {
5090+ res[r].name = blk->res[r].name; // Fixme - should copy
5091+
5092+ /* Find out base to use */
5093+ base = 0;
5094+ if (blk->res[r].flags & IORESOURCE_MEM) {
5095+ base = mem->start;
5096+ } else if ((blk->res[r].flags & IORESOURCE_IRQ) &&
5097+ (blk->res[r].flags & IORESOURCE_IRQ_SOC_SUBDEVICE)) {
5098+ base = irq_base;
5099+ }
5100+
5101+ /* Adjust resource */
5102+ if (blk->res[r].flags & IORESOURCE_MEM) {
5103+ res[r].parent = mem;
5104+ res[r].start = base + SIGNED_SHIFT(blk->res[r].start, relative_addr_shift);
5105+ res[r].end = base + SIGNED_SHIFT(blk->res[r].end, relative_addr_shift);
5106+ } else {
5107+ res[r].start = base + blk->res[r].start;
5108+ res[r].end = base + blk->res[r].end;
5109+ }
5110+ res[r].flags = blk->res[r].flags;
5111+ }
5112+
5113+ sdev->resource = res;
5114+ if (platform_device_register(sdev)) {
5115+ kfree(res);
5116+ goto fail;
5117+ }
5118+
5119+ printk(KERN_INFO "SoC: registering %s\n", blk->name);
5120+ }
5121+ return devices;
5122+
5123+fail:
5124+ soc_free_devices(devices, i + 1);
5125+ return NULL;
5126+}
5127+EXPORT_SYMBOL_GPL(soc_add_devices);
5128Index: linux-2.6.22/drivers/mfd/soc-core.h
5129===================================================================
5130--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5131+++ linux-2.6.22/drivers/mfd/soc-core.h 2007-09-11 12:53:37.000000000 +0200
5132@@ -0,0 +1,30 @@
5133+/*
5134+ * drivers/soc/soc-core.h
5135+ *
5136+ * core SoC support
5137+ * Copyright (c) 2006 Ian Molton
5138+ *
5139+ * This program is free software; you can redistribute it and/or modify
5140+ * it under the terms of the GNU General Public License version 2 as
5141+ * published by the Free Software Foundation.
5142+ *
5143+ * This file contains prototypes for the functions in soc-core.c
5144+ *
5145+ * Created: 2006-11-28
5146+ *
5147+ */
5148+
5149+struct soc_device_data {
5150+ char *name;
5151+ struct resource *res;
5152+ int num_resources;
5153+ void *hwconfig; /* platform_data to pass to the subdevice */
5154+};
5155+
5156+struct platform_device *soc_add_devices(struct platform_device *dev,
5157+ struct soc_device_data *soc, int n_devs,
5158+ struct resource *mem,
5159+ int relative_addr_shift, int irq_base);
5160+
5161+void soc_free_devices(struct platform_device *devices, int nr_devs);
5162+
5163Index: linux-2.6.22/include/asm-arm/arch-pxa/clock.h
5164===================================================================
5165--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5166+++ linux-2.6.22/include/asm-arm/arch-pxa/clock.h 2007-09-11 12:53:37.000000000 +0200
5167@@ -0,0 +1,27 @@
5168+/*
5169+ * linux/include/asm-arm/arch-pxa/clock.h
5170+ *
5171+ * Copyright (C) 2006 Erik Hovland
5172+ *
5173+ * This program is free software; you can redistribute it and/or modify
5174+ * it under the terms of the GNU General Public License version 2 as
5175+ * published by the Free Software Foundation.
5176+ */
5177+
5178+struct clk {
5179+ struct list_head node;
5180+ struct module *owner;
5181+ struct clk *parent;
5182+ const char *name;
5183+ int id;
5184+ unsigned int enabled;
5185+ unsigned long rate;
5186+ unsigned long ctrlbit;
5187+
5188+ void (*enable)(struct clk *);
5189+ void (*disable)(struct clk *);
5190+};
5191+
5192+
5193+extern int clk_register(struct clk *clk);
5194+extern void clk_unregister(struct clk *clk);
5195Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h
5196===================================================================
5197--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5198+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h 2007-09-11 12:53:37.000000000 +0200
5199@@ -0,0 +1,213 @@
5200+/*
5201+ * include/asm/arm/arch-pxa/htcuniversal-asic.h
5202+ *
5203+ * Authors: Giuseppe Zompatori <giuseppe_zompatori@yahoo.it>
5204+ *
5205+ * based on previews work, see below:
5206+ *
5207+ * include/asm/arm/arch-pxa/hx4700-asic.h
5208+ * Copyright (c) 2004 SDG Systems, LLC
5209+ *
5210+ */
5211+
5212+#ifndef _HTCUNIVERSAL_ASIC_H_
5213+#define _HTCUNIVERSAL_ASIC_H_
5214+
5215+#include <asm/hardware/ipaq-asic3.h>
5216+
5217+/* ASIC3 */
5218+
5219+#define HTCUNIVERSAL_ASIC3_GPIO_PHYS PXA_CS4_PHYS
5220+#define HTCUNIVERSAL_ASIC3_MMC_PHYS PXA_CS3_PHYS
5221+
5222+/* TODO: some information is missing here */
5223+
5224+/* ASIC3 GPIO A bank */
5225+
5226+#define GPIOA_I2C_EN 0 /* Output */
5227+#define GPIOA_SPK_PWR1_ON 1 /* Output */
5228+#define GPIOA_AUDIO_PWR_ON 2 /* Output */
5229+#define GPIOA_EARPHONE_PWR_ON 3 /* Output */
5230+
5231+#define GPIOA_UNKNOWN4 4 /* Output */
5232+#define GPIOA_BUTTON_BACKLIGHT_N 5 /* Input */
5233+#define GPIOA_SPK_PWR2_ON 6 /* Output */
5234+#define GPIOA_BUTTON_RECORD_N 7 /* Input */
5235+
5236+#define GPIOA_BUTTON_CAMERA_N 8 /* Input */
5237+#define GPIOA_UNKNOWN9 9 /* Output */
5238+#define GPIOA_FLASHLIGHT 10 /* Output */
5239+#define GPIOA_COVER_ROTATE_N 11 /* Input */
5240+
5241+#define GPIOA_TOUCHSCREEN_N 12 /* Input */
5242+#define GPIOA_VOL_UP_N 13 /* Input */
5243+#define GPIOA_VOL_DOWN_N 14 /* Input */
5244+#define GPIOA_LCD_PWR5_ON 15 /* Output */
5245+
5246+/* ASIC3 GPIO B bank */
5247+
5248+#define GPIOB_BB_READY 0 /* Input */
5249+#define GPIOB_CODEC_PDN 1 /* Output */
5250+#define GPIOB_UNKNOWN2 2 /* Input */
5251+#define GPIOB_BB_UNKNOWN3 3 /* Input */
5252+
5253+#define GPIOB_BT_IRQ 4 /* Input */
5254+#define GPIOB_CLAMSHELL_N 5 /* Input */
5255+#define GPIOB_LCD_PWR3_ON 6 /* Output */
5256+#define GPIOB_BB_ALERT 7 /* Input */
5257+
5258+#define GPIOB_BB_RESET2 8 /* Output */
5259+#define GPIOB_EARPHONE_N 9 /* Input */
5260+#define GPIOB_MICRECORD_N 10 /* Input */
5261+#define GPIOB_NIGHT_SENSOR 11 /* Input */
5262+
5263+#define GPIOB_UMTS_DCD 12 /* Input */
5264+#define GPIOB_UNKNOWN13 13 /* Input */
5265+#define GPIOB_CHARGE_EN 14 /* Output */
5266+#define GPIOB_USB_PUEN 15 /* Output */
5267+
5268+/* ASIC3 GPIO C bank */
5269+
5270+#define GPIOC_LED_BTWIFI 0 /* Output */
5271+#define GPIOC_LED_RED 1 /* Output */
5272+#define GPIOC_LED_GREEN 2 /* Output */
5273+#define GPIOC_BOARDID3 3 /* Input */
5274+
5275+#define GPIOC_WIFI_IRQ_N 4 /* Input */
5276+#define GPIOC_WIFI_RESET 5 /* Output */
5277+#define GPIOC_WIFI_PWR1_ON 6 /* Output */
5278+#define GPIOC_BT_RESET 7 /* Output */
5279+
5280+#define GPIOC_UNKNOWN8 8 /* Output */
5281+#define GPIOC_LCD_PWR1_ON 9 /* Output */
5282+#define GPIOC_LCD_PWR2_ON 10 /* Output */
5283+#define GPIOC_BOARDID2 11 /* Input */
5284+
5285+#define GPIOC_BOARDID1 12 /* Input */
5286+#define GPIOC_BOARDID0 13 /* Input */
5287+#define GPIOC_BT_PWR_ON 14 /* Output */
5288+#define GPIOC_CHARGE_ON 15 /* Output */
5289+
5290+/* ASIC3 GPIO D bank */
5291+
5292+#define GPIOD_KEY_OK_N 0 /* Input */
5293+#define GPIOD_KEY_RIGHT_N 1 /* Input */
5294+#define GPIOD_KEY_LEFT_N 2 /* Input */
5295+#define GPIOD_KEY_DOWN_N 3 /* Input */
5296+
5297+#define GPIOD_KEY_UP_N 4 /* Input */
5298+#define GPIOD_SDIO_DET 5 /* Input */
5299+#define GPIOD_WIFI_PWR2_ON 6 /* Output */
5300+#define GPIOD_HW_REBOOT 7 /* Output */
5301+
5302+#define GPIOD_BB_RESET1 8 /* Output */
5303+#define GPIOD_UNKNOWN9 9 /* Output */
5304+#define GPIOD_VIBRA_PWR_ON 10 /* Output */
5305+#define GPIOD_WIFI_PWR3_ON 11 /* Output */
5306+
5307+#define GPIOD_FL_PWR_ON 12 /* Output */
5308+#define GPIOD_LCD_PWR4_ON 13 /* Output */
5309+#define GPIOD_BL_KEYP_PWR_ON 14 /* Output */
5310+#define GPIOD_BL_KEYB_PWR_ON 15 /* Output */
5311+
5312+extern struct platform_device htcuniversal_asic3;
5313+
5314+/* ASIC3 GPIO A bank */
5315+
5316+#define GPIO_I2C_EN 0*16+GPIOA_I2C_EN
5317+#define GPIO_SPK_PWR1_ON 0*16+GPIOA_SPK_PWR1_ON
5318+#define GPIO_AUDIO_PWR_ON 0*16+GPIOA_AUDIO_PWR_ON
5319+#define GPIO_EARPHONE_PWR_ON 0*16+GPIOA_EARPHONE_PWR_ON
5320+
5321+#define GPIO_UNKNOWNA4 0*16+GPIOA_UNKNOWN4
5322+#define GPIO_BUTTON_BACKLIGHT_N 0*16+GPIOA_BUTTON_BACKLIGHT_N
5323+#define GPIO_SPK_PWR2_ON 0*16+GPIOA_SPK_PWR2_ON
5324+#define GPIO_BUTTON_RECORD_N 0*16+GPIOA_BUTTON_RECORD_N
5325+
5326+#define GPIO_BUTTON_CAMERA_N 0*16+GPIOA_BUTTON_CAMERA_N
5327+#define GPIO_UNKNOWNA9 0*16+GPIOA_UNKNOWN9
5328+#define GPIO_FLASHLIGHT 0*16+GPIOA_FLASHLIGHT
5329+#define GPIO_COVER_ROTATE_N 0*16+GPIOA_COVER_ROTATE_N
5330+
5331+#define GPIO_TOUCHSCREEN_N 0*16+GPIOA_TOUCHSCREEN_N
5332+#define GPIO_VOL_UP_N 0*16+GPIOA_VOL_UP_N
5333+#define GPIO_VOL_DOWN_N 0*16+GPIOA_VOL_DOWN_N
5334+#define GPIO_LCD_PWR5_ON 0*16+GPIOA_LCD_PWR5_ON
5335+
5336+/* ASIC3 GPIO B bank */
5337+
5338+#define GPIO_BB_READY 1*16+GPIOB_BB_READY
5339+#define GPIO_CODEC_PDN 1*16+GPIOB_CODEC_PDN
5340+#define GPIO_UNKNOWNB2 1*16+GPIOB_UNKNOWN2
5341+#define GPIO_BB_UNKNOWN3 1*16+GPIOB_BB_UNKNOWN3
5342+
5343+#define GPIO_BT_IRQ 1*16+GPIOB_BT_IRQ
5344+#define GPIO_CLAMSHELL_N 1*16+GPIOB_CLAMSHELL_N
5345+#define GPIO_LCD_PWR3_ON 1*16+GPIOB_LCD_PWR3_ON
5346+#define GPIO_BB_ALERT 1*16+GPIOB_BB_ALERT
5347+
5348+#define GPIO_BB_RESET2 1*16+GPIOB_BB_RESET2
5349+#define GPIO_EARPHONE_N 1*16+GPIOB_EARPHONE_N
5350+#define GPIO_MICRECORD_N 1*16+GPIOB_MICRECORD_N
5351+#define GPIO_NIGHT_SENSOR 1*16+GPIOB_NIGHT_SENSOR
5352+
5353+#define GPIO_UMTS_DCD 1*16+GPIOB_UMTS_DCD
5354+#define GPIO_UNKNOWNB13 1*16+GPIOB_UNKNOWN13
5355+#define GPIO_CHARGE_EN 1*16+GPIOB_CHARGE_EN
5356+#define GPIO_USB_PUEN 1*16+GPIOB_USB_PUEN
5357+
5358+/* ASIC3 GPIO C bank */
5359+
5360+#define GPIO_LED_BTWIFI 2*16+GPIOC_LED_BTWIFI
5361+#define GPIO_LED_RED 2*16+GPIOC_LED_RED
5362+#define GPIO_LED_GREEN 2*16+GPIOC_LED_GREEN
5363+#define GPIO_BOARDID3 2*16+GPIOC_BOARDID3
5364+
5365+#define GPIO_WIFI_IRQ_N 2*16+GPIOC_WIFI_IRQ_N
5366+#define GPIO_WIFI_RESET 2*16+GPIOC_WIFI_RESET
5367+#define GPIO_WIFI_PWR1_ON 2*16+GPIOC_WIFI_PWR1_ON
5368+#define GPIO_BT_RESET 2*16+GPIOC_BT_RESET
5369+
5370+#define GPIO_UNKNOWNC8 2*16+GPIOC_UNKNOWN8
5371+#define GPIO_LCD_PWR1_ON 2*16+GPIOC_LCD_PWR1_ON
5372+#define GPIO_LCD_PWR2_ON 2*16+GPIOC_LCD_PWR2_ON
5373+#define GPIO_BOARDID2 2*16+GPIOC_BOARDID2
5374+
5375+#define GPIO_BOARDID1 2*16+GPIOC_BOARDID1
5376+#define GPIO_BOARDID0 2*16+GPIOC_BOARDID0
5377+#define GPIO_BT_PWR_ON 2*16+GPIOC_BT_PWR_ON
5378+#define GPIO_CHARGE_ON 2*16+GPIOC_CHARGE_ON
5379+
5380+/* ASIC3 GPIO D bank */
5381+
5382+#define GPIO_KEY_OK_N 3*16+GPIOD_KEY_OK_N
5383+#define GPIO_KEY_RIGHT_N 3*16+GPIOD_KEY_RIGHT_N
5384+#define GPIO_KEY_LEFT_N 3*16+GPIOD_KEY_LEFT_N
5385+#define GPIO_KEY_DOWN_N 3*16+GPIOD_KEY_DOWN_N
5386+
5387+#define GPIO_KEY_UP_N 3*16+GPIOD_KEY_UP_N
5388+#define GPIO_SDIO_DET 3*16+GPIOD_SDIO_DET
5389+#define GPIO_WIFI_PWR2_ON 3*16+GPIOD_WIFI_PWR2_ON
5390+#define GPIO_HW_REBOOT 3*16+GPIOD_HW_REBOOT
5391+
5392+#define GPIO_BB_RESET1 3*16+GPIOD_BB_RESET1
5393+#define GPIO_UNKNOWND9 3*16+GPIOD_UNKNOWN9
5394+#define GPIO_VIBRA_PWR_ON 3*16+GPIOD_VIBRA_PWR_ON
5395+#define GPIO_WIFI_PWR3_ON 3*16+GPIOD_WIFI_PWR3_ON
5396+
5397+#define GPIO_FL_PWR_ON 3*16+GPIOD_FL_PWR_ON
5398+#define GPIO_LCD_PWR4_ON 3*16+GPIOD_LCD_PWR4_ON
5399+#define GPIO_BL_KEYP_PWR_ON 3*16+GPIOD_BL_KEYP_PWR_ON
5400+#define GPIO_BL_KEYB_PWR_ON 3*16+GPIOD_BL_KEYB_PWR_ON
5401+
5402+#define HTCUNIVERSAL_EGPIO_BASE PXA_CS2_PHYS+0x02000000
5403+
5404+#define EGPIO4_ON 4 /* something */
5405+#define EGPIO5_BT_3V3_ON 5 /* Bluetooth related */
5406+#define EGPIO6_WIFI_ON 6 /* WLAN related*/
5407+
5408+extern void htcuniversal_egpio_enable( u_int16_t bits );
5409+extern void htcuniversal_egpio_disable( u_int16_t bits );
5410+
5411+#endif /* _HTCUNIVERSAL_ASIC_H_ */
5412+
5413Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h
5414===================================================================
5415--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5416+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h 2007-09-11 12:53:37.000000000 +0200
5417@@ -0,0 +1,220 @@
5418+/*
5419+ * include/asm-arm/arch-pxa/htcuniversal-gpio.h
5420+ * History:
5421+ *
5422+ * 2004-12-10 Michael Opdenacker. Wrote down GPIO settings as identified by Jamey Hicks.
5423+ * Reused the h2200-gpio.h file as a template.
5424+ */
5425+
5426+#ifndef _HTCUNIVERSAL_GPIO_H_
5427+#define _HTCUNIVERSAL_GPIO_H_
5428+
5429+#include <asm/arch/pxa-regs.h>
5430+
5431+#define GET_HTCUNIVERSAL_GPIO(gpio) \
5432+ (GPLR(GPIO_NR_HTCUNIVERSAL_ ## gpio) & GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio))
5433+
5434+#define SET_HTCUNIVERSAL_GPIO(gpio, setp) \
5435+do { \
5436+if (setp) \
5437+ GPSR(GPIO_NR_HTCUNIVERSAL_ ## gpio) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio); \
5438+else \
5439+ GPCR(GPIO_NR_HTCUNIVERSAL_ ## gpio) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio); \
5440+} while (0)
5441+
5442+#define SET_HTCUNIVERSAL_GPIO_N(gpio, setp) \
5443+do { \
5444+if (setp) \
5445+ GPCR(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N); \
5446+else \
5447+ GPSR(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N); \
5448+} while (0)
5449+
5450+#define HTCUNIVERSAL_IRQ(gpio) \
5451+ IRQ_GPIO(GPIO_NR_HTCUNIVERSAL_ ## gpio)
5452+
5453+#define GPIO_NR_HTCUNIVERSAL_KEY_ON_N 0
5454+#define GPIO_NR_HTCUNIVERSAL_GP_RST_N 1
5455+
5456+#define GPIO_NR_HTCUNIVERSAL_USB_DET 9
5457+#define GPIO_NR_HTCUNIVERSAL_POWER_DET 10
5458+
5459+#define GPIO_NR_HTCUNIVERSAL_CIF_DD7 12
5460+#define GPIO_NR_HTCUNIVERSAL_ASIC3_SDIO_INT_N 13
5461+#define GPIO_NR_HTCUNIVERSAL_ASIC3_EXT_INT 14
5462+#define GPIO_NR_HTCUNIVERSAL_CS1_N 15
5463+
5464+#define GPIO_NR_HTCUNIVERSAL_CIF_DD6 17
5465+#define GPIO_NR_HTCUNIVERSAL_RDY 18
5466+
5467+#define GPIO_NR_HTCUNIVERSAL_PHONE_START 19
5468+
5469+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT7 22
5470+#define GPIO_NR_HTCUNIVERSAL_SPI_CLK 23
5471+#define GPIO_NR_HTCUNIVERSAL_SPI_FRM 24
5472+#define GPIO_NR_HTCUNIVERSAL_SPI_DO 25
5473+#define GPIO_NR_HTCUNIVERSAL_SPI_DI 26
5474+
5475+#define GPIO_NR_HTCUNIVERSAL_CODEC_ON 27
5476+#define GPIO_NR_HTCUNIVERSAL_I2S_BCK 28
5477+#define GPIO_NR_HTCUNIVERSAL_I2S_DIN 29
5478+#define GPIO_NR_HTCUNIVERSAL_I2S_DOUT 30
5479+#define GPIO_NR_HTCUNIVERSAL_I2S_SYNC 31
5480+
5481+#define GPIO_NR_HTCUNIVERSAL_RS232_ON 32
5482+#define GPIO_NR_HTCUNIVERSAL_CS5_N 33
5483+
5484+#define GPIO_NR_HTCUNIVERSAL_PHONE_RXD 34
5485+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS 35
5486+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN7 36
5487+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN3 37
5488+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN4 38
5489+#define GPIO_NR_HTCUNIVERSAL_PHONE_TXD 39
5490+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT6 40
5491+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS 41
5492+#define GPIO_NR_HTCUNIVERSAL_BT_RXD 42
5493+#define GPIO_NR_HTCUNIVERSAL_BT_TXD 43
5494+#define GPIO_NR_HTCUNIVERSAL_BT_UART_CTS 44
5495+#define GPIO_NR_HTCUNIVERSAL_BT_UART_RTS 45
5496+
5497+#define GPIO_NR_HTCUNIVERSAL_SIR_RXD 42
5498+#define GPIO_NR_HTCUNIVERSAL_SIR_TXD 43
5499+
5500+#define GPIO_NR_HTCUNIVERSAL_POE_N 48
5501+#define GPIO_NR_HTCUNIVERSAL_PWE_N 49
5502+#define GPIO_NR_HTCUNIVERSAL_CIF_DD3 50
5503+#define GPIO_NR_HTCUNIVERSAL_CIF_DD2 51
5504+#define GPIO_NR_HTCUNIVERSAL_CIF_DD4 52
5505+
5506+#define GPIO_NR_HTCUNIVERSAL_CIF_MCLK 53
5507+#define GPIO_NR_HTCUNIVERSAL_CIF_PCLK 54
5508+#define GPIO_NR_HTCUNIVERSAL_CIF_DD1 55
5509+
5510+#define GPIO_NR_HTCUNIVERSAL_LDD0 58
5511+#define GPIO_NR_HTCUNIVERSAL_LDD1 59
5512+#define GPIO_NR_HTCUNIVERSAL_LDD2 60
5513+#define GPIO_NR_HTCUNIVERSAL_LDD3 61
5514+#define GPIO_NR_HTCUNIVERSAL_LDD4 62
5515+#define GPIO_NR_HTCUNIVERSAL_LDD5 63
5516+#define GPIO_NR_HTCUNIVERSAL_LDD6 64
5517+#define GPIO_NR_HTCUNIVERSAL_LDD7 65
5518+#define GPIO_NR_HTCUNIVERSAL_LDD8 66
5519+#define GPIO_NR_HTCUNIVERSAL_LDD9 67
5520+#define GPIO_NR_HTCUNIVERSAL_LDD10 68
5521+#define GPIO_NR_HTCUNIVERSAL_LDD11 69
5522+#define GPIO_NR_HTCUNIVERSAL_LDD12 70
5523+#define GPIO_NR_HTCUNIVERSAL_LDD13 71
5524+#define GPIO_NR_HTCUNIVERSAL_LDD14 72
5525+#define GPIO_NR_HTCUNIVERSAL_LDD15 73
5526+
5527+#define GPIO_NR_HTCUNIVERSAL_LFCLK_RD 74
5528+#define GPIO_NR_HTCUNIVERSAL_LFCLK_A0 75
5529+#define GPIO_NR_HTCUNIVERSAL_LFCLK_WR 76
5530+#define GPIO_NR_HTCUNIVERSAL_LBIAS 77
5531+
5532+#define GPIO_NR_HTCUNIVERSAL_CS2_N 78
5533+#define GPIO_NR_HTCUNIVERSAL_CS3_N 79
5534+#define GPIO_NR_HTCUNIVERSAL_CS4_N 80
5535+#define GPIO_NR_HTCUNIVERSAL_CIF_DD0 81
5536+#define GPIO_NR_HTCUNIVERSAL_CIF_DD5 82
5537+
5538+#define GPIO_NR_HTCUNIVERSAL_CIF_LV 84
5539+#define GPIO_NR_HTCUNIVERSAL_CIF_FV 85
5540+
5541+#define GPIO_NR_HTCUNIVERSAL_LCD1 86
5542+#define GPIO_NR_HTCUNIVERSAL_LCD2 87
5543+
5544+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN5 90
5545+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN6 91
5546+
5547+#define GPIO_NR_HTCUNIVERSAL_DREQ1 97
5548+
5549+#define GPIO_NR_HTCUNIVERSAL_PHONE_RESET 98
5550+
5551+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN0 100
5552+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN1 101
5553+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN2 102
5554+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT0 103
5555+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT1 104
5556+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT2 105
5557+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT3 106
5558+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT4 107
5559+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT5 108
5560+
5561+#define GPIO_NR_HTCUNIVERSAL_PHONE_UNKNOWN 109
5562+#define GPIO_NR_HTCUNIVERSAL_PHONE_OFF 110
5563+
5564+#define GPIO_NR_HTCUNIVERSAL_USB_PUEN 112
5565+#define GPIO_NR_HTCUNIVERSAL_I2S_SYSCLK 113
5566+
5567+#define GPIO_NR_HTCUNIVERSAL_PWM_OUT1 115
5568+
5569+#define GPIO_NR_HTCUNIVERSAL_I2C_SCL 117
5570+#define GPIO_NR_HTCUNIVERSAL_I2C_SDA 118
5571+
5572+#if 0
5573+#define GPIO_NR_HTCUNIVERSAL_CPU_BATT_FAULT_N
5574+#define GPIO_NR_HTCUNIVERSAL_ASIC3_RESET_N
5575+#define GPIO_NR_HTCUNIVERSAL_CHARGE_EN_N
5576+#define GPIO_NR_HTCUNIVERSAL_FLASH_VPEN
5577+#define GPIO_NR_HTCUNIVERSAL_BATT_OFF
5578+#define GPIO_NR_HTCUNIVERSAL_USB_CHARGE_RATE
5579+#define GPIO_NR_HTCUNIVERSAL_BL_DETECT_N
5580+#define GPIO_NR_HTCUNIVERSAL_CPU_HW_RESET_N
5581+#endif
5582+
5583+
5584+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_CLK_MD (23 | GPIO_ALT_FN_2_OUT)
5585+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_FRM_MD (24 | GPIO_ALT_FN_2_OUT)
5586+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DO_MD (25 | GPIO_ALT_FN_2_OUT)
5587+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DI_MD (26 | GPIO_ALT_FN_1_IN)
5588+
5589+#define GPIO_NR_HTCUNIVERSAL_I2S_BCK_MD (28 | GPIO_ALT_FN_1_OUT)
5590+#define GPIO_NR_HTCUNIVERSAL_I2S_DIN_MD (29 | GPIO_ALT_FN_2_IN)
5591+#define GPIO_NR_HTCUNIVERSAL_I2S_DOUT_MD (30 | GPIO_ALT_FN_1_OUT)
5592+#define GPIO_NR_HTCUNIVERSAL_I2S_SYNC_MD (31 | GPIO_ALT_FN_1_OUT)
5593+
5594+#define GPIO_NR_HTCUNIVERSAL_PHONE_RXD_MD (34 | GPIO_ALT_FN_1_IN)
5595+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS_MD (35 | GPIO_ALT_FN_1_IN)
5596+
5597+#define GPIO_NR_HTCUNIVERSAL_PHONE_TXD_MD (39 | GPIO_ALT_FN_2_OUT)
5598+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS_MD (41 | GPIO_ALT_FN_2_OUT)
5599+
5600+#define GPIO_NR_HTCUNIVERSAL_BT_RXD_MD (42 | GPIO_ALT_FN_1_IN)
5601+#define GPIO_NR_HTCUNIVERSAL_BT_TXD_MD (43 | GPIO_ALT_FN_2_OUT)
5602+#define GPIO_NR_HTCUNIVERSAL_BT_UART_CTS_MD (44 | GPIO_ALT_FN_1_IN)
5603+#define GPIO_NR_HTCUNIVERSAL_BT_UART_RTS_MD (45 | GPIO_ALT_FN_2_OUT)
5604+
5605+#define GPIO_NR_HTCUNIVERSAL_SIR_RXD_MD (46 | GPIO_ALT_FN_2_IN)
5606+#define GPIO_NR_HTCUNIVERSAL_SIR_TXD_MD (47 | GPIO_ALT_FN_1_OUT)
5607+
5608+#define GPIO_NR_HTCUNIVERSAL_POE_N_MD (48 | GPIO_ALT_FN_2_OUT | GPIO_DFLT_HIGH)
5609+#define GPIO_NR_HTCUNIVERSAL_PWE_N_MD (49 | GPIO_ALT_FN_2_OUT | GPIO_DFLT_HIGH)
5610+
5611+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN0_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN0 | GPIO_ALT_FN_1_IN)
5612+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN1_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN1 | GPIO_ALT_FN_1_IN)
5613+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN2_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN2 | GPIO_ALT_FN_1_IN)
5614+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN3_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN3 | GPIO_ALT_FN_3_IN)
5615+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN4_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN4 | GPIO_ALT_FN_2_IN)
5616+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN5_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN5 | GPIO_ALT_FN_1_IN)
5617+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN6_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN6 | GPIO_ALT_FN_1_IN)
5618+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN7_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN7 | GPIO_ALT_FN_3_IN)
5619+
5620+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT0_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT0 | GPIO_ALT_FN_2_OUT)
5621+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT1_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT1 | GPIO_ALT_FN_2_OUT)
5622+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT2_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT2 | GPIO_ALT_FN_2_OUT)
5623+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT3_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT3 | GPIO_ALT_FN_2_OUT)
5624+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT4_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT4 | GPIO_ALT_FN_2_OUT)
5625+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT5_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT5 | GPIO_ALT_FN_2_OUT)
5626+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT6_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT6 | GPIO_ALT_FN_1_OUT)
5627+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT7_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT7 | GPIO_ALT_FN_1_OUT)
5628+
5629+
5630+#define GPIO_NR_HTCUNIVERSAL_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT)
5631+
5632+#define GPIO_NR_HTCUNIVERSAL_PWM1OUT_MD (115 | GPIO_ALT_FN_3_OUT)
5633+
5634+#define GPIO_NR_HTCUNIVERSAL_I2C_SCL_MD (117 | GPIO_ALT_FN_1_OUT)
5635+#define GPIO_NR_HTCUNIVERSAL_I2C_SDA_MD (118 | GPIO_ALT_FN_1_OUT)
5636+
5637+#endif /* _HTCUNIVERSAL_GPIO_H */
5638Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h
5639===================================================================
5640--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5641+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h 2007-09-11 12:53:37.000000000 +0200
5642@@ -0,0 +1,14 @@
5643+/*
5644+ * include/asm/arm/arch-pxa/htcuniversal-init.h
5645+ * Copyright (c) 2004 SDG Systems, LLC
5646+ */
5647+
5648+#ifndef _HTCUNIVERSAL_INIT_H_
5649+#define _HTCUNIVERSAL_INIT_H_
5650+
5651+/* htcuniversal initialization data should be found here
5652+ * See -init.h files from other devices for details
5653+ */
5654+
5655+#endif /* _HTCUNIVERSAL_INIT_H_ */
5656+
5657Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h
5658===================================================================
5659--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5660+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h 2007-09-11 12:53:37.000000000 +0200
5661@@ -0,0 +1,3 @@
5662+#include <asm/arch/irqs.h>
5663+
5664+#define HTCUNIVERSAL_ASIC3_IRQ_BASE IRQ_BOARD_START
5665Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h
5666===================================================================
5667--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5668+++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h 2007-09-11 12:53:37.000000000 +0200
5669@@ -0,0 +1,6 @@
5670+struct pxa_ll_pm_ops {
5671+ void (*suspend)(unsigned long);
5672+ void (*resume)(void);
5673+};
5674+
5675+extern struct pxa_ll_pm_ops *pxa_pm_set_ll_ops(struct pxa_ll_pm_ops *new_ops);
5676Index: linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h
5677===================================================================
5678--- linux-2.6.22.orig/include/asm-arm/arch-pxa/sharpsl.h 2007-07-09 01:32:17.000000000 +0200
5679+++ linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h 2007-09-11 12:53:37.000000000 +0200
5680@@ -25,12 +25,6 @@
5681 /*
5682 * SharpSL Backlight
5683 */
5684-struct corgibl_machinfo {
5685- int max_intensity;
5686- int default_intensity;
5687- int limit_mask;
5688- void (*set_bl_intensity)(int intensity);
5689-};
5690 extern void corgibl_limit_intensity(int limit);
5691
5692
5693Index: linux-2.6.22/include/asm-arm/hardware/asic3_keys.h
5694===================================================================
5695--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5696+++ linux-2.6.22/include/asm-arm/hardware/asic3_keys.h 2007-09-11 12:53:37.000000000 +0200
5697@@ -0,0 +1,18 @@
5698+#include <linux/input.h>
5699+
5700+struct asic3_keys_button {
5701+ /* Configuration parameters */
5702+ int keycode;
5703+ int gpio;
5704+ int active_low;
5705+ char *desc;
5706+ int type;
5707+ /* Internal state vars - add below */
5708+};
5709+
5710+struct asic3_keys_platform_data {
5711+ struct asic3_keys_button *buttons;
5712+ int nbuttons;
5713+ struct input_dev *input;
5714+ struct device *asic3_dev;
5715+};
5716Index: linux-2.6.22/include/asm-arm/hardware/asic3_leds.h
5717===================================================================
5718--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5719+++ linux-2.6.22/include/asm-arm/hardware/asic3_leds.h 2007-09-11 12:53:37.000000000 +0200
5720@@ -0,0 +1,34 @@
5721+/*
5722+ * LEDs support for HTC ASIC3 devices.
5723+ *
5724+ * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru>
5725+ *
5726+ * This file is subject to the terms and conditions of the GNU General Public
5727+ * License. See the file COPYING in the main directory of this archive for
5728+ * more details.
5729+ *
5730+ */
5731+
5732+#include <linux/kernel.h>
5733+#include <linux/init.h>
5734+#include <linux/platform_device.h>
5735+#include <linux/leds.h>
5736+
5737+struct asic3_leds_machinfo;
5738+
5739+struct asic3_led {
5740+ struct led_classdev led_cdev;
5741+ int hw_num; /* Number of "hardware-accelerated" led */
5742+ int gpio_num; /* Number of GPIO if hw_num == -1 */
5743+ struct asic3_leds_machinfo *machinfo;
5744+};
5745+
5746+struct asic3_leds_machinfo {
5747+ int num_leds;
5748+ struct asic3_led *leds;
5749+ struct platform_device *asic3_pdev;
5750+};
5751+
5752+extern int asic3_leds_register(void);
5753+extern void asic3_leds_unregister(void);
5754+
5755Index: linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h
5756===================================================================
5757--- /dev/null 1970-01-01 00:00:00.000000000 +0000
5758+++ linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h 2007-09-11 12:53:37.000000000 +0200
5759@@ -0,0 +1,602 @@
5760+/*
5761+ *
5762+ * Definitions for the HTC ASIC3 chip found in several handheld devices
5763+ *
5764+ * Copyright 2001 Compaq Computer Corporation.
5765+ *
5766+ * This program is free software; you can redistribute it and/or modify
5767+ * it under the terms of the GNU General Public License as published by
5768+ * the Free Software Foundation; either version 2 of the License, or
5769+ * (at your option) any later version.
5770+ *
5771+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
5772+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
5773+ * FITNESS FOR ANY PARTICULAR PURPOSE.
5774+ *
5775+ * Author: Andrew Christian
5776+ *
5777+ */
5778+
5779+#ifndef IPAQ_ASIC3_H
5780+#define IPAQ_ASIC3_H
5781+
5782+/****************************************************/
5783+/* IPAQ, ASIC #3, replaces ASIC #1 */
5784+
5785+#define IPAQ_ASIC3_OFFSET(x,y) (_IPAQ_ASIC3_ ## x ## _Base + _IPAQ_ASIC3_ ## x ## _ ## y)
5786+#define IPAQ_ASIC3_GPIO_OFFSET(x,y) (_IPAQ_ASIC3_GPIO_ ## x ## _Base + _IPAQ_ASIC3_GPIO_ ## y)
5787+
5788+
5789+/* All offsets below are specified with the following address bus shift */
5790+#define ASIC3_DEFAULT_ADDR_SHIFT 2
5791+
5792+#define _IPAQ_ASIC3_GPIO_A_Base 0x0000
5793+#define _IPAQ_ASIC3_GPIO_B_Base 0x0100
5794+#define _IPAQ_ASIC3_GPIO_C_Base 0x0200
5795+#define _IPAQ_ASIC3_GPIO_D_Base 0x0300
5796+
5797+#define _IPAQ_ASIC3_GPIO_Mask 0x00 /* R/W 0:don't mask, 1:mask interrupt */
5798+#define _IPAQ_ASIC3_GPIO_Direction 0x04 /* R/W 0:input, 1:output */
5799+#define _IPAQ_ASIC3_GPIO_Out 0x08 /* R/W 0:output low, 1:output high */
5800+#define _IPAQ_ASIC3_GPIO_TriggerType 0x0c /* R/W 0:level, 1:edge */
5801+#define _IPAQ_ASIC3_GPIO_EdgeTrigger 0x10 /* R/W 0:falling, 1:rising */
5802+#define _IPAQ_ASIC3_GPIO_LevelTrigger 0x14 /* R/W 0:low, 1:high level detect */
5803+#define _IPAQ_ASIC3_GPIO_SleepMask 0x18 /* R/W 0:don't mask, 1:mask trigger in sleep mode */
5804+#define _IPAQ_ASIC3_GPIO_SleepOut 0x1c /* R/W level 0:low, 1:high in sleep mode */
5805+#define _IPAQ_ASIC3_GPIO_BattFaultOut 0x20 /* R/W level 0:low, 1:high in batt_fault */
5806+#define _IPAQ_ASIC3_GPIO_IntStatus 0x24 /* R/W 0:none, 1:detect */
5807+#define _IPAQ_ASIC3_GPIO_AltFunction 0x28 /* R/W 0:normal control 1:LED register control */
5808+#define _IPAQ_ASIC3_GPIO_SleepConf 0x2c /* R/W bit 1: autosleep 0: disable gposlpout in normal mode, enable gposlpout in sleep mode */
5809+#define _IPAQ_ASIC3_GPIO_Status 0x30 /* R Pin status */
5810+
5811+#define IPAQ_ASIC3_GPIO_A_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Mask )
5812+#define IPAQ_ASIC3_GPIO_A_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Direction )
5813+#define IPAQ_ASIC3_GPIO_A_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Out )
5814+#define IPAQ_ASIC3_GPIO_A_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, A, TriggerType )
5815+#define IPAQ_ASIC3_GPIO_A_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, A, EdgeTrigger )
5816+#define IPAQ_ASIC3_GPIO_A_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, A, LevelTrigger )
5817+#define IPAQ_ASIC3_GPIO_A_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepMask )
5818+#define IPAQ_ASIC3_GPIO_A_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepOut )
5819+#define IPAQ_ASIC3_GPIO_A_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, A, BattFaultOut )
5820+#define IPAQ_ASIC3_GPIO_A_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, A, IntStatus )
5821+#define IPAQ_ASIC3_GPIO_A_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, A, AltFunction )
5822+#define IPAQ_ASIC3_GPIO_A_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepConf )
5823+#define IPAQ_ASIC3_GPIO_A_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Status )
5824+
5825+#define IPAQ_ASIC3_GPIO_B_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Mask )
5826+#define IPAQ_ASIC3_GPIO_B_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Direction )
5827+#define IPAQ_ASIC3_GPIO_B_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Out )
5828+#define IPAQ_ASIC3_GPIO_B_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, B, TriggerType )
5829+#define IPAQ_ASIC3_GPIO_B_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, B, EdgeTrigger )
5830+#define IPAQ_ASIC3_GPIO_B_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, B, LevelTrigger )
5831+#define IPAQ_ASIC3_GPIO_B_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepMask )
5832+#define IPAQ_ASIC3_GPIO_B_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepOut )
5833+#define IPAQ_ASIC3_GPIO_B_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, B, BattFaultOut )
5834+#define IPAQ_ASIC3_GPIO_B_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, B, IntStatus )
5835+#define IPAQ_ASIC3_GPIO_B_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, B, AltFunction )
5836+#define IPAQ_ASIC3_GPIO_B_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepConf )
5837+#define IPAQ_ASIC3_GPIO_B_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Status )
5838+
5839+#define IPAQ_ASIC3_GPIO_C_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Mask )
5840+#define IPAQ_ASIC3_GPIO_C_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Direction )
5841+#define IPAQ_ASIC3_GPIO_C_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Out )
5842+#define IPAQ_ASIC3_GPIO_C_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, C, TriggerType )
5843+#define IPAQ_ASIC3_GPIO_C_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, C, EdgeTrigger )
5844+#define IPAQ_ASIC3_GPIO_C_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, C, LevelTrigger )
5845+#define IPAQ_ASIC3_GPIO_C_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepMask )
5846+#define IPAQ_ASIC3_GPIO_C_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepOut )
5847+#define IPAQ_ASIC3_GPIO_C_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, C, BattFaultOut )
5848+#define IPAQ_ASIC3_GPIO_C_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, C, IntStatus )
5849+#define IPAQ_ASIC3_GPIO_C_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, C, AltFunction )
5850+#define IPAQ_ASIC3_GPIO_C_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepConf )
5851+#define IPAQ_ASIC3_GPIO_C_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Status )
5852+
5853+#define IPAQ_ASIC3_GPIO_D_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Mask )
5854+#define IPAQ_ASIC3_GPIO_D_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Direction )
5855+#define IPAQ_ASIC3_GPIO_D_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Out )
5856+#define IPAQ_ASIC3_GPIO_D_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, D, TriggerType )
5857+#define IPAQ_ASIC3_GPIO_D_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, D, EdgeTrigger )
5858+#define IPAQ_ASIC3_GPIO_D_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, D, LevelTrigger )
5859+#define IPAQ_ASIC3_GPIO_D_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepMask )
5860+#define IPAQ_ASIC3_GPIO_D_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepOut )
5861+#define IPAQ_ASIC3_GPIO_D_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, D, BattFaultOut )
5862+#define IPAQ_ASIC3_GPIO_D_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, D, IntStatus )
5863+#define IPAQ_ASIC3_GPIO_D_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, D, AltFunction )
5864+#define IPAQ_ASIC3_GPIO_D_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepConf )
5865+#define IPAQ_ASIC3_GPIO_D_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Status )
5866+
5867+#define _IPAQ_ASIC3_SPI_Base 0x0400
5868+#define _IPAQ_ASIC3_SPI_Control 0x0000
5869+#define _IPAQ_ASIC3_SPI_TxData 0x0004
5870+#define _IPAQ_ASIC3_SPI_RxData 0x0008
5871+#define _IPAQ_ASIC3_SPI_Int 0x000c
5872+#define _IPAQ_ASIC3_SPI_Status 0x0010
5873+
5874+#define IPAQ_ASIC3_SPI_Control(_b) IPAQ_ASIC3( _b, u16, SPI, Control )
5875+#define IPAQ_ASIC3_SPI_TxData(_b) IPAQ_ASIC3( _b, u16, SPI, TxData )
5876+#define IPAQ_ASIC3_SPI_RxData(_b) IPAQ_ASIC3( _b, u16, SPI, RxData )
5877+#define IPAQ_ASIC3_SPI_Int(_b) IPAQ_ASIC3( _b, u16, SPI, Int )
5878+#define IPAQ_ASIC3_SPI_Status(_b) IPAQ_ASIC3( _b, u16, SPI, Status )
5879+
5880+#define SPI_CONTROL_SPR(clk) ((clk) & 0x0f) /* Clock rate */
5881+
5882+#define _IPAQ_ASIC3_PWM_0_Base 0x0500
5883+#define _IPAQ_ASIC3_PWM_1_Base 0x0600
5884+#define _IPAQ_ASIC3_PWM_TimeBase 0x0000
5885+#define _IPAQ_ASIC3_PWM_PeriodTime 0x0004
5886+#define _IPAQ_ASIC3_PWM_DutyTime 0x0008
5887+
5888+#define IPAQ_ASIC3_PWM_TimeBase(_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, TimeBase )
5889+#define IPAQ_ASIC3_PWM_PeriodTime(_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, PeriodTime )
5890+#define IPAQ_ASIC3_PWM_DutyTime(_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, DutyTime )
5891+
5892+#define PWM_TIMEBASE_VALUE(x) ((x)&0xf) /* Low 4 bits sets time base */
5893+#define PWM_TIMEBASE_ENABLE (1 << 4) /* Enable clock */
5894+
5895+#define _IPAQ_ASIC3_LED_0_Base 0x0700
5896+#define _IPAQ_ASIC3_LED_1_Base 0x0800
5897+#define _IPAQ_ASIC3_LED_2_Base 0x0900
5898+#define _IPAQ_ASIC3_LED_TimeBase 0x0000 /* R/W 7 bits */
5899+#define _IPAQ_ASIC3_LED_PeriodTime 0x0004 /* R/W 12 bits */
5900+#define _IPAQ_ASIC3_LED_DutyTime 0x0008 /* R/W 12 bits */
5901+#define _IPAQ_ASIC3_LED_AutoStopCount 0x000c /* R/W 16 bits */
5902+
5903+#define IPAQ_ASIC3_LED_TimeBase(_b, x) IPAQ_ASIC3_N( _b, u8, LED, x, TimeBase )
5904+#define IPAQ_ASIC3_LED_PeriodTime(_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, PeriodTime )
5905+#define IPAQ_ASIC3_LED_DutyTime(_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, DutyTime )
5906+#define IPAQ_ASIC3_LED_AutoStopCount(_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, AutoStopCount )
5907+
5908+/* LED TimeBase bits - match ASIC2 */
5909+#define LED_TBS 0x0f /* Low 4 bits sets time base, max = 13 */
5910+ /* Note: max = 5 on hx4700 */
5911+ /* 0: maximum time base */
5912+ /* 1: maximum time base / 2 */
5913+ /* n: maximum time base / 2^n */
5914+
5915+#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */
5916+#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
5917+#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
5918+
5919+#define _IPAQ_ASIC3_CLOCK_Base 0x0A00
5920+#define _IPAQ_ASIC3_CLOCK_CDEX 0x00
5921+#define _IPAQ_ASIC3_CLOCK_SEL 0x04
5922+
5923+#define IPAQ_ASIC3_CLOCK_CDEX(_b) IPAQ_ASIC3( _b, u16, CLOCK, CDEX )
5924+#define IPAQ_ASIC3_CLOCK_SEL(_b) IPAQ_ASIC3( _b, u16, CLOCK, SEL )
5925+
5926+#define CLOCK_CDEX_SOURCE (1 << 0) /* 2 bits */
5927+#define CLOCK_CDEX_SOURCE0 (1 << 0)
5928+#define CLOCK_CDEX_SOURCE1 (1 << 1)
5929+#define CLOCK_CDEX_SPI (1 << 2)
5930+#define CLOCK_CDEX_OWM (1 << 3)
5931+#define CLOCK_CDEX_PWM0 (1 << 4)
5932+#define CLOCK_CDEX_PWM1 (1 << 5)
5933+#define CLOCK_CDEX_LED0 (1 << 6)
5934+#define CLOCK_CDEX_LED1 (1 << 7)
5935+#define CLOCK_CDEX_LED2 (1 << 8)
5936+
5937+#define CLOCK_CDEX_SD_HOST (1 << 9) /* R/W: SD host clock source 24.576M/12.288M */
5938+#define CLOCK_CDEX_SD_BUS (1 << 10) /* R/W: SD bus clock source control 24.576M/12.288M */
5939+#define CLOCK_CDEX_SMBUS (1 << 11)
5940+#define CLOCK_CDEX_CONTROL_CX (1 << 12)
5941+
5942+#define CLOCK_CDEX_EX0 (1 << 13) /* R/W: 32.768 kHz crystal */
5943+#define CLOCK_CDEX_EX1 (1 << 14) /* R/W: 24.576 MHz crystal */
5944+
5945+#define CLOCK_SEL_SD_HCLK_SEL (1 << 0) /* R/W: SDIO host clock select - 1: 24.576 Mhz, 0: 12.288 MHz */
5946+#define CLOCK_SEL_SD_BCLK_SEL (1 << 1) /* R/W: SDIO bus clock select - 1: 24.576 MHz, 0: 12.288 MHz */
5947+#define CLOCK_SEL_CX (1 << 2) /* R/W: INT clock source control (32.768 kHz) */
5948+
5949+
5950+#define _IPAQ_ASIC3_INTR_Base 0x0B00
5951+
5952+#define _IPAQ_ASIC3_INTR_IntMask 0x00 /* Interrupt mask control */
5953+#define _IPAQ_ASIC3_INTR_PIntStat 0x04 /* Peripheral interrupt status */
5954+#define _IPAQ_ASIC3_INTR_IntCPS 0x08 /* Interrupt timer clock pre-scale */
5955+#define _IPAQ_ASIC3_INTR_IntTBS 0x0c /* Interrupt timer set */
5956+
5957+#define IPAQ_ASIC3_INTR_IntMask(_b) IPAQ_ASIC3( _b, u8, INTR, IntMask )
5958+#define IPAQ_ASIC3_INTR_PIntStat(_b) IPAQ_ASIC3( _b, u8, INTR, PIntStat )
5959+#define IPAQ_ASIC3_INTR_IntCPS(_b) IPAQ_ASIC3( _b, u8, INTR, IntCPS )
5960+#define IPAQ_ASIC3_INTR_IntTBS(_b) IPAQ_ASIC3( _b, u16, INTR, IntTBS )
5961+
5962+#define ASIC3_INTMASK_GINTMASK (1 << 0) /* Global interrupt mask 1:enable */
5963+#define ASIC3_INTMASK_GINTEL (1 << 1) /* 1: rising edge, 0: hi level */
5964+#define ASIC3_INTMASK_MASK0 (1 << 2)
5965+#define ASIC3_INTMASK_MASK1 (1 << 3)
5966+#define ASIC3_INTMASK_MASK2 (1 << 4)
5967+#define ASIC3_INTMASK_MASK3 (1 << 5)
5968+#define ASIC3_INTMASK_MASK4 (1 << 6)
5969+#define ASIC3_INTMASK_MASK5 (1 << 7)
5970+
5971+#define ASIC3_INTR_PERIPHERAL_A (1 << 0)
5972+#define ASIC3_INTR_PERIPHERAL_B (1 << 1)
5973+#define ASIC3_INTR_PERIPHERAL_C (1 << 2)
5974+#define ASIC3_INTR_PERIPHERAL_D (1 << 3)
5975+#define ASIC3_INTR_LED0 (1 << 4)
5976+#define ASIC3_INTR_LED1 (1 << 5)
5977+#define ASIC3_INTR_LED2 (1 << 6)
5978+#define ASIC3_INTR_SPI (1 << 7)
5979+#define ASIC3_INTR_SMBUS (1 << 8)
5980+#define ASIC3_INTR_OWM (1 << 9)
5981+
5982+#define ASIC3_INTR_CPS(x) ((x)&0x0f) /* 4 bits, max 14 */
5983+#define ASIC3_INTR_CPS_SET ( 1 << 4 ) /* Time base enable */
5984+
5985+
5986+/* Basic control of the SD ASIC */
5987+#define _IPAQ_ASIC3_SDHWCTRL_Base 0x0E00
5988+
5989+#define _IPAQ_ASIC3_SDHWCTRL_SDConf 0x00
5990+#define IPAQ_ASIC3_SDHWCTRL_SDConf(_b) IPAQ_ASIC3( _b, u8, SDHWCTRL, SDConf )
5991+
5992+#define ASIC3_SDHWCTRL_SUSPEND (1 << 0) /* 1=suspend all SD operations */
5993+#define ASIC3_SDHWCTRL_CLKSEL (1 << 1) /* 1=SDICK, 0=HCLK */
5994+#define ASIC3_SDHWCTRL_PCLR (1 << 2) /* All registers of SDIO cleared */
5995+#define ASIC3_SDHWCTRL_LEVCD (1 << 3) /* Level of SD card detection: 1:high, 0:low */
5996+#define ASIC3_SDHWCTRL_LEVWP (1 << 4) /* Level of SD card write protection: 1=low, 0=high */
5997+#define ASIC3_SDHWCTRL_SDLED (1 << 5) /* SD card LED signal 1=enable, 0=disable */
5998+#define ASIC3_SDHWCTRL_SDPWR (1 << 6) /* SD card power supply control 1=enable */
5999+
6000+
6001+/* This is a pointer to an array of 12 u32 values - but only the lower 2 bytes matter */
6002+/* Use it as "IPAQ_ASIC3_HWPROTECT_ARRAY[x]" */
6003+
6004+#define _IPAQ_ASIC3_HWPROTECT_Base 0x1000
6005+#define IPAQ_ASIC3_HWPROTECT_ARRAY ((volatile u32*)(_IPAQ_ASIC3_Base + _IPAQ_ASIC3_HWPROTECT_Base))
6006+#define HWPROTECT_ARRAY_LEN 12
6007+#define HWPROTECT_ARRAY_VALUES {0x4854,0x432d,0x5344,0x494f,0x2050,0x2f4e,0x3a33,0x3048,0x3830,0x3032,0x382d,0x3030}
6008+
6009+
6010+#define _IPAQ_ASIC3_EXTCF_Base 0x1100
6011+
6012+#define _IPAQ_ASIC3_EXTCF_Select 0x00
6013+#define _IPAQ_ASIC3_EXTCF_Reset 0x04
6014+
6015+#define IPAQ_ASIC3_EXTCF_Select(_b) IPAQ_ASIC3( _b, u16, EXTCF, Select )
6016+#define IPAQ_ASIC3_EXTCF_Reset(_b) IPAQ_ASIC3( _b, u16, EXTCF, Reset )
6017+
6018+#define ASIC3_EXTCF_SMOD0 (1 << 0) /* slot number of mode 0 */
6019+#define ASIC3_EXTCF_SMOD1 (1 << 1) /* slot number of mode 1 */
6020+#define ASIC3_EXTCF_SMOD2 (1 << 2) /* slot number of mode 2 */
6021+#define ASIC3_EXTCF_OWM_EN (1 << 4) /* enable onewire module */
6022+#define ASIC3_EXTCF_OWM_SMB (1 << 5) /* OWM bus selection */
6023+#define ASIC3_EXTCF_OWM_RESET (1 << 6) /* undocumented, used by OWM and CF */
6024+#define ASIC3_EXTCF_CF0_SLEEP_MODE (1 << 7) /* CF0 sleep state control */
6025+#define ASIC3_EXTCF_CF1_SLEEP_MODE (1 << 8) /* CF1 sleep state control */
6026+#define ASIC3_EXTCF_CF0_PWAIT_EN (1 << 10) /* CF0 PWAIT_n control */
6027+#define ASIC3_EXTCF_CF1_PWAIT_EN (1 << 11) /* CF1 PWAIT_n control */
6028+#define ASIC3_EXTCF_CF0_BUF_EN (1 << 12) /* CF0 buffer control */
6029+#define ASIC3_EXTCF_CF1_BUF_EN (1 << 13) /* CF1 buffer control */
6030+#define ASIC3_EXTCF_SD_MEM_ENABLE (1 << 14)
6031+#define ASIC3_EXTCF_CF_SLEEP (1 << 15) /* CF sleep mode control */
6032+
6033+/*****************************************************************************
6034+ * The Onewire interface registers
6035+ *
6036+ * OWM_CMD
6037+ * OWM_DAT
6038+ * OWM_INTR
6039+ * OWM_INTEN
6040+ * OWM_CLKDIV
6041+ *
6042+ *****************************************************************************/
6043+
6044+#define _IPAQ_ASIC3_OWM_Base 0xC00
6045+
6046+#define _IPAQ_ASIC3_OWM_CMD 0x00
6047+#define _IPAQ_ASIC3_OWM_DAT 0x04
6048+#define _IPAQ_ASIC3_OWM_INTR 0x08
6049+#define _IPAQ_ASIC3_OWM_INTEN 0x0C
6050+#define _IPAQ_ASIC3_OWM_CLKDIV 0x10
6051+
6052+#define ASIC3_OWM_CMD_ONEWR (1 << 0)
6053+#define ASIC3_OWM_CMD_SRA (1 << 1)
6054+#define ASIC3_OWM_CMD_DQO (1 << 2)
6055+#define ASIC3_OWM_CMD_DQI (1 << 3)
6056+
6057+#define ASIC3_OWM_INTR_PD (1 << 0)
6058+#define ASIC3_OWM_INTR_PDR (1 << 1)
6059+#define ASIC3_OWM_INTR_TBE (1 << 2)
6060+#define ASIC3_OWM_INTR_TEMP (1 << 3)
6061+#define ASIC3_OWM_INTR_RBF (1 << 4)
6062+
6063+#define ASIC3_OWM_INTEN_EPD (1 << 0)
6064+#define ASIC3_OWM_INTEN_IAS (1 << 1)
6065+#define ASIC3_OWM_INTEN_ETBE (1 << 2)
6066+#define ASIC3_OWM_INTEN_ETMT (1 << 3)
6067+#define ASIC3_OWM_INTEN_ERBF (1 << 4)
6068+
6069+#define ASIC3_OWM_CLKDIV_PRE (3 << 0) /* two bits wide at bit position 0 */
6070+#define ASIC3_OWM_CLKDIV_DIV (7 << 2) /* 3 bits wide at bit position 2 */
6071+
6072+
6073+/*****************************************************************************
6074+ * The SD configuration registers are at a completely different location
6075+ * in memory. They are divided into three sets of registers:
6076+ *
6077+ * SD_CONFIG Core configuration register
6078+ * SD_CTRL Control registers for SD operations
6079+ * SDIO_CTRL Control registers for SDIO operations
6080+ *
6081+ *****************************************************************************/
6082+
6083+#define IPAQ_ASIC3_SD_CONFIG(_b, s,x) \
6084+ (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CONFIG_Base + (_IPAQ_ASIC3_SD_CONFIG_ ## x))))
6085+
6086+#define _IPAQ_ASIC3_SD_CONFIG_Base 0x0400 // Assumes 32 bit addressing
6087+
6088+#define _IPAQ_ASIC3_SD_CONFIG_Command 0x08 /* R/W: Command */
6089+#define _IPAQ_ASIC3_SD_CONFIG_Addr0 0x20 /* [9:31] SD Control Register Base Address */
6090+#define _IPAQ_ASIC3_SD_CONFIG_Addr1 0x24 /* [9:31] SD Control Register Base Address */
6091+#define _IPAQ_ASIC3_SD_CONFIG_IntPin 0x78 /* R/O: interrupt assigned to pin */
6092+#define _IPAQ_ASIC3_SD_CONFIG_ClkStop 0x80 /* Set to 0x1f to clock SD controller, 0 otherwise. */
6093+ /* at 0x82 - Gated Clock Control */
6094+#define _IPAQ_ASIC3_SD_CONFIG_ClockMode 0x84 /* Control clock of SD controller */
6095+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus 0x88 /* R/0: read status of SD pins */
6096+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power1 0x90 /* Power1 - manual power control */
6097+ /* Power2 is at 0x92 - auto power up after card inserted */
6098+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power3 0x94 /* auto power down when card removed */
6099+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect 0x98 /* */
6100+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Slot 0xA0 /* R/O: define support slot number */
6101+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1 0x1E0 /* Could be used for gated clock (don't use) */
6102+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk2 0x1E2 /* Could be used for gated clock (don't use) */
6103+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_OutAndEnable 0x1E8 /* GPIO Output Reg. , at 0x1EA - GPIO Output Enable Reg. */
6104+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_Status 0x1EC /* GPIO Status Reg. */
6105+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3 0x1F0 /* Bit 1: double buffer/single buffer */
6106+
6107+#define IPAQ_ASIC3_SD_CONFIG_Command(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Command )
6108+#define IPAQ_ASIC3_SD_CONFIG_Addr0(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr0 )
6109+#define IPAQ_ASIC3_SD_CONFIG_Addr1(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr1 )
6110+#define IPAQ_ASIC3_SD_CONFIG_IntPin(_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, IntPin )
6111+#define IPAQ_ASIC3_SD_CONFIG_ClkStop(_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, ClkStop )
6112+#define IPAQ_ASIC3_SD_CONFIG_ClockMode(_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, ClockMode )
6113+#define IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_PinStatus )
6114+#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power1(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power1 )
6115+#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power3(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power3 )
6116+#define IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_CardDetect )
6117+#define IPAQ_ASIC3_SD_CONFIG_SDHC_Slot(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Slot )
6118+#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk1 )
6119+#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk3 )
6120+
6121+#define SD_CONFIG_
6122+
6123+#define SD_CONFIG_COMMAND_MAE (1<<1) /* Memory access enable (set to 1 to access SD Controller) */
6124+
6125+#define SD_CONFIG_CLK_ENABLE_ALL 0x1f
6126+
6127+#define SD_CONFIG_POWER1_PC_33V 0x0200 /* Set for 3.3 volts */
6128+#define SD_CONFIG_POWER1_PC_OFF 0x0000 /* Turn off power */
6129+
6130+#define SD_CONFIG_CARDDETECTMODE_CLK ((x)&0x3) /* two bits - number of cycles for card detection */
6131+
6132+
6133+#define _IPAQ_ASIC3_SD_CTRL_Base 0x1000
6134+
6135+#define IPAQ_ASIC3_SD(_b, s,x) \
6136+ (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CTRL_Base + (_IPAQ_ASIC3_SD_CTRL_ ## x))))
6137+
6138+#define _IPAQ_ASIC3_SD_CTRL_Cmd 0x00
6139+#define _IPAQ_ASIC3_SD_CTRL_Arg0 0x08
6140+#define _IPAQ_ASIC3_SD_CTRL_Arg1 0x0C
6141+#define _IPAQ_ASIC3_SD_CTRL_StopInternal 0x10
6142+#define _IPAQ_ASIC3_SD_CTRL_TransferSectorCount 0x14
6143+#define _IPAQ_ASIC3_SD_CTRL_Response0 0x18
6144+#define _IPAQ_ASIC3_SD_CTRL_Response1 0x1C
6145+#define _IPAQ_ASIC3_SD_CTRL_Response2 0x20
6146+#define _IPAQ_ASIC3_SD_CTRL_Response3 0x24
6147+#define _IPAQ_ASIC3_SD_CTRL_Response4 0x28
6148+#define _IPAQ_ASIC3_SD_CTRL_Response5 0x2C
6149+#define _IPAQ_ASIC3_SD_CTRL_Response6 0x30
6150+#define _IPAQ_ASIC3_SD_CTRL_Response7 0x34
6151+#define _IPAQ_ASIC3_SD_CTRL_CardStatus 0x38
6152+#define _IPAQ_ASIC3_SD_CTRL_BufferCtrl 0x3C
6153+#define _IPAQ_ASIC3_SD_CTRL_IntMaskCard 0x40
6154+#define _IPAQ_ASIC3_SD_CTRL_IntMaskBuffer 0x44
6155+#define _IPAQ_ASIC3_SD_CTRL_CardClockCtrl 0x48
6156+#define _IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen 0x4C
6157+#define _IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup 0x50
6158+#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus0 0x58
6159+#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus1 0x5C
6160+#define _IPAQ_ASIC3_SD_CTRL_DataPort 0x60
6161+#define _IPAQ_ASIC3_SD_CTRL_TransactionCtrl 0x68
6162+#define _IPAQ_ASIC3_SD_CTRL_SoftwareReset 0x1C0
6163+
6164+#define IPAQ_ASIC3_SD_CTRL_Cmd(_b) IPAQ_ASIC3_SD( _b, u16, Cmd ) /* */
6165+#define IPAQ_ASIC3_SD_CTRL_Arg0(_b) IPAQ_ASIC3_SD( _b, u16, Arg0 ) /* */
6166+#define IPAQ_ASIC3_SD_CTRL_Arg1(_b) IPAQ_ASIC3_SD( _b, u16, Arg1 ) /* */
6167+#define IPAQ_ASIC3_SD_CTRL_StopInternal(_b) IPAQ_ASIC3_SD( _b, u16, StopInternal ) /* */
6168+#define IPAQ_ASIC3_SD_CTRL_TransferSectorCount(_b) IPAQ_ASIC3_SD( _b, u16, TransferSectorCount ) /* */
6169+#define IPAQ_ASIC3_SD_CTRL_Response0(_b) IPAQ_ASIC3_SD( _b, u16, Response0 ) /* */
6170+#define IPAQ_ASIC3_SD_CTRL_Response1(_b) IPAQ_ASIC3_SD( _b, u16, Response1 ) /* */
6171+#define IPAQ_ASIC3_SD_CTRL_Response2(_b) IPAQ_ASIC3_SD( _b, u16, Response2 ) /* */
6172+#define IPAQ_ASIC3_SD_CTRL_Response3(_b) IPAQ_ASIC3_SD( _b, u16, Response3 ) /* */
6173+#define IPAQ_ASIC3_SD_CTRL_Response4(_b) IPAQ_ASIC3_SD( _b, u16, Response4 ) /* */
6174+#define IPAQ_ASIC3_SD_CTRL_Response5(_b) IPAQ_ASIC3_SD( _b, u16, Response5 ) /* */
6175+#define IPAQ_ASIC3_SD_CTRL_Response6(_b) IPAQ_ASIC3_SD( _b, u16, Response6 ) /* */
6176+#define IPAQ_ASIC3_SD_CTRL_Response7(_b) IPAQ_ASIC3_SD( _b, u16, Response7 ) /* */
6177+#define IPAQ_ASIC3_SD_CTRL_CardStatus(_b) IPAQ_ASIC3_SD( _b, u16, CardStatus ) /* */
6178+#define IPAQ_ASIC3_SD_CTRL_BufferCtrl(_b) IPAQ_ASIC3_SD( _b, u16, BufferCtrl ) /* and error status*/
6179+#define IPAQ_ASIC3_SD_CTRL_IntMaskCard(_b) IPAQ_ASIC3_SD( _b, u16, IntMaskCard ) /* */
6180+#define IPAQ_ASIC3_SD_CTRL_IntMaskBuffer(_b) IPAQ_ASIC3_SD( _b, u16, IntMaskBuffer ) /* */
6181+#define IPAQ_ASIC3_SD_CTRL_CardClockCtrl(_b) IPAQ_ASIC3_SD( _b, u16, CardClockCtrl ) /* */
6182+#define IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen(_b) IPAQ_ASIC3_SD( _b, u16, MemCardXferDataLen ) /* */
6183+#define IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup(_b) IPAQ_ASIC3_SD( _b, u16, MemCardOptionSetup ) /* */
6184+#define IPAQ_ASIC3_SD_CTRL_ErrorStatus0(_b) IPAQ_ASIC3_SD( _b, u16, ErrorStatus0 ) /* */
6185+#define IPAQ_ASIC3_SD_CTRL_ErrorStatus1(_b) IPAQ_ASIC3_SD( _b, u16, ErrorStatus1 ) /* */
6186+#define IPAQ_ASIC3_SD_CTRL_DataPort(_b) IPAQ_ASIC3_SD( _b, u16, DataPort ) /* */
6187+#define IPAQ_ASIC3_SD_CTRL_TransactionCtrl(_b) IPAQ_ASIC3_SD( _b, u16, TransactionCtrl ) /* */
6188+#define IPAQ_ASIC3_SD_CTRL_SoftwareReset(_b) IPAQ_ASIC3_SD( _b, u16, SoftwareReset ) /* */
6189+
6190+#define SD_CTRL_SOFTWARE_RESET_CLEAR (1<<0)
6191+
6192+#define SD_CTRL_TRANSACTIONCONTROL_SET (1<<8) // 0x0100
6193+
6194+#define SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD (1<<15)// 0x8000
6195+#define SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK (1<<8) // 0x0100
6196+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_512 (1<<7) // 0x0080
6197+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_256 (1<<6) // 0x0040
6198+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_128 (1<<5) // 0x0020
6199+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_64 (1<<4) // 0x0010
6200+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_32 (1<<3) // 0x0008
6201+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_16 (1<<2) // 0x0004
6202+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_8 (1<<1) // 0x0002
6203+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_4 (1<<0) // 0x0001
6204+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_2 (0<<0) // 0x0000
6205+
6206+#define MEM_CARD_OPTION_REQUIRED 0x000e
6207+#define MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(x) (((x)&0x0f)<<4) /* Four bits */
6208+#define MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT (1<<14) // 0x4000
6209+#define MEM_CARD_OPTION_DATA_XFR_WIDTH_1 (1<<15) // 0x8000
6210+#define MEM_CARD_OPTION_DATA_XFR_WIDTH_4 (0<<15) //~0x8000
6211+
6212+#define SD_CTRL_COMMAND_INDEX(x) ((x)&0x3f) /* 0=CMD0, 1=CMD1, ..., 63=CMD63 */
6213+#define SD_CTRL_COMMAND_TYPE_CMD (0 << 6)
6214+#define SD_CTRL_COMMAND_TYPE_ACMD (1 << 6)
6215+#define SD_CTRL_COMMAND_TYPE_AUTHENTICATION (2 << 6)
6216+#define SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL (0 << 8)
6217+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1 (4 << 8)
6218+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B (5 << 8)
6219+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2 (6 << 8)
6220+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3 (7 << 8)
6221+#define SD_CTRL_COMMAND_DATA_PRESENT (1 << 11)
6222+#define SD_CTRL_COMMAND_TRANSFER_READ (1 << 12)
6223+#define SD_CTRL_COMMAND_TRANSFER_WRITE (0 << 12)
6224+#define SD_CTRL_COMMAND_MULTI_BLOCK (1 << 13)
6225+#define SD_CTRL_COMMAND_SECURITY_CMD (1 << 14)
6226+
6227+#define SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12 (1 << 0)
6228+#define SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12 (1 << 8)
6229+
6230+#define SD_CTRL_CARDSTATUS_RESPONSE_END (1 << 0)
6231+#define SD_CTRL_CARDSTATUS_RW_END (1 << 2)
6232+#define SD_CTRL_CARDSTATUS_CARD_REMOVED_0 (1 << 3)
6233+#define SD_CTRL_CARDSTATUS_CARD_INSERTED_0 (1 << 4)
6234+#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_0 (1 << 5)
6235+#define SD_CTRL_CARDSTATUS_WRITE_PROTECT (1 << 7)
6236+#define SD_CTRL_CARDSTATUS_CARD_REMOVED_3 (1 << 8)
6237+#define SD_CTRL_CARDSTATUS_CARD_INSERTED_3 (1 << 9)
6238+#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_3 (1 << 10)
6239+
6240+#define SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR (1 << 0) // 0x0001
6241+#define SD_CTRL_BUFFERSTATUS_CRC_ERROR (1 << 1) // 0x0002
6242+#define SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR (1 << 2) // 0x0004
6243+#define SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT (1 << 3) // 0x0008
6244+#define SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW (1 << 4) // 0x0010
6245+#define SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW (1 << 5) // 0x0020
6246+#define SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT (1 << 6) // 0x0040
6247+#define SD_CTRL_BUFFERSTATUS_UNK7 (1 << 7) // 0x0080
6248+#define SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE (1 << 8) // 0x0100
6249+#define SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE (1 << 9) // 0x0200
6250+#define SD_CTRL_BUFFERSTATUS_ILLEGAL_FUNCTION (1 << 13)// 0x2000
6251+#define SD_CTRL_BUFFERSTATUS_CMD_BUSY (1 << 14)// 0x4000
6252+#define SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS (1 << 15)// 0x8000
6253+
6254+#define SD_CTRL_INTMASKCARD_RESPONSE_END (1 << 0) // 0x0001
6255+#define SD_CTRL_INTMASKCARD_RW_END (1 << 2) // 0x0004
6256+#define SD_CTRL_INTMASKCARD_CARD_REMOVED_0 (1 << 3) // 0x0008
6257+#define SD_CTRL_INTMASKCARD_CARD_INSERTED_0 (1 << 4) // 0x0010
6258+#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 (1 << 5) // 0x0020
6259+#define SD_CTRL_INTMASKCARD_UNK6 (1 << 6) // 0x0040
6260+#define SD_CTRL_INTMASKCARD_WRITE_PROTECT (1 << 7) // 0x0080
6261+#define SD_CTRL_INTMASKCARD_CARD_REMOVED_3 (1 << 8) // 0x0100
6262+#define SD_CTRL_INTMASKCARD_CARD_INSERTED_3 (1 << 9) // 0x0200
6263+#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 (1 << 10)// 0x0400
6264+
6265+#define SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR (1 << 0) // 0x0001
6266+#define SD_CTRL_INTMASKBUFFER_CRC_ERROR (1 << 1) // 0x0002
6267+#define SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR (1 << 2) // 0x0004
6268+#define SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT (1 << 3) // 0x0008
6269+#define SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW (1 << 4) // 0x0010
6270+#define SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW (1 << 5) // 0x0020
6271+#define SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT (1 << 6) // 0x0040
6272+#define SD_CTRL_INTMASKBUFFER_UNK7 (1 << 7) // 0x0080
6273+#define SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE (1 << 8) // 0x0100
6274+#define SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE (1 << 9) // 0x0200
6275+#define SD_CTRL_INTMASKBUFFER_ILLEGAL_FUNCTION (1 << 13)// 0x2000
6276+#define SD_CTRL_INTMASKBUFFER_CMD_BUSY (1 << 14)// 0x4000
6277+#define SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS (1 << 15)// 0x8000
6278+
6279+#define SD_CTRL_DETAIL0_RESPONSE_CMD_ERROR (1 << 0) // 0x0001
6280+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 2) // 0x0004
6281+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_CMD12 (1 << 3) // 0x0008
6282+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_READ_DATA (1 << 4) // 0x0010
6283+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_WRITE_CRC_STATUS (1 << 5) // 0x0020
6284+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 8) // 0x0100
6285+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_CMD12 (1 << 9) // 0x0200
6286+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_READ_DATA (1 << 10)// 0x0400
6287+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_WRITE_CMD (1 << 11)// 0x0800
6288+
6289+#define SD_CTRL_DETAIL1_NO_CMD_RESPONSE (1 << 0) // 0x0001
6290+#define SD_CTRL_DETAIL1_TIMEOUT_READ_DATA (1 << 4) // 0x0010
6291+#define SD_CTRL_DETAIL1_TIMEOUT_CRS_STATUS (1 << 5) // 0x0020
6292+#define SD_CTRL_DETAIL1_TIMEOUT_CRC_BUSY (1 << 6) // 0x0040
6293+
6294+#define _IPAQ_ASIC3_SDIO_CTRL_Base 0x1200
6295+
6296+#define IPAQ_ASIC3_SDIO(_b, s,x) \
6297+ (*((volatile s *) ((_b) + _IPAQ_ASIC3_SDIO_CTRL_Base + (_IPAQ_ASIC3_SDIO_CTRL_ ## x))))
6298+
6299+#define _IPAQ_ASIC3_SDIO_CTRL_Cmd 0x00
6300+#define _IPAQ_ASIC3_SDIO_CTRL_CardPortSel 0x04
6301+#define _IPAQ_ASIC3_SDIO_CTRL_Arg0 0x08
6302+#define _IPAQ_ASIC3_SDIO_CTRL_Arg1 0x0C
6303+#define _IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount 0x14
6304+#define _IPAQ_ASIC3_SDIO_CTRL_Response0 0x18
6305+#define _IPAQ_ASIC3_SDIO_CTRL_Response1 0x1C
6306+#define _IPAQ_ASIC3_SDIO_CTRL_Response2 0x20
6307+#define _IPAQ_ASIC3_SDIO_CTRL_Response3 0x24
6308+#define _IPAQ_ASIC3_SDIO_CTRL_Response4 0x28
6309+#define _IPAQ_ASIC3_SDIO_CTRL_Response5 0x2C
6310+#define _IPAQ_ASIC3_SDIO_CTRL_Response6 0x30
6311+#define _IPAQ_ASIC3_SDIO_CTRL_Response7 0x34
6312+#define _IPAQ_ASIC3_SDIO_CTRL_CardStatus 0x38
6313+#define _IPAQ_ASIC3_SDIO_CTRL_BufferCtrl 0x3C
6314+#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskCard 0x40
6315+#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer 0x44
6316+#define _IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen 0x4C
6317+#define _IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup 0x50
6318+#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0 0x54
6319+#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1 0x58
6320+#define _IPAQ_ASIC3_SDIO_CTRL_DataPort 0x60
6321+#define _IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl 0x68
6322+#define _IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl 0x6C
6323+#define _IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl 0x70
6324+#define _IPAQ_ASIC3_SDIO_CTRL_HostInformation 0x74
6325+#define _IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl 0x78
6326+#define _IPAQ_ASIC3_SDIO_CTRL_LEDCtrl 0x7C
6327+#define _IPAQ_ASIC3_SDIO_CTRL_SoftwareReset 0x1C0
6328+
6329+#define IPAQ_ASIC3_SDIO_CTRL_Cmd(_b) IPAQ_ASIC3_SDIO( _b, u16, Cmd ) /* */
6330+#define IPAQ_ASIC3_SDIO_CTRL_CardPortSel(_b) IPAQ_ASIC3_SDIO( _b, u16, CardPortSel ) /* */
6331+#define IPAQ_ASIC3_SDIO_CTRL_Arg0(_b) IPAQ_ASIC3_SDIO( _b, u16, Arg0 ) /* */
6332+#define IPAQ_ASIC3_SDIO_CTRL_Arg1(_b) IPAQ_ASIC3_SDIO( _b, u16, Arg1 ) /* */
6333+#define IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount(_b) IPAQ_ASIC3_SDIO( _b, u16, TransferBlockCount ) /* */
6334+#define IPAQ_ASIC3_SDIO_CTRL_Response0(_b) IPAQ_ASIC3_SDIO( _b, u16, Response0 ) /* */
6335+#define IPAQ_ASIC3_SDIO_CTRL_Response1(_b) IPAQ_ASIC3_SDIO( _b, u16, Response1 ) /* */
6336+#define IPAQ_ASIC3_SDIO_CTRL_Response2(_b) IPAQ_ASIC3_SDIO( _b, u16, Response2 ) /* */
6337+#define IPAQ_ASIC3_SDIO_CTRL_Response3(_b) IPAQ_ASIC3_SDIO( _b, u16, Response3 ) /* */
6338+#define IPAQ_ASIC3_SDIO_CTRL_Response4(_b) IPAQ_ASIC3_SDIO( _b, u16, Response4 ) /* */
6339+#define IPAQ_ASIC3_SDIO_CTRL_Response5(_b) IPAQ_ASIC3_SDIO( _b, u16, Response5 ) /* */
6340+#define IPAQ_ASIC3_SDIO_CTRL_Response6(_b) IPAQ_ASIC3_SDIO( _b, u16, Response6 ) /* */
6341+#define IPAQ_ASIC3_SDIO_CTRL_Response7(_b) IPAQ_ASIC3_SDIO( _b, u16, Response7 ) /* */
6342+#define IPAQ_ASIC3_SDIO_CTRL_CardStatus(_b) IPAQ_ASIC3_SDIO( _b, u16, CardStatus ) /* */
6343+#define IPAQ_ASIC3_SDIO_CTRL_BufferCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, BufferCtrl ) /* and error status*/
6344+#define IPAQ_ASIC3_SDIO_CTRL_IntMaskCard(_b) IPAQ_ASIC3_SDIO( _b, u16, IntMaskCard ) /* */
6345+#define IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer(_b) IPAQ_ASIC3_SDIO( _b, u16, IntMaskBuffer ) /* */
6346+#define IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen(_b) IPAQ_ASIC3_SDIO( _b, u16, CardXferDataLen ) /* */
6347+#define IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup(_b) IPAQ_ASIC3_SDIO( _b, u16, CardOptionSetup ) /* */
6348+#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0(_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus0 ) /* */
6349+#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1(_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus1 ) /* */
6350+#define IPAQ_ASIC3_SDIO_CTRL_DataPort(_b) IPAQ_ASIC3_SDIO( _b, u16, DataPort ) /* */
6351+#define IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, TransactionCtrl ) /* */
6352+#define IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, CardIntCtrl ) /* */
6353+#define IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, ClocknWaitCtrl ) /* */
6354+#define IPAQ_ASIC3_SDIO_CTRL_HostInformation(_b) IPAQ_ASIC3_SDIO( _b, u16, HostInformation ) /* */
6355+#define IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorCtrl ) /* */
6356+#define IPAQ_ASIC3_SDIO_CTRL_LEDCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, LEDCtrl ) /* */
6357+#define IPAQ_ASIC3_SDIO_CTRL_SoftwareReset(_b) IPAQ_ASIC3_SDIO( _b, u16, SoftwareReset ) /* */
6358+
6359+#define IPAQ_ASIC3_MAP_SIZE 0x2000
6360+
6361+#endif
6362Index: linux-2.6.22/include/linux/backlight.h
6363===================================================================
6364--- linux-2.6.22.orig/include/linux/backlight.h 2007-09-11 12:53:26.000000000 +0200
6365+++ linux-2.6.22/include/linux/backlight.h 2007-09-11 12:53:37.000000000 +0200
6366@@ -92,4 +92,11 @@
6367 return dev_get_drvdata(&bl_dev->dev);
6368 }
6369
6370+struct generic_bl_info {
6371+ int max_intensity;
6372+ int default_intensity;
6373+ int limit_mask;
6374+ void (*set_bl_intensity)(int intensity);
6375+};
6376+
6377 #endif
6378Index: linux-2.6.22/include/linux/gpiodev.h
6379===================================================================
6380--- /dev/null 1970-01-01 00:00:00.000000000 +0000
6381+++ linux-2.6.22/include/linux/gpiodev.h 2007-09-11 12:53:37.000000000 +0200
6382@@ -0,0 +1,44 @@
6383+#ifndef __GPIODEV_H
6384+#define __GPIODEV_H
6385+
6386+#include <linux/device.h>
6387+#include <linux/platform_device.h>
6388+#include <asm/gpio.h>
6389+
6390+/* Interface */
6391+
6392+/* This structure must be first member of device platform_data structure
6393+ of a device which provides gpiodev interface. All method pointers
6394+ must be non-NULL, so stubs must be used for non-implemented ones. */
6395+struct gpiodev_ops {
6396+ int (*get)(struct device *this, unsigned gpio_no);
6397+ void (*set)(struct device *this, unsigned gpio_no, int val);
6398+ int (*to_irq)(struct device *this, unsigned gpio_no);
6399+};
6400+
6401+/* Generalized GPIO structure */
6402+
6403+struct gpio {
6404+ struct device *gpio_dev;
6405+ unsigned gpio_no;
6406+};
6407+
6408+/* API functions */
6409+
6410+static inline int gpiodev_get_value(struct gpio *gpio)
6411+{
6412+ struct gpiodev_ops *ops = gpio->gpio_dev->platform_data;
6413+ return ops->get(gpio->gpio_dev, gpio->gpio_no);
6414+}
6415+static inline void gpiodev_set_value(struct gpio *gpio, int val)
6416+{
6417+ struct gpiodev_ops *ops = gpio->gpio_dev->platform_data;
6418+ ops->set(gpio->gpio_dev, gpio->gpio_no, val);
6419+}
6420+static inline int gpiodev_to_irq(struct gpio *gpio)
6421+{
6422+ struct gpiodev_ops *ops = gpio->gpio_dev->platform_data;
6423+ return ops->to_irq(gpio->gpio_dev, gpio->gpio_no);
6424+}
6425+
6426+#endif /* __GPIODEV_H */
6427Index: linux-2.6.22/include/linux/input_pda.h
6428===================================================================
6429--- /dev/null 1970-01-01 00:00:00.000000000 +0000
6430+++ linux-2.6.22/include/linux/input_pda.h 2007-09-11 12:53:37.000000000 +0200
6431@@ -0,0 +1,47 @@
6432+#ifndef _INPUT_PDA_H
6433+#define _INPUT_PDA_H
6434+
6435+/*
6436+ * This is temporary virtual button key codes map
6437+ * for keyboardless handheld computers.
6438+ * Its purpose is to provide map common to all devices
6439+ * and known to work with current software and its bugs
6440+ * and misfeatures. Once issues with the software are
6441+ * solved, codes from input.h will be used directly
6442+ * (missing key definitions will be added).
6443+ */
6444+
6445+/* Some directly usable keycodes:
6446+KEY_POWER - Power/suspend button
6447+KEY_ENTER - Enter/Action/Central button on joypad
6448+KEY_UP
6449+KEY_DOWN
6450+KEY_LEFT
6451+KEY_RIGHT
6452+*/
6453+
6454+/* XXX Instead of using any values in include/linux/input.h, we have to use
6455+ use values < 128 due to some munging that kdrive does to get keystrokes.
6456+ When kdrive gets its key events from evdev instead of the console,
6457+ we should be able to switch to using input.h values and get rid of
6458+ xmodmap. */
6459+
6460+#define _KEY_APP1 KEY_F9 // xmodmap sees 67 + 8 = 75
6461+#define _KEY_APP2 KEY_F10 // xmodmap 76
6462+#define _KEY_APP3 KEY_F11 // xmodmap 95
6463+#define _KEY_APP4 KEY_F12 // xmodmap 96
6464+
6465+#define _KEY_RECORD KEY_RO
6466+
6467+/* It is highly recommended to use exactly 4 codes above for
6468+ 4 buttons the device has. This will ensure that console and
6469+ framebuffer applications (e.g. games) will work ok on all
6470+ devices. If you'd like more distinguishable names, following
6471+ convenience defines are provided, suiting many devices. */
6472+
6473+#define _KEY_CALENDAR _KEY_APP1
6474+#define _KEY_CONTACTS _KEY_APP2
6475+#define _KEY_MAIL _KEY_APP3
6476+#define _KEY_HOMEPAGE _KEY_APP4
6477+
6478+#endif
6479Index: linux-2.6.22/include/linux/soc/asic3_base.h
6480===================================================================
6481--- /dev/null 1970-01-01 00:00:00.000000000 +0000
6482+++ linux-2.6.22/include/linux/soc/asic3_base.h 2007-09-11 12:53:37.000000000 +0200
6483@@ -0,0 +1,104 @@
6484+#include <asm/types.h>
6485+#include <linux/gpiodev.h>
6486+
6487+/* Private API - for ASIC3 devices internal use only */
6488+#define HDR_IPAQ_ASIC3_ACTION(ACTION,action,fn,FN) \
6489+u32 asic3_get_gpio_ ## action ## _ ## fn (struct device *dev); \
6490+void asic3_set_gpio_ ## action ## _ ## fn (struct device *dev, u32 bits, u32 val);
6491+
6492+#define HDR_IPAQ_ASIC3_FN(fn,FN) \
6493+ HDR_IPAQ_ASIC3_ACTION ( MASK,mask,fn,FN) \
6494+ HDR_IPAQ_ASIC3_ACTION ( DIR, dir, fn, FN) \
6495+ HDR_IPAQ_ASIC3_ACTION ( OUT, out, fn, FN) \
6496+ HDR_IPAQ_ASIC3_ACTION ( LEVELTRI, trigtype, fn, FN) \
6497+ HDR_IPAQ_ASIC3_ACTION ( RISING, rising, fn, FN) \
6498+ HDR_IPAQ_ASIC3_ACTION ( LEVEL, triglevel, fn, FN) \
6499+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_MASK, sleepmask, fn, FN) \
6500+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_OUT, sleepout, fn, FN) \
6501+ HDR_IPAQ_ASIC3_ACTION ( BATT_FAULT_OUT, battfaultout, fn, FN) \
6502+ HDR_IPAQ_ASIC3_ACTION ( INT_STATUS, intstatus, fn, FN) \
6503+ HDR_IPAQ_ASIC3_ACTION ( ALT_FUNCTION, alt_fn, fn, FN) \
6504+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_CONF, sleepconf, fn, FN) \
6505+ HDR_IPAQ_ASIC3_ACTION ( STATUS, status, fn, FN)
6506+
6507+/* Public API */
6508+
6509+#define ASIC3_GPIOA_IRQ_BASE 0
6510+#define ASIC3_GPIOB_IRQ_BASE 16
6511+#define ASIC3_GPIOC_IRQ_BASE 32
6512+#define ASIC3_GPIOD_IRQ_BASE 48
6513+#define ASIC3_LED0_IRQ 64
6514+#define ASIC3_LED1_IRQ 65
6515+#define ASIC3_LED2_IRQ 66
6516+#define ASIC3_SPI_IRQ 67
6517+#define ASIC3_SMBUS_IRQ 68
6518+#define ASIC3_OWM_IRQ 69
6519+
6520+#define ASIC3_NR_GPIO_IRQS 64 /* 16 bits each GPIO A...D banks */
6521+#define ASIC3_NR_IRQS (ASIC3_OWM_IRQ + 1)
6522+
6523+extern int asic3_irq_base(struct device *dev);
6524+
6525+extern void asic3_write_register(struct device *dev, unsigned int reg,
6526+ u32 value);
6527+extern u32 asic3_read_register(struct device *dev, unsigned int reg);
6528+
6529+/* old clock api */
6530+extern void asic3_set_clock_sel(struct device *dev, u32 bits, u32 val);
6531+extern u32 asic3_get_clock_cdex(struct device *dev);
6532+extern void asic3_set_clock_cdex(struct device *dev, u32 bits, u32 val);
6533+
6534+extern void asic3_set_extcf_select(struct device *dev, u32 bits, u32 val);
6535+extern void asic3_set_extcf_reset(struct device *dev, u32 bits, u32 val);
6536+extern void asic3_set_sdhwctrl(struct device *dev, u32 bits, u32 val);
6537+
6538+extern void asic3_set_led(struct device *dev, int led_num, int duty_time,
6539+ int cycle_time, int timebase);
6540+
6541+extern int asic3_register_mmc(struct device *dev);
6542+extern int asic3_unregister_mmc(struct device *dev);
6543+
6544+/* Accessors for GPIO banks */
6545+HDR_IPAQ_ASIC3_FN(a, A)
6546+HDR_IPAQ_ASIC3_FN(b, B)
6547+HDR_IPAQ_ASIC3_FN(c, C)
6548+HDR_IPAQ_ASIC3_FN(d, D)
6549+
6550+#define _IPAQ_ASIC3_GPIO_BANK_A 0
6551+#define _IPAQ_ASIC3_GPIO_BANK_B 1
6552+#define _IPAQ_ASIC3_GPIO_BANK_C 2
6553+#define _IPAQ_ASIC3_GPIO_BANK_D 3
6554+
6555+#define ASIC3_GPIO_bit(gpio) (1 << (gpio & 0xf))
6556+
6557+extern int asic3_get_gpio_bit(struct device *dev, int gpio);
6558+extern void asic3_set_gpio_bit(struct device *dev, int gpio, int val);
6559+extern int asic3_gpio_get_value(struct device *dev, unsigned gpio);
6560+extern void asic3_gpio_set_value(struct device *dev, unsigned gpio, int val);
6561+
6562+
6563+struct tmio_mmc_hwconfig;
6564+
6565+struct asic3_platform_data
6566+{
6567+ // Must be first member
6568+ struct gpiodev_ops gpiodev_ops;
6569+
6570+ struct {
6571+ u32 dir;
6572+ u32 init;
6573+ u32 sleep_mask;
6574+ u32 sleep_out;
6575+ u32 batt_fault_out;
6576+ u32 sleep_conf;
6577+ u32 alt_function;
6578+ } gpio_a, gpio_b, gpio_c, gpio_d;
6579+
6580+ int irq_base;
6581+ unsigned int bus_shift;
6582+
6583+ struct platform_device **child_platform_devs;
6584+ int num_child_platform_devs;
6585+
6586+ struct tmio_mmc_hwconfig *tmio_mmc_hwconfig;
6587+};
6588Index: linux-2.6.22/include/linux/soc/tmio_mmc.h
6589===================================================================
6590--- /dev/null 1970-01-01 00:00:00.000000000 +0000
6591+++ linux-2.6.22/include/linux/soc/tmio_mmc.h 2007-09-11 12:53:37.000000000 +0200
6592@@ -0,0 +1,17 @@
6593+#include <linux/platform_device.h>
6594+
6595+#define MMC_CLOCK_DISABLED 0
6596+#define MMC_CLOCK_ENABLED 1
6597+
6598+#define TMIO_WP_ALWAYS_RW ((void*)-1)
6599+
6600+struct tmio_mmc_hwconfig {
6601+ void (*hwinit)(struct platform_device *sdev);
6602+ void (*set_mmc_clock)(struct platform_device *sdev, int state);
6603+
6604+ /* NULL - use ASIC3 signal,
6605+ TMIO_WP_ALWAYS_RW - assume always R/W (e.g. miniSD)
6606+ otherwise - machine-specific handler */
6607+ int (*mmc_get_ro)(struct platform_device *pdev);
6608+ short address_shift;
6609+};
6610Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h
6611===================================================================
6612--- linux-2.6.22.orig/include/asm-arm/arch-pxa/pxa-regs.h 2007-09-11 12:53:34.000000000 +0200
6613+++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h 2007-09-11 12:53:37.000000000 +0200
6614@@ -2043,6 +2043,8 @@
6615 #define LDCMD_SOFINT (1 << 22)
6616 #define LDCMD_EOFINT (1 << 21)
6617
6618+#define LCCR4_13M_PCD_EN (1<<25) /* 13M PCD enable */
6619+#define LCCR4_PCDDIV (1<<31) /* PCD selection */
6620
6621 #define LCCR5_SOFM1 (1<<0) /* Start Of Frame Mask for Overlay 1 (channel 1) */
6622 #define LCCR5_SOFM2 (1<<1) /* Start Of Frame Mask for Overlay 2 (channel 2) */
6623Index: linux-2.6.22/drivers/mmc/host/Kconfig
6624===================================================================
6625--- linux-2.6.22.orig/drivers/mmc/host/Kconfig 2007-07-09 01:32:17.000000000 +0200
6626+++ linux-2.6.22/drivers/mmc/host/Kconfig 2007-09-11 12:53:37.000000000 +0200
6627@@ -100,3 +100,9 @@
6628 To compile this driver as a module, choose M here: the
6629 module will be called tifm_sd.
6630
6631+config MMC_ASIC3
6632+ tristate "HTC ASIC3 SD/MMC support"
6633+ depends on MMC && HTC_ASIC3
6634+ help
6635+ This provides support for the ASIC3 SD/MMC controller, used
6636+ in the iPAQ hx4700 and others.
6637Index: linux-2.6.22/drivers/mmc/host/Makefile
6638===================================================================
6639--- linux-2.6.22.orig/drivers/mmc/host/Makefile 2007-07-09 01:32:17.000000000 +0200
6640+++ linux-2.6.22/drivers/mmc/host/Makefile 2007-09-11 12:53:37.000000000 +0200
6641@@ -15,4 +15,4 @@
6642 obj-$(CONFIG_MMC_OMAP) += omap.o
6643 obj-$(CONFIG_MMC_AT91) += at91_mci.o
6644 obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
6645-
6646+obj-$(CONFIG_MMC_ASIC3) += asic3_mmc.o
6647Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.c
6648===================================================================
6649--- /dev/null 1970-01-01 00:00:00.000000000 +0000
6650+++ linux-2.6.22/drivers/mmc/host/asic3_mmc.c 2007-09-11 12:53:37.000000000 +0200
6651@@ -0,0 +1,900 @@
6652+/* Note that this driver can likely be merged into the tmio driver, so
6653+ * consider this code temporary. It works, though.
6654+ */
6655+/*
6656+ * linux/drivers/mmc/asic3_mmc.c
6657+ *
6658+ * Copyright (c) 2005 SDG Systems, LLC
6659+ *
6660+ * based on tmio_mmc.c
6661+ * Copyright (C) 2004 Ian Molton
6662+ *
6663+ * Refactored to support all ASIC3 devices, 2006 Paul Sokolovsky
6664+ *
6665+ * This program is free software; you can redistribute it and/or modify
6666+ * it under the terms of the GNU General Public License version 2 as
6667+ * published by the Free Software Foundation.
6668+ *
6669+ * Driver for the SD / SDIO cell found in:
6670+ *
6671+ * TC6393XB
6672+ *
6673+ * This driver draws mainly on scattered spec sheets, Reverse engineering
6674+ * of the toshiba e800 SD driver and some parts of the 2.4 ASIC3 driver (4 bit
6675+ * support).
6676+ *
6677+ * Supports MMC 1 bit transfers and SD 1 and 4 bit modes.
6678+ *
6679+ * TODO:
6680+ * Eliminate FIXMEs
6681+ * SDIO support
6682+ * Power management
6683+ * Handle MMC errors (at all)
6684+ *
6685+ */
6686+#include <linux/module.h>
6687+#include <linux/moduleparam.h>
6688+#include <linux/init.h>
6689+#include <linux/ioport.h>
6690+#include <linux/platform_device.h>
6691+#include <linux/interrupt.h>
6692+#include <linux/blkdev.h>
6693+#include <linux/delay.h>
6694+#include <linux/err.h>
6695+#include <linux/mmc/mmc.h>
6696+#include <linux/mmc/host.h>
6697+#include <linux/mmc/card.h>
6698+//#include <linux/mmc/protocol.h>
6699+#include <linux/mmc/sd.h>
6700+#include <linux/scatterlist.h>
6701+//#include <linux/soc-old.h>
6702+#include <linux/soc/asic3_base.h>
6703+#include <linux/soc/tmio_mmc.h>
6704+
6705+#include <asm/io.h>
6706+#include <asm/irq.h>
6707+#include <asm/mach/irq.h>
6708+#include <linux/clk.h>
6709+#include <asm/mach-types.h>
6710+
6711+#include <asm/hardware/ipaq-asic3.h>
6712+#include "asic3_mmc.h"
6713+
6714+struct asic3_mmc_host {
6715+ void *ctl_base;
6716+ struct device *asic3_dev; /* asic3 device */
6717+ struct tmio_mmc_hwconfig *hwconfig; /* HW config data/handlers, guaranteed != NULL */
6718+ unsigned long bus_shift;
6719+ struct mmc_command *cmd;
6720+ struct mmc_request *mrq;
6721+ struct mmc_data *data;
6722+ struct mmc_host *mmc;
6723+ int irq;
6724+ unsigned short clock_for_sd;
6725+
6726+ /* I/O related stuff */
6727+ struct scatterlist *sg_ptr;
6728+ unsigned int sg_len;
6729+ unsigned int sg_off;
6730+};
6731+
6732+static void
6733+mmc_finish_request(struct asic3_mmc_host *host)
6734+{
6735+ struct mmc_request *mrq = host->mrq;
6736+
6737+ /* Write something to end the command */
6738+ host->mrq = NULL;
6739+ host->cmd = NULL;
6740+ host->data = NULL;
6741+
6742+ mmc_request_done(host->mmc, mrq);
6743+}
6744+
6745+
6746+#define ASIC3_MMC_REG(host, block, reg) (*((volatile u16 *) ((host->ctl_base) + ((_IPAQ_ASIC3_## block ## _Base + _IPAQ_ASIC3_ ## block ## _ ## reg) >> (2 - host->bus_shift))) ))
6747+
6748+static void
6749+mmc_start_command(struct asic3_mmc_host *host, struct mmc_command *cmd)
6750+{
6751+ struct mmc_data *data = host->data;
6752+ int c = cmd->opcode;
6753+
6754+ DBG("Opcode: %d, base: %p\n", cmd->opcode, host->ctl_base);
6755+
6756+ if(cmd->opcode == MMC_STOP_TRANSMISSION) {
6757+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12;
6758+ cmd->resp[0] = cmd->opcode;
6759+ cmd->resp[1] = 0;
6760+ cmd->resp[2] = 0;
6761+ cmd->resp[3] = 0;
6762+ cmd->resp[4] = 0;
6763+ return;
6764+ }
6765+
6766+ switch(cmd->flags & 0x1f) {
6767+ case MMC_RSP_NONE: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL; break;
6768+ case MMC_RSP_R1: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1; break;
6769+ case MMC_RSP_R1B: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B; break;
6770+ case MMC_RSP_R2: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2; break;
6771+ case MMC_RSP_R3: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3; break;
6772+ default:
6773+ DBG("Unknown response type %d\n", cmd->flags & 0x1f);
6774+ break;
6775+ }
6776+
6777+ host->cmd = cmd;
6778+
6779+ if(cmd->opcode == MMC_APP_CMD) {
6780+ c |= APP_CMD;
6781+ }
6782+ if (cmd->opcode == MMC_GO_IDLE_STATE) {
6783+ c |= (3 << 8); /* This was removed from ipaq-asic3.h for some reason */
6784+ }
6785+ if(data) {
6786+ c |= SD_CTRL_COMMAND_DATA_PRESENT;
6787+ if(data->blocks > 1) {
6788+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12;
6789+ c |= SD_CTRL_COMMAND_MULTI_BLOCK;
6790+ }
6791+ if(data->flags & MMC_DATA_READ) {
6792+ c |= SD_CTRL_COMMAND_TRANSFER_READ;
6793+ }
6794+ /* MMC_DATA_WRITE does not require a bit to be set */
6795+ }
6796+
6797+ /* Enable the command and data interrupts */
6798+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
6799+ SD_CTRL_INTMASKCARD_RESPONSE_END
6800+ | SD_CTRL_INTMASKCARD_RW_END
6801+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_0
6802+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_0
6803+#if 0
6804+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_3
6805+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_3
6806+#endif
6807+ );
6808+
6809+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) = ~(
6810+ SD_CTRL_INTMASKBUFFER_UNK7
6811+ | SD_CTRL_INTMASKBUFFER_CMD_BUSY
6812+#if 0
6813+ | SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR
6814+ | SD_CTRL_INTMASKBUFFER_CRC_ERROR
6815+ | SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR
6816+ | SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT
6817+ | SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW
6818+ | SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW
6819+ | SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT
6820+ | SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE
6821+ | SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE
6822+ | SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS
6823+#endif
6824+ );
6825+
6826+ /* Send the command */
6827+ ASIC3_MMC_REG(host, SD_CTRL, Arg1) = cmd->arg >> 16;
6828+ ASIC3_MMC_REG(host, SD_CTRL, Arg0) = cmd->arg & 0xffff;
6829+ ASIC3_MMC_REG(host, SD_CTRL, Cmd) = c;
6830+}
6831+
6832+/* This chip always returns (at least?) as much data as you ask for. I'm
6833+ * unsure what happens if you ask for less than a block. This should be looked
6834+ * into to ensure that a funny length read doesnt mess up the controller data
6835+ * state machine.
6836+ *
6837+ * Aric: Statement above may not apply to ASIC3.
6838+ *
6839+ * FIXME - this chip cannot do 1 and 2 byte data requests in 4 bit mode
6840+ *
6841+ * Aric: Statement above may not apply to ASIC3.
6842+ */
6843+
6844+static struct tasklet_struct mmc_data_read_tasklet;
6845+
6846+static void
6847+mmc_data_transfer(unsigned long h)
6848+{
6849+ struct asic3_mmc_host *host = (struct asic3_mmc_host *)h;
6850+ struct mmc_data *data = host->data;
6851+ unsigned short *buf;
6852+ int count;
6853+ /* unsigned long flags; */
6854+
6855+ if(!data){
6856+ printk(KERN_WARNING DRIVER_NAME ": Spurious Data IRQ\n");
6857+ return;
6858+ }
6859+
6860+ /* local_irq_save(flags); */
6861+ /* buf = kmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ); */
6862+ buf = kmap(host->sg_ptr->page);
6863+ buf += host->sg_ptr->offset/2 + host->sg_off/2;
6864+
6865+ /*
6866+ * Ensure we dont read more than one block. The chip will interrupt us
6867+ * When the next block is available.
6868+ */
6869+ count = host->sg_ptr->length - host->sg_off;
6870+ if(count > data->blksz) {
6871+ count = data->blksz;
6872+ }
6873+
6874+ DBG("count: %08x, page: %p, offset: %08x flags %08x\n",
6875+ count, host->sg_ptr->page, host->sg_off, data->flags);
6876+
6877+ host->sg_off += count;
6878+
6879+ /* Transfer the data */
6880+ if(data->flags & MMC_DATA_READ) {
6881+ while(count > 0) {
6882+ /* Read two bytes from SD/MMC controller. */
6883+ *buf = ASIC3_MMC_REG(host, SD_CTRL, DataPort);
6884+ buf++;
6885+ count -= 2;
6886+ }
6887+ //flush_dcache_page(host->sg_ptr->page);
6888+ } else {
6889+ while(count > 0) {
6890+ /* Write two bytes to SD/MMC controller. */
6891+ ASIC3_MMC_REG(host, SD_CTRL, DataPort) = *buf;
6892+ buf++;
6893+ count -= 2;
6894+ }
6895+ }
6896+
6897+ /* kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ); */
6898+ kunmap(host->sg_ptr->page);
6899+ /* local_irq_restore(flags); */
6900+ if(host->sg_off == host->sg_ptr->length) {
6901+ host->sg_ptr++;
6902+ host->sg_off = 0;
6903+ --host->sg_len;
6904+ }
6905+
6906+ return;
6907+}
6908+
6909+static void
6910+mmc_data_end_irq(struct asic3_mmc_host *host)
6911+{
6912+ struct mmc_data *data = host->data;
6913+
6914+ host->data = NULL;
6915+
6916+ if(!data){
6917+ printk(KERN_WARNING DRIVER_NAME ": Spurious data end IRQ\n");
6918+ return;
6919+ }
6920+
6921+ if (data->error == MMC_ERR_NONE) {
6922+ data->bytes_xfered = data->blocks * data->blksz;
6923+ } else {
6924+ data->bytes_xfered = 0;
6925+ }
6926+
6927+ DBG("Completed data request\n");
6928+
6929+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = 0;
6930+
6931+ /* Make sure read enable interrupt and write enable interrupt are disabled */
6932+ if(data->flags & MMC_DATA_READ) {
6933+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) |= SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE;
6934+ } else {
6935+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) |= SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE;
6936+ }
6937+
6938+ mmc_finish_request(host);
6939+}
6940+
6941+static void
6942+mmc_cmd_irq(struct asic3_mmc_host *host, unsigned int buffer_stat)
6943+{
6944+ struct mmc_command *cmd = host->cmd;
6945+ u8 *buf = (u8 *)cmd->resp;
6946+ u16 data;
6947+
6948+ if(!host->cmd) {
6949+ printk(KERN_WARNING DRIVER_NAME ": Spurious CMD irq\n");
6950+ return;
6951+ }
6952+
6953+ host->cmd = NULL;
6954+ if(cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) {
6955+ /* R2 */
6956+ buf[12] = 0xff;
6957+ data = ASIC3_MMC_REG(host, SD_CTRL, Response0);
6958+ buf[13] = data & 0xff;
6959+ buf[14] = data >> 8;
6960+ data = ASIC3_MMC_REG(host, SD_CTRL, Response1);
6961+ buf[15] = data & 0xff;
6962+ buf[8] = data >> 8;
6963+ data = ASIC3_MMC_REG(host, SD_CTRL, Response2);
6964+ buf[9] = data & 0xff;
6965+ buf[10] = data >> 8;
6966+ data = ASIC3_MMC_REG(host, SD_CTRL, Response3);
6967+ buf[11] = data & 0xff;
6968+ buf[4] = data >> 8;
6969+ data = ASIC3_MMC_REG(host, SD_CTRL, Response4);
6970+ buf[5] = data & 0xff;
6971+ buf[6] = data >> 8;
6972+ data = ASIC3_MMC_REG(host, SD_CTRL, Response5);
6973+ buf[7] = data & 0xff;
6974+ buf[0] = data >> 8;
6975+ data = ASIC3_MMC_REG(host, SD_CTRL, Response6);
6976+ buf[1] = data & 0xff;
6977+ buf[2] = data >> 8;
6978+ data = ASIC3_MMC_REG(host, SD_CTRL, Response7);
6979+ buf[3] = data & 0xff;
6980+ } else if(cmd->flags & MMC_RSP_PRESENT) {
6981+ /* R1, R1B, R3 */
6982+ data = ASIC3_MMC_REG(host, SD_CTRL, Response0);
6983+ buf[0] = data & 0xff;
6984+ buf[1] = data >> 8;
6985+ data = ASIC3_MMC_REG(host, SD_CTRL, Response1);
6986+ buf[2] = data & 0xff;
6987+ buf[3] = data >> 8;
6988+ }
6989+ DBG("Response: %08x %08x %08x %08x\n", cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
6990+
6991+ if(buffer_stat & SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT) {
6992+ cmd->error = MMC_ERR_TIMEOUT;
6993+ } else if((buffer_stat & SD_CTRL_BUFFERSTATUS_CRC_ERROR) && (cmd->flags & MMC_RSP_CRC)) {
6994+ cmd->error = MMC_ERR_BADCRC;
6995+ } else if(buffer_stat &
6996+ (
6997+ SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS
6998+ | SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR
6999+ | SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR
7000+ | SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW
7001+ | SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW
7002+ | SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT
7003+ )
7004+ ) {
7005+ DBG("Buffer status ERROR 0x%04x - inside check buffer\n", buffer_stat);
7006+ DBG("detail0 error status 0x%04x\n", ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus0));
7007+ DBG("detail1 error status 0x%04x\n", ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus1));
7008+ cmd->error = MMC_ERR_FAILED;
7009+ }
7010+
7011+ if(cmd->error == MMC_ERR_NONE) {
7012+ switch (cmd->opcode) {
7013+ case SD_APP_SET_BUS_WIDTH:
7014+ if(cmd->arg == SD_BUS_WIDTH_4) {
7015+ host->clock_for_sd = SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD;
7016+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
7017+ MEM_CARD_OPTION_REQUIRED
7018+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
7019+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
7020+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_4;
7021+ } else {
7022+ host->clock_for_sd = 0;
7023+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
7024+ MEM_CARD_OPTION_REQUIRED
7025+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
7026+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
7027+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_1;
7028+ }
7029+ break;
7030+ case MMC_SELECT_CARD:
7031+ if((cmd->arg >> 16) == 0) {
7032+ /* We have been deselected. */
7033+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
7034+ MEM_CARD_OPTION_REQUIRED
7035+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
7036+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
7037+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_1;
7038+ }
7039+ }
7040+ }
7041+
7042+ /*
7043+ * If there is data to handle we enable data IRQs here, and we will
7044+ * ultimatley finish the request in the mmc_data_end_irq handler.
7045+ */
7046+ if(host->data && (cmd->error == MMC_ERR_NONE)){
7047+ if(host->data->flags & MMC_DATA_READ) {
7048+ /* Enable the read enable interrupt */
7049+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &=
7050+ ~SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE;
7051+ } else {
7052+ /* Enable the write enable interrupt */
7053+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &=
7054+ ~SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE;
7055+ }
7056+ } else {
7057+ /* There's no data, or we encountered an error, so finish now. */
7058+ mmc_finish_request(host);
7059+ }
7060+
7061+ return;
7062+}
7063+
7064+static void hwinit2_irqsafe(struct asic3_mmc_host *host);
7065+
7066+static irqreturn_t
7067+mmc_irq(int irq, void *irq_desc)
7068+{
7069+ struct asic3_mmc_host *host;
7070+ unsigned int breg, bmask, bstatus, creg, cmask, cstatus;
7071+
7072+ host = irq_desc;
7073+
7074+ /* asic3 bstatus has errors */
7075+ bstatus = ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl);
7076+ bmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer);
7077+ cstatus = ASIC3_MMC_REG(host, SD_CTRL, CardStatus);
7078+ cmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard);
7079+ breg = bstatus & ~bmask & ~DONT_CARE_BUFFER_BITS;
7080+ creg = cstatus & ~cmask & ~DONT_CARE_CARD_BITS;
7081+
7082+ if (!breg && !creg) {
7083+ /* This occurs sometimes for no known reason. It doesn't hurt
7084+ * anything, so I don't print it. */
7085+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &= ~breg;
7086+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) &= ~creg;
7087+ goto out;
7088+ }
7089+
7090+ while (breg || creg) {
7091+
7092+ /* XXX TODO: Need to handle errors in breg here. */
7093+
7094+ /*
7095+ * Card insert/remove. The mmc controlling code is stateless. That
7096+ * is, it doesn't care if it was an insert or a remove. It treats
7097+ * both the same.
7098+ */
7099+ /* XXX Asic3 has _3 versions of these status bits, too, for a second slot, perhaps? */
7100+ if (creg & (SD_CTRL_CARDSTATUS_CARD_INSERTED_0 | SD_CTRL_CARDSTATUS_CARD_REMOVED_0)) {
7101+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &=
7102+ ~(SD_CTRL_CARDSTATUS_CARD_REMOVED_0 | SD_CTRL_CARDSTATUS_CARD_INSERTED_0);
7103+ if(creg & SD_CTRL_CARDSTATUS_CARD_INSERTED_0) {
7104+ hwinit2_irqsafe(host);
7105+ }
7106+ mmc_detect_change(host->mmc,1);
7107+ }
7108+
7109+ /* Command completion */
7110+ if (creg & SD_CTRL_CARDSTATUS_RESPONSE_END) {
7111+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &=
7112+ ~(SD_CTRL_CARDSTATUS_RESPONSE_END);
7113+ mmc_cmd_irq(host, bstatus);
7114+ }
7115+
7116+ /* Data transfer */
7117+ if (breg & (SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE | SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE)) {
7118+ ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) &=
7119+ ~(SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE | SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE);
7120+ tasklet_schedule(&mmc_data_read_tasklet);
7121+ }
7122+
7123+ /* Data transfer completion */
7124+ if (creg & SD_CTRL_CARDSTATUS_RW_END) {
7125+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &= ~(SD_CTRL_CARDSTATUS_RW_END);
7126+ mmc_data_end_irq(host);
7127+ }
7128+
7129+ /* Check status - keep going until we've handled it all */
7130+ bstatus = ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl);
7131+ bmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer);
7132+ cstatus = ASIC3_MMC_REG(host, SD_CTRL, CardStatus);
7133+ cmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard);
7134+ breg = bstatus & ~bmask & ~DONT_CARE_BUFFER_BITS;
7135+ creg = cstatus & ~cmask & ~DONT_CARE_CARD_BITS;
7136+ }
7137+
7138+out:
7139+ /* Ensure all interrupt sources are cleared */
7140+ ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) = 0;
7141+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) = 0;
7142+ return IRQ_HANDLED;
7143+}
7144+
7145+static void
7146+mmc_start_data(struct asic3_mmc_host *host, struct mmc_data *data)
7147+{
7148+ DBG("setup data transfer: blocksize %08x nr_blocks %d, page: %08x, offset: %08x\n", data->blksz,
7149+ data->blocks, (int)data->sg->page, data->sg->offset);
7150+
7151+ host->sg_len = data->sg_len;
7152+ host->sg_ptr = data->sg;
7153+ host->sg_off = 0;
7154+ host->data = data;
7155+
7156+ /* Set transfer length and blocksize */
7157+ ASIC3_MMC_REG(host, SD_CTRL, TransferSectorCount) = data->blocks;
7158+ ASIC3_MMC_REG(host, SD_CTRL, MemCardXferDataLen) = data->blksz;
7159+}
7160+
7161+/* Process requests from the MMC layer */
7162+static void
7163+mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
7164+{
7165+ struct asic3_mmc_host *host = mmc_priv(mmc);
7166+
7167+ WARN_ON(host->mrq != NULL);
7168+
7169+ host->mrq = mrq;
7170+
7171+ /* If we're performing a data request we need to setup some
7172+ extra information */
7173+ if(mrq->data) {
7174+ mmc_start_data(host, mrq->data);
7175+ }
7176+
7177+ mmc_start_command(host, mrq->cmd);
7178+}
7179+
7180+/* Set MMC clock / power.
7181+ * Note: This controller uses a simple divider scheme therefore it cannot run
7182+ * a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as MMC
7183+ * wont run that fast, it has to be clocked at 12MHz which is the next slowest
7184+ * setting. This is likely not an issue because we are doing single 16-bit
7185+ * writes for data I/O.
7186+ */
7187+static void
7188+mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
7189+{
7190+ struct asic3_mmc_host *host = mmc_priv(mmc);
7191+ u32 clk = 0;
7192+
7193+ DBG("clock %uHz busmode %u powermode %u Vdd %u\n",
7194+ ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
7195+
7196+ if (ios->clock) {
7197+ clk = 0x80; /* slowest by default */
7198+ if(ios->clock >= 24000000 / 256) clk >>= 1;
7199+ if(ios->clock >= 24000000 / 128) clk >>= 1;
7200+ if(ios->clock >= 24000000 / 64) clk >>= 1;
7201+ if(ios->clock >= 24000000 / 32) clk >>= 1;
7202+ if(ios->clock >= 24000000 / 16) clk >>= 1;
7203+ if(ios->clock >= 24000000 / 8) clk >>= 1;
7204+ if(ios->clock >= 24000000 / 4) clk >>= 1;
7205+ if(ios->clock >= 24000000 / 2) clk >>= 1;
7206+ if(ios->clock >= 24000000 / 1) clk >>= 1;
7207+ if(clk == 0) { /* For fastest speed we disable the divider. */
7208+ ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 0;
7209+ } else {
7210+ ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 1;
7211+ }
7212+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
7213+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) =
7214+ host->clock_for_sd
7215+ | SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK
7216+ | clk;
7217+ msleep(10);
7218+ } else {
7219+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
7220+ }
7221+
7222+ switch (ios->power_mode) {
7223+ case MMC_POWER_OFF:
7224+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = 0;
7225+ msleep(1);
7226+ break;
7227+ case MMC_POWER_UP:
7228+ break;
7229+ case MMC_POWER_ON:
7230+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = SD_CONFIG_POWER1_PC_33V;
7231+ msleep(20);
7232+ break;
7233+ }
7234+}
7235+
7236+static int
7237+mmc_get_ro(struct mmc_host *mmc)
7238+{
7239+ struct asic3_mmc_host *host = mmc_priv(mmc);
7240+
7241+ /* Call custom handler for RO status */
7242+ if(host->hwconfig->mmc_get_ro) {
7243+ /* Special case for cards w/o WP lock (like miniSD) */
7244+ if (host->hwconfig->mmc_get_ro == (void*)-1) {
7245+ return 0;
7246+ } else {
7247+ struct platform_device *pdev = to_platform_device(mmc_dev(mmc));
7248+ return host->hwconfig->mmc_get_ro(pdev);
7249+ }
7250+ }
7251+
7252+ /* WRITE_PROTECT is active low */
7253+ return (ASIC3_MMC_REG(host, SD_CTRL, CardStatus) & SD_CTRL_CARDSTATUS_WRITE_PROTECT)?0:1;
7254+}
7255+
7256+static struct mmc_host_ops mmc_ops = {
7257+ .request = mmc_request,
7258+ .set_ios = mmc_set_ios,
7259+ .get_ro = mmc_get_ro,
7260+};
7261+
7262+static void
7263+hwinit2_irqsafe(struct asic3_mmc_host *host)
7264+{
7265+ ASIC3_MMC_REG(host, SD_CONFIG, Addr1) = 0x0000;
7266+ ASIC3_MMC_REG(host, SD_CONFIG, Addr0) = 0x0800;
7267+
7268+ ASIC3_MMC_REG(host, SD_CONFIG, ClkStop) = SD_CONFIG_CLKSTOP_ENABLE_ALL;
7269+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_CardDetect) = 2;
7270+ ASIC3_MMC_REG(host, SD_CONFIG, Command) = SD_CONFIG_COMMAND_MAE;
7271+
7272+ ASIC3_MMC_REG(host, SD_CTRL, SoftwareReset) = 0; /* reset on */
7273+ mdelay(2);
7274+
7275+ ASIC3_MMC_REG(host, SD_CTRL, SoftwareReset) = 1; /* reset off */
7276+ mdelay(2);
7277+
7278+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
7279+ MEM_CARD_OPTION_REQUIRED
7280+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
7281+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
7282+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_1
7283+ ;
7284+ host->clock_for_sd = 0;
7285+
7286+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
7287+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) = 0;
7288+ ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) = 0;
7289+ ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus0) = 0;
7290+ ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus1) = 0;
7291+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = 0;
7292+
7293+ ASIC3_MMC_REG(host, SDIO_CTRL, ClocknWaitCtrl) = 0x100;
7294+ /* *((unsigned short *)(((char *)host->ctl_base) + 0x938)) = 0x100; */
7295+
7296+ ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 0;
7297+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
7298+
7299+ mdelay(1);
7300+
7301+
7302+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
7303+ SD_CTRL_INTMASKCARD_RESPONSE_END
7304+ | SD_CTRL_INTMASKCARD_RW_END
7305+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_0
7306+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_0
7307+#if 0
7308+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_3
7309+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_3
7310+#endif
7311+ )
7312+ ; /* check */
7313+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) = 0xffff; /* IRQs off */
7314+
7315+ /*
7316+ * ASIC3_MMC_REG(host, SD_CTRL, TransactionCtrl) = SD_CTRL_TRANSACTIONCONTROL_SET;
7317+ * Wince has 0x1000
7318+ */
7319+ /* ASIC3_MMC_REG(host, SD_CTRL, TransactionCtrl) = 0x1000; */
7320+
7321+
7322+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SDPWR, ASIC3_SDHWCTRL_SDPWR); /* turn on power at controller(?) */
7323+
7324+}
7325+
7326+static void
7327+hwinit(struct asic3_mmc_host *host, struct platform_device *pdev)
7328+{
7329+ /* Call custom handler for enabling clock (if needed) */
7330+ if(host->hwconfig->set_mmc_clock)
7331+ host->hwconfig->set_mmc_clock(pdev, MMC_CLOCK_ENABLED);
7332+
7333+ /* Not sure if it must be done bit by bit, but leaving as-is */
7334+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_LEVCD, ASIC3_SDHWCTRL_LEVCD);
7335+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_LEVWP, ASIC3_SDHWCTRL_LEVWP);
7336+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, 0);
7337+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_PCLR, 0);
7338+
7339+ asic3_set_clock_cdex (host->asic3_dev,
7340+ CLOCK_CDEX_EX1 | CLOCK_CDEX_EX0, CLOCK_CDEX_EX1 | CLOCK_CDEX_EX0);
7341+ msleep(1);
7342+
7343+ asic3_set_clock_sel (host->asic3_dev,
7344+ CLOCK_SEL_SD_HCLK_SEL | CLOCK_SEL_SD_BCLK_SEL,
7345+ CLOCK_SEL_SD_HCLK_SEL | 0); /* ? */
7346+
7347+ asic3_set_clock_cdex (host->asic3_dev,
7348+ CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS,
7349+ CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS);
7350+ msleep(1);
7351+
7352+ asic3_set_extcf_select(host->asic3_dev, ASIC3_EXTCF_SD_MEM_ENABLE, ASIC3_EXTCF_SD_MEM_ENABLE);
7353+
7354+ /* Long Delay */
7355+ if( !machine_is_h4700())
7356+ msleep(500);
7357+
7358+ hwinit2_irqsafe(host);
7359+}
7360+
7361+#ifdef CONFIG_PM
7362+static int
7363+mmc_suspend(struct platform_device *pdev, pm_message_t state)
7364+{
7365+ struct mmc_host *mmc = platform_get_drvdata(pdev);
7366+ struct asic3_mmc_host *host = mmc_priv(mmc);
7367+ int ret;
7368+
7369+ ret = mmc_suspend_host(mmc, state);
7370+
7371+ if (ret) {
7372+ printk(KERN_ERR DRIVER_NAME ": Could not suspend MMC host, hardware not suspended");
7373+ return ret;
7374+ }
7375+
7376+ /* disable the card insert / remove interrupt while sleeping */
7377+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
7378+ SD_CTRL_INTMASKCARD_RESPONSE_END
7379+ | SD_CTRL_INTMASKCARD_RW_END);
7380+
7381+ /* disable clock */
7382+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
7383+ ASIC3_MMC_REG(host, SD_CONFIG, ClkStop) = 0;
7384+
7385+ /* power down */
7386+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = 0;
7387+
7388+ asic3_set_clock_cdex (host->asic3_dev,
7389+ CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS, 0);
7390+
7391+ /* disable core clock */
7392+ if(host->hwconfig->set_mmc_clock)
7393+ host->hwconfig->set_mmc_clock(pdev, MMC_CLOCK_DISABLED);
7394+
7395+ /* Put in suspend mode */
7396+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, ASIC3_SDHWCTRL_SUSPEND);
7397+ return 0;
7398+}
7399+
7400+static int
7401+mmc_resume(struct platform_device *pdev)
7402+{
7403+ struct mmc_host *mmc = platform_get_drvdata(pdev);
7404+ struct asic3_mmc_host *host = mmc_priv(mmc);
7405+
7406+ printk(KERN_INFO "%s: starting resume\n", DRIVER_NAME);
7407+
7408+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, 0);
7409+ hwinit(host, pdev);
7410+
7411+ /* re-enable card remove / insert interrupt */
7412+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
7413+ SD_CTRL_INTMASKCARD_RESPONSE_END
7414+ | SD_CTRL_INTMASKCARD_RW_END
7415+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_0
7416+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_0 );
7417+
7418+ mmc_resume_host(mmc);
7419+
7420+ printk(KERN_INFO "%s: finished resume\n", DRIVER_NAME);
7421+ return 0;
7422+}
7423+#endif
7424+
7425+static int
7426+mmc_probe(struct platform_device *pdev)
7427+{
7428+ struct mmc_host *mmc;
7429+ struct asic3_mmc_host *host = NULL;
7430+ int retval = 0;
7431+ struct tmio_mmc_hwconfig *mmc_config = (struct tmio_mmc_hwconfig *)pdev->dev.platform_data;
7432+
7433+ /* bus_shift is mandatory */
7434+ if (!mmc_config) {
7435+ printk(KERN_ERR DRIVER_NAME ": Invalid configuration\n");
7436+ return -EINVAL;
7437+ }
7438+
7439+ mmc = mmc_alloc_host(sizeof(struct asic3_mmc_host) + 128, &pdev->dev);
7440+ if (!mmc) {
7441+ retval = -ENOMEM;
7442+ goto exceptional_return;
7443+ }
7444+
7445+ host = mmc_priv(mmc);
7446+ host->mmc = mmc;
7447+ platform_set_drvdata(pdev, mmc);
7448+
7449+ host->ctl_base = 0;
7450+ host->hwconfig = mmc_config;
7451+ host->bus_shift = mmc_config->address_shift;
7452+ host->asic3_dev = pdev->dev.parent;
7453+ host->clock_for_sd = 0;
7454+
7455+ tasklet_init(&mmc_data_read_tasklet, mmc_data_transfer, (unsigned long)host);
7456+
7457+ host->ctl_base = ioremap_nocache ((unsigned long)pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start);
7458+ if(!host->ctl_base){
7459+ printk(KERN_ERR DRIVER_NAME ": Could not map ASIC3 SD controller\n");
7460+ retval = -ENODEV;
7461+ goto exceptional_return;
7462+ }
7463+
7464+ printk(DRIVER_NAME ": ASIC3 MMC/SD Driver, controller at 0x%lx\n", (unsigned long)pdev->resource[0].start);
7465+
7466+ mmc->ops = &mmc_ops;
7467+ mmc->caps = MMC_CAP_4_BIT_DATA;
7468+ mmc->f_min = 46875; /* ARIC: not sure what these should be */
7469+ mmc->f_max = 24000000; /* ARIC: not sure what these should be */
7470+ mmc->ocr_avail = MMC_VDD_32_33;
7471+
7472+ hwinit(host, pdev);
7473+
7474+
7475+ host->irq = pdev->resource[1].start;
7476+
7477+ retval = request_irq(host->irq, mmc_irq, 0, DRIVER_NAME, host);
7478+ if(retval) {
7479+ printk(KERN_ERR DRIVER_NAME ": Unable to get interrupt\n");
7480+ retval = -ENODEV;
7481+ goto exceptional_return;
7482+ }
7483+ set_irq_type(host->irq, IRQT_FALLING);
7484+
7485+ mmc_add_host(mmc);
7486+
7487+#ifdef CONFIG_PM
7488+ // resume_timer.function = resume_timer_callback;
7489+ // resume_timer.data = 0;
7490+ // init_timer(&resume_timer);
7491+#endif
7492+
7493+ return 0;
7494+
7495+exceptional_return:
7496+ if (mmc) {
7497+ mmc_free_host(mmc);
7498+ }
7499+ if(host && host->ctl_base) iounmap(host->ctl_base);
7500+ return retval;
7501+}
7502+
7503+static int
7504+mmc_remove(struct platform_device *pdev)
7505+{
7506+ struct mmc_host *mmc = platform_get_drvdata(pdev);
7507+
7508+ platform_set_drvdata(pdev, NULL);
7509+
7510+ if (mmc) {
7511+ struct asic3_mmc_host *host = mmc_priv(mmc);
7512+ mmc_remove_host(mmc);
7513+ free_irq(host->irq, host);
7514+ /* FIXME - we might want to consider stopping the chip here... */
7515+ iounmap(host->ctl_base);
7516+ mmc_free_host(mmc); /* FIXME - why does this call hang? */
7517+ }
7518+ return 0;
7519+}
7520+
7521+/* ------------------- device registration ----------------------- */
7522+
7523+static struct platform_driver mmc_asic3_driver = {
7524+ .driver = {
7525+ .name = DRIVER_NAME,
7526+ },
7527+ .probe = mmc_probe,
7528+ .remove = mmc_remove,
7529+#ifdef CONFIG_PM
7530+ .suspend = mmc_suspend,
7531+ .resume = mmc_resume,
7532+#endif
7533+};
7534+
7535+static int __init mmc_init(void)
7536+{
7537+ return platform_driver_register(&mmc_asic3_driver);
7538+}
7539+
7540+static void __exit mmc_exit(void)
7541+{
7542+ platform_driver_unregister(&mmc_asic3_driver);
7543+}
7544+
7545+late_initcall(mmc_init);
7546+module_exit(mmc_exit);
7547+
7548+MODULE_DESCRIPTION("HTC ASIC3 SD/MMC driver");
7549+MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");
7550+MODULE_LICENSE("GPL");
7551+
7552Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.h
7553===================================================================
7554--- /dev/null 1970-01-01 00:00:00.000000000 +0000
7555+++ linux-2.6.22/drivers/mmc/host/asic3_mmc.h 2007-09-11 12:53:37.000000000 +0200
7556@@ -0,0 +1,25 @@
7557+#ifndef __ASIC3_MMC_H
7558+#define __ASIC3_MMC_H
7559+
7560+#define DRIVER_NAME "asic3_mmc"
7561+
7562+#ifdef CONFIG_MMC_DEBUG
7563+#define DBG(x...) printk(DRIVER_NAME ": " x)
7564+#else
7565+#define DBG(x...) do { } while (0)
7566+#endif
7567+
7568+/* Response types */
7569+#define APP_CMD 0x0040
7570+
7571+#define SD_CONFIG_CLKSTOP_ENABLE_ALL 0x1f
7572+
7573+#define DONT_CARE_CARD_BITS ( \
7574+ SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 \
7575+ | SD_CTRL_INTMASKCARD_WRITE_PROTECT \
7576+ | SD_CTRL_INTMASKCARD_UNK6 \
7577+ | SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 \
7578+ )
7579+#define DONT_CARE_BUFFER_BITS ( SD_CTRL_INTMASKBUFFER_UNK7 | SD_CTRL_INTMASKBUFFER_CMD_BUSY )
7580+
7581+#endif // __ASIC3_MMC_H
7582Index: linux-2.6.22/drivers/input/keyboard/Makefile
7583===================================================================
7584--- linux-2.6.22.orig/drivers/input/keyboard/Makefile 2007-07-09 01:32:17.000000000 +0200
7585+++ linux-2.6.22/drivers/input/keyboard/Makefile 2007-09-11 12:53:37.000000000 +0200
7586@@ -21,4 +21,4 @@
7587 obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o
7588 obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
7589 obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
7590-
7591+obj-$(CONFIG_KEYBOARD_ASIC3) += asic3_keys.o
7592Index: linux-2.6.22/drivers/input/keyboard/asic3_keys.c
7593===================================================================
7594--- /dev/null 1970-01-01 00:00:00.000000000 +0000
7595+++ linux-2.6.22/drivers/input/keyboard/asic3_keys.c 2007-09-11 12:53:37.000000000 +0200
7596@@ -0,0 +1,131 @@
7597+/*
7598+ * Generic buttons driver for ASIC3 SoC.
7599+ *
7600+ * This file is subject to the terms and conditions of the GNU General Public
7601+ * License. See the file COPYING in the main directory of this archive for
7602+ * more details.
7603+ *
7604+ * Copyright (C) 2003 Joshua Wise
7605+ * Copyright (C) 2005 Pawel Kolodziejski
7606+ * Copyright (C) 2006 Paul Sokolovsky
7607+ *
7608+ */
7609+
7610+#include <linux/input.h>
7611+#include <linux/module.h>
7612+#include <linux/init.h>
7613+#include <linux/interrupt.h>
7614+#include <linux/platform_device.h>
7615+#include <linux/irq.h>
7616+#include <linux/soc/asic3_base.h>
7617+#include <asm/mach/arch.h>
7618+#include <asm/mach/map.h>
7619+#include <asm/arch/irqs.h>
7620+#include <asm/hardware.h>
7621+#include <asm/hardware/ipaq-asic3.h>
7622+#include <asm/hardware/asic3_keys.h>
7623+
7624+static irqreturn_t asic3_keys_asic_handle(int irq, void *data)
7625+{
7626+ struct asic3_keys_platform_data *pdata = data;
7627+ int i, base_irq;
7628+
7629+ base_irq = asic3_irq_base(pdata->asic3_dev);
7630+ for (i = 0; i < pdata->nbuttons; i++) {
7631+ struct asic3_keys_button *b = &pdata->buttons[i];
7632+ if ((base_irq + b->gpio) == irq) {
7633+ int state = !!asic3_gpio_get_value(pdata->asic3_dev, b->gpio);
7634+
7635+ if (pdata->buttons[i].type == EV_SW)
7636+ input_report_switch(pdata->input, pdata->buttons[i].keycode, state ^ b->active_low);
7637+ else
7638+ input_report_key(pdata->input, b->keycode, state ^ b->active_low);
7639+ input_sync(pdata->input);
7640+ }
7641+ }
7642+
7643+ return IRQ_HANDLED;
7644+}
7645+
7646+static int __devinit asic3_keys_probe(struct platform_device *pdev)
7647+{
7648+ struct asic3_keys_platform_data *pdata = pdev->dev.platform_data;
7649+ int i, base_irq;
7650+ int j, ret;
7651+
7652+ pdata->input = input_allocate_device();
7653+
7654+ base_irq = asic3_irq_base(pdata->asic3_dev);
7655+
7656+ for (i = 0; i < pdata->nbuttons; i++) {
7657+ struct asic3_keys_button *b = &pdata->buttons[i];
7658+ set_bit(b->keycode, pdata->input->keybit);
7659+ ret=request_irq(base_irq + b->gpio, asic3_keys_asic_handle, SA_SAMPLE_RANDOM, b->desc, pdata);
7660+ if (ret)
7661+ {
7662+ printk(KERN_NOTICE "Failed to allocate asic3_keys irq=%d.\n",b->gpio);
7663+
7664+ for(j=0; j<i ; j++)
7665+ free_irq(base_irq + pdata->buttons[i].gpio, NULL);
7666+
7667+ input_unregister_device (pdata->input);
7668+
7669+ return -ENODEV;
7670+ }
7671+
7672+ set_irq_type(base_irq + b->gpio, IRQT_BOTHEDGE);
7673+ if (pdata->buttons[i].type == EV_SW) {
7674+ pdata->input->evbit[0] |= BIT(EV_SW);
7675+ set_bit(b->keycode, pdata->input->swbit);
7676+ } else {
7677+ pdata->input->evbit[0] |= BIT(EV_KEY);
7678+ set_bit(b->keycode, pdata->input->keybit);
7679+ }
7680+ }
7681+
7682+ pdata->input->name = pdev->name;
7683+ input_register_device(pdata->input);
7684+
7685+ return 0;
7686+}
7687+
7688+static int __devexit asic3_keys_remove(struct platform_device *pdev)
7689+{
7690+ struct asic3_keys_platform_data *pdata = pdev->dev.platform_data;
7691+ int i, base_irq;
7692+
7693+ base_irq = asic3_irq_base(pdata->asic3_dev);
7694+ for (i = 0; i < pdata->nbuttons; i++) {
7695+ free_irq(base_irq + pdata->buttons[i].gpio, NULL);
7696+ }
7697+
7698+ input_unregister_device(pdata->input);
7699+
7700+ return 0;
7701+}
7702+
7703+
7704+static struct platform_driver asic3_keys_driver = {
7705+ .probe = asic3_keys_probe,
7706+ .remove = __devexit_p(asic3_keys_remove),
7707+ .driver = {
7708+ .name = "asic3-keys",
7709+ },
7710+};
7711+
7712+static int __init asic3_keys_init(void)
7713+{
7714+ return platform_driver_register(&asic3_keys_driver);
7715+}
7716+
7717+static void __exit asic3_keys_exit(void)
7718+{
7719+ platform_driver_unregister(&asic3_keys_driver);
7720+}
7721+
7722+module_init(asic3_keys_init);
7723+module_exit(asic3_keys_exit);
7724+
7725+MODULE_AUTHOR("Joshua Wise, Pawel Kolodziejski, Paul Sokolovsky");
7726+MODULE_DESCRIPTION("Buttons driver for HTC ASIC3 SoC");
7727+MODULE_LICENSE("GPL");
7728Index: linux-2.6.22/include/asm-arm/arch-pxa/irqs.h
7729===================================================================
7730--- linux-2.6.22.orig/include/asm-arm/arch-pxa/irqs.h 2007-09-11 12:53:24.000000000 +0200
7731+++ linux-2.6.22/include/asm-arm/arch-pxa/irqs.h 2007-09-11 12:53:37.000000000 +0200
7732@@ -172,6 +172,8 @@
7733 defined(CONFIG_MACH_LOGICPD_PXA270) || \
7734 defined(CONFIG_MACH_MAINSTONE)
7735 #define NR_IRQS (IRQ_BOARD_END)
7736+#elif defined(CONFIG_MACH_HTCUNIVERSAL)
7737+#define NR_IRQS (IRQ_BOARD_START + 96)
7738 #else
7739 #define NR_IRQS (IRQ_BOARD_START)
7740 #endif
7741Index: linux-2.6.22/include/linux/ioport.h
7742===================================================================
7743--- linux-2.6.22.orig/include/linux/ioport.h 2007-07-09 01:32:17.000000000 +0200
7744+++ linux-2.6.22/include/linux/ioport.h 2007-09-11 12:53:37.000000000 +0200
7745@@ -56,6 +56,7 @@
7746 #define IORESOURCE_IRQ_HIGHLEVEL (1<<2)
7747 #define IORESOURCE_IRQ_LOWLEVEL (1<<3)
7748 #define IORESOURCE_IRQ_SHAREABLE (1<<4)
7749+#define IORESOURCE_IRQ_SOC_SUBDEVICE (1<<5)
7750
7751 /* ISA PnP DMA specific bits (IORESOURCE_BITS) */
7752 #define IORESOURCE_DMA_TYPE_MASK (3<<0)
7753Index: linux-2.6.22/drivers/video/backlight/Kconfig
7754===================================================================
7755--- linux-2.6.22.orig/drivers/video/backlight/Kconfig 2007-09-11 12:53:30.000000000 +0200
7756+++ linux-2.6.22/drivers/video/backlight/Kconfig 2007-09-11 12:53:37.000000000 +0200
7757@@ -40,7 +40,7 @@
7758
7759 config BACKLIGHT_CORGI
7760 tristate "Sharp Corgi Backlight Driver (SL Series)"
7761- depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL
7762+ depends on BACKLIGHT_CLASS_DEVICE
7763 default y
7764 help
7765 If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
7766Index: linux-2.6.22/drivers/video/backlight/corgi_bl.c
7767===================================================================
7768--- linux-2.6.22.orig/drivers/video/backlight/corgi_bl.c 2007-07-09 01:32:17.000000000 +0200
7769+++ linux-2.6.22/drivers/video/backlight/corgi_bl.c 2007-09-11 12:53:37.000000000 +0200
7770@@ -24,7 +24,7 @@
7771 static int corgibl_intensity;
7772 static struct backlight_properties corgibl_data;
7773 static struct backlight_device *corgi_backlight_device;
7774-static struct corgibl_machinfo *bl_machinfo;
7775+static struct generic_bl_info *bl_machinfo;
7776
7777 static unsigned long corgibl_flags;
7778 #define CORGIBL_SUSPENDED 0x01
7779@@ -107,7 +107,7 @@
7780
7781 static int corgibl_probe(struct platform_device *pdev)
7782 {
7783- struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
7784+ struct generic_bl_info *machinfo = pdev->dev.platform_data;
7785
7786 bl_machinfo = machinfo;
7787 if (!machinfo->limit_mask)
7788Index: linux-2.6.22/arch/arm/mach-pxa/corgi.c
7789===================================================================
7790--- linux-2.6.22.orig/arch/arm/mach-pxa/corgi.c 2007-09-11 12:53:32.000000000 +0200
7791+++ linux-2.6.22/arch/arm/mach-pxa/corgi.c 2007-09-11 12:53:37.000000000 +0200
7792@@ -20,6 +20,7 @@
7793 #include <linux/interrupt.h>
7794 #include <linux/mmc/host.h>
7795 #include <linux/pm.h>
7796+#include <linux/backlight.h>
7797
7798 #include <asm/setup.h>
7799 #include <asm/memory.h>
7800@@ -143,7 +144,7 @@
7801 /*
7802 * Corgi Backlight Device
7803 */
7804-static struct corgibl_machinfo corgi_bl_machinfo = {
7805+static struct generic_bl_info corgi_bl_machinfo = {
7806 .max_intensity = 0x2f,
7807 .default_intensity = 0x1f,
7808 .limit_mask = 0x0b,
7809Index: linux-2.6.22/arch/arm/mach-pxa/spitz.c
7810===================================================================
7811--- linux-2.6.22.orig/arch/arm/mach-pxa/spitz.c 2007-09-11 12:53:33.000000000 +0200
7812+++ linux-2.6.22/arch/arm/mach-pxa/spitz.c 2007-09-11 12:53:37.000000000 +0200
7813@@ -222,7 +222,7 @@
7814 /*
7815 * Spitz Backlight Device
7816 */
7817-static struct corgibl_machinfo spitz_bl_machinfo = {
7818+static struct generic_bl_info spitz_bl_machinfo = {
7819 .default_intensity = 0x1f,
7820 .limit_mask = 0x0b,
7821 .max_intensity = 0x2f,
7822Index: linux-2.6.22/include/asm-arm/arch-pxa/serial.h
7823===================================================================
7824--- /dev/null 1970-01-01 00:00:00.000000000 +0000
7825+++ linux-2.6.22/include/asm-arm/arch-pxa/serial.h 2007-09-11 12:53:37.000000000 +0200
7826@@ -0,0 +1,78 @@
7827+/*
7828+ * linux/include/asm-arm/arch-pxa/serial.h
7829+ *
7830+ * Author: Nicolas Pitre
7831+ * Copyright: (C) 2001 MontaVista Software Inc.
7832+ *
7833+ * This program is free software; you can redistribute it and/or modify
7834+ * it under the terms of the GNU General Public License version 2 as
7835+ * published by the Free Software Foundation.
7836+ */
7837+
7838+#include <asm/arch/pxa-regs.h>
7839+
7840+#define BAUD_BASE 921600
7841+
7842+/* Standard COM flags */
7843+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
7844+
7845+#define STD_SERIAL_PORT_DEFNS \
7846+ { \
7847+ type: PORT_PXA, \
7848+ xmit_fifo_size: 64, \
7849+ baud_base: BAUD_BASE, \
7850+ iomem_base: &FFUART, \
7851+ iomem_reg_shift: 2, \
7852+ io_type: SERIAL_IO_MEM, \
7853+ irq: IRQ_FFUART, \
7854+ flags: STD_COM_FLAGS, \
7855+ }, { \
7856+ type: PORT_PXA, \
7857+ xmit_fifo_size: 64, \
7858+ baud_base: BAUD_BASE, \
7859+ iomem_base: &STUART, \
7860+ iomem_reg_shift: 2, \
7861+ io_type: SERIAL_IO_MEM, \
7862+ irq: IRQ_STUART, \
7863+ flags: STD_COM_FLAGS, \
7864+ }, { \
7865+ type: PORT_PXA, \
7866+ xmit_fifo_size: 64, \
7867+ baud_base: BAUD_BASE, \
7868+ iomem_base: &BTUART, \
7869+ iomem_reg_shift: 2, \
7870+ io_type: SERIAL_IO_MEM, \
7871+ irq: IRQ_BTUART, \
7872+ flags: STD_COM_FLAGS, \
7873+ }
7874+
7875+#define EXTRA_SERIAL_PORT_DEFNS
7876+
7877+struct platform_pxa_serial_funcs {
7878+
7879+ /* Initialize whatever is connected to this serial port. */
7880+ void (*configure)(int state);
7881+#define PXA_UART_CFG_PRE_STARTUP 0
7882+#define PXA_UART_CFG_POST_STARTUP 1
7883+#define PXA_UART_CFG_PRE_SHUTDOWN 2
7884+#define PXA_UART_CFG_POST_SHUTDOWN 3
7885+
7886+ /* Enable or disable the individual transmitter/receiver submodules.
7887+ * On transceivers without echo cancellation (e.g. SIR)
7888+ * transmitter always has priority; e.g. if both bits are set,
7889+ * only the transmitter is enabled. */
7890+ void (*set_txrx)(int txrx);
7891+#define PXA_SERIAL_TX 1
7892+#define PXA_SERIAL_RX 2
7893+
7894+ /* Get the current state of tx/rx. */
7895+ int (*get_txrx)(void);
7896+
7897+ int (*suspend)(struct platform_device *dev, pm_message_t state);
7898+ int (*resume)(struct platform_device *dev);
7899+};
7900+
7901+void pxa_set_ffuart_info(struct platform_pxa_serial_funcs *ffuart_funcs);
7902+void pxa_set_btuart_info(struct platform_pxa_serial_funcs *btuart_funcs);
7903+void pxa_set_stuart_info(struct platform_pxa_serial_funcs *stuart_funcs);
7904+void pxa_set_hwuart_info(struct platform_pxa_serial_funcs *hwuart_funcs);
7905Index: linux-2.6.22/drivers/serial/pxa.c
7906===================================================================
7907--- linux-2.6.22.orig/drivers/serial/pxa.c 2007-07-09 01:32:17.000000000 +0200
7908+++ linux-2.6.22/drivers/serial/pxa.c 2007-09-11 12:53:37.000000000 +0200
7909@@ -46,6 +46,7 @@
7910 #include <asm/io.h>
7911 #include <asm/hardware.h>
7912 #include <asm/irq.h>
7913+#include <asm/arch/serial.h>
7914 #include <asm/arch/pxa-regs.h>
7915
7916
7917@@ -59,6 +60,14 @@
7918 char *name;
7919 };
7920
7921+
7922+#define IS_METHOD(dev, method) (dev && (dev)->platform_data && ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method)
7923+#define METHOD_CALL(dev, method) \
7924+ ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method()
7925+#define SAFE_METHOD_CALL(dev, method, args...) \
7926+ if (IS_METHOD(dev, method)) \
7927+ ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method(args)
7928+
7929 static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
7930 {
7931 offset <<= 2;
7932@@ -346,6 +355,9 @@
7933 unsigned long flags;
7934 int retval;
7935
7936+ /* Perform platform-specific port initialization, if needed. */
7937+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_STARTUP);
7938+
7939 if (port->line == 3) /* HWUART */
7940 up->mcr |= UART_MCR_AFE;
7941 else
7942@@ -401,6 +413,12 @@
7943 (void) serial_in(up, UART_IIR);
7944 (void) serial_in(up, UART_MSR);
7945
7946+ /*
7947+ * Perform platform-specific port initialization if needed
7948+ */
7949+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_STARTUP);
7950+ SAFE_METHOD_CALL(port->dev, set_txrx, PXA_SERIAL_RX);
7951+
7952 return 0;
7953 }
7954
7955@@ -409,6 +427,8 @@
7956 struct uart_pxa_port *up = (struct uart_pxa_port *)port;
7957 unsigned long flags;
7958
7959+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_SHUTDOWN);
7960+
7961 free_irq(up->port.irq, up);
7962
7963 /*
7964@@ -430,6 +450,8 @@
7965 UART_FCR_CLEAR_RCVR |
7966 UART_FCR_CLEAR_XMIT);
7967 serial_out(up, UART_FCR, 0);
7968+
7969+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_SHUTDOWN);
7970 }
7971
7972 static void
7973Index: linux-2.6.22/arch/arm/mach-pxa/generic.c
7974===================================================================
7975--- linux-2.6.22.orig/arch/arm/mach-pxa/generic.c 2007-09-11 12:53:11.000000000 +0200
7976+++ linux-2.6.22/arch/arm/mach-pxa/generic.c 2007-09-11 12:53:37.000000000 +0200
7977@@ -42,6 +42,7 @@
7978 #include <asm/arch/mmc.h>
7979 #include <asm/arch/irda.h>
7980 #include <asm/arch/i2c.h>
7981+#include <asm/arch/serial.h>
7982
7983 #include "devices.h"
7984 #include "generic.h"
7985@@ -346,6 +347,18 @@
7986 .id = 3,
7987 };
7988
7989+void __init pxa_set_ffuart_info(struct platform_pxa_serial_funcs *info)
7990+{
7991+ pxa_device_ffuart.dev.platform_data = info;
7992+}
7993+EXPORT_SYMBOL(pxa_set_ffuart_info);
7994+
7995+void __init pxa_set_btuart_info(struct platform_pxa_serial_funcs *info)
7996+{
7997+ pxa_device_btuart.dev.platform_data = info;
7998+}
7999+EXPORT_SYMBOL(pxa_set_btuart_info);
8000+
8001 static struct resource pxai2c_resources[] = {
8002 {
8003 .start = 0x40301680,
8004Index: linux-2.6.22/drivers/leds/Makefile
8005===================================================================
8006--- linux-2.6.22.orig/drivers/leds/Makefile 2007-09-11 12:53:14.000000000 +0200
8007+++ linux-2.6.22/drivers/leds/Makefile 2007-09-11 12:53:37.000000000 +0200
8008@@ -16,6 +16,7 @@
8009 obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
8010 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
8011 obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
8012+obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
8013 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
8014
8015 # LED Triggers
8016Index: linux-2.6.22/arch/arm/Kconfig
8017===================================================================
8018--- linux-2.6.22.orig/arch/arm/Kconfig 2007-09-11 12:53:32.000000000 +0200
8019+++ linux-2.6.22/arch/arm/Kconfig 2007-09-11 12:53:37.000000000 +0200
8020@@ -1032,6 +1032,8 @@
8021
8022 source "drivers/w1/Kconfig"
8023
8024+source "drivers/power/Kconfig"
8025+
8026 source "drivers/hwmon/Kconfig"
8027
8028 #source "drivers/l3/Kconfig"
8029Index: linux-2.6.22/drivers/input/keyboard/Kconfig
8030===================================================================
8031--- linux-2.6.22.orig/drivers/input/keyboard/Kconfig 2007-09-11 14:28:45.000000000 +0200
8032+++ linux-2.6.22/drivers/input/keyboard/Kconfig 2007-09-11 14:29:05.000000000 +0200
8033@@ -253,4 +253,11 @@
8034 To compile this driver as a module, choose M here: the
8035 module will be called gpio-keys.
8036
8037+config KEYBOARD_ASIC3
8038+ tristate "Buttons on ASIC3 SoC GPIOs (iPaqs, etc.)"
8039+ depends on HTC_ASIC3
8040+ help
8041+ This enables support for the buttons attached to GPIOs of
8042+ HTC ASIC3 peripheral controller.
8043+
8044 endif