]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/power/ds2782_battery.c
[SCSI] ipr: Fix oops while resetting an ipr adapter
[karo-tx-linux.git] / drivers / power / ds2782_battery.c
1 /*
2  * I2C client/driver for the Maxim/Dallas DS2782 Stand-Alone Fuel Gauge IC
3  *
4  * Copyright (C) 2009 Bluewater Systems Ltd
5  *
6  * Author: Ryan Mallon
7  *
8  * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il>
9  *
10  * This program 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  */
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/errno.h>
20 #include <linux/swab.h>
21 #include <linux/i2c.h>
22 #include <linux/idr.h>
23 #include <linux/power_supply.h>
24 #include <linux/slab.h>
25 #include <linux/ds2782_battery.h>
26
27 #define DS2782_REG_RARC         0x06    /* Remaining active relative capacity */
28
29 #define DS278x_REG_VOLT_MSB     0x0c
30 #define DS278x_REG_TEMP_MSB     0x0a
31 #define DS278x_REG_CURRENT_MSB  0x0e
32
33 /* EEPROM Block */
34 #define DS2782_REG_RSNSP        0x69    /* Sense resistor value */
35
36 /* Current unit measurement in uA for a 1 milli-ohm sense resistor */
37 #define DS2782_CURRENT_UNITS    1563
38
39 #define DS2786_REG_RARC         0x02    /* Remaining active relative capacity */
40
41 #define DS2786_CURRENT_UNITS    25
42
43 struct ds278x_info;
44
45 struct ds278x_battery_ops {
46         int (*get_battery_current)(struct ds278x_info *info, int *current_uA);
47         int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uV);
48         int (*get_battery_capacity)(struct ds278x_info *info, int *capacity);
49 };
50
51 #define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)
52
53 struct ds278x_info {
54         struct i2c_client       *client;
55         struct power_supply     battery;
56         struct ds278x_battery_ops  *ops;
57         int                     id;
58         int                     rsns;
59 };
60
61 static DEFINE_IDR(battery_id);
62 static DEFINE_MUTEX(battery_lock);
63
64 static inline int ds278x_read_reg(struct ds278x_info *info, int reg, u8 *val)
65 {
66         int ret;
67
68         ret = i2c_smbus_read_byte_data(info->client, reg);
69         if (ret < 0) {
70                 dev_err(&info->client->dev, "register read failed\n");
71                 return ret;
72         }
73
74         *val = ret;
75         return 0;
76 }
77
78 static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb,
79                                     s16 *val)
80 {
81         int ret;
82
83         ret = i2c_smbus_read_word_data(info->client, reg_msb);
84         if (ret < 0) {
85                 dev_err(&info->client->dev, "register read failed\n");
86                 return ret;
87         }
88
89         *val = swab16(ret);
90         return 0;
91 }
92
93 static int ds278x_get_temp(struct ds278x_info *info, int *temp)
94 {
95         s16 raw;
96         int err;
97
98         /*
99          * Temperature is measured in units of 0.125 degrees celcius, the
100          * power_supply class measures temperature in tenths of degrees
101          * celsius. The temperature value is stored as a 10 bit number, plus
102          * sign in the upper bits of a 16 bit register.
103          */
104         err = ds278x_read_reg16(info, DS278x_REG_TEMP_MSB, &raw);
105         if (err)
106                 return err;
107         *temp = ((raw / 32) * 125) / 100;
108         return 0;
109 }
110
111 static int ds2782_get_current(struct ds278x_info *info, int *current_uA)
112 {
113         int sense_res;
114         int err;
115         u8 sense_res_raw;
116         s16 raw;
117
118         /*
119          * The units of measurement for current are dependent on the value of
120          * the sense resistor.
121          */
122         err = ds278x_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw);
123         if (err)
124                 return err;
125         if (sense_res_raw == 0) {
126                 dev_err(&info->client->dev, "sense resistor value is 0\n");
127                 return -ENXIO;
128         }
129         sense_res = 1000 / sense_res_raw;
130
131         dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n",
132                 sense_res);
133         err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw);
134         if (err)
135                 return err;
136         *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res);
137         return 0;
138 }
139
140 static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uV)
141 {
142         s16 raw;
143         int err;
144
145         /*
146          * Voltage is measured in units of 4.88mV. The voltage is stored as
147          * a 10-bit number plus sign, in the upper bits of a 16-bit register
148          */
149         err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
150         if (err)
151                 return err;
152         *voltage_uV = (raw / 32) * 4800;
153         return 0;
154 }
155
156 static int ds2782_get_capacity(struct ds278x_info *info, int *capacity)
157 {
158         int err;
159         u8 raw;
160
161         err = ds278x_read_reg(info, DS2782_REG_RARC, &raw);
162         if (err)
163                 return err;
164         *capacity = raw;
165         return 0;
166 }
167
168 static int ds2786_get_current(struct ds278x_info *info, int *current_uA)
169 {
170         int err;
171         s16 raw;
172
173         err = ds278x_read_reg16(info, DS278x_REG_CURRENT_MSB, &raw);
174         if (err)
175                 return err;
176         *current_uA = (raw / 16) * (DS2786_CURRENT_UNITS / info->rsns);
177         return 0;
178 }
179
180 static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uV)
181 {
182         s16 raw;
183         int err;
184
185         /*
186          * Voltage is measured in units of 1.22mV. The voltage is stored as
187          * a 10-bit number plus sign, in the upper bits of a 16-bit register
188          */
189         err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
190         if (err)
191                 return err;
192         *voltage_uV = (raw / 8) * 1220;
193         return 0;
194 }
195
196 static int ds2786_get_capacity(struct ds278x_info *info, int *capacity)
197 {
198         int err;
199         u8 raw;
200
201         err = ds278x_read_reg(info, DS2786_REG_RARC, &raw);
202         if (err)
203                 return err;
204         /* Relative capacity is displayed with resolution 0.5 % */
205         *capacity = raw/2 ;
206         return 0;
207 }
208
209 static int ds278x_get_status(struct ds278x_info *info, int *status)
210 {
211         int err;
212         int current_uA;
213         int capacity;
214
215         err = info->ops->get_battery_current(info, &current_uA);
216         if (err)
217                 return err;
218
219         err = info->ops->get_battery_capacity(info, &capacity);
220         if (err)
221                 return err;
222
223         if (capacity == 100)
224                 *status = POWER_SUPPLY_STATUS_FULL;
225         else if (current_uA == 0)
226                 *status = POWER_SUPPLY_STATUS_NOT_CHARGING;
227         else if (current_uA < 0)
228                 *status = POWER_SUPPLY_STATUS_DISCHARGING;
229         else
230                 *status = POWER_SUPPLY_STATUS_CHARGING;
231
232         return 0;
233 }
234
235 static int ds278x_battery_get_property(struct power_supply *psy,
236                                        enum power_supply_property prop,
237                                        union power_supply_propval *val)
238 {
239         struct ds278x_info *info = to_ds278x_info(psy);
240         int ret;
241
242         switch (prop) {
243         case POWER_SUPPLY_PROP_STATUS:
244                 ret = ds278x_get_status(info, &val->intval);
245                 break;
246
247         case POWER_SUPPLY_PROP_CAPACITY:
248                 ret = info->ops->get_battery_capacity(info, &val->intval);
249                 break;
250
251         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
252                 ret = info->ops->get_battery_voltage(info, &val->intval);
253                 break;
254
255         case POWER_SUPPLY_PROP_CURRENT_NOW:
256                 ret = info->ops->get_battery_current(info, &val->intval);
257                 break;
258
259         case POWER_SUPPLY_PROP_TEMP:
260                 ret = ds278x_get_temp(info, &val->intval);
261                 break;
262
263         default:
264                 ret = -EINVAL;
265         }
266
267         return ret;
268 }
269
270 static enum power_supply_property ds278x_battery_props[] = {
271         POWER_SUPPLY_PROP_STATUS,
272         POWER_SUPPLY_PROP_CAPACITY,
273         POWER_SUPPLY_PROP_VOLTAGE_NOW,
274         POWER_SUPPLY_PROP_CURRENT_NOW,
275         POWER_SUPPLY_PROP_TEMP,
276 };
277
278 static void ds278x_power_supply_init(struct power_supply *battery)
279 {
280         battery->type                   = POWER_SUPPLY_TYPE_BATTERY;
281         battery->properties             = ds278x_battery_props;
282         battery->num_properties         = ARRAY_SIZE(ds278x_battery_props);
283         battery->get_property           = ds278x_battery_get_property;
284         battery->external_power_changed = NULL;
285 }
286
287 static int ds278x_battery_remove(struct i2c_client *client)
288 {
289         struct ds278x_info *info = i2c_get_clientdata(client);
290
291         power_supply_unregister(&info->battery);
292         kfree(info->battery.name);
293
294         mutex_lock(&battery_lock);
295         idr_remove(&battery_id, info->id);
296         mutex_unlock(&battery_lock);
297
298         kfree(info);
299         return 0;
300 }
301
302 enum ds278x_num_id {
303         DS2782 = 0,
304         DS2786,
305 };
306
307 static struct ds278x_battery_ops ds278x_ops[] = {
308         [DS2782] = {
309                 .get_battery_current  = ds2782_get_current,
310                 .get_battery_voltage  = ds2782_get_voltage,
311                 .get_battery_capacity = ds2782_get_capacity,
312         },
313         [DS2786] = {
314                 .get_battery_current  = ds2786_get_current,
315                 .get_battery_voltage  = ds2786_get_voltage,
316                 .get_battery_capacity = ds2786_get_capacity,
317         }
318 };
319
320 static int ds278x_battery_probe(struct i2c_client *client,
321                                 const struct i2c_device_id *id)
322 {
323         struct ds278x_platform_data *pdata = client->dev.platform_data;
324         struct ds278x_info *info;
325         int ret;
326         int num;
327
328         /*
329          * ds2786 should have the sense resistor value set
330          * in the platform data
331          */
332         if (id->driver_data == DS2786 && !pdata) {
333                 dev_err(&client->dev, "missing platform data for ds2786\n");
334                 return -EINVAL;
335         }
336
337         /* Get an ID for this battery */
338         ret = idr_pre_get(&battery_id, GFP_KERNEL);
339         if (ret == 0) {
340                 ret = -ENOMEM;
341                 goto fail_id;
342         }
343
344         mutex_lock(&battery_lock);
345         ret = idr_get_new(&battery_id, client, &num);
346         mutex_unlock(&battery_lock);
347         if (ret < 0)
348                 goto fail_id;
349
350         info = kzalloc(sizeof(*info), GFP_KERNEL);
351         if (!info) {
352                 ret = -ENOMEM;
353                 goto fail_info;
354         }
355
356         info->battery.name = kasprintf(GFP_KERNEL, "%s-%d", client->name, num);
357         if (!info->battery.name) {
358                 ret = -ENOMEM;
359                 goto fail_name;
360         }
361
362         if (id->driver_data == DS2786)
363                 info->rsns = pdata->rsns;
364
365         i2c_set_clientdata(client, info);
366         info->client = client;
367         info->id = num;
368         info->ops  = &ds278x_ops[id->driver_data];
369         ds278x_power_supply_init(&info->battery);
370
371         ret = power_supply_register(&client->dev, &info->battery);
372         if (ret) {
373                 dev_err(&client->dev, "failed to register battery\n");
374                 goto fail_register;
375         }
376
377         return 0;
378
379 fail_register:
380         kfree(info->battery.name);
381 fail_name:
382         kfree(info);
383 fail_info:
384         mutex_lock(&battery_lock);
385         idr_remove(&battery_id, num);
386         mutex_unlock(&battery_lock);
387 fail_id:
388         return ret;
389 }
390
391 static const struct i2c_device_id ds278x_id[] = {
392         {"ds2782", DS2782},
393         {"ds2786", DS2786},
394         {},
395 };
396 MODULE_DEVICE_TABLE(i2c, ds278x_id);
397
398 static struct i2c_driver ds278x_battery_driver = {
399         .driver         = {
400                 .name   = "ds2782-battery",
401         },
402         .probe          = ds278x_battery_probe,
403         .remove         = ds278x_battery_remove,
404         .id_table       = ds278x_id,
405 };
406 module_i2c_driver(ds278x_battery_driver);
407
408 MODULE_AUTHOR("Ryan Mallon");
409 MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
410 MODULE_LICENSE("GPL");