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