nfs: new subdir Documentation/filesystems/nfs
[safe/jmp/linux-2.6] / 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 <ryan@bluewatersys.com>
7  *
8  * 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
10  * published by the Free Software Foundation.
11  *
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/errno.h>
18 #include <linux/swab.h>
19 #include <linux/i2c.h>
20 #include <linux/idr.h>
21 #include <linux/power_supply.h>
22
23 #define DS2782_REG_RARC         0x06    /* Remaining active relative capacity */
24
25 #define DS2782_REG_VOLT_MSB     0x0c
26 #define DS2782_REG_TEMP_MSB     0x0a
27 #define DS2782_REG_CURRENT_MSB  0x0e
28
29 /* EEPROM Block */
30 #define DS2782_REG_RSNSP        0x69    /* Sense resistor value */
31
32 /* Current unit measurement in uA for a 1 milli-ohm sense resistor */
33 #define DS2782_CURRENT_UNITS    1563
34
35 #define to_ds2782_info(x) container_of(x, struct ds2782_info, battery)
36
37 struct ds2782_info {
38         struct i2c_client       *client;
39         struct power_supply     battery;
40         int                     id;
41 };
42
43 static DEFINE_IDR(battery_id);
44 static DEFINE_MUTEX(battery_lock);
45
46 static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val)
47 {
48         int ret;
49
50         ret = i2c_smbus_read_byte_data(info->client, reg);
51         if (ret < 0) {
52                 dev_err(&info->client->dev, "register read failed\n");
53                 return ret;
54         }
55
56         *val = ret;
57         return 0;
58 }
59
60 static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb,
61                                     s16 *val)
62 {
63         int ret;
64
65         ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb));
66         if (ret < 0) {
67                 dev_err(&info->client->dev, "register read failed\n");
68                 return ret;
69         }
70
71         *val = ret;
72         return 0;
73 }
74
75 static int ds2782_get_temp(struct ds2782_info *info, int *temp)
76 {
77         s16 raw;
78         int err;
79
80         /*
81          * Temperature is measured in units of 0.125 degrees celcius, the
82          * power_supply class measures temperature in tenths of degrees
83          * celsius. The temperature value is stored as a 10 bit number, plus
84          * sign in the upper bits of a 16 bit register.
85          */
86         err = ds2782_read_reg16(info, DS2782_REG_TEMP_MSB, &raw);
87         if (err)
88                 return err;
89         *temp = ((raw / 32) * 125) / 100;
90         return 0;
91 }
92
93 static int ds2782_get_current(struct ds2782_info *info, int *current_uA)
94 {
95         int sense_res;
96         int err;
97         u8 sense_res_raw;
98         s16 raw;
99
100         /*
101          * The units of measurement for current are dependent on the value of
102          * the sense resistor.
103          */
104         err = ds2782_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw);
105         if (err)
106                 return err;
107         if (sense_res_raw == 0) {
108                 dev_err(&info->client->dev, "sense resistor value is 0\n");
109                 return -ENXIO;
110         }
111         sense_res = 1000 / sense_res_raw;
112
113         dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n",
114                 sense_res);
115         err = ds2782_read_reg16(info, DS2782_REG_CURRENT_MSB, &raw);
116         if (err)
117                 return err;
118         *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res);
119         return 0;
120 }
121
122 static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA)
123 {
124         s16 raw;
125         int err;
126
127         /*
128          * Voltage is measured in units of 4.88mV. The voltage is stored as
129          * a 10-bit number plus sign, in the upper bits of a 16-bit register
130          */
131         err = ds2782_read_reg16(info, DS2782_REG_VOLT_MSB, &raw);
132         if (err)
133                 return err;
134         *voltage_uA = (raw / 32) * 4800;
135         return 0;
136 }
137
138 static int ds2782_get_capacity(struct ds2782_info *info, int *capacity)
139 {
140         int err;
141         u8 raw;
142
143         err = ds2782_read_reg(info, DS2782_REG_RARC, &raw);
144         if (err)
145                 return err;
146         *capacity = raw;
147         return raw;
148 }
149
150 static int ds2782_get_status(struct ds2782_info *info, int *status)
151 {
152         int err;
153         int current_uA;
154         int capacity;
155
156         err = ds2782_get_current(info, &current_uA);
157         if (err)
158                 return err;
159
160         err = ds2782_get_capacity(info, &capacity);
161         if (err)
162                 return err;
163
164         if (capacity == 100)
165                 *status = POWER_SUPPLY_STATUS_FULL;
166         else if (current_uA == 0)
167                 *status = POWER_SUPPLY_STATUS_NOT_CHARGING;
168         else if (current_uA < 0)
169                 *status = POWER_SUPPLY_STATUS_DISCHARGING;
170         else
171                 *status = POWER_SUPPLY_STATUS_CHARGING;
172
173         return 0;
174 }
175
176 static int ds2782_battery_get_property(struct power_supply *psy,
177                                        enum power_supply_property prop,
178                                        union power_supply_propval *val)
179 {
180         struct ds2782_info *info = to_ds2782_info(psy);
181         int ret;
182
183         switch (prop) {
184         case POWER_SUPPLY_PROP_STATUS:
185                 ret = ds2782_get_status(info, &val->intval);
186                 break;
187
188         case POWER_SUPPLY_PROP_CAPACITY:
189                 ret = ds2782_get_capacity(info, &val->intval);
190                 break;
191
192         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
193                 ret = ds2782_get_voltage(info, &val->intval);
194                 break;
195
196         case POWER_SUPPLY_PROP_CURRENT_NOW:
197                 ret = ds2782_get_current(info, &val->intval);
198                 break;
199
200         case POWER_SUPPLY_PROP_TEMP:
201                 ret = ds2782_get_temp(info, &val->intval);
202                 break;
203
204         default:
205                 ret = -EINVAL;
206         }
207
208         return ret;
209 }
210
211 static enum power_supply_property ds2782_battery_props[] = {
212         POWER_SUPPLY_PROP_STATUS,
213         POWER_SUPPLY_PROP_CAPACITY,
214         POWER_SUPPLY_PROP_VOLTAGE_NOW,
215         POWER_SUPPLY_PROP_CURRENT_NOW,
216         POWER_SUPPLY_PROP_TEMP,
217 };
218
219 static void ds2782_power_supply_init(struct power_supply *battery)
220 {
221         battery->type                   = POWER_SUPPLY_TYPE_BATTERY;
222         battery->properties             = ds2782_battery_props;
223         battery->num_properties         = ARRAY_SIZE(ds2782_battery_props);
224         battery->get_property           = ds2782_battery_get_property;
225         battery->external_power_changed = NULL;
226 }
227
228 static int ds2782_battery_remove(struct i2c_client *client)
229 {
230         struct ds2782_info *info = i2c_get_clientdata(client);
231
232         power_supply_unregister(&info->battery);
233         kfree(info->battery.name);
234
235         mutex_lock(&battery_lock);
236         idr_remove(&battery_id, info->id);
237         mutex_unlock(&battery_lock);
238
239         i2c_set_clientdata(client, info);
240
241         kfree(info);
242         return 0;
243 }
244
245 static int ds2782_battery_probe(struct i2c_client *client,
246                                 const struct i2c_device_id *id)
247 {
248         struct ds2782_info *info;
249         int ret;
250         int num;
251
252         /* Get an ID for this battery */
253         ret = idr_pre_get(&battery_id, GFP_KERNEL);
254         if (ret == 0) {
255                 ret = -ENOMEM;
256                 goto fail_id;
257         }
258
259         mutex_lock(&battery_lock);
260         ret = idr_get_new(&battery_id, client, &num);
261         mutex_unlock(&battery_lock);
262         if (ret < 0)
263                 goto fail_id;
264
265         info = kzalloc(sizeof(*info), GFP_KERNEL);
266         if (!info) {
267                 ret = -ENOMEM;
268                 goto fail_info;
269         }
270
271         info->battery.name = kasprintf(GFP_KERNEL, "ds2782-%d", num);
272         if (!info->battery.name) {
273                 ret = -ENOMEM;
274                 goto fail_name;
275         }
276
277         i2c_set_clientdata(client, info);
278         info->client = client;
279         ds2782_power_supply_init(&info->battery);
280
281         ret = power_supply_register(&client->dev, &info->battery);
282         if (ret) {
283                 dev_err(&client->dev, "failed to register battery\n");
284                 goto fail_register;
285         }
286
287         return 0;
288
289 fail_register:
290         kfree(info->battery.name);
291 fail_name:
292         i2c_set_clientdata(client, info);
293         kfree(info);
294 fail_info:
295         mutex_lock(&battery_lock);
296         idr_remove(&battery_id, num);
297         mutex_unlock(&battery_lock);
298 fail_id:
299         return ret;
300 }
301
302 static const struct i2c_device_id ds2782_id[] = {
303         {"ds2782", 0},
304         {},
305 };
306
307 static struct i2c_driver ds2782_battery_driver = {
308         .driver         = {
309                 .name   = "ds2782-battery",
310         },
311         .probe          = ds2782_battery_probe,
312         .remove         = ds2782_battery_remove,
313         .id_table       = ds2782_id,
314 };
315
316 static int __init ds2782_init(void)
317 {
318         return i2c_add_driver(&ds2782_battery_driver);
319 }
320 module_init(ds2782_init);
321
322 static void __exit ds2782_exit(void)
323 {
324         i2c_del_driver(&ds2782_battery_driver);
325 }
326 module_exit(ds2782_exit);
327
328 MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
329 MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
330 MODULE_LICENSE("GPL");