3 * fuel-gauge systems for lithium-ion (Li+) batteries
5 * Copyright (C) 2009 Samsung Electronics
6 * Minkyu Kang <mk7.kang@samsung.com>
8 * This program is not provided / owned by Maxim Integrated Products.
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.
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/platform_device.h>
18 #include <linux/mutex.h>
19 #include <linux/err.h>
20 #include <linux/i2c.h>
21 #include <linux/delay.h>
22 #include <linux/power_supply.h>
23 #include <linux/max17040_battery.h>
24 #include <linux/slab.h>
26 #define MAX17040_VCELL_MSB 0x02
27 #define MAX17040_VCELL_LSB 0x03
28 #define MAX17040_SOC_MSB 0x04
29 #define MAX17040_SOC_LSB 0x05
30 #define MAX17040_MODE_MSB 0x06
31 #define MAX17040_MODE_LSB 0x07
32 #define MAX17040_VER_MSB 0x08
33 #define MAX17040_VER_LSB 0x09
34 #define MAX17040_RCOMP_MSB 0x0C
35 #define MAX17040_RCOMP_LSB 0x0D
36 #define MAX17040_CMD_MSB 0xFE
37 #define MAX17040_CMD_LSB 0xFF
39 #define MAX17040_DELAY 1000
40 #define MAX17040_BATTERY_FULL 95
42 struct max17040_chip {
43 struct i2c_client *client;
44 struct delayed_work work;
45 struct power_supply battery;
46 struct max17040_platform_data *pdata;
50 /* State Of Connect */
54 /* battery capacity */
56 /* battery compensation */
60 static int max17040_write_reg(struct i2c_client *client,
61 int reg, unsigned int value)
65 ret = i2c_smbus_write_i2c_block_data(client, reg, 2, (u8 *)&value);
68 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
73 static int max17040_read_reg(struct i2c_client *client, int reg)
77 ret = i2c_smbus_read_byte_data(client, reg);
80 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
85 static void max17040_set_rcomp(struct i2c_client *client, unsigned int value)
89 revert = (value >> 8) + ((value & 0xff) << 8);
90 max17040_write_reg(client, MAX17040_RCOMP_MSB, revert);
93 static void max17040_reset(struct i2c_client *client, int reset)
95 struct max17040_chip *chip = i2c_get_clientdata(client);
100 ret = max17040_write_reg(client, MAX17040_CMD_MSB, 0x5400);
104 ret = max17040_write_reg(client, MAX17040_MODE_MSB, 0x4000);
112 if (chip->pdata->rcomp)
113 max17040_set_rcomp(client, chip->pdata->rcomp);
115 if (chip->pdata->poll)
116 schedule_delayed_work(&chip->work, MAX17040_DELAY);
120 static unsigned int max17040_get_vcell(struct i2c_client *client)
122 struct max17040_chip *chip = i2c_get_clientdata(client);
126 msb = max17040_read_reg(client, MAX17040_VCELL_MSB);
127 lsb = max17040_read_reg(client, MAX17040_VCELL_LSB);
129 chip->vcell = ((msb << 4) + (lsb >> 4)) * 125 / 100;
131 return (msb << 4) + (lsb >> 4);
134 static void max17040_get_soc(struct i2c_client *client)
136 struct max17040_chip *chip = i2c_get_clientdata(client);
140 msb = max17040_read_reg(client, MAX17040_SOC_MSB);
141 lsb = max17040_read_reg(client, MAX17040_SOC_LSB);
146 static void max17040_get_version(struct i2c_client *client)
151 msb = max17040_read_reg(client, MAX17040_VER_MSB);
152 lsb = max17040_read_reg(client, MAX17040_VER_LSB);
154 dev_info(&client->dev, "MAX17040 Fuel-Gauge Ver %d%d\n", msb, lsb);
157 static void max17040_get_rcomp(struct i2c_client *client)
159 struct max17040_chip *chip = i2c_get_clientdata(client);
163 msb = max17040_read_reg(client, MAX17040_RCOMP_MSB);
164 lsb = max17040_read_reg(client, MAX17040_RCOMP_LSB);
166 chip->rcomp = (msb << 8) + lsb;
169 static void max17040_work(struct work_struct *work)
171 struct max17040_chip *chip;
173 chip = container_of(work, struct max17040_chip, work.work);
175 max17040_get_vcell(chip->client);
176 max17040_get_soc(chip->client);
178 schedule_delayed_work(&chip->work, MAX17040_DELAY);
181 static enum power_supply_property max17040_battery_props[] = {
182 POWER_SUPPLY_PROP_VOLTAGE_NOW,
183 POWER_SUPPLY_PROP_CAPACITY,
184 POWER_SUPPLY_PROP_CHARGE_FULL,
187 static int max17040_get_property(struct power_supply *psy,
188 enum power_supply_property psp,
189 union power_supply_propval *val)
191 struct max17040_chip *chip = container_of(psy,
192 struct max17040_chip, battery);
194 if (!chip->operate) {
200 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
201 if (!chip->pdata->poll)
202 max17040_get_vcell(chip->client);
203 val->intval = chip->vcell * 1000; /* uA is the standard */
205 case POWER_SUPPLY_PROP_CAPACITY:
206 if (!chip->pdata->poll)
207 max17040_get_soc(chip->client);
208 val->intval = chip->soc;
210 case POWER_SUPPLY_PROP_CHARGE_FULL:
211 if (!chip->pdata->poll)
212 max17040_get_soc(chip->client);
213 if (chip->soc > MAX17040_BATTERY_FULL)
224 static ssize_t max17040_show_rcomp(struct device *dev,
225 struct device_attribute *attr, char *buf)
227 struct max17040_chip *chip = dev_get_drvdata(dev);
229 max17040_get_rcomp(chip->client);
230 return sprintf(buf, "%x\n", chip->rcomp);
233 static ssize_t max17040_store_rcomp(struct device *dev,
234 struct device_attribute *attr, const char *buf, size_t count)
236 struct max17040_chip *chip = dev_get_drvdata(dev);
239 strict_strtoul(buf, 16, (unsigned long *)&value);
244 max17040_set_rcomp(chip->client, value);
249 DEVICE_ATTR(rcomp, S_IRUGO|S_IWUSR,
250 max17040_show_rcomp, max17040_store_rcomp);
252 static ssize_t max17040_show_operate(struct device *dev,
253 struct device_attribute *attr, char *buf)
255 struct max17040_chip *chip = dev_get_drvdata(dev);
256 return sprintf(buf, "%x\n", chip->operate);
259 static ssize_t max17040_store_operate(struct device *dev,
260 struct device_attribute *attr, const char *buf, size_t count)
262 struct max17040_chip *chip = dev_get_drvdata(dev);
265 strict_strtoul(buf, 16, (unsigned long *)&value);
271 max17040_reset(chip->client, 1);
276 DEVICE_ATTR(operate, S_IRUGO|S_IWUSR,
277 max17040_show_operate, max17040_store_operate);
279 static int __devinit max17040_probe(struct i2c_client *client,
280 const struct i2c_device_id *id)
282 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
283 struct max17040_chip *chip;
286 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
289 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
293 chip->client = client;
294 chip->pdata = client->dev.platform_data;
296 i2c_set_clientdata(client, chip);
298 chip->battery.name = "max17040_battery";
299 chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
300 chip->battery.get_property = max17040_get_property;
301 chip->battery.properties = max17040_battery_props;
302 chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props);
304 ret = power_supply_register(&client->dev, &chip->battery);
306 dev_err(&client->dev, "failed: power supply register\n");
307 i2c_set_clientdata(client, NULL);
312 ret = device_create_file(&client->dev, &dev_attr_rcomp);
313 ret = device_create_file(&client->dev, &dev_attr_operate);
315 INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17040_work);
317 max17040_reset(client, chip->pdata->reset);
318 max17040_get_version(client);
323 static int __devexit max17040_remove(struct i2c_client *client)
325 struct max17040_chip *chip = i2c_get_clientdata(client);
327 power_supply_unregister(&chip->battery);
328 device_remove_file(&client->dev, &dev_attr_rcomp);
329 device_remove_file(&client->dev, &dev_attr_operate);
331 if (chip->pdata->poll)
332 cancel_delayed_work(&chip->work);
333 i2c_set_clientdata(client, NULL);
340 static int max17040_suspend(struct i2c_client *client,
343 struct max17040_chip *chip = i2c_get_clientdata(client);
345 if (chip->pdata->poll)
346 cancel_delayed_work(&chip->work);
350 static int max17040_resume(struct i2c_client *client)
352 struct max17040_chip *chip = i2c_get_clientdata(client);
354 if (chip->pdata->poll)
355 schedule_delayed_work(&chip->work, MAX17040_DELAY);
361 #define max17040_suspend NULL
362 #define max17040_resume NULL
364 #endif /* CONFIG_PM */
366 static const struct i2c_device_id max17040_id[] = {
370 MODULE_DEVICE_TABLE(i2c, max17040_id);
372 static struct i2c_driver max17040_i2c_driver = {
376 .probe = max17040_probe,
377 .remove = __devexit_p(max17040_remove),
378 .suspend = max17040_suspend,
379 .resume = max17040_resume,
380 .id_table = max17040_id,
383 static int __init max17040_init(void)
385 return i2c_add_driver(&max17040_i2c_driver);
387 module_init(max17040_init);
389 static void __exit max17040_exit(void)
391 i2c_del_driver(&max17040_i2c_driver);
393 module_exit(max17040_exit);
395 MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
396 MODULE_DESCRIPTION("MAX17040 Fuel Gauge");
397 MODULE_LICENSE("GPL");