aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/ds2782_battery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/ds2782_battery.c')
-rw-r--r--drivers/power/ds2782_battery.c184
1 files changed, 136 insertions, 48 deletions
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index ba1bd1a545be..c665e8007235 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -5,6 +5,8 @@
5 * 5 *
6 * Author: Ryan Mallon <ryan@bluewatersys.com> 6 * Author: Ryan Mallon <ryan@bluewatersys.com>
7 * 7 *
8 * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il>
9 *
8 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
@@ -20,12 +22,13 @@
20#include <linux/idr.h> 22#include <linux/idr.h>
21#include <linux/power_supply.h> 23#include <linux/power_supply.h>
22#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/ds2782_battery.h>
23 26
24#define DS2782_REG_RARC 0x06 /* Remaining active relative capacity */ 27#define DS2782_REG_RARC 0x06 /* Remaining active relative capacity */
25 28
26#define DS2782_REG_VOLT_MSB 0x0c 29#define DS278x_REG_VOLT_MSB 0x0c
27#define DS2782_REG_TEMP_MSB 0x0a 30#define DS278x_REG_TEMP_MSB 0x0a
28#define DS2782_REG_CURRENT_MSB 0x0e 31#define DS278x_REG_CURRENT_MSB 0x0e
29 32
30/* EEPROM Block */ 33/* EEPROM Block */
31#define DS2782_REG_RSNSP 0x69 /* Sense resistor value */ 34#define DS2782_REG_RSNSP 0x69 /* Sense resistor value */
@@ -33,18 +36,33 @@
33/* Current unit measurement in uA for a 1 milli-ohm sense resistor */ 36/* Current unit measurement in uA for a 1 milli-ohm sense resistor */
34#define DS2782_CURRENT_UNITS 1563 37#define DS2782_CURRENT_UNITS 1563
35 38
36#define to_ds2782_info(x) container_of(x, struct ds2782_info, battery) 39#define DS2786_REG_RARC 0x02 /* Remaining active relative capacity */
40
41#define DS2786_CURRENT_UNITS 25
42
43struct ds278x_info;
44
45struct ds278x_battery_ops {
46 int (*get_current)(struct ds278x_info *info, int *current_uA);
47 int (*get_voltage)(struct ds278x_info *info, int *voltage_uA);
48 int (*get_capacity)(struct ds278x_info *info, int *capacity_uA);
49
50};
51
52#define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)
37 53
38struct ds2782_info { 54struct ds278x_info {
39 struct i2c_client *client; 55 struct i2c_client *client;
40 struct power_supply battery; 56 struct power_supply battery;
57 struct ds278x_battery_ops *ops;
41 int id; 58 int id;
59 int rsns;
42}; 60};
43 61
44static DEFINE_IDR(battery_id); 62static DEFINE_IDR(battery_id);
45static DEFINE_MUTEX(battery_lock); 63static DEFINE_MUTEX(battery_lock);
46 64
47static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val) 65static inline int ds278x_read_reg(struct ds278x_info *info, int reg, u8 *val)
48{ 66{
49 int ret; 67 int ret;
50 68
@@ -58,7 +76,7 @@ static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val)
58 return 0; 76 return 0;
59} 77}
60 78
61static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb, 79static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb,
62 s16 *val) 80 s16 *val)
63{ 81{
64 int ret; 82 int ret;
@@ -73,7 +91,7 @@ static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb,
73 return 0; 91 return 0;
74} 92}
75 93
76static int ds2782_get_temp(struct ds2782_info *info, int *temp) 94static int ds278x_get_temp(struct ds278x_info *info, int *temp)
77{ 95{
78 s16 raw; 96 s16 raw;
79 int err; 97 int err;
@@ -84,14 +102,14 @@ static int ds2782_get_temp(struct ds2782_info *info, int *temp)
84 * celsius. The temperature value is stored as a 10 bit number, plus 102 * celsius. The temperature value is stored as a 10 bit number, plus
85 * sign in the upper bits of a 16 bit register. 103 * sign in the upper bits of a 16 bit register.
86 */ 104 */
87 err = ds2782_read_reg16(info, DS2782_REG_TEMP_MSB, &raw); 105 err = ds278x_read_reg16(info, DS278x_REG_TEMP_MSB, &raw);
88 if (err) 106 if (err)
89 return err; 107 return err;
90 *temp = ((raw / 32) * 125) / 100; 108 *temp = ((raw / 32) * 125) / 100;
91 return 0; 109 return 0;
92} 110}
93 111
94static int ds2782_get_current(struct ds2782_info *info, int *current_uA) 112static int ds2782_get_current(struct ds278x_info *info, int *current_uA)
95{ 113{
96 int sense_res; 114 int sense_res;
97 int err; 115 int err;
@@ -102,7 +120,7 @@ static int ds2782_get_current(struct ds2782_info *info, int *current_uA)
102 * The units of measurement for current are dependent on the value of 120 * The units of measurement for current are dependent on the value of
103 * the sense resistor. 121 * the sense resistor.
104 */ 122 */
105 err = ds2782_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw); 123 err = ds278x_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw);
106 if (err) 124 if (err)
107 return err; 125 return err;
108 if (sense_res_raw == 0) { 126 if (sense_res_raw == 0) {
@@ -113,14 +131,14 @@ static int ds2782_get_current(struct ds2782_info *info, int *current_uA)
113 131
114 dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n", 132 dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n",
115 sense_res); 133 sense_res);
116 err = ds2782_read_reg16(info, DS2782_REG_CURRENT_MSB, &raw); 134 err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw);
117 if (err) 135 if (err)
118 return err; 136 return err;
119 *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res); 137 *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res);
120 return 0; 138 return 0;
121} 139}
122 140
123static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA) 141static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uA)
124{ 142{
125 s16 raw; 143 s16 raw;
126 int err; 144 int err;
@@ -129,36 +147,77 @@ static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA)
129 * Voltage is measured in units of 4.88mV. The voltage is stored as 147 * Voltage is measured in units of 4.88mV. The voltage is stored as
130 * a 10-bit number plus sign, in the upper bits of a 16-bit register 148 * a 10-bit number plus sign, in the upper bits of a 16-bit register
131 */ 149 */
132 err = ds2782_read_reg16(info, DS2782_REG_VOLT_MSB, &raw); 150 err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
133 if (err) 151 if (err)
134 return err; 152 return err;
135 *voltage_uA = (raw / 32) * 4800; 153 *voltage_uA = (raw / 32) * 4800;
136 return 0; 154 return 0;
137} 155}
138 156
139static int ds2782_get_capacity(struct ds2782_info *info, int *capacity) 157static int ds2782_get_capacity(struct ds278x_info *info, int *capacity)
140{ 158{
141 int err; 159 int err;
142 u8 raw; 160 u8 raw;
143 161
144 err = ds2782_read_reg(info, DS2782_REG_RARC, &raw); 162 err = ds278x_read_reg(info, DS2782_REG_RARC, &raw);
145 if (err) 163 if (err)
146 return err; 164 return err;
147 *capacity = raw; 165 *capacity = raw;
148 return raw; 166 return raw;
149} 167}
150 168
151static int ds2782_get_status(struct ds2782_info *info, int *status) 169static int ds2786_get_current(struct ds278x_info *info, int *current_uA)
170{
171 int err;
172 s16 raw;
173
174 err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw);
175 if (err)
176 return err;
177 *current_uA = (raw / 16) * (DS2786_CURRENT_UNITS / info->rsns);
178 return 0;
179}
180
181static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uA)
182{
183 s16 raw;
184 int err;
185
186 /*
187 * Voltage is measured in units of 1.22mV. The voltage is stored as
188 * a 10-bit number plus sign, in the upper bits of a 16-bit register
189 */
190 err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
191 if (err)
192 return err;
193 *voltage_uA = (raw / 8) * 1220;
194 return 0;
195}
196
197static int ds2786_get_capacity(struct ds278x_info *info, int *capacity)
198{
199 int err;
200 u8 raw;
201
202 err = ds278x_read_reg(info, DS2786_REG_RARC, &raw);
203 if (err)
204 return err;
205 /* Relative capacity is displayed with resolution 0.5 % */
206 *capacity = raw/2 ;
207 return 0;
208}
209
210static int ds278x_get_status(struct ds278x_info *info, int *status)
152{ 211{
153 int err; 212 int err;
154 int current_uA; 213 int current_uA;
155 int capacity; 214 int capacity;
156 215
157 err = ds2782_get_current(info, &current_uA); 216 err = info->ops->get_current(info, &current_uA);
158 if (err) 217 if (err)
159 return err; 218 return err;
160 219
161 err = ds2782_get_capacity(info, &capacity); 220 err = info->ops->get_capacity(info, &capacity);
162 if (err) 221 if (err)
163 return err; 222 return err;
164 223
@@ -174,32 +233,32 @@ static int ds2782_get_status(struct ds2782_info *info, int *status)
174 return 0; 233 return 0;
175} 234}
176 235
177static int ds2782_battery_get_property(struct power_supply *psy, 236static int ds278x_battery_get_property(struct power_supply *psy,
178 enum power_supply_property prop, 237 enum power_supply_property prop,
179 union power_supply_propval *val) 238 union power_supply_propval *val)
180{ 239{
181 struct ds2782_info *info = to_ds2782_info(psy); 240 struct ds278x_info *info = to_ds278x_info(psy);
182 int ret; 241 int ret;
183 242
184 switch (prop) { 243 switch (prop) {
185 case POWER_SUPPLY_PROP_STATUS: 244 case POWER_SUPPLY_PROP_STATUS:
186 ret = ds2782_get_status(info, &val->intval); 245 ret = ds278x_get_status(info, &val->intval);
187 break; 246 break;
188 247
189 case POWER_SUPPLY_PROP_CAPACITY: 248 case POWER_SUPPLY_PROP_CAPACITY:
190 ret = ds2782_get_capacity(info, &val->intval); 249 ret = info->ops->get_capacity(info, &val->intval);
191 break; 250 break;
192 251
193 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 252 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
194 ret = ds2782_get_voltage(info, &val->intval); 253 ret = info->ops->get_voltage(info, &val->intval);
195 break; 254 break;
196 255
197 case POWER_SUPPLY_PROP_CURRENT_NOW: 256 case POWER_SUPPLY_PROP_CURRENT_NOW:
198 ret = ds2782_get_current(info, &val->intval); 257 ret = info->ops->get_current(info, &val->intval);
199 break; 258 break;
200 259
201 case POWER_SUPPLY_PROP_TEMP: 260 case POWER_SUPPLY_PROP_TEMP:
202 ret = ds2782_get_temp(info, &val->intval); 261 ret = ds278x_get_temp(info, &val->intval);
203 break; 262 break;
204 263
205 default: 264 default:
@@ -209,7 +268,7 @@ static int ds2782_battery_get_property(struct power_supply *psy,
209 return ret; 268 return ret;
210} 269}
211 270
212static enum power_supply_property ds2782_battery_props[] = { 271static enum power_supply_property ds278x_battery_props[] = {
213 POWER_SUPPLY_PROP_STATUS, 272 POWER_SUPPLY_PROP_STATUS,
214 POWER_SUPPLY_PROP_CAPACITY, 273 POWER_SUPPLY_PROP_CAPACITY,
215 POWER_SUPPLY_PROP_VOLTAGE_NOW, 274 POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -217,18 +276,18 @@ static enum power_supply_property ds2782_battery_props[] = {
217 POWER_SUPPLY_PROP_TEMP, 276 POWER_SUPPLY_PROP_TEMP,
218}; 277};
219 278
220static void ds2782_power_supply_init(struct power_supply *battery) 279static void ds278x_power_supply_init(struct power_supply *battery)
221{ 280{
222 battery->type = POWER_SUPPLY_TYPE_BATTERY; 281 battery->type = POWER_SUPPLY_TYPE_BATTERY;
223 battery->properties = ds2782_battery_props; 282 battery->properties = ds278x_battery_props;
224 battery->num_properties = ARRAY_SIZE(ds2782_battery_props); 283 battery->num_properties = ARRAY_SIZE(ds278x_battery_props);
225 battery->get_property = ds2782_battery_get_property; 284 battery->get_property = ds278x_battery_get_property;
226 battery->external_power_changed = NULL; 285 battery->external_power_changed = NULL;
227} 286}
228 287
229static int ds2782_battery_remove(struct i2c_client *client) 288static int ds278x_battery_remove(struct i2c_client *client)
230{ 289{
231 struct ds2782_info *info = i2c_get_clientdata(client); 290 struct ds278x_info *info = i2c_get_clientdata(client);
232 291
233 power_supply_unregister(&info->battery); 292 power_supply_unregister(&info->battery);
234 kfree(info->battery.name); 293 kfree(info->battery.name);
@@ -241,13 +300,36 @@ static int ds2782_battery_remove(struct i2c_client *client)
241 return 0; 300 return 0;
242} 301}
243 302
244static int ds2782_battery_probe(struct i2c_client *client, 303static struct ds278x_battery_ops ds278x_ops[] = {
304 [0] = {
305 .get_current = ds2782_get_current,
306 .get_voltage = ds2782_get_voltage,
307 .get_capacity = ds2782_get_capacity,
308 },
309 [1] = {
310 .get_current = ds2786_get_current,
311 .get_voltage = ds2786_get_voltage,
312 .get_capacity = ds2786_get_capacity,
313 }
314};
315
316static int ds278x_battery_probe(struct i2c_client *client,
245 const struct i2c_device_id *id) 317 const struct i2c_device_id *id)
246{ 318{
247 struct ds2782_info *info; 319 struct ds278x_platform_data *pdata = client->dev.platform_data;
320 struct ds278x_info *info;
248 int ret; 321 int ret;
249 int num; 322 int num;
250 323
324 /*
325 * ds2786 should have the sense resistor value set
326 * in the platform data
327 */
328 if (id->driver_data == 1 && !pdata) {
329 dev_err(&client->dev, "missing platform data for ds2786\n");
330 return -EINVAL;
331 }
332
251 /* Get an ID for this battery */ 333 /* Get an ID for this battery */
252 ret = idr_pre_get(&battery_id, GFP_KERNEL); 334 ret = idr_pre_get(&battery_id, GFP_KERNEL);
253 if (ret == 0) { 335 if (ret == 0) {
@@ -267,15 +349,20 @@ static int ds2782_battery_probe(struct i2c_client *client,
267 goto fail_info; 349 goto fail_info;
268 } 350 }
269 351
270 info->battery.name = kasprintf(GFP_KERNEL, "ds2782-%d", num); 352 info->battery.name = kasprintf(GFP_KERNEL, "%s-%d", client->name, num);
271 if (!info->battery.name) { 353 if (!info->battery.name) {
272 ret = -ENOMEM; 354 ret = -ENOMEM;
273 goto fail_name; 355 goto fail_name;
274 } 356 }
275 357
358 if (id->driver_data == 1)
359 info->rsns = pdata->rsns;
360
276 i2c_set_clientdata(client, info); 361 i2c_set_clientdata(client, info);
277 info->client = client; 362 info->client = client;
278 ds2782_power_supply_init(&info->battery); 363 info->id = num;
364 info->ops = &ds278x_ops[id->driver_data];
365 ds278x_power_supply_init(&info->battery);
279 366
280 ret = power_supply_register(&client->dev, &info->battery); 367 ret = power_supply_register(&client->dev, &info->battery);
281 if (ret) { 368 if (ret) {
@@ -297,31 +384,32 @@ fail_id:
297 return ret; 384 return ret;
298} 385}
299 386
300static const struct i2c_device_id ds2782_id[] = { 387static const struct i2c_device_id ds278x_id[] = {
301 {"ds2782", 0}, 388 {"ds2782", 0},
389 {"ds2786", 1},
302 {}, 390 {},
303}; 391};
304 392
305static struct i2c_driver ds2782_battery_driver = { 393static struct i2c_driver ds278x_battery_driver = {
306 .driver = { 394 .driver = {
307 .name = "ds2782-battery", 395 .name = "ds2782-battery",
308 }, 396 },
309 .probe = ds2782_battery_probe, 397 .probe = ds278x_battery_probe,
310 .remove = ds2782_battery_remove, 398 .remove = ds278x_battery_remove,
311 .id_table = ds2782_id, 399 .id_table = ds278x_id,
312}; 400};
313 401
314static int __init ds2782_init(void) 402static int __init ds278x_init(void)
315{ 403{
316 return i2c_add_driver(&ds2782_battery_driver); 404 return i2c_add_driver(&ds278x_battery_driver);
317} 405}
318module_init(ds2782_init); 406module_init(ds278x_init);
319 407
320static void __exit ds2782_exit(void) 408static void __exit ds278x_exit(void)
321{ 409{
322 i2c_del_driver(&ds2782_battery_driver); 410 i2c_del_driver(&ds278x_battery_driver);
323} 411}
324module_exit(ds2782_exit); 412module_exit(ds278x_exit);
325 413
326MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); 414MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
327MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver"); 415MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");