···117118config BATTERY_BQ27x00119 tristate "BQ27x00 battery driver"000000120 depends on I2C0121 help122 Say Y here to enable support for batteries with BQ27x00 (I2C) chips.0000000123124config BATTERY_DA9030125 tristate "DA9030 battery driver"
···117118config BATTERY_BQ27x00119 tristate "BQ27x00 battery driver"120+ help121+ Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.122+123+config BATTERY_BQ27X00_I2C124+ bool "BQ27200/BQ27500 support"125+ depends on BATTERY_BQ27x00126 depends on I2C127+ default y128 help129 Say Y here to enable support for batteries with BQ27x00 (I2C) chips.130+131+config BATTERY_BQ27X00_PLATFORM132+ bool "BQ27000 support"133+ depends on BATTERY_BQ27x00134+ default y135+ help136+ Say Y here to enable support for batteries with BQ27000 (HDQ) chips.137138config BATTERY_DA9030139 tristate "DA9030 battery driver"
+596-207
drivers/power/bq27x00_battery.c
···3 *4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>06 *7 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.8 *···16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.17 *18 */000000019#include <linux/module.h>20#include <linux/param.h>21#include <linux/jiffies.h>···35#include <linux/slab.h>36#include <asm/unaligned.h>3738-#define DRIVER_VERSION "1.1.0"003940#define BQ27x00_REG_TEMP 0x0641#define BQ27x00_REG_VOLT 0x08···46#define BQ27x00_REG_TTE 0x1647#define BQ27x00_REG_TTF 0x1848#define BQ27x00_REG_TTECP 0x2600004950#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */051#define BQ27000_FLAG_CHGS BIT(7)05253-#define BQ27500_REG_SOC 0x2c054#define BQ27500_FLAG_DSC BIT(0)55#define BQ27500_FLAG_FC BIT(9)5657-/* If the system has several batteries we need a different name for each58- * of them...59- */60-static DEFINE_IDR(battery_id);61-static DEFINE_MUTEX(battery_mutex);6263struct bq27x00_device_info;64struct bq27x00_access_methods {65- int (*read)(u8 reg, int *rt_value, int b_single,66- struct bq27x00_device_info *di);67};6869enum bq27x00_chip { BQ27000, BQ27500 };70000000000000071struct bq27x00_device_info {72 struct device *dev;73 int id;74- struct bq27x00_access_methods *bus;75- struct power_supply bat;76 enum bq27x00_chip chip;7778- struct i2c_client *client;000000000079};8081static enum power_supply_property bq27x00_battery_props[] = {···111 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,112 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,113 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,000000114};00000115116/*117 * Common code for BQ27x00 devices118 */119120-static int bq27x00_read(u8 reg, int *rt_value, int b_single,121- struct bq27x00_device_info *di)122{123- return di->bus->read(reg, rt_value, b_single, di);124-}125-126-/*127- * Return the battery temperature in tenths of degree Celsius128- * Or < 0 if something fails.129- */130-static int bq27x00_battery_temperature(struct bq27x00_device_info *di)131-{132- int ret;133- int temp = 0;134-135- ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);136- if (ret) {137- dev_err(di->dev, "error reading temperature\n");138- return ret;139- }140-141- if (di->chip == BQ27500)142- return temp - 2731;143- else144- return ((temp >> 2) - 273) * 10;145-}146-147-/*148- * Return the battery Voltage in milivolts149- * Or < 0 if something fails.150- */151-static int bq27x00_battery_voltage(struct bq27x00_device_info *di)152-{153- int ret;154- int volt = 0;155-156- ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);157- if (ret) {158- dev_err(di->dev, "error reading voltage\n");159- return ret;160- }161-162- return volt * 1000;163-}164-165-/*166- * Return the battery average current167- * Note that current can be negative signed as well168- * Or 0 if something fails.169- */170-static int bq27x00_battery_current(struct bq27x00_device_info *di)171-{172- int ret;173- int curr = 0;174- int flags = 0;175-176- ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);177- if (ret) {178- dev_err(di->dev, "error reading current\n");179- return 0;180- }181-182- if (di->chip == BQ27500) {183- /* bq27500 returns signed value */184- curr = (int)(s16)curr;185- } else {186- ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);187- if (ret < 0) {188- dev_err(di->dev, "error reading flags\n");189- return 0;190- }191- if (flags & BQ27000_FLAG_CHGS) {192- dev_dbg(di->dev, "negative current!\n");193- curr = -curr;194- }195- }196-197- return curr * 1000;198}199200/*201 * Return the battery Relative State-of-Charge202 * Or < 0 if something fails.203 */204-static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)205{206- int ret;207- int rsoc = 0;208209 if (di->chip == BQ27500)210- ret = bq27x00_read(BQ27500_REG_SOC, &rsoc, 0, di);211 else212- ret = bq27x00_read(BQ27000_REG_RSOC, &rsoc, 1, di);213- if (ret) {0214 dev_err(di->dev, "error reading relative State-of-Charge\n");215- return ret;216- }217218 return rsoc;219}220221-static int bq27x00_battery_status(struct bq27x00_device_info *di,222- union power_supply_propval *val)000223{224- int flags = 0;225- int status;226- int ret;227228- ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);229- if (ret < 0) {230- dev_err(di->dev, "error reading flags\n");231- return ret;232 }233234- if (di->chip == BQ27500) {235- if (flags & BQ27500_FLAG_FC)236- status = POWER_SUPPLY_STATUS_FULL;237- else if (flags & BQ27500_FLAG_DSC)238- status = POWER_SUPPLY_STATUS_DISCHARGING;239- else240- status = POWER_SUPPLY_STATUS_CHARGING;241- } else {242- if (flags & BQ27000_FLAG_CHGS)243- status = POWER_SUPPLY_STATUS_CHARGING;244- else245- status = POWER_SUPPLY_STATUS_DISCHARGING;000000000000000000000000000000246 }247248- val->intval = status;249- return 0;0000000000000000000250}251252/*253 * Read a time register.254 * Return < 0 if something fails.255 */256-static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg,257- union power_supply_propval *val)258{259- int tval = 0;260- int ret;261262- ret = bq27x00_read(reg, &tval, 0, di);263- if (ret) {264- dev_err(di->dev, "error reading register %02x\n", reg);265- return ret;266 }267268 if (tval == 65535)269 return -ENODATA;270271- val->intval = tval * 60;0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272 return 0;273}274···446 int ret = 0;447 struct bq27x00_device_info *di = to_bq27x00_device_info(psy);4480000000000449 switch (psp) {450 case POWER_SUPPLY_PROP_STATUS:451 ret = bq27x00_battery_status(di, val);452 break;453 case POWER_SUPPLY_PROP_VOLTAGE_NOW:00454 case POWER_SUPPLY_PROP_PRESENT:455- val->intval = bq27x00_battery_voltage(di);456- if (psp == POWER_SUPPLY_PROP_PRESENT)457- val->intval = val->intval <= 0 ? 0 : 1;458 break;459 case POWER_SUPPLY_PROP_CURRENT_NOW:460- val->intval = bq27x00_battery_current(di);461 break;462 case POWER_SUPPLY_PROP_CAPACITY:463- val->intval = bq27x00_battery_rsoc(di);464 break;465 case POWER_SUPPLY_PROP_TEMP:466- val->intval = bq27x00_battery_temperature(di);467 break;468 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:469- ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val);470 break;471 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:472- ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val);473 break;474 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:475- ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val);000000000000000000476 break;477 default:478 return -EINVAL;···509 return ret;510}511512-static void bq27x00_powersupply_init(struct bq27x00_device_info *di)513{0000000000514 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;515 di->bat.properties = bq27x00_battery_props;516 di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);517 di->bat.get_property = bq27x00_battery_get_property;518- di->bat.external_power_changed = NULL;000000000000000519}520521-/*522- * i2c specific code523- */524-525-static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single,526- struct bq27x00_device_info *di)527{528- struct i2c_client *client = di->client;529- struct i2c_msg msg[1];0000000000000000000530 unsigned char data[2];531- int err;532533 if (!client->adapter)534 return -ENODEV;535536- msg->addr = client->addr;537- msg->flags = 0;538- msg->len = 1;539- msg->buf = data;0000000540541- data[0] = reg;542- err = i2c_transfer(client->adapter, msg, 1);0543544- if (err >= 0) {545- if (!b_single)546- msg->len = 2;547- else548- msg->len = 1;549550- msg->flags = I2C_M_RD;551- err = i2c_transfer(client->adapter, msg, 1);552- if (err >= 0) {553- if (!b_single)554- *rt_value = get_unaligned_le16(data);555- else556- *rt_value = data[0];557-558- return 0;559- }560- }561- return err;562}563564static int bq27x00_battery_probe(struct i2c_client *client,···601{602 char *name;603 struct bq27x00_device_info *di;604- struct bq27x00_access_methods *bus;605 int num;606 int retval = 0;607···627 retval = -ENOMEM;628 goto batt_failed_2;629 }630- di->id = num;631- di->chip = id->driver_data;632633- bus = kzalloc(sizeof(*bus), GFP_KERNEL);634- if (!bus) {635- dev_err(&client->dev, "failed to allocate access method "636- "data\n");637- retval = -ENOMEM;00638 goto batt_failed_3;639- }640641 i2c_set_clientdata(client, di);642- di->dev = &client->dev;643- di->bat.name = name;644- bus->read = &bq27x00_read_i2c;645- di->bus = bus;646- di->client = client;647-648- bq27x00_powersupply_init(di);649-650- retval = power_supply_register(&client->dev, &di->bat);651- if (retval) {652- dev_err(&client->dev, "failed to register battery\n");653- goto batt_failed_4;654- }655-656- dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);657658 return 0;659660-batt_failed_4:661- kfree(bus);662batt_failed_3:663 kfree(di);664batt_failed_2:···657{658 struct bq27x00_device_info *di = i2c_get_clientdata(client);659660- power_supply_unregister(&di->bat);661662- kfree(di->bus);663 kfree(di->bat.name);664665 mutex_lock(&battery_mutex);···670 return 0;671}672673-/*674- * Module stuff675- */676-677static const struct i2c_device_id bq27x00_id[] = {678 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */679 { "bq27500", BQ27500 },680 {},681};0682683static struct i2c_driver bq27x00_battery_driver = {684 .driver = {···686 .id_table = bq27x00_id,687};688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000689static int __init bq27x00_battery_init(void)690{691 int ret;692693- ret = i2c_add_driver(&bq27x00_battery_driver);694 if (ret)695- printk(KERN_ERR "Unable to register BQ27x00 driver\n");0000696697 return ret;698}···851852static void __exit bq27x00_battery_exit(void)853{854- i2c_del_driver(&bq27x00_battery_driver);0855}856module_exit(bq27x00_battery_exit);857
···3 *4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>6+ * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>7 *8 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.9 *···15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.16 *17 */18+19+/*20+ * Datasheets:21+ * http://focus.ti.com/docs/prod/folders/print/bq27000.html22+ * http://focus.ti.com/docs/prod/folders/print/bq27500.html23+ */24+25#include <linux/module.h>26#include <linux/param.h>27#include <linux/jiffies.h>···27#include <linux/slab.h>28#include <asm/unaligned.h>2930+#include <linux/power/bq27x00_battery.h>31+32+#define DRIVER_VERSION "1.2.0"3334#define BQ27x00_REG_TEMP 0x0635#define BQ27x00_REG_VOLT 0x08···36#define BQ27x00_REG_TTE 0x1637#define BQ27x00_REG_TTF 0x1838#define BQ27x00_REG_TTECP 0x2639+#define BQ27x00_REG_NAC 0x0C /* Nominal available capaciy */40+#define BQ27x00_REG_LMD 0x12 /* Last measured discharge */41+#define BQ27x00_REG_CYCT 0x2A /* Cycle count total */42+#define BQ27x00_REG_AE 0x22 /* Available enery */4344#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */45+#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */46#define BQ27000_FLAG_CHGS BIT(7)47+#define BQ27000_FLAG_FC BIT(5)4849+#define BQ27500_REG_SOC 0x2C50+#define BQ27500_REG_DCAP 0x3C /* Design capacity */51#define BQ27500_FLAG_DSC BIT(0)52#define BQ27500_FLAG_FC BIT(9)5354+#define BQ27000_RS 20 /* Resistor sense */00005556struct bq27x00_device_info;57struct bq27x00_access_methods {58+ int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);059};6061enum bq27x00_chip { BQ27000, BQ27500 };6263+struct bq27x00_reg_cache {64+ int temperature;65+ int time_to_empty;66+ int time_to_empty_avg;67+ int time_to_full;68+ int charge_full;69+ int charge_counter;70+ int capacity;71+ int flags;72+73+ int current_now;74+};75+76struct bq27x00_device_info {77 struct device *dev;78 int id;0079 enum bq27x00_chip chip;8081+ struct bq27x00_reg_cache cache;82+ int charge_design_full;83+84+ unsigned long last_update;85+ struct delayed_work work;86+87+ struct power_supply bat;88+89+ struct bq27x00_access_methods bus;90+91+ struct mutex lock;92};9394static enum power_supply_property bq27x00_battery_props[] = {···78 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,79 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,80 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,81+ POWER_SUPPLY_PROP_TECHNOLOGY,82+ POWER_SUPPLY_PROP_CHARGE_FULL,83+ POWER_SUPPLY_PROP_CHARGE_NOW,84+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,85+ POWER_SUPPLY_PROP_CHARGE_COUNTER,86+ POWER_SUPPLY_PROP_ENERGY_NOW,87};88+89+static unsigned int poll_interval = 360;90+module_param(poll_interval, uint, 0644);91+MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \92+ "0 disables polling");9394/*95 * Common code for BQ27x00 devices96 */9798+static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,99+ bool single)100{101+ return di->bus.read(di, reg, single);00000000000000000000000000000000000000000000000000000000000000000000000000102}103104/*105 * Return the battery Relative State-of-Charge106 * Or < 0 if something fails.107 */108+static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)109{110+ int rsoc;0111112 if (di->chip == BQ27500)113+ rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);114 else115+ rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);116+117+ if (rsoc < 0)118 dev_err(di->dev, "error reading relative State-of-Charge\n");00119120 return rsoc;121}122123+/*124+ * Return a battery charge value in µAh125+ * Or < 0 if something fails.126+ */127+static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)128{129+ int charge;00130131+ charge = bq27x00_read(di, reg, false);132+ if (charge < 0) {133+ dev_err(di->dev, "error reading nominal available capacity\n");134+ return charge;135 }136137+ if (di->chip == BQ27500)138+ charge *= 1000;139+ else140+ charge = charge * 3570 / BQ27000_RS;141+142+ return charge;143+}144+145+/*146+ * Return the battery Nominal available capaciy in µAh147+ * Or < 0 if something fails.148+ */149+static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)150+{151+ return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);152+}153+154+/*155+ * Return the battery Last measured discharge in µAh156+ * Or < 0 if something fails.157+ */158+static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di)159+{160+ return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD);161+}162+163+/*164+ * Return the battery Initial last measured discharge in µAh165+ * Or < 0 if something fails.166+ */167+static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)168+{169+ int ilmd;170+171+ if (di->chip == BQ27500)172+ ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);173+ else174+ ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);175+176+ if (ilmd < 0) {177+ dev_err(di->dev, "error reading initial last measured discharge\n");178+ return ilmd;179 }180181+ if (di->chip == BQ27500)182+ ilmd *= 1000;183+ else184+ ilmd = ilmd * 256 * 3570 / BQ27000_RS;185+186+ return ilmd;187+}188+189+/*190+ * Return the battery Cycle count total191+ * Or < 0 if something fails.192+ */193+static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)194+{195+ int cyct;196+197+ cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);198+ if (cyct < 0)199+ dev_err(di->dev, "error reading cycle count total\n");200+201+ return cyct;202}203204/*205 * Read a time register.206 * Return < 0 if something fails.207 */208+static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)0209{210+ int tval;0211212+ tval = bq27x00_read(di, reg, false);213+ if (tval < 0) {214+ dev_err(di->dev, "error reading register %02x: %d\n", reg, tval);215+ return tval;216 }217218 if (tval == 65535)219 return -ENODATA;220221+ return tval * 60;222+}223+224+static void bq27x00_update(struct bq27x00_device_info *di)225+{226+ struct bq27x00_reg_cache cache = {0, };227+ bool is_bq27500 = di->chip == BQ27500;228+229+ cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);230+ if (cache.flags >= 0) {231+ cache.capacity = bq27x00_battery_read_rsoc(di);232+ cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false);233+ cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);234+ cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);235+ cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);236+ cache.charge_full = bq27x00_battery_read_lmd(di);237+ cache.charge_counter = bq27x00_battery_read_cyct(di);238+239+ if (!is_bq27500)240+ cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);241+242+ /* We only have to read charge design full once */243+ if (di->charge_design_full <= 0)244+ di->charge_design_full = bq27x00_battery_read_ilmd(di);245+ }246+247+ /* Ignore current_now which is a snapshot of the current battery state248+ * and is likely to be different even between two consecutive reads */249+ if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {250+ di->cache = cache;251+ power_supply_changed(&di->bat);252+ }253+254+ di->last_update = jiffies;255+}256+257+static void bq27x00_battery_poll(struct work_struct *work)258+{259+ struct bq27x00_device_info *di =260+ container_of(work, struct bq27x00_device_info, work.work);261+262+ bq27x00_update(di);263+264+ if (poll_interval > 0) {265+ /* The timer does not have to be accurate. */266+ set_timer_slack(&di->work.timer, poll_interval * HZ / 4);267+ schedule_delayed_work(&di->work, poll_interval * HZ);268+ }269+}270+271+272+/*273+ * Return the battery temperature in tenths of degree Celsius274+ * Or < 0 if something fails.275+ */276+static int bq27x00_battery_temperature(struct bq27x00_device_info *di,277+ union power_supply_propval *val)278+{279+ if (di->cache.temperature < 0)280+ return di->cache.temperature;281+282+ if (di->chip == BQ27500)283+ val->intval = di->cache.temperature - 2731;284+ else285+ val->intval = ((di->cache.temperature * 5) - 5463) / 2;286+287+ return 0;288+}289+290+/*291+ * Return the battery average current in µA292+ * Note that current can be negative signed as well293+ * Or 0 if something fails.294+ */295+static int bq27x00_battery_current(struct bq27x00_device_info *di,296+ union power_supply_propval *val)297+{298+ int curr;299+300+ if (di->chip == BQ27500)301+ curr = bq27x00_read(di, BQ27x00_REG_AI, false);302+ else303+ curr = di->cache.current_now;304+305+ if (curr < 0)306+ return curr;307+308+ if (di->chip == BQ27500) {309+ /* bq27500 returns signed value */310+ val->intval = (int)((s16)curr) * 1000;311+ } else {312+ if (di->cache.flags & BQ27000_FLAG_CHGS) {313+ dev_dbg(di->dev, "negative current!\n");314+ curr = -curr;315+ }316+317+ val->intval = curr * 3570 / BQ27000_RS;318+ }319+320+ return 0;321+}322+323+static int bq27x00_battery_status(struct bq27x00_device_info *di,324+ union power_supply_propval *val)325+{326+ int status;327+328+ if (di->chip == BQ27500) {329+ if (di->cache.flags & BQ27500_FLAG_FC)330+ status = POWER_SUPPLY_STATUS_FULL;331+ else if (di->cache.flags & BQ27500_FLAG_DSC)332+ status = POWER_SUPPLY_STATUS_DISCHARGING;333+ else334+ status = POWER_SUPPLY_STATUS_CHARGING;335+ } else {336+ if (di->cache.flags & BQ27000_FLAG_FC)337+ status = POWER_SUPPLY_STATUS_FULL;338+ else if (di->cache.flags & BQ27000_FLAG_CHGS)339+ status = POWER_SUPPLY_STATUS_CHARGING;340+ else if (power_supply_am_i_supplied(&di->bat))341+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;342+ else343+ status = POWER_SUPPLY_STATUS_DISCHARGING;344+ }345+346+ val->intval = status;347+348+ return 0;349+}350+351+/*352+ * Return the battery Voltage in milivolts353+ * Or < 0 if something fails.354+ */355+static int bq27x00_battery_voltage(struct bq27x00_device_info *di,356+ union power_supply_propval *val)357+{358+ int volt;359+360+ volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);361+ if (volt < 0)362+ return volt;363+364+ val->intval = volt * 1000;365+366+ return 0;367+}368+369+/*370+ * Return the battery Available energy in µWh371+ * Or < 0 if something fails.372+ */373+static int bq27x00_battery_energy(struct bq27x00_device_info *di,374+ union power_supply_propval *val)375+{376+ int ae;377+378+ ae = bq27x00_read(di, BQ27x00_REG_AE, false);379+ if (ae < 0) {380+ dev_err(di->dev, "error reading available energy\n");381+ return ae;382+ }383+384+ if (di->chip == BQ27500)385+ ae *= 1000;386+ else387+ ae = ae * 29200 / BQ27000_RS;388+389+ val->intval = ae;390+391+ return 0;392+}393+394+395+static int bq27x00_simple_value(int value,396+ union power_supply_propval *val)397+{398+ if (value < 0)399+ return value;400+401+ val->intval = value;402+403 return 0;404}405···249 int ret = 0;250 struct bq27x00_device_info *di = to_bq27x00_device_info(psy);251252+ mutex_lock(&di->lock);253+ if (time_is_before_jiffies(di->last_update + 5 * HZ)) {254+ cancel_delayed_work_sync(&di->work);255+ bq27x00_battery_poll(&di->work.work);256+ }257+ mutex_unlock(&di->lock);258+259+ if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)260+ return -ENODEV;261+262 switch (psp) {263 case POWER_SUPPLY_PROP_STATUS:264 ret = bq27x00_battery_status(di, val);265 break;266 case POWER_SUPPLY_PROP_VOLTAGE_NOW:267+ ret = bq27x00_battery_voltage(di, val);268+ break;269 case POWER_SUPPLY_PROP_PRESENT:270+ val->intval = di->cache.flags < 0 ? 0 : 1;00271 break;272 case POWER_SUPPLY_PROP_CURRENT_NOW:273+ ret = bq27x00_battery_current(di, val);274 break;275 case POWER_SUPPLY_PROP_CAPACITY:276+ ret = bq27x00_simple_value(di->cache.capacity, val);277 break;278 case POWER_SUPPLY_PROP_TEMP:279+ ret = bq27x00_battery_temperature(di, val);280 break;281 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:282+ ret = bq27x00_simple_value(di->cache.time_to_empty, val);283 break;284 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:285+ ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val);286 break;287 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:288+ ret = bq27x00_simple_value(di->cache.time_to_full, val);289+ break;290+ case POWER_SUPPLY_PROP_TECHNOLOGY:291+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;292+ break;293+ case POWER_SUPPLY_PROP_CHARGE_NOW:294+ ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val);295+ break;296+ case POWER_SUPPLY_PROP_CHARGE_FULL:297+ ret = bq27x00_simple_value(di->cache.charge_full, val);298+ break;299+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:300+ ret = bq27x00_simple_value(di->charge_design_full, val);301+ break;302+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:303+ ret = bq27x00_simple_value(di->cache.charge_counter, val);304+ break;305+ case POWER_SUPPLY_PROP_ENERGY_NOW:306+ ret = bq27x00_battery_energy(di, val);307 break;308 default:309 return -EINVAL;···284 return ret;285}286287+static void bq27x00_external_power_changed(struct power_supply *psy)288{289+ struct bq27x00_device_info *di = to_bq27x00_device_info(psy);290+291+ cancel_delayed_work_sync(&di->work);292+ schedule_delayed_work(&di->work, 0);293+}294+295+static int bq27x00_powersupply_init(struct bq27x00_device_info *di)296+{297+ int ret;298+299 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;300 di->bat.properties = bq27x00_battery_props;301 di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);302 di->bat.get_property = bq27x00_battery_get_property;303+ di->bat.external_power_changed = bq27x00_external_power_changed;304+305+ INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);306+ mutex_init(&di->lock);307+308+ ret = power_supply_register(di->dev, &di->bat);309+ if (ret) {310+ dev_err(di->dev, "failed to register battery: %d\n", ret);311+ return ret;312+ }313+314+ dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);315+316+ bq27x00_update(di);317+318+ return 0;319}320321+static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)00000322{323+ cancel_delayed_work_sync(&di->work);324+325+ power_supply_unregister(&di->bat);326+327+ mutex_destroy(&di->lock);328+}329+330+331+/* i2c specific code */332+#ifdef CONFIG_BATTERY_BQ27X00_I2C333+334+/* If the system has several batteries we need a different name for each335+ * of them...336+ */337+static DEFINE_IDR(battery_id);338+static DEFINE_MUTEX(battery_mutex);339+340+static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)341+{342+ struct i2c_client *client = to_i2c_client(di->dev);343+ struct i2c_msg msg[2];344 unsigned char data[2];345+ int ret;346347 if (!client->adapter)348 return -ENODEV;349350+ msg[0].addr = client->addr;351+ msg[0].flags = 0;352+ msg[0].buf = ®353+ msg[0].len = sizeof(reg);354+ msg[1].addr = client->addr;355+ msg[1].flags = I2C_M_RD;356+ msg[1].buf = data;357+ if (single)358+ msg[1].len = 1;359+ else360+ msg[1].len = 2;361362+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));363+ if (ret < 0)364+ return ret;365366+ if (!single)367+ ret = get_unaligned_le16(data);368+ else369+ ret = data[0];0370371+ return ret;00000000000372}373374static int bq27x00_battery_probe(struct i2c_client *client,···341{342 char *name;343 struct bq27x00_device_info *di;0344 int num;345 int retval = 0;346···368 retval = -ENOMEM;369 goto batt_failed_2;370 }00371372+ di->id = num;373+ di->dev = &client->dev;374+ di->chip = id->driver_data;375+ di->bat.name = name;376+ di->bus.read = &bq27x00_read_i2c;377+378+ if (bq27x00_powersupply_init(di))379 goto batt_failed_3;0380381 i2c_set_clientdata(client, di);000000000000000382383 return 0;38400385batt_failed_3:386 kfree(di);387batt_failed_2:···416{417 struct bq27x00_device_info *di = i2c_get_clientdata(client);418419+ bq27x00_powersupply_unregister(di);4200421 kfree(di->bat.name);422423 mutex_lock(&battery_mutex);···430 return 0;431}4320000433static const struct i2c_device_id bq27x00_id[] = {434 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */435 { "bq27500", BQ27500 },436 {},437};438+MODULE_DEVICE_TABLE(i2c, bq27x00_id);439440static struct i2c_driver bq27x00_battery_driver = {441 .driver = {···449 .id_table = bq27x00_id,450};451452+static inline int bq27x00_battery_i2c_init(void)453+{454+ int ret = i2c_add_driver(&bq27x00_battery_driver);455+ if (ret)456+ printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n");457+458+ return ret;459+}460+461+static inline void bq27x00_battery_i2c_exit(void)462+{463+ i2c_del_driver(&bq27x00_battery_driver);464+}465+466+#else467+468+static inline int bq27x00_battery_i2c_init(void) { return 0; }469+static inline void bq27x00_battery_i2c_exit(void) {};470+471+#endif472+473+/* platform specific code */474+#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM475+476+static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,477+ bool single)478+{479+ struct device *dev = di->dev;480+ struct bq27000_platform_data *pdata = dev->platform_data;481+ unsigned int timeout = 3;482+ int upper, lower;483+ int temp;484+485+ if (!single) {486+ /* Make sure the value has not changed in between reading the487+ * lower and the upper part */488+ upper = pdata->read(dev, reg + 1);489+ do {490+ temp = upper;491+ if (upper < 0)492+ return upper;493+494+ lower = pdata->read(dev, reg);495+ if (lower < 0)496+ return lower;497+498+ upper = pdata->read(dev, reg + 1);499+ } while (temp != upper && --timeout);500+501+ if (timeout == 0)502+ return -EIO;503+504+ return (upper << 8) | lower;505+ }506+507+ return pdata->read(dev, reg);508+}509+510+static int __devinit bq27000_battery_probe(struct platform_device *pdev)511+{512+ struct bq27x00_device_info *di;513+ struct bq27000_platform_data *pdata = pdev->dev.platform_data;514+ int ret;515+516+ if (!pdata) {517+ dev_err(&pdev->dev, "no platform_data supplied\n");518+ return -EINVAL;519+ }520+521+ if (!pdata->read) {522+ dev_err(&pdev->dev, "no hdq read callback supplied\n");523+ return -EINVAL;524+ }525+526+ di = kzalloc(sizeof(*di), GFP_KERNEL);527+ if (!di) {528+ dev_err(&pdev->dev, "failed to allocate device info data\n");529+ return -ENOMEM;530+ }531+532+ platform_set_drvdata(pdev, di);533+534+ di->dev = &pdev->dev;535+ di->chip = BQ27000;536+537+ di->bat.name = pdata->name ?: dev_name(&pdev->dev);538+ di->bus.read = &bq27000_read_platform;539+540+ ret = bq27x00_powersupply_init(di);541+ if (ret)542+ goto err_free;543+544+ return 0;545+546+err_free:547+ platform_set_drvdata(pdev, NULL);548+ kfree(di);549+550+ return ret;551+}552+553+static int __devexit bq27000_battery_remove(struct platform_device *pdev)554+{555+ struct bq27x00_device_info *di = platform_get_drvdata(pdev);556+557+ bq27x00_powersupply_unregister(di);558+559+ platform_set_drvdata(pdev, NULL);560+ kfree(di);561+562+ return 0;563+}564+565+static struct platform_driver bq27000_battery_driver = {566+ .probe = bq27000_battery_probe,567+ .remove = __devexit_p(bq27000_battery_remove),568+ .driver = {569+ .name = "bq27000-battery",570+ .owner = THIS_MODULE,571+ },572+};573+574+static inline int bq27x00_battery_platform_init(void)575+{576+ int ret = platform_driver_register(&bq27000_battery_driver);577+ if (ret)578+ printk(KERN_ERR "Unable to register BQ27000 platform driver\n");579+580+ return ret;581+}582+583+static inline void bq27x00_battery_platform_exit(void)584+{585+ platform_driver_unregister(&bq27000_battery_driver);586+}587+588+#else589+590+static inline int bq27x00_battery_platform_init(void) { return 0; }591+static inline void bq27x00_battery_platform_exit(void) {};592+593+#endif594+595+/*596+ * Module stuff597+ */598+599static int __init bq27x00_battery_init(void)600{601 int ret;602603+ ret = bq27x00_battery_i2c_init();604 if (ret)605+ return ret;606+607+ ret = bq27x00_battery_platform_init();608+ if (ret)609+ bq27x00_battery_i2c_exit();610611 return ret;612}···463464static void __exit bq27x00_battery_exit(void)465{466+ bq27x00_battery_platform_exit();467+ bq27x00_battery_i2c_exit();468}469module_exit(bq27x00_battery_exit);470
+2-2
drivers/power/power_supply_core.c
···171 dev_set_drvdata(dev, psy);172 psy->dev = dev;17300174 rc = kobject_set_name(&dev->kobj, "%s", psy->name);175 if (rc)176 goto kobject_set_name_failed;···180 rc = device_add(dev);181 if (rc)182 goto device_add_failed;183-184- INIT_WORK(&psy->changed_work, power_supply_changed_work);185186 rc = power_supply_create_triggers(psy);187 if (rc)
···171 dev_set_drvdata(dev, psy);172 psy->dev = dev;173174+ INIT_WORK(&psy->changed_work, power_supply_changed_work);175+176 rc = kobject_set_name(&dev->kobj, "%s", psy->name);177 if (rc)178 goto kobject_set_name_failed;···178 rc = device_add(dev);179 if (rc)180 goto device_add_failed;00181182 rc = power_supply_create_triggers(psy);183 if (rc)
+1-1
drivers/power/power_supply_sysfs.c
···270 attr = &power_supply_attrs[psy->properties[j]];271272 ret = power_supply_show_property(dev, attr, prop_buf);273- if (ret == -ENODEV) {274 /* When a battery is absent, we expect -ENODEV. Don't abort;275 send the uevent with at least the the PRESENT=0 property */276 ret = 0;
···270 attr = &power_supply_attrs[psy->properties[j]];271272 ret = power_supply_show_property(dev, attr, prop_buf);273+ if (ret == -ENODEV || ret == -ENODATA) {274 /* When a battery is absent, we expect -ENODEV. Don't abort;275 send the uevent with at least the the PRESENT=0 property */276 ret = 0;
+19
include/linux/power/bq27x00_battery.h
···0000000000000000000
···1+#ifndef __LINUX_BQ27X00_BATTERY_H__2+#define __LINUX_BQ27X00_BATTERY_H__3+4+/**5+ * struct bq27000_plaform_data - Platform data for bq27000 devices6+ * @name: Name of the battery. If NULL the driver will fallback to "bq27000".7+ * @read: HDQ read callback.8+ * This function should provide access to the HDQ bus the battery is9+ * connected to.10+ * The first parameter is a pointer to the battery device, the second the11+ * register to be read. The return value should either be the content of12+ * the passed register or an error value.13+ */14+struct bq27000_platform_data {15+ const char *name;16+ int (*read)(struct device *dev, unsigned int);17+};18+19+#endif