diff options
Diffstat (limited to 'packages/linux/linux-rp-2.6.23+2.6.24-rc6+git/htcuni.patch')
-rw-r--r-- | packages/linux/linux-rp-2.6.23+2.6.24-rc6+git/htcuni.patch | 8044 |
1 files changed, 0 insertions, 8044 deletions
diff --git a/packages/linux/linux-rp-2.6.23+2.6.24-rc6+git/htcuni.patch b/packages/linux/linux-rp-2.6.23+2.6.24-rc6+git/htcuni.patch deleted file mode 100644 index 4d746749c5..0000000000 --- a/packages/linux/linux-rp-2.6.23+2.6.24-rc6+git/htcuni.patch +++ /dev/null @@ -1,8044 +0,0 @@ ---- - arch/arm/Kconfig | 2 - arch/arm/mach-pxa/Kconfig | 89 + - arch/arm/mach-pxa/Makefile | 1 - arch/arm/mach-pxa/corgi.c | 3 - arch/arm/mach-pxa/generic.c | 13 - arch/arm/mach-pxa/htcuniversal/Makefile | 19 - arch/arm/mach-pxa/htcuniversal/htcuniversal.c | 468 +++++ - arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c | 917 +++++++++++ - arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h | 65 - arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c | 143 + - arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c | 61 - arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c | 135 + - arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h | 17 - arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c | 87 + - arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c | 226 ++ - arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c | 212 ++ - arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c | 167 ++ - arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h | 16 - arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c | 69 - arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c | 97 + - arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c | 490 ++++++ - arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c | 71 - arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h | 20 - arch/arm/mach-pxa/spitz.c | 2 - drivers/input/keyboard/Kconfig | 7 - drivers/input/keyboard/Makefile | 2 - drivers/input/keyboard/asic3_keys.c | 131 + - drivers/leds/Kconfig | 7 - drivers/leds/Makefile | 1 - drivers/leds/leds-asic3.c | 189 ++ - drivers/mfd/Kconfig | 10 - drivers/mfd/Makefile | 2 - drivers/mfd/asic3_base.c | 1208 +++++++++++++++ - drivers/mfd/soc-core.c | 106 + - drivers/mfd/soc-core.h | 30 - drivers/mmc/host/Kconfig | 6 - drivers/mmc/host/Makefile | 2 - drivers/mmc/host/asic3_mmc.c | 900 +++++++++++ - drivers/mmc/host/asic3_mmc.h | 25 - drivers/serial/pxa.c | 22 - drivers/video/backlight/Kconfig | 2 - drivers/video/backlight/corgi_bl.c | 4 - include/asm-arm/arch-pxa/clock.h | 27 - include/asm-arm/arch-pxa/htcuniversal-asic.h | 213 ++ - include/asm-arm/arch-pxa/htcuniversal-gpio.h | 220 ++ - include/asm-arm/arch-pxa/htcuniversal-init.h | 14 - include/asm-arm/arch-pxa/htcuniversal.h | 3 - include/asm-arm/arch-pxa/irqs.h | 2 - include/asm-arm/arch-pxa/pxa-pm_ll.h | 6 - include/asm-arm/arch-pxa/pxa-regs.h | 2 - include/asm-arm/arch-pxa/serial.h | 78 - include/asm-arm/arch-pxa/sharpsl.h | 6 - include/asm-arm/hardware/asic3_keys.h | 18 - include/asm-arm/hardware/asic3_leds.h | 34 - include/asm-arm/hardware/ipaq-asic3.h | 602 +++++++ - include/linux/backlight.h | 7 - include/linux/gpiodev.h | 44 - include/linux/input_pda.h | 47 - include/linux/ioport.h | 1 - include/linux/soc/asic3_base.h | 104 + - include/linux/soc/tmio_mmc.h | 17 - 61 files changed, 7475 insertions(+), 14 deletions(-) - -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,19 @@ -+# -+# Makefile for HTC Universal -+# -+ -+snd-htcuniversal-ak4641-objs := htcuniversal_ak4641.o -+ -+obj-$(CONFIG_MACH_HTCUNIVERSAL) += htcuniversal.o -+obj-$(CONFIG_HTCUNIVERSAL_CORE) += htcuniversal_core.o -+obj-$(CONFIG_HTCUNIVERSAL_POWER) += htcuniversal_power2.o -+obj-$(CONFIG_HTCUNIVERSAL_LCD) += htcuniversal_lcd.o -+obj-$(CONFIG_HTCUNIVERSAL_BACKLIGHT) += htcuniversal_bl.o -+obj-$(CONFIG_HTCUNIVERSAL_TS2) += htcuniversal_ts2.o -+obj-$(CONFIG_HTCUNIVERSAL_BUTTONS) += htcuniversal_buttons.o -+obj-$(CONFIG_HTCUNIVERSAL_BLUETOOTH) += htcuniversal_bt.o -+obj-$(CONFIG_HTCUNIVERSAL_PHONE) += htcuniversal_phone.o -+obj-$(CONFIG_HTCUNIVERSAL_ASIC3_LEDS) += htcuniversal_asic3_leds.o -+obj-$(CONFIG_HTCUNIVERSAL_UDC) += htcuniversal_udc.o -+ -+obj-$(CONFIG_HTCUNIVERSAL_AK4641) += htcuniversal_ak4641.o -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,468 @@ -+/* -+ * Hardware definitions for HTC Universal -+ * -+ * Copyright (c) 2006 Oleg Gusev -+ * -+ * Use consistent with the GNU GPL is permitted, -+ * provided that this copyright notice is -+ * preserved in its entirety in all copies and derived works. -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/irq.h> -+#include <linux/input.h> -+#include <linux/gpio_keys.h> -+#include <linux/soc/asic3_base.h> -+ -+#include <asm/mach-types.h> -+#include <asm/hardware.h> -+#include <asm/setup.h> -+ -+#include <asm/mach/irq.h> -+#include <asm/mach/arch.h> -+ -+#include <asm/arch/bitfield.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/serial.h> -+#include <asm/arch/pxa27x_keyboard.h> -+#include <asm/arch/pxafb.h> -+#include <asm/arch/irda.h> -+#include <asm/arch/ohci.h> -+ -+#include <asm/arch/htcuniversal.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-init.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+#include <asm/hardware/ipaq-asic3.h> -+ -+#include "../generic.h" -+ -+#include "htcuniversal_bt.h" -+#include "htcuniversal_phone.h" -+#include "tsc2046_ts.h" -+ -+/* -+ * IRDA -+ */ -+ -+static void htcuniversal_irda_transceiver_mode(struct device *dev, int mode) -+{ -+ /* */ -+} -+ -+static struct pxaficp_platform_data htcuniversal_ficp_platform_data = { -+ .transceiver_cap = IR_SIRMODE | IR_FIRMODE, -+ .transceiver_mode = htcuniversal_irda_transceiver_mode, -+}; -+ -+/* -+ * Bluetooth - Relies on other loadable modules, like ASIC3 and Core, -+ * so make the calls indirectly through pointers. Requires that the -+ * htcuniversal_bt module be loaded before any attempt to use -+ * bluetooth (obviously). -+ */ -+ -+static struct htcuniversal_bt_funcs bt_funcs; -+ -+static void -+htcuniversal_bt_configure( int state ) -+{ -+ if (bt_funcs.configure != NULL) -+ bt_funcs.configure( state ); -+} -+ -+static struct htcuniversal_phone_funcs phone_funcs; -+ -+static void -+htcuniversal_phone_configure( int state ) -+{ -+ if (phone_funcs.configure != NULL) -+ phone_funcs.configure( state ); -+} -+ -+//void htcuniversal_ll_pm_init(void); -+ -+extern struct platform_device htcuniversal_bl; -+static struct platform_device htcuniversal_lcd = { .name = "htcuniversal_lcd", }; -+//static struct platform_device htcuniversal_kbd = { .name = "htcuniversal_kbd", }; -+static struct platform_device htcuniversal_buttons = { .name = "htcuniversal_buttons", }; -+//static struct platform_device htcuniversal_ts = { .name = "htcuniversal_ts", }; -+//static struct platform_device htcuniversal_bt = { .name = "htcuniversal_bt", }; -+//static struct platform_device htcuniversal_phone = { .name = "htcuniversal_phone", }; -+static struct platform_device htcuniversal_power = { .name = "htcuniversal_power", }; -+static struct platform_device htcuniversal_udc = { .name = "htcuniversal_udc", }; -+ -+static struct tsc2046_mach_info htcuniversal_ts_platform_data = { -+ .port = 1, -+ .clock = CKEN_SSP1, -+ .pwrbit_X = 1, -+ .pwrbit_Y = 1, -+ .irq = 0 /* asic3 irq */ -+}; -+ -+static struct platform_device htcuniversal_ts = { -+ .name = "htcuniversal_ts", -+ .dev = { -+ .platform_data = &htcuniversal_ts_platform_data, -+ }, -+}; -+ -+ -+/* Bluetooth */ -+ -+static struct platform_device htcuniversal_bt = { -+ .name = "htcuniversal_bt", -+ .id = -1, -+ .dev = { -+ .platform_data = &bt_funcs, -+ }, -+}; -+ -+static struct platform_device htcuniversal_phone = { -+ .name = "htcuniversal_phone", -+ .id = -1, -+ .dev = { -+ .platform_data = &phone_funcs, -+ }, -+}; -+ -+/* PXA2xx Keys */ -+ -+static struct gpio_keys_button htcuniversal_button_table[] = { -+ { KEY_POWER, GPIO_NR_HTCUNIVERSAL_KEY_ON_N, 1 }, -+}; -+ -+static struct gpio_keys_platform_data htcuniversal_pxa_keys_data = { -+ .buttons = htcuniversal_button_table, -+ .nbuttons = ARRAY_SIZE(htcuniversal_button_table), -+}; -+ -+static struct platform_device htcuniversal_pxa_keys = { -+ .name = "gpio-keys", -+ .dev = { -+ .platform_data = &htcuniversal_pxa_keys_data, -+ }, -+ .id = -1, -+}; -+ -+/**************************************************************** -+ * Keyboard -+ ****************************************************************/ -+ -+static struct pxa27x_keyboard_platform_data htcuniversal_kbd = { -+ .nr_rows = 8, -+ .nr_cols = 8, -+ .keycodes = { -+ { -+ /* row 0 */ -+ KEY_ENTER, -+ KEY_MINUS, -+ KEY_ESC, -+ KEY_1, -+ KEY_TAB, -+ KEY_CAPSLOCK, -+ KEY_LEFTSHIFT, -+ KEY_RIGHTALT, /* Fn */ -+ }, { /* row 1 */ -+ KEY_COMMA, -+ KEY_EQUAL, -+ KEY_F1, -+ KEY_2, -+ KEY_Q, -+ KEY_A, -+ KEY_Z, -+ KEY_LEFTCTRL, -+ }, { /* row 2 */ -+ KEY_UP, -+ KEY_I, -+ KEY_F2, -+ KEY_3, -+ KEY_W, -+ KEY_S, -+ KEY_X, -+ KEY_F6, -+ }, { /* row 3 */ -+ KEY_DOT, -+ KEY_O, -+ KEY_F3, -+ KEY_4, -+ KEY_E, -+ KEY_D, -+ KEY_C, -+ KEY_LEFTALT, -+ }, { /* row 4 */ -+ KEY_F9, -+ KEY_P, -+ KEY_F4, -+ KEY_5, -+ KEY_R, -+ KEY_F, -+ KEY_V, -+ KEY_SPACE, -+ }, { /* row 5 */ -+ KEY_RIGHT, -+ KEY_BACKSPACE, -+ KEY_F5, -+ KEY_6, -+ KEY_T, -+ KEY_G, -+ KEY_B, -+ KEY_F7, -+ }, { /* row 6 */ -+ KEY_F9, -+ KEY_K, -+ KEY_9, -+ KEY_7, -+ KEY_Y, -+ KEY_H, -+ KEY_N, -+ KEY_LEFT, -+ }, { /* row 7 */ -+ KEY_F10, -+ KEY_L, -+ KEY_0, -+ KEY_8, -+ KEY_U, -+ KEY_J, -+ KEY_M, -+ KEY_DOWN, -+ }, -+ }, -+ .gpio_modes = { -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN0_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN1_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN2_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN3_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN4_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN5_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN6_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKIN7_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT0_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT1_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT2_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT3_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT4_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT5_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT6_MD, -+ GPIO_NR_HTCUNIVERSAL_KP_MKOUT7_MD, -+ }, -+}; -+ -+static struct platform_device htcuniversal_pxa_keyboard = { -+ .name = "pxa27x-keyboard", -+ .id = -1, -+ .dev = { -+ .platform_data = &htcuniversal_kbd, -+ }, -+}; -+/* Core Hardware Functions */ -+ -+struct platform_device htcuniversal_core = { -+ .name = "htcuniversal_core", -+ .id = 0, -+ .dev = { -+ .platform_data = NULL, -+ }, -+}; -+ -+static struct platform_device *devices[] __initdata = { -+ &htcuniversal_core, -+// &htcuniversal_flash, -+ &htcuniversal_pxa_keyboard, -+ &htcuniversal_pxa_keys, -+}; -+ -+static struct platform_device *htcuniversal_asic3_devices[] __initdata = { -+ &htcuniversal_lcd, -+#ifdef CONFIG_HTCUNIVERSAL_BACKLIGHT -+ &htcuniversal_bl, -+#endif -+ &htcuniversal_buttons, -+ &htcuniversal_ts, -+ &htcuniversal_bt, -+ &htcuniversal_phone, -+ &htcuniversal_power, -+ &htcuniversal_udc, -+}; -+ -+static struct asic3_platform_data htcuniversal_asic3_platform_data = { -+ -+ /* Setting ASIC3 GPIO registers to the below initialization states -+ * HTC Universal asic3 information: -+ * http://wiki.xda-developers.com/index.php?pagename=UniversalASIC3 -+ * http://wiki.xda-developers.com/index.php?pagename=ASIC3 -+ * -+ * dir: Direction of the GPIO pin. 0: input, 1: output. -+ * If unknown, set as output to avoid power consuming floating input nodes -+ * init: Initial state of the GPIO bits -+ * -+ * These registers are configured as they are on Wince. -+ */ -+ .gpio_a = { -+ .dir = (1<<GPIOA_LCD_PWR5_ON) | -+ (1<<GPIOA_FLASHLIGHT) | -+ (1<<GPIOA_UNKNOWN9) | -+ (1<<GPIOA_SPK_PWR2_ON) | -+ (1<<GPIOA_UNKNOWN4) | -+ (1<<GPIOA_EARPHONE_PWR_ON)| -+ (1<<GPIOA_AUDIO_PWR_ON) | -+ (1<<GPIOA_SPK_PWR1_ON) | -+ (1<<GPIOA_I2C_EN), -+ .init = (1<<GPIOA_LCD_PWR5_ON) | -+ (1<<GPIOA_I2C_EN), -+ .sleep_out = 0x0000, -+ .batt_fault_out = 0x0000, -+ .alt_function = 0x0000, -+ .sleep_conf = 0x000c, -+ }, -+ .gpio_b = { -+ .dir = 0xc142, -+ .init = 0x8842, // TODO: 0x0900 -+ .sleep_out = 0x0000, -+ .batt_fault_out = 0x0000, -+ .alt_function = 0x0000, -+ .sleep_conf = 0x000c, -+ }, -+ .gpio_c = { -+ .dir = 0xc7e7, -+ .init = 0xc6e0, // TODO: 0x8000 -+ .sleep_out = 0x0000, -+ .batt_fault_out = 0x0000, -+ .alt_function = 0x0007, // GPIOC_LED_RED | GPIOC_LED_GREEN | GPIOC_LED_BLUE -+ .sleep_conf = 0x000c, -+ }, -+ .gpio_d = { -+ .dir = 0xffc0, -+ .init = 0x7840, // TODO: 0x0000 -+ .sleep_out = 0x0000, -+ .batt_fault_out = 0x0000, -+ .alt_function = 0x0000, -+ .sleep_conf = 0x0008, -+ }, -+ .bus_shift = 1, -+ .irq_base = HTCUNIVERSAL_ASIC3_IRQ_BASE, -+ -+ .child_platform_devs = htcuniversal_asic3_devices, -+ .num_child_platform_devs = ARRAY_SIZE(htcuniversal_asic3_devices), -+}; -+ -+static struct resource htcuniversal_asic3_resources[] = { -+ [0] = { -+ .start = HTCUNIVERSAL_ASIC3_GPIO_PHYS, -+ .end = HTCUNIVERSAL_ASIC3_GPIO_PHYS + IPAQ_ASIC3_MAP_SIZE, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = HTCUNIVERSAL_IRQ(ASIC3_EXT_INT), -+ .end = HTCUNIVERSAL_IRQ(ASIC3_EXT_INT), -+ .flags = IORESOURCE_IRQ, -+ }, -+ [2] = { -+ .start = HTCUNIVERSAL_ASIC3_MMC_PHYS, -+ .end = HTCUNIVERSAL_ASIC3_MMC_PHYS + IPAQ_ASIC3_MAP_SIZE, -+ .flags = IORESOURCE_MEM, -+ }, -+ [3] = { -+ .start = HTCUNIVERSAL_IRQ(ASIC3_SDIO_INT_N), -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+struct platform_device htcuniversal_asic3 = { -+ .name = "asic3", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(htcuniversal_asic3_resources), -+ .resource = htcuniversal_asic3_resources, -+ .dev = { .platform_data = &htcuniversal_asic3_platform_data, }, -+}; -+EXPORT_SYMBOL(htcuniversal_asic3); -+ -+static struct pxafb_mode_info htcuniversal_lcd_modes[] = { -+{ -+ .pixclock = 96153, -+ .xres = 480, -+ .yres = 640, -+ .bpp = 16, -+ .hsync_len = 4, -+ .vsync_len = 1, -+ .left_margin = 20, -+ .right_margin = 8, -+ .upper_margin = 7, -+ .lower_margin = 8, -+ -+// .sync = FB_SYNC_HOR_LOW_ACT|FB_SYNC_VERT_LOW_ACT, -+ -+}, -+}; -+ -+static struct pxafb_mach_info sony_acx526akm = { -+ .modes = htcuniversal_lcd_modes, -+ .num_modes = ARRAY_SIZE(htcuniversal_lcd_modes), -+ -+ /* fixme: use constants defined in pxafb.h */ -+ .lccr0 = 0x00000080, -+ .lccr3 = 0x00400000, -+// .lccr4 = 0x80000000, -+}; -+ -+static void __init htcuniversal_init_irq(void) -+{ -+ pxa27x_init_irq(); -+} -+ -+static struct platform_pxa_serial_funcs htcuniversal_pxa_bt_funcs = { -+ .configure = htcuniversal_bt_configure, -+}; -+static struct platform_pxa_serial_funcs htcuniversal_pxa_phone_funcs = { -+ .configure = htcuniversal_phone_configure, -+}; -+ -+/* USB OHCI */ -+ -+static int htcuniversal_ohci_init(struct device *dev) -+{ -+ /* missing GPIO setup here */ -+ -+ /* got the value from wince */ -+ UHCHR=UHCHR_CGR; -+ -+ return 0; -+} -+ -+static struct pxaohci_platform_data htcuniversal_ohci_platform_data = { -+ .port_mode = PMM_PERPORT_MODE, -+ .init = htcuniversal_ohci_init, -+}; -+ -+static void __init htcuniversal_map_io(void) -+{ -+ pxa_map_io(); -+ -+ pxa_set_btuart_info(&htcuniversal_pxa_bt_funcs); -+ pxa_set_ffuart_info(&htcuniversal_pxa_phone_funcs); -+} -+ -+static void __init htcuniversal_init(void) -+{ -+ set_pxa_fb_info(&sony_acx526akm); -+ -+ platform_device_register(&htcuniversal_asic3); -+ platform_add_devices(devices, ARRAY_SIZE(devices) ); -+ pxa_set_ficp_info(&htcuniversal_ficp_platform_data); -+ pxa_set_ohci_info(&htcuniversal_ohci_platform_data); -+} -+ -+MACHINE_START(HTCUNIVERSAL, "HTC Universal") -+ /* Maintainer xanadux.org */ -+ .phys_io = 0x40000000, -+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, -+ .boot_params = 0xa0000100, -+ .map_io = htcuniversal_map_io, -+ .init_irq = htcuniversal_init_irq, -+ .init_machine = htcuniversal_init, -+ .timer = &pxa_timer, -+MACHINE_END -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,917 @@ -+/* -+ * Audio support for codec Asahi Kasei AK4641 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * Copyright (c) 2006 Giorgio Padrin <giorgio@mandarinlogiq.org> -+ * -+ * History: -+ * -+ * 2006-03 Written -- Giorgio Padrin -+ * 2006-09 Test and debug on machine (HP hx4700) -- Elshin Roman <roxmail@list.ru> -+ * -+ * AK4641 codec device driver -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * Based on code: -+ * Copyright (c) 2002 Hewlett-Packard Company -+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org> -+ * Copyright (c) 2000 Lernout & Hauspie Speech Products, N.V. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License. -+ */ -+ -+#include <sound/driver.h> -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/types.h> -+#include <linux/string.h> -+#include <linux/slab.h> -+#include <linux/errno.h> -+#include <linux/ioctl.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+ -+#include <sound/core.h> -+#include <sound/control.h> -+#include <sound/initval.h> -+#include <sound/info.h> -+ -+#include "htcuniversal_ak4641.h" -+ -+/* Registers */ -+#define R_PM1 0x00 -+#define R_PM2 0x01 -+#define R_SEL1 0x02 -+#define R_SEL2 0x03 -+#define R_MODE1 0x04 -+#define R_MODE2 0x05 -+#define R_DAC 0x06 -+#define R_MIC 0x07 -+#define REG_TIMER 0x08 -+#define REG_ALC1 0x09 -+#define REG_ALC2 0x0a -+#define R_PGA 0x0b -+#define R_ATTL 0x0c -+#define R_ATTR 0x0d -+#define REG_VOL 0x0e -+#define R_STATUS 0x0f -+#define REG_EQLO 0x10 -+#define REG_EQMID 0x11 -+#define REG_EQHI 0x12 -+#define REG_BTIF 0x13 -+ -+/* Register flags */ -+/* REG_PWR1 */ -+#define R_PM1_PMADC 0x01 -+#define R_PM1_PMMIC 0x02 -+#define REG_PWR1_PMAUX 0x04 -+#define REG_PWR1_PMMO 0x08 -+#define R_PM1_PMLO 0x10 -+/* unused 0x20 */ -+/* unused 0x40 */ -+#define R_PM1_PMVCM 0x80 -+ -+/* REG_PWR2 */ -+#define R_PM2_PMDAC 0x01 -+/* unused 0x02 */ -+/* unused 0x04 */ -+#define R_PM2_PMMO2 0x08 -+#define REG_PWR2_MCKAC 0x10 -+/* unused 0x20 */ -+/* unused 0x40 */ -+#define R_PM2_MCKPD 0x80 -+ -+/* REG_SEL1 */ -+#define R_SEL1_PSMO2 0x01 -+/* unused 0x02 */ -+/* unused 0x04 */ -+/* unused 0x08 */ -+#define REG_SEL1_MICM 0x10 -+#define REG_SEL1_DACM 0x20 -+#define REG_SEL1_PSMO 0x40 -+#define REG_SEL1_MOGN 0x80 -+ -+/* REG_SEL2 */ -+#define R_SEL2_PSLOR 0x01 -+#define R_SEL2_PSLOL 0x02 -+#define REG_SEL2_AUXSI 0x04 -+/* unused 0x08 */ -+#define REG_SEL2_MICL 0x10 -+#define REG_SEL2_AUXL 0x20 -+/* unused 0x40 */ -+#define R_SEL2_DACL 0x80 -+ -+/* REG_MODE1 */ -+#define REG_MODE1_DIF0 0x01 -+#define REG_MODE1_DIF1 0x02 -+/* unused 0x04 */ -+/* unused 0x08 */ -+/* unused 0x10 */ -+/* unused 0x20 */ -+/* unused 0x40 */ -+/* unused 0x80 */ -+ -+/* REG_MODE2 */ -+/* unused 0x01 */ -+#define REG_MODE2_LOOP 0x02 -+#define REG_MODE2_HPM 0x04 -+/* unused 0x08 */ -+/* unused 0x10 */ -+#define REG_MODE2_MCK0 0x20 -+#define REG_MODE2_MCK1 0x40 -+/* unused 0x80 */ -+ -+/* REG_DAC */ -+#define REG_DAC_DEM0 0x01 -+#define REG_DAC_DEM1 0x02 -+#define REG_DAC_EQ 0x04 -+/* unused 0x08 */ -+#define R_DAC_DATTC 0x10 -+#define R_DAC_SMUTE 0x20 -+#define REG_DAC_TM 0x40 -+/* unused 0x80 */ -+ -+/* REG_MIC */ -+#define R_MIC_MGAIN 0x01 -+#define R_MIC_MSEL 0x02 -+#define R_MIC_MICAD 0x04 -+#define R_MIC_MPWRI 0x08 -+#define R_MIC_MPWRE 0x10 -+#define REG_MIC_AUXAD 0x20 -+/* unused 0x40 */ -+/* unused 0x80 */ -+ -+/* REG_TIMER */ -+ -+#define REG_TIMER_LTM0 0x01 -+#define REG_TIMER_LTM1 0x02 -+#define REG_TIMER_WTM0 0x04 -+#define REG_TIMER_WTM1 0x08 -+#define REG_TIMER_ZTM0 0x10 -+#define REG_TIMER_ZTM1 0x20 -+/* unused 0x40 */ -+/* unused 0x80 */ -+ -+#define REG_ALC1_LMTH 0x01 -+#define REG_ALC1_RATT 0x02 -+#define REG_ALC1_LMAT0 0x04 -+#define REG_ALC1_LMAT1 0x08 -+#define REG_ALC1_ZELM 0x10 -+#define REG_ALC1_ALC1 0x20 -+/* unused 0x40 */ -+/* unused 0x80 */ -+ -+/* REG_ALC2 */ -+ -+/* REG_PGA */ -+ -+/* REG_ATTL */ -+ -+/* REG_ATTR */ -+ -+/* REG_VOL */ -+#define REG_VOL_ATTM 0x80 -+ -+/* REG_STATUS */ -+#define R_STATUS_DTMIC 0x01 -+ -+/* REG_EQ controls use 4 bits for each of 5 EQ levels */ -+ -+/* Bluetooth not yet implemented */ -+#define REG_BTIF_PMAD2 0x01 -+#define REG_BTIF_PMDA2 0x02 -+#define REG_BTIF_PMBIF 0x04 -+#define REG_BTIF_ADC2 0x08 -+#define REG_BTIF_DAC2 0x10 -+#define REG_BTIF_BTFMT0 0x20 -+#define REG_BTIF_BTFMT1 0x40 -+/* unused 0x80 */ -+ -+/* begin {{ I2C }} */ -+ -+static struct i2c_driver snd_ak4641_i2c_driver = { -+ .driver = { -+ .name = "ak4641-i2c" -+ }, -+}; -+ -+static int snd_ak4641_i2c_init(void) -+{ -+ return i2c_add_driver(&snd_ak4641_i2c_driver); -+} -+ -+static void snd_ak4641_i2c_free(void) -+{ -+ i2c_del_driver(&snd_ak4641_i2c_driver); -+} -+ -+static inline int snd_ak4641_i2c_probe(struct snd_ak4641 *ak) -+{ -+ if (ak->i2c_client.adapter == NULL) return -EINVAL; -+ ak->i2c_client.addr = 0x12; -+ if (i2c_smbus_xfer(ak->i2c_client.adapter, ak->i2c_client.addr, -+ 0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0) -+ return -ENODEV; -+ else return 0; -+} -+ -+static int snd_ak4641_i2c_attach(struct snd_ak4641 *ak) -+{ -+ int ret = 0; -+ if ((ret = snd_ak4641_i2c_probe(ak)) < 0) return ret; -+ snprintf(ak->i2c_client.name, sizeof(ak->i2c_client.name), -+ "ak4641-i2c at %d-%04x", -+ i2c_adapter_id(ak->i2c_client.adapter), ak->i2c_client.addr); -+ return i2c_attach_client(&ak->i2c_client); -+} -+ -+static void snd_ak4641_i2c_detach(struct snd_ak4641 *ak) -+{ -+ i2c_detach_client(&ak->i2c_client); -+} -+ -+/* end {{ I2C }} */ -+ -+ -+/* begin {{ Registers & Cache Ops }} */ -+ -+static int snd_ak4641_hwsync(struct snd_ak4641 *ak, int read, u8 reg) -+{ -+ struct i2c_msg msgs[2]; -+ u8 buf[2]; -+ int ret; -+ -+ snd_assert(reg < ARRAY_SIZE(ak->regs), return -EINVAL); -+ -+ /* setup i2c msgs */ -+ msgs[0].addr = ak->i2c_client.addr; -+ msgs[0].flags = 0; -+ msgs[0].buf = buf; -+ if (!read) -+ msgs[0].len = 2; -+ else { -+ msgs[1].flags = I2C_M_RD; -+ msgs[1].addr = msgs[0].addr; -+ msgs[1].buf = msgs[0].buf + 1; -+ msgs[0].len = 1; -+ msgs[1].len = 1; -+ } -+ -+ buf[0] = reg; -+ -+ /* regs[reg] -> buffer, on write */ -+ if (!read) buf[1] = ak->regs[reg]; -+ -+ /* i2c transfer */ -+ ret = i2c_transfer(ak->i2c_client.adapter, msgs, read ? 2 : 1); -+ if (ret != (read ? 2 : 1)) return ret; /* transfer error */ //@@ error ret < 0, or not ? -+ -+ /* regs[reg] <- buffer, on read */ -+ if (read) ak->regs[reg] = buf[1]; -+ -+ return 0; -+} -+ -+static inline int snd_ak4641_hwsync_read(struct snd_ak4641 *ak, u8 reg) -+{ -+ return snd_ak4641_hwsync(ak, 1, reg); -+} -+ -+static inline int snd_ak4641_hwsync_write(struct snd_ak4641 *ak, u8 reg) -+{ -+ return snd_ak4641_hwsync(ak, 0, reg); -+} -+ -+static int snd_ak4641_hwsync_read_all(struct snd_ak4641 *ak) -+{ -+ u8 reg; -+ for (reg = 0; reg < ARRAY_SIZE(ak->regs); reg++) -+ if (snd_ak4641_hwsync_read(ak, reg) < 0) return -1; -+ return 0; -+} -+ -+static int snd_ak4641_hwsync_write_all(struct snd_ak4641 *ak) -+{ -+ u8 reg; -+ for (reg = 0; reg < ARRAY_SIZE(ak->regs); reg++) -+ if (snd_ak4641_hwsync_write(ak, reg) < 0) return -1; -+ return 0; -+} -+ -+static int snd_ak4641_reg_changed(struct snd_ak4641 *ak, u8 reg) -+{ -+ if ((reg != R_PGA && ak->powered_on) || -+ (reg == R_PGA && (ak->regs[R_PM1] & R_PM1_PMMIC))) -+ return snd_ak4641_hwsync_write(ak, reg); -+ return 0; -+} -+ -+/* end {{ Registers & Cache Ops }}*/ -+ -+ -+static inline void snd_ak4641_lock(struct snd_ak4641 *ak) -+{ -+ down(&ak->sem); -+} -+ -+static inline void snd_ak4641_unlock(struct snd_ak4641 *ak) -+{ -+ up(&ak->sem); -+} -+ -+#define WRITE_MASK(i, val, mask) (((i) & ~(mask)) | ((val) & (mask))) -+ -+ -+/* begin {{ Controls }} */ -+ -+#define INV_RANGE(val, mask) \ -+ (~(val) & (mask)) -+ -+/*-begin----------------------------------------------------------*/ -+static int snd_ak4641_actl_playback_volume_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 2; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 0xff; -+ return 0; -+} -+ -+static int snd_ak4641_actl_playback_volume_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data; -+ -+ snd_ak4641_lock(ak); -+ ucontrol->value.integer.value[0] = INV_RANGE(ak->regs[R_ATTL], 0xff); -+ ucontrol->value.integer.value[1] = INV_RANGE(ak->regs[R_ATTR], 0xff); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+ -+static int snd_ak4641_actl_playback_volume_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data; -+ -+ snd_ak4641_lock(ak); -+ ak->regs[R_ATTL] = INV_RANGE(ucontrol->value.integer.value[0], 0xff); -+ ak->regs[R_ATTR] = INV_RANGE(ucontrol->value.integer.value[1], 0xff); -+ snd_ak4641_reg_changed(ak, R_ATTL); -+ snd_ak4641_reg_changed(ak, R_ATTR); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+/*-end------------------------------------------------------------*/ -+ -+/*-begin----------------------------------------------------------*/ -+static int snd_ak4641_actl_mic_gain_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 0x7f; -+ return 0; -+} -+ -+static int snd_ak4641_actl_mic_gain_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data; -+ -+ ucontrol->value.integer.value[0] = ak->regs[R_PGA]; -+ return 0; -+} -+ -+static int snd_ak4641_actl_mic_gain_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data; -+ -+ snd_ak4641_lock(ak); -+ ak->regs[R_PGA] = ucontrol->value.integer.value[0]; -+ snd_ak4641_reg_changed(ak, R_PGA); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+/*-end------------------------------------------------------------*/ -+ -+#define ACTL(ctl_name, _name) \ -+static struct snd_kcontrol_new snd_ak4641_actl_ ## ctl_name = \ -+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = _name, \ -+ .info = snd_ak4641_actl_ ## ctl_name ## _info, \ -+ .get = snd_ak4641_actl_ ## ctl_name ## _get, .put = snd_ak4641_actl_ ## ctl_name ## _put }; -+ -+ACTL(playback_volume, "Master Playback Volume") -+ACTL(mic_gain, "Mic Capture Gain") -+ -+struct snd_ak4641_uctl_bool { -+ int (*get) (struct snd_ak4641 *uda); -+ int (*set) (struct snd_ak4641 *uda, int on); -+}; -+ -+static int snd_ak4641_actl_bool_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+ uinfo->count = 1; -+ return 0; -+} -+ -+static int snd_ak4641_actl_bool_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data; -+ struct snd_ak4641_uctl_bool *uctl = -+ (struct snd_ak4641_uctl_bool *) kcontrol->private_value; -+ -+ ucontrol->value.integer.value[0] = uctl->get(ak); -+ return 0; -+} -+ -+static int snd_ak4641_actl_bool_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data; -+ struct snd_ak4641_uctl_bool *uctl = -+ (struct snd_ak4641_uctl_bool *) kcontrol->private_value; -+ -+ return uctl->set(ak, ucontrol->value.integer.value[0]); -+} -+ -+/*-begin----------------------------------------------------------*/ -+static int snd_ak4641_uctl_playback_switch_get(struct snd_ak4641 *ak) -+{ -+ return (ak->regs[R_DAC] & R_DAC_SMUTE) == 0x00; -+} -+ -+static int snd_ak4641_uctl_playback_switch_set(struct snd_ak4641 *ak, int on) -+{ -+ snd_ak4641_lock(ak); -+ ak->regs[R_DAC] = WRITE_MASK(ak->regs[R_DAC], -+ on ? 0x00 : R_DAC_SMUTE, R_DAC_SMUTE); -+ snd_ak4641_reg_changed(ak, R_DAC); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+/*-end------------------------------------------------------------*/ -+ -+/*-begin----------------------------------------------------------*/ -+static int snd_ak4641_uctl_mic_boost_get(struct snd_ak4641 *ak) -+{ -+ return (ak->regs[R_MIC] & R_MIC_MGAIN) == R_MIC_MGAIN; -+} -+ -+static int snd_ak4641_uctl_mic_boost_set(struct snd_ak4641 *ak, int on) -+{ -+ snd_ak4641_lock(ak); -+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], -+ on ? R_MIC_MGAIN : 0x00, R_MIC_MGAIN); -+ snd_ak4641_reg_changed(ak, R_MIC); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+/*-end------------------------------------------------------------*/ -+ -+/*-begin----------------------------------------------------------*/ -+static int snd_ak4641_uctl_mono_out_get(struct snd_ak4641 *ak) -+{ -+ printk("mono_out status 0x%8.8x -> 0x%8.8x\n",ak->regs[R_SEL1], ak->regs[R_SEL1] & REG_SEL1_PSMO); -+ return (ak->regs[R_SEL1] & REG_SEL1_PSMO) == REG_SEL1_PSMO; -+} -+ -+static int snd_ak4641_uctl_mono_out_set(struct snd_ak4641 *ak, int on) -+{ -+ printk("phone mic enable called. on=%d\n",on); -+ snd_ak4641_lock(ak); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], on ? R_PM1_PMMIC : 0x00, R_PM1_PMMIC); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], on ? REG_PWR1_PMMO : 0x00, REG_PWR1_PMMO); -+ snd_ak4641_reg_changed(ak, R_PM1); -+ -+ snd_ak4641_hwsync_write(ak, R_PGA); /* mic PGA gain is reset when PMMIC = 0 */ -+ -+ /* internal mic */ -+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], on ? R_MIC_MPWRI : 0x0, R_MIC_MPWRI); -+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], 0x0, R_MIC_MSEL); -+ snd_ak4641_hwsync_write(ak, R_MIC); -+ -+// ak->regs[REG_BTIF] = WRITE_MASK(ak->regs[REG_BTIF], 0x0, REG_BTIF_DAC2); -+// snd_ak4641_hwsync_write(ak, REG_BTIF); -+ /* */ -+// ak->regs[REG_VOL] = WRITE_MASK(ak->regs[REG_VOL], on ? REG_VOL_ATTM : 0x00, REG_VOL_ATTM); -+// ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_MOGN : 0x00, REG_SEL1_MOGN); -+ ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_MICM : 0x00, REG_SEL1_MICM); -+ ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_PSMO : 0x00, REG_SEL1_PSMO); -+ snd_ak4641_reg_changed(ak, R_SEL1); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+/*-end------------------------------------------------------------*/ -+ -+#define ACTL_BOOL(ctl_name, _name) \ -+static struct snd_ak4641_uctl_bool snd_ak4641_actl_ ## ctl_name ## _pvalue = \ -+{ .get = snd_ak4641_uctl_ ## ctl_name ## _get, \ -+ .set = snd_ak4641_uctl_ ## ctl_name ## _set }; \ -+static struct snd_kcontrol_new snd_ak4641_actl_ ## ctl_name = \ -+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = _name, .info = snd_ak4641_actl_bool_info, \ -+ .get = snd_ak4641_actl_bool_get, .put = snd_ak4641_actl_bool_put, \ -+ .private_value = (unsigned long) &snd_ak4641_actl_ ## ctl_name ## _pvalue }; -+ -+ACTL_BOOL(playback_switch, "Master Playback Switch") -+ACTL_BOOL(mic_boost, "Mic Boost (+20dB)") -+ACTL_BOOL(mono_out, "Phone mic enable") -+ -+static void snd_ak4641_headphone_on(struct snd_ak4641 *ak, int on); -+static void snd_ak4641_speaker_on(struct snd_ak4641 *ak, int on); -+static void snd_ak4641_select_mic(struct snd_ak4641 *ak); -+ -+void snd_ak4641_hp_connected(struct snd_ak4641 *ak, int connected) -+{ -+ snd_ak4641_lock(ak); -+ if (connected != ak->hp_connected) { -+ ak->hp_connected = connected; -+ -+ /* headphone or speaker, on playback */ -+ if (ak->playback_on) { -+ if (connected) { -+ snd_ak4641_headphone_on(ak, 1); -+ snd_ak4641_speaker_on(ak, 0); -+ } else { -+ snd_ak4641_speaker_on(ak, 1); -+ snd_ak4641_headphone_on(ak, 0); -+ } -+ } -+ -+ /* headset or internal mic, on capture */ -+ if (ak->capture_on) -+ snd_ak4641_select_mic(ak); -+ } -+ snd_ak4641_unlock(ak); -+} -+ -+/* end {{ Controls }} */ -+ -+ -+/* begin {{ Headphone Detected Notification }} */ -+ -+static void snd_ak4641_hp_detected_w_fn(void *p) -+{ -+ struct snd_ak4641 *ak = (struct snd_ak4641 *)p; -+ -+ snd_ak4641_hp_connected(ak, ak->hp_detected.detected); -+} -+ -+void snd_ak4641_hp_detected(struct snd_ak4641 *ak, int detected) -+{ -+ if (detected != ak->hp_detected.detected) { -+ ak->hp_detected.detected = detected; -+ queue_work(ak->hp_detected.wq, &ak->hp_detected.w); -+ } -+} -+ -+static int snd_ak4641_hp_detected_init(struct snd_ak4641 *ak) -+{ -+ INIT_WORK(&ak->hp_detected.w, snd_ak4641_hp_detected_w_fn); -+ ak->hp_detected.detected = ak->hp_connected; -+ ak->hp_detected.wq = create_singlethread_workqueue("ak4641"); -+ if (ak->hp_detected.wq) return 0; -+ else return -1; -+} -+ -+static void snd_ak4641_hp_detected_free(struct snd_ak4641 *ak) -+{ -+ destroy_workqueue(ak->hp_detected.wq); -+} -+ -+/* end {{ Headphone Detected Notification }} */ -+ -+ -+/* begin {{ Codec Control }} */ -+ -+static void snd_ak4641_headphone_on(struct snd_ak4641 *ak, int on) -+{ -+ if (on) { -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ ak->headphone_out_on(1); -+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2], -+ R_SEL2_PSLOL | R_SEL2_PSLOR, -+ R_SEL2_PSLOL | R_SEL2_PSLOR); -+ snd_ak4641_hwsync_write(ak, R_SEL2); -+ } else { -+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2], -+ 0x00, R_SEL2_PSLOL | R_SEL2_PSLOR); -+ snd_ak4641_hwsync_write(ak, R_SEL2); -+ ak->headphone_out_on(0); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ } -+} -+ -+static void snd_ak4641_speaker_on(struct snd_ak4641 *ak, int on) -+{ -+ if (on) { -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ ak->speaker_out_on(1); -+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2], -+ R_SEL2_PSLOL | R_SEL2_PSLOR, -+ R_SEL2_PSLOL | R_SEL2_PSLOR); -+ snd_ak4641_hwsync_write(ak, R_SEL2); -+ } else { -+ ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2], -+ 0x00, R_SEL2_PSLOL | R_SEL2_PSLOR); -+ snd_ak4641_hwsync_write(ak, R_SEL2); -+ ak->speaker_out_on(0); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ } -+} -+ -+static inline int snd_ak4641_power_on(struct snd_ak4641 *ak) -+{ -+ ak->reset_pin(1); -+ ak->power_on_chip(1); -+ msleep(1); -+ ak->reset_pin(0); -+ ak->powered_on = 1; -+ return 0; -+} -+ -+static inline int snd_ak4641_power_off(struct snd_ak4641 *ak) -+{ -+ ak->powered_on = 0; -+ ak->power_on_chip(0); -+ return 0; -+} -+ -+static inline void snd_ak4641_headphone_out_on(struct snd_ak4641 *ak, int on) -+{ -+ if (ak->headphone_out_on) ak->headphone_out_on(on); -+} -+ -+static inline void snd_ak4641_speaker_out_on(struct snd_ak4641 *ak, int on) -+{ -+ if (ak->speaker_out_on) ak->speaker_out_on(on); -+} -+ -+static int snd_ak4641_playback_on(struct snd_ak4641 *ak) -+{ -+ if (ak->playback_on) return 0; -+ -+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], -+ R_PM2_PMDAC, R_PM2_MCKPD | R_PM2_PMDAC); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO); -+ snd_ak4641_hwsync_write(ak, R_PM2); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ if (ak->hp_connected) snd_ak4641_headphone_on(ak, 1); -+ else snd_ak4641_speaker_on(ak, 1); -+ -+ ak->playback_on = 1; -+ -+ return 0; -+} -+ -+static int snd_ak4641_playback_off(struct snd_ak4641 *ak) -+{ -+ if (!ak->playback_on) return 0; -+ -+ ak->playback_on = 0; -+ -+ if (ak->hp_connected) snd_ak4641_headphone_on(ak, 0); -+ else snd_ak4641_speaker_on(ak, 0); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO); -+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], -+ (!ak->capture_on ? R_PM2_MCKPD : 0x00) | R_PM2_PMDAC, -+ R_PM2_MCKPD | R_PM2_PMDAC); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ snd_ak4641_hwsync_write(ak, R_PM2); -+ -+ return 0; -+} -+ -+static void snd_ak4641_select_mic(struct snd_ak4641 *ak) -+{ -+ int mic = 0; -+ u8 r_mic; -+ -+ if (ak->hp_connected) { -+ /* check headset mic */ -+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], R_MIC_MPWRE, R_MIC_MPWRE); -+ snd_ak4641_hwsync_write(ak, R_MIC); -+ snd_ak4641_hwsync_read(ak, R_STATUS); -+ mic = (ak->regs[R_STATUS] & R_STATUS_DTMIC) == R_STATUS_DTMIC; -+ -+ printk("htcuniversal_ak4641_select_mic: mic=%d\n",mic); -+ -+ r_mic = WRITE_MASK(ak->regs[R_MIC], -+ R_MIC_MSEL | (ak->capture_on ? R_MIC_MPWRE : 0x00), -+ R_MIC_MSEL | R_MIC_MPWRI | R_MIC_MPWRE); -+ } -+ else -+ r_mic = WRITE_MASK(ak->regs[R_MIC], -+ 0x00 | (ak->capture_on ? R_MIC_MPWRI : 0x00), -+ R_MIC_MSEL | R_MIC_MPWRI | R_MIC_MPWRE); -+ -+ if (r_mic != ak->regs[R_MIC]) { -+ ak->regs[R_MIC] = r_mic; -+ snd_ak4641_hwsync_write(ak, R_MIC); -+ } -+} -+ -+static int snd_ak4641_capture_on(struct snd_ak4641 *ak) -+{ -+ if (ak->capture_on) return 0; -+ -+ if (!ak->playback_on) { -+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], 0x00, R_PM2_MCKPD); -+ snd_ak4641_hwsync_write(ak, R_PM2); -+ } -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMMIC | R_PM1_PMADC, -+ R_PM1_PMMIC | R_PM1_PMADC); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ snd_ak4641_hwsync_write(ak, R_PGA); /* mic PGA gain is reset when PMMIC = 0 */ -+ -+ ak->capture_on = 1; -+ -+ snd_ak4641_select_mic(ak); -+ -+ msleep(47); /* accounts for ADC init cycle, time enough for fs >= 44.1 kHz */ -+ -+ return 0; -+} -+ -+static int snd_ak4641_capture_off(struct snd_ak4641 *ak) -+{ -+ if (!ak->capture_on) return 0; -+ -+ ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], -+ 0x00, R_MIC_MPWRI | R_MIC_MPWRE | R_MIC_MSEL); -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMMIC | R_PM1_PMADC); -+ snd_ak4641_hwsync_write(ak, R_MIC); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ if (!ak->playback_on) { -+ ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], R_PM2_MCKPD, R_PM2_MCKPD); -+ snd_ak4641_hwsync_write(ak, R_PM2); -+ } -+ -+ ak->capture_on = 0; -+ -+ return 0; -+} -+ -+int snd_ak4641_open_stream(struct snd_ak4641 *ak, int stream) -+{ -+ snd_ak4641_lock(ak); -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ ak->playback_stream_opened = 1; -+ snd_ak4641_playback_on(ak); -+ } else { -+ ak->capture_stream_opened = 1; -+ snd_ak4641_capture_on(ak); -+ } -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+ -+int snd_ak4641_close_stream(struct snd_ak4641 *ak, int stream) -+{ -+ snd_ak4641_lock(ak); -+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ ak->playback_stream_opened = 0; -+ snd_ak4641_playback_off(ak); -+ } else { -+ ak->capture_stream_opened = 0; -+ snd_ak4641_capture_off(ak); -+ } -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+ -+static int snd_ak4641_init_regs(struct snd_ak4641 *ak) -+{ -+ snd_ak4641_hwsync_read_all(ak); -+ -+ //@@ MEMO: add some configs -+ -+ ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMVCM, R_PM1_PMVCM); -+ ak->regs[R_DAC] = WRITE_MASK(ak->regs[R_DAC], 0x00, R_DAC_DATTC); -+ snd_ak4641_hwsync_write(ak, R_PM1); -+ snd_ak4641_hwsync_write(ak, R_DAC); -+ -+ return 0; -+} -+ -+int snd_ak4641_suspend(struct snd_ak4641 *ak, pm_message_t state) -+{ -+ snd_ak4641_lock(ak); -+ if (ak->playback_on) snd_ak4641_playback_off(ak); -+ if (ak->capture_on) snd_ak4641_capture_off(ak); -+ snd_ak4641_power_off(ak); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+ -+int snd_ak4641_resume(struct snd_ak4641 *ak) -+{ -+ snd_ak4641_lock(ak); -+ snd_ak4641_power_on(ak); -+ snd_ak4641_hwsync_write_all(ak); -+ if (ak->playback_stream_opened) snd_ak4641_playback_on(ak); -+ if (ak->capture_stream_opened) snd_ak4641_capture_on(ak); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+ -+static void snd_ak4641_init_ak(struct snd_ak4641 *ak) -+{ -+ init_MUTEX(&ak->sem); -+ ak->i2c_client.driver = &snd_ak4641_i2c_driver; -+} -+ -+int snd_ak4641_activate(struct snd_ak4641 *ak) -+{ -+ int ret = 0; -+ -+ snd_ak4641_init_ak(ak); -+ snd_ak4641_lock(ak); -+ snd_ak4641_power_on(ak); -+ if ((ret = snd_ak4641_i2c_attach(ak)) < 0) -+ goto failed_i2c_attach; -+ snd_ak4641_init_regs(ak); -+ if ((ret = snd_ak4641_hp_detected_init(ak)) < 0) -+ goto failed_hp_detected_init; -+ snd_ak4641_unlock(ak); -+ return 0; -+ -+ failed_hp_detected_init: -+ snd_ak4641_i2c_detach(ak); -+ failed_i2c_attach: -+ snd_ak4641_power_off(ak); -+ snd_ak4641_unlock(ak); -+ return ret; -+} -+ -+void snd_ak4641_deactivate(struct snd_ak4641 *ak) -+{ -+ snd_ak4641_lock(ak); -+ snd_ak4641_hp_detected_free(ak); -+ snd_ak4641_i2c_detach(ak); -+ snd_ak4641_power_off(ak); -+ snd_ak4641_unlock(ak); -+} -+ -+int snd_ak4641_add_mixer_controls(struct snd_ak4641 *ak, struct snd_card *card) -+{ -+ snd_ak4641_lock(ak); -+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_playback_volume, ak)); -+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_playback_switch, ak)); -+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mic_gain, ak)); -+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mic_boost, ak)); -+ snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mono_out, ak)); -+ snd_ak4641_unlock(ak); -+ return 0; -+} -+ -+/* end {{ Codec Control }} */ -+ -+ -+/* begin {{ Module }} */ -+ -+static int __init snd_ak4641_module_on_load(void) -+{ -+ snd_ak4641_i2c_init(); -+ return 0; -+} -+ -+static void __exit snd_ak4641_module_on_unload(void) -+{ -+ snd_ak4641_i2c_free(); -+} -+ -+module_init(snd_ak4641_module_on_load); -+module_exit(snd_ak4641_module_on_unload); -+ -+EXPORT_SYMBOL(snd_ak4641_activate); -+EXPORT_SYMBOL(snd_ak4641_deactivate); -+EXPORT_SYMBOL(snd_ak4641_add_mixer_controls); -+EXPORT_SYMBOL(snd_ak4641_open_stream); -+EXPORT_SYMBOL(snd_ak4641_close_stream); -+EXPORT_SYMBOL(snd_ak4641_suspend); -+EXPORT_SYMBOL(snd_ak4641_resume); -+EXPORT_SYMBOL(snd_ak4641_hp_connected); -+EXPORT_SYMBOL(snd_ak4641_hp_detected); -+ -+MODULE_AUTHOR("Giorgio Padrin"); -+MODULE_DESCRIPTION("Audio support for codec Asahi Kasei AK4641"); -+MODULE_LICENSE("GPL"); -+ -+/* end {{ Module }} */ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,65 @@ -+/* -+ * Audio support for codec Asahi Kasei AK4641 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * Copyright (c) 2006 Giorgio Padrin <giorgio@mandarinlogiq.org> -+ */ -+ -+#ifndef __SOUND_AK4641_H -+#define __SOUND_AK4641_H -+ -+#include <linux/i2c.h> -+ -+struct snd_ak4641 { -+ struct semaphore sem; -+ -+ u8 regs[0x14]; /* registers cache */ -+ -+ unsigned int -+ powered_on:1, -+ playback_on:1, -+ playback_stream_opened:1, -+ capture_on:1, -+ capture_stream_opened:1; -+ -+ unsigned int -+ hp_connected:1; -+ -+ /* -- configuration (to fill before activation) -- */ -+ void (*power_on_chip)(int on); -+ void (*reset_pin)(int on); -+ void (*headphone_out_on)(int on); -+ void (*speaker_out_on)(int on); -+ -+ struct i2c_client i2c_client; /* to fill .adapter */ -+ /* ----------------------------------------------- */ -+ -+ struct { -+ int detected; -+ struct workqueue_struct *wq; -+ struct work_struct w; -+ } hp_detected; -+}; -+ -+ -+/* Note: opening, closing, suspending and resuming a stream -+ * require the clocks (MCLK and I2S ones) running -+ */ -+ -+/* don't forget to specify I2C adapter in i2c_client field */ -+int snd_ak4641_activate(struct snd_ak4641 *ak); -+ -+void snd_ak4641_deactivate(struct snd_ak4641 *ak); -+int snd_ak4641_add_mixer_controls(struct snd_ak4641 *ak, struct snd_card *card); -+int snd_ak4641_open_stream(struct snd_ak4641 *ak, int stream); -+int snd_ak4641_close_stream(struct snd_ak4641 *ak, int stream); -+int snd_ak4641_suspend(struct snd_ak4641 *ak, pm_message_t state); -+int snd_ak4641_resume(struct snd_ak4641 *ak); -+ -+void snd_ak4641_hp_connected(struct snd_ak4641 *ak, int connected); /* non atomic context */ -+void snd_ak4641_hp_detected(struct snd_ak4641 *ak, int detected); /* atomic context */ -+ -+#endif /* __SOUND_AK4641_H */ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,143 @@ -+/* -+ * LEDs support for the HP iPaq hx4700 -+ * -+ * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru> -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <linux/soc/asic3_base.h> -+ -+#include <asm/hardware/ipaq-asic3.h> -+#include <asm/mach-types.h> -+#include <asm/hardware/asic3_leds.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+//FIXME -+//DEFINE_LED_TRIGGER_SHARED_GLOBAL(htcuniversal_radio_trig); -+//EXPORT_LED_TRIGGER_SHARED(htcuniversal_radio_trig); -+ -+static struct asic3_led htcuniversal_leds[] = { -+ { -+ .led_cdev = { -+ .name = "htcuniversal:red", -+ .default_trigger = "htcuniversal-charging", -+ }, -+ .hw_num = 2, -+ -+ }, -+ { -+ .led_cdev = { -+ .name = "htcuniversal:green", -+ .default_trigger = "htcuniversal-chargefull", -+ }, -+ .hw_num = 1, -+ }, -+ { -+ .led_cdev = { -+ .name = "htcuniversal:wifi-bt", -+ .default_trigger = "htcuniversal-radio", -+ }, -+ .hw_num = 0, -+ }, -+ { -+ .led_cdev = { -+ .name = "htcuniversal:phonebuttons", -+ .default_trigger = "htcuniversal-phonebuttons", -+ }, -+ .hw_num = -1, -+ .gpio_num = ('D'-'A')*16+GPIOD_BL_KEYP_PWR_ON, -+ }, -+ { -+ .led_cdev = { -+ .name = "htcuniversal:vibra", -+ .default_trigger = "htcuniversal-vibra", -+ }, -+ .hw_num = -1, -+ .gpio_num = ('D'-'A')*16+GPIOD_VIBRA_PWR_ON, -+ }, -+ { -+ .led_cdev = { -+ .name = "htcuniversal:flashlight1", -+ .default_trigger = "htcuniversal-flashlight1", -+ }, -+ .hw_num = -1, -+ .gpio_num = ('A'-'A')*16+GPIOA_FLASHLIGHT, -+ }, -+ { -+ .led_cdev = { -+ .name = "htcuniversal:kbdbacklight", -+ .default_trigger = "htcuniversal-kbdbacklight", -+ }, -+ .hw_num = -1, -+ .gpio_num = ('D'-'A')*16+GPIOD_BL_KEYB_PWR_ON, -+ }, -+}; -+ -+void htcuniversal_leds_release(struct device *dev) -+{ -+ return; -+} -+ -+static -+struct asic3_leds_machinfo htcuniversal_leds_machinfo = { -+ .num_leds = ARRAY_SIZE(htcuniversal_leds), -+ .leds = htcuniversal_leds, -+ .asic3_pdev = &htcuniversal_asic3, -+}; -+ -+static -+struct platform_device htcuniversal_leds_pdev = { -+ .name = "asic3-leds", -+ .dev = { -+ .platform_data = &htcuniversal_leds_machinfo, -+ .release = htcuniversal_leds_release, -+ }, -+}; -+ -+static -+int __init htcuniversal_leds_init(void) -+{ -+ int ret; -+ printk("htcuniversal LEDs Driver\n"); -+// led_trigger_register_shared("htcuniversal-radio", &htcuniversal_radio_trig); -+ -+ ret = asic3_leds_register(); -+ if (ret) goto asic3_leds_failed; -+ -+ ret = platform_device_register(&htcuniversal_leds_pdev); -+ if (ret) goto platform_device_failed; -+ -+ goto success; -+ -+platform_device_failed: -+ asic3_leds_unregister(); -+asic3_leds_failed: -+// led_trigger_unregister_shared(htcuniversal_radio_trig); -+ printk("htcuniversal LEDs Driver failed to init"); -+success: -+ return ret; -+} -+ -+static -+void __exit htcuniversal_leds_exit(void) -+{ -+// led_trigger_unregister_shared(htcuniversal_radio_trig); -+ platform_device_unregister(&htcuniversal_leds_pdev); -+ asic3_leds_unregister(); -+ return; -+} -+ -+module_init(htcuniversal_leds_init); -+module_exit(htcuniversal_leds_exit); -+ -+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>"); -+MODULE_DESCRIPTION("htcuniversal LEDs driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,61 @@ -+/* -+ * Use consistent with the GNU GPL is permitted, -+ * provided that this copyright notice is -+ * preserved in its entirety in all copies and derived works. -+ * -+ * Copyright (C) 2006 Paul Sokolosvky -+ * Based on code from older versions of htcuniversal_lcd.c -+ * -+ */ -+ -+#include <linux/types.h> -+#include <linux/platform_device.h> -+#include <asm/arch/hardware.h> /* for pxa-regs.h (__REG) */ -+#include <asm/arch/pxa-regs.h> -+#include <asm/mach-types.h> /* machine_is_htcuniversal */ -+//#include <linux/corgi_bl.h> -+#include <linux/backlight.h> -+#include <linux/err.h> -+ -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+#include <asm/hardware/ipaq-asic3.h> -+#include <linux/soc/asic3_base.h> -+ -+#define HTCUNIVERSAL_MAX_INTENSITY 0xc7 -+ -+static void htcuniversal_set_bl_intensity(int intensity) -+{ -+ PWM_CTRL1 = 1; /* pre-scaler */ -+ PWM_PWDUTY1 = intensity; /* duty cycle */ -+ PWM_PERVAL1 = HTCUNIVERSAL_MAX_INTENSITY+1; /* period */ -+ -+ if (intensity > 0) { -+ pxa_set_cken(CKEN_PWM1, 1); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, -+ (1<<GPIOD_FL_PWR_ON), (1<<GPIOD_FL_PWR_ON)); -+ } else { -+ pxa_set_cken(CKEN_PWM1, 0); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, -+ (1<<GPIOD_FL_PWR_ON), 0); -+ } -+} -+ -+ -+static struct generic_bl_info htcuniversal_bl_machinfo = { -+ .default_intensity = HTCUNIVERSAL_MAX_INTENSITY / 4, -+ .limit_mask = 0xff, -+ .max_intensity = HTCUNIVERSAL_MAX_INTENSITY, -+ .set_bl_intensity = htcuniversal_set_bl_intensity, -+}; -+ -+struct platform_device htcuniversal_bl = { -+ .name = "corgi-bl", -+ .dev = { -+ .platform_data = &htcuniversal_bl_machinfo, -+ }, -+}; -+ -+MODULE_AUTHOR("Paul Sokolovsky <pmiscml@gmail.com>"); -+MODULE_DESCRIPTION("Backlight driver for HTC Universal"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,135 @@ -+/* Bluetooth interface driver for TI BRF6150 on HX4700 -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * 2005-04-21 Todd Blumer Created. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <linux/soc/asic3_base.h> -+ -+#include <asm/hardware.h> -+#include <asm/arch/serial.h> -+#include <asm/hardware/ipaq-asic3.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+#include "htcuniversal_bt.h" -+ -+static uint use_led=1; -+ -+static void -+htcuniversal_bt_configure( int state ) -+{ -+ int tries; -+ -+ printk( KERN_NOTICE "htcuniversal configure bluetooth: %d\n", state ); -+ switch (state) { -+ -+ case PXA_UART_CFG_PRE_STARTUP: -+ break; -+ -+ case PXA_UART_CFG_POST_STARTUP: -+ /* pre-serial-up hardware configuration */ -+ htcuniversal_egpio_enable(1<<EGPIO5_BT_3V3_ON); -+ mdelay(50); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_PWR_ON, 1<<GPIOC_BT_PWR_ON); -+ mdelay(10); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_RESET, 0); -+ mdelay(10); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_RESET, 1<<GPIOC_BT_RESET); -+ mdelay(10); -+ -+ /* -+ * BRF6150's RTS goes low when firmware is ready -+ * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms -+ */ -+ tries = 0; -+ do { -+ mdelay(10); -+ } while ((BTMSR & MSR_CTS) == 0 && tries++ < 50); -+ if (use_led) { -+// htcuniversal_set_led(2, 16, 16); -+ } -+ break; -+ -+ case PXA_UART_CFG_PRE_SHUTDOWN: -+ htcuniversal_egpio_disable(1<<EGPIO5_BT_3V3_ON ); -+ mdelay(50); -+// htcuniversal_clear_led(2); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_PWR_ON, 0); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+ -+static int -+htcuniversal_bt_probe( struct platform_device *dev ) -+{ -+ struct htcuniversal_bt_funcs *funcs = dev->dev.platform_data; -+ -+ /* configure bluetooth UART */ -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_RXD_MD ); -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_TXD_MD ); -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_UART_CTS_MD ); -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_UART_RTS_MD ); -+ -+ funcs->configure = htcuniversal_bt_configure; -+ -+ /* Make sure the LED is off */ -+// htcuniversal_clear_led(2); -+ -+ return 0; -+} -+ -+static int -+htcuniversal_bt_remove( struct platform_device *dev ) -+{ -+ struct htcuniversal_bt_funcs *funcs = dev->dev.platform_data; -+ -+ funcs->configure = NULL; -+ -+ /* Make sure the LED is off */ -+// htcuniversal_clear_led(2); -+ -+ return 0; -+} -+ -+static struct platform_driver bt_driver = { -+ .driver = { -+ .name = "htcuniversal_bt", -+ }, -+ .probe = htcuniversal_bt_probe, -+ .remove = htcuniversal_bt_remove, -+}; -+ -+module_param(use_led, uint, 0); -+ -+static int __init -+htcuniversal_bt_init( void ) -+{ -+ printk(KERN_NOTICE "htcuniversal Bluetooth Driver\n"); -+ return platform_driver_register( &bt_driver ); -+} -+ -+static void __exit -+htcuniversal_bt_exit( void ) -+{ -+ platform_driver_unregister( &bt_driver ); -+} -+ -+module_init( htcuniversal_bt_init ); -+module_exit( htcuniversal_bt_exit ); -+ -+MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC"); -+MODULE_DESCRIPTION("HTC Universal Bluetooth Support Driver"); -+MODULE_LICENSE("GPL"); -+ -+/* vim600: set noexpandtab sw=8 ts=8 :*/ -+ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,17 @@ -+/* -+ * Bluetooth support file for calling bluetooth configuration functions -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * 2005-06 Todd Blumer Initial Revision -+ */ -+ -+#ifndef _HTCUNIVERSAL_BT_H -+#define _HTCUNIVERSAL_BT_H -+ -+struct htcuniversal_bt_funcs { -+ void (*configure) ( int state ); -+}; -+ -+ -+#endif -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,87 @@ -+/* -+ * Buttons driver for HTC Universal -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. -+ * -+ * Copyright (C) 2005 Pawel Kolodziejski -+ * Copyright (C) 2003 Joshua Wise -+ * -+ */ -+ -+#include <linux/input.h> -+#include <linux/input_pda.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/irq.h> -+#include <linux/platform_device.h> -+#include <linux/gpio_keys.h> -+#include <linux/soc/asic3_base.h> -+#include <asm/mach-types.h> -+#include <asm/hardware/asic3_keys.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+static struct asic3_keys_button asic3_buttons[] = { -+//{KEY_SCREEN, ASIC3_GPIOA_IRQ_BASE+GPIOA_COVER_ROTATE_N, 1, "screen_cover", EV_SW}, -+//{KEY_SWITCHVIDEOMODE, ASIC3_GPIOB_IRQ_BASE+GPIOB_CLAMSHELL_N, 1, "clamshell_rotate", EV_SW}, -+//{KEY_KBDILLUMTOGGLE, ASIC3_GPIOB_IRQ_BASE+GPIOB_NIGHT_SENSOR, 1, "night_sensor", EV_SW}, -+{SW_LID, ASIC3_GPIOA_IRQ_BASE+GPIOA_COVER_ROTATE_N, 1, "screen_cover", EV_SW}, -+{SW_TABLET_MODE, ASIC3_GPIOB_IRQ_BASE+GPIOB_CLAMSHELL_N, 1, "clamshell_rotate", EV_SW}, -+//{SW_NIGHT_SENSOR, ASIC3_GPIOB_IRQ_BASE+GPIOB_NIGHT_SENSOR, 1, "night_sensor", EV_SW}, -+{KEY_F10, ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_BACKLIGHT_N, 1, "backlight_button"}, -+{KEY_RECORD, ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_RECORD_N, 1, "record_button"}, -+{KEY_CAMERA, ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_CAMERA_N, 1, "camera_button"}, -+{KEY_VOLUMEDOWN, ASIC3_GPIOA_IRQ_BASE+GPIOA_VOL_UP_N, 1, "volume_slider_down"}, -+{KEY_VOLUMEUP, ASIC3_GPIOA_IRQ_BASE+GPIOA_VOL_DOWN_N, 1, "volume_slider_up"}, -+{KEY_KPENTER, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_OK_N, 1, "select"}, -+{KEY_RIGHT, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_RIGHT_N, 1, "right"}, -+{KEY_LEFT, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_LEFT_N, 1, "left"}, -+{KEY_DOWN, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_DOWN_N, 1, "down"}, -+{KEY_UP, ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_UP_N, 1, "up"}, -+}; -+ -+static struct asic3_keys_platform_data asic3_keys_data = { -+ .buttons = asic3_buttons, -+ .nbuttons = ARRAY_SIZE(asic3_buttons), -+ .asic3_dev = &htcuniversal_asic3.dev, -+}; -+ -+static struct platform_device htcuniversal_keys_asic3 = { -+ .name = "asic3-keys", -+ .dev = { .platform_data = &asic3_keys_data, } -+}; -+ -+static int __init htcuniversal_buttons_probe(struct platform_device *dev) -+{ -+ platform_device_register(&htcuniversal_keys_asic3); -+ return 0; -+} -+ -+static struct platform_driver htcuniversal_buttons_driver = { -+ .driver = { -+ .name = "htcuniversal_buttons", -+ }, -+ .probe = htcuniversal_buttons_probe, -+}; -+ -+static int __init htcuniversal_buttons_init(void) -+{ -+ if (!machine_is_htcuniversal()) -+ return -ENODEV; -+ -+ return platform_driver_register(&htcuniversal_buttons_driver); -+} -+ -+static void __exit htcuniversal_buttons_exit(void) -+{ -+ platform_driver_unregister(&htcuniversal_buttons_driver); -+} -+ -+module_init(htcuniversal_buttons_init); -+module_exit(htcuniversal_buttons_exit); -+ -+MODULE_AUTHOR ("Joshua Wise, Pawel Kolodziejski, Paul Sokolosvky"); -+MODULE_DESCRIPTION ("Buttons support for HTC Universal"); -+MODULE_LICENSE ("GPL"); -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,226 @@ -+/* Core Hardware driver for Hx4700 (Serial, ASIC3, EGPIOs) -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * 2005-03-29 Todd Blumer Converted basic structure to support hx4700 -+ * 2005-04-30 Todd Blumer Add IRDA code from H2200 -+ */ -+ -+#include <linux/module.h> -+#include <linux/version.h> -+#include <linux/interrupt.h> -+#include <linux/platform_device.h> -+#include <linux/delay.h> -+#include <linux/pm.h> -+#include <linux/irq.h> -+ -+#include <asm/io.h> -+#include <asm/mach/irq.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/pxa-pm_ll.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+#include <linux/soc/asic3_base.h> -+#include <asm/hardware/ipaq-asic3.h> -+ -+volatile u_int16_t *egpios; -+u_int16_t egpio_reg; -+ -+static int htc_bootloader = 0; /* Is the stock HTC bootloader installed? */ -+ -+/* -+ * may make sense to put egpios elsewhere, but they're here now -+ * since they share some of the same address space with the TI WLAN -+ * -+ * EGPIO register is write-only -+ */ -+ -+void -+htcuniversal_egpio_enable( u_int16_t bits ) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ -+ egpio_reg |= bits; -+ *egpios = egpio_reg; -+ -+ local_irq_restore(flags); -+} -+EXPORT_SYMBOL_GPL(htcuniversal_egpio_enable); -+ -+void -+htcuniversal_egpio_disable( u_int16_t bits ) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ -+ egpio_reg &= ~bits; -+ *egpios = egpio_reg; -+ -+ local_irq_restore(flags); -+} -+EXPORT_SYMBOL_GPL(htcuniversal_egpio_disable); -+ -+#ifdef CONFIG_PM -+ -+//void htcuniversal_ll_pm_init(void); -+ -+static int htcuniversal_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ /* Turn off external clocks here, because htcuniversal_power and asic3_mmc -+ * scared to do so to not hurt each other. (-5 mA) */ -+ -+ -+ /* 0x20c2 is HTC clock value -+ * CLOCK_CDEX_SOURCE 2 -+ * CLOCK_CDEX_SPI 0 -+ * CLOCK_CDEX_OWM 0 -+ * -+ * CLOCK_CDEX_PWM0 0 -+ * CLOCK_CDEX_PWM1 0 -+ * CLOCK_CDEX_LED0 1 -+ * CLOCK_CDEX_LED1 1 -+ * -+ * CLOCK_CDEX_LED2 0 -+ * CLOCK_CDEX_SD_HOST 0 -+ * CLOCK_CDEX_SD_BUS 0 -+ * CLOCK_CDEX_SMBUS 0 -+ * -+ * CLOCK_CDEX_CONTROL_CX 0 -+ * CLOCK_CDEX_EX0 1 -+ * CLOCK_CDEX_EX1 0 -+ * */ -+ asic3_set_clock_cdex(&htcuniversal_asic3.dev, 0xffff, CLOCK_CDEX_SOURCE1 -+ |CLOCK_CDEX_LED0 -+ |CLOCK_CDEX_LED1 -+ |CLOCK_CDEX_LED2 -+ |CLOCK_CDEX_EX0 -+ |CLOCK_CDEX_EX1); -+ -+ *egpios = 0; /* turn off all egpio power */ -+ -+ /* Wake up enable. */ -+ PWER = PWER_GPIO0 -+ | PWER_GPIO1 /* reset */ -+ | PWER_GPIO9 /* USB */ -+ | PWER_GPIO10 /* AC on USB */ -+ | PWER_GPIO14 /* ASIC3 mux */ -+ | PWER_RTC; -+ /* Wake up on falling edge. */ -+ PFER = PWER_GPIO0 -+ | PWER_GPIO1 -+ | PWER_GPIO9 -+ | PWER_GPIO10 -+ | PWER_GPIO14; -+ -+ /* Wake up on rising edge. */ -+ PRER = PWER_GPIO0 -+ | PWER_GPIO1 -+ | PWER_GPIO9 -+ | PWER_GPIO10; -+ /* 3.6864 MHz oscillator power-down enable */ -+ PCFR = PCFR_OPDE | PCFR_PI2CEN | PCFR_GPROD | PCFR_GPR_EN; -+ -+ PGSR0 = 0x09088004; -+ PGSR1 = 0x00020002; -+ PGSR2 = 0x8001c000; -+ PGSR3 = 0x00106284; -+ -+ PSLR = 0xcc000000; -+ -+#if 0 -+ /* -+ * If we're using bootldr and not the stock HTC bootloader, -+ * we want to wake up periodically to see if the charge is full while -+ * it is suspended. We do this with the OS timer 4 in the pxa270. -+ */ -+ if (!htc_bootloader) { -+ OMCR4 = 0x4b; /* Periodic, self-resetting, 1-second timer */ -+ OSMR4 = 5; /* Wake up bootldr after x seconds so it can -+ figure out what to do with the LEDs. */ -+ OIER |= 0x10; /* Enable interrupt source for Timer 4 */ -+ OSCR4 = 0; /* This starts the timer */ -+ } -+#endif -+ -+ asic3_set_extcf_select(&htcuniversal_asic3.dev, ASIC3_EXTCF_OWM_EN, 0); -+ -+ return 0; -+} -+ -+static int htcuniversal_resume(struct platform_device *dev) -+{ -+ htcuniversal_egpio_enable(0); -+ -+ return 0; -+} -+#else -+# define htcuniversal_suspend NULL -+# define htcuniversal_resume NULL -+#endif -+ -+static int -+htcuniversal_core_probe( struct platform_device *dev ) -+{ -+ -+ printk( KERN_NOTICE "HTC Universal Core Hardware Driver\n" ); -+ -+ egpios = (volatile u_int16_t *)ioremap_nocache(HTCUNIVERSAL_EGPIO_BASE, sizeof *egpios ); -+ if (!egpios) -+ return -ENODEV; -+ else -+ printk( KERN_NOTICE "HTC Universal Core: egpio at phy=0x%8.8x is at virt=0x%p\n", -+ HTCUNIVERSAL_EGPIO_BASE, egpios ); -+ -+ printk("Using stock HTC first stage bootloader\n"); -+ htc_bootloader = 1; -+ -+// htcuniversal_ll_pm_init(); -+ -+ return 0; -+} -+ -+static int -+htcuniversal_core_remove( struct platform_device *dev ) -+{ -+ -+ if (egpios != NULL) -+ iounmap( (void *)egpios ); -+ -+ return 0; -+} -+ -+static struct platform_driver htcuniversal_core_driver = { -+ .driver = { -+ .name = "htcuniversal_core", -+ }, -+ .probe = htcuniversal_core_probe, -+ .remove = htcuniversal_core_remove, -+ .suspend = htcuniversal_suspend, -+ .resume = htcuniversal_resume, -+}; -+ -+static int __init -+htcuniversal_core_init( void ) -+{ -+ return platform_driver_register( &htcuniversal_core_driver ); -+} -+ -+ -+static void __exit -+htcuniversal_core_exit( void ) -+{ -+ platform_driver_unregister( &htcuniversal_core_driver ); -+} -+ -+module_init( htcuniversal_core_init ); -+module_exit( htcuniversal_core_exit ); -+ -+MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC"); -+MODULE_DESCRIPTION("HTC Universal Core Hardware Driver"); -+MODULE_LICENSE("GPL"); -+ -+/* vim600: set noexpandtab sw=8 ts=8 :*/ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,212 @@ -+/* -+ * Use consistent with the GNU GPL is permitted, -+ * provided that this copyright notice is -+ * preserved in its entirety in all copies and derived works. -+ * -+ * History: -+ * -+ * 2004-03-01 Eddi De Pieri Adapted for htcuniversal using h3900_lcd.c -+ * 2004 Shawn Anderson Lcd hacking on htcuniversal -+ * see h3900_lcd.c for more history. -+ * -+ */ -+ -+#include <linux/types.h> -+#include <asm/arch/hardware.h> /* for pxa-regs.h (__REG) */ -+#include <linux/platform_device.h> -+#include <asm/arch/pxa-regs.h> /* LCCR[0,1,2,3]* */ -+#include <asm/arch/bitfield.h> /* for pxa-regs.h (Fld, etc) */ -+#include <asm/arch/pxafb.h> /* pxafb_mach_info, set_pxa_fb_info */ -+#include <asm/mach-types.h> /* machine_is_htcuniversal */ -+#include <linux/lcd.h> /* lcd_device */ -+#include <linux/err.h> -+#include <linux/delay.h> -+ -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+#include <asm/hardware/ipaq-asic3.h> -+#include <linux/soc/asic3_base.h> -+ -+static int saved_lcdpower=-1; -+ -+static int powerup_lcd(void) -+{ -+ printk( KERN_INFO "htcuniversal powerup_lcd: called\n"); -+ -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0); -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0); -+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0); -+#if 1 -+ LCCR4|=LCCR4_PCDDIV; -+#endif -+ pxa_set_cken(CKEN_LCD, 0); -+ -+ mdelay(100); -+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 1<<GPIOA_LCD_PWR5_ON); -+ mdelay(5); -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 1<<GPIOB_LCD_PWR3_ON); -+ mdelay(2); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 1<<GPIOC_LCD_PWR1_ON); -+ mdelay(2); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 1<<GPIOC_LCD_PWR2_ON); -+ mdelay(20); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 1<<GPIOD_LCD_PWR4_ON); -+ mdelay(1); -+ pxa_set_cken(CKEN_LCD, 1); -+ -+ SET_HTCUNIVERSAL_GPIO(LCD1,1); -+ SET_HTCUNIVERSAL_GPIO(LCD2,1); -+ return 0; -+} -+ -+static int powerdown_lcd(void) -+{ -+ printk( KERN_INFO "htcuniversal powerdown_lcd: called\n"); -+ -+#if 1 -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0); -+ mdelay(100); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0); -+ mdelay(10); -+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0); -+ mdelay(1); -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0); -+ mdelay(1); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0); -+ pxa_set_cken(CKEN_LCD, 0); -+ -+ SET_HTCUNIVERSAL_GPIO(LCD1,0); -+ SET_HTCUNIVERSAL_GPIO(LCD2,0); -+#else -+ pxa_set_cken(CKEN_LCD, 0); -+ -+ SET_HTCUNIVERSAL_GPIO(LCD1,0); -+ SET_HTCUNIVERSAL_GPIO(LCD2,0); -+ -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0); -+ mdelay(100); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0); -+ mdelay(10); -+ asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0); -+ mdelay(1); -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0); -+ mdelay(1); -+ asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0); -+#endif -+ return 0; -+} -+ -+static int htcuniversal_lcd_set_power(struct lcd_device *lm, int power) -+{ -+ /* Enable or disable power to the LCD (0: on; 4: off) */ -+ -+ if ( power < 1 ) { -+ -+ powerup_lcd(); -+ -+ } else { -+ -+ powerdown_lcd(); -+ -+ } -+ -+ saved_lcdpower=power; -+ -+ return 0; -+} -+ -+static int htcuniversal_lcd_get_power(struct lcd_device *lm) -+{ -+ /* Get the LCD panel power status (0: full on, 1..3: controller -+ * power on, flat panel power off, 4: full off) */ -+ -+ if (saved_lcdpower == -1) -+ { -+ htcuniversal_lcd_set_power(lm, 4); -+ saved_lcdpower=4; -+ } -+ -+ return saved_lcdpower; -+} -+ -+static struct lcd_ops htcuniversal_lcd_properties = -+{ -+ .get_power = htcuniversal_lcd_get_power, -+ .set_power = htcuniversal_lcd_set_power, -+}; -+ -+static struct lcd_device *htcuniversal_lcd_dev; -+ -+static int htcuniversal_lcd_probe(struct platform_device * dev) -+{ -+ htcuniversal_lcd_dev = lcd_device_register("pxa2xx-fb", &dev->dev, NULL, -+ &htcuniversal_lcd_properties); -+ if (IS_ERR(htcuniversal_lcd_dev)) { -+ printk("htcuniversal_lcd_probe: error registering devices\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int htcuniversal_lcd_remove(struct platform_device * dev) -+{ -+ htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 4); -+ lcd_device_unregister(htcuniversal_lcd_dev); -+ -+ return 0; -+} -+ -+static int htcuniversal_lcd_suspend(struct platform_device * dev, pm_message_t state) -+{ -+// printk("htcuniversal_lcd_suspend: called.\n"); -+ htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 4); -+ return 0; -+} -+ -+static int htcuniversal_lcd_resume(struct platform_device * dev) -+{ -+// printk("htcuniversal_lcd_resume: called.\n"); -+ -+ /* */ -+#if 1 -+ LCCR4|=LCCR4_PCDDIV; -+#endif -+ -+ htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 0); -+ return 0; -+} -+ -+static struct platform_driver htcuniversal_lcd_driver = { -+ .driver = { -+ .name = "htcuniversal_lcd", -+ }, -+ .probe = htcuniversal_lcd_probe, -+ .remove = htcuniversal_lcd_remove, -+ .suspend = htcuniversal_lcd_suspend, -+ .resume = htcuniversal_lcd_resume, -+}; -+ -+static int htcuniversal_lcd_init(void) -+{ -+ if (!machine_is_htcuniversal()) -+ return -ENODEV; -+ -+ return platform_driver_register(&htcuniversal_lcd_driver); -+} -+ -+static void htcuniversal_lcd_exit(void) -+{ -+ lcd_device_unregister(htcuniversal_lcd_dev); -+ platform_driver_unregister(&htcuniversal_lcd_driver); -+} -+ -+module_init(htcuniversal_lcd_init); -+module_exit(htcuniversal_lcd_exit); -+ -+MODULE_AUTHOR("xanadux.org"); -+MODULE_DESCRIPTION("Framebuffer driver for HTC Universal"); -+MODULE_LICENSE("GPL"); -+ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,167 @@ -+ -+/* Phone interface driver for Qualcomm MSM6250 on HTC Universal -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * 2005-04-21 Todd Blumer Created. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <linux/soc/asic3_base.h> -+ -+#include <asm/hardware.h> -+#include <asm/arch/serial.h> -+#include <asm/hardware/ipaq-asic3.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+#include "htcuniversal_phone.h" -+ -+static void phone_reset(void) -+{ -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_RESET2, 0); -+ -+ SET_HTCUNIVERSAL_GPIO(PHONE_RESET,0); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0); -+ mdelay(1); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 1<<GPIOD_BB_RESET1); -+ mdelay(20); -+ SET_HTCUNIVERSAL_GPIO(PHONE_RESET,1); -+ mdelay(200); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0); -+} -+ -+static void phone_off(void) -+{ -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 1<<GPIOD_BB_RESET1); -+ mdelay(2000); -+ asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0); -+ -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_RESET2, 1<<GPIOB_BB_RESET2); -+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0); -+} -+ -+static void -+htcuniversal_phone_configure( int state ) -+{ -+ int tries; -+ unsigned short statusb; -+ -+ printk( KERN_NOTICE "htcuniversal configure phone: %d\n", state ); -+ switch (state) { -+ -+ case PXA_UART_CFG_PRE_STARTUP: -+ break; -+ -+ case PXA_UART_CFG_POST_STARTUP: -+ /* pre-serial-up hardware configuration */ -+ -+ SET_HTCUNIVERSAL_GPIO(PHONE_START,0); /* "bootloader" */ -+ SET_HTCUNIVERSAL_GPIO(PHONE_UNKNOWN,0); /* not used */ -+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0); /* PHONE_OFF */ -+ -+ phone_reset(); -+ -+ SET_HTCUNIVERSAL_GPIO(PHONE_START,1); /* phone */ -+ -+ phone_reset(); -+ -+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_READY, 0); -+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_UNKNOWN3, 0); -+ -+ /* -+ */ -+ tries = 0; -+ do { -+ mdelay(10); -+ statusb = asic3_get_gpio_status_b( &htcuniversal_asic3.dev ); -+ } while ( (statusb & (1<<GPIOB_UMTS_DCD)) == 0 && tries++ < 200); -+ -+ printk("UMTS_DCD tries=%d of 200\n",tries); -+ -+ tries = 0; -+ do { -+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,1); -+ mdelay(10); -+ SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0); -+ mdelay(20); -+ statusb = asic3_get_gpio_status_b( &htcuniversal_asic3.dev ); -+ } while ( (statusb & (1<<GPIOB_BB_READY)) == 0 && tries++ < 200); -+ -+ printk("BB_READY tries=%d of 200\n",tries); -+ -+ break; -+ -+ case PXA_UART_CFG_PRE_SHUTDOWN: -+ -+ phone_off(); -+ -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+ -+static int -+htcuniversal_phone_probe( struct platform_device *dev ) -+{ -+ struct htcuniversal_phone_funcs *funcs = dev->dev.platform_data; -+ -+ /* configure phone UART */ -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_RXD_MD ); -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_TXD_MD ); -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS_MD ); -+ pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS_MD ); -+ -+ funcs->configure = htcuniversal_phone_configure; -+ -+ return 0; -+} -+ -+static int -+htcuniversal_phone_remove( struct platform_device *dev ) -+{ -+ struct htcuniversal_phone_funcs *funcs = dev->dev.platform_data; -+ -+ funcs->configure = NULL; -+ -+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_READY, 1<<GPIOB_BB_READY); -+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_UNKNOWN3, 1<<GPIOB_BB_UNKNOWN3); -+ -+ return 0; -+} -+ -+static struct platform_driver phone_driver = { -+ .driver = { -+ .name = "htcuniversal_phone", -+ }, -+ .probe = htcuniversal_phone_probe, -+ .remove = htcuniversal_phone_remove, -+}; -+ -+static int __init -+htcuniversal_phone_init( void ) -+{ -+ printk(KERN_NOTICE "htcuniversal Phone Driver\n"); -+ return platform_driver_register( &phone_driver ); -+} -+ -+static void __exit -+htcuniversal_phone_exit( void ) -+{ -+ platform_driver_unregister( &phone_driver ); -+} -+ -+module_init( htcuniversal_phone_init ); -+module_exit( htcuniversal_phone_exit ); -+ -+MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC"); -+MODULE_DESCRIPTION("HTC Universal Phone Support Driver"); -+MODULE_LICENSE("GPL"); -+ -+/* vim600: set noexpandtab sw=8 ts=8 :*/ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,16 @@ -+/* -+ * Bluetooth support file for calling bluetooth configuration functions -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * 2005-06 Todd Blumer Initial Revision -+ */ -+ -+#ifndef _HTCUNIVERSAL_PHONE_H -+#define _HTCUNIVERSAL_PHONE_H -+ -+struct htcuniversal_phone_funcs { -+ void (*configure) ( int state ); -+}; -+ -+#endif -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,69 @@ -+/* -+ * MyPal 716 power management support for the original HTC IPL in DoC G3 -+ * -+ * Use consistent with the GNU GPL is permitted, provided that this -+ * copyright notice is preserved in its entirety in all copies and -+ * derived works. -+ * -+ * Copyright (C) 2005 Pawel Kolodziejski -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/device.h> -+#include <linux/pm.h> -+ -+#include <asm/mach-types.h> -+#include <asm/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/pxa-pm_ll.h> -+ -+#ifdef CONFIG_PM -+ -+static u32 *addr_a0040000; -+static u32 *addr_a0040004; -+static u32 *addr_a0040008; -+static u32 *addr_a004000c; -+ -+static u32 save_a0040000; -+static u32 save_a0040004; -+static u32 save_a0040008; -+static u32 save_a004000c; -+ -+static void htcuniversal_pxa_ll_pm_suspend(unsigned long resume_addr) -+{ -+ save_a0040000 = *addr_a0040000; -+ save_a0040004 = *addr_a0040004; -+ save_a0040008 = *addr_a0040008; -+ save_a004000c = *addr_a004000c; -+ -+ /* jump to PSPR */ -+ *addr_a0040000 = 0xe3a00101; // mov r0, #0x40000000 -+ *addr_a0040004 = 0xe380060f; // orr r0, r0, #0x0f000000 -+ *addr_a0040008 = 0xe3800008; // orr r0, r0, #8 -+ *addr_a004000c = 0xe590f000; // ldr pc, [r0] -+} -+ -+static void htcuniversal_pxa_ll_pm_resume(void) -+{ -+ *addr_a0040000 = save_a0040000; -+ *addr_a0040004 = save_a0040004; -+ *addr_a0040008 = save_a0040008; -+ *addr_a004000c = save_a004000c; -+} -+ -+static struct pxa_ll_pm_ops htcuniversal_ll_pm_ops = { -+ .suspend = htcuniversal_pxa_ll_pm_suspend, -+ .resume = htcuniversal_pxa_ll_pm_resume, -+}; -+ -+void htcuniversal_ll_pm_init(void) { -+ addr_a0040000 = phys_to_virt(0xa0040000); -+ addr_a0040004 = phys_to_virt(0xa0040004); -+ addr_a0040008 = phys_to_virt(0xa0040008); -+ addr_a004000c = phys_to_virt(0xa004000c); -+ -+ pxa_pm_set_ll_ops(&htcuniversal_ll_pm_ops); -+} -+#endif /* CONFIG_PM */ -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,97 @@ -+/* -+ * pda_power driver for HTC Universal -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at -+ * your option) any later version. -+ * -+ */ -+ -+#include <linux/platform_device.h> -+#include <linux/module.h> -+#include <linux/pda_power.h> -+#include <linux/soc/asic3_base.h> -+ -+#include <asm/mach-types.h> -+#include <asm/hardware.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+static void charge_on(int flags) -+{ -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_CHARGE_EN, 0); -+} -+ -+static int ac_on(void) -+{ -+ return (GET_HTCUNIVERSAL_GPIO(POWER_DET) == 0); -+} -+ -+static int usb_on(void) -+{ -+ return (GET_HTCUNIVERSAL_GPIO(USB_DET) == 0); -+} -+ -+static char *supplicants[] = { -+ "ds2760-battery.0", "backup-battery" -+}; -+ -+static struct pda_power_pdata power_pdata = { -+ .is_ac_online = ac_on, -+ .is_usb_online = usb_on, -+ .set_charge = charge_on, -+ .supplied_to = supplicants, -+ .num_supplicants = ARRAY_SIZE(supplicants), -+}; -+ -+static struct resource power_resources[] = { -+ [0] = { -+ .name = "ac", -+ .start = HTCUNIVERSAL_IRQ(POWER_DET), -+ .end = HTCUNIVERSAL_IRQ(POWER_DET), -+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, -+ }, -+ [1] = { -+ .name = "usb", -+ .start = HTCUNIVERSAL_IRQ(USB_DET), -+ .end = HTCUNIVERSAL_IRQ(USB_DET), -+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, -+ }, -+}; -+ -+static void dev_release(struct device *dev) -+{ -+ return; -+} -+ -+static struct platform_device power_dev = -+{ -+ .name = "pda-power", -+ .id = -1, -+ .resource = power_resources, -+ .num_resources = ARRAY_SIZE(power_resources), -+ .dev = -+ { -+ .platform_data = &power_pdata, -+ .release = dev_release, -+ }, -+}; -+ -+static int htcuniversal_power_init(void) -+{ -+ return platform_device_register(&power_dev); -+} -+ -+static void htcuniversal_power_exit(void) -+{ -+ platform_device_unregister(&power_dev); -+ -+ return; -+} -+ -+module_init(htcuniversal_power_init); -+module_exit(htcuniversal_power_exit); -+ -+MODULE_DESCRIPTION("Power driver for HTC Universal"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,490 @@ -+/* Touch screen driver for the TI something-or-other -+ * -+ * Copyright © 2005 SDG Systems, LLC -+ * -+ * Based on code that was based on the SAMCOP driver. -+ * Copyright © 2003, 2004 Compaq Computer Corporation. -+ * -+ * Use consistent with the GNU GPL is permitted, -+ * provided that this copyright notice is -+ * preserved in its entirety in all copies and derived works. -+ * -+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, -+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS -+ * FITNESS FOR ANY PARTICULAR PURPOSE. -+ * -+ * Author: Keith Packard <keith.packard@hp.com> -+ * May 2003 -+ * -+ * Updates: -+ * -+ * 2004-02-11 Michael Opdenacker Renamed names from samcop to shamcop, -+ * Goal:support HAMCOP and SAMCOP. -+ * 2004-02-14 Michael Opdenacker Temporary fix for device id handling -+ * -+ * 2005-02-18 Aric Blumer Converted basic structure to support hx4700 -+ * -+ * 2005-06-07 Aric Blumer Added tssim device handling so we can -+ * hook in the fbvncserver. -+ */ -+ -+#include <linux/module.h> -+#include <linux/version.h> -+ -+#include <linux/init.h> -+#include <linux/fs.h> -+#include <linux/cdev.h> -+#include <linux/interrupt.h> -+#include <linux/sched.h> -+#include <linux/pm.h> -+#include <linux/delay.h> -+#include <linux/input.h> -+#include <linux/platform_device.h> -+#include <linux/irq.h> -+ -+#include <asm/arch/hardware.h> -+#include <asm/mach/irq.h> -+#include <asm/io.h> -+ -+/* remove me */ -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+#include <asm/mach-types.h> -+ -+#include <asm/hardware/ipaq-asic3.h> -+#include <linux/soc/asic3_base.h> -+ -+ -+#include "tsc2046_ts.h" -+ -+enum touchscreen_state { -+ STATE_WAIT_FOR_TOUCH, /* Waiting for a PEN interrupt */ -+ STATE_SAMPLING /* Actively sampling ADC */ -+}; -+ -+struct touchscreen_data { -+ enum touchscreen_state state; -+ struct timer_list timer; -+ int irq; -+ struct input_dev *input; -+ /* */ -+ int port; -+ int clock; -+ int pwrbit_X; -+ int pwrbit_Y; -+ int (*pen_down)(void); -+}; -+ -+static unsigned long poll_sample_time = 10; /* Sample every 10 milliseconds */ -+ -+static struct touchscreen_data *ts_data; -+ -+static int irqblock; -+ -+module_param(poll_sample_time, ulong, 0644); -+MODULE_PARM_DESC(poll_sample_time, "Poll sample time"); -+ -+static inline void -+report_touchpanel(struct touchscreen_data *ts, int pressure, int x, int y) -+{ -+ input_report_abs(ts->input, ABS_PRESSURE, pressure); -+ input_report_abs(ts->input, ABS_X, x); -+ input_report_abs(ts->input, ABS_Y, y); -+ input_sync(ts->input); -+} -+ -+static void start_read(struct touchscreen_data *touch); -+ -+static irqreturn_t -+pen_isr(int irq, void *irq_desc) -+{ -+ struct touchscreen_data *ts = ts_data; -+ -+ if(irq == ts->irq /* && !irqblock */) { -+ irqblock = 1; -+ -+ /* -+ * Disable the pen interrupt. It's reenabled when the user lifts the -+ * pen. -+ */ -+ disable_irq(ts->irq); -+ -+ if (ts->state == STATE_WAIT_FOR_TOUCH) { -+ ts->state = STATE_SAMPLING; -+ start_read(ts); -+ } else { -+ /* Shouldn't happen */ -+ printk(KERN_ERR "Unexpected ts interrupt\n"); -+ } -+ -+ } -+ return IRQ_HANDLED; -+} -+ -+static void -+ssp_init(int port, int clock) -+{ -+ -+ pxa_set_cken(clock, 0); -+ -+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_CLK_MD); -+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_FRM_MD); -+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DO_MD); -+ pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DI_MD); -+ -+ SET_HTCUNIVERSAL_GPIO(SPI_FRM,1); -+ -+ /* *** Set up the SPI Registers *** */ -+ SSCR0_P(port) = -+ SSCR0_EDSS /* Extended Data Size Select */ -+ | SSCR0_SerClkDiv(7) /* Serial Clock Rate */ -+ /* Synchronous Serial Enable (Disable for now) */ -+ | SSCR0_Motorola /* Motorola SPI Interface */ -+ | SSCR0_DataSize(8) /* Data Size Select (24-bit) */ -+ ; -+ SSCR1_P(port) = 0; -+ SSPSP_P(port) = 0; -+ -+ /* Clear the Status */ -+ SSSR_P(port) = SSSR_P(port) & 0x00fcfffc; -+ -+ /* Now enable it */ -+ SSCR0_P(port) = -+ SSCR0_EDSS /* Extended Data Size Select */ -+ | SSCR0_SerClkDiv(7) /* Serial Clock Rate */ -+ | SSCR0_SSE /* Synchronous Serial Enable */ -+ | SSCR0_Motorola /* Motorola SPI Interface */ -+ | SSCR0_DataSize(8) /* Data Size Select (24-bit) */ -+ ; -+ -+ pxa_set_cken(clock, 1); -+} -+ -+static void -+start_read(struct touchscreen_data *touch) -+{ -+ unsigned long inc = (poll_sample_time * HZ) / 1000; -+ int i; -+ -+ /* Write here to the serial port. We request X and Y only for now. -+ * Then we have to wait for poll_sample_time before we read out the serial -+ * port. Then, when we read it out, we check to see if the pen is still -+ * down. If so, then we issue another request here. -+ */ -+#define TS_SAMPLES 7 -+ -+ /* -+ * We do four samples for each, and throw out the highest and lowest, then -+ * average the other two. -+ */ -+ -+ for(i = 0; i < TS_SAMPLES; i++) { -+ while(!(SSSR_P(touch->port) & SSSR_TNF)) -+ ; -+ /* It's not full. Write the command for X */ -+ SSDR_P(touch->port) = (TSC2046_SAMPLE_X|(touch->pwrbit_X))<<16; -+ } -+ -+ for(i = 0; i < TS_SAMPLES; i++) { -+ while(!(SSSR_P(touch->port) & SSSR_TNF)) -+ ; -+ /* It's not full. Write the command for Y */ -+ SSDR_P(touch->port) = (TSC2046_SAMPLE_Y|(touch->pwrbit_Y))<<16; -+ } -+ -+ /* -+ * Enable the timer. We should get an interrupt, but we want keep a timer -+ * to ensure that we can detect missing data -+ */ -+ mod_timer(&touch->timer, jiffies + inc); -+} -+ -+static void -+ts_timer_callback(unsigned long data) -+{ -+ struct touchscreen_data *ts = (struct touchscreen_data *)data; -+ int x, a[TS_SAMPLES], y; -+ static int oldx, oldy; -+ int ssrval; -+ -+ /* -+ * Check here to see if there is anything in the SPI FIFO. If so, -+ * return it if there has been a change. If not, then we have a -+ * timeout. Generate an erro somehow. -+ */ -+ ssrval = SSSR_P(ts->port); -+ -+ if(ssrval & SSSR_RNE) { /* Look at Rx Not Empty bit */ -+ int number_of_entries_in_fifo; -+ -+ /* The FIFO is not emtpy. Good! Now make sure there are at least two -+ * entries. (Should be two exactly.) */ -+ -+ number_of_entries_in_fifo = ((ssrval >> 12) & 0xf) + 1; -+ -+ if(number_of_entries_in_fifo < TS_SAMPLES * 2) { -+ /* Not ready yet. Come back later. */ -+ unsigned long inc = (poll_sample_time * HZ) / 1000; -+ mod_timer(&ts->timer, jiffies + inc); -+ return; -+ } -+ -+ if(number_of_entries_in_fifo == TS_SAMPLES * 2) { -+ int i, j; -+ -+ for(i = 0; i < TS_SAMPLES; i++) { -+ a[i] = SSDR_P(ts->port); -+ } -+ /* Sort them (bubble) */ -+ for(j = TS_SAMPLES - 1; j > 0; j--) { -+ for(i = 0; i < j; i++) { -+ if(a[i] > a[i + 1]) { -+ int tmp; -+ tmp = a[i+1]; -+ a[i+1] = a[i]; -+ a[i] = tmp; -+ } -+ } -+ } -+ -+ /* Take the average of the middle two */ -+ /* x = (a[TS_SAMPLES/2 - 1] + a[TS_SAMPLES/2] + a[TS_SAMPLES/2+1] + a[TS_SAMPLES/2+2]) >> 2; */ -+ x = a[TS_SAMPLES/2]; -+ -+ for(i = 0; i < TS_SAMPLES; i++) { -+ a[i] = SSDR_P(ts->port); -+ } -+ /* Sort them (bubble) */ -+ for(j = TS_SAMPLES - 1; j > 0; j--) { -+ for(i = 0; i < j; i++) { -+ if(a[i] > a[i + 1]) { -+ int tmp; -+ tmp = a[i+1]; -+ a[i+1] = a[i]; -+ a[i] = tmp; -+ } -+ } -+ } -+ -+ -+ /* Take the average of the middle two */ -+ /* y = (a[TS_SAMPLES/2 - 1] + a[TS_SAMPLES/2] + a[TS_SAMPLES/2+1] + a[TS_SAMPLES/2+2]) >> 2; */ -+ y = a[TS_SAMPLES/2]; -+ } else { -+ /* We have an error! Too many entries. */ -+ printk(KERN_ERR "TS: Expected %d entries. Got %d\n", TS_SAMPLES*2, number_of_entries_in_fifo); -+ /* Try to clear the FIFO */ -+ while(number_of_entries_in_fifo--) { -+ (void)SSDR_P(ts->port); -+ } -+ -+ if (ts->pen_down()) -+ start_read(ts); -+ -+ return; -+ } -+ } else { -+ /* Not ready yet. Come back later. */ -+ unsigned long inc = (poll_sample_time * HZ) / 1000; -+ mod_timer(&ts->timer, jiffies + inc); -+ return; -+ } -+ -+ /* -+ * Now we check to see if the pen is still down. If it is, then call -+ * start_read(). -+ */ -+ if (ts->pen_down()) -+ { -+ /* Still down */ -+ if(oldx != x || oldy != y) { -+ oldx = x; -+ oldy = y; -+ report_touchpanel(ts, 1, x, y); -+ } -+ start_read(ts); -+ } else { -+ /* Up */ -+ report_touchpanel(ts, 0, 0, 0); -+ irqblock = 0; -+ ts->state = STATE_WAIT_FOR_TOUCH; -+ /* Re-enable pen down interrupt */ -+ enable_irq(ts->irq); -+ } -+} -+ -+static int pen_down(void) -+{ -+ return ( asic3_get_gpio_status_a( &htcuniversal_asic3.dev ) & (1<<GPIOA_TOUCHSCREEN_N)) == 0 ; -+} -+ -+static int -+ts_probe (struct platform_device *dev) -+{ -+ int retval; -+ struct touchscreen_data *ts; -+ struct tsc2046_mach_info *mach = dev->dev.platform_data; -+ -+ printk("htcuniversal: ts_probe\n"); -+ -+ ts = ts_data = kmalloc (sizeof (*ts), GFP_KERNEL); -+ if (ts == NULL) { -+ printk( KERN_NOTICE "htcuniversal_ts: unable to allocate memory\n" ); -+ return -ENOMEM; -+ } -+ memset (ts, 0, sizeof (*ts)); -+ -+ ts->input = input_allocate_device(); -+ if (ts->input == NULL) { -+ printk( KERN_NOTICE "htcuniversal_ts: unable to allocation touchscreen input\n" ); -+ kfree(ts); -+ return -ENOMEM; -+ } -+ ts->input->evbit[0] = BIT(EV_ABS); -+ ts->input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); -+ ts->input->absmin[ABS_X] = 0; -+ ts->input->absmax[ABS_X] = 32767; -+ ts->input->absmin[ABS_Y] = 0; -+ ts->input->absmax[ABS_Y] = 32767; -+ ts->input->absmin[ABS_PRESSURE] = 0; -+ ts->input->absmax[ABS_PRESSURE] = 1; -+ -+ ts->input->name = "htcuniversal_ts"; -+ ts->input->phys = "touchscreen/htcuniversal_ts"; -+ ts->input->private = ts; -+ -+ input_register_device(ts->input); -+ -+ ts->timer.function = ts_timer_callback; -+ ts->timer.data = (unsigned long)ts; -+ ts->state = STATE_WAIT_FOR_TOUCH; -+ init_timer (&ts->timer); -+ -+ platform_set_drvdata(dev, ts); -+ -+ ts->port=-1; -+ -+ if (mach) { -+ ts->port = mach->port; -+ ts->clock = mach->clock; -+ ts->pwrbit_X = mach->pwrbit_X; -+ ts->pwrbit_Y = mach->pwrbit_Y; -+ -+ /* static irq */ -+ if (mach->irq) -+ ts->irq = mach->irq; -+ -+ if (mach->pen_down) -+ ts->pen_down=mach->pen_down; -+ } -+ -+ if (ts->port == -1) -+ { -+ printk("tsc2046: your device is not supported by this driver\n"); -+ return -ENODEV; -+ } -+ -+ /* *** Initialize the SSP interface *** */ -+ ssp_init(ts->port, ts->clock); -+ -+ while(!(SSSR_P(ts->port) & SSSR_TNF)) -+ ; -+ SSDR_P(ts->port) = (TSC2046_SAMPLE_X|(ts->pwrbit_X))<<16; -+ -+ for(retval = 0; retval < 100; retval++) { -+ if(SSSR_P(ts->port) & SSSR_RNE) { -+ while(SSSR_P(ts->port) & SSSR_RNE) { -+ (void)SSDR_P(ts->port); -+ } -+ break; -+ } -+ mdelay(1); -+ } -+ -+ if (machine_is_htcuniversal() ) -+ { -+ ts->irq = asic3_irq_base( &htcuniversal_asic3.dev ) + ASIC3_GPIOA_IRQ_BASE + GPIOA_TOUCHSCREEN_N; -+ ts->pen_down=pen_down; -+ } -+ -+ retval = request_irq(ts->irq, pen_isr, IRQF_DISABLED, "tsc2046_ts", ts); -+ if(retval) { -+ printk("Unable to get interrupt\n"); -+ input_unregister_device (ts->input); -+ return -ENODEV; -+ } -+ set_irq_type(ts->irq, IRQ_TYPE_EDGE_FALLING); -+ -+ return 0; -+} -+ -+static int -+ts_remove (struct platform_device *dev) -+{ -+ struct touchscreen_data *ts = platform_get_drvdata(dev); -+ -+ input_unregister_device (ts->input); -+ del_timer_sync (&ts->timer); -+ free_irq (ts->irq, ts); -+ pxa_set_cken(ts->clock, 0); -+ -+ kfree(ts); -+ return 0; -+} -+ -+static int -+ts_suspend (struct platform_device *dev, pm_message_t state) -+{ -+ struct touchscreen_data *ts = platform_get_drvdata(dev); -+ -+ disable_irq(ts->irq); -+ -+ printk("htcuniversal_ts2_suspend: called.\n"); -+ return 0; -+} -+ -+static int -+ts_resume (struct platform_device *dev) -+{ -+ struct touchscreen_data *ts = platform_get_drvdata(dev); -+ -+ ts->state = STATE_WAIT_FOR_TOUCH; -+ ssp_init(ts->port, ts->clock); -+ enable_irq(ts->irq); -+ -+ printk("htcuniversal_ts2_resume: called.\n"); -+ return 0; -+} -+ -+static struct platform_driver ts_driver = { -+ .probe = ts_probe, -+ .remove = ts_remove, -+ .suspend = ts_suspend, -+ .resume = ts_resume, -+ .driver = { -+ .name = "htcuniversal_ts", -+ }, -+}; -+ -+ -+static int -+ts_module_init (void) -+{ -+ printk(KERN_NOTICE "HTC Universal Touch Screen Driver\n"); -+ -+ return platform_driver_register(&ts_driver); -+} -+ -+static void -+ts_module_cleanup (void) -+{ -+ platform_driver_unregister (&ts_driver); -+} -+ -+module_init(ts_module_init); -+module_exit(ts_module_cleanup); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC"); -+MODULE_DESCRIPTION("HTC Universal Touch Screen Driver"); -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,71 @@ -+ -+/* -+ * -+ * htcuniversal_udc.c: -+ * htcuniversal specific code for the pxa27x usb device controller. -+ * -+ * Use consistent with the GNU GPL is permitted. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/udc.h> -+#include <linux/soc/asic3_base.h> -+#include <asm/arch/htcuniversal-gpio.h> -+#include <asm/arch/htcuniversal-asic.h> -+ -+static void htcuniversal_udc_command(int cmd) -+{ -+ switch (cmd) { -+ case PXA2XX_UDC_CMD_DISCONNECT: -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, -+ 1<<GPIOB_USB_PUEN, 0); -+// SET_HTCUNIVERSAL_GPIO(USB_PUEN,0); -+ break; -+ case PXA2XX_UDC_CMD_CONNECT: -+ asic3_set_gpio_out_b(&htcuniversal_asic3.dev, -+ 1<<GPIOB_USB_PUEN, 1<<GPIOB_USB_PUEN); -+// SET_HTCUNIVERSAL_GPIO(USB_PUEN,1); -+ break; -+ default: -+ printk("_udc_control: unknown command!\n"); -+ break; -+ } -+} -+ -+static int htcuniversal_udc_is_connected(void) -+{ -+ return (GET_HTCUNIVERSAL_GPIO(USB_DET) != 0); -+} -+ -+static struct pxa2xx_udc_mach_info htcuniversal_udc_info __initdata = { -+ .udc_is_connected = htcuniversal_udc_is_connected, -+ .udc_command = htcuniversal_udc_command, -+}; -+ -+static int htcuniversal_udc_probe(struct platform_device * dev) -+{ -+ asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_USB_PUEN, 1<<GPIOB_USB_PUEN); -+ -+ pxa_set_udc_info(&htcuniversal_udc_info); -+ return 0; -+} -+ -+static struct platform_driver htcuniversal_udc_driver = { -+ .driver = { -+ .name = "htcuniversal_udc", -+ }, -+ .probe = htcuniversal_udc_probe, -+}; -+ -+static int __init htcuniversal_udc_init(void) -+{ -+ return platform_driver_register(&htcuniversal_udc_driver); -+} -+ -+module_init(htcuniversal_udc_init); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,20 @@ -+/* -+ * temporary TSC2046 touchscreen hack -+ */ -+ -+#ifndef _TSC2046_TS_H -+#define _TSC2046_TS_H -+ -+struct tsc2046_mach_info { -+ int port; -+ int clock; -+ int pwrbit_X; -+ int pwrbit_Y; -+ int irq; -+ int (*pen_down)(void); -+}; -+ -+#define TSC2046_SAMPLE_X 0xd0 -+#define TSC2046_SAMPLE_Y 0x90 -+ -+#endif -Index: linux-2.6.22/arch/arm/mach-pxa/Kconfig -=================================================================== ---- linux-2.6.22.orig/arch/arm/mach-pxa/Kconfig 2007-09-11 12:53:33.000000000 +0200 -+++ linux-2.6.22/arch/arm/mach-pxa/Kconfig 2007-09-11 12:53:37.000000000 +0200 -@@ -50,6 +50,14 @@ - help - This enables support for the HP iPAQ HX2750 handheld. - -+config MACH_HTCUNIVERSAL -+ bool "HTC Universal" -+ select PXA27x -+ help -+ Say Y here if you intend to run this kernel on a -+ HTC Universal. Currently there is only basic support -+ for this PDA. -+ - endchoice - - if PXA_SHARPSL -@@ -84,6 +92,86 @@ - - endif - -+if MACH_HTCUNIVERSAL -+ -+menu "HTC Universal support" -+ -+config HTCUNIVERSAL_CORE -+ tristate "HTC Universal core" -+ depends on MACH_HTCUNIVERSAL -+ help -+ This selection enables HTC Universal core support. -+ -+config HTCUNIVERSAL_UDC -+ bool "USB Device Controller support" -+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && USB_PXA27X -+ help -+ Enables HTC Universal specific USB detection -+ -+config HTCUNIVERSAL_POWER -+ tristate "HTC Universal power" -+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 -+ help -+ This selection enables HTC Universal power monitoring -+ hardware support (through ASIC3). -+ -+config HTCUNIVERSAL_BACKLIGHT -+ bool "HTC Universal Backlight" -+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && BACKLIGHT_CLASS_DEVICE -+ help -+ This driver provides support for changing power and brightness -+ on HTC Universal LCD backlight. -+ -+config HTCUNIVERSAL_LCD -+ tristate "HTC Universal LCD" -+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && LCD_CLASS_DEVICE -+ help -+ This driver provides support for changing power and brightness -+ on HTC Universal LCD display. -+ -+config HTCUNIVERSAL_TS2 -+ tristate "HTC Universal Touchscreen (old)" -+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 -+ help -+ Enable support for the HTC Universal Touchscreen Panel. -+ -+config HTCUNIVERSAL_BUTTONS -+ tristate "HTC Universal buttons support" -+ depends on MACH_HTCUNIVERSAL && HTC_ASIC3 -+ -+config HTCUNIVERSAL_BLUETOOTH -+ tristate "HTC Universal Bluetooth" -+ depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3 -+ help -+ Enables support for the TI BRF6150 Bluetooth Module -+ in the HTC Universal. -+ -+config HTCUNIVERSAL_ASIC3_LEDS -+ tristate "HTC Universal ASIC3 LED support" -+ select LEDS_ASIC3 -+ depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3 -+ ---help--- -+ Support for right (colors red+green+(amber)) and left (green+blue) led -+ Off/on hook keys LED backlight -+ Keyboard backlight -+ Vibra -+ Flashlight -+ -+config HTCUNIVERSAL_PHONE -+ tristate "HTC Universal Phone" -+ depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3 -+ help -+ Enables support for the Qualcomm MSM6520 Phone Module -+ in the HTC Universal. -+ -+config HTCUNIVERSAL_AK4641 -+ depends on SND && I2C -+ tristate "AK4641 chipset support" -+ -+endmenu -+ -+endif -+ - endmenu - - config MACH_POODLE -@@ -164,4 +252,3 @@ - depends on (PXA25x || PXA27x) && INPUT - - endif -- -Index: linux-2.6.22/arch/arm/mach-pxa/Makefile -=================================================================== ---- linux-2.6.22.orig/arch/arm/mach-pxa/Makefile 2007-09-11 12:53:33.000000000 +0200 -+++ linux-2.6.22/arch/arm/mach-pxa/Makefile 2007-09-11 12:53:37.000000000 +0200 -@@ -20,6 +20,7 @@ - obj-$(CONFIG_MACH_TOSA) += tosa.o - obj-$(CONFIG_MACH_EM_X270) += em-x270.o - obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o -+obj-$(CONFIG_MACH_HTCUNIVERSAL) += htcuniversal/ - - # Support for blinky lights - led-y := leds.o -Index: linux-2.6.22/drivers/leds/Kconfig -=================================================================== ---- linux-2.6.22.orig/drivers/leds/Kconfig 2007-09-11 12:53:14.000000000 +0200 -+++ linux-2.6.22/drivers/leds/Kconfig 2007-09-11 12:53:37.000000000 +0200 -@@ -101,6 +101,13 @@ - outputs. To be useful the particular board must have LEDs - and they must be connected to the GPIO lines. - -+config LEDS_ASIC3 -+ tristate "LED Support for the HTC ASIC3 chip" -+ depends LEDS_CLASS && HTC_ASIC3 -+ help -+ This option enables support for the LEDs connected to the -+ HTC ASIC3 chip. -+ - comment "LED Triggers" - - config LEDS_TRIGGERS -Index: linux-2.6.22/drivers/leds/leds-asic3.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/leds/leds-asic3.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,189 @@ -+/* -+ * LEDs support for HTC ASIC3 devices. -+ * -+ * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru> -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+#include <asm/hardware/ipaq-asic3.h> -+#include <linux/soc/asic3_base.h> -+#include <asm/mach-types.h> -+#include <asm/hardware/asic3_leds.h> -+ -+#ifdef DEBUG -+#define dbg(msg, ...) printk(msg, __VA_ARGS__) -+#else -+#define dbg(msg, ...) -+#endif -+ -+static -+void asic3_leds_set(struct led_classdev *led_cdev, enum led_brightness b) -+{ -+ struct asic3_led *led = container_of(led_cdev, struct asic3_led, -+ led_cdev); -+ struct asic3_leds_machinfo *machinfo = led->machinfo; -+ struct device *asic3_dev = &machinfo->asic3_pdev->dev; -+ -+ dbg("%s:%s %d(%d)-%s %d\n", __FILE__, __FUNCTION__, led->hw_num, -+ led->gpio_num, led->led_cdev.name, b); -+ -+ if (led->hw_num == -1) { -+ asic3_gpio_set_value(asic3_dev, led->gpio_num, b); -+ return; -+ } -+ -+ if (b == LED_OFF) { -+ asic3_set_led(asic3_dev, led->hw_num, 0, 16, 6); -+ asic3_set_gpio_out_c(asic3_dev, led->hw_num, 0); -+ } -+ else { -+ asic3_set_gpio_out_c(asic3_dev, led->hw_num, led->hw_num); -+ #ifdef CONFIG_LEDS_TRIGGER_HWTIMER -+ if (led_cdev->trigger && led_cdev->trigger->is_led_supported && -+ (led_cdev->trigger->is_led_supported(led_cdev) & -+ LED_SUPPORTS_HWTIMER)) { -+ struct hwtimer_data *td = led_cdev->trigger_data; -+ if (!td) return; -+ asic3_set_led(asic3_dev, led->hw_num, td->delay_on/8, -+ (td->delay_on + td->delay_off)/8, 6); -+ } -+ else -+ #endif -+ asic3_set_led(asic3_dev, led->hw_num, 16, 16, 6); -+ } -+ -+ return; -+} -+ -+static -+int asic3_leds_probe(struct platform_device *pdev) -+{ -+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data; -+ struct asic3_led *leds = machinfo->leds; -+ int ret, i = 0; -+ -+ dbg("%s:%s\n", __FILE__, __FUNCTION__); -+ -+ // Turn on clocks early, for the case if trigger would enable -+ // led immediately after led_classdev_register(). -+ asic3_set_clock_cdex(&machinfo->asic3_pdev->dev, -+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2, -+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2); -+ -+ for (i = 0; i < machinfo->num_leds; i++) { -+ leds[i].machinfo = machinfo; -+ leds[i].led_cdev.brightness_set = asic3_leds_set; -+ ret = led_classdev_register(&pdev->dev, &leds[i].led_cdev); -+ if (ret) { -+ printk(KERN_ERR "Error: can't register %s led\n", -+ leds[i].led_cdev.name); -+ goto out_err; -+ } -+ } -+ -+ return 0; -+ -+out_err: -+ while (--i >= 0) led_classdev_unregister(&leds[i].led_cdev); -+ -+ asic3_set_clock_cdex(&machinfo->asic3_pdev->dev, -+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2, -+ 0 | 0 | 0); -+ -+ return ret; -+} -+ -+static -+int asic3_leds_remove(struct platform_device *pdev) -+{ -+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data; -+ struct asic3_led *leds = machinfo->leds; -+ int i = 0; -+ -+ dbg("%s:%s\n", __FILE__, __FUNCTION__); -+ -+ for (i = 0; i < machinfo->num_leds; i++) -+ led_classdev_unregister(&leds[i].led_cdev); -+ -+ asic3_set_clock_cdex(&machinfo->asic3_pdev->dev, -+ CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2, -+ 0 | 0 | 0); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+ -+static -+int asic3_leds_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data; -+ struct asic3_led *leds = machinfo->leds; -+ int i = 0; -+ -+ dbg("%s:%s\n", __FILE__, __FUNCTION__); -+ -+ for (i = 0; i < machinfo->num_leds; i++) -+ led_classdev_suspend(&leds[i].led_cdev); -+ -+ return 0; -+} -+ -+static -+int asic3_leds_resume(struct platform_device *pdev) -+{ -+ struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data; -+ struct asic3_led *leds = machinfo->leds; -+ int i = 0; -+ -+ dbg("%s:%s\n", __FILE__, __FUNCTION__); -+ -+ for (i = 0; i < machinfo->num_leds; i++) -+ led_classdev_resume(&leds[i].led_cdev); -+ -+ return 0; -+} -+ -+#endif -+ -+static -+struct platform_driver asic3_leds_driver = { -+ .probe = asic3_leds_probe, -+ .remove = asic3_leds_remove, -+#ifdef CONFIG_PM -+ .suspend = asic3_leds_suspend, -+ .resume = asic3_leds_resume, -+#endif -+ .driver = { -+ .name = "asic3-leds", -+ }, -+}; -+ -+int asic3_leds_register(void) -+{ -+ dbg("%s:%s\n", __FILE__, __FUNCTION__); -+ return platform_driver_register(&asic3_leds_driver); -+} -+ -+void asic3_leds_unregister(void) -+{ -+ platform_driver_unregister(&asic3_leds_driver); -+ return; -+} -+ -+EXPORT_SYMBOL_GPL(asic3_leds_register); -+EXPORT_SYMBOL_GPL(asic3_leds_unregister); -+ -+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>"); -+MODULE_DESCRIPTION("HTC ASIC3 LEDs driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.22/drivers/mfd/Kconfig -=================================================================== ---- linux-2.6.22.orig/drivers/mfd/Kconfig 2007-09-11 12:53:30.000000000 +0200 -+++ linux-2.6.22/drivers/mfd/Kconfig 2007-09-11 12:53:37.000000000 +0200 -@@ -15,6 +15,16 @@ - interface. The device may be connected by PCI or local bus with - varying functions enabled. - -+config HTC_ASIC3 -+ tristate "HTC ASIC3 (iPAQ h1900/h3900/h4000/hx4700/rx3000) support" -+ -+config HTC_ASIC3_DS1WM -+ bool "Support HTC ASIC3 builtin DS1WM block" -+ help -+ Choose Y here if you want to include support for ASIC3's builtin -+ W1 controller. Some devices do not use it, and yet other have -+ separate DS1WM controller. For them, choose N. -+ - endmenu - - menu "Multimedia Capabilities Port drivers" -Index: linux-2.6.22/drivers/mfd/Makefile -=================================================================== ---- linux-2.6.22.orig/drivers/mfd/Makefile 2007-09-11 12:53:30.000000000 +0200 -+++ linux-2.6.22/drivers/mfd/Makefile 2007-09-11 12:53:37.000000000 +0200 -@@ -2,6 +2,8 @@ - # Makefile for multifunction miscellaneous devices - # - -+obj-$(CONFIG_HTC_ASIC3) += asic3_base.o soc-core.o -+ - obj-$(CONFIG_MFD_SM501) += sm501.o - - obj-$(CONFIG_MCP) += mcp-core.o -Index: linux-2.6.22/drivers/mfd/asic3_base.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/mfd/asic3_base.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,1208 @@ -+/* -+ * Driver interface to HTC "ASIC3" -+ * -+ * Copyright 2001 Compaq Computer Corporation. -+ * Copyright 2004-2005 Phil Blundell -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, -+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS -+ * FITNESS FOR ANY PARTICULAR PURPOSE. -+ * -+ * Author: Andrew Christian -+ * <Andrew.Christian@compaq.com> -+ * October 2001 -+ */ -+ -+#include <linux/module.h> -+#include <linux/version.h> -+#include <linux/platform_device.h> -+#include <linux/delay.h> -+#include <linux/init.h> -+#include <linux/irq.h> -+#include <linux/clk.h> -+#include <linux/ds1wm.h> -+#include <asm/arch/clock.h> -+ -+#include <asm/hardware.h> -+#include <asm/irq.h> -+#include <asm/io.h> -+ -+#include <asm/hardware/ipaq-asic3.h> -+#include <linux/soc/asic3_base.h> -+#include <linux/soc/tmio_mmc.h> -+#include "soc-core.h" -+ -+ -+struct asic3_data { -+ void *mapping; -+ unsigned int bus_shift; -+ int irq_base; -+ int irq_nr; -+ -+ u16 irq_bothedge[4]; -+ struct device *dev; -+ -+ struct platform_device *mmc_dev; -+}; -+ -+static DEFINE_SPINLOCK(asic3_gpio_lock); -+ -+static int asic3_remove(struct platform_device *dev); -+ -+static inline unsigned long asic3_address(struct device *dev, -+ unsigned int reg) -+{ -+ struct asic3_data *adata; -+ -+ adata = (struct asic3_data *)dev->driver_data; -+ -+ return (unsigned long)adata->mapping + (reg >> (2 - adata->bus_shift)); -+} -+ -+void asic3_write_register(struct device *dev, unsigned int reg, u32 value) -+{ -+ __raw_writew(value, asic3_address(dev, reg)); -+} -+EXPORT_SYMBOL(asic3_write_register); -+ -+u32 asic3_read_register(struct device *dev, unsigned int reg) -+{ -+ return __raw_readw(asic3_address(dev, reg)); -+} -+EXPORT_SYMBOL(asic3_read_register); -+ -+static inline void __asic3_write_register(struct asic3_data *asic, -+ unsigned int reg, u32 value) -+{ -+ __raw_writew(value, (unsigned long)asic->mapping -+ + (reg >> (2 - asic->bus_shift))); -+} -+ -+static inline u32 __asic3_read_register(struct asic3_data *asic, -+ unsigned int reg) -+{ -+ return __raw_readw((unsigned long)asic->mapping -+ + (reg >> (2 - asic->bus_shift))); -+} -+ -+#define ASIC3_GPIO_FN(get_fn_name, set_fn_name, REG) \ -+u32 get_fn_name(struct device *dev) \ -+{ \ -+ return asic3_read_register(dev, REG); \ -+} \ -+EXPORT_SYMBOL(get_fn_name); \ -+ \ -+void set_fn_name(struct device *dev, u32 bits, u32 val) \ -+{ \ -+ unsigned long flags; \ -+ \ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); \ -+ val |= (asic3_read_register(dev, REG) & ~bits); \ -+ asic3_write_register(dev, REG, val); \ -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); \ -+} \ -+EXPORT_SYMBOL(set_fn_name); -+ -+#define ASIC3_GPIO_REGISTER(ACTION, action, fn, FN) \ -+ ASIC3_GPIO_FN(asic3_get_gpio_ ## action ## _ ## fn , \ -+ asic3_set_gpio_ ## action ## _ ## fn , \ -+ _IPAQ_ASIC3_GPIO_ ## FN ## _Base \ -+ + _IPAQ_ASIC3_GPIO_ ## ACTION ) -+ -+#define ASIC3_GPIO_FUNCTIONS(fn, FN) \ -+ ASIC3_GPIO_REGISTER(Direction, dir, fn, FN) \ -+ ASIC3_GPIO_REGISTER(Out, out, fn, FN) \ -+ ASIC3_GPIO_REGISTER(SleepMask, sleepmask, fn, FN) \ -+ ASIC3_GPIO_REGISTER(SleepOut, sleepout, fn, FN) \ -+ ASIC3_GPIO_REGISTER(BattFaultOut, battfaultout, fn, FN) \ -+ ASIC3_GPIO_REGISTER(AltFunction, alt_fn, fn, FN) \ -+ ASIC3_GPIO_REGISTER(SleepConf, sleepconf, fn, FN) \ -+ ASIC3_GPIO_REGISTER(Status, status, fn, FN) -+ -+#if 0 -+ ASIC3_GPIO_REGISTER(Mask, mask, fn, FN) -+ ASIC3_GPIO_REGISTER(TriggerType, trigtype, fn, FN) -+ ASIC3_GPIO_REGISTER(EdgeTrigger, rising, fn, FN) -+ ASIC3_GPIO_REGISTER(LevelTrigger, triglevel, fn, FN) -+ ASIC3_GPIO_REGISTER(IntStatus, intstatus, fn, FN) -+#endif -+ -+ASIC3_GPIO_FUNCTIONS(a, A) -+ASIC3_GPIO_FUNCTIONS(b, B) -+ASIC3_GPIO_FUNCTIONS(c, C) -+ASIC3_GPIO_FUNCTIONS(d, D) -+ -+int asic3_gpio_get_value(struct device *dev, unsigned gpio) -+{ -+ u32 mask = ASIC3_GPIO_bit(gpio); -+ printk("%s(%d)\n", __FUNCTION__, gpio); -+ switch (gpio >> 4) { -+ case _IPAQ_ASIC3_GPIO_BANK_A: -+ return asic3_get_gpio_status_a(dev) & mask; -+ case _IPAQ_ASIC3_GPIO_BANK_B: -+ return asic3_get_gpio_status_b(dev) & mask; -+ case _IPAQ_ASIC3_GPIO_BANK_C: -+ return asic3_get_gpio_status_c(dev) & mask; -+ case _IPAQ_ASIC3_GPIO_BANK_D: -+ return asic3_get_gpio_status_d(dev) & mask; -+ } -+ -+ printk(KERN_ERR "%s: invalid GPIO value 0x%x", __FUNCTION__, gpio); -+ return 0; -+} -+EXPORT_SYMBOL(asic3_gpio_get_value); -+ -+void asic3_gpio_set_value(struct device *dev, unsigned gpio, int val) -+{ -+ u32 mask = ASIC3_GPIO_bit(gpio); -+ u32 bitval = 0; -+ if (val) bitval = mask; -+ printk("%s(%d, %d)\n", __FUNCTION__, gpio, val); -+ -+ switch (gpio >> 4) { -+ case _IPAQ_ASIC3_GPIO_BANK_A: -+ asic3_set_gpio_out_a(dev, mask, bitval); -+ return; -+ case _IPAQ_ASIC3_GPIO_BANK_B: -+ asic3_set_gpio_out_b(dev, mask, bitval); -+ return; -+ case _IPAQ_ASIC3_GPIO_BANK_C: -+ asic3_set_gpio_out_c(dev, mask, bitval); -+ return; -+ case _IPAQ_ASIC3_GPIO_BANK_D: -+ asic3_set_gpio_out_d(dev, mask, bitval); -+ return; -+ } -+ -+ printk(KERN_ERR "%s: invalid GPIO value 0x%x", __FUNCTION__, gpio); -+} -+EXPORT_SYMBOL(asic3_gpio_set_value); -+ -+int asic3_irq_base(struct device *dev) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ -+ return asic->irq_base; -+} -+EXPORT_SYMBOL(asic3_irq_base); -+ -+static int asic3_gpio_to_irq(struct device *dev, unsigned gpio) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ printk("%s(%d)\n", __FUNCTION__, gpio); -+ -+ return asic->irq_base + gpio; -+} -+ -+void asic3_set_led(struct device *dev, int led_num, int duty_time, -+ int cycle_time, int timebase) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ unsigned int led_base; -+ -+ /* it's a macro thing: see #define _IPAQ_ASIC_LED_0_Base for why you -+ * can't substitute led_num in the macros below... -+ */ -+ -+ switch (led_num) { -+ case 0: -+ led_base = _IPAQ_ASIC3_LED_0_Base; -+ break; -+ case 1: -+ led_base = _IPAQ_ASIC3_LED_1_Base; -+ break; -+ case 2: -+ led_base = _IPAQ_ASIC3_LED_2_Base; -+ break; -+ default: -+ printk(KERN_ERR "%s: invalid led number %d", __FUNCTION__, -+ led_num); -+ return; -+ } -+ -+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_TimeBase, -+ timebase | LED_EN); -+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_PeriodTime, -+ cycle_time); -+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_DutyTime, -+ 0); -+ udelay(20); /* asic voodoo - possibly need a whole duty cycle? */ -+ __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_DutyTime, -+ duty_time); -+} -+EXPORT_SYMBOL(asic3_set_led); -+ -+void asic3_set_clock_sel(struct device *dev, u32 bits, u32 val) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ unsigned long flags; -+ u32 v; -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL)); -+ v = (v & ~bits) | val; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), v); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+EXPORT_SYMBOL(asic3_set_clock_sel); -+ -+void asic3_set_clock_cdex(struct device *dev, u32 bits, u32 val) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ unsigned long flags; -+ u32 v; -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX)); -+ v = (v & ~bits) | val; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), v); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+EXPORT_SYMBOL(asic3_set_clock_cdex); -+ -+static void asic3_clock_cdex_enable(struct clk *clk) -+{ -+ struct asic3_data *asic = (struct asic3_data *)clk->parent->ctrlbit; -+ unsigned long flags, val; -+ -+ local_irq_save(flags); -+ -+ val = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX)); -+ val |= clk->ctrlbit; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), val); -+ -+ local_irq_restore(flags); -+} -+ -+static void asic3_clock_cdex_disable(struct clk *clk) -+{ -+ struct asic3_data *asic = (struct asic3_data *)clk->parent->ctrlbit; -+ unsigned long flags, val; -+ -+ local_irq_save(flags); -+ -+ val = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX)); -+ val &= ~clk->ctrlbit; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), val); -+ -+ local_irq_restore(flags); -+} -+ -+/* base clocks */ -+ -+static struct clk clk_g = { -+ .name = "gclk", -+ .rate = 0, -+ .parent = NULL, -+}; -+ -+/* clock definitions */ -+ -+static struct clk asic3_clocks[] = { -+ { -+ .name = "spi", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_SPI, -+ }, -+#ifdef CONFIG_HTC_ASIC3_DS1WM -+ { -+ .name = "ds1wm", -+ .id = -1, -+ .rate = 5000000, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_OWM, -+ }, -+#endif -+ { -+ .name = "pwm0", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_PWM0, -+ }, -+ { -+ .name = "pwm1", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_PWM1, -+ }, -+ { -+ .name = "led0", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_LED0, -+ }, -+ { -+ .name = "led1", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_LED1, -+ }, -+ { -+ .name = "led2", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_LED2, -+ }, -+ { -+ .name = "smbus", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_SMBUS, -+ }, -+ { -+ .name = "ex0", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_EX0, -+ }, -+ { -+ .name = "ex1", -+ .id = -1, -+ .parent = &clk_g, -+ .enable = asic3_clock_cdex_enable, -+ .disable = asic3_clock_cdex_disable, -+ .ctrlbit = CLOCK_CDEX_EX1, -+ }, -+}; -+ -+void asic3_set_extcf_select(struct device *dev, u32 bits, u32 val) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ unsigned long flags; -+ u32 v; -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Select)); -+ v = (v & ~bits) | val; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Select), v); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+EXPORT_SYMBOL(asic3_set_extcf_select); -+ -+void asic3_set_extcf_reset(struct device *dev, u32 bits, u32 val) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ unsigned long flags; -+ u32 v; -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Reset)); -+ v = (v & ~bits) | val; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Reset), v); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+EXPORT_SYMBOL(asic3_set_extcf_reset); -+ -+void asic3_set_sdhwctrl(struct device *dev, u32 bits, u32 val) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ unsigned long flags; -+ u32 v; -+ -+ spin_lock_irqsave (&asic3_gpio_lock, flags); -+ v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(SDHWCTRL, SDConf)); -+ v = (v & ~bits) | val; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(SDHWCTRL, SDConf), v); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+EXPORT_SYMBOL(asic3_set_sdhwctrl); -+ -+ -+#define MAX_ASIC_ISR_LOOPS 20 -+#define _IPAQ_ASIC3_GPIO_Base_INCR \ -+ (_IPAQ_ASIC3_GPIO_B_Base - _IPAQ_ASIC3_GPIO_A_Base) -+ -+static inline void asic3_irq_flip_edge(struct asic3_data *asic, -+ u32 base, int bit) -+{ -+ u16 edge = __asic3_read_register(asic, -+ base + _IPAQ_ASIC3_GPIO_EdgeTrigger); -+ edge ^= bit; -+ __asic3_write_register(asic, -+ base + _IPAQ_ASIC3_GPIO_EdgeTrigger, edge); -+} -+ -+static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) -+{ -+ int iter; -+ struct asic3_data *asic; -+ -+ /* Acknowledge the parrent (i.e. CPU's) IRQ */ -+ desc->chip->ack(irq); -+ -+ asic = desc->handler_data; -+ -+ /* printk( KERN_NOTICE "asic3_irq_demux: irq=%d\n", irq ); */ -+ for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) { -+ u32 status; -+ int bank; -+ -+ status = __asic3_read_register(asic, -+ IPAQ_ASIC3_OFFSET(INTR, PIntStat)); -+ /* Check all ten register bits */ -+ if ((status & 0x3ff) == 0) -+ break; -+ -+ /* Handle GPIO IRQs */ -+ for (bank = 0; bank < 4; bank++) { -+ if (status & (1 << bank)) { -+ unsigned long base, i, istat; -+ -+ base = _IPAQ_ASIC3_GPIO_A_Base -+ + bank * _IPAQ_ASIC3_GPIO_Base_INCR; -+ istat = __asic3_read_register(asic, -+ base + _IPAQ_ASIC3_GPIO_IntStatus); -+ /* IntStatus is write 0 to clear */ -+ /* XXX could miss interrupts! */ -+ __asic3_write_register(asic, -+ base + _IPAQ_ASIC3_GPIO_IntStatus, 0); -+ -+ for (i = 0; i < 16; i++) { -+ int bit = (1 << i); -+ unsigned int irqnr; -+ if (!(istat & bit)) -+ continue; -+ -+ irqnr = asic->irq_base -+ + (16 * bank) + i; -+ desc = irq_desc + irqnr; -+ desc->handle_irq(irqnr, desc); -+ if (asic->irq_bothedge[bank] & bit) { -+ asic3_irq_flip_edge(asic, base, -+ bit); -+ } -+ } -+ } -+ } -+ -+ /* Handle remaining IRQs in the status register */ -+ { -+ int i; -+ -+ for (i = ASIC3_LED0_IRQ; i <= ASIC3_OWM_IRQ; i++) { -+ /* They start at bit 4 and go up */ -+ if (status & (1 << (i - ASIC3_LED0_IRQ + 4))) { -+ desc = irq_desc + asic->irq_base + i; -+ desc->handle_irq(asic->irq_base + i, -+ desc); -+ } -+ } -+ } -+ -+ } -+ -+ if (iter >= MAX_ASIC_ISR_LOOPS) -+ printk(KERN_ERR "%s: interrupt processing overrun\n", -+ __FUNCTION__); -+} -+ -+static inline int asic3_irq_to_bank(struct asic3_data *asic, int irq) -+{ -+ int n; -+ -+ n = (irq - asic->irq_base) >> 4; -+ -+ return (n * (_IPAQ_ASIC3_GPIO_B_Base - _IPAQ_ASIC3_GPIO_A_Base)); -+} -+ -+static inline int asic3_irq_to_index(struct asic3_data *asic, int irq) -+{ -+ return (irq - asic->irq_base) & 15; -+} -+ -+static void asic3_mask_gpio_irq(unsigned int irq) -+{ -+ struct asic3_data *asic = get_irq_chip_data(irq); -+ u32 val, bank, index; -+ unsigned long flags; -+ -+ bank = asic3_irq_to_bank(asic, irq); -+ index = asic3_irq_to_index(asic, irq); -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ val = __asic3_read_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask); -+ val |= 1 << index; -+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask, val); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+ -+static void asic3_mask_irq(unsigned int irq) -+{ -+ struct asic3_data *asic = get_irq_chip_data(irq); -+ int regval; -+ -+ if (irq < ASIC3_NR_GPIO_IRQS) { -+ printk(KERN_ERR "asic3_base: gpio mask attempt, irq %d\n", -+ irq); -+ return; -+ } -+ -+ regval = __asic3_read_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask); -+ -+ switch (irq - asic->irq_base) { -+ case ASIC3_LED0_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval & ~ASIC3_INTMASK_MASK0); -+ break; -+ case ASIC3_LED1_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval & ~ASIC3_INTMASK_MASK1); -+ break; -+ case ASIC3_LED2_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval & ~ASIC3_INTMASK_MASK2); -+ break; -+ case ASIC3_SPI_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval & ~ASIC3_INTMASK_MASK3); -+ break; -+ case ASIC3_SMBUS_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval & ~ASIC3_INTMASK_MASK4); -+ break; -+ case ASIC3_OWM_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval & ~ASIC3_INTMASK_MASK5); -+ break; -+ default: -+ printk(KERN_ERR "asic3_base: bad non-gpio irq %d\n", irq); -+ break; -+ } -+} -+ -+static void asic3_unmask_gpio_irq(unsigned int irq) -+{ -+ struct asic3_data *asic = get_irq_chip_data(irq); -+ u32 val, bank, index; -+ unsigned long flags; -+ -+ bank = asic3_irq_to_bank(asic, irq); -+ index = asic3_irq_to_index(asic, irq); -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ val = __asic3_read_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask); -+ val &= ~(1 << index); -+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask, val); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+} -+ -+static void asic3_unmask_irq(unsigned int irq) -+{ -+ struct asic3_data *asic = get_irq_chip_data(irq); -+ int regval; -+ -+ if (irq < ASIC3_NR_GPIO_IRQS) { -+ printk(KERN_ERR "asic3_base: gpio unmask attempt, irq %d\n", -+ irq); -+ return; -+ } -+ -+ regval = __asic3_read_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask); -+ -+ switch (irq - asic->irq_base) { -+ case ASIC3_LED0_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval | ASIC3_INTMASK_MASK0); -+ break; -+ case ASIC3_LED1_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval | ASIC3_INTMASK_MASK1); -+ break; -+ case ASIC3_LED2_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval | ASIC3_INTMASK_MASK2); -+ break; -+ case ASIC3_SPI_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval | ASIC3_INTMASK_MASK3); -+ break; -+ case ASIC3_SMBUS_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval | ASIC3_INTMASK_MASK4); -+ break; -+ case ASIC3_OWM_IRQ: -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, -+ regval | ASIC3_INTMASK_MASK5); -+ break; -+ default: -+ printk(KERN_ERR "asic3_base: bad non-gpio irq %d\n", irq); -+ break; -+ } -+} -+ -+static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) -+{ -+ struct asic3_data *asic = get_irq_chip_data(irq); -+ u32 bank, index; -+ unsigned long flags; -+ u16 trigger, level, edge, bit; -+ -+ bank = asic3_irq_to_bank(asic, irq); -+ index = asic3_irq_to_index(asic, irq); -+ bit = 1<<index; -+ -+ spin_lock_irqsave(&asic3_gpio_lock, flags); -+ level = __asic3_read_register(asic, -+ bank + _IPAQ_ASIC3_GPIO_LevelTrigger); -+ edge = __asic3_read_register(asic, -+ bank + _IPAQ_ASIC3_GPIO_EdgeTrigger); -+ trigger = __asic3_read_register(asic, -+ bank + _IPAQ_ASIC3_GPIO_TriggerType); -+ asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; -+ -+ if (type == IRQT_RISING) { -+ trigger |= bit; -+ edge |= bit; -+ } else if (type == IRQT_FALLING) { -+ trigger |= bit; -+ edge &= ~bit; -+ } else if (type == IRQT_BOTHEDGE) { -+ trigger |= bit; -+ if (asic3_gpio_get_value(asic->dev, irq - asic->irq_base)) -+ edge &= ~bit; -+ else -+ edge |= bit; -+ asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit; -+ } else if (type == IRQT_LOW) { -+ trigger &= ~bit; -+ level &= ~bit; -+ } else if (type == IRQT_HIGH) { -+ trigger &= ~bit; -+ level |= bit; -+ } else { -+ /* -+ * if type == IRQT_NOEDGE, we should mask interrupts, but -+ * be careful to not unmask them if mask was also called. -+ * Probably need internal state for mask. -+ */ -+ printk(KERN_NOTICE "asic3: irq type not changed.\n"); -+ } -+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_LevelTrigger, -+ level); -+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_EdgeTrigger, -+ edge); -+ __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_TriggerType, -+ trigger); -+ spin_unlock_irqrestore(&asic3_gpio_lock, flags); -+ return 0; -+} -+ -+static struct irq_chip asic3_gpio_irq_chip = { -+ .name = "ASIC3-GPIO", -+ .ack = asic3_mask_gpio_irq, -+ .mask = asic3_mask_gpio_irq, -+ .unmask = asic3_unmask_gpio_irq, -+ .set_type = asic3_gpio_irq_type, -+}; -+ -+static struct irq_chip asic3_irq_chip = { -+ .name = "ASIC3", -+ .ack = asic3_mask_irq, -+ .mask = asic3_mask_irq, -+ .unmask = asic3_unmask_irq, -+}; -+ -+static void asic3_release(struct device *dev) -+{ -+ struct platform_device *sdev = to_platform_device(dev); -+ -+ kfree(sdev->resource); -+ kfree(sdev); -+} -+ -+int asic3_register_mmc(struct device *dev) -+{ -+ struct platform_device *sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); -+ struct tmio_mmc_hwconfig *mmc_config = kmalloc(sizeof(*mmc_config), -+ GFP_KERNEL); -+ struct platform_device *pdev = to_platform_device(dev); -+ struct asic3_data *asic = dev->driver_data; -+ struct asic3_platform_data *asic3_pdata = dev->platform_data; -+ struct resource *res; -+ int rc; -+ -+ if (sdev == NULL || mmc_config == NULL) -+ return -ENOMEM; -+ -+ if (asic3_pdata->tmio_mmc_hwconfig) { -+ memcpy(mmc_config, asic3_pdata->tmio_mmc_hwconfig, -+ sizeof(*mmc_config)); -+ } else { -+ memset(mmc_config, 0, sizeof(*mmc_config)); -+ } -+ mmc_config->address_shift = asic->bus_shift; -+ -+ sdev->id = -1; -+ sdev->name = "asic3_mmc"; -+ sdev->dev.parent = dev; -+ sdev->num_resources = 2; -+ sdev->dev.platform_data = mmc_config; -+ sdev->dev.release = asic3_release; -+ -+ res = kzalloc(sdev->num_resources * sizeof(struct resource), -+ GFP_KERNEL); -+ if (res == NULL) { -+ kfree(sdev); -+ kfree(mmc_config); -+ return -ENOMEM; -+ } -+ sdev->resource = res; -+ -+ res[0].start = pdev->resource[2].start; -+ res[0].end = pdev->resource[2].end; -+ res[0].flags = IORESOURCE_MEM; -+ res[1].start = res[1].end = pdev->resource[3].start; -+ res[1].flags = IORESOURCE_IRQ; -+ -+ rc = platform_device_register(sdev); -+ if (rc) { -+ printk(KERN_ERR "asic3_base: " -+ "Could not register asic3_mmc device\n"); -+ kfree(res); -+ kfree(sdev); -+ return rc; -+ } -+ -+ asic->mmc_dev = sdev; -+ -+ return 0; -+} -+EXPORT_SYMBOL(asic3_register_mmc); -+ -+int asic3_unregister_mmc(struct device *dev) -+{ -+ struct asic3_data *asic = dev->driver_data; -+ platform_device_unregister(asic->mmc_dev); -+ asic->mmc_dev = 0; -+ -+ return 0; -+} -+EXPORT_SYMBOL(asic3_unregister_mmc); -+ -+#ifdef CONFIG_HTC_ASIC3_DS1WM -+/* -+ * DS1WM subdevice -+ */ -+ -+static void asic3_ds1wm_enable(struct platform_device *ds1wm_dev) -+{ -+ struct device *dev = ds1wm_dev->dev.parent; -+ -+ /* Turn on external clocks and the OWM clock */ -+ asic3_set_clock_cdex(dev, -+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM, -+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM); -+ -+ mdelay(1); -+ -+ asic3_set_extcf_reset(dev, ASIC3_EXTCF_OWM_RESET, -+ ASIC3_EXTCF_OWM_RESET); -+ mdelay(1); -+ asic3_set_extcf_reset(dev, ASIC3_EXTCF_OWM_RESET, 0); -+ mdelay(1); -+ -+ /* Clear OWM_SMB, set OWM_EN */ -+ asic3_set_extcf_select(dev, -+ ASIC3_EXTCF_OWM_SMB | ASIC3_EXTCF_OWM_EN, -+ 0 | ASIC3_EXTCF_OWM_EN); -+ -+ mdelay(1); -+} -+ -+static void asic3_ds1wm_disable(struct platform_device *ds1wm_dev) -+{ -+ struct device *dev = ds1wm_dev->dev.parent; -+ -+ asic3_set_extcf_select(dev, -+ ASIC3_EXTCF_OWM_SMB | ASIC3_EXTCF_OWM_EN, -+ 0 | 0); -+ -+ asic3_set_clock_cdex(dev, -+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM, -+ CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | 0); -+} -+ -+ -+static struct resource asic3_ds1wm_resources[] = { -+ { -+ .start = _IPAQ_ASIC3_OWM_Base, -+ .end = _IPAQ_ASIC3_OWM_Base + 0x14 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = ASIC3_OWM_IRQ, -+ .end = ASIC3_OWM_IRQ, -+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | -+ IORESOURCE_IRQ_SOC_SUBDEVICE, -+ }, -+}; -+ -+static struct ds1wm_platform_data ds1wm_pd = { -+ .enable = asic3_ds1wm_enable, -+ .disable = asic3_ds1wm_disable, -+}; -+#endif -+ -+static struct soc_device_data asic3_blocks[] = { -+#ifdef CONFIG_HTC_ASIC3_DS1WM -+ { -+ .name = "ds1wm", -+ .res = asic3_ds1wm_resources, -+ .num_resources = ARRAY_SIZE(asic3_ds1wm_resources), -+ .hwconfig = &ds1wm_pd, -+ }, -+#endif -+}; -+ -+static int asic3_probe(struct platform_device *pdev) -+{ -+ struct asic3_platform_data *pdata = pdev->dev.platform_data; -+ struct asic3_data *asic; -+ struct device *dev = &pdev->dev; -+ unsigned long clksel; -+ int i, rc; -+ -+ asic = kzalloc(sizeof(struct asic3_data), GFP_KERNEL); -+ if (!asic) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, asic); -+ asic->dev = &pdev->dev; -+ -+ asic->mapping = ioremap(pdev->resource[0].start, IPAQ_ASIC3_MAP_SIZE); -+ if (!asic->mapping) { -+ printk(KERN_ERR "asic3: couldn't ioremap ASIC3\n"); -+ kfree (asic); -+ return -ENOMEM; -+ } -+ -+ if (pdata && pdata->bus_shift) -+ asic->bus_shift = pdata->bus_shift; -+ else -+ asic->bus_shift = 2; -+ -+ /* XXX: should get correct SD clock values from pdata struct */ -+ clksel = 0; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), clksel); -+ -+ /* Register ASIC3's clocks. */ -+ clk_g.ctrlbit = (int)asic; -+ -+ if (clk_register(&clk_g) < 0) -+ printk(KERN_ERR "asic3: failed to register ASIC3 gclk\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++) { -+ rc = clk_register(&asic3_clocks[i]); -+ if (rc < 0) -+ printk(KERN_ERR "asic3: " -+ "failed to register clock %s (%d)\n", -+ asic3_clocks[i].name, rc); -+ } -+ -+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(A, Mask), 0xffff); -+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(B, Mask), 0xffff); -+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(C, Mask), 0xffff); -+ __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(D, Mask), 0xffff); -+ -+ asic3_set_gpio_sleepmask_a(dev, 0xffff, 0xffff); -+ asic3_set_gpio_sleepmask_b(dev, 0xffff, 0xffff); -+ asic3_set_gpio_sleepmask_c(dev, 0xffff, 0xffff); -+ asic3_set_gpio_sleepmask_d(dev, 0xffff, 0xffff); -+ -+ if (pdata) { -+ asic3_set_gpio_out_a(dev, 0xffff, pdata->gpio_a.init); -+ asic3_set_gpio_out_b(dev, 0xffff, pdata->gpio_b.init); -+ asic3_set_gpio_out_c(dev, 0xffff, pdata->gpio_c.init); -+ asic3_set_gpio_out_d(dev, 0xffff, pdata->gpio_d.init); -+ -+ asic3_set_gpio_dir_a(dev, 0xffff, pdata->gpio_a.dir); -+ asic3_set_gpio_dir_b(dev, 0xffff, pdata->gpio_b.dir); -+ asic3_set_gpio_dir_c(dev, 0xffff, pdata->gpio_c.dir); -+ asic3_set_gpio_dir_d(dev, 0xffff, pdata->gpio_d.dir); -+ -+ asic3_set_gpio_sleepmask_a(dev, 0xffff, -+ pdata->gpio_a.sleep_mask); -+ asic3_set_gpio_sleepmask_b(dev, 0xffff, -+ pdata->gpio_b.sleep_mask); -+ asic3_set_gpio_sleepmask_c(dev, 0xffff, -+ pdata->gpio_c.sleep_mask); -+ asic3_set_gpio_sleepmask_d(dev, 0xffff, -+ pdata->gpio_d.sleep_mask); -+ -+ asic3_set_gpio_sleepout_a(dev, 0xffff, -+ pdata->gpio_a.sleep_out); -+ asic3_set_gpio_sleepout_b(dev, 0xffff, -+ pdata->gpio_b.sleep_out); -+ asic3_set_gpio_sleepout_c(dev, 0xffff, -+ pdata->gpio_c.sleep_out); -+ asic3_set_gpio_sleepout_d(dev, 0xffff, -+ pdata->gpio_d.sleep_out); -+ -+ asic3_set_gpio_battfaultout_a(dev, 0xffff, -+ pdata->gpio_a.batt_fault_out); -+ asic3_set_gpio_battfaultout_b(dev, 0xffff, -+ pdata->gpio_b.batt_fault_out); -+ asic3_set_gpio_battfaultout_c(dev, 0xffff, -+ pdata->gpio_c.batt_fault_out); -+ asic3_set_gpio_battfaultout_d(dev, 0xffff, -+ pdata->gpio_d.batt_fault_out); -+ -+ asic3_set_gpio_sleepconf_a(dev, 0xffff, -+ pdata->gpio_a.sleep_conf); -+ asic3_set_gpio_sleepconf_b(dev, 0xffff, -+ pdata->gpio_b.sleep_conf); -+ asic3_set_gpio_sleepconf_c(dev, 0xffff, -+ pdata->gpio_c.sleep_conf); -+ asic3_set_gpio_sleepconf_d(dev, 0xffff, -+ pdata->gpio_d.sleep_conf); -+ -+ asic3_set_gpio_alt_fn_a(dev, 0xffff, -+ pdata->gpio_a.alt_function); -+ asic3_set_gpio_alt_fn_b(dev, 0xffff, -+ pdata->gpio_b.alt_function); -+ asic3_set_gpio_alt_fn_c(dev, 0xffff, -+ pdata->gpio_c.alt_function); -+ asic3_set_gpio_alt_fn_d(dev, 0xffff, -+ pdata->gpio_d.alt_function); -+ } -+ -+ asic->irq_nr = -1; -+ asic->irq_base = -1; -+ -+ if (pdev->num_resources > 1) -+ asic->irq_nr = pdev->resource[1].start; -+ -+ if (asic->irq_nr != -1) { -+ unsigned int i; -+ -+ if (!pdata->irq_base) { -+ printk(KERN_ERR "asic3: IRQ base not specified\n"); -+ asic3_remove(pdev); -+ return -EINVAL; -+ } -+ -+ asic->irq_base = pdata->irq_base; -+ -+ /* turn on clock to IRQ controller */ -+ clksel |= CLOCK_SEL_CX; -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), -+ clksel); -+ -+ printk(KERN_INFO "asic3: using irq %d-%d on irq %d\n", -+ asic->irq_base, asic->irq_base + ASIC3_NR_IRQS - 1, -+ asic->irq_nr); -+ -+ for (i = 0 ; i < ASIC3_NR_IRQS ; i++) { -+ int irq = i + asic->irq_base; -+ if (i < ASIC3_NR_GPIO_IRQS) { -+ set_irq_chip(irq, &asic3_gpio_irq_chip); -+ set_irq_chip_data(irq, asic); -+ set_irq_handler(irq, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); -+ } else { -+ /* The remaining IRQs are not GPIO */ -+ set_irq_chip(irq, &asic3_irq_chip); -+ set_irq_chip_data(irq, asic); -+ set_irq_handler(irq, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); -+ } -+ } -+ -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask), -+ ASIC3_INTMASK_GINTMASK); -+ -+ set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); -+ set_irq_type(asic->irq_nr, IRQT_RISING); -+ set_irq_data(asic->irq_nr, asic); -+ } -+ -+#ifdef CONFIG_HTC_ASIC3_DS1WM -+ ds1wm_pd.bus_shift = asic->bus_shift; -+#endif -+ -+ pdata->gpiodev_ops.get = asic3_gpio_get_value; -+ pdata->gpiodev_ops.set = asic3_gpio_set_value; -+ pdata->gpiodev_ops.to_irq = asic3_gpio_to_irq; -+ -+ soc_add_devices(pdev, asic3_blocks, ARRAY_SIZE(asic3_blocks), -+ &pdev->resource[0], -+ asic->bus_shift - ASIC3_DEFAULT_ADDR_SHIFT, -+ asic->irq_base); -+ -+ if (pdev->num_resources > 2) { -+ int rc; -+ rc = asic3_register_mmc(dev); -+ if (rc) { -+ asic3_remove(pdev); -+ return rc; -+ } -+ } -+ -+ if (pdata && pdata->num_child_platform_devs != 0) -+ platform_add_devices(pdata->child_platform_devs, -+ pdata->num_child_platform_devs); -+ -+ return 0; -+} -+ -+static int asic3_remove(struct platform_device *pdev) -+{ -+ struct asic3_platform_data *pdata = pdev->dev.platform_data; -+ struct asic3_data *asic = platform_get_drvdata(pdev); -+ int i; -+ -+ if (pdata && pdata->num_child_platform_devs != 0) { -+ for (i = 0; i < pdata->num_child_platform_devs; i++) { -+ platform_device_unregister( -+ pdata->child_platform_devs[i]); -+ } -+ } -+ -+ if (asic->irq_nr != -1) { -+ unsigned int i; -+ -+ for (i = 0 ; i < ASIC3_NR_IRQS ; i++) { -+ int irq = i + asic->irq_base; -+ set_irq_flags(irq, 0); -+ set_irq_handler (irq, NULL); -+ set_irq_chip (irq, NULL); -+ set_irq_chip_data(irq, NULL); -+ } -+ -+ set_irq_chained_handler(asic->irq_nr, NULL); -+ } -+ -+ if (asic->mmc_dev) -+ asic3_unregister_mmc(&pdev->dev); -+ -+ for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++) -+ clk_unregister(&asic3_clocks[i]); -+ clk_unregister(&clk_g); -+ -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), 0); -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask), 0); -+ -+ iounmap(asic->mapping); -+ -+ kfree(asic); -+ -+ return 0; -+} -+ -+static void asic3_shutdown(struct platform_device *pdev) -+{ -+} -+ -+#define ASIC3_SUSPEND_CDEX_MASK \ -+ (CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2) -+static unsigned short suspend_cdex; -+ -+static int asic3_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct asic3_data *asic = platform_get_drvdata(pdev); -+ suspend_cdex = __asic3_read_register(asic, -+ _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX); -+ /* The LEDs are still active during suspend */ -+ __asic3_write_register(asic, -+ _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX, -+ suspend_cdex & ASIC3_SUSPEND_CDEX_MASK); -+ return 0; -+} -+ -+static int asic3_resume(struct platform_device *pdev) -+{ -+ struct asic3_data *asic = platform_get_drvdata(pdev); -+ unsigned short intmask; -+ -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), -+ suspend_cdex); -+ -+ if (asic->irq_nr != -1) { -+ /* Toggle the interrupt mask to try to get ASIC3 to show -+ * the CPU an interrupt edge. For more details see the -+ * kernel-discuss thread around 13 June 2005 with the -+ * subject "asic3 suspend / resume". */ -+ intmask = __asic3_read_register(asic, -+ IPAQ_ASIC3_OFFSET(INTR, IntMask)); -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask), -+ intmask & ~ASIC3_INTMASK_GINTMASK); -+ mdelay(1); -+ __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask), -+ intmask | ASIC3_INTMASK_GINTMASK); -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver asic3_device_driver = { -+ .driver = { -+ .name = "asic3", -+ }, -+ .probe = asic3_probe, -+ .remove = asic3_remove, -+ .suspend = asic3_suspend, -+ .resume = asic3_resume, -+ .shutdown = asic3_shutdown, -+}; -+ -+static int __init asic3_base_init(void) -+{ -+ int retval = 0; -+ retval = platform_driver_register(&asic3_device_driver); -+ return retval; -+} -+ -+static void __exit asic3_base_exit(void) -+{ -+ platform_driver_unregister(&asic3_device_driver); -+} -+ -+#ifdef MODULE -+module_init(asic3_base_init); -+#else /* start early for dependencies */ -+subsys_initcall(asic3_base_init); -+#endif -+module_exit(asic3_base_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); -+MODULE_DESCRIPTION("Core driver for HTC ASIC3"); -+MODULE_SUPPORTED_DEVICE("asic3"); -Index: linux-2.6.22/drivers/mfd/soc-core.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/mfd/soc-core.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,106 @@ -+/* -+ * drivers/soc/soc-core.c -+ * -+ * core SoC support -+ * Copyright (c) 2006 Ian Molton -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This file contains functionality used by many SoC type devices. -+ * -+ * Created: 2006-11-28 -+ * -+ */ -+ -+#include <linux/ioport.h> -+#include <linux/slab.h> -+#include <linux/kernel.h> -+#include <linux/platform_device.h> -+#include "soc-core.h" -+ -+void soc_free_devices(struct platform_device *devices, int nr_devs) -+{ -+ struct platform_device *dev = devices; -+ int i; -+ -+ for (i = 0; i < nr_devs; i++) { -+ struct resource *res = dev->resource; -+ platform_device_unregister(dev++); -+ kfree(res); -+ } -+ kfree(devices); -+} -+EXPORT_SYMBOL_GPL(soc_free_devices); -+ -+#define SIGNED_SHIFT(val, shift) ((shift) >= 0 ? ((val) << (shift)) : ((val) >> -(shift))) -+ -+struct platform_device *soc_add_devices(struct platform_device *dev, -+ struct soc_device_data *soc, int nr_devs, -+ struct resource *mem, -+ int relative_addr_shift, int irq_base) -+{ -+ struct platform_device *devices; -+ int i, r, base; -+ -+ devices = kzalloc(nr_devs * sizeof(struct platform_device), GFP_KERNEL); -+ if (!devices) -+ return NULL; -+ -+ for (i = 0; i < nr_devs; i++) { -+ struct platform_device *sdev = &devices[i]; -+ struct soc_device_data *blk = &soc[i]; -+ struct resource *res; -+ -+ sdev->id = -1; -+ sdev->name = blk->name; -+ -+ sdev->dev.parent = &dev->dev; -+ sdev->dev.platform_data = (void *)blk->hwconfig; -+ sdev->num_resources = blk->num_resources; -+ -+ /* Allocate space for the subdevice resources */ -+ res = kzalloc (blk->num_resources * sizeof (struct resource), GFP_KERNEL); -+ if (!res) -+ goto fail; -+ -+ for (r = 0 ; r < blk->num_resources ; r++) { -+ res[r].name = blk->res[r].name; // Fixme - should copy -+ -+ /* Find out base to use */ -+ base = 0; -+ if (blk->res[r].flags & IORESOURCE_MEM) { -+ base = mem->start; -+ } else if ((blk->res[r].flags & IORESOURCE_IRQ) && -+ (blk->res[r].flags & IORESOURCE_IRQ_SOC_SUBDEVICE)) { -+ base = irq_base; -+ } -+ -+ /* Adjust resource */ -+ if (blk->res[r].flags & IORESOURCE_MEM) { -+ res[r].parent = mem; -+ res[r].start = base + SIGNED_SHIFT(blk->res[r].start, relative_addr_shift); -+ res[r].end = base + SIGNED_SHIFT(blk->res[r].end, relative_addr_shift); -+ } else { -+ res[r].start = base + blk->res[r].start; -+ res[r].end = base + blk->res[r].end; -+ } -+ res[r].flags = blk->res[r].flags; -+ } -+ -+ sdev->resource = res; -+ if (platform_device_register(sdev)) { -+ kfree(res); -+ goto fail; -+ } -+ -+ printk(KERN_INFO "SoC: registering %s\n", blk->name); -+ } -+ return devices; -+ -+fail: -+ soc_free_devices(devices, i + 1); -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(soc_add_devices); -Index: linux-2.6.22/drivers/mfd/soc-core.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/mfd/soc-core.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,30 @@ -+/* -+ * drivers/soc/soc-core.h -+ * -+ * core SoC support -+ * Copyright (c) 2006 Ian Molton -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This file contains prototypes for the functions in soc-core.c -+ * -+ * Created: 2006-11-28 -+ * -+ */ -+ -+struct soc_device_data { -+ char *name; -+ struct resource *res; -+ int num_resources; -+ void *hwconfig; /* platform_data to pass to the subdevice */ -+}; -+ -+struct platform_device *soc_add_devices(struct platform_device *dev, -+ struct soc_device_data *soc, int n_devs, -+ struct resource *mem, -+ int relative_addr_shift, int irq_base); -+ -+void soc_free_devices(struct platform_device *devices, int nr_devs); -+ -Index: linux-2.6.22/include/asm-arm/arch-pxa/clock.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/clock.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,27 @@ -+/* -+ * linux/include/asm-arm/arch-pxa/clock.h -+ * -+ * Copyright (C) 2006 Erik Hovland -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+struct clk { -+ struct list_head node; -+ struct module *owner; -+ struct clk *parent; -+ const char *name; -+ int id; -+ unsigned int enabled; -+ unsigned long rate; -+ unsigned long ctrlbit; -+ -+ void (*enable)(struct clk *); -+ void (*disable)(struct clk *); -+}; -+ -+ -+extern int clk_register(struct clk *clk); -+extern void clk_unregister(struct clk *clk); -Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,213 @@ -+/* -+ * include/asm/arm/arch-pxa/htcuniversal-asic.h -+ * -+ * Authors: Giuseppe Zompatori <giuseppe_zompatori@yahoo.it> -+ * -+ * based on previews work, see below: -+ * -+ * include/asm/arm/arch-pxa/hx4700-asic.h -+ * Copyright (c) 2004 SDG Systems, LLC -+ * -+ */ -+ -+#ifndef _HTCUNIVERSAL_ASIC_H_ -+#define _HTCUNIVERSAL_ASIC_H_ -+ -+#include <asm/hardware/ipaq-asic3.h> -+ -+/* ASIC3 */ -+ -+#define HTCUNIVERSAL_ASIC3_GPIO_PHYS PXA_CS4_PHYS -+#define HTCUNIVERSAL_ASIC3_MMC_PHYS PXA_CS3_PHYS -+ -+/* TODO: some information is missing here */ -+ -+/* ASIC3 GPIO A bank */ -+ -+#define GPIOA_I2C_EN 0 /* Output */ -+#define GPIOA_SPK_PWR1_ON 1 /* Output */ -+#define GPIOA_AUDIO_PWR_ON 2 /* Output */ -+#define GPIOA_EARPHONE_PWR_ON 3 /* Output */ -+ -+#define GPIOA_UNKNOWN4 4 /* Output */ -+#define GPIOA_BUTTON_BACKLIGHT_N 5 /* Input */ -+#define GPIOA_SPK_PWR2_ON 6 /* Output */ -+#define GPIOA_BUTTON_RECORD_N 7 /* Input */ -+ -+#define GPIOA_BUTTON_CAMERA_N 8 /* Input */ -+#define GPIOA_UNKNOWN9 9 /* Output */ -+#define GPIOA_FLASHLIGHT 10 /* Output */ -+#define GPIOA_COVER_ROTATE_N 11 /* Input */ -+ -+#define GPIOA_TOUCHSCREEN_N 12 /* Input */ -+#define GPIOA_VOL_UP_N 13 /* Input */ -+#define GPIOA_VOL_DOWN_N 14 /* Input */ -+#define GPIOA_LCD_PWR5_ON 15 /* Output */ -+ -+/* ASIC3 GPIO B bank */ -+ -+#define GPIOB_BB_READY 0 /* Input */ -+#define GPIOB_CODEC_PDN 1 /* Output */ -+#define GPIOB_UNKNOWN2 2 /* Input */ -+#define GPIOB_BB_UNKNOWN3 3 /* Input */ -+ -+#define GPIOB_BT_IRQ 4 /* Input */ -+#define GPIOB_CLAMSHELL_N 5 /* Input */ -+#define GPIOB_LCD_PWR3_ON 6 /* Output */ -+#define GPIOB_BB_ALERT 7 /* Input */ -+ -+#define GPIOB_BB_RESET2 8 /* Output */ -+#define GPIOB_EARPHONE_N 9 /* Input */ -+#define GPIOB_MICRECORD_N 10 /* Input */ -+#define GPIOB_NIGHT_SENSOR 11 /* Input */ -+ -+#define GPIOB_UMTS_DCD 12 /* Input */ -+#define GPIOB_UNKNOWN13 13 /* Input */ -+#define GPIOB_CHARGE_EN 14 /* Output */ -+#define GPIOB_USB_PUEN 15 /* Output */ -+ -+/* ASIC3 GPIO C bank */ -+ -+#define GPIOC_LED_BTWIFI 0 /* Output */ -+#define GPIOC_LED_RED 1 /* Output */ -+#define GPIOC_LED_GREEN 2 /* Output */ -+#define GPIOC_BOARDID3 3 /* Input */ -+ -+#define GPIOC_WIFI_IRQ_N 4 /* Input */ -+#define GPIOC_WIFI_RESET 5 /* Output */ -+#define GPIOC_WIFI_PWR1_ON 6 /* Output */ -+#define GPIOC_BT_RESET 7 /* Output */ -+ -+#define GPIOC_UNKNOWN8 8 /* Output */ -+#define GPIOC_LCD_PWR1_ON 9 /* Output */ -+#define GPIOC_LCD_PWR2_ON 10 /* Output */ -+#define GPIOC_BOARDID2 11 /* Input */ -+ -+#define GPIOC_BOARDID1 12 /* Input */ -+#define GPIOC_BOARDID0 13 /* Input */ -+#define GPIOC_BT_PWR_ON 14 /* Output */ -+#define GPIOC_CHARGE_ON 15 /* Output */ -+ -+/* ASIC3 GPIO D bank */ -+ -+#define GPIOD_KEY_OK_N 0 /* Input */ -+#define GPIOD_KEY_RIGHT_N 1 /* Input */ -+#define GPIOD_KEY_LEFT_N 2 /* Input */ -+#define GPIOD_KEY_DOWN_N 3 /* Input */ -+ -+#define GPIOD_KEY_UP_N 4 /* Input */ -+#define GPIOD_SDIO_DET 5 /* Input */ -+#define GPIOD_WIFI_PWR2_ON 6 /* Output */ -+#define GPIOD_HW_REBOOT 7 /* Output */ -+ -+#define GPIOD_BB_RESET1 8 /* Output */ -+#define GPIOD_UNKNOWN9 9 /* Output */ -+#define GPIOD_VIBRA_PWR_ON 10 /* Output */ -+#define GPIOD_WIFI_PWR3_ON 11 /* Output */ -+ -+#define GPIOD_FL_PWR_ON 12 /* Output */ -+#define GPIOD_LCD_PWR4_ON 13 /* Output */ -+#define GPIOD_BL_KEYP_PWR_ON 14 /* Output */ -+#define GPIOD_BL_KEYB_PWR_ON 15 /* Output */ -+ -+extern struct platform_device htcuniversal_asic3; -+ -+/* ASIC3 GPIO A bank */ -+ -+#define GPIO_I2C_EN 0*16+GPIOA_I2C_EN -+#define GPIO_SPK_PWR1_ON 0*16+GPIOA_SPK_PWR1_ON -+#define GPIO_AUDIO_PWR_ON 0*16+GPIOA_AUDIO_PWR_ON -+#define GPIO_EARPHONE_PWR_ON 0*16+GPIOA_EARPHONE_PWR_ON -+ -+#define GPIO_UNKNOWNA4 0*16+GPIOA_UNKNOWN4 -+#define GPIO_BUTTON_BACKLIGHT_N 0*16+GPIOA_BUTTON_BACKLIGHT_N -+#define GPIO_SPK_PWR2_ON 0*16+GPIOA_SPK_PWR2_ON -+#define GPIO_BUTTON_RECORD_N 0*16+GPIOA_BUTTON_RECORD_N -+ -+#define GPIO_BUTTON_CAMERA_N 0*16+GPIOA_BUTTON_CAMERA_N -+#define GPIO_UNKNOWNA9 0*16+GPIOA_UNKNOWN9 -+#define GPIO_FLASHLIGHT 0*16+GPIOA_FLASHLIGHT -+#define GPIO_COVER_ROTATE_N 0*16+GPIOA_COVER_ROTATE_N -+ -+#define GPIO_TOUCHSCREEN_N 0*16+GPIOA_TOUCHSCREEN_N -+#define GPIO_VOL_UP_N 0*16+GPIOA_VOL_UP_N -+#define GPIO_VOL_DOWN_N 0*16+GPIOA_VOL_DOWN_N -+#define GPIO_LCD_PWR5_ON 0*16+GPIOA_LCD_PWR5_ON -+ -+/* ASIC3 GPIO B bank */ -+ -+#define GPIO_BB_READY 1*16+GPIOB_BB_READY -+#define GPIO_CODEC_PDN 1*16+GPIOB_CODEC_PDN -+#define GPIO_UNKNOWNB2 1*16+GPIOB_UNKNOWN2 -+#define GPIO_BB_UNKNOWN3 1*16+GPIOB_BB_UNKNOWN3 -+ -+#define GPIO_BT_IRQ 1*16+GPIOB_BT_IRQ -+#define GPIO_CLAMSHELL_N 1*16+GPIOB_CLAMSHELL_N -+#define GPIO_LCD_PWR3_ON 1*16+GPIOB_LCD_PWR3_ON -+#define GPIO_BB_ALERT 1*16+GPIOB_BB_ALERT -+ -+#define GPIO_BB_RESET2 1*16+GPIOB_BB_RESET2 -+#define GPIO_EARPHONE_N 1*16+GPIOB_EARPHONE_N -+#define GPIO_MICRECORD_N 1*16+GPIOB_MICRECORD_N -+#define GPIO_NIGHT_SENSOR 1*16+GPIOB_NIGHT_SENSOR -+ -+#define GPIO_UMTS_DCD 1*16+GPIOB_UMTS_DCD -+#define GPIO_UNKNOWNB13 1*16+GPIOB_UNKNOWN13 -+#define GPIO_CHARGE_EN 1*16+GPIOB_CHARGE_EN -+#define GPIO_USB_PUEN 1*16+GPIOB_USB_PUEN -+ -+/* ASIC3 GPIO C bank */ -+ -+#define GPIO_LED_BTWIFI 2*16+GPIOC_LED_BTWIFI -+#define GPIO_LED_RED 2*16+GPIOC_LED_RED -+#define GPIO_LED_GREEN 2*16+GPIOC_LED_GREEN -+#define GPIO_BOARDID3 2*16+GPIOC_BOARDID3 -+ -+#define GPIO_WIFI_IRQ_N 2*16+GPIOC_WIFI_IRQ_N -+#define GPIO_WIFI_RESET 2*16+GPIOC_WIFI_RESET -+#define GPIO_WIFI_PWR1_ON 2*16+GPIOC_WIFI_PWR1_ON -+#define GPIO_BT_RESET 2*16+GPIOC_BT_RESET -+ -+#define GPIO_UNKNOWNC8 2*16+GPIOC_UNKNOWN8 -+#define GPIO_LCD_PWR1_ON 2*16+GPIOC_LCD_PWR1_ON -+#define GPIO_LCD_PWR2_ON 2*16+GPIOC_LCD_PWR2_ON -+#define GPIO_BOARDID2 2*16+GPIOC_BOARDID2 -+ -+#define GPIO_BOARDID1 2*16+GPIOC_BOARDID1 -+#define GPIO_BOARDID0 2*16+GPIOC_BOARDID0 -+#define GPIO_BT_PWR_ON 2*16+GPIOC_BT_PWR_ON -+#define GPIO_CHARGE_ON 2*16+GPIOC_CHARGE_ON -+ -+/* ASIC3 GPIO D bank */ -+ -+#define GPIO_KEY_OK_N 3*16+GPIOD_KEY_OK_N -+#define GPIO_KEY_RIGHT_N 3*16+GPIOD_KEY_RIGHT_N -+#define GPIO_KEY_LEFT_N 3*16+GPIOD_KEY_LEFT_N -+#define GPIO_KEY_DOWN_N 3*16+GPIOD_KEY_DOWN_N -+ -+#define GPIO_KEY_UP_N 3*16+GPIOD_KEY_UP_N -+#define GPIO_SDIO_DET 3*16+GPIOD_SDIO_DET -+#define GPIO_WIFI_PWR2_ON 3*16+GPIOD_WIFI_PWR2_ON -+#define GPIO_HW_REBOOT 3*16+GPIOD_HW_REBOOT -+ -+#define GPIO_BB_RESET1 3*16+GPIOD_BB_RESET1 -+#define GPIO_UNKNOWND9 3*16+GPIOD_UNKNOWN9 -+#define GPIO_VIBRA_PWR_ON 3*16+GPIOD_VIBRA_PWR_ON -+#define GPIO_WIFI_PWR3_ON 3*16+GPIOD_WIFI_PWR3_ON -+ -+#define GPIO_FL_PWR_ON 3*16+GPIOD_FL_PWR_ON -+#define GPIO_LCD_PWR4_ON 3*16+GPIOD_LCD_PWR4_ON -+#define GPIO_BL_KEYP_PWR_ON 3*16+GPIOD_BL_KEYP_PWR_ON -+#define GPIO_BL_KEYB_PWR_ON 3*16+GPIOD_BL_KEYB_PWR_ON -+ -+#define HTCUNIVERSAL_EGPIO_BASE PXA_CS2_PHYS+0x02000000 -+ -+#define EGPIO4_ON 4 /* something */ -+#define EGPIO5_BT_3V3_ON 5 /* Bluetooth related */ -+#define EGPIO6_WIFI_ON 6 /* WLAN related*/ -+ -+extern void htcuniversal_egpio_enable( u_int16_t bits ); -+extern void htcuniversal_egpio_disable( u_int16_t bits ); -+ -+#endif /* _HTCUNIVERSAL_ASIC_H_ */ -+ -Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,220 @@ -+/* -+ * include/asm-arm/arch-pxa/htcuniversal-gpio.h -+ * History: -+ * -+ * 2004-12-10 Michael Opdenacker. Wrote down GPIO settings as identified by Jamey Hicks. -+ * Reused the h2200-gpio.h file as a template. -+ */ -+ -+#ifndef _HTCUNIVERSAL_GPIO_H_ -+#define _HTCUNIVERSAL_GPIO_H_ -+ -+#include <asm/arch/pxa-regs.h> -+ -+#define GET_HTCUNIVERSAL_GPIO(gpio) \ -+ (GPLR(GPIO_NR_HTCUNIVERSAL_ ## gpio) & GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio)) -+ -+#define SET_HTCUNIVERSAL_GPIO(gpio, setp) \ -+do { \ -+if (setp) \ -+ GPSR(GPIO_NR_HTCUNIVERSAL_ ## gpio) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio); \ -+else \ -+ GPCR(GPIO_NR_HTCUNIVERSAL_ ## gpio) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio); \ -+} while (0) -+ -+#define SET_HTCUNIVERSAL_GPIO_N(gpio, setp) \ -+do { \ -+if (setp) \ -+ GPCR(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N); \ -+else \ -+ GPSR(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N); \ -+} while (0) -+ -+#define HTCUNIVERSAL_IRQ(gpio) \ -+ IRQ_GPIO(GPIO_NR_HTCUNIVERSAL_ ## gpio) -+ -+#define GPIO_NR_HTCUNIVERSAL_KEY_ON_N 0 -+#define GPIO_NR_HTCUNIVERSAL_GP_RST_N 1 -+ -+#define GPIO_NR_HTCUNIVERSAL_USB_DET 9 -+#define GPIO_NR_HTCUNIVERSAL_POWER_DET 10 -+ -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD7 12 -+#define GPIO_NR_HTCUNIVERSAL_ASIC3_SDIO_INT_N 13 -+#define GPIO_NR_HTCUNIVERSAL_ASIC3_EXT_INT 14 -+#define GPIO_NR_HTCUNIVERSAL_CS1_N 15 -+ -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD6 17 -+#define GPIO_NR_HTCUNIVERSAL_RDY 18 -+ -+#define GPIO_NR_HTCUNIVERSAL_PHONE_START 19 -+ -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT7 22 -+#define GPIO_NR_HTCUNIVERSAL_SPI_CLK 23 -+#define GPIO_NR_HTCUNIVERSAL_SPI_FRM 24 -+#define GPIO_NR_HTCUNIVERSAL_SPI_DO 25 -+#define GPIO_NR_HTCUNIVERSAL_SPI_DI 26 -+ -+#define GPIO_NR_HTCUNIVERSAL_CODEC_ON 27 -+#define GPIO_NR_HTCUNIVERSAL_I2S_BCK 28 -+#define GPIO_NR_HTCUNIVERSAL_I2S_DIN 29 -+#define GPIO_NR_HTCUNIVERSAL_I2S_DOUT 30 -+#define GPIO_NR_HTCUNIVERSAL_I2S_SYNC 31 -+ -+#define GPIO_NR_HTCUNIVERSAL_RS232_ON 32 -+#define GPIO_NR_HTCUNIVERSAL_CS5_N 33 -+ -+#define GPIO_NR_HTCUNIVERSAL_PHONE_RXD 34 -+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS 35 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN7 36 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN3 37 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN4 38 -+#define GPIO_NR_HTCUNIVERSAL_PHONE_TXD 39 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT6 40 -+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS 41 -+#define GPIO_NR_HTCUNIVERSAL_BT_RXD 42 -+#define GPIO_NR_HTCUNIVERSAL_BT_TXD 43 -+#define GPIO_NR_HTCUNIVERSAL_BT_UART_CTS 44 -+#define GPIO_NR_HTCUNIVERSAL_BT_UART_RTS 45 -+ -+#define GPIO_NR_HTCUNIVERSAL_SIR_RXD 42 -+#define GPIO_NR_HTCUNIVERSAL_SIR_TXD 43 -+ -+#define GPIO_NR_HTCUNIVERSAL_POE_N 48 -+#define GPIO_NR_HTCUNIVERSAL_PWE_N 49 -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD3 50 -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD2 51 -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD4 52 -+ -+#define GPIO_NR_HTCUNIVERSAL_CIF_MCLK 53 -+#define GPIO_NR_HTCUNIVERSAL_CIF_PCLK 54 -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD1 55 -+ -+#define GPIO_NR_HTCUNIVERSAL_LDD0 58 -+#define GPIO_NR_HTCUNIVERSAL_LDD1 59 -+#define GPIO_NR_HTCUNIVERSAL_LDD2 60 -+#define GPIO_NR_HTCUNIVERSAL_LDD3 61 -+#define GPIO_NR_HTCUNIVERSAL_LDD4 62 -+#define GPIO_NR_HTCUNIVERSAL_LDD5 63 -+#define GPIO_NR_HTCUNIVERSAL_LDD6 64 -+#define GPIO_NR_HTCUNIVERSAL_LDD7 65 -+#define GPIO_NR_HTCUNIVERSAL_LDD8 66 -+#define GPIO_NR_HTCUNIVERSAL_LDD9 67 -+#define GPIO_NR_HTCUNIVERSAL_LDD10 68 -+#define GPIO_NR_HTCUNIVERSAL_LDD11 69 -+#define GPIO_NR_HTCUNIVERSAL_LDD12 70 -+#define GPIO_NR_HTCUNIVERSAL_LDD13 71 -+#define GPIO_NR_HTCUNIVERSAL_LDD14 72 -+#define GPIO_NR_HTCUNIVERSAL_LDD15 73 -+ -+#define GPIO_NR_HTCUNIVERSAL_LFCLK_RD 74 -+#define GPIO_NR_HTCUNIVERSAL_LFCLK_A0 75 -+#define GPIO_NR_HTCUNIVERSAL_LFCLK_WR 76 -+#define GPIO_NR_HTCUNIVERSAL_LBIAS 77 -+ -+#define GPIO_NR_HTCUNIVERSAL_CS2_N 78 -+#define GPIO_NR_HTCUNIVERSAL_CS3_N 79 -+#define GPIO_NR_HTCUNIVERSAL_CS4_N 80 -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD0 81 -+#define GPIO_NR_HTCUNIVERSAL_CIF_DD5 82 -+ -+#define GPIO_NR_HTCUNIVERSAL_CIF_LV 84 -+#define GPIO_NR_HTCUNIVERSAL_CIF_FV 85 -+ -+#define GPIO_NR_HTCUNIVERSAL_LCD1 86 -+#define GPIO_NR_HTCUNIVERSAL_LCD2 87 -+ -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN5 90 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN6 91 -+ -+#define GPIO_NR_HTCUNIVERSAL_DREQ1 97 -+ -+#define GPIO_NR_HTCUNIVERSAL_PHONE_RESET 98 -+ -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN0 100 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN1 101 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN2 102 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT0 103 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT1 104 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT2 105 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT3 106 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT4 107 -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT5 108 -+ -+#define GPIO_NR_HTCUNIVERSAL_PHONE_UNKNOWN 109 -+#define GPIO_NR_HTCUNIVERSAL_PHONE_OFF 110 -+ -+#define GPIO_NR_HTCUNIVERSAL_USB_PUEN 112 -+#define GPIO_NR_HTCUNIVERSAL_I2S_SYSCLK 113 -+ -+#define GPIO_NR_HTCUNIVERSAL_PWM_OUT1 115 -+ -+#define GPIO_NR_HTCUNIVERSAL_I2C_SCL 117 -+#define GPIO_NR_HTCUNIVERSAL_I2C_SDA 118 -+ -+#if 0 -+#define GPIO_NR_HTCUNIVERSAL_CPU_BATT_FAULT_N -+#define GPIO_NR_HTCUNIVERSAL_ASIC3_RESET_N -+#define GPIO_NR_HTCUNIVERSAL_CHARGE_EN_N -+#define GPIO_NR_HTCUNIVERSAL_FLASH_VPEN -+#define GPIO_NR_HTCUNIVERSAL_BATT_OFF -+#define GPIO_NR_HTCUNIVERSAL_USB_CHARGE_RATE -+#define GPIO_NR_HTCUNIVERSAL_BL_DETECT_N -+#define GPIO_NR_HTCUNIVERSAL_CPU_HW_RESET_N -+#endif -+ -+ -+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_CLK_MD (23 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_FRM_MD (24 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DO_MD (25 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DI_MD (26 | GPIO_ALT_FN_1_IN) -+ -+#define GPIO_NR_HTCUNIVERSAL_I2S_BCK_MD (28 | GPIO_ALT_FN_1_OUT) -+#define GPIO_NR_HTCUNIVERSAL_I2S_DIN_MD (29 | GPIO_ALT_FN_2_IN) -+#define GPIO_NR_HTCUNIVERSAL_I2S_DOUT_MD (30 | GPIO_ALT_FN_1_OUT) -+#define GPIO_NR_HTCUNIVERSAL_I2S_SYNC_MD (31 | GPIO_ALT_FN_1_OUT) -+ -+#define GPIO_NR_HTCUNIVERSAL_PHONE_RXD_MD (34 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS_MD (35 | GPIO_ALT_FN_1_IN) -+ -+#define GPIO_NR_HTCUNIVERSAL_PHONE_TXD_MD (39 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS_MD (41 | GPIO_ALT_FN_2_OUT) -+ -+#define GPIO_NR_HTCUNIVERSAL_BT_RXD_MD (42 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_BT_TXD_MD (43 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_BT_UART_CTS_MD (44 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_BT_UART_RTS_MD (45 | GPIO_ALT_FN_2_OUT) -+ -+#define GPIO_NR_HTCUNIVERSAL_SIR_RXD_MD (46 | GPIO_ALT_FN_2_IN) -+#define GPIO_NR_HTCUNIVERSAL_SIR_TXD_MD (47 | GPIO_ALT_FN_1_OUT) -+ -+#define GPIO_NR_HTCUNIVERSAL_POE_N_MD (48 | GPIO_ALT_FN_2_OUT | GPIO_DFLT_HIGH) -+#define GPIO_NR_HTCUNIVERSAL_PWE_N_MD (49 | GPIO_ALT_FN_2_OUT | GPIO_DFLT_HIGH) -+ -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN0_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN0 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN1_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN1 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN2_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN2 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN3_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN3 | GPIO_ALT_FN_3_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN4_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN4 | GPIO_ALT_FN_2_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN5_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN5 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN6_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN6 | GPIO_ALT_FN_1_IN) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKIN7_MD (GPIO_NR_HTCUNIVERSAL_KP_MKIN7 | GPIO_ALT_FN_3_IN) -+ -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT0_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT0 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT1_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT1 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT2_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT2 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT3_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT3 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT4_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT4 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT5_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT5 | GPIO_ALT_FN_2_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT6_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT6 | GPIO_ALT_FN_1_OUT) -+#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT7_MD (GPIO_NR_HTCUNIVERSAL_KP_MKOUT7 | GPIO_ALT_FN_1_OUT) -+ -+ -+#define GPIO_NR_HTCUNIVERSAL_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT) -+ -+#define GPIO_NR_HTCUNIVERSAL_PWM1OUT_MD (115 | GPIO_ALT_FN_3_OUT) -+ -+#define GPIO_NR_HTCUNIVERSAL_I2C_SCL_MD (117 | GPIO_ALT_FN_1_OUT) -+#define GPIO_NR_HTCUNIVERSAL_I2C_SDA_MD (118 | GPIO_ALT_FN_1_OUT) -+ -+#endif /* _HTCUNIVERSAL_GPIO_H */ -Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,14 @@ -+/* -+ * include/asm/arm/arch-pxa/htcuniversal-init.h -+ * Copyright (c) 2004 SDG Systems, LLC -+ */ -+ -+#ifndef _HTCUNIVERSAL_INIT_H_ -+#define _HTCUNIVERSAL_INIT_H_ -+ -+/* htcuniversal initialization data should be found here -+ * See -init.h files from other devices for details -+ */ -+ -+#endif /* _HTCUNIVERSAL_INIT_H_ */ -+ -Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,3 @@ -+#include <asm/arch/irqs.h> -+ -+#define HTCUNIVERSAL_ASIC3_IRQ_BASE IRQ_BOARD_START -Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,6 @@ -+struct pxa_ll_pm_ops { -+ void (*suspend)(unsigned long); -+ void (*resume)(void); -+}; -+ -+extern struct pxa_ll_pm_ops *pxa_pm_set_ll_ops(struct pxa_ll_pm_ops *new_ops); -Index: linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h -=================================================================== ---- linux-2.6.22.orig/include/asm-arm/arch-pxa/sharpsl.h 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h 2007-09-11 12:53:37.000000000 +0200 -@@ -25,12 +25,6 @@ - /* - * SharpSL Backlight - */ --struct corgibl_machinfo { -- int max_intensity; -- int default_intensity; -- int limit_mask; -- void (*set_bl_intensity)(int intensity); --}; - extern void corgibl_limit_intensity(int limit); - - -Index: linux-2.6.22/include/asm-arm/hardware/asic3_keys.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/hardware/asic3_keys.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,18 @@ -+#include <linux/input.h> -+ -+struct asic3_keys_button { -+ /* Configuration parameters */ -+ int keycode; -+ int gpio; -+ int active_low; -+ char *desc; -+ int type; -+ /* Internal state vars - add below */ -+}; -+ -+struct asic3_keys_platform_data { -+ struct asic3_keys_button *buttons; -+ int nbuttons; -+ struct input_dev *input; -+ struct device *asic3_dev; -+}; -Index: linux-2.6.22/include/asm-arm/hardware/asic3_leds.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/hardware/asic3_leds.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,34 @@ -+/* -+ * LEDs support for HTC ASIC3 devices. -+ * -+ * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru> -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+ -+struct asic3_leds_machinfo; -+ -+struct asic3_led { -+ struct led_classdev led_cdev; -+ int hw_num; /* Number of "hardware-accelerated" led */ -+ int gpio_num; /* Number of GPIO if hw_num == -1 */ -+ struct asic3_leds_machinfo *machinfo; -+}; -+ -+struct asic3_leds_machinfo { -+ int num_leds; -+ struct asic3_led *leds; -+ struct platform_device *asic3_pdev; -+}; -+ -+extern int asic3_leds_register(void); -+extern void asic3_leds_unregister(void); -+ -Index: linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,602 @@ -+/* -+ * -+ * Definitions for the HTC ASIC3 chip found in several handheld devices -+ * -+ * Copyright 2001 Compaq Computer Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, -+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS -+ * FITNESS FOR ANY PARTICULAR PURPOSE. -+ * -+ * Author: Andrew Christian -+ * -+ */ -+ -+#ifndef IPAQ_ASIC3_H -+#define IPAQ_ASIC3_H -+ -+/****************************************************/ -+/* IPAQ, ASIC #3, replaces ASIC #1 */ -+ -+#define IPAQ_ASIC3_OFFSET(x,y) (_IPAQ_ASIC3_ ## x ## _Base + _IPAQ_ASIC3_ ## x ## _ ## y) -+#define IPAQ_ASIC3_GPIO_OFFSET(x,y) (_IPAQ_ASIC3_GPIO_ ## x ## _Base + _IPAQ_ASIC3_GPIO_ ## y) -+ -+ -+/* All offsets below are specified with the following address bus shift */ -+#define ASIC3_DEFAULT_ADDR_SHIFT 2 -+ -+#define _IPAQ_ASIC3_GPIO_A_Base 0x0000 -+#define _IPAQ_ASIC3_GPIO_B_Base 0x0100 -+#define _IPAQ_ASIC3_GPIO_C_Base 0x0200 -+#define _IPAQ_ASIC3_GPIO_D_Base 0x0300 -+ -+#define _IPAQ_ASIC3_GPIO_Mask 0x00 /* R/W 0:don't mask, 1:mask interrupt */ -+#define _IPAQ_ASIC3_GPIO_Direction 0x04 /* R/W 0:input, 1:output */ -+#define _IPAQ_ASIC3_GPIO_Out 0x08 /* R/W 0:output low, 1:output high */ -+#define _IPAQ_ASIC3_GPIO_TriggerType 0x0c /* R/W 0:level, 1:edge */ -+#define _IPAQ_ASIC3_GPIO_EdgeTrigger 0x10 /* R/W 0:falling, 1:rising */ -+#define _IPAQ_ASIC3_GPIO_LevelTrigger 0x14 /* R/W 0:low, 1:high level detect */ -+#define _IPAQ_ASIC3_GPIO_SleepMask 0x18 /* R/W 0:don't mask, 1:mask trigger in sleep mode */ -+#define _IPAQ_ASIC3_GPIO_SleepOut 0x1c /* R/W level 0:low, 1:high in sleep mode */ -+#define _IPAQ_ASIC3_GPIO_BattFaultOut 0x20 /* R/W level 0:low, 1:high in batt_fault */ -+#define _IPAQ_ASIC3_GPIO_IntStatus 0x24 /* R/W 0:none, 1:detect */ -+#define _IPAQ_ASIC3_GPIO_AltFunction 0x28 /* R/W 0:normal control 1:LED register control */ -+#define _IPAQ_ASIC3_GPIO_SleepConf 0x2c /* R/W bit 1: autosleep 0: disable gposlpout in normal mode, enable gposlpout in sleep mode */ -+#define _IPAQ_ASIC3_GPIO_Status 0x30 /* R Pin status */ -+ -+#define IPAQ_ASIC3_GPIO_A_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Mask ) -+#define IPAQ_ASIC3_GPIO_A_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Direction ) -+#define IPAQ_ASIC3_GPIO_A_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Out ) -+#define IPAQ_ASIC3_GPIO_A_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, A, TriggerType ) -+#define IPAQ_ASIC3_GPIO_A_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, A, EdgeTrigger ) -+#define IPAQ_ASIC3_GPIO_A_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, A, LevelTrigger ) -+#define IPAQ_ASIC3_GPIO_A_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepMask ) -+#define IPAQ_ASIC3_GPIO_A_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepOut ) -+#define IPAQ_ASIC3_GPIO_A_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, A, BattFaultOut ) -+#define IPAQ_ASIC3_GPIO_A_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, A, IntStatus ) -+#define IPAQ_ASIC3_GPIO_A_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, A, AltFunction ) -+#define IPAQ_ASIC3_GPIO_A_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepConf ) -+#define IPAQ_ASIC3_GPIO_A_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, A, Status ) -+ -+#define IPAQ_ASIC3_GPIO_B_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Mask ) -+#define IPAQ_ASIC3_GPIO_B_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Direction ) -+#define IPAQ_ASIC3_GPIO_B_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Out ) -+#define IPAQ_ASIC3_GPIO_B_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, B, TriggerType ) -+#define IPAQ_ASIC3_GPIO_B_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, B, EdgeTrigger ) -+#define IPAQ_ASIC3_GPIO_B_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, B, LevelTrigger ) -+#define IPAQ_ASIC3_GPIO_B_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepMask ) -+#define IPAQ_ASIC3_GPIO_B_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepOut ) -+#define IPAQ_ASIC3_GPIO_B_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, B, BattFaultOut ) -+#define IPAQ_ASIC3_GPIO_B_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, B, IntStatus ) -+#define IPAQ_ASIC3_GPIO_B_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, B, AltFunction ) -+#define IPAQ_ASIC3_GPIO_B_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepConf ) -+#define IPAQ_ASIC3_GPIO_B_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, B, Status ) -+ -+#define IPAQ_ASIC3_GPIO_C_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Mask ) -+#define IPAQ_ASIC3_GPIO_C_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Direction ) -+#define IPAQ_ASIC3_GPIO_C_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Out ) -+#define IPAQ_ASIC3_GPIO_C_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, C, TriggerType ) -+#define IPAQ_ASIC3_GPIO_C_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, C, EdgeTrigger ) -+#define IPAQ_ASIC3_GPIO_C_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, C, LevelTrigger ) -+#define IPAQ_ASIC3_GPIO_C_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepMask ) -+#define IPAQ_ASIC3_GPIO_C_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepOut ) -+#define IPAQ_ASIC3_GPIO_C_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, C, BattFaultOut ) -+#define IPAQ_ASIC3_GPIO_C_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, C, IntStatus ) -+#define IPAQ_ASIC3_GPIO_C_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, C, AltFunction ) -+#define IPAQ_ASIC3_GPIO_C_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepConf ) -+#define IPAQ_ASIC3_GPIO_C_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, C, Status ) -+ -+#define IPAQ_ASIC3_GPIO_D_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Mask ) -+#define IPAQ_ASIC3_GPIO_D_DIR(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Direction ) -+#define IPAQ_ASIC3_GPIO_D_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Out ) -+#define IPAQ_ASIC3_GPIO_D_LEVELTRI(_b) IPAQ_ASIC3_GPIO( _b, u16, D, TriggerType ) -+#define IPAQ_ASIC3_GPIO_D_RISING(_b) IPAQ_ASIC3_GPIO( _b, u16, D, EdgeTrigger ) -+#define IPAQ_ASIC3_GPIO_D_LEVEL(_b) IPAQ_ASIC3_GPIO( _b, u16, D, LevelTrigger ) -+#define IPAQ_ASIC3_GPIO_D_SLEEP_MASK(_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepMask ) -+#define IPAQ_ASIC3_GPIO_D_SLEEP_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepOut ) -+#define IPAQ_ASIC3_GPIO_D_BATT_FAULT_OUT(_b) IPAQ_ASIC3_GPIO( _b, u16, D, BattFaultOut ) -+#define IPAQ_ASIC3_GPIO_D_INT_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, D, IntStatus ) -+#define IPAQ_ASIC3_GPIO_D_ALT_FUNCTION(_b) IPAQ_ASIC3_GPIO( _b, u16, D, AltFunction ) -+#define IPAQ_ASIC3_GPIO_D_SLEEP_CONF(_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepConf ) -+#define IPAQ_ASIC3_GPIO_D_STATUS(_b) IPAQ_ASIC3_GPIO( _b, u16, D, Status ) -+ -+#define _IPAQ_ASIC3_SPI_Base 0x0400 -+#define _IPAQ_ASIC3_SPI_Control 0x0000 -+#define _IPAQ_ASIC3_SPI_TxData 0x0004 -+#define _IPAQ_ASIC3_SPI_RxData 0x0008 -+#define _IPAQ_ASIC3_SPI_Int 0x000c -+#define _IPAQ_ASIC3_SPI_Status 0x0010 -+ -+#define IPAQ_ASIC3_SPI_Control(_b) IPAQ_ASIC3( _b, u16, SPI, Control ) -+#define IPAQ_ASIC3_SPI_TxData(_b) IPAQ_ASIC3( _b, u16, SPI, TxData ) -+#define IPAQ_ASIC3_SPI_RxData(_b) IPAQ_ASIC3( _b, u16, SPI, RxData ) -+#define IPAQ_ASIC3_SPI_Int(_b) IPAQ_ASIC3( _b, u16, SPI, Int ) -+#define IPAQ_ASIC3_SPI_Status(_b) IPAQ_ASIC3( _b, u16, SPI, Status ) -+ -+#define SPI_CONTROL_SPR(clk) ((clk) & 0x0f) /* Clock rate */ -+ -+#define _IPAQ_ASIC3_PWM_0_Base 0x0500 -+#define _IPAQ_ASIC3_PWM_1_Base 0x0600 -+#define _IPAQ_ASIC3_PWM_TimeBase 0x0000 -+#define _IPAQ_ASIC3_PWM_PeriodTime 0x0004 -+#define _IPAQ_ASIC3_PWM_DutyTime 0x0008 -+ -+#define IPAQ_ASIC3_PWM_TimeBase(_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, TimeBase ) -+#define IPAQ_ASIC3_PWM_PeriodTime(_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, PeriodTime ) -+#define IPAQ_ASIC3_PWM_DutyTime(_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, DutyTime ) -+ -+#define PWM_TIMEBASE_VALUE(x) ((x)&0xf) /* Low 4 bits sets time base */ -+#define PWM_TIMEBASE_ENABLE (1 << 4) /* Enable clock */ -+ -+#define _IPAQ_ASIC3_LED_0_Base 0x0700 -+#define _IPAQ_ASIC3_LED_1_Base 0x0800 -+#define _IPAQ_ASIC3_LED_2_Base 0x0900 -+#define _IPAQ_ASIC3_LED_TimeBase 0x0000 /* R/W 7 bits */ -+#define _IPAQ_ASIC3_LED_PeriodTime 0x0004 /* R/W 12 bits */ -+#define _IPAQ_ASIC3_LED_DutyTime 0x0008 /* R/W 12 bits */ -+#define _IPAQ_ASIC3_LED_AutoStopCount 0x000c /* R/W 16 bits */ -+ -+#define IPAQ_ASIC3_LED_TimeBase(_b, x) IPAQ_ASIC3_N( _b, u8, LED, x, TimeBase ) -+#define IPAQ_ASIC3_LED_PeriodTime(_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, PeriodTime ) -+#define IPAQ_ASIC3_LED_DutyTime(_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, DutyTime ) -+#define IPAQ_ASIC3_LED_AutoStopCount(_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, AutoStopCount ) -+ -+/* LED TimeBase bits - match ASIC2 */ -+#define LED_TBS 0x0f /* Low 4 bits sets time base, max = 13 */ -+ /* Note: max = 5 on hx4700 */ -+ /* 0: maximum time base */ -+ /* 1: maximum time base / 2 */ -+ /* n: maximum time base / 2^n */ -+ -+#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */ -+#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */ -+#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */ -+ -+#define _IPAQ_ASIC3_CLOCK_Base 0x0A00 -+#define _IPAQ_ASIC3_CLOCK_CDEX 0x00 -+#define _IPAQ_ASIC3_CLOCK_SEL 0x04 -+ -+#define IPAQ_ASIC3_CLOCK_CDEX(_b) IPAQ_ASIC3( _b, u16, CLOCK, CDEX ) -+#define IPAQ_ASIC3_CLOCK_SEL(_b) IPAQ_ASIC3( _b, u16, CLOCK, SEL ) -+ -+#define CLOCK_CDEX_SOURCE (1 << 0) /* 2 bits */ -+#define CLOCK_CDEX_SOURCE0 (1 << 0) -+#define CLOCK_CDEX_SOURCE1 (1 << 1) -+#define CLOCK_CDEX_SPI (1 << 2) -+#define CLOCK_CDEX_OWM (1 << 3) -+#define CLOCK_CDEX_PWM0 (1 << 4) -+#define CLOCK_CDEX_PWM1 (1 << 5) -+#define CLOCK_CDEX_LED0 (1 << 6) -+#define CLOCK_CDEX_LED1 (1 << 7) -+#define CLOCK_CDEX_LED2 (1 << 8) -+ -+#define CLOCK_CDEX_SD_HOST (1 << 9) /* R/W: SD host clock source 24.576M/12.288M */ -+#define CLOCK_CDEX_SD_BUS (1 << 10) /* R/W: SD bus clock source control 24.576M/12.288M */ -+#define CLOCK_CDEX_SMBUS (1 << 11) -+#define CLOCK_CDEX_CONTROL_CX (1 << 12) -+ -+#define CLOCK_CDEX_EX0 (1 << 13) /* R/W: 32.768 kHz crystal */ -+#define CLOCK_CDEX_EX1 (1 << 14) /* R/W: 24.576 MHz crystal */ -+ -+#define CLOCK_SEL_SD_HCLK_SEL (1 << 0) /* R/W: SDIO host clock select - 1: 24.576 Mhz, 0: 12.288 MHz */ -+#define CLOCK_SEL_SD_BCLK_SEL (1 << 1) /* R/W: SDIO bus clock select - 1: 24.576 MHz, 0: 12.288 MHz */ -+#define CLOCK_SEL_CX (1 << 2) /* R/W: INT clock source control (32.768 kHz) */ -+ -+ -+#define _IPAQ_ASIC3_INTR_Base 0x0B00 -+ -+#define _IPAQ_ASIC3_INTR_IntMask 0x00 /* Interrupt mask control */ -+#define _IPAQ_ASIC3_INTR_PIntStat 0x04 /* Peripheral interrupt status */ -+#define _IPAQ_ASIC3_INTR_IntCPS 0x08 /* Interrupt timer clock pre-scale */ -+#define _IPAQ_ASIC3_INTR_IntTBS 0x0c /* Interrupt timer set */ -+ -+#define IPAQ_ASIC3_INTR_IntMask(_b) IPAQ_ASIC3( _b, u8, INTR, IntMask ) -+#define IPAQ_ASIC3_INTR_PIntStat(_b) IPAQ_ASIC3( _b, u8, INTR, PIntStat ) -+#define IPAQ_ASIC3_INTR_IntCPS(_b) IPAQ_ASIC3( _b, u8, INTR, IntCPS ) -+#define IPAQ_ASIC3_INTR_IntTBS(_b) IPAQ_ASIC3( _b, u16, INTR, IntTBS ) -+ -+#define ASIC3_INTMASK_GINTMASK (1 << 0) /* Global interrupt mask 1:enable */ -+#define ASIC3_INTMASK_GINTEL (1 << 1) /* 1: rising edge, 0: hi level */ -+#define ASIC3_INTMASK_MASK0 (1 << 2) -+#define ASIC3_INTMASK_MASK1 (1 << 3) -+#define ASIC3_INTMASK_MASK2 (1 << 4) -+#define ASIC3_INTMASK_MASK3 (1 << 5) -+#define ASIC3_INTMASK_MASK4 (1 << 6) -+#define ASIC3_INTMASK_MASK5 (1 << 7) -+ -+#define ASIC3_INTR_PERIPHERAL_A (1 << 0) -+#define ASIC3_INTR_PERIPHERAL_B (1 << 1) -+#define ASIC3_INTR_PERIPHERAL_C (1 << 2) -+#define ASIC3_INTR_PERIPHERAL_D (1 << 3) -+#define ASIC3_INTR_LED0 (1 << 4) -+#define ASIC3_INTR_LED1 (1 << 5) -+#define ASIC3_INTR_LED2 (1 << 6) -+#define ASIC3_INTR_SPI (1 << 7) -+#define ASIC3_INTR_SMBUS (1 << 8) -+#define ASIC3_INTR_OWM (1 << 9) -+ -+#define ASIC3_INTR_CPS(x) ((x)&0x0f) /* 4 bits, max 14 */ -+#define ASIC3_INTR_CPS_SET ( 1 << 4 ) /* Time base enable */ -+ -+ -+/* Basic control of the SD ASIC */ -+#define _IPAQ_ASIC3_SDHWCTRL_Base 0x0E00 -+ -+#define _IPAQ_ASIC3_SDHWCTRL_SDConf 0x00 -+#define IPAQ_ASIC3_SDHWCTRL_SDConf(_b) IPAQ_ASIC3( _b, u8, SDHWCTRL, SDConf ) -+ -+#define ASIC3_SDHWCTRL_SUSPEND (1 << 0) /* 1=suspend all SD operations */ -+#define ASIC3_SDHWCTRL_CLKSEL (1 << 1) /* 1=SDICK, 0=HCLK */ -+#define ASIC3_SDHWCTRL_PCLR (1 << 2) /* All registers of SDIO cleared */ -+#define ASIC3_SDHWCTRL_LEVCD (1 << 3) /* Level of SD card detection: 1:high, 0:low */ -+#define ASIC3_SDHWCTRL_LEVWP (1 << 4) /* Level of SD card write protection: 1=low, 0=high */ -+#define ASIC3_SDHWCTRL_SDLED (1 << 5) /* SD card LED signal 1=enable, 0=disable */ -+#define ASIC3_SDHWCTRL_SDPWR (1 << 6) /* SD card power supply control 1=enable */ -+ -+ -+/* This is a pointer to an array of 12 u32 values - but only the lower 2 bytes matter */ -+/* Use it as "IPAQ_ASIC3_HWPROTECT_ARRAY[x]" */ -+ -+#define _IPAQ_ASIC3_HWPROTECT_Base 0x1000 -+#define IPAQ_ASIC3_HWPROTECT_ARRAY ((volatile u32*)(_IPAQ_ASIC3_Base + _IPAQ_ASIC3_HWPROTECT_Base)) -+#define HWPROTECT_ARRAY_LEN 12 -+#define HWPROTECT_ARRAY_VALUES {0x4854,0x432d,0x5344,0x494f,0x2050,0x2f4e,0x3a33,0x3048,0x3830,0x3032,0x382d,0x3030} -+ -+ -+#define _IPAQ_ASIC3_EXTCF_Base 0x1100 -+ -+#define _IPAQ_ASIC3_EXTCF_Select 0x00 -+#define _IPAQ_ASIC3_EXTCF_Reset 0x04 -+ -+#define IPAQ_ASIC3_EXTCF_Select(_b) IPAQ_ASIC3( _b, u16, EXTCF, Select ) -+#define IPAQ_ASIC3_EXTCF_Reset(_b) IPAQ_ASIC3( _b, u16, EXTCF, Reset ) -+ -+#define ASIC3_EXTCF_SMOD0 (1 << 0) /* slot number of mode 0 */ -+#define ASIC3_EXTCF_SMOD1 (1 << 1) /* slot number of mode 1 */ -+#define ASIC3_EXTCF_SMOD2 (1 << 2) /* slot number of mode 2 */ -+#define ASIC3_EXTCF_OWM_EN (1 << 4) /* enable onewire module */ -+#define ASIC3_EXTCF_OWM_SMB (1 << 5) /* OWM bus selection */ -+#define ASIC3_EXTCF_OWM_RESET (1 << 6) /* undocumented, used by OWM and CF */ -+#define ASIC3_EXTCF_CF0_SLEEP_MODE (1 << 7) /* CF0 sleep state control */ -+#define ASIC3_EXTCF_CF1_SLEEP_MODE (1 << 8) /* CF1 sleep state control */ -+#define ASIC3_EXTCF_CF0_PWAIT_EN (1 << 10) /* CF0 PWAIT_n control */ -+#define ASIC3_EXTCF_CF1_PWAIT_EN (1 << 11) /* CF1 PWAIT_n control */ -+#define ASIC3_EXTCF_CF0_BUF_EN (1 << 12) /* CF0 buffer control */ -+#define ASIC3_EXTCF_CF1_BUF_EN (1 << 13) /* CF1 buffer control */ -+#define ASIC3_EXTCF_SD_MEM_ENABLE (1 << 14) -+#define ASIC3_EXTCF_CF_SLEEP (1 << 15) /* CF sleep mode control */ -+ -+/***************************************************************************** -+ * The Onewire interface registers -+ * -+ * OWM_CMD -+ * OWM_DAT -+ * OWM_INTR -+ * OWM_INTEN -+ * OWM_CLKDIV -+ * -+ *****************************************************************************/ -+ -+#define _IPAQ_ASIC3_OWM_Base 0xC00 -+ -+#define _IPAQ_ASIC3_OWM_CMD 0x00 -+#define _IPAQ_ASIC3_OWM_DAT 0x04 -+#define _IPAQ_ASIC3_OWM_INTR 0x08 -+#define _IPAQ_ASIC3_OWM_INTEN 0x0C -+#define _IPAQ_ASIC3_OWM_CLKDIV 0x10 -+ -+#define ASIC3_OWM_CMD_ONEWR (1 << 0) -+#define ASIC3_OWM_CMD_SRA (1 << 1) -+#define ASIC3_OWM_CMD_DQO (1 << 2) -+#define ASIC3_OWM_CMD_DQI (1 << 3) -+ -+#define ASIC3_OWM_INTR_PD (1 << 0) -+#define ASIC3_OWM_INTR_PDR (1 << 1) -+#define ASIC3_OWM_INTR_TBE (1 << 2) -+#define ASIC3_OWM_INTR_TEMP (1 << 3) -+#define ASIC3_OWM_INTR_RBF (1 << 4) -+ -+#define ASIC3_OWM_INTEN_EPD (1 << 0) -+#define ASIC3_OWM_INTEN_IAS (1 << 1) -+#define ASIC3_OWM_INTEN_ETBE (1 << 2) -+#define ASIC3_OWM_INTEN_ETMT (1 << 3) -+#define ASIC3_OWM_INTEN_ERBF (1 << 4) -+ -+#define ASIC3_OWM_CLKDIV_PRE (3 << 0) /* two bits wide at bit position 0 */ -+#define ASIC3_OWM_CLKDIV_DIV (7 << 2) /* 3 bits wide at bit position 2 */ -+ -+ -+/***************************************************************************** -+ * The SD configuration registers are at a completely different location -+ * in memory. They are divided into three sets of registers: -+ * -+ * SD_CONFIG Core configuration register -+ * SD_CTRL Control registers for SD operations -+ * SDIO_CTRL Control registers for SDIO operations -+ * -+ *****************************************************************************/ -+ -+#define IPAQ_ASIC3_SD_CONFIG(_b, s,x) \ -+ (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CONFIG_Base + (_IPAQ_ASIC3_SD_CONFIG_ ## x)))) -+ -+#define _IPAQ_ASIC3_SD_CONFIG_Base 0x0400 // Assumes 32 bit addressing -+ -+#define _IPAQ_ASIC3_SD_CONFIG_Command 0x08 /* R/W: Command */ -+#define _IPAQ_ASIC3_SD_CONFIG_Addr0 0x20 /* [9:31] SD Control Register Base Address */ -+#define _IPAQ_ASIC3_SD_CONFIG_Addr1 0x24 /* [9:31] SD Control Register Base Address */ -+#define _IPAQ_ASIC3_SD_CONFIG_IntPin 0x78 /* R/O: interrupt assigned to pin */ -+#define _IPAQ_ASIC3_SD_CONFIG_ClkStop 0x80 /* Set to 0x1f to clock SD controller, 0 otherwise. */ -+ /* at 0x82 - Gated Clock Control */ -+#define _IPAQ_ASIC3_SD_CONFIG_ClockMode 0x84 /* Control clock of SD controller */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus 0x88 /* R/0: read status of SD pins */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power1 0x90 /* Power1 - manual power control */ -+ /* Power2 is at 0x92 - auto power up after card inserted */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power3 0x94 /* auto power down when card removed */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect 0x98 /* */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Slot 0xA0 /* R/O: define support slot number */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1 0x1E0 /* Could be used for gated clock (don't use) */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk2 0x1E2 /* Could be used for gated clock (don't use) */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_OutAndEnable 0x1E8 /* GPIO Output Reg. , at 0x1EA - GPIO Output Enable Reg. */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_Status 0x1EC /* GPIO Status Reg. */ -+#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3 0x1F0 /* Bit 1: double buffer/single buffer */ -+ -+#define IPAQ_ASIC3_SD_CONFIG_Command(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Command ) -+#define IPAQ_ASIC3_SD_CONFIG_Addr0(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr0 ) -+#define IPAQ_ASIC3_SD_CONFIG_Addr1(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr1 ) -+#define IPAQ_ASIC3_SD_CONFIG_IntPin(_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, IntPin ) -+#define IPAQ_ASIC3_SD_CONFIG_ClkStop(_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, ClkStop ) -+#define IPAQ_ASIC3_SD_CONFIG_ClockMode(_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, ClockMode ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_PinStatus ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power1(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power1 ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power3(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power3 ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_CardDetect ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_Slot(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Slot ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk1 ) -+#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3(_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk3 ) -+ -+#define SD_CONFIG_ -+ -+#define SD_CONFIG_COMMAND_MAE (1<<1) /* Memory access enable (set to 1 to access SD Controller) */ -+ -+#define SD_CONFIG_CLK_ENABLE_ALL 0x1f -+ -+#define SD_CONFIG_POWER1_PC_33V 0x0200 /* Set for 3.3 volts */ -+#define SD_CONFIG_POWER1_PC_OFF 0x0000 /* Turn off power */ -+ -+#define SD_CONFIG_CARDDETECTMODE_CLK ((x)&0x3) /* two bits - number of cycles for card detection */ -+ -+ -+#define _IPAQ_ASIC3_SD_CTRL_Base 0x1000 -+ -+#define IPAQ_ASIC3_SD(_b, s,x) \ -+ (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CTRL_Base + (_IPAQ_ASIC3_SD_CTRL_ ## x)))) -+ -+#define _IPAQ_ASIC3_SD_CTRL_Cmd 0x00 -+#define _IPAQ_ASIC3_SD_CTRL_Arg0 0x08 -+#define _IPAQ_ASIC3_SD_CTRL_Arg1 0x0C -+#define _IPAQ_ASIC3_SD_CTRL_StopInternal 0x10 -+#define _IPAQ_ASIC3_SD_CTRL_TransferSectorCount 0x14 -+#define _IPAQ_ASIC3_SD_CTRL_Response0 0x18 -+#define _IPAQ_ASIC3_SD_CTRL_Response1 0x1C -+#define _IPAQ_ASIC3_SD_CTRL_Response2 0x20 -+#define _IPAQ_ASIC3_SD_CTRL_Response3 0x24 -+#define _IPAQ_ASIC3_SD_CTRL_Response4 0x28 -+#define _IPAQ_ASIC3_SD_CTRL_Response5 0x2C -+#define _IPAQ_ASIC3_SD_CTRL_Response6 0x30 -+#define _IPAQ_ASIC3_SD_CTRL_Response7 0x34 -+#define _IPAQ_ASIC3_SD_CTRL_CardStatus 0x38 -+#define _IPAQ_ASIC3_SD_CTRL_BufferCtrl 0x3C -+#define _IPAQ_ASIC3_SD_CTRL_IntMaskCard 0x40 -+#define _IPAQ_ASIC3_SD_CTRL_IntMaskBuffer 0x44 -+#define _IPAQ_ASIC3_SD_CTRL_CardClockCtrl 0x48 -+#define _IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen 0x4C -+#define _IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup 0x50 -+#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus0 0x58 -+#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus1 0x5C -+#define _IPAQ_ASIC3_SD_CTRL_DataPort 0x60 -+#define _IPAQ_ASIC3_SD_CTRL_TransactionCtrl 0x68 -+#define _IPAQ_ASIC3_SD_CTRL_SoftwareReset 0x1C0 -+ -+#define IPAQ_ASIC3_SD_CTRL_Cmd(_b) IPAQ_ASIC3_SD( _b, u16, Cmd ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Arg0(_b) IPAQ_ASIC3_SD( _b, u16, Arg0 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Arg1(_b) IPAQ_ASIC3_SD( _b, u16, Arg1 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_StopInternal(_b) IPAQ_ASIC3_SD( _b, u16, StopInternal ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_TransferSectorCount(_b) IPAQ_ASIC3_SD( _b, u16, TransferSectorCount ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response0(_b) IPAQ_ASIC3_SD( _b, u16, Response0 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response1(_b) IPAQ_ASIC3_SD( _b, u16, Response1 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response2(_b) IPAQ_ASIC3_SD( _b, u16, Response2 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response3(_b) IPAQ_ASIC3_SD( _b, u16, Response3 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response4(_b) IPAQ_ASIC3_SD( _b, u16, Response4 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response5(_b) IPAQ_ASIC3_SD( _b, u16, Response5 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response6(_b) IPAQ_ASIC3_SD( _b, u16, Response6 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_Response7(_b) IPAQ_ASIC3_SD( _b, u16, Response7 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_CardStatus(_b) IPAQ_ASIC3_SD( _b, u16, CardStatus ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_BufferCtrl(_b) IPAQ_ASIC3_SD( _b, u16, BufferCtrl ) /* and error status*/ -+#define IPAQ_ASIC3_SD_CTRL_IntMaskCard(_b) IPAQ_ASIC3_SD( _b, u16, IntMaskCard ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_IntMaskBuffer(_b) IPAQ_ASIC3_SD( _b, u16, IntMaskBuffer ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_CardClockCtrl(_b) IPAQ_ASIC3_SD( _b, u16, CardClockCtrl ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen(_b) IPAQ_ASIC3_SD( _b, u16, MemCardXferDataLen ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup(_b) IPAQ_ASIC3_SD( _b, u16, MemCardOptionSetup ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_ErrorStatus0(_b) IPAQ_ASIC3_SD( _b, u16, ErrorStatus0 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_ErrorStatus1(_b) IPAQ_ASIC3_SD( _b, u16, ErrorStatus1 ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_DataPort(_b) IPAQ_ASIC3_SD( _b, u16, DataPort ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_TransactionCtrl(_b) IPAQ_ASIC3_SD( _b, u16, TransactionCtrl ) /* */ -+#define IPAQ_ASIC3_SD_CTRL_SoftwareReset(_b) IPAQ_ASIC3_SD( _b, u16, SoftwareReset ) /* */ -+ -+#define SD_CTRL_SOFTWARE_RESET_CLEAR (1<<0) -+ -+#define SD_CTRL_TRANSACTIONCONTROL_SET (1<<8) // 0x0100 -+ -+#define SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD (1<<15)// 0x8000 -+#define SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK (1<<8) // 0x0100 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_512 (1<<7) // 0x0080 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_256 (1<<6) // 0x0040 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_128 (1<<5) // 0x0020 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_64 (1<<4) // 0x0010 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_32 (1<<3) // 0x0008 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_16 (1<<2) // 0x0004 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_8 (1<<1) // 0x0002 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_4 (1<<0) // 0x0001 -+#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_2 (0<<0) // 0x0000 -+ -+#define MEM_CARD_OPTION_REQUIRED 0x000e -+#define MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(x) (((x)&0x0f)<<4) /* Four bits */ -+#define MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT (1<<14) // 0x4000 -+#define MEM_CARD_OPTION_DATA_XFR_WIDTH_1 (1<<15) // 0x8000 -+#define MEM_CARD_OPTION_DATA_XFR_WIDTH_4 (0<<15) //~0x8000 -+ -+#define SD_CTRL_COMMAND_INDEX(x) ((x)&0x3f) /* 0=CMD0, 1=CMD1, ..., 63=CMD63 */ -+#define SD_CTRL_COMMAND_TYPE_CMD (0 << 6) -+#define SD_CTRL_COMMAND_TYPE_ACMD (1 << 6) -+#define SD_CTRL_COMMAND_TYPE_AUTHENTICATION (2 << 6) -+#define SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL (0 << 8) -+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1 (4 << 8) -+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B (5 << 8) -+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2 (6 << 8) -+#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3 (7 << 8) -+#define SD_CTRL_COMMAND_DATA_PRESENT (1 << 11) -+#define SD_CTRL_COMMAND_TRANSFER_READ (1 << 12) -+#define SD_CTRL_COMMAND_TRANSFER_WRITE (0 << 12) -+#define SD_CTRL_COMMAND_MULTI_BLOCK (1 << 13) -+#define SD_CTRL_COMMAND_SECURITY_CMD (1 << 14) -+ -+#define SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12 (1 << 0) -+#define SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12 (1 << 8) -+ -+#define SD_CTRL_CARDSTATUS_RESPONSE_END (1 << 0) -+#define SD_CTRL_CARDSTATUS_RW_END (1 << 2) -+#define SD_CTRL_CARDSTATUS_CARD_REMOVED_0 (1 << 3) -+#define SD_CTRL_CARDSTATUS_CARD_INSERTED_0 (1 << 4) -+#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_0 (1 << 5) -+#define SD_CTRL_CARDSTATUS_WRITE_PROTECT (1 << 7) -+#define SD_CTRL_CARDSTATUS_CARD_REMOVED_3 (1 << 8) -+#define SD_CTRL_CARDSTATUS_CARD_INSERTED_3 (1 << 9) -+#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_3 (1 << 10) -+ -+#define SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR (1 << 0) // 0x0001 -+#define SD_CTRL_BUFFERSTATUS_CRC_ERROR (1 << 1) // 0x0002 -+#define SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR (1 << 2) // 0x0004 -+#define SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT (1 << 3) // 0x0008 -+#define SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW (1 << 4) // 0x0010 -+#define SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW (1 << 5) // 0x0020 -+#define SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT (1 << 6) // 0x0040 -+#define SD_CTRL_BUFFERSTATUS_UNK7 (1 << 7) // 0x0080 -+#define SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE (1 << 8) // 0x0100 -+#define SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE (1 << 9) // 0x0200 -+#define SD_CTRL_BUFFERSTATUS_ILLEGAL_FUNCTION (1 << 13)// 0x2000 -+#define SD_CTRL_BUFFERSTATUS_CMD_BUSY (1 << 14)// 0x4000 -+#define SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS (1 << 15)// 0x8000 -+ -+#define SD_CTRL_INTMASKCARD_RESPONSE_END (1 << 0) // 0x0001 -+#define SD_CTRL_INTMASKCARD_RW_END (1 << 2) // 0x0004 -+#define SD_CTRL_INTMASKCARD_CARD_REMOVED_0 (1 << 3) // 0x0008 -+#define SD_CTRL_INTMASKCARD_CARD_INSERTED_0 (1 << 4) // 0x0010 -+#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 (1 << 5) // 0x0020 -+#define SD_CTRL_INTMASKCARD_UNK6 (1 << 6) // 0x0040 -+#define SD_CTRL_INTMASKCARD_WRITE_PROTECT (1 << 7) // 0x0080 -+#define SD_CTRL_INTMASKCARD_CARD_REMOVED_3 (1 << 8) // 0x0100 -+#define SD_CTRL_INTMASKCARD_CARD_INSERTED_3 (1 << 9) // 0x0200 -+#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 (1 << 10)// 0x0400 -+ -+#define SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR (1 << 0) // 0x0001 -+#define SD_CTRL_INTMASKBUFFER_CRC_ERROR (1 << 1) // 0x0002 -+#define SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR (1 << 2) // 0x0004 -+#define SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT (1 << 3) // 0x0008 -+#define SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW (1 << 4) // 0x0010 -+#define SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW (1 << 5) // 0x0020 -+#define SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT (1 << 6) // 0x0040 -+#define SD_CTRL_INTMASKBUFFER_UNK7 (1 << 7) // 0x0080 -+#define SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE (1 << 8) // 0x0100 -+#define SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE (1 << 9) // 0x0200 -+#define SD_CTRL_INTMASKBUFFER_ILLEGAL_FUNCTION (1 << 13)// 0x2000 -+#define SD_CTRL_INTMASKBUFFER_CMD_BUSY (1 << 14)// 0x4000 -+#define SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS (1 << 15)// 0x8000 -+ -+#define SD_CTRL_DETAIL0_RESPONSE_CMD_ERROR (1 << 0) // 0x0001 -+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 2) // 0x0004 -+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_CMD12 (1 << 3) // 0x0008 -+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_READ_DATA (1 << 4) // 0x0010 -+#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_WRITE_CRC_STATUS (1 << 5) // 0x0020 -+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 8) // 0x0100 -+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_CMD12 (1 << 9) // 0x0200 -+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_READ_DATA (1 << 10)// 0x0400 -+#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_WRITE_CMD (1 << 11)// 0x0800 -+ -+#define SD_CTRL_DETAIL1_NO_CMD_RESPONSE (1 << 0) // 0x0001 -+#define SD_CTRL_DETAIL1_TIMEOUT_READ_DATA (1 << 4) // 0x0010 -+#define SD_CTRL_DETAIL1_TIMEOUT_CRS_STATUS (1 << 5) // 0x0020 -+#define SD_CTRL_DETAIL1_TIMEOUT_CRC_BUSY (1 << 6) // 0x0040 -+ -+#define _IPAQ_ASIC3_SDIO_CTRL_Base 0x1200 -+ -+#define IPAQ_ASIC3_SDIO(_b, s,x) \ -+ (*((volatile s *) ((_b) + _IPAQ_ASIC3_SDIO_CTRL_Base + (_IPAQ_ASIC3_SDIO_CTRL_ ## x)))) -+ -+#define _IPAQ_ASIC3_SDIO_CTRL_Cmd 0x00 -+#define _IPAQ_ASIC3_SDIO_CTRL_CardPortSel 0x04 -+#define _IPAQ_ASIC3_SDIO_CTRL_Arg0 0x08 -+#define _IPAQ_ASIC3_SDIO_CTRL_Arg1 0x0C -+#define _IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount 0x14 -+#define _IPAQ_ASIC3_SDIO_CTRL_Response0 0x18 -+#define _IPAQ_ASIC3_SDIO_CTRL_Response1 0x1C -+#define _IPAQ_ASIC3_SDIO_CTRL_Response2 0x20 -+#define _IPAQ_ASIC3_SDIO_CTRL_Response3 0x24 -+#define _IPAQ_ASIC3_SDIO_CTRL_Response4 0x28 -+#define _IPAQ_ASIC3_SDIO_CTRL_Response5 0x2C -+#define _IPAQ_ASIC3_SDIO_CTRL_Response6 0x30 -+#define _IPAQ_ASIC3_SDIO_CTRL_Response7 0x34 -+#define _IPAQ_ASIC3_SDIO_CTRL_CardStatus 0x38 -+#define _IPAQ_ASIC3_SDIO_CTRL_BufferCtrl 0x3C -+#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskCard 0x40 -+#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer 0x44 -+#define _IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen 0x4C -+#define _IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup 0x50 -+#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0 0x54 -+#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1 0x58 -+#define _IPAQ_ASIC3_SDIO_CTRL_DataPort 0x60 -+#define _IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl 0x68 -+#define _IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl 0x6C -+#define _IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl 0x70 -+#define _IPAQ_ASIC3_SDIO_CTRL_HostInformation 0x74 -+#define _IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl 0x78 -+#define _IPAQ_ASIC3_SDIO_CTRL_LEDCtrl 0x7C -+#define _IPAQ_ASIC3_SDIO_CTRL_SoftwareReset 0x1C0 -+ -+#define IPAQ_ASIC3_SDIO_CTRL_Cmd(_b) IPAQ_ASIC3_SDIO( _b, u16, Cmd ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_CardPortSel(_b) IPAQ_ASIC3_SDIO( _b, u16, CardPortSel ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Arg0(_b) IPAQ_ASIC3_SDIO( _b, u16, Arg0 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Arg1(_b) IPAQ_ASIC3_SDIO( _b, u16, Arg1 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount(_b) IPAQ_ASIC3_SDIO( _b, u16, TransferBlockCount ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response0(_b) IPAQ_ASIC3_SDIO( _b, u16, Response0 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response1(_b) IPAQ_ASIC3_SDIO( _b, u16, Response1 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response2(_b) IPAQ_ASIC3_SDIO( _b, u16, Response2 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response3(_b) IPAQ_ASIC3_SDIO( _b, u16, Response3 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response4(_b) IPAQ_ASIC3_SDIO( _b, u16, Response4 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response5(_b) IPAQ_ASIC3_SDIO( _b, u16, Response5 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response6(_b) IPAQ_ASIC3_SDIO( _b, u16, Response6 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_Response7(_b) IPAQ_ASIC3_SDIO( _b, u16, Response7 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_CardStatus(_b) IPAQ_ASIC3_SDIO( _b, u16, CardStatus ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_BufferCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, BufferCtrl ) /* and error status*/ -+#define IPAQ_ASIC3_SDIO_CTRL_IntMaskCard(_b) IPAQ_ASIC3_SDIO( _b, u16, IntMaskCard ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer(_b) IPAQ_ASIC3_SDIO( _b, u16, IntMaskBuffer ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen(_b) IPAQ_ASIC3_SDIO( _b, u16, CardXferDataLen ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup(_b) IPAQ_ASIC3_SDIO( _b, u16, CardOptionSetup ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0(_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus0 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1(_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus1 ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_DataPort(_b) IPAQ_ASIC3_SDIO( _b, u16, DataPort ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, TransactionCtrl ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, CardIntCtrl ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, ClocknWaitCtrl ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_HostInformation(_b) IPAQ_ASIC3_SDIO( _b, u16, HostInformation ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorCtrl ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_LEDCtrl(_b) IPAQ_ASIC3_SDIO( _b, u16, LEDCtrl ) /* */ -+#define IPAQ_ASIC3_SDIO_CTRL_SoftwareReset(_b) IPAQ_ASIC3_SDIO( _b, u16, SoftwareReset ) /* */ -+ -+#define IPAQ_ASIC3_MAP_SIZE 0x2000 -+ -+#endif -Index: linux-2.6.22/include/linux/backlight.h -=================================================================== ---- linux-2.6.22.orig/include/linux/backlight.h 2007-09-11 12:53:26.000000000 +0200 -+++ linux-2.6.22/include/linux/backlight.h 2007-09-11 12:53:37.000000000 +0200 -@@ -92,4 +92,11 @@ - return dev_get_drvdata(&bl_dev->dev); - } - -+struct generic_bl_info { -+ int max_intensity; -+ int default_intensity; -+ int limit_mask; -+ void (*set_bl_intensity)(int intensity); -+}; -+ - #endif -Index: linux-2.6.22/include/linux/gpiodev.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/linux/gpiodev.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,44 @@ -+#ifndef __GPIODEV_H -+#define __GPIODEV_H -+ -+#include <linux/device.h> -+#include <linux/platform_device.h> -+#include <asm/gpio.h> -+ -+/* Interface */ -+ -+/* This structure must be first member of device platform_data structure -+ of a device which provides gpiodev interface. All method pointers -+ must be non-NULL, so stubs must be used for non-implemented ones. */ -+struct gpiodev_ops { -+ int (*get)(struct device *this, unsigned gpio_no); -+ void (*set)(struct device *this, unsigned gpio_no, int val); -+ int (*to_irq)(struct device *this, unsigned gpio_no); -+}; -+ -+/* Generalized GPIO structure */ -+ -+struct gpio { -+ struct device *gpio_dev; -+ unsigned gpio_no; -+}; -+ -+/* API functions */ -+ -+static inline int gpiodev_get_value(struct gpio *gpio) -+{ -+ struct gpiodev_ops *ops = gpio->gpio_dev->platform_data; -+ return ops->get(gpio->gpio_dev, gpio->gpio_no); -+} -+static inline void gpiodev_set_value(struct gpio *gpio, int val) -+{ -+ struct gpiodev_ops *ops = gpio->gpio_dev->platform_data; -+ ops->set(gpio->gpio_dev, gpio->gpio_no, val); -+} -+static inline int gpiodev_to_irq(struct gpio *gpio) -+{ -+ struct gpiodev_ops *ops = gpio->gpio_dev->platform_data; -+ return ops->to_irq(gpio->gpio_dev, gpio->gpio_no); -+} -+ -+#endif /* __GPIODEV_H */ -Index: linux-2.6.22/include/linux/input_pda.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/linux/input_pda.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,47 @@ -+#ifndef _INPUT_PDA_H -+#define _INPUT_PDA_H -+ -+/* -+ * This is temporary virtual button key codes map -+ * for keyboardless handheld computers. -+ * Its purpose is to provide map common to all devices -+ * and known to work with current software and its bugs -+ * and misfeatures. Once issues with the software are -+ * solved, codes from input.h will be used directly -+ * (missing key definitions will be added). -+ */ -+ -+/* Some directly usable keycodes: -+KEY_POWER - Power/suspend button -+KEY_ENTER - Enter/Action/Central button on joypad -+KEY_UP -+KEY_DOWN -+KEY_LEFT -+KEY_RIGHT -+*/ -+ -+/* XXX Instead of using any values in include/linux/input.h, we have to use -+ use values < 128 due to some munging that kdrive does to get keystrokes. -+ When kdrive gets its key events from evdev instead of the console, -+ we should be able to switch to using input.h values and get rid of -+ xmodmap. */ -+ -+#define _KEY_APP1 KEY_F9 // xmodmap sees 67 + 8 = 75 -+#define _KEY_APP2 KEY_F10 // xmodmap 76 -+#define _KEY_APP3 KEY_F11 // xmodmap 95 -+#define _KEY_APP4 KEY_F12 // xmodmap 96 -+ -+#define _KEY_RECORD KEY_RO -+ -+/* It is highly recommended to use exactly 4 codes above for -+ 4 buttons the device has. This will ensure that console and -+ framebuffer applications (e.g. games) will work ok on all -+ devices. If you'd like more distinguishable names, following -+ convenience defines are provided, suiting many devices. */ -+ -+#define _KEY_CALENDAR _KEY_APP1 -+#define _KEY_CONTACTS _KEY_APP2 -+#define _KEY_MAIL _KEY_APP3 -+#define _KEY_HOMEPAGE _KEY_APP4 -+ -+#endif -Index: linux-2.6.22/include/linux/soc/asic3_base.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/linux/soc/asic3_base.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,104 @@ -+#include <asm/types.h> -+#include <linux/gpiodev.h> -+ -+/* Private API - for ASIC3 devices internal use only */ -+#define HDR_IPAQ_ASIC3_ACTION(ACTION,action,fn,FN) \ -+u32 asic3_get_gpio_ ## action ## _ ## fn (struct device *dev); \ -+void asic3_set_gpio_ ## action ## _ ## fn (struct device *dev, u32 bits, u32 val); -+ -+#define HDR_IPAQ_ASIC3_FN(fn,FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( MASK,mask,fn,FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( DIR, dir, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( OUT, out, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( LEVELTRI, trigtype, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( RISING, rising, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( LEVEL, triglevel, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_MASK, sleepmask, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_OUT, sleepout, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( BATT_FAULT_OUT, battfaultout, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( INT_STATUS, intstatus, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( ALT_FUNCTION, alt_fn, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_CONF, sleepconf, fn, FN) \ -+ HDR_IPAQ_ASIC3_ACTION ( STATUS, status, fn, FN) -+ -+/* Public API */ -+ -+#define ASIC3_GPIOA_IRQ_BASE 0 -+#define ASIC3_GPIOB_IRQ_BASE 16 -+#define ASIC3_GPIOC_IRQ_BASE 32 -+#define ASIC3_GPIOD_IRQ_BASE 48 -+#define ASIC3_LED0_IRQ 64 -+#define ASIC3_LED1_IRQ 65 -+#define ASIC3_LED2_IRQ 66 -+#define ASIC3_SPI_IRQ 67 -+#define ASIC3_SMBUS_IRQ 68 -+#define ASIC3_OWM_IRQ 69 -+ -+#define ASIC3_NR_GPIO_IRQS 64 /* 16 bits each GPIO A...D banks */ -+#define ASIC3_NR_IRQS (ASIC3_OWM_IRQ + 1) -+ -+extern int asic3_irq_base(struct device *dev); -+ -+extern void asic3_write_register(struct device *dev, unsigned int reg, -+ u32 value); -+extern u32 asic3_read_register(struct device *dev, unsigned int reg); -+ -+/* old clock api */ -+extern void asic3_set_clock_sel(struct device *dev, u32 bits, u32 val); -+extern u32 asic3_get_clock_cdex(struct device *dev); -+extern void asic3_set_clock_cdex(struct device *dev, u32 bits, u32 val); -+ -+extern void asic3_set_extcf_select(struct device *dev, u32 bits, u32 val); -+extern void asic3_set_extcf_reset(struct device *dev, u32 bits, u32 val); -+extern void asic3_set_sdhwctrl(struct device *dev, u32 bits, u32 val); -+ -+extern void asic3_set_led(struct device *dev, int led_num, int duty_time, -+ int cycle_time, int timebase); -+ -+extern int asic3_register_mmc(struct device *dev); -+extern int asic3_unregister_mmc(struct device *dev); -+ -+/* Accessors for GPIO banks */ -+HDR_IPAQ_ASIC3_FN(a, A) -+HDR_IPAQ_ASIC3_FN(b, B) -+HDR_IPAQ_ASIC3_FN(c, C) -+HDR_IPAQ_ASIC3_FN(d, D) -+ -+#define _IPAQ_ASIC3_GPIO_BANK_A 0 -+#define _IPAQ_ASIC3_GPIO_BANK_B 1 -+#define _IPAQ_ASIC3_GPIO_BANK_C 2 -+#define _IPAQ_ASIC3_GPIO_BANK_D 3 -+ -+#define ASIC3_GPIO_bit(gpio) (1 << (gpio & 0xf)) -+ -+extern int asic3_get_gpio_bit(struct device *dev, int gpio); -+extern void asic3_set_gpio_bit(struct device *dev, int gpio, int val); -+extern int asic3_gpio_get_value(struct device *dev, unsigned gpio); -+extern void asic3_gpio_set_value(struct device *dev, unsigned gpio, int val); -+ -+ -+struct tmio_mmc_hwconfig; -+ -+struct asic3_platform_data -+{ -+ // Must be first member -+ struct gpiodev_ops gpiodev_ops; -+ -+ struct { -+ u32 dir; -+ u32 init; -+ u32 sleep_mask; -+ u32 sleep_out; -+ u32 batt_fault_out; -+ u32 sleep_conf; -+ u32 alt_function; -+ } gpio_a, gpio_b, gpio_c, gpio_d; -+ -+ int irq_base; -+ unsigned int bus_shift; -+ -+ struct platform_device **child_platform_devs; -+ int num_child_platform_devs; -+ -+ struct tmio_mmc_hwconfig *tmio_mmc_hwconfig; -+}; -Index: linux-2.6.22/include/linux/soc/tmio_mmc.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/linux/soc/tmio_mmc.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,17 @@ -+#include <linux/platform_device.h> -+ -+#define MMC_CLOCK_DISABLED 0 -+#define MMC_CLOCK_ENABLED 1 -+ -+#define TMIO_WP_ALWAYS_RW ((void*)-1) -+ -+struct tmio_mmc_hwconfig { -+ void (*hwinit)(struct platform_device *sdev); -+ void (*set_mmc_clock)(struct platform_device *sdev, int state); -+ -+ /* NULL - use ASIC3 signal, -+ TMIO_WP_ALWAYS_RW - assume always R/W (e.g. miniSD) -+ otherwise - machine-specific handler */ -+ int (*mmc_get_ro)(struct platform_device *pdev); -+ short address_shift; -+}; -Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h -=================================================================== ---- linux-2.6.22.orig/include/asm-arm/arch-pxa/pxa-regs.h 2007-09-11 12:53:34.000000000 +0200 -+++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h 2007-09-11 12:53:37.000000000 +0200 -@@ -2043,6 +2043,8 @@ - #define LDCMD_SOFINT (1 << 22) - #define LDCMD_EOFINT (1 << 21) - -+#define LCCR4_13M_PCD_EN (1<<25) /* 13M PCD enable */ -+#define LCCR4_PCDDIV (1<<31) /* PCD selection */ - - #define LCCR5_SOFM1 (1<<0) /* Start Of Frame Mask for Overlay 1 (channel 1) */ - #define LCCR5_SOFM2 (1<<1) /* Start Of Frame Mask for Overlay 2 (channel 2) */ -Index: linux-2.6.22/drivers/mmc/host/Kconfig -=================================================================== ---- linux-2.6.22.orig/drivers/mmc/host/Kconfig 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/drivers/mmc/host/Kconfig 2007-09-11 12:53:37.000000000 +0200 -@@ -100,3 +100,9 @@ - To compile this driver as a module, choose M here: the - module will be called tifm_sd. - -+config MMC_ASIC3 -+ tristate "HTC ASIC3 SD/MMC support" -+ depends on MMC && HTC_ASIC3 -+ help -+ This provides support for the ASIC3 SD/MMC controller, used -+ in the iPAQ hx4700 and others. -Index: linux-2.6.22/drivers/mmc/host/Makefile -=================================================================== ---- linux-2.6.22.orig/drivers/mmc/host/Makefile 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/drivers/mmc/host/Makefile 2007-09-11 12:53:37.000000000 +0200 -@@ -15,4 +15,4 @@ - obj-$(CONFIG_MMC_OMAP) += omap.o - obj-$(CONFIG_MMC_AT91) += at91_mci.o - obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o -- -+obj-$(CONFIG_MMC_ASIC3) += asic3_mmc.o -Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/mmc/host/asic3_mmc.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,900 @@ -+/* Note that this driver can likely be merged into the tmio driver, so -+ * consider this code temporary. It works, though. -+ */ -+/* -+ * linux/drivers/mmc/asic3_mmc.c -+ * -+ * Copyright (c) 2005 SDG Systems, LLC -+ * -+ * based on tmio_mmc.c -+ * Copyright (C) 2004 Ian Molton -+ * -+ * Refactored to support all ASIC3 devices, 2006 Paul Sokolovsky -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * Driver for the SD / SDIO cell found in: -+ * -+ * TC6393XB -+ * -+ * This driver draws mainly on scattered spec sheets, Reverse engineering -+ * of the toshiba e800 SD driver and some parts of the 2.4 ASIC3 driver (4 bit -+ * support). -+ * -+ * Supports MMC 1 bit transfers and SD 1 and 4 bit modes. -+ * -+ * TODO: -+ * Eliminate FIXMEs -+ * SDIO support -+ * Power management -+ * Handle MMC errors (at all) -+ * -+ */ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/init.h> -+#include <linux/ioport.h> -+#include <linux/platform_device.h> -+#include <linux/interrupt.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/err.h> -+#include <linux/mmc/mmc.h> -+#include <linux/mmc/host.h> -+#include <linux/mmc/card.h> -+//#include <linux/mmc/protocol.h> -+#include <linux/mmc/sd.h> -+#include <linux/scatterlist.h> -+//#include <linux/soc-old.h> -+#include <linux/soc/asic3_base.h> -+#include <linux/soc/tmio_mmc.h> -+ -+#include <asm/io.h> -+#include <asm/irq.h> -+#include <asm/mach/irq.h> -+#include <linux/clk.h> -+#include <asm/mach-types.h> -+ -+#include <asm/hardware/ipaq-asic3.h> -+#include "asic3_mmc.h" -+ -+struct asic3_mmc_host { -+ void *ctl_base; -+ struct device *asic3_dev; /* asic3 device */ -+ struct tmio_mmc_hwconfig *hwconfig; /* HW config data/handlers, guaranteed != NULL */ -+ unsigned long bus_shift; -+ struct mmc_command *cmd; -+ struct mmc_request *mrq; -+ struct mmc_data *data; -+ struct mmc_host *mmc; -+ int irq; -+ unsigned short clock_for_sd; -+ -+ /* I/O related stuff */ -+ struct scatterlist *sg_ptr; -+ unsigned int sg_len; -+ unsigned int sg_off; -+}; -+ -+static void -+mmc_finish_request(struct asic3_mmc_host *host) -+{ -+ struct mmc_request *mrq = host->mrq; -+ -+ /* Write something to end the command */ -+ host->mrq = NULL; -+ host->cmd = NULL; -+ host->data = NULL; -+ -+ mmc_request_done(host->mmc, mrq); -+} -+ -+ -+#define ASIC3_MMC_REG(host, block, reg) (*((volatile u16 *) ((host->ctl_base) + ((_IPAQ_ASIC3_## block ## _Base + _IPAQ_ASIC3_ ## block ## _ ## reg) >> (2 - host->bus_shift))) )) -+ -+static void -+mmc_start_command(struct asic3_mmc_host *host, struct mmc_command *cmd) -+{ -+ struct mmc_data *data = host->data; -+ int c = cmd->opcode; -+ -+ DBG("[1;33mOpcode: %d[0m, base: %p\n", cmd->opcode, host->ctl_base); -+ -+ if(cmd->opcode == MMC_STOP_TRANSMISSION) { -+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12; -+ cmd->resp[0] = cmd->opcode; -+ cmd->resp[1] = 0; -+ cmd->resp[2] = 0; -+ cmd->resp[3] = 0; -+ cmd->resp[4] = 0; -+ return; -+ } -+ -+ switch(cmd->flags & 0x1f) { -+ case MMC_RSP_NONE: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL; break; -+ case MMC_RSP_R1: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1; break; -+ case MMC_RSP_R1B: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B; break; -+ case MMC_RSP_R2: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2; break; -+ case MMC_RSP_R3: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3; break; -+ default: -+ DBG("Unknown response type %d\n", cmd->flags & 0x1f); -+ break; -+ } -+ -+ host->cmd = cmd; -+ -+ if(cmd->opcode == MMC_APP_CMD) { -+ c |= APP_CMD; -+ } -+ if (cmd->opcode == MMC_GO_IDLE_STATE) { -+ c |= (3 << 8); /* This was removed from ipaq-asic3.h for some reason */ -+ } -+ if(data) { -+ c |= SD_CTRL_COMMAND_DATA_PRESENT; -+ if(data->blocks > 1) { -+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12; -+ c |= SD_CTRL_COMMAND_MULTI_BLOCK; -+ } -+ if(data->flags & MMC_DATA_READ) { -+ c |= SD_CTRL_COMMAND_TRANSFER_READ; -+ } -+ /* MMC_DATA_WRITE does not require a bit to be set */ -+ } -+ -+ /* Enable the command and data interrupts */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~( -+ SD_CTRL_INTMASKCARD_RESPONSE_END -+ | SD_CTRL_INTMASKCARD_RW_END -+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_0 -+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_0 -+#if 0 -+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_3 -+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_3 -+#endif -+ ); -+ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) = ~( -+ SD_CTRL_INTMASKBUFFER_UNK7 -+ | SD_CTRL_INTMASKBUFFER_CMD_BUSY -+#if 0 -+ | SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR -+ | SD_CTRL_INTMASKBUFFER_CRC_ERROR -+ | SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR -+ | SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT -+ | SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW -+ | SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW -+ | SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT -+ | SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE -+ | SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE -+ | SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS -+#endif -+ ); -+ -+ /* Send the command */ -+ ASIC3_MMC_REG(host, SD_CTRL, Arg1) = cmd->arg >> 16; -+ ASIC3_MMC_REG(host, SD_CTRL, Arg0) = cmd->arg & 0xffff; -+ ASIC3_MMC_REG(host, SD_CTRL, Cmd) = c; -+} -+ -+/* This chip always returns (at least?) as much data as you ask for. I'm -+ * unsure what happens if you ask for less than a block. This should be looked -+ * into to ensure that a funny length read doesnt mess up the controller data -+ * state machine. -+ * -+ * Aric: Statement above may not apply to ASIC3. -+ * -+ * FIXME - this chip cannot do 1 and 2 byte data requests in 4 bit mode -+ * -+ * Aric: Statement above may not apply to ASIC3. -+ */ -+ -+static struct tasklet_struct mmc_data_read_tasklet; -+ -+static void -+mmc_data_transfer(unsigned long h) -+{ -+ struct asic3_mmc_host *host = (struct asic3_mmc_host *)h; -+ struct mmc_data *data = host->data; -+ unsigned short *buf; -+ int count; -+ /* unsigned long flags; */ -+ -+ if(!data){ -+ printk(KERN_WARNING DRIVER_NAME ": Spurious Data IRQ\n"); -+ return; -+ } -+ -+ /* local_irq_save(flags); */ -+ /* buf = kmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ); */ -+ buf = kmap(host->sg_ptr->page); -+ buf += host->sg_ptr->offset/2 + host->sg_off/2; -+ -+ /* -+ * Ensure we dont read more than one block. The chip will interrupt us -+ * When the next block is available. -+ */ -+ count = host->sg_ptr->length - host->sg_off; -+ if(count > data->blksz) { -+ count = data->blksz; -+ } -+ -+ DBG("count: %08x, page: %p, offset: %08x flags %08x\n", -+ count, host->sg_ptr->page, host->sg_off, data->flags); -+ -+ host->sg_off += count; -+ -+ /* Transfer the data */ -+ if(data->flags & MMC_DATA_READ) { -+ while(count > 0) { -+ /* Read two bytes from SD/MMC controller. */ -+ *buf = ASIC3_MMC_REG(host, SD_CTRL, DataPort); -+ buf++; -+ count -= 2; -+ } -+ //flush_dcache_page(host->sg_ptr->page); -+ } else { -+ while(count > 0) { -+ /* Write two bytes to SD/MMC controller. */ -+ ASIC3_MMC_REG(host, SD_CTRL, DataPort) = *buf; -+ buf++; -+ count -= 2; -+ } -+ } -+ -+ /* kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ); */ -+ kunmap(host->sg_ptr->page); -+ /* local_irq_restore(flags); */ -+ if(host->sg_off == host->sg_ptr->length) { -+ host->sg_ptr++; -+ host->sg_off = 0; -+ --host->sg_len; -+ } -+ -+ return; -+} -+ -+static void -+mmc_data_end_irq(struct asic3_mmc_host *host) -+{ -+ struct mmc_data *data = host->data; -+ -+ host->data = NULL; -+ -+ if(!data){ -+ printk(KERN_WARNING DRIVER_NAME ": Spurious data end IRQ\n"); -+ return; -+ } -+ -+ if (data->error == MMC_ERR_NONE) { -+ data->bytes_xfered = data->blocks * data->blksz; -+ } else { -+ data->bytes_xfered = 0; -+ } -+ -+ DBG("Completed data request\n"); -+ -+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = 0; -+ -+ /* Make sure read enable interrupt and write enable interrupt are disabled */ -+ if(data->flags & MMC_DATA_READ) { -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) |= SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE; -+ } else { -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) |= SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE; -+ } -+ -+ mmc_finish_request(host); -+} -+ -+static void -+mmc_cmd_irq(struct asic3_mmc_host *host, unsigned int buffer_stat) -+{ -+ struct mmc_command *cmd = host->cmd; -+ u8 *buf = (u8 *)cmd->resp; -+ u16 data; -+ -+ if(!host->cmd) { -+ printk(KERN_WARNING DRIVER_NAME ": Spurious CMD irq\n"); -+ return; -+ } -+ -+ host->cmd = NULL; -+ if(cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) { -+ /* R2 */ -+ buf[12] = 0xff; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response0); -+ buf[13] = data & 0xff; -+ buf[14] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response1); -+ buf[15] = data & 0xff; -+ buf[8] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response2); -+ buf[9] = data & 0xff; -+ buf[10] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response3); -+ buf[11] = data & 0xff; -+ buf[4] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response4); -+ buf[5] = data & 0xff; -+ buf[6] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response5); -+ buf[7] = data & 0xff; -+ buf[0] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response6); -+ buf[1] = data & 0xff; -+ buf[2] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response7); -+ buf[3] = data & 0xff; -+ } else if(cmd->flags & MMC_RSP_PRESENT) { -+ /* R1, R1B, R3 */ -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response0); -+ buf[0] = data & 0xff; -+ buf[1] = data >> 8; -+ data = ASIC3_MMC_REG(host, SD_CTRL, Response1); -+ buf[2] = data & 0xff; -+ buf[3] = data >> 8; -+ } -+ DBG("Response: %08x %08x %08x %08x\n", cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); -+ -+ if(buffer_stat & SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT) { -+ cmd->error = MMC_ERR_TIMEOUT; -+ } else if((buffer_stat & SD_CTRL_BUFFERSTATUS_CRC_ERROR) && (cmd->flags & MMC_RSP_CRC)) { -+ cmd->error = MMC_ERR_BADCRC; -+ } else if(buffer_stat & -+ ( -+ SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS -+ | SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR -+ | SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR -+ | SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW -+ | SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW -+ | SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT -+ ) -+ ) { -+ DBG("Buffer status ERROR 0x%04x - inside check buffer\n", buffer_stat); -+ DBG("detail0 error status 0x%04x\n", ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus0)); -+ DBG("detail1 error status 0x%04x\n", ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus1)); -+ cmd->error = MMC_ERR_FAILED; -+ } -+ -+ if(cmd->error == MMC_ERR_NONE) { -+ switch (cmd->opcode) { -+ case SD_APP_SET_BUS_WIDTH: -+ if(cmd->arg == SD_BUS_WIDTH_4) { -+ host->clock_for_sd = SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD; -+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) = -+ MEM_CARD_OPTION_REQUIRED -+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14) -+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT -+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_4; -+ } else { -+ host->clock_for_sd = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) = -+ MEM_CARD_OPTION_REQUIRED -+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14) -+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT -+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_1; -+ } -+ break; -+ case MMC_SELECT_CARD: -+ if((cmd->arg >> 16) == 0) { -+ /* We have been deselected. */ -+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) = -+ MEM_CARD_OPTION_REQUIRED -+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14) -+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT -+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_1; -+ } -+ } -+ } -+ -+ /* -+ * If there is data to handle we enable data IRQs here, and we will -+ * ultimatley finish the request in the mmc_data_end_irq handler. -+ */ -+ if(host->data && (cmd->error == MMC_ERR_NONE)){ -+ if(host->data->flags & MMC_DATA_READ) { -+ /* Enable the read enable interrupt */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &= -+ ~SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE; -+ } else { -+ /* Enable the write enable interrupt */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &= -+ ~SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE; -+ } -+ } else { -+ /* There's no data, or we encountered an error, so finish now. */ -+ mmc_finish_request(host); -+ } -+ -+ return; -+} -+ -+static void hwinit2_irqsafe(struct asic3_mmc_host *host); -+ -+static irqreturn_t -+mmc_irq(int irq, void *irq_desc) -+{ -+ struct asic3_mmc_host *host; -+ unsigned int breg, bmask, bstatus, creg, cmask, cstatus; -+ -+ host = irq_desc; -+ -+ /* asic3 bstatus has errors */ -+ bstatus = ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl); -+ bmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer); -+ cstatus = ASIC3_MMC_REG(host, SD_CTRL, CardStatus); -+ cmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard); -+ breg = bstatus & ~bmask & ~DONT_CARE_BUFFER_BITS; -+ creg = cstatus & ~cmask & ~DONT_CARE_CARD_BITS; -+ -+ if (!breg && !creg) { -+ /* This occurs sometimes for no known reason. It doesn't hurt -+ * anything, so I don't print it. */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &= ~breg; -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) &= ~creg; -+ goto out; -+ } -+ -+ while (breg || creg) { -+ -+ /* XXX TODO: Need to handle errors in breg here. */ -+ -+ /* -+ * Card insert/remove. The mmc controlling code is stateless. That -+ * is, it doesn't care if it was an insert or a remove. It treats -+ * both the same. -+ */ -+ /* XXX Asic3 has _3 versions of these status bits, too, for a second slot, perhaps? */ -+ if (creg & (SD_CTRL_CARDSTATUS_CARD_INSERTED_0 | SD_CTRL_CARDSTATUS_CARD_REMOVED_0)) { -+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &= -+ ~(SD_CTRL_CARDSTATUS_CARD_REMOVED_0 | SD_CTRL_CARDSTATUS_CARD_INSERTED_0); -+ if(creg & SD_CTRL_CARDSTATUS_CARD_INSERTED_0) { -+ hwinit2_irqsafe(host); -+ } -+ mmc_detect_change(host->mmc,1); -+ } -+ -+ /* Command completion */ -+ if (creg & SD_CTRL_CARDSTATUS_RESPONSE_END) { -+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &= -+ ~(SD_CTRL_CARDSTATUS_RESPONSE_END); -+ mmc_cmd_irq(host, bstatus); -+ } -+ -+ /* Data transfer */ -+ if (breg & (SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE | SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE)) { -+ ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) &= -+ ~(SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE | SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE); -+ tasklet_schedule(&mmc_data_read_tasklet); -+ } -+ -+ /* Data transfer completion */ -+ if (creg & SD_CTRL_CARDSTATUS_RW_END) { -+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &= ~(SD_CTRL_CARDSTATUS_RW_END); -+ mmc_data_end_irq(host); -+ } -+ -+ /* Check status - keep going until we've handled it all */ -+ bstatus = ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl); -+ bmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer); -+ cstatus = ASIC3_MMC_REG(host, SD_CTRL, CardStatus); -+ cmask = ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard); -+ breg = bstatus & ~bmask & ~DONT_CARE_BUFFER_BITS; -+ creg = cstatus & ~cmask & ~DONT_CARE_CARD_BITS; -+ } -+ -+out: -+ /* Ensure all interrupt sources are cleared */ -+ ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) = 0; -+ return IRQ_HANDLED; -+} -+ -+static void -+mmc_start_data(struct asic3_mmc_host *host, struct mmc_data *data) -+{ -+ DBG("setup data transfer: blocksize %08x nr_blocks %d, page: %08x, offset: %08x\n", data->blksz, -+ data->blocks, (int)data->sg->page, data->sg->offset); -+ -+ host->sg_len = data->sg_len; -+ host->sg_ptr = data->sg; -+ host->sg_off = 0; -+ host->data = data; -+ -+ /* Set transfer length and blocksize */ -+ ASIC3_MMC_REG(host, SD_CTRL, TransferSectorCount) = data->blocks; -+ ASIC3_MMC_REG(host, SD_CTRL, MemCardXferDataLen) = data->blksz; -+} -+ -+/* Process requests from the MMC layer */ -+static void -+mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct asic3_mmc_host *host = mmc_priv(mmc); -+ -+ WARN_ON(host->mrq != NULL); -+ -+ host->mrq = mrq; -+ -+ /* If we're performing a data request we need to setup some -+ extra information */ -+ if(mrq->data) { -+ mmc_start_data(host, mrq->data); -+ } -+ -+ mmc_start_command(host, mrq->cmd); -+} -+ -+/* Set MMC clock / power. -+ * Note: This controller uses a simple divider scheme therefore it cannot run -+ * a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as MMC -+ * wont run that fast, it has to be clocked at 12MHz which is the next slowest -+ * setting. This is likely not an issue because we are doing single 16-bit -+ * writes for data I/O. -+ */ -+static void -+mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct asic3_mmc_host *host = mmc_priv(mmc); -+ u32 clk = 0; -+ -+ DBG("clock %uHz busmode %u powermode %u Vdd %u\n", -+ ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); -+ -+ if (ios->clock) { -+ clk = 0x80; /* slowest by default */ -+ if(ios->clock >= 24000000 / 256) clk >>= 1; -+ if(ios->clock >= 24000000 / 128) clk >>= 1; -+ if(ios->clock >= 24000000 / 64) clk >>= 1; -+ if(ios->clock >= 24000000 / 32) clk >>= 1; -+ if(ios->clock >= 24000000 / 16) clk >>= 1; -+ if(ios->clock >= 24000000 / 8) clk >>= 1; -+ if(ios->clock >= 24000000 / 4) clk >>= 1; -+ if(ios->clock >= 24000000 / 2) clk >>= 1; -+ if(ios->clock >= 24000000 / 1) clk >>= 1; -+ if(clk == 0) { /* For fastest speed we disable the divider. */ -+ ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 0; -+ } else { -+ ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 1; -+ } -+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = -+ host->clock_for_sd -+ | SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK -+ | clk; -+ msleep(10); -+ } else { -+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0; -+ } -+ -+ switch (ios->power_mode) { -+ case MMC_POWER_OFF: -+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = 0; -+ msleep(1); -+ break; -+ case MMC_POWER_UP: -+ break; -+ case MMC_POWER_ON: -+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = SD_CONFIG_POWER1_PC_33V; -+ msleep(20); -+ break; -+ } -+} -+ -+static int -+mmc_get_ro(struct mmc_host *mmc) -+{ -+ struct asic3_mmc_host *host = mmc_priv(mmc); -+ -+ /* Call custom handler for RO status */ -+ if(host->hwconfig->mmc_get_ro) { -+ /* Special case for cards w/o WP lock (like miniSD) */ -+ if (host->hwconfig->mmc_get_ro == (void*)-1) { -+ return 0; -+ } else { -+ struct platform_device *pdev = to_platform_device(mmc_dev(mmc)); -+ return host->hwconfig->mmc_get_ro(pdev); -+ } -+ } -+ -+ /* WRITE_PROTECT is active low */ -+ return (ASIC3_MMC_REG(host, SD_CTRL, CardStatus) & SD_CTRL_CARDSTATUS_WRITE_PROTECT)?0:1; -+} -+ -+static struct mmc_host_ops mmc_ops = { -+ .request = mmc_request, -+ .set_ios = mmc_set_ios, -+ .get_ro = mmc_get_ro, -+}; -+ -+static void -+hwinit2_irqsafe(struct asic3_mmc_host *host) -+{ -+ ASIC3_MMC_REG(host, SD_CONFIG, Addr1) = 0x0000; -+ ASIC3_MMC_REG(host, SD_CONFIG, Addr0) = 0x0800; -+ -+ ASIC3_MMC_REG(host, SD_CONFIG, ClkStop) = SD_CONFIG_CLKSTOP_ENABLE_ALL; -+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_CardDetect) = 2; -+ ASIC3_MMC_REG(host, SD_CONFIG, Command) = SD_CONFIG_COMMAND_MAE; -+ -+ ASIC3_MMC_REG(host, SD_CTRL, SoftwareReset) = 0; /* reset on */ -+ mdelay(2); -+ -+ ASIC3_MMC_REG(host, SD_CTRL, SoftwareReset) = 1; /* reset off */ -+ mdelay(2); -+ -+ ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) = -+ MEM_CARD_OPTION_REQUIRED -+ | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14) -+ | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT -+ | MEM_CARD_OPTION_DATA_XFR_WIDTH_1 -+ ; -+ host->clock_for_sd = 0; -+ -+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, CardStatus) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus0) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus1) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = 0; -+ -+ ASIC3_MMC_REG(host, SDIO_CTRL, ClocknWaitCtrl) = 0x100; -+ /* *((unsigned short *)(((char *)host->ctl_base) + 0x938)) = 0x100; */ -+ -+ ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 0; -+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0; -+ -+ mdelay(1); -+ -+ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~( -+ SD_CTRL_INTMASKCARD_RESPONSE_END -+ | SD_CTRL_INTMASKCARD_RW_END -+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_0 -+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_0 -+#if 0 -+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_3 -+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_3 -+#endif -+ ) -+ ; /* check */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) = 0xffff; /* IRQs off */ -+ -+ /* -+ * ASIC3_MMC_REG(host, SD_CTRL, TransactionCtrl) = SD_CTRL_TRANSACTIONCONTROL_SET; -+ * Wince has 0x1000 -+ */ -+ /* ASIC3_MMC_REG(host, SD_CTRL, TransactionCtrl) = 0x1000; */ -+ -+ -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SDPWR, ASIC3_SDHWCTRL_SDPWR); /* turn on power at controller(?) */ -+ -+} -+ -+static void -+hwinit(struct asic3_mmc_host *host, struct platform_device *pdev) -+{ -+ /* Call custom handler for enabling clock (if needed) */ -+ if(host->hwconfig->set_mmc_clock) -+ host->hwconfig->set_mmc_clock(pdev, MMC_CLOCK_ENABLED); -+ -+ /* Not sure if it must be done bit by bit, but leaving as-is */ -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_LEVCD, ASIC3_SDHWCTRL_LEVCD); -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_LEVWP, ASIC3_SDHWCTRL_LEVWP); -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, 0); -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_PCLR, 0); -+ -+ asic3_set_clock_cdex (host->asic3_dev, -+ CLOCK_CDEX_EX1 | CLOCK_CDEX_EX0, CLOCK_CDEX_EX1 | CLOCK_CDEX_EX0); -+ msleep(1); -+ -+ asic3_set_clock_sel (host->asic3_dev, -+ CLOCK_SEL_SD_HCLK_SEL | CLOCK_SEL_SD_BCLK_SEL, -+ CLOCK_SEL_SD_HCLK_SEL | 0); /* ? */ -+ -+ asic3_set_clock_cdex (host->asic3_dev, -+ CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS, -+ CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS); -+ msleep(1); -+ -+ asic3_set_extcf_select(host->asic3_dev, ASIC3_EXTCF_SD_MEM_ENABLE, ASIC3_EXTCF_SD_MEM_ENABLE); -+ -+ /* Long Delay */ -+ if( !machine_is_h4700()) -+ msleep(500); -+ -+ hwinit2_irqsafe(host); -+} -+ -+#ifdef CONFIG_PM -+static int -+mmc_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(pdev); -+ struct asic3_mmc_host *host = mmc_priv(mmc); -+ int ret; -+ -+ ret = mmc_suspend_host(mmc, state); -+ -+ if (ret) { -+ printk(KERN_ERR DRIVER_NAME ": Could not suspend MMC host, hardware not suspended"); -+ return ret; -+ } -+ -+ /* disable the card insert / remove interrupt while sleeping */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~( -+ SD_CTRL_INTMASKCARD_RESPONSE_END -+ | SD_CTRL_INTMASKCARD_RW_END); -+ -+ /* disable clock */ -+ ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0; -+ ASIC3_MMC_REG(host, SD_CONFIG, ClkStop) = 0; -+ -+ /* power down */ -+ ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = 0; -+ -+ asic3_set_clock_cdex (host->asic3_dev, -+ CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS, 0); -+ -+ /* disable core clock */ -+ if(host->hwconfig->set_mmc_clock) -+ host->hwconfig->set_mmc_clock(pdev, MMC_CLOCK_DISABLED); -+ -+ /* Put in suspend mode */ -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, ASIC3_SDHWCTRL_SUSPEND); -+ return 0; -+} -+ -+static int -+mmc_resume(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(pdev); -+ struct asic3_mmc_host *host = mmc_priv(mmc); -+ -+ printk(KERN_INFO "%s: starting resume\n", DRIVER_NAME); -+ -+ asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, 0); -+ hwinit(host, pdev); -+ -+ /* re-enable card remove / insert interrupt */ -+ ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~( -+ SD_CTRL_INTMASKCARD_RESPONSE_END -+ | SD_CTRL_INTMASKCARD_RW_END -+ | SD_CTRL_INTMASKCARD_CARD_REMOVED_0 -+ | SD_CTRL_INTMASKCARD_CARD_INSERTED_0 ); -+ -+ mmc_resume_host(mmc); -+ -+ printk(KERN_INFO "%s: finished resume\n", DRIVER_NAME); -+ return 0; -+} -+#endif -+ -+static int -+mmc_probe(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc; -+ struct asic3_mmc_host *host = NULL; -+ int retval = 0; -+ struct tmio_mmc_hwconfig *mmc_config = (struct tmio_mmc_hwconfig *)pdev->dev.platform_data; -+ -+ /* bus_shift is mandatory */ -+ if (!mmc_config) { -+ printk(KERN_ERR DRIVER_NAME ": Invalid configuration\n"); -+ return -EINVAL; -+ } -+ -+ mmc = mmc_alloc_host(sizeof(struct asic3_mmc_host) + 128, &pdev->dev); -+ if (!mmc) { -+ retval = -ENOMEM; -+ goto exceptional_return; -+ } -+ -+ host = mmc_priv(mmc); -+ host->mmc = mmc; -+ platform_set_drvdata(pdev, mmc); -+ -+ host->ctl_base = 0; -+ host->hwconfig = mmc_config; -+ host->bus_shift = mmc_config->address_shift; -+ host->asic3_dev = pdev->dev.parent; -+ host->clock_for_sd = 0; -+ -+ tasklet_init(&mmc_data_read_tasklet, mmc_data_transfer, (unsigned long)host); -+ -+ host->ctl_base = ioremap_nocache ((unsigned long)pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start); -+ if(!host->ctl_base){ -+ printk(KERN_ERR DRIVER_NAME ": Could not map ASIC3 SD controller\n"); -+ retval = -ENODEV; -+ goto exceptional_return; -+ } -+ -+ printk(DRIVER_NAME ": ASIC3 MMC/SD Driver, controller at 0x%lx\n", (unsigned long)pdev->resource[0].start); -+ -+ mmc->ops = &mmc_ops; -+ mmc->caps = MMC_CAP_4_BIT_DATA; -+ mmc->f_min = 46875; /* ARIC: not sure what these should be */ -+ mmc->f_max = 24000000; /* ARIC: not sure what these should be */ -+ mmc->ocr_avail = MMC_VDD_32_33; -+ -+ hwinit(host, pdev); -+ -+ -+ host->irq = pdev->resource[1].start; -+ -+ retval = request_irq(host->irq, mmc_irq, 0, DRIVER_NAME, host); -+ if(retval) { -+ printk(KERN_ERR DRIVER_NAME ": Unable to get interrupt\n"); -+ retval = -ENODEV; -+ goto exceptional_return; -+ } -+ set_irq_type(host->irq, IRQT_FALLING); -+ -+ mmc_add_host(mmc); -+ -+#ifdef CONFIG_PM -+ // resume_timer.function = resume_timer_callback; -+ // resume_timer.data = 0; -+ // init_timer(&resume_timer); -+#endif -+ -+ return 0; -+ -+exceptional_return: -+ if (mmc) { -+ mmc_free_host(mmc); -+ } -+ if(host && host->ctl_base) iounmap(host->ctl_base); -+ return retval; -+} -+ -+static int -+mmc_remove(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ if (mmc) { -+ struct asic3_mmc_host *host = mmc_priv(mmc); -+ mmc_remove_host(mmc); -+ free_irq(host->irq, host); -+ /* FIXME - we might want to consider stopping the chip here... */ -+ iounmap(host->ctl_base); -+ mmc_free_host(mmc); /* FIXME - why does this call hang? */ -+ } -+ return 0; -+} -+ -+/* ------------------- device registration ----------------------- */ -+ -+static struct platform_driver mmc_asic3_driver = { -+ .driver = { -+ .name = DRIVER_NAME, -+ }, -+ .probe = mmc_probe, -+ .remove = mmc_remove, -+#ifdef CONFIG_PM -+ .suspend = mmc_suspend, -+ .resume = mmc_resume, -+#endif -+}; -+ -+static int __init mmc_init(void) -+{ -+ return platform_driver_register(&mmc_asic3_driver); -+} -+ -+static void __exit mmc_exit(void) -+{ -+ platform_driver_unregister(&mmc_asic3_driver); -+} -+ -+late_initcall(mmc_init); -+module_exit(mmc_exit); -+ -+MODULE_DESCRIPTION("HTC ASIC3 SD/MMC driver"); -+MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC"); -+MODULE_LICENSE("GPL"); -+ -Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/mmc/host/asic3_mmc.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,25 @@ -+#ifndef __ASIC3_MMC_H -+#define __ASIC3_MMC_H -+ -+#define DRIVER_NAME "asic3_mmc" -+ -+#ifdef CONFIG_MMC_DEBUG -+#define DBG(x...) printk(DRIVER_NAME ": " x) -+#else -+#define DBG(x...) do { } while (0) -+#endif -+ -+/* Response types */ -+#define APP_CMD 0x0040 -+ -+#define SD_CONFIG_CLKSTOP_ENABLE_ALL 0x1f -+ -+#define DONT_CARE_CARD_BITS ( \ -+ SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 \ -+ | SD_CTRL_INTMASKCARD_WRITE_PROTECT \ -+ | SD_CTRL_INTMASKCARD_UNK6 \ -+ | SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 \ -+ ) -+#define DONT_CARE_BUFFER_BITS ( SD_CTRL_INTMASKBUFFER_UNK7 | SD_CTRL_INTMASKBUFFER_CMD_BUSY ) -+ -+#endif // __ASIC3_MMC_H -Index: linux-2.6.22/drivers/input/keyboard/Makefile -=================================================================== ---- linux-2.6.22.orig/drivers/input/keyboard/Makefile 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/drivers/input/keyboard/Makefile 2007-09-11 12:53:37.000000000 +0200 -@@ -21,4 +21,4 @@ - obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o - obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o - obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o -- -+obj-$(CONFIG_KEYBOARD_ASIC3) += asic3_keys.o -Index: linux-2.6.22/drivers/input/keyboard/asic3_keys.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/drivers/input/keyboard/asic3_keys.c 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,131 @@ -+/* -+ * Generic buttons driver for ASIC3 SoC. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ * Copyright (C) 2003 Joshua Wise -+ * Copyright (C) 2005 Pawel Kolodziejski -+ * Copyright (C) 2006 Paul Sokolovsky -+ * -+ */ -+ -+#include <linux/input.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/platform_device.h> -+#include <linux/irq.h> -+#include <linux/soc/asic3_base.h> -+#include <asm/mach/arch.h> -+#include <asm/mach/map.h> -+#include <asm/arch/irqs.h> -+#include <asm/hardware.h> -+#include <asm/hardware/ipaq-asic3.h> -+#include <asm/hardware/asic3_keys.h> -+ -+static irqreturn_t asic3_keys_asic_handle(int irq, void *data) -+{ -+ struct asic3_keys_platform_data *pdata = data; -+ int i, base_irq; -+ -+ base_irq = asic3_irq_base(pdata->asic3_dev); -+ for (i = 0; i < pdata->nbuttons; i++) { -+ struct asic3_keys_button *b = &pdata->buttons[i]; -+ if ((base_irq + b->gpio) == irq) { -+ int state = !!asic3_gpio_get_value(pdata->asic3_dev, b->gpio); -+ -+ if (pdata->buttons[i].type == EV_SW) -+ input_report_switch(pdata->input, pdata->buttons[i].keycode, state ^ b->active_low); -+ else -+ input_report_key(pdata->input, b->keycode, state ^ b->active_low); -+ input_sync(pdata->input); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int __devinit asic3_keys_probe(struct platform_device *pdev) -+{ -+ struct asic3_keys_platform_data *pdata = pdev->dev.platform_data; -+ int i, base_irq; -+ int j, ret; -+ -+ pdata->input = input_allocate_device(); -+ -+ base_irq = asic3_irq_base(pdata->asic3_dev); -+ -+ for (i = 0; i < pdata->nbuttons; i++) { -+ struct asic3_keys_button *b = &pdata->buttons[i]; -+ set_bit(b->keycode, pdata->input->keybit); -+ ret=request_irq(base_irq + b->gpio, asic3_keys_asic_handle, SA_SAMPLE_RANDOM, b->desc, pdata); -+ if (ret) -+ { -+ printk(KERN_NOTICE "Failed to allocate asic3_keys irq=%d.\n",b->gpio); -+ -+ for(j=0; j<i ; j++) -+ free_irq(base_irq + pdata->buttons[i].gpio, NULL); -+ -+ input_unregister_device (pdata->input); -+ -+ return -ENODEV; -+ } -+ -+ set_irq_type(base_irq + b->gpio, IRQT_BOTHEDGE); -+ if (pdata->buttons[i].type == EV_SW) { -+ pdata->input->evbit[0] |= BIT(EV_SW); -+ set_bit(b->keycode, pdata->input->swbit); -+ } else { -+ pdata->input->evbit[0] |= BIT(EV_KEY); -+ set_bit(b->keycode, pdata->input->keybit); -+ } -+ } -+ -+ pdata->input->name = pdev->name; -+ input_register_device(pdata->input); -+ -+ return 0; -+} -+ -+static int __devexit asic3_keys_remove(struct platform_device *pdev) -+{ -+ struct asic3_keys_platform_data *pdata = pdev->dev.platform_data; -+ int i, base_irq; -+ -+ base_irq = asic3_irq_base(pdata->asic3_dev); -+ for (i = 0; i < pdata->nbuttons; i++) { -+ free_irq(base_irq + pdata->buttons[i].gpio, NULL); -+ } -+ -+ input_unregister_device(pdata->input); -+ -+ return 0; -+} -+ -+ -+static struct platform_driver asic3_keys_driver = { -+ .probe = asic3_keys_probe, -+ .remove = __devexit_p(asic3_keys_remove), -+ .driver = { -+ .name = "asic3-keys", -+ }, -+}; -+ -+static int __init asic3_keys_init(void) -+{ -+ return platform_driver_register(&asic3_keys_driver); -+} -+ -+static void __exit asic3_keys_exit(void) -+{ -+ platform_driver_unregister(&asic3_keys_driver); -+} -+ -+module_init(asic3_keys_init); -+module_exit(asic3_keys_exit); -+ -+MODULE_AUTHOR("Joshua Wise, Pawel Kolodziejski, Paul Sokolovsky"); -+MODULE_DESCRIPTION("Buttons driver for HTC ASIC3 SoC"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.22/include/asm-arm/arch-pxa/irqs.h -=================================================================== ---- linux-2.6.22.orig/include/asm-arm/arch-pxa/irqs.h 2007-09-11 12:53:24.000000000 +0200 -+++ linux-2.6.22/include/asm-arm/arch-pxa/irqs.h 2007-09-11 12:53:37.000000000 +0200 -@@ -172,6 +172,8 @@ - defined(CONFIG_MACH_LOGICPD_PXA270) || \ - defined(CONFIG_MACH_MAINSTONE) - #define NR_IRQS (IRQ_BOARD_END) -+#elif defined(CONFIG_MACH_HTCUNIVERSAL) -+#define NR_IRQS (IRQ_BOARD_START + 96) - #else - #define NR_IRQS (IRQ_BOARD_START) - #endif -Index: linux-2.6.22/include/linux/ioport.h -=================================================================== ---- linux-2.6.22.orig/include/linux/ioport.h 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/include/linux/ioport.h 2007-09-11 12:53:37.000000000 +0200 -@@ -56,6 +56,7 @@ - #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) - #define IORESOURCE_IRQ_LOWLEVEL (1<<3) - #define IORESOURCE_IRQ_SHAREABLE (1<<4) -+#define IORESOURCE_IRQ_SOC_SUBDEVICE (1<<5) - - /* ISA PnP DMA specific bits (IORESOURCE_BITS) */ - #define IORESOURCE_DMA_TYPE_MASK (3<<0) -Index: linux-2.6.22/drivers/video/backlight/Kconfig -=================================================================== ---- linux-2.6.22.orig/drivers/video/backlight/Kconfig 2007-09-11 12:53:30.000000000 +0200 -+++ linux-2.6.22/drivers/video/backlight/Kconfig 2007-09-11 12:53:37.000000000 +0200 -@@ -40,7 +40,7 @@ - - config BACKLIGHT_CORGI - tristate "Sharp Corgi Backlight Driver (SL Series)" -- depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL -+ depends on BACKLIGHT_CLASS_DEVICE - default y - help - If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the -Index: linux-2.6.22/drivers/video/backlight/corgi_bl.c -=================================================================== ---- linux-2.6.22.orig/drivers/video/backlight/corgi_bl.c 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/drivers/video/backlight/corgi_bl.c 2007-09-11 12:53:37.000000000 +0200 -@@ -24,7 +24,7 @@ - static int corgibl_intensity; - static struct backlight_properties corgibl_data; - static struct backlight_device *corgi_backlight_device; --static struct corgibl_machinfo *bl_machinfo; -+static struct generic_bl_info *bl_machinfo; - - static unsigned long corgibl_flags; - #define CORGIBL_SUSPENDED 0x01 -@@ -107,7 +107,7 @@ - - static int corgibl_probe(struct platform_device *pdev) - { -- struct corgibl_machinfo *machinfo = pdev->dev.platform_data; -+ struct generic_bl_info *machinfo = pdev->dev.platform_data; - - bl_machinfo = machinfo; - if (!machinfo->limit_mask) -Index: linux-2.6.22/arch/arm/mach-pxa/corgi.c -=================================================================== ---- linux-2.6.22.orig/arch/arm/mach-pxa/corgi.c 2007-09-11 12:53:32.000000000 +0200 -+++ linux-2.6.22/arch/arm/mach-pxa/corgi.c 2007-09-11 12:53:37.000000000 +0200 -@@ -20,6 +20,7 @@ - #include <linux/interrupt.h> - #include <linux/mmc/host.h> - #include <linux/pm.h> -+#include <linux/backlight.h> - - #include <asm/setup.h> - #include <asm/memory.h> -@@ -143,7 +144,7 @@ - /* - * Corgi Backlight Device - */ --static struct corgibl_machinfo corgi_bl_machinfo = { -+static struct generic_bl_info corgi_bl_machinfo = { - .max_intensity = 0x2f, - .default_intensity = 0x1f, - .limit_mask = 0x0b, -Index: linux-2.6.22/arch/arm/mach-pxa/spitz.c -=================================================================== ---- linux-2.6.22.orig/arch/arm/mach-pxa/spitz.c 2007-09-11 12:53:33.000000000 +0200 -+++ linux-2.6.22/arch/arm/mach-pxa/spitz.c 2007-09-11 12:53:37.000000000 +0200 -@@ -222,7 +222,7 @@ - /* - * Spitz Backlight Device - */ --static struct corgibl_machinfo spitz_bl_machinfo = { -+static struct generic_bl_info spitz_bl_machinfo = { - .default_intensity = 0x1f, - .limit_mask = 0x0b, - .max_intensity = 0x2f, -Index: linux-2.6.22/include/asm-arm/arch-pxa/serial.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.22/include/asm-arm/arch-pxa/serial.h 2007-09-11 12:53:37.000000000 +0200 -@@ -0,0 +1,78 @@ -+/* -+ * linux/include/asm-arm/arch-pxa/serial.h -+ * -+ * Author: Nicolas Pitre -+ * Copyright: (C) 2001 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <asm/arch/pxa-regs.h> -+ -+#define BAUD_BASE 921600 -+ -+/* Standard COM flags */ -+#define STD_COM_FLAGS (ASYNC_SKIP_TEST) -+ -+#define STD_SERIAL_PORT_DEFNS \ -+ { \ -+ type: PORT_PXA, \ -+ xmit_fifo_size: 64, \ -+ baud_base: BAUD_BASE, \ -+ iomem_base: &FFUART, \ -+ iomem_reg_shift: 2, \ -+ io_type: SERIAL_IO_MEM, \ -+ irq: IRQ_FFUART, \ -+ flags: STD_COM_FLAGS, \ -+ }, { \ -+ type: PORT_PXA, \ -+ xmit_fifo_size: 64, \ -+ baud_base: BAUD_BASE, \ -+ iomem_base: &STUART, \ -+ iomem_reg_shift: 2, \ -+ io_type: SERIAL_IO_MEM, \ -+ irq: IRQ_STUART, \ -+ flags: STD_COM_FLAGS, \ -+ }, { \ -+ type: PORT_PXA, \ -+ xmit_fifo_size: 64, \ -+ baud_base: BAUD_BASE, \ -+ iomem_base: &BTUART, \ -+ iomem_reg_shift: 2, \ -+ io_type: SERIAL_IO_MEM, \ -+ irq: IRQ_BTUART, \ -+ flags: STD_COM_FLAGS, \ -+ } -+ -+#define EXTRA_SERIAL_PORT_DEFNS -+ -+struct platform_pxa_serial_funcs { -+ -+ /* Initialize whatever is connected to this serial port. */ -+ void (*configure)(int state); -+#define PXA_UART_CFG_PRE_STARTUP 0 -+#define PXA_UART_CFG_POST_STARTUP 1 -+#define PXA_UART_CFG_PRE_SHUTDOWN 2 -+#define PXA_UART_CFG_POST_SHUTDOWN 3 -+ -+ /* Enable or disable the individual transmitter/receiver submodules. -+ * On transceivers without echo cancellation (e.g. SIR) -+ * transmitter always has priority; e.g. if both bits are set, -+ * only the transmitter is enabled. */ -+ void (*set_txrx)(int txrx); -+#define PXA_SERIAL_TX 1 -+#define PXA_SERIAL_RX 2 -+ -+ /* Get the current state of tx/rx. */ -+ int (*get_txrx)(void); -+ -+ int (*suspend)(struct platform_device *dev, pm_message_t state); -+ int (*resume)(struct platform_device *dev); -+}; -+ -+void pxa_set_ffuart_info(struct platform_pxa_serial_funcs *ffuart_funcs); -+void pxa_set_btuart_info(struct platform_pxa_serial_funcs *btuart_funcs); -+void pxa_set_stuart_info(struct platform_pxa_serial_funcs *stuart_funcs); -+void pxa_set_hwuart_info(struct platform_pxa_serial_funcs *hwuart_funcs); -Index: linux-2.6.22/drivers/serial/pxa.c -=================================================================== ---- linux-2.6.22.orig/drivers/serial/pxa.c 2007-07-09 01:32:17.000000000 +0200 -+++ linux-2.6.22/drivers/serial/pxa.c 2007-09-11 12:53:37.000000000 +0200 -@@ -46,6 +46,7 @@ - #include <asm/io.h> - #include <asm/hardware.h> - #include <asm/irq.h> -+#include <asm/arch/serial.h> - #include <asm/arch/pxa-regs.h> - - -@@ -59,6 +60,14 @@ - char *name; - }; - -+ -+#define IS_METHOD(dev, method) (dev && (dev)->platform_data && ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method) -+#define METHOD_CALL(dev, method) \ -+ ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method() -+#define SAFE_METHOD_CALL(dev, method, args...) \ -+ if (IS_METHOD(dev, method)) \ -+ ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method(args) -+ - static inline unsigned int serial_in(struct uart_pxa_port *up, int offset) - { - offset <<= 2; -@@ -346,6 +355,9 @@ - unsigned long flags; - int retval; - -+ /* Perform platform-specific port initialization, if needed. */ -+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_STARTUP); -+ - if (port->line == 3) /* HWUART */ - up->mcr |= UART_MCR_AFE; - else -@@ -401,6 +413,12 @@ - (void) serial_in(up, UART_IIR); - (void) serial_in(up, UART_MSR); - -+ /* -+ * Perform platform-specific port initialization if needed -+ */ -+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_STARTUP); -+ SAFE_METHOD_CALL(port->dev, set_txrx, PXA_SERIAL_RX); -+ - return 0; - } - -@@ -409,6 +427,8 @@ - struct uart_pxa_port *up = (struct uart_pxa_port *)port; - unsigned long flags; - -+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_SHUTDOWN); -+ - free_irq(up->port.irq, up); - - /* -@@ -430,6 +450,8 @@ - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT); - serial_out(up, UART_FCR, 0); -+ -+ SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_SHUTDOWN); - } - - static void -Index: linux-2.6.22/arch/arm/mach-pxa/generic.c -=================================================================== ---- linux-2.6.22.orig/arch/arm/mach-pxa/generic.c 2007-09-11 12:53:11.000000000 +0200 -+++ linux-2.6.22/arch/arm/mach-pxa/generic.c 2007-09-11 12:53:37.000000000 +0200 -@@ -42,6 +42,7 @@ - #include <asm/arch/mmc.h> - #include <asm/arch/irda.h> - #include <asm/arch/i2c.h> -+#include <asm/arch/serial.h> - - #include "devices.h" - #include "generic.h" -@@ -346,6 +347,18 @@ - .id = 3, - }; - -+void __init pxa_set_ffuart_info(struct platform_pxa_serial_funcs *info) -+{ -+ pxa_device_ffuart.dev.platform_data = info; -+} -+EXPORT_SYMBOL(pxa_set_ffuart_info); -+ -+void __init pxa_set_btuart_info(struct platform_pxa_serial_funcs *info) -+{ -+ pxa_device_btuart.dev.platform_data = info; -+} -+EXPORT_SYMBOL(pxa_set_btuart_info); -+ - static struct resource pxai2c_resources[] = { - { - .start = 0x40301680, -Index: linux-2.6.22/drivers/leds/Makefile -=================================================================== ---- linux-2.6.22.orig/drivers/leds/Makefile 2007-09-11 12:53:14.000000000 +0200 -+++ linux-2.6.22/drivers/leds/Makefile 2007-09-11 12:53:37.000000000 +0200 -@@ -16,6 +16,7 @@ - obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o - obj-$(CONFIG_LEDS_H1940) += leds-h1940.o - obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o -+obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o - obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o - - # LED Triggers -Index: linux-2.6.22/arch/arm/Kconfig -=================================================================== ---- linux-2.6.22.orig/arch/arm/Kconfig 2007-09-11 12:53:32.000000000 +0200 -+++ linux-2.6.22/arch/arm/Kconfig 2007-09-11 12:53:37.000000000 +0200 -@@ -1032,6 +1032,8 @@ - - source "drivers/w1/Kconfig" - -+source "drivers/power/Kconfig" -+ - source "drivers/hwmon/Kconfig" - - #source "drivers/l3/Kconfig" -Index: linux-2.6.22/drivers/input/keyboard/Kconfig -=================================================================== ---- linux-2.6.22.orig/drivers/input/keyboard/Kconfig 2007-09-11 14:28:45.000000000 +0200 -+++ linux-2.6.22/drivers/input/keyboard/Kconfig 2007-09-11 14:29:05.000000000 +0200 -@@ -253,4 +253,11 @@ - To compile this driver as a module, choose M here: the - module will be called gpio-keys. - -+config KEYBOARD_ASIC3 -+ tristate "Buttons on ASIC3 SoC GPIOs (iPaqs, etc.)" -+ depends on HTC_ASIC3 -+ help -+ This enables support for the buttons attached to GPIOs of -+ HTC ASIC3 peripheral controller. -+ - endif |