614683faf8
SVN-Revision: 13613
326 lines
10 KiB
Diff
326 lines
10 KiB
Diff
From 8aefbe43a7864e611dca9821daec3e10009e7171 Mon Sep 17 00:00:00 2001
|
|
From: Mike Westerhof <mwester@dls.net>
|
|
Date: Thu, 13 Nov 2008 20:50:55 +0000
|
|
Subject: [PATCH] gta01-battery-driver.patch
|
|
|
|
Adds a simple pass-through battery driver module for the GTA01.
|
|
This will simplify user-space by providing the same sysfs API
|
|
on both GTA01 and GTA02, and is a first step towards eliminating
|
|
the need for APM emulation.
|
|
|
|
Signed-off-by: Mike Westerhof <mwester@dls.net>
|
|
---
|
|
arch/arm/configs/gta02-moredrivers-defconfig | 1 +
|
|
defconfig-gta01 | 1 +
|
|
defconfig-gta02 | 1 +
|
|
drivers/i2c/chips/pcf50606.c | 96 +++++++++++++++++++++++++
|
|
drivers/power/Kconfig | 6 ++
|
|
drivers/power/Makefile | 1 +
|
|
drivers/power/gta01_battery.c | 97 ++++++++++++++++++++++++++
|
|
7 files changed, 203 insertions(+), 0 deletions(-)
|
|
create mode 100644 drivers/power/gta01_battery.c
|
|
|
|
diff --git a/arch/arm/configs/gta02-moredrivers-defconfig b/arch/arm/configs/gta02-moredrivers-defconfig
|
|
index 113eaec..5e1547e 100644
|
|
--- a/arch/arm/configs/gta02-moredrivers-defconfig
|
|
+++ b/arch/arm/configs/gta02-moredrivers-defconfig
|
|
@@ -1060,6 +1060,7 @@ CONFIG_POWER_SUPPLY_DEBUG=y
|
|
CONFIG_PDA_POWER=y
|
|
CONFIG_APM_POWER=y
|
|
# CONFIG_BATTERY_DS2760 is not set
|
|
+# CONFIG_BATTERY_GTA01 is not set
|
|
CONFIG_BATTERY_BQ27000_HDQ=y
|
|
CONFIG_GTA02_HDQ=y
|
|
CONFIG_HWMON=y
|
|
diff --git a/defconfig-gta01 b/defconfig-gta01
|
|
index cecb57f..e2e4330 100644
|
|
--- a/defconfig-gta01
|
|
+++ b/defconfig-gta01
|
|
@@ -1021,6 +1021,7 @@ CONFIG_POWER_SUPPLY=y
|
|
# CONFIG_PDA_POWER is not set
|
|
# CONFIG_APM_POWER is not set
|
|
# CONFIG_BATTERY_DS2760 is not set
|
|
+CONFIG_BATTERY_GTA01=y
|
|
CONFIG_BATTERY_BQ27000_HDQ=y
|
|
CONFIG_GTA02_HDQ=y
|
|
# CONFIG_HWMON is not set
|
|
diff --git a/defconfig-gta02 b/defconfig-gta02
|
|
index 619f7f2..2a6e398 100644
|
|
--- a/defconfig-gta02
|
|
+++ b/defconfig-gta02
|
|
@@ -1021,6 +1021,7 @@ CONFIG_POWER_SUPPLY=y
|
|
# CONFIG_PDA_POWER is not set
|
|
CONFIG_APM_POWER=y
|
|
# CONFIG_BATTERY_DS2760 is not set
|
|
+# CONFIG_BATTERY_GTA01 is not set
|
|
CONFIG_BATTERY_BQ27000_HDQ=y
|
|
CONFIG_GTA02_HDQ=y
|
|
# CONFIG_HWMON is not set
|
|
diff --git a/drivers/i2c/chips/pcf50606.c b/drivers/i2c/chips/pcf50606.c
|
|
index 706ce6d..f585013 100644
|
|
--- a/drivers/i2c/chips/pcf50606.c
|
|
+++ b/drivers/i2c/chips/pcf50606.c
|
|
@@ -50,6 +50,7 @@
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pcf50606.h>
|
|
#include <linux/apm-emulation.h>
|
|
+#include <linux/power_supply.h>
|
|
|
|
#include <asm/mach-types.h>
|
|
#include <asm/arch/gta01.h>
|
|
@@ -141,6 +142,12 @@ struct pcf50606_data {
|
|
|
|
static struct i2c_driver pcf50606_driver;
|
|
|
|
+/* This global is set by the pcf50606 driver to the correct callback
|
|
+ * for the gta01 battery driver. */
|
|
+int (*pmu_bat_get_property)(struct power_supply *, enum power_supply_property,
|
|
+ union power_supply_propval *);
|
|
+EXPORT_SYMBOL(pmu_bat_get_property);
|
|
+
|
|
/* This is an ugly construct on how to access the (currently single/global)
|
|
* pcf50606 handle from other code in the kernel. I didn't really come up with
|
|
* a more decent method of dynamically resolving this */
|
|
@@ -1270,6 +1277,92 @@ static void pcf50606_get_power_status(struct apm_power_info *info)
|
|
}
|
|
|
|
/***********************************************************************
|
|
+ * Battery driver interface
|
|
+ ***********************************************************************/
|
|
+static int pcf50606_bat_get_property(struct power_supply *psy,
|
|
+ enum power_supply_property psp,
|
|
+ union power_supply_propval *val)
|
|
+{
|
|
+ u_int16_t adc, adc_adcin1;
|
|
+ u_int8_t mbcc1, chgmod;
|
|
+ struct pcf50606_data *pcf = pcf50606_global;
|
|
+ int ret = 0;
|
|
+
|
|
+ switch (psp) {
|
|
+
|
|
+ case POWER_SUPPLY_PROP_STATUS:
|
|
+ if (!(reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON)) {
|
|
+ /* No charger, clearly we're discharging then */
|
|
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
|
+ } else {
|
|
+
|
|
+ /* We have a charger present, get charge mode */
|
|
+ mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
|
|
+ chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK);
|
|
+ switch (chgmod) {
|
|
+
|
|
+ /* TODO: How to determine POWER_SUPPLY_STATUS_FULL? */
|
|
+
|
|
+ case PCF50606_MBCC1_CHGMOD_QUAL:
|
|
+ case PCF50606_MBCC1_CHGMOD_PRE:
|
|
+ case PCF50606_MBCC1_CHGMOD_IDLE:
|
|
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
|
+ break;
|
|
+
|
|
+ case PCF50606_MBCC1_CHGMOD_TRICKLE:
|
|
+ case PCF50606_MBCC1_CHGMOD_FAST_CCCV:
|
|
+ case PCF50606_MBCC1_CHGMOD_FAST_NOCC:
|
|
+ case PCF50606_MBCC1_CHGMOD_FAST_NOCV:
|
|
+ case PCF50606_MBCC1_CHGMOD_FAST_SW:
|
|
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
|
|
+ break;
|
|
+
|
|
+ }
|
|
+ }
|
|
+
|
|
+ case POWER_SUPPLY_PROP_PRESENT:
|
|
+ val->intval = 1; /* Must be, or the magic smoke comes out */
|
|
+ break;
|
|
+
|
|
+ case POWER_SUPPLY_PROP_ONLINE:
|
|
+ val->intval = !!(reg_read(pcf, PCF50606_REG_OOCS) &
|
|
+ PCF50606_OOCS_EXTON);
|
|
+ break;
|
|
+
|
|
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
|
+ adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_RES, NULL);
|
|
+ /* (adc * 6000000) / 1024 == (adc * 46875) / 8 */
|
|
+ val->intval = (adc * 46875) / 8;
|
|
+ break;
|
|
+
|
|
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
|
|
+ adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_ADCIN1,
|
|
+ &adc_adcin1);
|
|
+ val->intval = adc_to_chg_milliamps(pcf, adc_adcin1, adc) * 1000;
|
|
+ break;
|
|
+
|
|
+ case POWER_SUPPLY_PROP_TEMP:
|
|
+ adc = adc_read(pcf, PCF50606_ADCMUX_BATTEMP, NULL);
|
|
+ val->intval = rntc_to_temp(adc_to_rntc(pcf, adc)) * 10;
|
|
+ break;
|
|
+
|
|
+ case POWER_SUPPLY_PROP_CAPACITY:
|
|
+ val->intval = battvolt_scale(pcf50606_battvolt(pcf));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ ret = -EINVAL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/***********************************************************************
|
|
* RTC
|
|
***********************************************************************/
|
|
|
|
@@ -1900,6 +1993,7 @@ static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind)
|
|
}
|
|
|
|
apm_get_power_status = pcf50606_get_power_status;
|
|
+ pmu_bat_get_property = pcf50606_bat_get_property;
|
|
|
|
#ifdef CONFIG_MACH_NEO1973_GTA01
|
|
if (machine_is_neo1973_gta01()) {
|
|
@@ -1962,6 +2056,8 @@ static int pcf50606_detach_client(struct i2c_client *client)
|
|
struct pcf50606_data *pcf = i2c_get_clientdata(client);
|
|
|
|
apm_get_power_status = NULL;
|
|
+ pmu_bat_get_property = NULL;
|
|
+
|
|
input_unregister_device(pcf->input_dev);
|
|
|
|
if (pcf->pdata->used_features & PCF50606_FEAT_PWM_BL)
|
|
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
|
|
index 8c50ecb..470e08c 100644
|
|
--- a/drivers/power/Kconfig
|
|
+++ b/drivers/power/Kconfig
|
|
@@ -62,5 +62,11 @@ config GTA02_HDQ
|
|
on the Neo Freerunner. You probably want to select
|
|
at least BATTERY_BQ27000_HDQ as well
|
|
|
|
+config BATTERY_GTA01
|
|
+ tristate "Neo GTA01 battery"
|
|
+ depends on MACH_NEO1973_GTA01
|
|
+ help
|
|
+ Say Y to enable support for the battery on the Neo GTA01
|
|
+
|
|
endif # POWER_SUPPLY
|
|
|
|
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
|
|
index d7e87ad..2013e89 100644
|
|
--- a/drivers/power/Makefile
|
|
+++ b/drivers/power/Makefile
|
|
@@ -21,5 +21,6 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
|
|
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
|
|
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
|
|
obj-$(CONFIG_BATTERY_BQ27000_HDQ) += bq27000_battery.o
|
|
+obj-$(CONFIG_BATTERY_GTA01) += gta01_battery.o
|
|
|
|
obj-$(CONFIG_GTA02_HDQ) += gta02_hdq.o
|
|
diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c
|
|
new file mode 100644
|
|
index 0000000..5acb45c
|
|
--- /dev/null
|
|
+++ b/drivers/power/gta01_battery.c
|
|
@@ -0,0 +1,97 @@
|
|
+/*
|
|
+ * Battery driver for the Openmoko GTA01 device, using the pcf50606 chip.
|
|
+ *
|
|
+ * This is nothing more than a write-thru interface to the real logic,
|
|
+ * which is part of the pcf50606.c multifunction chip driver.
|
|
+ * Copyright © 2008 Mike Westerhof <mwester@dls.net>
|
|
+ *
|
|
+ *
|
|
+ * Portions liberally borrowed from olpc_battery.c, copyright below:
|
|
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
|
|
+ *
|
|
+ * 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/err.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/power_supply.h>
|
|
+#include <linux/jiffies.h>
|
|
+#include <linux/sched.h>
|
|
+
|
|
+/*********************************************************************
|
|
+ * This global is set by the pcf50606 driver to the correct callback
|
|
+ *********************************************************************/
|
|
+
|
|
+extern int (*pmu_bat_get_property)(struct power_supply *,
|
|
+ enum power_supply_property,
|
|
+ union power_supply_propval *);
|
|
+
|
|
+
|
|
+/*********************************************************************
|
|
+ * Battery properties
|
|
+ *********************************************************************/
|
|
+static int gta01_bat_get_property(struct power_supply *psy,
|
|
+ enum power_supply_property psp,
|
|
+ union power_supply_propval *val)
|
|
+{
|
|
+ if (pmu_bat_get_property)
|
|
+ return (pmu_bat_get_property)(psy, psp, val);
|
|
+ else
|
|
+ return -ENODEV;
|
|
+}
|
|
+
|
|
+static enum power_supply_property gta01_bat_props[] = {
|
|
+ POWER_SUPPLY_PROP_STATUS,
|
|
+ POWER_SUPPLY_PROP_PRESENT,
|
|
+ POWER_SUPPLY_PROP_ONLINE,
|
|
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
|
+ POWER_SUPPLY_PROP_CURRENT_NOW,
|
|
+ POWER_SUPPLY_PROP_TEMP,
|
|
+ POWER_SUPPLY_PROP_CAPACITY,
|
|
+};
|
|
+
|
|
+/*********************************************************************
|
|
+ * Initialisation
|
|
+ *********************************************************************/
|
|
+
|
|
+static struct platform_device *bat_pdev;
|
|
+
|
|
+static struct power_supply gta01_bat = {
|
|
+ .properties = gta01_bat_props,
|
|
+ .num_properties = ARRAY_SIZE(gta01_bat_props),
|
|
+ .get_property = gta01_bat_get_property,
|
|
+ .use_for_apm = 0, /* pcf50606 driver has its own apm driver */
|
|
+};
|
|
+
|
|
+static int __init gta01_bat_init(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ bat_pdev = platform_device_register_simple("gta01-battery", 0, NULL, 0);
|
|
+ if (IS_ERR(bat_pdev))
|
|
+ return PTR_ERR(bat_pdev);
|
|
+
|
|
+ gta01_bat.name = bat_pdev->name;
|
|
+
|
|
+ ret = power_supply_register(&bat_pdev->dev, >a01_bat);
|
|
+ if (ret)
|
|
+ platform_device_unregister(bat_pdev);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void __exit gta01_bat_exit(void)
|
|
+{
|
|
+ power_supply_unregister(>a01_bat);
|
|
+ platform_device_unregister(bat_pdev);
|
|
+}
|
|
+
|
|
+module_init(gta01_bat_init);
|
|
+module_exit(gta01_bat_exit);
|
|
+
|
|
+MODULE_AUTHOR("Mike Westerhof <mwester@dls.net>");
|
|
+MODULE_LICENSE("GPL");
|
|
+MODULE_DESCRIPTION("Battery driver for GTA01");
|
|
--
|
|
1.5.6.5
|
|
|