All pastes #297019 Raw Edit

Miscellany

public text v1 · immutable
#297019 ·published 2006-12-30 20:00 UTC
rendered paste body
Index: Kconfig
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/htcblueangel/Kconfig,v
retrieving revision 1.8
diff -u -r1.8 Kconfig
--- Kconfig	17 Dec 2006 12:23:37 -0000	1.8
+++ Kconfig	30 Dec 2006 19:53:03 -0000
@@ -46,10 +46,6 @@
 	Support for function keys
 	Pull-out keyboard not yet working
 
-menuconfig MACH_BLUEANGEL_AUDIO
-	tristate "HTC Blueangel audio support"
-	depends on MACH_BLUEANGEL
-
 menuconfig MACH_BLUEANGEL_BATTERY
 	tristate "HTC Blueangel battery support"
 	depends on MACH_BLUEANGEL
@@ -68,7 +64,12 @@
 	---help---
 	Required for using data transfer via GPRS, CSD and FAX
 
+menuconfig MACH_BLUEANGEL_TSC2200
+	tristate "HTC Blueangel tsc2200 support"
+	depends on MACH_BLUEANGEL
+	---help---
+	Required for using tsc2200
+
 config MACH_BLUEANGEL_UDC
 	bool "HTC Blueangel UDC support"
 	depends on MACH_BLUEANGEL
-	
Index: Makefile
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/htcblueangel/Makefile,v
retrieving revision 1.7
diff -u -r1.7 Makefile
--- Makefile	17 Dec 2006 12:23:37 -0000	1.7
+++ Makefile	30 Dec 2006 19:53:03 -0000
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_MACH_BLUEANGEL)         += blueangel.o
-obj-$(CONFIG_MACH_BLUEANGEL)         += blueangel_tsc2200.o
+obj-$(CONFIG_MACH_BLUEANGEL_TSC2200) += blueangel_tsc2200.o
 obj-$(CONFIG_MACH_BLUEANGEL_LCD)     += blueangel_lcd.o
 obj-$(CONFIG_MACH_BLUEANGEL_DS1WM)   += blueangel_ds1wm.o
 obj-$(CONFIG_MACH_BLUEANGEL_BACKLIGHT) += blueangel_bl.o
@@ -16,3 +16,4 @@
 obj-$(CONFIG_MACH_BLUEANGEL_ROM)     += blueangel_rom.o
 obj-$(CONFIG_MACH_BLUEANGEL_DPRAM)   += blueangel_dpram.o
 obj-$(CONFIG_MACH_BLUEANGEL_UDC)     += blueangel_udc.o
+obj-$(CONFIG_MACH_BLUEANGEL_DS1WM)     += blueangel_ds1wm.o
Index: blueangel_battery.c
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/htcblueangel/blueangel_battery.c,v
retrieving revision 1.5
diff -u -r1.5 blueangel_battery.c
--- blueangel_battery.c	22 Dec 2006 03:57:06 -0000	1.5
+++ blueangel_battery.c	30 Dec 2006 19:53:04 -0000
@@ -12,6 +12,8 @@
 #include <linux/version.h>
 #include <linux/battery.h>
 #include <linux/leds.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/soc/asic3_base.h>
 #include <linux/platform_device.h>
 
@@ -23,15 +25,54 @@
 
 #include <linux/soc/tsc2200.h>
 
+#include "../../../../drivers/w1/w1.h"
+#include "../../../../drivers/w1/slaves/w1_ds2760.h"
+
 #ifdef DEBUG
 #define dprintk(x...) printk(x)
 #else
 #define dprintk(x...)
 #endif
 
+#define BATTERY_CHECK_INTERVAL  (HZ * 60)       /* every 60 seconds */
+
+#define BLUEANGEL_BATTERY_MAX_VOLTAGE 4400  /* My measurements */
+#define BLUEANGEL_BATTERY_MIN_VOLTAGE    0  /* Maybe incorrect */
+#define BLUEANGEL_BATTERY_MAX_CURRENT  950  /* MUST BE MEASURED */
+#define BLUEANGEL_BATTERY_MIN_CURRENT -950  /* Maybe incorrect */
+#define BLUEANGEL_BATTERY_MIN_CHARGE     0  /* Maybe incorrect */
+
+/* DS2760 device */
+struct device *ds2760_dev = NULL;
+
+/* Cache the battery status for this many seconds. */
+#define STATUS_CACHE_TIME (HZ * 1)
+static struct ds2760_status battery_status;
+
+
 extern struct platform_device blueangel_tsc2200;
+extern struct platform_device blueangel_asic3;
+
 DEFINE_LED_TRIGGER(ledtrig_cradle);
+DEFINE_LED_TRIGGER(ledtrig_phone);
+
+/* w1_samcop device */
+static struct workqueue_struct *probe_q;
+static struct work_struct       probe_work;
+
+/* battery monitor */
+static struct timer_list        monitor_timer;
+static struct workqueue_struct *monitor_q;
+static struct work_struct       monitor_work;
+
+static int battery_charge_state;
+#define BATTERY_STATE_UNKNOWN   0
+#define BATTERY_DISCHARGING     1
+#define BATTERY_CHARGING        2
+#define BATTERY_FULL            3
 
+/* AC present? */
+static int power_status;
 
 
 static void bat_tsc2200_start_conv_scan(void)
@@ -47,18 +88,6 @@
 		TSC2200_CTRLREG_ADC_PV  (TSC2200_CTRLREG_ADC_PV_500uS) );
 }
 
-static void bat_tsc2200_start_conv_temp(void)
-{
-	tsc2200_write(&blueangel_tsc2200.dev, TSC2200_CTRLREG_REF, 31);
-	tsc2200_write(&blueangel_tsc2200.dev, TSC2200_CTRLREG_ADC,
-		TSC2200_CTRLREG_ADC_AD3 |
-		TSC2200_CTRLREG_ADC_AD1 |
-		TSC2200_CTRLREG_ADC_RES (TSC2200_CTRLREG_ADC_RES_12BITP) |
-		TSC2200_CTRLREG_ADC_AVG (TSC2200_CTRLREG_ADC_8AVG) |
-		TSC2200_CTRLREG_ADC_CL  (TSC2200_CTRLREG_ADC_CL_2MHZ_12BIT) |
-		TSC2200_CTRLREG_ADC_PV  (TSC2200_CTRLREG_ADC_PV_500uS) );
-}
-
 static void bat_tsc2200_stop_conv(void)
 {
 	tsc2200_write(&blueangel_tsc2200.dev, TSC2200_CTRLREG_ADC,
@@ -70,6 +99,60 @@
 		TSC2200_CTRLREG_ADC_PV  (TSC2200_CTRLREG_ADC_PV_500uS) );
 }
 
+int blueangel_battery_read_status(void)
+{
+        if (jiffies < (battery_status.update_time + STATUS_CACHE_TIME))
+                return 0;
+
+        if (!ds2760_dev)
+                return 0;
+
+        if (!w1_ds2760_status(ds2760_dev, &battery_status)) {
+                printk("call to w1_ds2760_status failed (0x%08x)\n",
+                       (unsigned int)ds2760_dev);
+                return 1;
+        }
+
+        return 0;
+}
+
+static int
+blueangel_battery_match_callback(struct device *dev, void *data)
+{
+        struct w1_slave *sl;
+
+        if (!(dev->driver && dev->driver->name &&
+             (strcmp(dev->driver->name, "w1_slave_driver") == 0)))
+                return 0;
+
+        sl = container_of(dev, struct w1_slave, dev);
+
+        /* DS2760 w1 slave device names begin with the family number 0x30. */
+        if (strncmp(sl->name, "30-", 3) != 0)
+                return 0;
+
+        return 1;
+}
+
+void
+blueangel_battery_probe_work(void *data)
+{
+        struct bus_type *bus;
+
+        /* Get the battery w1 slave device. */
+        bus = find_bus("w1");
+        if (bus)
+                ds2760_dev = bus_find_device(bus, NULL, NULL,
+                                             blueangel_battery_match_callback);
+
+        if (!ds2760_dev) {
+                /* No DS2760 device found; try again later. */
+                //queue_delayed_work(probe_q, &probe_work, HZ * 5);
+                return;
+        }
+}
+
+
 static int blueangel_battery_get_status(struct battery *bat)
 {
 	dprintk("%s: in.\n", __FUNCTION__);
@@ -108,116 +191,176 @@
 static int blueangel_battery_get_voltage(struct battery *bat)
 {
 	int retval;
-	
-	dprintk("%s: in.\n", __FUNCTION__);
-
-	//down_interruptible(&tsc2200_sem);
-	//tsc2200_lock(&blueangel_tsc2200.dev);
-	bat_tsc2200_start_conv_scan();
-
-	while ( !(tsc2200_read(&blueangel_tsc2200.dev, TSC2200_CTRLREG_ADC) & 0x4000) &&
-			 !tsc2200_dav(&blueangel_tsc2200.dev )) {
-		dprintk("B2: %X\n", tsc2200_read(&blueangel_tsc2200.dev, TSC2200_CTRLREG_ADC));
-		mdelay(1);
-	}
-	
-	retval = tsc2200_read(&blueangel_tsc2200.dev, TSC2200_DATAREG_AUX2);
-	
-	bat_tsc2200_stop_conv();
-	//tsc2200_unlock(&blueangel_tsc2200.dev);
-	//up(&tsc2200_sem);
+	blueangel_battery_read_status();
+	retval = battery_status.voltage_mV;	
 	return retval;
 }
 
 static int blueangel_battery_get_temp(struct battery *bat)
 {
 	int retval;
+	blueangel_battery_read_status();
+	retval = battery_status.temp_C;	
 	
-	dprintk("%s: in.\n", __FUNCTION__);
+	return retval;
+}
+blueangel_battery_get_max_voltage(struct battery *bat)
+{
+        return BLUEANGEL_BATTERY_MAX_VOLTAGE;
+}
 
-	//down_interruptible(&tsc2200_sem);
-	//tsc2200_lock(&blueangel_tsc2200.dev);
-	bat_tsc2200_start_conv_temp();
+int
+blueangel_battery_get_min_voltage(struct battery *bat)
+{
+        return BLUEANGEL_BATTERY_MIN_VOLTAGE;
+}
 
-	while ( !(tsc2200_read(&blueangel_tsc2200.dev, TSC2200_CTRLREG_ADC) & 0x4000) &&
-			 !tsc2200_dav(&blueangel_tsc2200.dev)) {
-		dprintk("1: %X\n", tsc2200_read(&blueangel_tsc2200.dev, TSC2200_CTRLREG_ADC)); 
-		mdelay(1);
-	}
-	
-	retval = tsc2200_read(&blueangel_tsc2200.dev, TSC2200_DATAREG_TEMP1);
-	dprintk("retval=0x%x\n", retval);
-	
-	bat_tsc2200_stop_conv();
-	//tsc2200_unlock(&blueangel_tsc2200.dev);
-	//up(&tsc2200_sem);
-	dprintk("%s: out\n", __FUNCTION__);
-	return retval;
+int
+blueangel_battery_get_max_current(struct battery *bat)
+{
+        return BLUEANGEL_BATTERY_MAX_CURRENT;
+}
+
+int
+blueangel_battery_get_min_current(struct battery *bat)
+{
+        return BLUEANGEL_BATTERY_MIN_CURRENT;
+}
+
+int
+blueangel_battery_get_current(struct battery *bat)
+{
+        blueangel_battery_read_status();
+        return battery_status.current_mA;
+}
+int
+blueangel_battery_get_max_charge(struct battery *bat)
+{
+        blueangel_battery_read_status();
+        return battery_status.rated_capacity;
 }
 
+int
+blueangel_battery_get_min_charge(struct battery *bat)
+{
+        return BLUEANGEL_BATTERY_MIN_CHARGE;
+}
+
+int
+blueangel_battery_get_charge(struct battery *bat)
+{
+        blueangel_battery_read_status();
+        return battery_status.accum_current_mAh;
+}
+
+
 struct battery battery_dev = {
-	.name           = "Main battery",
+	.name           = "main",
 	.id		= "battery0",
 	.get_voltage	= blueangel_battery_get_voltage,
-	.get_status	= blueangel_battery_get_status,
-	//.get_temp	= blueangel_battery_get_temp,
+        .get_min_voltage = blueangel_battery_get_min_voltage,
+        .get_max_voltage = blueangel_battery_get_max_voltage,
+        .get_current     = blueangel_battery_get_current,
+        .get_min_current = blueangel_battery_get_min_current,
+        .get_max_current = blueangel_battery_get_max_current,
+        .get_charge      = blueangel_battery_get_charge,
+        .get_min_charge  = blueangel_battery_get_min_charge,
+        .get_max_charge  = blueangel_battery_get_max_charge,
+        .get_temp        = blueangel_battery_get_temp,
+        .get_status      = blueangel_battery_get_status,
+
 };
 
 struct battery battery_dev1 = {
-	.name           = "Backup battery",
+	.name           = "backup",
 	.id		= "battery1",
 	.get_voltage	= blueangel_battery_get_voltage1,
 	.get_status	= blueangel_battery_get_status,
-	//.get_temp	= blueangel_battery_get_tempi1,
 };
 
+static irqreturn_t
+blueangel_ac_plug_isr (int isr, void *data)
+{
+
+        /* Update the LED status right away, for timely feedback. */
+        /* Set the proper charging rate. */
+	if (!(asic3_get_gpio_status_d(&blueangel_asic3.dev) & GPIOD_AC_CHARGER_N)) {
+        	power_status = APM_AC_ONLINE;
+	}
+	if (!(GPLR(GPIO_NR_BLUEANGEL_USB_DETECT_N) & GPIO_bit(GPIO_NR_BLUEANGEL_USB_DETECT_N))) {
+        	power_status = APM_AC_ONLINE;
+	}
+        if (power_status) {
+                /* Start off with a solid LED; if we're charging,
+                   the LED state will be updated when the queued work runs. */
+		#ifdef CONFIG_LEDS_TRIGGERS
+			led_trigger_event(ledtrig_cradle, LED_FULL);
+		#endif
+        } else {
+		#ifdef CONFIG_LEDS_TRIGGERS
+			led_trigger_event(ledtrig_cradle, LED_OFF);
+		#endif
+        }
+
+        /* Force the data to be re-read. */
+        battery_status.update_time = 0;
+
+        /* Wait a few seconds to let the DS2760 update its current reading. */
+        queue_delayed_work(monitor_q, &monitor_work, HZ * 7);
+
+        return IRQ_HANDLED;
+}
+
+
 static void
 blueangel_battery_get_power_status (struct apm_power_info *info)
 {
-	int val;
-	int val1;
-	int full=0x8ea;
-	int empty=0x8a3;
-
-	int full1=0xb0f;
-	int empty1=0x8a3;
-	val=blueangel_battery_get_voltage(NULL);
-	val1=blueangel_battery_get_voltage1(NULL);
-
-	info->battery_life = (val1-empty)*100/(full-empty);
-	if (info->battery_life < 0 || info->battery_life > 100) 
-		printk("battery voltage (0x%x) not within [0x%x,0x%x]. Please report.\n", val, full, empty);
-	if (info->battery_life < 0) 
-		info->battery_life = 0;
-	if (info->battery_life > 100)
-		info->battery_life = 100;
+        blueangel_battery_read_status();
+
         info->ac_line_status = APM_AC_OFFLINE;
-	if (!(asic3_get_gpio_status_d(&blueangel_tsc2200.dev) & GPIOD_AC_CHARGER_N)) {
+	if (!(asic3_get_gpio_status_d(&blueangel_asic3.dev) & GPIOD_AC_CHARGER_N)) {
         	info->ac_line_status = APM_AC_ONLINE;
 	}
 	if (!(GPLR(GPIO_NR_BLUEANGEL_USB_DETECT_N) & GPIO_bit(GPIO_NR_BLUEANGEL_USB_DETECT_N))) {
         	info->ac_line_status = APM_AC_ONLINE;
 	}
-	info->units=APM_UNITS_MINS;
-	info->time = 360 * info->battery_life/100;	/* time remaining */
-	info->battery_flag = 0;
-	if (info->ac_line_status == APM_AC_OFFLINE) {
+	power_status = info->ac_line_status;
+
+        if (info->ac_line_status == APM_AC_ONLINE && current > 0) {
 		#ifdef CONFIG_LEDS_TRIGGERS
-			led_trigger_event(ledtrig_cradle, LED_OFF);
+			led_trigger_event(ledtrig_cradle, LED_FULL);
 		#endif
-		info->battery_status = APM_BATTERY_STATUS_CRITICAL;
-		if(info->battery_life > 5) {
-			info->battery_status = APM_BATTERY_STATUS_LOW;
-		}
-		if(info->battery_life > 20) {
-			info->battery_status = APM_BATTERY_STATUS_HIGH;
-		}
-	} else {
-		info->battery_status = APM_BATTERY_STATUS_CHARGING;
+                info->battery_status = APM_BATTERY_STATUS_CHARGING;
+        } else {
 		#ifdef CONFIG_LEDS_TRIGGERS
-			led_trigger_event(ledtrig_cradle, LED_FULL);
+			led_trigger_event(ledtrig_cradle, LED_OFF);
 		#endif
-	}
+
+                info->battery_status = battery_status.accum_current_mAh >
+                    ((battery_status.rated_capacity * 75) / 100) ?
+                        APM_BATTERY_STATUS_HIGH :
+                    battery_status.accum_current_mAh >
+                        ((battery_status.rated_capacity* 25) / 100) ?
+                        APM_BATTERY_STATUS_LOW : APM_BATTERY_STATUS_CRITICAL;
+        }
+
+        info->battery_flag = info->battery_status;
+
+        if (battery_status.rated_capacity)
+                info->battery_life = (battery_status.accum_current_mAh * 100) /
+                                     battery_status.rated_capacity;
+
+        if (info->battery_life > 100)
+                info->battery_life = 100;
+        if (info->battery_life < 0)
+                info->battery_life = 0;
+
+        if (battery_status.current_mA) {
+                info->time = - ((battery_status.accum_current_mAh * 6000) /
+                                battery_status.current_mA) / 100;
+                info->units = APM_UNITS_MINS;
+        } else
+                info->units = APM_UNITS_UNKNOWN;
 }
 
 static int bat_setup(void)
@@ -227,17 +370,131 @@
 	return 0;
 }
 
-static int __init bat_init(void)
+static void
+blueangel_battery_timer(unsigned long data)
 {
-	bat_setup();
-	blueangel_battery_get_voltage(NULL);
-	blueangel_battery_get_voltage1(NULL);
-	blueangel_battery_get_temp(NULL);
-	apm_get_power_status = blueangel_battery_get_power_status;
+        queue_work(monitor_q, &monitor_work);
+        mod_timer(&monitor_timer, jiffies + BATTERY_CHECK_INTERVAL);
+}
+
+void
+blueangel_battery_update_status(void *data)
+{
+        static int full_counter;
+
+        blueangel_battery_read_status();
+
+        if (battery_charge_state == BATTERY_STATE_UNKNOWN)
+                full_counter = 0;
+
+        /* Set the proper charging rate. */
+	if (!(asic3_get_gpio_status_d(&blueangel_asic3.dev) & GPIOD_AC_CHARGER_N)) {
+        	power_status = APM_AC_ONLINE;
+	}
+	if (!(GPLR(GPIO_NR_BLUEANGEL_USB_DETECT_N) & GPIO_bit(GPIO_NR_BLUEANGEL_USB_DETECT_N))) {
+        	power_status = APM_AC_ONLINE;
+	}
+        if (power_status) {
+
+                asic3_set_gpio_out_c(&blueangel_asic3.dev,1 << GPIOC_CHARGER_MODE, 1 << GPIOC_CHARGER_MODE);
+
+                if (battery_status.current_mA > 10) {
+
+                        battery_charge_state = BATTERY_CHARGING;
+                        full_counter = 0;
+
+                } else if (battery_status.current_mA < 10 &&
+                           battery_charge_state != BATTERY_FULL) {
+
+                        /* Don't consider the battery to be full unless
+                         * we've seen the current < 10 mA at least two
+                         * consecutive times. */
+
+                        full_counter++;
+
+                        if (full_counter < 2)
+                                battery_charge_state = BATTERY_CHARGING;
+                        else  {
+
+                                unsigned char acr[2];
+
+                                acr[0] = (battery_status.rated_capacity * 4) >> 8;
+                                acr[1] = (battery_status.rated_capacity * 4) & 0xff;
+
+                                if (w1_ds2760_write(ds2760_dev, acr,
+                                    DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+                                        printk(KERN_ERR "ACR reset failed\n");
+                                battery_charge_state = BATTERY_FULL;
+				#ifdef CONFIG_LEDS_TRIGGERS
+					led_trigger_event(ledtrig_phone, LED_FULL);
+				#endif
+                        }
+                }
+
+                if (battery_charge_state == BATTERY_CHARGING) {
+			#ifdef CONFIG_LEDS_TRIGGERS
+				led_trigger_event(ledtrig_cradle, LED_FULL);
+			#endif
+                } else {
+
+                        /* Set the LED solid while on AC and not charging. */
+			#ifdef CONFIG_LEDS_TRIGGERS
+				led_trigger_event(ledtrig_phone,  LED_FULL);
+				led_trigger_event(ledtrig_cradle, LED_OFF);
+			#endif
+                }
+
+        } else {
+
+                battery_charge_state = BATTERY_DISCHARGING;
+                full_counter = 0;
+                asic3_set_gpio_out_c(&blueangel_asic3.dev,1 << GPIOC_CHARGER_MODE, 0);
+
+                /* Turn off the LED while unplugged from AC. */
 		#ifdef CONFIG_LEDS_TRIGGERS
-	led_trigger_register_simple("charge", &ledtrig_cradle);
+			led_trigger_event(ledtrig_cradle, LED_OFF);
 		#endif
+        }
+
+}
+
+
+
+static int __init bat_init(void)
+{
+	bat_setup();
+
+        battery_charge_state = BATTERY_STATE_UNKNOWN;
+
+        /* Install an interrupt handler for AC plug/unplug. */
+        set_irq_type(IRQ_GPIO(GPIO_NR_BLUEANGEL_USB_DETECT_N), IRQT_BOTHEDGE);
+        request_irq(IRQ_GPIO(GPIO_NR_BLUEANGEL_USB_DETECT_N), blueangel_ac_plug_isr, SA_SAMPLE_RANDOM,
+                     "AC plug", NULL);
+
+        /* Create a workqueue in which the battery monitor will run. */
+        monitor_q = create_singlethread_workqueue("battmon");
+        INIT_WORK(&monitor_work, blueangel_battery_update_status, NULL);
+
+        /* Create a timer to run the battery monitor every
+           BATTERY_CHECK_INTERVAL seconds. */
+        init_timer(&monitor_timer);
+        monitor_timer.function = blueangel_battery_timer;
+        monitor_timer.data = 0;
 
+        /* Start the first monitor task a few seconds from now. */
+        mod_timer(&monitor_timer, jiffies + HZ * 10);
+
+	apm_get_power_status = blueangel_battery_get_power_status;
+	#ifdef CONFIG_LEDS_TRIGGERS
+		led_trigger_register_simple("charge", &ledtrig_cradle);
+		led_trigger_register_simple("phone", &ledtrig_phone);
+	#endif
+
+        /* Get the DS2760 W1 device. */
+        probe_q = create_singlethread_workqueue("battmonprb");
+        INIT_WORK(&probe_work, blueangel_battery_probe_work, NULL);
+        blueangel_battery_probe_work(NULL);
+	//enable_irq(IRQ_GPIO(GPIO_NR_BLUEANGEL_USB_DETECT_N));
 	return 0;
 }
 
@@ -246,14 +503,32 @@
 	apm_get_power_status = NULL;
 	battery_class_unregister(&battery_dev);
 	battery_class_unregister(&battery_dev1);
-		#ifdef CONFIG_LEDS_TRIGGERS
-        led_trigger_unregister_simple(ledtrig_cradle);
-		#endif
+	
+	disable_irq(IRQ_GPIO(GPIO_NR_BLUEANGEL_USB_DETECT_N));
+	free_irq(IRQ_GPIO(GPIO_NR_BLUEANGEL_USB_DETECT_N), NULL);
+
+
+        cancel_delayed_work(&monitor_work);
+        flush_workqueue(monitor_q);
+        destroy_workqueue(monitor_q);
+
+        cancel_delayed_work(&probe_work);
+        flush_workqueue(probe_q);
+        destroy_workqueue(probe_q);
+
+        if (ds2760_dev)
+                put_device(ds2760_dev);
+	#ifdef CONFIG_LEDS_TRIGGERS
+		led_trigger_event(ledtrig_phone, LED_OFF);
+       	        led_trigger_unregister_simple(ledtrig_phone);
+		led_trigger_event(ledtrig_cradle, LED_OFF);
+       	        led_trigger_unregister_simple(ledtrig_cradle);
+	#endif
 }
 
 module_init(bat_init)
 module_exit(bat_exit)
 
 MODULE_AUTHOR("Matthias Burghardt");
-MODULE_DESCRIPTION("Battery (TI TSC2200) support for the HTC Blueangel");
+MODULE_DESCRIPTION("Battery (TI TSC2200) and DS2760 upport for the HTC Blueangel");
 MODULE_LICENSE("GPL");
Index: blueangel_ds1wm.c
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/htcblueangel/blueangel_ds1wm.c,v
retrieving revision 1.5
diff -u -r1.5 blueangel_ds1wm.c
--- blueangel_ds1wm.c	17 Dec 2006 12:23:37 -0000	1.5
+++ blueangel_ds1wm.c	30 Dec 2006 19:53:04 -0000
@@ -36,7 +36,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = 0,
+//		.start  = 0,
 		.flags  = IORESOURCE_IRQ,
 	}
 
@@ -75,9 +75,8 @@
 	int irq;
 	printk("HTC Blueangel DS1WM driver\n");
 	irq = asic3_irq_base(&blueangel_asic3.dev) + BLUEANGEL_OWM_IRQ;
-
-	enable_irq(irq);
 	blueangel_ds1wm_resources[1].start = irq;
+	blueangel_ds1wm_resources[1].end = irq;
 
 	if (clk_register(&ds1wm_clk) < 0)
 		printk(KERN_ERR "failed to register DS1WM clock\n");
@@ -97,13 +96,14 @@
                 platform_device_put(blueangel_ds1wm);
 		printk("blueangel_ds1wm: failed to add platform device\n");
 	}
+	printk("HTC Blueangel DS1WM registered\n");
 
 	return ret;
 }
 
 static void blueangel_ds1wm_exit(void)
 {
-	disable_irq(asic3_irq_base(&blueangel_asic3.dev) + BLUEANGEL_OWM_IRQ);
+	//disable_irq(asic3_irq_base(&blueangel_asic3.dev) + BLUEANGEL_OWM_IRQ);
 	platform_device_del(blueangel_ds1wm);
 }
 
Index: blueangel_lcd.c
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/htcblueangel/blueangel_lcd.c,v
retrieving revision 1.8
diff -u -r1.8 blueangel_lcd.c
--- blueangel_lcd.c	21 Dec 2006 00:18:17 -0000	1.8
+++ blueangel_lcd.c	30 Dec 2006 19:53:04 -0000
@@ -221,7 +221,7 @@
 	.lcd_format =        0x00000003,
 	.lcdd_cntl1 =        0x00000000,
 	.lcdd_cntl2 =        0x0003ffff,
-	.genlcd_cntl1 =      0x00fff003,	//  0x00fff003
+	.genlcd_cntl1 =      0x00abf003,	//  0x00fff003
 	.genlcd_cntl2 =      0x00000003,	
 	.genlcd_cntl3 =      0x000102aa,
 };
Index: blueangel_pcmcia.c
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/htcblueangel/blueangel_pcmcia.c,v
retrieving revision 1.5
diff -u -r1.5 blueangel_pcmcia.c
--- blueangel_pcmcia.c	4 Dec 2006 02:23:51 -0000	1.5
+++ blueangel_pcmcia.c	30 Dec 2006 19:53:04 -0000
@@ -1,278 +1,170 @@
-/*
- * HTC Blueangel PCMCIA support
- *
- * Copyright (c) 2005 SDG Systems, LLC
- *
- * Based on code from iPAQ h2200
- *   Copyright  2004 Koen Kooi <koen@vestingbar.nl>
- *
- * 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.
- */
+ /*
+  *   h4000_pcmcia.c
+  *
+  *   Created Apr 2, 2005, by Shawn Anderson
+  *
+  *  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 <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/soc-old.h>
-
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include <asm/hardware.h>
-#include <asm/irq.h>
-
 #include <asm/arch/pxa-regs.h>
-#include <asm/arch/htcblueangel-gpio.h>
-#include <asm/arch/htcblueangel-asic.h>
 #include <asm/hardware/ipaq-asic3.h>
 #include <linux/soc/asic3_base.h>
-
 #include "../../../../drivers/pcmcia/soc_common.h"
+#include "../../../../drivers/pcmcia/pxa2xx_base.h"
+#include <asm/arch/htcblueangel-gpio.h>
+#include <asm/arch/htcblueangel-asic.h>
 
 extern struct platform_device blueangel_asic3;
 
-/*
- * CF resources used on blueangel :
- *
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_POE_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PWE_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PIOR_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PIOW_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PCE1_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PCE2_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PREG_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PWAIT_N_MD);
- *     pxa_gpio_mode(GPIO_NR_BLUEANGEL_PIOIS16_N_MD);
- */
-
-#if 0
-#define _debug(s, args...) printk (KERN_INFO s, ##args)
-#define _debug_func(s, args...) _debug ("%s: " s, __FUNCTION__, ##args)
-#else
-#define _debug(s, args...)
-#define _debug_func(s, args...) _debug ("%s: " s, __FUNCTION__, ##args)
-#endif
-
-#if 0
-static struct pcmcia_irqs blueangel_cd_irq[] = {
-	{ 0, 0,  "PCMCIA CD" }	/* fill in IRQ below */
-};
-#endif
+#define GET_BLUEANGEL_GPIO(gpio) \
+        (GPLR(GPIO_NR_BLUEANGEL_ ## gpio) & GPIO_bit(GPIO_NR_BLUEANGEL_ ## gpio))
+
+#define SET_BLUEANGEL_GPIO(gpio, setp) \
+do { \
+if (setp) \
+	GPSR( gpio) = GPIO_bit( gpio); \
+else \
+	GPCR( gpio) = GPIO_bit( gpio); \
+} while (0)
 
-static int power_en=0;
+static struct pcmcia_irqs irqs[] = {
+	{0, IRQ_GPIO(75), "PCMCIA0"},
+};
 
-static void
-blueangel_cf_reset( int state )
+static irqreturn_t acx_event(int irq, void* data, struct pt_regs *regs)
 {
-	printk("reset\n");
-#if 0
-	_debug_func ("%d\n", state);
-	SET_HX4700_GPIO( CF_RESET, state?1:0 );
-#endif
-}
+	struct acx_data *devdata = data;
 
-static int
-blueangel_pcmcia_hw_init( struct soc_pcmcia_socket *skt )
+	printk("acx receive irq pcmcia shared\n");
+	
+	return IRQ_HANDLED;
+};
+static int htcblueangel_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
-	int statusd;
-	int irq;
+	GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | GPIO_bit(GPIO49_nPWE) |
+	    GPIO_bit(GPIO52_nPCE_1_MD) | GPIO_bit(GPIO53_nPCE_2_MD) |
+	    GPIO_bit(GPIO55_nPREG_MD) | GPIO_bit(GPIO56_nPWAIT_MD);
 
-	_debug_func ("\n");
+	pxa_gpio_mode(GPIO48_nPOE_MD);
+	pxa_gpio_mode(GPIO49_nPWE_MD);
+	pxa_gpio_mode(GPIO52_nPCE_1_MD);
+	pxa_gpio_mode(GPIO55_nPREG_MD);
+	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+	pxa_gpio_mode(75 | GPIO_IN);
 
-	printk("hw_init\n");
-#if 0
-	/* Turn on sleep mode, I think */
-	asic3_set_extcf_select(&blueangel_asic3.dev,
-		ASIC3_EXTCF_CF_SLEEP | (ASIC3_EXTCF_CF0_SLEEP_MODE * 3) | ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF0_PWAIT_EN,
-		ASIC3_EXTCF_CF_SLEEP | 0                                | 0                      | 0
-	);
-	mdelay(50);
-
-	statusd = asic3_get_gpio_status_d( &blueangel_asic3.dev );
-	power_en = (statusd & (1<<GPIOD_CF_CD_N)) ? 0 : 1;
-
-	irq = hx4700_cd_irq[0].irq = asic3_irq_base( &hx4700_asic3.dev )
-			+ ASIC3_GPIOD_IRQ_BASE + GPIOD_CF_CD_N;
-	skt->irq = HX4700_IRQ( CF_RNB );
-
-	if (power_en) {
-		hx4700_egpio_enable( EGPIO4_CF_3V3_ON );
-		set_irq_type( irq, IRQT_RISING );
-	}
-	else {
-		hx4700_egpio_disable( EGPIO4_CF_3V3_ON );
-		set_irq_type( irq, IRQT_FALLING );
-	}
+	asic3_set_clock_cdex(&blueangel_asic3.dev, CLOCK_CDEX_EX1, CLOCK_CDEX_EX1);
+	asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << GPIOA_WLAN_RESET,
+				  1 << GPIOA_WLAN_RESET);
+	asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << GPIOA_WLAN_RESET, 0);
 
-	pxa_gpio_mode(GPIO_NR_HX4700_POE_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PWE_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PIOR_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PIOW_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PCE1_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PCE2_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PREG_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PWAIT_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PIOIS16_N_MD | GPIO_DFLT_HIGH);
-	pxa_gpio_mode(GPIO_NR_HX4700_PSKTSEL_MD);
+	skt->irq = irqs[0].irq;
 
-	return soc_pcmcia_request_irqs(skt, blueangel_cd_irq, ARRAY_SIZE(blueangel_cd_irq));
-#endif
-	return 0;
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-/*
- * Release all resources.
- */
-static void
-blueangel_pcmcia_hw_shutdown( struct soc_pcmcia_socket *skt )
+static void htcblueangel_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	printk("shutdown\n");
-#if 0
-	_debug_func ("\n");
-	soc_pcmcia_free_irqs( skt, blueangel_cd_irq, ARRAY_SIZE(blueangel_cd_irq) );
-#endif
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void
-blueangel_pcmcia_socket_state( struct soc_pcmcia_socket *skt,
-    struct pcmcia_state *state )
+static void htcblueangel_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+				      struct pcmcia_state *state)
 {
-	int statusd;
-
-	printk("socket_state\n");
-	state->detect = 1;
-	state->ready  = 1;
-	state->bvd1   = 1;
-	state->bvd2   = 1;
+	state->detect = GET_BLUEANGEL_GPIO(WLAN_IRQ2_N) ? 1 : 0; // 1;	// always attached
+	state->ready = 1; //GET_BLUEANGEL_GPIO(WLAN_IRQ2_N) ? 1 : 0;
+	state->bvd1 = 1;
+	state->bvd2 = 1;
 	state->wrprot = 0;
-	state->vs_3v  = 1;
-	state->vs_Xv  = 0;
-
-#if 0
-	if (state->detect)
-	    asic3_set_gpio_status_c( &hx4700_asic3.dev, 1<<GPIOC_CIOR_N,
-		1<<GPIOC_CIOR_N );
-	else
-	    asic3_set_gpio_status_c( &hx4700_asic3.dev, 1<<GPIOC_CIOR_N, 0 );
-#endif
-
-	_debug( "detect:%d ready:%d vcc:%d\n",
-	       state->detect, state->ready, state->vs_3v );
-}
+	state->vs_3v = asic3_get_gpio_status_a(&blueangel_asic3.dev)
+	    & (1 << GPIOA_WLAN_PWR2);
+	state->vs_Xv = 0;
+};
 
-static int
-blueangel_pcmcia_config_socket( struct soc_pcmcia_socket *skt,
-    const socket_state_t *state )
+static int htcblueangel_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+					 const socket_state_t * state)
 {
-	int statusc;
-
-#if 0
-	statusc = asic3_get_gpio_status_c( &hx4700_asic3.dev );
-#endif
-	printk("config_socket\n");
-	/* Silently ignore Vpp, output enable, speaker enable. */
-	_debug_func( "Reset:%d Vcc:%d Astatusc=0x%x\n",
-	    (state->flags & SS_RESET) ? 1 : 0, state->Vcc,
-	    statusc );
-
-#if 0
-	blueangel_cf_reset( state->flags & SS_RESET );
-	if (state->Vcc == 0) {
-		/* Turn on sleep mode, I think.  No docs for these bits. */
-		asic3_set_extcf_select(&blueangel_asic3.dev,
-			ASIC3_EXTCF_CF_SLEEP | (ASIC3_EXTCF_CF0_SLEEP_MODE * 3) | ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF0_PWAIT_EN,
-			ASIC3_EXTCF_CF_SLEEP | 0                                | 0                      | 0
-		);
-		blueangel_egpio_disable( EGPIO4_CF_3V3_ON );
-		power_en = 0;
-	}
-	else if (state->Vcc == 33 || state->Vcc == 50) {
-		blueangel_egpio_enable( EGPIO4_CF_3V3_ON );
-		mdelay(1);
-		/* Turn on CF stuff without messing with SD bit 14.  */
-		asic3_set_extcf_select(&blueangel_asic3.dev,
-			ASIC3_EXTCF_CF_SLEEP | (ASIC3_EXTCF_CF0_SLEEP_MODE * 3) | ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF0_PWAIT_EN,
-			0                    | (ASIC3_EXTCF_CF0_SLEEP_MODE * 2) | ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF0_PWAIT_EN
-		);
-		power_en = 1;
+	switch (state->Vcc) {
+	case 0:
+		asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << GPIOA_WLAN_PWR1,
+					  1 << GPIOA_WLAN_PWR1);
+		asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << GPIOA_WLAN_PWR2,
+					  1 << GPIOA_WLAN_PWR2);
+		break;
+	case 50:
+	case 33:
+		asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << GPIOA_WLAN_PWR1,
+					  1 << GPIOA_WLAN_PWR1);
+		asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << GPIOA_WLAN_PWR2,
+					  1 << GPIOA_WLAN_PWR2);
+		break;
+	default:
+		printk(KERN_ERR "%s: Unsupported Vcc:%d\n", __FUNCTION__,
+		       state->Vcc);
 	}
-	else {
-		printk (KERN_ERR "%s: Unsupported Vcc:%d\n",
-			__FUNCTION__, state->Vcc);
-	}
-#endif
 	return 0;
+
 }
 
-/*
- * Enable card status IRQs on (re-)initialisation.  This can
- * be called at initialisation, power management event, or
- * pcmcia event.
- */
-static void
-blueangel_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+static void htcblueangel_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	printk("socket_init\n");
-#if 0
-	_debug_func ("\n");
-	blueangel_cf_reset(0);
-#endif
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-/*
- * Disable card status IRQs on suspend.
- */
-static void
-blueangel_pcmcia_socket_suspend( struct soc_pcmcia_socket *skt )
+static void htcblueangel_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	printk("socket_suspend\n");
-#if 0
-	_debug_func ("\n");
-	blueangel_cf_reset(1);
-#endif
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static struct pcmcia_low_level blueangel_pcmcia_ops = {
-	.owner          	= THIS_MODULE,
-	.nr         		= 1,
-	.hw_init        	= blueangel_pcmcia_hw_init,
-	.hw_shutdown		= blueangel_pcmcia_hw_shutdown,
-	.socket_state		= blueangel_pcmcia_socket_state,
-	.configure_socket	= blueangel_pcmcia_config_socket,
-	.socket_init		= blueangel_pcmcia_socket_init,
-	.socket_suspend		= blueangel_pcmcia_socket_suspend,
+static struct pcmcia_low_level htcblueangel_pcmcia_ops = {
+	.owner            = THIS_MODULE,
+	.first            = 0,
+	.nr               = 1,
+	.hw_init          = htcblueangel_pcmcia_hw_init,
+	.hw_shutdown      = htcblueangel_pcmcia_hw_shutdown,
+	.socket_state     = htcblueangel_pcmcia_socket_state,
+	.configure_socket = htcblueangel_pcmcia_configure_socket,
+	.socket_init      = htcblueangel_pcmcia_socket_init,
+	.socket_suspend   = htcblueangel_pcmcia_socket_suspend,
+        .set_timing 	  = pxa2xx_pcmcia_set_timing,
 };
 
-static struct platform_device blueangel_pcmcia_device = {
-	.name			= "pxa2xx-pcmcia",
-	.dev			= {
-		.platform_data	= &blueangel_pcmcia_ops,
-	}
+static struct platform_device htcblueangel_pcmcia = {
+	.name = "pxa2xx-pcmcia",
+	.dev = {.platform_data = &htcblueangel_pcmcia_ops},
 };
 
-static int __init
-blueangel_pcmcia_init(void)
+static int __init htcblueangel_pcmcia_probe(struct platform_device *pdev)
 {
-	_debug_func ("\n");
+	return platform_device_register(&htcblueangel_pcmcia);
+}
 
-	return platform_device_register( &blueangel_pcmcia_device );
+static struct platform_driver htcblueangel_pcmcia_driver = {
+	.driver = {
+	    .name     = "htcblueangel_pcmcia",
+	},
+        .probe    = htcblueangel_pcmcia_probe,
+};
+
+static int __init htcblueangel_pcmcia_init(void)
+{  
+	return platform_driver_register(&htcblueangel_pcmcia_driver);
 }
 
-static void __exit
-blueangel_pcmcia_exit(void)
+static void __exit htcblueangel_pcmcia_exit(void)
 {
-	platform_device_unregister( &blueangel_pcmcia_device );
+	platform_device_unregister(&htcblueangel_pcmcia);
+	platform_driver_unregister(&htcblueangel_pcmcia_driver);
 }
 
-module_init(blueangel_pcmcia_init);
-module_exit(blueangel_pcmcia_exit);
+module_init(htcblueangel_pcmcia_init);
+module_exit(htcblueangel_pcmcia_exit);
 
-MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
-MODULE_DESCRIPTION("HTC Blueangel PCMCIA/CF platform-specific driver");
 MODULE_LICENSE("GPL");
-
-/* vim600: set noexpandtab sw=8 ts=8 :*/
-