Blame view

drivers/power/bq27x00_battery.c 21.6 KB
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
1
2
3
4
5
  /*
   * BQ27x00 battery driver
   *
   * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
   * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
6
   * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
73c244a8a   Pali Rohár   bq27x00_battery: ...
7
   * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com>
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
8
9
10
11
12
13
14
15
16
17
18
19
   *
   * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
   *
   * This package 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.
   *
   * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
   * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   *
   */
631c17ee5   Pali Rohár   bq27x00: Add new ...
20
21
22
23
24
25
  
  /*
   * Datasheets:
   * http://focus.ti.com/docs/prod/folders/print/bq27000.html
   * http://focus.ti.com/docs/prod/folders/print/bq27500.html
   */
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
26
27
28
29
30
31
32
33
  #include <linux/module.h>
  #include <linux/param.h>
  #include <linux/jiffies.h>
  #include <linux/workqueue.h>
  #include <linux/delay.h>
  #include <linux/platform_device.h>
  #include <linux/power_supply.h>
  #include <linux/idr.h>
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
34
  #include <linux/i2c.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
35
  #include <linux/slab.h>
8aef7e8f8   Harvey Harrison   bq27x00_battery: ...
36
  #include <asm/unaligned.h>
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
37

7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
38
  #include <linux/power/bq27x00_battery.h>
631c17ee5   Pali Rohár   bq27x00: Add new ...
39
  #define DRIVER_VERSION			"1.2.0"
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
40
41
42
  
  #define BQ27x00_REG_TEMP		0x06
  #define BQ27x00_REG_VOLT		0x08
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
43
44
  #define BQ27x00_REG_AI			0x14
  #define BQ27x00_REG_FLAGS		0x0A
4e924a814   Grazvydas Ignotas   power_supply: bq2...
45
46
47
  #define BQ27x00_REG_TTE			0x16
  #define BQ27x00_REG_TTF			0x18
  #define BQ27x00_REG_TTECP		0x26
631c17ee5   Pali Rohár   bq27x00: Add new ...
48
49
50
51
  #define BQ27x00_REG_NAC			0x0C /* Nominal available capaciy */
  #define BQ27x00_REG_LMD			0x12 /* Last measured discharge */
  #define BQ27x00_REG_CYCT		0x2A /* Cycle count total */
  #define BQ27x00_REG_AE			0x22 /* Available enery */
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
52

e20908d95   Grazvydas Ignotas   power_supply: bq2...
53
  #define BQ27000_REG_RSOC		0x0B /* Relative State-of-Charge */
631c17ee5   Pali Rohár   bq27x00: Add new ...
54
  #define BQ27000_REG_ILMD		0x76 /* Initial last measured discharge */
d66bab3f3   Pali Rohár   bq27x00_battery: ...
55
56
  #define BQ27000_FLAG_EDVF		BIT(0) /* Final End-of-Discharge-Voltage flag */
  #define BQ27000_FLAG_EDV1		BIT(1) /* First End-of-Discharge-Voltage flag */
4b226c2cf   Pali Rohár   bq27x00_battery: ...
57
  #define BQ27000_FLAG_CI			BIT(4) /* Capacity Inaccurate flag */
c1b9ab67e   Lars-Peter Clausen   bq27x00: Give mor...
58
  #define BQ27000_FLAG_FC			BIT(5)
d66bab3f3   Pali Rohár   bq27x00_battery: ...
59
  #define BQ27000_FLAG_CHGS		BIT(7) /* Charge state flag */
e20908d95   Grazvydas Ignotas   power_supply: bq2...
60

bf7d41404   Pali Rohár   bq27x00: Minor cl...
61
  #define BQ27500_REG_SOC			0x2C
631c17ee5   Pali Rohár   bq27x00: Add new ...
62
  #define BQ27500_REG_DCAP		0x3C /* Design capacity */
270968c09   Pali Rohár   bq27x00_battery: ...
63
  #define BQ27500_FLAG_DSG		BIT(0) /* Discharging */
d66bab3f3   Pali Rohár   bq27x00_battery: ...
64
65
  #define BQ27500_FLAG_SOCF		BIT(1) /* State-of-Charge threshold final */
  #define BQ27500_FLAG_SOC1		BIT(2) /* State-of-Charge threshold 1 */
270968c09   Pali Rohár   bq27x00_battery: ...
66
67
  #define BQ27500_FLAG_CHG		BIT(8) /* Charging */
  #define BQ27500_FLAG_FC			BIT(9) /* Fully charged */
e20908d95   Grazvydas Ignotas   power_supply: bq2...
68

a2e5118c3   Pali Rohár   bq27x00: Fix CURR...
69
  #define BQ27000_RS			20 /* Resistor sense */
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
70
71
  struct bq27x00_device_info;
  struct bq27x00_access_methods {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
72
  	int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
73
  };
e20908d95   Grazvydas Ignotas   power_supply: bq2...
74
  enum bq27x00_chip { BQ27000, BQ27500 };
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
75
76
77
78
79
  struct bq27x00_reg_cache {
  	int temperature;
  	int time_to_empty;
  	int time_to_empty_avg;
  	int time_to_full;
631c17ee5   Pali Rohár   bq27x00: Add new ...
80
  	int charge_full;
73c244a8a   Pali Rohár   bq27x00_battery: ...
81
  	int cycle_count;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
82
  	int capacity;
a8f6bd23c   Pali Rohár   bq27x00_battery: ...
83
  	int energy;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
84
  	int flags;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
85
  };
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
86
87
88
  struct bq27x00_device_info {
  	struct device 		*dev;
  	int			id;
e20908d95   Grazvydas Ignotas   power_supply: bq2...
89
  	enum bq27x00_chip	chip;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
90

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
91
  	struct bq27x00_reg_cache cache;
631c17ee5   Pali Rohár   bq27x00: Add new ...
92
  	int charge_design_full;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
93
  	unsigned long last_update;
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
94
  	struct delayed_work work;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
95

a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
96
97
98
  	struct power_supply	bat;
  
  	struct bq27x00_access_methods bus;
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
99
100
  
  	struct mutex lock;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
101
102
103
  };
  
  static enum power_supply_property bq27x00_battery_props[] = {
4e924a814   Grazvydas Ignotas   power_supply: bq2...
104
  	POWER_SUPPLY_PROP_STATUS,
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
105
106
107
108
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CAPACITY,
d66bab3f3   Pali Rohár   bq27x00_battery: ...
109
  	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
110
  	POWER_SUPPLY_PROP_TEMP,
4e924a814   Grazvydas Ignotas   power_supply: bq2...
111
112
113
  	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
  	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
  	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
5661f334e   Lars-Peter Clausen   bq27x00: Add type...
114
  	POWER_SUPPLY_PROP_TECHNOLOGY,
631c17ee5   Pali Rohár   bq27x00: Add new ...
115
116
117
  	POWER_SUPPLY_PROP_CHARGE_FULL,
  	POWER_SUPPLY_PROP_CHARGE_NOW,
  	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
73c244a8a   Pali Rohár   bq27x00_battery: ...
118
  	POWER_SUPPLY_PROP_CYCLE_COUNT,
631c17ee5   Pali Rohár   bq27x00: Add new ...
119
  	POWER_SUPPLY_PROP_ENERGY_NOW,
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
120
  };
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
121
122
123
124
  static unsigned int poll_interval = 360;
  module_param(poll_interval, uint, 0644);
  MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
  				"0 disables polling");
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
125
126
127
  /*
   * Common code for BQ27x00 devices
   */
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
128
  static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
129
  		bool single)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
130
  {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
131
  	return di->bus.read(di, reg, single);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
132
133
134
  }
  
  /*
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
135
   * Return the battery Relative State-of-Charge
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
136
137
   * Or < 0 if something fails.
   */
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
138
  static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
139
  {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
140
  	int rsoc;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
141

e20908d95   Grazvydas Ignotas   power_supply: bq2...
142
  	if (di->chip == BQ27500)
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
143
  		rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
e20908d95   Grazvydas Ignotas   power_supply: bq2...
144
  	else
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
145
146
147
  		rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
  
  	if (rsoc < 0)
c6cd4f267   Pali Rohár   bq27x00_battery: ...
148
149
  		dev_dbg(di->dev, "error reading relative State-of-Charge
  ");
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
150
151
  
  	return rsoc;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
152
153
154
  }
  
  /*
631c17ee5   Pali Rohár   bq27x00: Add new ...
155
156
157
158
159
160
161
162
163
   * Return a battery charge value in µAh
   * Or < 0 if something fails.
   */
  static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
  {
  	int charge;
  
  	charge = bq27x00_read(di, reg, false);
  	if (charge < 0) {
c6cd4f267   Pali Rohár   bq27x00_battery: ...
164
165
166
  		dev_dbg(di->dev, "error reading charge register %02x: %d
  ",
  			reg, charge);
631c17ee5   Pali Rohár   bq27x00: Add new ...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  		return charge;
  	}
  
  	if (di->chip == BQ27500)
  		charge *= 1000;
  	else
  		charge = charge * 3570 / BQ27000_RS;
  
  	return charge;
  }
  
  /*
   * Return the battery Nominal available capaciy in µAh
   * Or < 0 if something fails.
   */
  static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
  {
  	return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
  }
  
  /*
   * Return the battery Last measured discharge in µAh
   * Or < 0 if something fails.
   */
  static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di)
  {
  	return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD);
  }
  
  /*
   * Return the battery Initial last measured discharge in µAh
   * Or < 0 if something fails.
   */
  static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
  {
  	int ilmd;
  
  	if (di->chip == BQ27500)
  		ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
  	else
  		ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
  
  	if (ilmd < 0) {
c6cd4f267   Pali Rohár   bq27x00_battery: ...
210
211
  		dev_dbg(di->dev, "error reading initial last measured discharge
  ");
631c17ee5   Pali Rohár   bq27x00: Add new ...
212
213
214
215
216
217
218
219
220
221
222
223
  		return ilmd;
  	}
  
  	if (di->chip == BQ27500)
  		ilmd *= 1000;
  	else
  		ilmd = ilmd * 256 * 3570 / BQ27000_RS;
  
  	return ilmd;
  }
  
  /*
a8f6bd23c   Pali Rohár   bq27x00_battery: ...
224
225
226
227
228
229
230
231
232
   * Return the battery Available energy in µWh
   * Or < 0 if something fails.
   */
  static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
  {
  	int ae;
  
  	ae = bq27x00_read(di, BQ27x00_REG_AE, false);
  	if (ae < 0) {
c6cd4f267   Pali Rohár   bq27x00_battery: ...
233
234
  		dev_dbg(di->dev, "error reading available energy
  ");
a8f6bd23c   Pali Rohár   bq27x00_battery: ...
235
236
237
238
239
240
241
242
243
244
245
246
  		return ae;
  	}
  
  	if (di->chip == BQ27500)
  		ae *= 1000;
  	else
  		ae = ae * 29200 / BQ27000_RS;
  
  	return ae;
  }
  
  /*
d149e98e0   Pali Rohár   bq27x00_battery: ...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
   * Return the battery temperature in tenths of degree Celsius
   * Or < 0 if something fails.
   */
  static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
  {
  	int temp;
  
  	temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
  	if (temp < 0) {
  		dev_err(di->dev, "error reading temperature
  ");
  		return temp;
  	}
  
  	if (di->chip == BQ27500)
  		temp -= 2731;
  	else
  		temp = ((temp * 5) - 5463) / 2;
  
  	return temp;
  }
  
  /*
631c17ee5   Pali Rohár   bq27x00: Add new ...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
   * Return the battery Cycle count total
   * Or < 0 if something fails.
   */
  static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
  {
  	int cyct;
  
  	cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
  	if (cyct < 0)
  		dev_err(di->dev, "error reading cycle count total
  ");
  
  	return cyct;
  }
  
  /*
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
286
287
   * Read a time register.
   * Return < 0 if something fails.
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
288
   */
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
289
  static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
290
  {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
291
  	int tval;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
292

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
293
294
  	tval = bq27x00_read(di, reg, false);
  	if (tval < 0) {
c6cd4f267   Pali Rohár   bq27x00_battery: ...
295
296
297
  		dev_dbg(di->dev, "error reading time register %02x: %d
  ",
  			reg, tval);
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
298
  		return tval;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
299
  	}
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
300
301
302
303
304
305
306
307
308
309
310
311
312
  	if (tval == 65535)
  		return -ENODATA;
  
  	return tval * 60;
  }
  
  static void bq27x00_update(struct bq27x00_device_info *di)
  {
  	struct bq27x00_reg_cache cache = {0, };
  	bool is_bq27500 = di->chip == BQ27500;
  
  	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
  	if (cache.flags >= 0) {
4b226c2cf   Pali Rohár   bq27x00_battery: ...
313
  		if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
c6cd4f267   Pali Rohár   bq27x00_battery: ...
314
315
  			dev_info(di->dev, "battery is not calibrated! ignoring capacity values
  ");
4b226c2cf   Pali Rohár   bq27x00_battery: ...
316
  			cache.capacity = -ENODATA;
a8f6bd23c   Pali Rohár   bq27x00_battery: ...
317
  			cache.energy = -ENODATA;
4b226c2cf   Pali Rohár   bq27x00_battery: ...
318
319
320
321
322
323
  			cache.time_to_empty = -ENODATA;
  			cache.time_to_empty_avg = -ENODATA;
  			cache.time_to_full = -ENODATA;
  			cache.charge_full = -ENODATA;
  		} else {
  			cache.capacity = bq27x00_battery_read_rsoc(di);
a8f6bd23c   Pali Rohár   bq27x00_battery: ...
324
  			cache.energy = bq27x00_battery_read_energy(di);
4b226c2cf   Pali Rohár   bq27x00_battery: ...
325
326
327
328
329
  			cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
  			cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
  			cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
  			cache.charge_full = bq27x00_battery_read_lmd(di);
  		}
d149e98e0   Pali Rohár   bq27x00_battery: ...
330
  		cache.temperature = bq27x00_battery_read_temperature(di);
73c244a8a   Pali Rohár   bq27x00_battery: ...
331
  		cache.cycle_count = bq27x00_battery_read_cyct(di);
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
332

631c17ee5   Pali Rohár   bq27x00: Add new ...
333
334
335
  		/* We only have to read charge design full once */
  		if (di->charge_design_full <= 0)
  			di->charge_design_full = bq27x00_battery_read_ilmd(di);
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
336
  	}
b68f6216c   Pali Rohár   bq27x00_battery: ...
337
  	if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
338
339
340
341
342
343
  		di->cache = cache;
  		power_supply_changed(&di->bat);
  	}
  
  	di->last_update = jiffies;
  }
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
344
345
346
347
348
349
350
351
352
353
354
355
356
  static void bq27x00_battery_poll(struct work_struct *work)
  {
  	struct bq27x00_device_info *di =
  		container_of(work, struct bq27x00_device_info, work.work);
  
  	bq27x00_update(di);
  
  	if (poll_interval > 0) {
  		/* The timer does not have to be accurate. */
  		set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
  		schedule_delayed_work(&di->work, poll_interval * HZ);
  	}
  }
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
357
  /*
bf7d41404   Pali Rohár   bq27x00: Minor cl...
358
   * Return the battery average current in µA
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
359
360
361
   * Note that current can be negative signed as well
   * Or 0 if something fails.
   */
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
362
363
  static int bq27x00_battery_current(struct bq27x00_device_info *di,
  	union power_supply_propval *val)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
364
  {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
365
  	int curr;
b68f6216c   Pali Rohár   bq27x00_battery: ...
366
  	int flags;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
367

b68f6216c   Pali Rohár   bq27x00_battery: ...
368
  	curr = bq27x00_read(di, BQ27x00_REG_AI, false);
c6cd4f267   Pali Rohár   bq27x00_battery: ...
369
370
371
  	if (curr < 0) {
  		dev_err(di->dev, "error reading current
  ");
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
372
  		return curr;
c6cd4f267   Pali Rohár   bq27x00_battery: ...
373
  	}
e20908d95   Grazvydas Ignotas   power_supply: bq2...
374
375
376
  
  	if (di->chip == BQ27500) {
  		/* bq27500 returns signed value */
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
377
  		val->intval = (int)((s16)curr) * 1000;
e20908d95   Grazvydas Ignotas   power_supply: bq2...
378
  	} else {
b68f6216c   Pali Rohár   bq27x00_battery: ...
379
380
  		flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
  		if (flags & BQ27000_FLAG_CHGS) {
e20908d95   Grazvydas Ignotas   power_supply: bq2...
381
382
  			dev_dbg(di->dev, "negative current!
  ");
afbc74fdc   Grazvydas Ignotas   power_supply: bq2...
383
  			curr = -curr;
e20908d95   Grazvydas Ignotas   power_supply: bq2...
384
  		}
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
385

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
386
  		val->intval = curr * 3570 / BQ27000_RS;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
387
  	}
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
388
  	return 0;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
389
  }
4e924a814   Grazvydas Ignotas   power_supply: bq2...
390
  static int bq27x00_battery_status(struct bq27x00_device_info *di,
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
391
  	union power_supply_propval *val)
4e924a814   Grazvydas Ignotas   power_supply: bq2...
392
  {
4e924a814   Grazvydas Ignotas   power_supply: bq2...
393
  	int status;
4e924a814   Grazvydas Ignotas   power_supply: bq2...
394
395
  
  	if (di->chip == BQ27500) {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
396
  		if (di->cache.flags & BQ27500_FLAG_FC)
4e924a814   Grazvydas Ignotas   power_supply: bq2...
397
  			status = POWER_SUPPLY_STATUS_FULL;
270968c09   Pali Rohár   bq27x00_battery: ...
398
  		else if (di->cache.flags & BQ27500_FLAG_DSG)
4e924a814   Grazvydas Ignotas   power_supply: bq2...
399
  			status = POWER_SUPPLY_STATUS_DISCHARGING;
270968c09   Pali Rohár   bq27x00_battery: ...
400
  		else if (di->cache.flags & BQ27500_FLAG_CHG)
4e924a814   Grazvydas Ignotas   power_supply: bq2...
401
  			status = POWER_SUPPLY_STATUS_CHARGING;
270968c09   Pali Rohár   bq27x00_battery: ...
402
403
404
405
  		else if (power_supply_am_i_supplied(&di->bat))
  			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
  		else
  			status = POWER_SUPPLY_STATUS_UNKNOWN;
4e924a814   Grazvydas Ignotas   power_supply: bq2...
406
  	} else {
c1b9ab67e   Lars-Peter Clausen   bq27x00: Give mor...
407
408
409
  		if (di->cache.flags & BQ27000_FLAG_FC)
  			status = POWER_SUPPLY_STATUS_FULL;
  		else if (di->cache.flags & BQ27000_FLAG_CHGS)
4e924a814   Grazvydas Ignotas   power_supply: bq2...
410
  			status = POWER_SUPPLY_STATUS_CHARGING;
c1b9ab67e   Lars-Peter Clausen   bq27x00: Give mor...
411
412
  		else if (power_supply_am_i_supplied(&di->bat))
  			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
4e924a814   Grazvydas Ignotas   power_supply: bq2...
413
414
415
416
417
  		else
  			status = POWER_SUPPLY_STATUS_DISCHARGING;
  	}
  
  	val->intval = status;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
418

4e924a814   Grazvydas Ignotas   power_supply: bq2...
419
420
  	return 0;
  }
d66bab3f3   Pali Rohár   bq27x00_battery: ...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
  	union power_supply_propval *val)
  {
  	int level;
  
  	if (di->chip == BQ27500) {
  		if (di->cache.flags & BQ27500_FLAG_FC)
  			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
  		else if (di->cache.flags & BQ27500_FLAG_SOC1)
  			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
  		else if (di->cache.flags & BQ27500_FLAG_SOCF)
  			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
  		else
  			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
  	} else {
  		if (di->cache.flags & BQ27000_FLAG_FC)
  			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
  		else if (di->cache.flags & BQ27000_FLAG_EDV1)
  			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
  		else if (di->cache.flags & BQ27000_FLAG_EDVF)
  			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
  		else
  			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
  	}
  
  	val->intval = level;
  
  	return 0;
  }
4e924a814   Grazvydas Ignotas   power_supply: bq2...
450
  /*
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
451
452
   * Return the battery Voltage in milivolts
   * Or < 0 if something fails.
4e924a814   Grazvydas Ignotas   power_supply: bq2...
453
   */
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
454
455
  static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
  	union power_supply_propval *val)
4e924a814   Grazvydas Ignotas   power_supply: bq2...
456
  {
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
457
  	int volt;
4e924a814   Grazvydas Ignotas   power_supply: bq2...
458

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
459
  	volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
c6cd4f267   Pali Rohár   bq27x00_battery: ...
460
461
462
  	if (volt < 0) {
  		dev_err(di->dev, "error reading voltage
  ");
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
463
  		return volt;
c6cd4f267   Pali Rohár   bq27x00_battery: ...
464
  	}
4e924a814   Grazvydas Ignotas   power_supply: bq2...
465

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
466
467
468
469
470
471
472
473
474
475
476
477
  	val->intval = volt * 1000;
  
  	return 0;
  }
  
  static int bq27x00_simple_value(int value,
  	union power_supply_propval *val)
  {
  	if (value < 0)
  		return value;
  
  	val->intval = value;
4e924a814   Grazvydas Ignotas   power_supply: bq2...
478

4e924a814   Grazvydas Ignotas   power_supply: bq2...
479
480
  	return 0;
  }
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
481
482
483
484
485
486
487
  #define to_bq27x00_device_info(x) container_of((x), \
  				struct bq27x00_device_info, bat);
  
  static int bq27x00_battery_get_property(struct power_supply *psy,
  					enum power_supply_property psp,
  					union power_supply_propval *val)
  {
4e924a814   Grazvydas Ignotas   power_supply: bq2...
488
  	int ret = 0;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
489
  	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
3413b4ea2   Lars-Peter Clausen   bq27x00: Return -...
490

740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
491
492
493
494
495
496
  	mutex_lock(&di->lock);
  	if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
  		cancel_delayed_work_sync(&di->work);
  		bq27x00_battery_poll(&di->work.work);
  	}
  	mutex_unlock(&di->lock);
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
497
498
  
  	if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
3413b4ea2   Lars-Peter Clausen   bq27x00: Return -...
499
  		return -ENODEV;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
500
501
  
  	switch (psp) {
4e924a814   Grazvydas Ignotas   power_supply: bq2...
502
503
504
  	case POWER_SUPPLY_PROP_STATUS:
  		ret = bq27x00_battery_status(di, val);
  		break;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
505
  	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
506
  		ret = bq27x00_battery_voltage(di, val);
3413b4ea2   Lars-Peter Clausen   bq27x00: Return -...
507
  		break;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
508
  	case POWER_SUPPLY_PROP_PRESENT:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
509
  		val->intval = di->cache.flags < 0 ? 0 : 1;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
510
511
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_NOW:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
512
  		ret = bq27x00_battery_current(di, val);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
513
514
  		break;
  	case POWER_SUPPLY_PROP_CAPACITY:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
515
  		ret = bq27x00_simple_value(di->cache.capacity, val);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
516
  		break;
d66bab3f3   Pali Rohár   bq27x00_battery: ...
517
518
519
  	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
  		ret = bq27x00_battery_capacity_level(di, val);
  		break;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
520
  	case POWER_SUPPLY_PROP_TEMP:
d149e98e0   Pali Rohár   bq27x00_battery: ...
521
  		ret = bq27x00_simple_value(di->cache.temperature, val);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
522
  		break;
4e924a814   Grazvydas Ignotas   power_supply: bq2...
523
  	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
524
  		ret = bq27x00_simple_value(di->cache.time_to_empty, val);
4e924a814   Grazvydas Ignotas   power_supply: bq2...
525
526
  		break;
  	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
527
  		ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val);
4e924a814   Grazvydas Ignotas   power_supply: bq2...
528
529
  		break;
  	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
530
  		ret = bq27x00_simple_value(di->cache.time_to_full, val);
4e924a814   Grazvydas Ignotas   power_supply: bq2...
531
  		break;
5661f334e   Lars-Peter Clausen   bq27x00: Add type...
532
533
534
  	case POWER_SUPPLY_PROP_TECHNOLOGY:
  		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
  		break;
631c17ee5   Pali Rohár   bq27x00: Add new ...
535
536
537
538
539
540
541
542
543
  	case POWER_SUPPLY_PROP_CHARGE_NOW:
  		ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val);
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL:
  		ret = bq27x00_simple_value(di->cache.charge_full, val);
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  		ret = bq27x00_simple_value(di->charge_design_full, val);
  		break;
73c244a8a   Pali Rohár   bq27x00_battery: ...
544
545
  	case POWER_SUPPLY_PROP_CYCLE_COUNT:
  		ret = bq27x00_simple_value(di->cache.cycle_count, val);
631c17ee5   Pali Rohár   bq27x00: Add new ...
546
547
  		break;
  	case POWER_SUPPLY_PROP_ENERGY_NOW:
a8f6bd23c   Pali Rohár   bq27x00_battery: ...
548
  		ret = bq27x00_simple_value(di->cache.energy, val);
631c17ee5   Pali Rohár   bq27x00: Add new ...
549
  		break;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
550
551
552
  	default:
  		return -EINVAL;
  	}
4e924a814   Grazvydas Ignotas   power_supply: bq2...
553
  	return ret;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
554
  }
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
555
556
557
558
559
560
561
  static void bq27x00_external_power_changed(struct power_supply *psy)
  {
  	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
  
  	cancel_delayed_work_sync(&di->work);
  	schedule_delayed_work(&di->work, 0);
  }
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
562
  static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
563
  {
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
564
  	int ret;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
565
566
567
568
  	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
  	di->bat.properties = bq27x00_battery_props;
  	di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
  	di->bat.get_property = bq27x00_battery_get_property;
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
569
570
571
572
  	di->bat.external_power_changed = bq27x00_external_power_changed;
  
  	INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
  	mutex_init(&di->lock);
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
573
574
575
576
577
578
579
580
581
582
  
  	ret = power_supply_register(di->dev, &di->bat);
  	if (ret) {
  		dev_err(di->dev, "failed to register battery: %d
  ", ret);
  		return ret;
  	}
  
  	dev_info(di->dev, "support ver. %s enabled
  ", DRIVER_VERSION);
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
583
  	bq27x00_update(di);
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
584
  	return 0;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
585
  }
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
586
587
  static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
  {
8cfaaa811   Pali Rohár   bq27x00_battery: ...
588
589
590
591
592
593
594
  	/*
  	 * power_supply_unregister call bq27x00_battery_get_property which
  	 * call bq27x00_battery_poll.
  	 * Make sure that bq27x00_battery_poll will not call
  	 * schedule_delayed_work again after unregister (which cause OOPS).
  	 */
  	poll_interval = 0;
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
595
596
597
598
599
600
  	cancel_delayed_work_sync(&di->work);
  
  	power_supply_unregister(&di->bat);
  
  	mutex_destroy(&di->lock);
  }
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
601
602
603
604
605
606
  
  /* i2c specific code */
  #ifdef CONFIG_BATTERY_BQ27X00_I2C
  
  /* If the system has several batteries we need a different name for each
   * of them...
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
607
   */
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
608
609
  static DEFINE_IDR(battery_id);
  static DEFINE_MUTEX(battery_mutex);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
610

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
611
  static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
612
  {
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
613
  	struct i2c_client *client = to_i2c_client(di->dev);
9e912f452   Grazvydas Ignotas   bq27x00: Use sing...
614
  	struct i2c_msg msg[2];
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
615
  	unsigned char data[2];
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
616
  	int ret;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
617
618
619
  
  	if (!client->adapter)
  		return -ENODEV;
9e912f452   Grazvydas Ignotas   bq27x00: Use sing...
620
621
622
623
624
625
626
  	msg[0].addr = client->addr;
  	msg[0].flags = 0;
  	msg[0].buf = &reg;
  	msg[0].len = sizeof(reg);
  	msg[1].addr = client->addr;
  	msg[1].flags = I2C_M_RD;
  	msg[1].buf = data;
2ec523a82   Lars-Peter Clausen   bq27x00: Cleanup ...
627
  	if (single)
9e912f452   Grazvydas Ignotas   bq27x00: Use sing...
628
  		msg[1].len = 1;
2ec523a82   Lars-Peter Clausen   bq27x00: Cleanup ...
629
  	else
9e912f452   Grazvydas Ignotas   bq27x00: Use sing...
630
  		msg[1].len = 2;
2ec523a82   Lars-Peter Clausen   bq27x00: Cleanup ...
631

9e912f452   Grazvydas Ignotas   bq27x00: Use sing...
632
  	ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
2ec523a82   Lars-Peter Clausen   bq27x00: Cleanup ...
633
634
635
636
637
638
639
  	if (ret < 0)
  		return ret;
  
  	if (!single)
  		ret = get_unaligned_le16(data);
  	else
  		ret = data[0];
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
640

297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
641
  	return ret;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
642
  }
e20908d95   Grazvydas Ignotas   power_supply: bq2...
643
  static int bq27x00_battery_probe(struct i2c_client *client,
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
644
645
646
647
  				 const struct i2c_device_id *id)
  {
  	char *name;
  	struct bq27x00_device_info *di;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
648
649
650
651
652
653
654
655
656
657
658
659
  	int num;
  	int retval = 0;
  
  	/* Get new ID for the new battery device */
  	retval = idr_pre_get(&battery_id, GFP_KERNEL);
  	if (retval == 0)
  		return -ENOMEM;
  	mutex_lock(&battery_mutex);
  	retval = idr_get_new(&battery_id, client, &num);
  	mutex_unlock(&battery_mutex);
  	if (retval < 0)
  		return retval;
e20908d95   Grazvydas Ignotas   power_supply: bq2...
660
  	name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
661
662
663
664
665
666
667
668
669
670
671
672
673
674
  	if (!name) {
  		dev_err(&client->dev, "failed to allocate device name
  ");
  		retval = -ENOMEM;
  		goto batt_failed_1;
  	}
  
  	di = kzalloc(sizeof(*di), GFP_KERNEL);
  	if (!di) {
  		dev_err(&client->dev, "failed to allocate device info data
  ");
  		retval = -ENOMEM;
  		goto batt_failed_2;
  	}
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
675

b996ad0e9   Rodolfo Giometti   power_supply: Sup...
676
  	di->id = num;
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
677
  	di->dev = &client->dev;
e20908d95   Grazvydas Ignotas   power_supply: bq2...
678
  	di->chip = id->driver_data;
a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
679
680
  	di->bat.name = name;
  	di->bus.read = &bq27x00_read_i2c;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
681

a40402ef0   Lars-Peter Clausen   bq27x00: Prepare ...
682
  	if (bq27x00_powersupply_init(di))
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
683
  		goto batt_failed_3;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
684
685
  
  	i2c_set_clientdata(client, di);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
686
687
  
  	return 0;
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
688
689
690
691
692
693
694
695
696
697
698
  batt_failed_3:
  	kfree(di);
  batt_failed_2:
  	kfree(name);
  batt_failed_1:
  	mutex_lock(&battery_mutex);
  	idr_remove(&battery_id, num);
  	mutex_unlock(&battery_mutex);
  
  	return retval;
  }
e20908d95   Grazvydas Ignotas   power_supply: bq2...
699
  static int bq27x00_battery_remove(struct i2c_client *client)
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
700
701
  {
  	struct bq27x00_device_info *di = i2c_get_clientdata(client);
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
702
  	bq27x00_powersupply_unregister(di);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
703
704
705
706
707
708
709
710
711
712
713
  
  	kfree(di->bat.name);
  
  	mutex_lock(&battery_mutex);
  	idr_remove(&battery_id, di->id);
  	mutex_unlock(&battery_mutex);
  
  	kfree(di);
  
  	return 0;
  }
e20908d95   Grazvydas Ignotas   power_supply: bq2...
714
715
716
  static const struct i2c_device_id bq27x00_id[] = {
  	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
  	{ "bq27500", BQ27500 },
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
717
718
  	{},
  };
fd9b958c5   Pali Rohár   bq27x00: Add MODU...
719
  MODULE_DEVICE_TABLE(i2c, bq27x00_id);
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
720

e20908d95   Grazvydas Ignotas   power_supply: bq2...
721
  static struct i2c_driver bq27x00_battery_driver = {
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
722
  	.driver = {
e20908d95   Grazvydas Ignotas   power_supply: bq2...
723
  		.name = "bq27x00-battery",
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
724
  	},
e20908d95   Grazvydas Ignotas   power_supply: bq2...
725
726
727
  	.probe = bq27x00_battery_probe,
  	.remove = bq27x00_battery_remove,
  	.id_table = bq27x00_id,
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
728
  };
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  static inline int bq27x00_battery_i2c_init(void)
  {
  	int ret = i2c_add_driver(&bq27x00_battery_driver);
  	if (ret)
  		printk(KERN_ERR "Unable to register BQ27x00 i2c driver
  ");
  
  	return ret;
  }
  
  static inline void bq27x00_battery_i2c_exit(void)
  {
  	i2c_del_driver(&bq27x00_battery_driver);
  }
  
  #else
  
  static inline int bq27x00_battery_i2c_init(void) { return 0; }
  static inline void bq27x00_battery_i2c_exit(void) {};
  
  #endif
  
  /* platform specific code */
  #ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
  
  static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
755
  			bool single)
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  {
  	struct device *dev = di->dev;
  	struct bq27000_platform_data *pdata = dev->platform_data;
  	unsigned int timeout = 3;
  	int upper, lower;
  	int temp;
  
  	if (!single) {
  		/* Make sure the value has not changed in between reading the
  		 * lower and the upper part */
  		upper = pdata->read(dev, reg + 1);
  		do {
  			temp = upper;
  			if (upper < 0)
  				return upper;
  
  			lower = pdata->read(dev, reg);
  			if (lower < 0)
  				return lower;
  
  			upper = pdata->read(dev, reg + 1);
  		} while (temp != upper && --timeout);
  
  		if (timeout == 0)
  			return -EIO;
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
781
  		return (upper << 8) | lower;
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
782
  	}
297a533b3   Lars-Peter Clausen   bq27x00: Cache ba...
783
784
  
  	return pdata->read(dev, reg);
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  }
  
  static int __devinit bq27000_battery_probe(struct platform_device *pdev)
  {
  	struct bq27x00_device_info *di;
  	struct bq27000_platform_data *pdata = pdev->dev.platform_data;
  	int ret;
  
  	if (!pdata) {
  		dev_err(&pdev->dev, "no platform_data supplied
  ");
  		return -EINVAL;
  	}
  
  	if (!pdata->read) {
  		dev_err(&pdev->dev, "no hdq read callback supplied
  ");
  		return -EINVAL;
  	}
  
  	di = kzalloc(sizeof(*di), GFP_KERNEL);
  	if (!di) {
  		dev_err(&pdev->dev, "failed to allocate device info data
  ");
  		return -ENOMEM;
  	}
  
  	platform_set_drvdata(pdev, di);
  
  	di->dev = &pdev->dev;
  	di->chip = BQ27000;
  
  	di->bat.name = pdata->name ?: dev_name(&pdev->dev);
  	di->bus.read = &bq27000_read_platform;
  
  	ret = bq27x00_powersupply_init(di);
  	if (ret)
  		goto err_free;
  
  	return 0;
  
  err_free:
  	platform_set_drvdata(pdev, NULL);
  	kfree(di);
  
  	return ret;
  }
  
  static int __devexit bq27000_battery_remove(struct platform_device *pdev)
  {
  	struct bq27x00_device_info *di = platform_get_drvdata(pdev);
740b755a3   Lars-Peter Clausen   bq27x00: Poll bat...
836
  	bq27x00_powersupply_unregister(di);
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  	platform_set_drvdata(pdev, NULL);
  	kfree(di);
  
  	return 0;
  }
  
  static struct platform_driver bq27000_battery_driver = {
  	.probe	= bq27000_battery_probe,
  	.remove = __devexit_p(bq27000_battery_remove),
  	.driver = {
  		.name = "bq27000-battery",
  		.owner = THIS_MODULE,
  	},
  };
  
  static inline int bq27x00_battery_platform_init(void)
  {
  	int ret = platform_driver_register(&bq27000_battery_driver);
  	if (ret)
  		printk(KERN_ERR "Unable to register BQ27000 platform driver
  ");
  
  	return ret;
  }
  
  static inline void bq27x00_battery_platform_exit(void)
  {
  	platform_driver_unregister(&bq27000_battery_driver);
  }
  
  #else
  
  static inline int bq27x00_battery_platform_init(void) { return 0; }
  static inline void bq27x00_battery_platform_exit(void) {};
  
  #endif
  
  /*
   * Module stuff
   */
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
877
878
879
  static int __init bq27x00_battery_init(void)
  {
  	int ret;
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
880
881
882
883
884
  	ret = bq27x00_battery_i2c_init();
  	if (ret)
  		return ret;
  
  	ret = bq27x00_battery_platform_init();
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
885
  	if (ret)
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
886
  		bq27x00_battery_i2c_exit();
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
887
888
889
890
891
892
893
  
  	return ret;
  }
  module_init(bq27x00_battery_init);
  
  static void __exit bq27x00_battery_exit(void)
  {
7fb7ba588   Lars-Peter Clausen   bq27x00: Add bq27...
894
895
  	bq27x00_battery_platform_exit();
  	bq27x00_battery_i2c_exit();
b996ad0e9   Rodolfo Giometti   power_supply: Sup...
896
897
898
899
900
901
  }
  module_exit(bq27x00_battery_exit);
  
  MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
  MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
  MODULE_LICENSE("GPL");