Author: nick
Date: 2012-01-30 16:35:35 +0000 (Mon, 30 Jan 2012)
New Revision: 1835
Modified:
balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/battery-tt.patch
Log:
update battery to include vbus sysfs entry. Also to poll voltage on read/interrupt not periodically
Modified: balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/battery-tt.patch
===================================================================
--- balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/battery-tt.patch 2012-01-30 16:34:34 UTC (rev 1834)
+++ balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/battery-tt.patch 2012-01-30 16:35:35 UTC (rev 1835)
@@ -1,24 +1,29 @@
Index: linux-2.6.39.4/drivers/power/Kconfig
===================================================================
---- linux-2.6.39.4.orig/drivers/power/Kconfig 2012-01-06 13:48:02.000000000 +0000
-+++ linux-2.6.39.4/drivers/power/Kconfig 2012-01-06 13:48:08.000000000 +0000
-@@ -219,4 +219,12 @@
+--- linux-2.6.39.4.orig/drivers/power/Kconfig 2012-01-30 10:34:18.000000000 +0000
++++ linux-2.6.39.4/drivers/power/Kconfig 2012-01-30 10:35:54.000000000 +0000
+@@ -219,4 +219,17 @@
This driver can be build as a module. If so, the module will be
called gpio-charger.
+config BATTERY_TT
+ tristate "Battery driver for Bubble TT"
-+# depends on INTEL_SCU_IPC && SPI
-+ depends on MACH_BALLOON3_BUBBLE
++ depends on MACH_BALLOON3_BUBBLE && SPI_TT
+ help
+ Say Y here to enable the battery driver on Bubble TT
+ platforms.
+
++config BATTERY_TT_LED
++ bool "Use leds to indicate battery state"
++ depends on BATTERY_TT
++ help
++ Say Y here to enable the low battery led warning.
++
endif # POWER_SUPPLY
Index: linux-2.6.39.4/drivers/power/Makefile
===================================================================
---- linux-2.6.39.4.orig/drivers/power/Makefile 2012-01-06 13:48:02.000000000 +0000
-+++ linux-2.6.39.4/drivers/power/Makefile 2012-01-06 13:48:08.000000000 +0000
+--- linux-2.6.39.4.orig/drivers/power/Makefile 2012-01-30 10:34:18.000000000 +0000
++++ linux-2.6.39.4/drivers/power/Makefile 2012-01-30 10:35:54.000000000 +0000
@@ -34,3 +34,4 @@
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
@@ -27,8 +32,8 @@
Index: linux-2.6.39.4/drivers/power/tt_battery.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.39.4/drivers/power/tt_battery.c 2012-01-06 15:17:48.000000000 +0000
-@@ -0,0 +1,322 @@
++++ linux-2.6.39.4/drivers/power/tt_battery.c 2012-01-30 16:08:59.000000000 +0000
+@@ -0,0 +1,398 @@
+/*
+ * Battery and Power Management code for the Bubble TT device
+ * Copyright (c) 2011 Nick Bane
@@ -56,11 +61,17 @@
+#include <asm/mach-types.h>
+#include <mach/balloon3.h>
+
++//#define BATTERY_POLL
++//#define BATTERY_WARN
++
++#ifdef BATTERY_POLL
++static unsigned long batt_delay;
++#endif
++
+static struct delayed_work bat_work;
+static DEFINE_MUTEX(bat_lock);
-+static unsigned long batt_delay;
-+
+struct tt_bat {
++ int vbus_status;
+ int status;
+ int charge_type;
+ struct power_supply psy;
@@ -77,10 +88,33 @@
+ int bat_min;
+ int bat_scale;
+
++#ifdef BATTERY_WARN
++ int bat_warn;
++ int bat_warn_counter;
++#endif
++
+};
+
+static struct tt_bat tt_bat;
+
++static ssize_t
++show_vbus(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, tt_bat.vbus_status ? "ok\n" : "n/c\n");
++}
++
++static DEVICE_ATTR(vbus, S_IRUGO, show_vbus, NULL);
++
++static struct attribute *tt_bat_sysfs_entries[] = {
++ &dev_attr_vbus.attr,
++ NULL,
++};
++
++static struct attribute_group tt_bat_attr_group = {
++ .name = NULL, /* put in device directory */
++ .attrs = tt_bat_sysfs_entries,
++};
++
+static int spiReadReg16(struct spi_device *spi, u8 *result)
+{
+ int res = 0;
@@ -103,21 +137,66 @@
+{
+ unsigned long value = 0;
+ u8 result[2]={0,0};
-+
-+ mutex_lock(&bat_lock);
++
++// mutex_lock(&bat_lock);
+ value = spiReadReg16(bat->spi, result);
-+ mutex_unlock(&bat_lock);
++// mutex_unlock(&bat_lock);
+
+ // we have to shuffle the bits around due to endianness issues
+ // and the fact that the ADC only gives us 10 bits
-+ value=(result[0]<<5)+(result[1]>>3);
-+ // and mask off the bits which the ADC doesn't give us
-+// value = value * 1000000 / bat->adc_bat_divider;
++ value = (result[0]<<5) + (result[1]>>3);
+
-+// pr_info("%s: battery level %lu (0x%lx) - scaled value %lu\n", __func__, value, value, value * bat->bat_scale);
+ return value;
+}
+
++static void tt_bat_update(struct tt_bat *bat)
++{
++ int old_status;
++ int old_charge_type;
++ struct power_supply *psy = &bat->psy;
++
++ u8 bat_status = samosa_read8(SAMOSA_ADDR_USB_CHG_REG_STATUS);
++ int vbus_ok = bat_status & (1 << USB_VBUS_OK_BIT);
++ int charger_present = bat_status & (1 << USB_CHARGER_PRESENT_BIT);
++ int charge_fast = bat_status & (1 << USB_CHARGE_FAST_BIT);
++ int notify_changed = 0;
++
++ u16 bat_val;
++// mutex_lock(&bat->work_lock);
++ bat_val = tt_read_bat(bat);
++
++ // see if we have changed in status or charging type
++ old_status = bat->status;
++ old_charge_type = bat->charge_type;
++
++ bat->status = charger_present ? POWER_SUPPLY_STATUS_CHARGING : POWER_SUPPLY_STATUS_DISCHARGING;
++ bat->charge_type = charger_present ? (charge_fast ? POWER_SUPPLY_CHARGE_TYPE_FAST : POWER_SUPPLY_CHARGE_TYPE_TRICKLE) : POWER_SUPPLY_CHARGE_TYPE_NONE;
++
++ notify_changed = (vbus_ok != bat->vbus_status) || (old_status != bat->status) || (old_charge_type != bat->charge_type);
++
++ bat->vbus_status = vbus_ok;
++
++#ifdef BATTERY_WARN
++ // see if we have crossed a bat_warn threshold for long enough to believe it
++ if ((bat_val * bat->bat_scale) < bat->bat_warn) {
++ bat->bat_warn_counter++;
++ // if below bat_warn for 5 secs, do something
++ if (bat->bat_warn_counter == 5) {
++ pr_info("%s: battery level crossed below warn threshold 5 times in a row\n", __func__);
++ notify_changed = 1;
++ }
++ }
++ else {
++ if (bat->bat_warn_counter)
++ bat->bat_warn_counter--;
++ }
++#endif
++ // report if power supply has changed
++ if (notify_changed)
++ power_supply_changed(psy);
++// mutex_unlock(&bat->work_lock);
++}
++
+static int tt_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
@@ -125,6 +204,10 @@
+ int ret = 0;
+ struct tt_bat *bat = container_of(psy, struct tt_bat, psy);
+
++#ifndef BATTERY_POLL
++ tt_bat_update(bat);
++#endif
++
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = bat->status;
@@ -153,6 +236,14 @@
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
++ case POWER_SUPPLY_PROP_MODEL_NAME:
++ val->strval = "Swift";
++ break;
++ case POWER_SUPPLY_PROP_MANUFACTURER:
++ val->strval = "Toby Churchill Ltd";
++ break;
++// case POWER_SUPPLY_PROP_SERIAL_NUMBER:
++// break;
+ default:
+ ret = -EINVAL;
+ break;
@@ -162,53 +253,25 @@
+
+static void tt_bat_external_power_changed(struct power_supply *psy)
+{
-+ schedule_delayed_work(&bat_work, batt_delay);
++ schedule_delayed_work(&bat_work, 1);
+}
+
+static irqreturn_t tt_bat_isr(int irq, void *data)
+{
+ pr_info("%s: vbus changed\n", __func__);
-+ // update in 1/2 sec after volts settled
-+ schedule_delayed_work(&bat_work, msecs_to_jiffies(500));
++ // update in 1/4 sec after volts settled
++ schedule_delayed_work(&bat_work, msecs_to_jiffies(250));
+ return IRQ_HANDLED;
+}
+
-+static void tt_bat_update(struct tt_bat *bat)
-+{
-+ int old_status;
-+ int old_charge_type;
-+ struct power_supply *psy = &bat->psy;
-+
-+ u8 bat_status = samosa_read8(SAMOSA_ADDR_USB_CHG_REG_STATUS);
-+ int vbus_ok = bat_status & (1 << USB_VBUS_OK_BIT);
-+ int charger_present = bat_status & (1 << USB_CHARGER_PRESENT_BIT);
-+ int charge_fast = bat_status & (1 << USB_CHARGE_FAST_BIT);
-+
-+ u16 bat_val;
-+// mutex_lock(&bat->work_lock);
-+ bat_val = tt_read_bat(bat);
-+
-+//pr_info("%s: status vbus %s. Charger %s. Fast charging %s\n", __func__, vbus_ok ? "ok":"absent", charger_present ? "present":"absent", charge_fast ? "on":"off");
-+
-+ old_status = bat->status;
-+ old_charge_type = bat->charge_type;
-+
-+ bat->status = charger_present ? POWER_SUPPLY_STATUS_CHARGING : POWER_SUPPLY_STATUS_DISCHARGING;
-+ bat->charge_type = charger_present ? (charge_fast ? POWER_SUPPLY_CHARGE_TYPE_FAST : POWER_SUPPLY_CHARGE_TYPE_TRICKLE) : POWER_SUPPLY_CHARGE_TYPE_NONE;
-+
-+ if ((old_status != bat->status) || (old_charge_type != bat->charge_type))
-+ power_supply_changed(psy);
-+
-+// mutex_unlock(&bat->work_lock);
-+}
-+
+static void tt_bat_work(struct work_struct *work)
+{
+ tt_bat_update(&tt_bat);
++#ifdef BATTERY_POLL
+ schedule_delayed_work(&bat_work, batt_delay);
++#endif
+}
+
-+
+static enum power_supply_property tt_bat_main_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
@@ -217,13 +280,18 @@
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_PRESENT,
++ POWER_SUPPLY_PROP_MODEL_NAME,
++ POWER_SUPPLY_PROP_MANUFACTURER,
++// POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
+static struct tt_bat tt_bat = {
++ .vbus_status = -1,
+ .status = POWER_SUPPLY_STATUS_DISCHARGING,
+ .full_chrg = -1,
+ .psy = {
-+ .name = "tt-battery",
++ // a standard name for laptop batteries
++ .name = "BAT0",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = tt_bat_main_props,
+ .num_properties = ARRAY_SIZE(tt_bat_main_props),
@@ -237,7 +305,10 @@
+ .bat_max = 5800000,
+ .bat_min = 4400000,
+ .bat_scale = 5000000 / 744,
-+
++#ifdef BATTERY_WARN
++ .bat_warn = 4600000,
++ .bat_warn_counter = 0,
++#endif
+};
+
+#ifdef CONFIG_PM
@@ -249,7 +320,7 @@
+
+static int tt_bat_resume(struct device *dev)
+{
-+ schedule_delayed_work(&bat_work, batt_delay);
++ schedule_delayed_work(&bat_work, msecs_to_jiffies(250));
+ return 0;
+}
+#else
@@ -265,9 +336,12 @@
+ return -ENODEV;
+
+ INIT_DELAYED_WORK(&bat_work, tt_bat_work);
-+ // check battery state every 2 secs
-+ batt_delay = msecs_to_jiffies(2000);
+
++#ifdef BATTERY_POLL
++ // check battery state every sec
++ batt_delay = msecs_to_jiffies(1000);
++#endif
++
+ dev->bits_per_word = 8;
+ ret = spi_setup(dev);
+ if (ret)
@@ -275,7 +349,7 @@
+
+ tt_bat.spi = dev;
+ tt_bat.irq = dev->irq;
-+
++
+ ret = power_supply_register(&dev->dev, &tt_bat.psy);
+ if (ret)
+ goto err_psy_reg_main;
@@ -291,8 +365,13 @@
+ if (ret)
+ goto err_req_main;
+
-+ schedule_delayed_work(&bat_work, batt_delay);
++// ret = sysfs_create_group(&dev->dev.kobj, &tt_bat_attr_group);
++ ret = sysfs_create_group(&tt_bat.psy.dev->kobj, &tt_bat_attr_group);
++ if (ret)
++ dev_err(&dev->dev, "failed to create sysfs entries\n");
+
++ schedule_delayed_work(&bat_work, msecs_to_jiffies(250));
++
+ pr_info("%s: added tt-battery support\n", __func__);
+ return 0;
+
@@ -310,6 +389,8 @@
+static int __devexit tt_bat_remove(struct spi_device *dev)
+{
+
++ sysfs_remove_group(&tt_bat.psy.dev->kobj, &tt_bat_attr_group);
++
+ power_supply_unregister(&tt_bat.psy);
+
+ cancel_delayed_work(&bat_work);