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