Merge branch 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal...
[pandora-kernel.git] / drivers / power / max17042_battery.c
1 /*
2  * Fuel gauge driver for Maxim 17042 / 8966 / 8997
3  *  Note that Maxim 8966 and 8997 are mfd and this is its subdevice.
4  *
5  * Copyright (C) 2011 Samsung Electronics
6  * MyungJoo Ham <myungjoo.ham@samsung.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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * This driver is based on max17040_battery.c
23  */
24
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/i2c.h>
28 #include <linux/mod_devicetable.h>
29 #include <linux/power_supply.h>
30 #include <linux/power/max17042_battery.h>
31
32 enum max17042_register {
33         MAX17042_STATUS         = 0x00,
34         MAX17042_VALRT_Th       = 0x01,
35         MAX17042_TALRT_Th       = 0x02,
36         MAX17042_SALRT_Th       = 0x03,
37         MAX17042_AtRate         = 0x04,
38         MAX17042_RepCap         = 0x05,
39         MAX17042_RepSOC         = 0x06,
40         MAX17042_Age            = 0x07,
41         MAX17042_TEMP           = 0x08,
42         MAX17042_VCELL          = 0x09,
43         MAX17042_Current        = 0x0A,
44         MAX17042_AvgCurrent     = 0x0B,
45         MAX17042_Qresidual      = 0x0C,
46         MAX17042_SOC            = 0x0D,
47         MAX17042_AvSOC          = 0x0E,
48         MAX17042_RemCap         = 0x0F,
49         MAX17402_FullCAP        = 0x10,
50         MAX17042_TTE            = 0x11,
51         MAX17042_V_empty        = 0x12,
52
53         MAX17042_RSLOW          = 0x14,
54
55         MAX17042_AvgTA          = 0x16,
56         MAX17042_Cycles         = 0x17,
57         MAX17042_DesignCap      = 0x18,
58         MAX17042_AvgVCELL       = 0x19,
59         MAX17042_MinMaxTemp     = 0x1A,
60         MAX17042_MinMaxVolt     = 0x1B,
61         MAX17042_MinMaxCurr     = 0x1C,
62         MAX17042_CONFIG         = 0x1D,
63         MAX17042_ICHGTerm       = 0x1E,
64         MAX17042_AvCap          = 0x1F,
65         MAX17042_ManName        = 0x20,
66         MAX17042_DevName        = 0x21,
67         MAX17042_DevChem        = 0x22,
68
69         MAX17042_TempNom        = 0x24,
70         MAX17042_TempCold       = 0x25,
71         MAX17042_TempHot        = 0x26,
72         MAX17042_AIN            = 0x27,
73         MAX17042_LearnCFG       = 0x28,
74         MAX17042_SHFTCFG        = 0x29,
75         MAX17042_RelaxCFG       = 0x2A,
76         MAX17042_MiscCFG        = 0x2B,
77         MAX17042_TGAIN          = 0x2C,
78         MAx17042_TOFF           = 0x2D,
79         MAX17042_CGAIN          = 0x2E,
80         MAX17042_COFF           = 0x2F,
81
82         MAX17042_Q_empty        = 0x33,
83         MAX17042_T_empty        = 0x34,
84
85         MAX17042_RCOMP0         = 0x38,
86         MAX17042_TempCo         = 0x39,
87         MAX17042_Rx             = 0x3A,
88         MAX17042_T_empty0       = 0x3B,
89         MAX17042_TaskPeriod     = 0x3C,
90         MAX17042_FSTAT          = 0x3D,
91
92         MAX17042_SHDNTIMER      = 0x3F,
93
94         MAX17042_VFRemCap       = 0x4A,
95
96         MAX17042_QH             = 0x4D,
97         MAX17042_QL             = 0x4E,
98 };
99
100 struct max17042_chip {
101         struct i2c_client *client;
102         struct power_supply battery;
103         struct max17042_platform_data *pdata;
104 };
105
106 static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value)
107 {
108         int ret = i2c_smbus_write_word_data(client, reg, value);
109
110         if (ret < 0)
111                 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
112
113         return ret;
114 }
115
116 static int max17042_read_reg(struct i2c_client *client, u8 reg)
117 {
118         int ret = i2c_smbus_read_word_data(client, reg);
119
120         if (ret < 0)
121                 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
122
123         return ret;
124 }
125
126 static enum power_supply_property max17042_battery_props[] = {
127         POWER_SUPPLY_PROP_VOLTAGE_NOW,
128         POWER_SUPPLY_PROP_VOLTAGE_AVG,
129         POWER_SUPPLY_PROP_CAPACITY,
130 };
131
132 static int max17042_get_property(struct power_supply *psy,
133                             enum power_supply_property psp,
134                             union power_supply_propval *val)
135 {
136         struct max17042_chip *chip = container_of(psy,
137                                 struct max17042_chip, battery);
138
139         switch (psp) {
140         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
141                 val->intval = max17042_read_reg(chip->client,
142                                 MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */
143                 break;
144         case POWER_SUPPLY_PROP_VOLTAGE_AVG:
145                 val->intval = max17042_read_reg(chip->client,
146                                 MAX17042_AvgVCELL) * 83;
147                 break;
148         case POWER_SUPPLY_PROP_CAPACITY:
149                 val->intval = max17042_read_reg(chip->client,
150                                 MAX17042_SOC) / 256;
151                 break;
152         default:
153                 return -EINVAL;
154         }
155         return 0;
156 }
157
158 static int __devinit max17042_probe(struct i2c_client *client,
159                         const struct i2c_device_id *id)
160 {
161         struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
162         struct max17042_chip *chip;
163         int ret;
164
165         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
166                 return -EIO;
167
168         chip = kzalloc(sizeof(*chip), GFP_KERNEL);
169         if (!chip)
170                 return -ENOMEM;
171
172         chip->client = client;
173         chip->pdata = client->dev.platform_data;
174
175         i2c_set_clientdata(client, chip);
176
177         chip->battery.name              = "max17042_battery";
178         chip->battery.type              = POWER_SUPPLY_TYPE_BATTERY;
179         chip->battery.get_property      = max17042_get_property;
180         chip->battery.properties        = max17042_battery_props;
181         chip->battery.num_properties    = ARRAY_SIZE(max17042_battery_props);
182
183         ret = power_supply_register(&client->dev, &chip->battery);
184         if (ret) {
185                 dev_err(&client->dev, "failed: power supply register\n");
186                 i2c_set_clientdata(client, NULL);
187                 kfree(chip);
188                 return ret;
189         }
190
191         if (!chip->pdata->enable_current_sense) {
192                 max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
193                 max17042_write_reg(client, MAX17042_MiscCFG, 0x0003);
194                 max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
195         }
196
197         return 0;
198 }
199
200 static int __devexit max17042_remove(struct i2c_client *client)
201 {
202         struct max17042_chip *chip = i2c_get_clientdata(client);
203
204         power_supply_unregister(&chip->battery);
205         i2c_set_clientdata(client, NULL);
206         kfree(chip);
207         return 0;
208 }
209
210 static const struct i2c_device_id max17042_id[] = {
211         { "max17042", 0 },
212         { }
213 };
214 MODULE_DEVICE_TABLE(i2c, max17042_id);
215
216 static struct i2c_driver max17042_i2c_driver = {
217         .driver = {
218                 .name   = "max17042",
219         },
220         .probe          = max17042_probe,
221         .remove         = __devexit_p(max17042_remove),
222         .id_table       = max17042_id,
223 };
224
225 static int __init max17042_init(void)
226 {
227         return i2c_add_driver(&max17042_i2c_driver);
228 }
229 module_init(max17042_init);
230
231 static void __exit max17042_exit(void)
232 {
233         i2c_del_driver(&max17042_i2c_driver);
234 }
235 module_exit(max17042_exit);
236
237 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
238 MODULE_DESCRIPTION("MAX17042 Fuel Gauge");
239 MODULE_LICENSE("GPL");