blob: 25350fcbadb3889eba7e11620f4f5721d20f7928 [file] [log] [blame]
Rodolfo Giomettib996ad02008-08-20 16:52:58 -07001/*
2 * BQ27x00 battery driver
3 *
4 * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
5 * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +02006 * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
Rodolfo Giomettib996ad02008-08-20 16:52:58 -07007 *
8 * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
9 *
10 * This package is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 */
19#include <linux/module.h>
20#include <linux/param.h>
21#include <linux/jiffies.h>
22#include <linux/workqueue.h>
23#include <linux/delay.h>
24#include <linux/platform_device.h>
25#include <linux/power_supply.h>
26#include <linux/idr.h>
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070027#include <linux/i2c.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090028#include <linux/slab.h>
Harvey Harrison8aef7e82008-09-22 14:53:50 -070029#include <asm/unaligned.h>
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070030
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +020031#include <linux/power/bq27x00_battery.h>
32
Grazvydas Ignotase20908d2010-02-12 23:57:23 +020033#define DRIVER_VERSION "1.1.0"
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070034
35#define BQ27x00_REG_TEMP 0x06
36#define BQ27x00_REG_VOLT 0x08
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070037#define BQ27x00_REG_AI 0x14
38#define BQ27x00_REG_FLAGS 0x0A
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +020039#define BQ27x00_REG_TTE 0x16
40#define BQ27x00_REG_TTF 0x18
41#define BQ27x00_REG_TTECP 0x26
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070042
Grazvydas Ignotase20908d2010-02-12 23:57:23 +020043#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +020044#define BQ27000_FLAG_CHGS BIT(7)
Grazvydas Ignotase20908d2010-02-12 23:57:23 +020045
46#define BQ27500_REG_SOC 0x2c
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +020047#define BQ27500_FLAG_DSC BIT(0)
48#define BQ27500_FLAG_FC BIT(9)
Grazvydas Ignotase20908d2010-02-12 23:57:23 +020049
Pali Rohára2e51182010-05-24 20:52:13 +020050#define BQ27000_RS 20 /* Resistor sense */
51
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070052struct bq27x00_device_info;
53struct bq27x00_access_methods {
Lars-Peter Clausen297a5332011-01-07 20:12:47 +010054 int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070055};
56
Grazvydas Ignotase20908d2010-02-12 23:57:23 +020057enum bq27x00_chip { BQ27000, BQ27500 };
58
Lars-Peter Clausen297a5332011-01-07 20:12:47 +010059struct bq27x00_reg_cache {
60 int temperature;
61 int time_to_empty;
62 int time_to_empty_avg;
63 int time_to_full;
64 int capacity;
65 int flags;
66
67 int current_now;
68};
69
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070070struct bq27x00_device_info {
71 struct device *dev;
72 int id;
Grazvydas Ignotase20908d2010-02-12 23:57:23 +020073 enum bq27x00_chip chip;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070074
Lars-Peter Clausen297a5332011-01-07 20:12:47 +010075 struct bq27x00_reg_cache cache;
76 unsigned long last_update;
Lars-Peter Clausen740b7552011-01-07 20:14:53 +010077 struct delayed_work work;
Lars-Peter Clausen297a5332011-01-07 20:12:47 +010078
Lars-Peter Clausena40402e2010-05-24 19:37:58 +020079 struct power_supply bat;
80
81 struct bq27x00_access_methods bus;
Lars-Peter Clausen740b7552011-01-07 20:14:53 +010082
83 struct mutex lock;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070084};
85
86static enum power_supply_property bq27x00_battery_props[] = {
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +020087 POWER_SUPPLY_PROP_STATUS,
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070088 POWER_SUPPLY_PROP_PRESENT,
89 POWER_SUPPLY_PROP_VOLTAGE_NOW,
90 POWER_SUPPLY_PROP_CURRENT_NOW,
91 POWER_SUPPLY_PROP_CAPACITY,
92 POWER_SUPPLY_PROP_TEMP,
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +020093 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
94 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
95 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
Lars-Peter Clausen5661f332010-05-24 20:36:52 +020096 POWER_SUPPLY_PROP_TECHNOLOGY,
Rodolfo Giomettib996ad02008-08-20 16:52:58 -070097};
98
Lars-Peter Clausen740b7552011-01-07 20:14:53 +010099static unsigned int poll_interval = 360;
100module_param(poll_interval, uint, 0644);
101MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
102 "0 disables polling");
103
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700104/*
105 * Common code for BQ27x00 devices
106 */
107
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200108static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100109 bool single)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700110{
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100111 return di->bus.read(di, reg, single);
112}
113
114/*
115 * Return the battery Relative State-of-Charge
116 * Or < 0 if something fails.
117 */
118static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
119{
120 int rsoc;
121
122 if (di->chip == BQ27500)
123 rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
124 else
125 rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
126
127 if (rsoc < 0)
128 dev_err(di->dev, "error reading relative State-of-Charge\n");
129
130 return rsoc;
131}
132
133/*
134 * Read a time register.
135 * Return < 0 if something fails.
136 */
137static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
138{
139 int tval;
140
141 tval = bq27x00_read(di, reg, false);
142 if (tval < 0) {
143 dev_err(di->dev, "error reading register %02x: %d\n", reg, tval);
144 return tval;
145 }
146
147 if (tval == 65535)
148 return -ENODATA;
149
150 return tval * 60;
151}
152
153static void bq27x00_update(struct bq27x00_device_info *di)
154{
155 struct bq27x00_reg_cache cache = {0, };
156 bool is_bq27500 = di->chip == BQ27500;
157
158 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
159 if (cache.flags >= 0) {
160 cache.capacity = bq27x00_battery_read_rsoc(di);
161 cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false);
162 cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
163 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
164 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
165
166 if (!is_bq27500)
167 cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
168 }
169
170 /* Ignore current_now which is a snapshot of the current battery state
171 * and is likely to be different even between two consecutive reads */
172 if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {
173 di->cache = cache;
174 power_supply_changed(&di->bat);
175 }
176
177 di->last_update = jiffies;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700178}
179
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100180static void bq27x00_battery_poll(struct work_struct *work)
181{
182 struct bq27x00_device_info *di =
183 container_of(work, struct bq27x00_device_info, work.work);
184
185 bq27x00_update(di);
186
187 if (poll_interval > 0) {
188 /* The timer does not have to be accurate. */
189 set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
190 schedule_delayed_work(&di->work, poll_interval * HZ);
191 }
192}
193
194
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700195/*
Grazvydas Ignotasb4de3602010-02-12 23:57:13 +0200196 * Return the battery temperature in tenths of degree Celsius
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700197 * Or < 0 if something fails.
198 */
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100199static int bq27x00_battery_temperature(struct bq27x00_device_info *di,
200 union power_supply_propval *val)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700201{
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100202 if (di->cache.temperature < 0)
203 return di->cache.temperature;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700204
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200205 if (di->chip == BQ27500)
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100206 val->intval = di->cache.temperature - 2731;
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200207 else
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100208 val->intval = ((di->cache.temperature * 5) - 5463) / 2;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700209
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100210 return 0;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700211}
212
213/*
214 * Return the battery average current
215 * Note that current can be negative signed as well
216 * Or 0 if something fails.
217 */
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100218static int bq27x00_battery_current(struct bq27x00_device_info *di,
219 union power_supply_propval *val)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700220{
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100221 int curr;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700222
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100223 if (di->chip == BQ27500)
224 curr = bq27x00_read(di, BQ27x00_REG_AI, false);
225 else
226 curr = di->cache.current_now;
227
228 if (curr < 0)
229 return curr;
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200230
231 if (di->chip == BQ27500) {
232 /* bq27500 returns signed value */
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100233 val->intval = (int)((s16)curr) * 1000;
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200234 } else {
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100235 if (di->cache.flags & BQ27000_FLAG_CHGS) {
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200236 dev_dbg(di->dev, "negative current!\n");
Grazvydas Ignotasafbc74f2010-02-27 17:06:44 +0200237 curr = -curr;
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200238 }
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100239
240 val->intval = curr * 3570 / BQ27000_RS;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700241 }
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200242
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100243 return 0;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700244}
245
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200246static int bq27x00_battery_status(struct bq27x00_device_info *di,
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100247 union power_supply_propval *val)
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200248{
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200249 int status;
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200250
251 if (di->chip == BQ27500) {
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100252 if (di->cache.flags & BQ27500_FLAG_FC)
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200253 status = POWER_SUPPLY_STATUS_FULL;
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100254 else if (di->cache.flags & BQ27500_FLAG_DSC)
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200255 status = POWER_SUPPLY_STATUS_DISCHARGING;
256 else
257 status = POWER_SUPPLY_STATUS_CHARGING;
258 } else {
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100259 if (di->cache.flags & BQ27000_FLAG_CHGS)
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200260 status = POWER_SUPPLY_STATUS_CHARGING;
261 else
262 status = POWER_SUPPLY_STATUS_DISCHARGING;
263 }
264
265 val->intval = status;
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100266
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200267 return 0;
268}
269
270/*
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100271 * Return the battery Voltage in milivolts
272 * Or < 0 if something fails.
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200273 */
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100274static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
275 union power_supply_propval *val)
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200276{
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100277 int volt;
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200278
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100279 volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
280 if (volt < 0)
281 return volt;
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200282
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100283 val->intval = volt * 1000;
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200284
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100285 return 0;
286}
287
288static int bq27x00_simple_value(int value,
289 union power_supply_propval *val)
290{
291 if (value < 0)
292 return value;
293
294 val->intval = value;
295
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200296 return 0;
297}
298
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700299#define to_bq27x00_device_info(x) container_of((x), \
300 struct bq27x00_device_info, bat);
301
302static int bq27x00_battery_get_property(struct power_supply *psy,
303 enum power_supply_property psp,
304 union power_supply_propval *val)
305{
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200306 int ret = 0;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700307 struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
Lars-Peter Clausen3413b4e2010-05-24 21:57:33 +0200308
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100309 mutex_lock(&di->lock);
310 if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
311 cancel_delayed_work_sync(&di->work);
312 bq27x00_battery_poll(&di->work.work);
313 }
314 mutex_unlock(&di->lock);
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100315
316 if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
Lars-Peter Clausen3413b4e2010-05-24 21:57:33 +0200317 return -ENODEV;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700318
319 switch (psp) {
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200320 case POWER_SUPPLY_PROP_STATUS:
321 ret = bq27x00_battery_status(di, val);
322 break;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700323 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100324 ret = bq27x00_battery_voltage(di, val);
Lars-Peter Clausen3413b4e2010-05-24 21:57:33 +0200325 break;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700326 case POWER_SUPPLY_PROP_PRESENT:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100327 val->intval = di->cache.flags < 0 ? 0 : 1;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700328 break;
329 case POWER_SUPPLY_PROP_CURRENT_NOW:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100330 ret = bq27x00_battery_current(di, val);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700331 break;
332 case POWER_SUPPLY_PROP_CAPACITY:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100333 ret = bq27x00_simple_value(di->cache.capacity, val);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700334 break;
335 case POWER_SUPPLY_PROP_TEMP:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100336 ret = bq27x00_battery_temperature(di, val);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700337 break;
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200338 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100339 ret = bq27x00_simple_value(di->cache.time_to_empty, val);
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200340 break;
341 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100342 ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val);
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200343 break;
344 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100345 ret = bq27x00_simple_value(di->cache.time_to_full, val);
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200346 break;
Lars-Peter Clausen5661f332010-05-24 20:36:52 +0200347 case POWER_SUPPLY_PROP_TECHNOLOGY:
348 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
349 break;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700350 default:
351 return -EINVAL;
352 }
353
Grazvydas Ignotas4e924a82010-02-27 17:06:09 +0200354 return ret;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700355}
356
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100357static void bq27x00_external_power_changed(struct power_supply *psy)
358{
359 struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
360
361 cancel_delayed_work_sync(&di->work);
362 schedule_delayed_work(&di->work, 0);
363}
364
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200365static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700366{
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200367 int ret;
368
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700369 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
370 di->bat.properties = bq27x00_battery_props;
371 di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
372 di->bat.get_property = bq27x00_battery_get_property;
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100373 di->bat.external_power_changed = bq27x00_external_power_changed;
374
375 INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
376 mutex_init(&di->lock);
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200377
378 ret = power_supply_register(di->dev, &di->bat);
379 if (ret) {
380 dev_err(di->dev, "failed to register battery: %d\n", ret);
381 return ret;
382 }
383
384 dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
385
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100386 bq27x00_update(di);
387
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200388 return 0;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700389}
390
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100391static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
392{
393 cancel_delayed_work_sync(&di->work);
394
395 power_supply_unregister(&di->bat);
396
397 mutex_destroy(&di->lock);
398}
399
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200400
401/* i2c specific code */
402#ifdef CONFIG_BATTERY_BQ27X00_I2C
403
404/* If the system has several batteries we need a different name for each
405 * of them...
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700406 */
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200407static DEFINE_IDR(battery_id);
408static DEFINE_MUTEX(battery_mutex);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700409
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100410static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700411{
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200412 struct i2c_client *client = to_i2c_client(di->dev);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700413 struct i2c_msg msg[1];
414 unsigned char data[2];
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100415 int ret;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700416
417 if (!client->adapter)
418 return -ENODEV;
419
420 msg->addr = client->addr;
421 msg->flags = 0;
422 msg->len = 1;
423 msg->buf = data;
424
425 data[0] = reg;
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100426 ret = i2c_transfer(client->adapter, msg, 1);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700427
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100428 if (ret >= 0) {
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200429 if (!single)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700430 msg->len = 2;
431 else
432 msg->len = 1;
433
434 msg->flags = I2C_M_RD;
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100435 ret = i2c_transfer(client->adapter, msg, 1);
436 if (ret >= 0) {
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200437 if (!single)
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100438 ret = get_unaligned_le16(data);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700439 else
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100440 ret = data[0];
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700441 }
442 }
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100443 return ret;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700444}
445
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200446static int bq27x00_battery_probe(struct i2c_client *client,
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700447 const struct i2c_device_id *id)
448{
449 char *name;
450 struct bq27x00_device_info *di;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700451 int num;
452 int retval = 0;
453
454 /* Get new ID for the new battery device */
455 retval = idr_pre_get(&battery_id, GFP_KERNEL);
456 if (retval == 0)
457 return -ENOMEM;
458 mutex_lock(&battery_mutex);
459 retval = idr_get_new(&battery_id, client, &num);
460 mutex_unlock(&battery_mutex);
461 if (retval < 0)
462 return retval;
463
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200464 name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700465 if (!name) {
466 dev_err(&client->dev, "failed to allocate device name\n");
467 retval = -ENOMEM;
468 goto batt_failed_1;
469 }
470
471 di = kzalloc(sizeof(*di), GFP_KERNEL);
472 if (!di) {
473 dev_err(&client->dev, "failed to allocate device info data\n");
474 retval = -ENOMEM;
475 goto batt_failed_2;
476 }
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700477
Lars-Peter Clausena40402e2010-05-24 19:37:58 +0200478 di->id = num;
479 di->dev = &client->dev;
480 di->chip = id->driver_data;
481 di->bat.name = name;
482 di->bus.read = &bq27x00_read_i2c;
483
484 if (bq27x00_powersupply_init(di))
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700485 goto batt_failed_3;
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700486
487 i2c_set_clientdata(client, di);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700488
489 return 0;
490
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700491batt_failed_3:
492 kfree(di);
493batt_failed_2:
494 kfree(name);
495batt_failed_1:
496 mutex_lock(&battery_mutex);
497 idr_remove(&battery_id, num);
498 mutex_unlock(&battery_mutex);
499
500 return retval;
501}
502
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200503static int bq27x00_battery_remove(struct i2c_client *client)
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700504{
505 struct bq27x00_device_info *di = i2c_get_clientdata(client);
506
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100507 bq27x00_powersupply_unregister(di);
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700508
509 kfree(di->bat.name);
510
511 mutex_lock(&battery_mutex);
512 idr_remove(&battery_id, di->id);
513 mutex_unlock(&battery_mutex);
514
515 kfree(di);
516
517 return 0;
518}
519
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200520static const struct i2c_device_id bq27x00_id[] = {
521 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */
522 { "bq27500", BQ27500 },
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700523 {},
524};
525
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200526static struct i2c_driver bq27x00_battery_driver = {
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700527 .driver = {
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200528 .name = "bq27x00-battery",
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700529 },
Grazvydas Ignotase20908d2010-02-12 23:57:23 +0200530 .probe = bq27x00_battery_probe,
531 .remove = bq27x00_battery_remove,
532 .id_table = bq27x00_id,
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700533};
534
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200535static inline int bq27x00_battery_i2c_init(void)
536{
537 int ret = i2c_add_driver(&bq27x00_battery_driver);
538 if (ret)
539 printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n");
540
541 return ret;
542}
543
544static inline void bq27x00_battery_i2c_exit(void)
545{
546 i2c_del_driver(&bq27x00_battery_driver);
547}
548
549#else
550
551static inline int bq27x00_battery_i2c_init(void) { return 0; }
552static inline void bq27x00_battery_i2c_exit(void) {};
553
554#endif
555
556/* platform specific code */
557#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
558
559static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100560 bool single)
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200561{
562 struct device *dev = di->dev;
563 struct bq27000_platform_data *pdata = dev->platform_data;
564 unsigned int timeout = 3;
565 int upper, lower;
566 int temp;
567
568 if (!single) {
569 /* Make sure the value has not changed in between reading the
570 * lower and the upper part */
571 upper = pdata->read(dev, reg + 1);
572 do {
573 temp = upper;
574 if (upper < 0)
575 return upper;
576
577 lower = pdata->read(dev, reg);
578 if (lower < 0)
579 return lower;
580
581 upper = pdata->read(dev, reg + 1);
582 } while (temp != upper && --timeout);
583
584 if (timeout == 0)
585 return -EIO;
586
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100587 return (upper << 8) | lower;
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200588 }
Lars-Peter Clausen297a5332011-01-07 20:12:47 +0100589
590 return pdata->read(dev, reg);
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200591}
592
593static int __devinit bq27000_battery_probe(struct platform_device *pdev)
594{
595 struct bq27x00_device_info *di;
596 struct bq27000_platform_data *pdata = pdev->dev.platform_data;
597 int ret;
598
599 if (!pdata) {
600 dev_err(&pdev->dev, "no platform_data supplied\n");
601 return -EINVAL;
602 }
603
604 if (!pdata->read) {
605 dev_err(&pdev->dev, "no hdq read callback supplied\n");
606 return -EINVAL;
607 }
608
609 di = kzalloc(sizeof(*di), GFP_KERNEL);
610 if (!di) {
611 dev_err(&pdev->dev, "failed to allocate device info data\n");
612 return -ENOMEM;
613 }
614
615 platform_set_drvdata(pdev, di);
616
617 di->dev = &pdev->dev;
618 di->chip = BQ27000;
619
620 di->bat.name = pdata->name ?: dev_name(&pdev->dev);
621 di->bus.read = &bq27000_read_platform;
622
623 ret = bq27x00_powersupply_init(di);
624 if (ret)
625 goto err_free;
626
627 return 0;
628
629err_free:
630 platform_set_drvdata(pdev, NULL);
631 kfree(di);
632
633 return ret;
634}
635
636static int __devexit bq27000_battery_remove(struct platform_device *pdev)
637{
638 struct bq27x00_device_info *di = platform_get_drvdata(pdev);
639
Lars-Peter Clausen740b7552011-01-07 20:14:53 +0100640 bq27x00_powersupply_unregister(di);
641
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200642 platform_set_drvdata(pdev, NULL);
643 kfree(di);
644
645 return 0;
646}
647
648static struct platform_driver bq27000_battery_driver = {
649 .probe = bq27000_battery_probe,
650 .remove = __devexit_p(bq27000_battery_remove),
651 .driver = {
652 .name = "bq27000-battery",
653 .owner = THIS_MODULE,
654 },
655};
656
657static inline int bq27x00_battery_platform_init(void)
658{
659 int ret = platform_driver_register(&bq27000_battery_driver);
660 if (ret)
661 printk(KERN_ERR "Unable to register BQ27000 platform driver\n");
662
663 return ret;
664}
665
666static inline void bq27x00_battery_platform_exit(void)
667{
668 platform_driver_unregister(&bq27000_battery_driver);
669}
670
671#else
672
673static inline int bq27x00_battery_platform_init(void) { return 0; }
674static inline void bq27x00_battery_platform_exit(void) {};
675
676#endif
677
678/*
679 * Module stuff
680 */
681
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700682static int __init bq27x00_battery_init(void)
683{
684 int ret;
685
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200686 ret = bq27x00_battery_i2c_init();
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700687 if (ret)
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200688 return ret;
689
690 ret = bq27x00_battery_platform_init();
691 if (ret)
692 bq27x00_battery_i2c_exit();
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700693
694 return ret;
695}
696module_init(bq27x00_battery_init);
697
698static void __exit bq27x00_battery_exit(void)
699{
Lars-Peter Clausen7fb7ba52010-05-24 19:55:27 +0200700 bq27x00_battery_platform_exit();
701 bq27x00_battery_i2c_exit();
Rodolfo Giomettib996ad02008-08-20 16:52:58 -0700702}
703module_exit(bq27x00_battery_exit);
704
705MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
706MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
707MODULE_LICENSE("GPL");