/drivers/power/max17048_battery.c

https://github.com/bladewing/thinkpad_tablet_jb_kernel · C · 398 lines · 310 code · 72 blank · 16 comment · 23 complexity · 7314d709a4875311e0ce315bafc396cb MD5 · raw file

  1. /*
  2. * max17048_battery.c
  3. * fuel-gauge systems for lithium-ion (Li+) batteries
  4. *
  5. * Copyright (C) 2012 Nvidia Cooperation
  6. * Chandler Zhang <chazhang@nvidia.com>
  7. * Syed Rafiuddin <srafiuddin@nvidia.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/init.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/mutex.h>
  17. #include <linux/err.h>
  18. #include <linux/i2c.h>
  19. #include <linux/delay.h>
  20. #include <linux/power_supply.h>
  21. #include <linux/slab.h>
  22. #include <linux/max17048_battery.h>
  23. #define MAX17048_VCELL_MSB 0x02
  24. #define MAX17048_VCELL_LSB 0x03
  25. #define MAX17048_SOC_MSB 0x04
  26. #define MAX17048_SOC_LSB 0x05
  27. #define MAX17048_MODE_MSB 0x06
  28. #define MAX17048_MODE_LSB 0x07
  29. #define MAX17048_VER_MSB 0x08
  30. #define MAX17048_VER_LSB 0x09
  31. #define MAX17048_RCOMP_MSB 0x0C
  32. #define MAX17048_RCOMP_LSB 0x0D
  33. #define MAX17048_CMD_MSB 0xFE
  34. #define MAX17048_CMD_LSB 0xFF
  35. #define RESET_MSB 0x54
  36. #define RESET_LSB 0x00
  37. #define MAX17048_DELAY 1000
  38. #define MAX17048_BATTERY_FULL 95
  39. struct max17048_chip {
  40. struct i2c_client *client;
  41. struct delayed_work work;
  42. struct power_supply battery;
  43. struct power_supply ac;
  44. struct power_supply usb;
  45. struct max17048_platform_data *pdata;
  46. /* State Of Connect */
  47. int ac_online;
  48. int usb_online;
  49. /* battery voltage */
  50. int vcell;
  51. /* battery capacity */
  52. int soc;
  53. /* State Of Charge */
  54. int status;
  55. int lasttime_vcell;
  56. int lasttime_soc;
  57. int lasttime_status;
  58. int lasttime_ac_online;
  59. int lasttime_usb_online;
  60. };
  61. static int max17048_get_property(struct power_supply *psy,
  62. enum power_supply_property psp,
  63. union power_supply_propval *val)
  64. {
  65. struct max17048_chip *chip = container_of(psy,
  66. struct max17048_chip, battery);
  67. switch (psp) {
  68. case POWER_SUPPLY_PROP_STATUS:
  69. val->intval = chip->status;
  70. break;
  71. case POWER_SUPPLY_PROP_VOLTAGE_NOW:
  72. val->intval = chip->vcell;
  73. break;
  74. case POWER_SUPPLY_PROP_CAPACITY:
  75. val->intval = chip->soc;
  76. break;
  77. default:
  78. return -EINVAL;
  79. }
  80. return 0;
  81. }
  82. static int max17048_ac_get_property(struct power_supply *psy,
  83. enum power_supply_property psp,
  84. union power_supply_propval *val)
  85. {
  86. struct max17048_chip *chip = container_of(psy,
  87. struct max17048_chip, ac);
  88. if (psp == POWER_SUPPLY_PROP_ONLINE)
  89. val->intval = chip->ac_online;
  90. else
  91. return -EINVAL;
  92. return 0;
  93. }
  94. static int max17048_usb_get_property(struct power_supply *psy,
  95. enum power_supply_property psp,
  96. union power_supply_propval *val)
  97. {
  98. struct max17048_chip *chip = container_of(psy,
  99. struct max17048_chip, usb);
  100. if (psp == POWER_SUPPLY_PROP_ONLINE)
  101. val->intval = chip->usb_online;
  102. else
  103. return -EINVAL;
  104. return 0;
  105. }
  106. static int max17048_write_reg(struct i2c_client *client, int reg, u8 value)
  107. {
  108. int ret;
  109. ret = i2c_smbus_write_byte_data(client, reg, value);
  110. if (ret < 0)
  111. dev_err(&client->dev, "%s: err %d\n", __func__, ret);
  112. return ret;
  113. }
  114. static int max17048_read_reg(struct i2c_client *client, int reg)
  115. {
  116. int ret;
  117. ret = i2c_smbus_read_byte_data(client, reg);
  118. if (ret < 0)
  119. dev_err(&client->dev, "%s: err %d\n", __func__, ret);
  120. return ret;
  121. }
  122. static void max17048_reset(struct i2c_client *client)
  123. {
  124. max17048_write_reg(client, MAX17048_CMD_MSB, RESET_MSB);
  125. max17048_write_reg(client, MAX17048_CMD_LSB, RESET_LSB);
  126. }
  127. static void max17048_get_vcell(struct i2c_client *client)
  128. {
  129. struct max17048_chip *chip = i2c_get_clientdata(client);
  130. u8 msb;
  131. u8 lsb;
  132. msb = max17048_read_reg(client, MAX17048_VCELL_MSB);
  133. lsb = max17048_read_reg(client, MAX17048_VCELL_LSB);
  134. chip->vcell = (msb << 4) + (lsb >> 4);
  135. }
  136. static void max17048_get_soc(struct i2c_client *client)
  137. {
  138. struct max17048_chip *chip = i2c_get_clientdata(client);
  139. u8 msb;
  140. u8 lsb;
  141. msb = max17048_read_reg(client, MAX17048_SOC_MSB);
  142. chip->soc = msb;
  143. }
  144. static void max17048_get_version(struct i2c_client *client)
  145. {
  146. u8 msb;
  147. u8 lsb;
  148. msb = max17048_read_reg(client, MAX17048_VER_MSB);
  149. lsb = max17048_read_reg(client, MAX17048_VER_LSB);
  150. dev_info(&client->dev, "MAX17048 Fuel-Gauge Ver %d%d\n", msb, lsb);
  151. }
  152. static void max17048_get_online(struct i2c_client *client)
  153. {
  154. struct max17048_chip *chip = i2c_get_clientdata(client);
  155. if (chip->pdata->charging_status && chip->pdata->charging_status()) {
  156. if (chip->pdata->charger_online &&
  157. chip->pdata->charger_online()) {
  158. chip->ac_online = 1;
  159. chip->usb_online = 0;
  160. } else {
  161. chip->ac_online = 0;
  162. chip->usb_online = 1;
  163. }
  164. } else {
  165. chip->ac_online = 0;
  166. chip->usb_online = 0;
  167. }
  168. }
  169. static void max17048_get_status(struct i2c_client *client)
  170. {
  171. struct max17048_chip *chip = i2c_get_clientdata(client);
  172. if (chip->pdata->charging_status())
  173. chip->status = POWER_SUPPLY_STATUS_CHARGING;
  174. else
  175. chip->status = POWER_SUPPLY_STATUS_DISCHARGING;
  176. if (chip->soc > MAX17048_BATTERY_FULL)
  177. chip->status = POWER_SUPPLY_STATUS_FULL;
  178. }
  179. static void max17048_work(struct work_struct *work)
  180. {
  181. struct max17048_chip *chip;
  182. chip = container_of(work, struct max17048_chip, work.work);
  183. max17048_get_vcell(chip->client);
  184. max17048_get_soc(chip->client);
  185. max17048_get_online(chip->client);
  186. max17048_get_status(chip->client);
  187. if (chip->vcell != chip->lasttime_vcell ||
  188. chip->soc != chip->lasttime_soc ||
  189. chip->ac_online != chip->lasttime_ac_online ||
  190. chip->usb_online != chip->lasttime_usb_online ||
  191. chip->status != chip->lasttime_status) {
  192. chip->lasttime_vcell = chip->vcell;
  193. chip->lasttime_soc = chip->soc;
  194. chip->lasttime_status = chip->status;
  195. chip->lasttime_ac_online = chip->ac_online;
  196. chip->lasttime_usb_online = chip->usb_online;
  197. power_supply_changed(&chip->battery);
  198. power_supply_changed(&chip->usb);
  199. power_supply_changed(&chip->ac);
  200. }
  201. schedule_delayed_work(&chip->work, MAX17048_DELAY);
  202. }
  203. static enum power_supply_property max17048_battery_props[] = {
  204. POWER_SUPPLY_PROP_STATUS,
  205. POWER_SUPPLY_PROP_VOLTAGE_NOW,
  206. POWER_SUPPLY_PROP_CAPACITY,
  207. };
  208. static enum power_supply_property max17048_ac_props[] = {
  209. POWER_SUPPLY_PROP_ONLINE,
  210. };
  211. static enum power_supply_property max17048_usb_props[] = {
  212. POWER_SUPPLY_PROP_ONLINE,
  213. };
  214. static int __devinit max17048_probe(struct i2c_client *client,
  215. const struct i2c_device_id *id)
  216. {
  217. struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
  218. struct max17048_chip *chip;
  219. int ret;
  220. chip = kzalloc(sizeof(*chip), GFP_KERNEL);
  221. if (!chip)
  222. return -ENOMEM;
  223. chip->client = client;
  224. chip->pdata = client->dev.platform_data;
  225. chip->ac_online = 0;
  226. chip->usb_online = 0;
  227. i2c_set_clientdata(client, chip);
  228. chip->battery.name = "battery";
  229. chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
  230. chip->battery.get_property = max17048_get_property;
  231. chip->battery.properties = max17048_battery_props;
  232. chip->battery.num_properties = ARRAY_SIZE(max17048_battery_props);
  233. ret = power_supply_register(&client->dev, &chip->battery);
  234. if (ret) {
  235. dev_err(&client->dev, "failed: power supply register\n");
  236. goto error2;
  237. }
  238. chip->ac.name = "maxim-ac";
  239. chip->ac.type = POWER_SUPPLY_TYPE_MAINS;
  240. chip->ac.get_property = max17048_ac_get_property;
  241. chip->ac.properties = max17048_ac_props;
  242. chip->ac.num_properties = ARRAY_SIZE(max17048_ac_props);
  243. ret = power_supply_register(&client->dev, &chip->ac);
  244. if (ret) {
  245. dev_err(&client->dev, "failed: power supply register\n");
  246. goto error1;
  247. }
  248. chip->usb.name = "maxim-usb";
  249. chip->usb.type = POWER_SUPPLY_TYPE_USB;
  250. chip->usb.get_property = max17048_usb_get_property;
  251. chip->usb.properties = max17048_usb_props;
  252. chip->usb.num_properties = ARRAY_SIZE(max17048_usb_props);
  253. ret = power_supply_register(&client->dev, &chip->usb);
  254. if (ret) {
  255. dev_err(&client->dev, "failed: power supply register\n");
  256. goto error;
  257. }
  258. max17048_reset(client);
  259. max17048_get_version(client);
  260. INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17048_work);
  261. schedule_delayed_work(&chip->work, MAX17048_DELAY);
  262. return 0;
  263. error:
  264. power_supply_unregister(&chip->ac);
  265. error1:
  266. power_supply_unregister(&chip->battery);
  267. error2:
  268. kfree(chip);
  269. return ret;
  270. }
  271. static int __devexit max17048_remove(struct i2c_client *client)
  272. {
  273. struct max17048_chip *chip = i2c_get_clientdata(client);
  274. power_supply_unregister(&chip->battery);
  275. power_supply_unregister(&chip->usb);
  276. power_supply_unregister(&chip->ac);
  277. cancel_delayed_work(&chip->work);
  278. kfree(chip);
  279. return 0;
  280. }
  281. #ifdef CONFIG_PM
  282. static int max17048_suspend(struct i2c_client *client,
  283. pm_message_t state)
  284. {
  285. struct max17048_chip *chip = i2c_get_clientdata(client);
  286. cancel_delayed_work(&chip->work);
  287. return 0;
  288. }
  289. static int max17048_resume(struct i2c_client *client)
  290. {
  291. struct max17048_chip *chip = i2c_get_clientdata(client);
  292. schedule_delayed_work(&chip->work, MAX17048_DELAY);
  293. return 0;
  294. }
  295. #else
  296. #define max17048_suspend NULL
  297. #define max17048_resume NULL
  298. #endif /* CONFIG_PM */
  299. static const struct i2c_device_id max17048_id[] = {
  300. { "max17048", 0 },
  301. { }
  302. };
  303. MODULE_DEVICE_TABLE(i2c, max17048_id);
  304. static struct i2c_driver max17048_i2c_driver = {
  305. .driver = {
  306. .name = "max17048",
  307. },
  308. .probe = max17048_probe,
  309. .remove = __devexit_p(max17048_remove),
  310. .suspend = max17048_suspend,
  311. .resume = max17048_resume,
  312. .id_table = max17048_id,
  313. };
  314. static int __init max17048_init(void)
  315. {
  316. return i2c_add_driver(&max17048_i2c_driver);
  317. }
  318. module_init(max17048_init);
  319. static void __exit max17048_exit(void)
  320. {
  321. i2c_del_driver(&max17048_i2c_driver);
  322. }
  323. module_exit(max17048_exit);
  324. MODULE_AUTHOR("Chandler Zhang <chazhang@nvidia.com>");
  325. MODULE_DESCRIPTION("MAX17048 Fuel Gauge");
  326. MODULE_LICENSE("GPL");