bq27xxx_battery_i2c.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * BQ27xxx battery monitor I2C driver
  3. *
  4. * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
  5. * Andrew F. Davis <afd@ti.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  12. * kind, whether express or implied; without even the implied warranty
  13. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/i2c.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/module.h>
  19. #include <asm/unaligned.h>
  20. #include <linux/power/bq27xxx_battery.h>
  21. static DEFINE_IDR(battery_id);
  22. static DEFINE_MUTEX(battery_mutex);
  23. static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
  24. {
  25. struct bq27xxx_device_info *di = data;
  26. bq27xxx_battery_update(di);
  27. return IRQ_HANDLED;
  28. }
  29. static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
  30. bool single)
  31. {
  32. struct i2c_client *client = to_i2c_client(di->dev);
  33. struct i2c_msg msg[2];
  34. unsigned char data[2];
  35. int ret;
  36. if (!client->adapter)
  37. return -ENODEV;
  38. msg[0].addr = client->addr;
  39. msg[0].flags = 0;
  40. msg[0].buf = &reg;
  41. msg[0].len = sizeof(reg);
  42. msg[1].addr = client->addr;
  43. msg[1].flags = I2C_M_RD;
  44. msg[1].buf = data;
  45. if (single)
  46. msg[1].len = 1;
  47. else
  48. msg[1].len = 2;
  49. ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
  50. if (ret < 0)
  51. return ret;
  52. if (!single)
  53. ret = get_unaligned_le16(data);
  54. else
  55. ret = data[0];
  56. return ret;
  57. }
  58. static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
  59. const struct i2c_device_id *id)
  60. {
  61. struct bq27xxx_device_info *di;
  62. int ret;
  63. char *name;
  64. int num;
  65. /* Get new ID for the new battery device */
  66. mutex_lock(&battery_mutex);
  67. num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
  68. mutex_unlock(&battery_mutex);
  69. if (num < 0)
  70. return num;
  71. name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
  72. if (!name)
  73. goto err_mem;
  74. di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
  75. if (!di)
  76. goto err_mem;
  77. di->id = num;
  78. di->dev = &client->dev;
  79. di->chip = id->driver_data;
  80. di->name = name;
  81. di->bus.read = bq27xxx_battery_i2c_read;
  82. ret = bq27xxx_battery_setup(di);
  83. if (ret)
  84. goto err_failed;
  85. /* Schedule a polling after about 1 min */
  86. schedule_delayed_work(&di->work, 60 * HZ);
  87. i2c_set_clientdata(client, di);
  88. if (client->irq) {
  89. ret = devm_request_threaded_irq(&client->dev, client->irq,
  90. NULL, bq27xxx_battery_irq_handler_thread,
  91. IRQF_ONESHOT,
  92. di->name, di);
  93. if (ret) {
  94. dev_err(&client->dev,
  95. "Unable to register IRQ %d error %d\n",
  96. client->irq, ret);
  97. return ret;
  98. }
  99. }
  100. return 0;
  101. err_mem:
  102. ret = -ENOMEM;
  103. err_failed:
  104. mutex_lock(&battery_mutex);
  105. idr_remove(&battery_id, num);
  106. mutex_unlock(&battery_mutex);
  107. return ret;
  108. }
  109. static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
  110. {
  111. struct bq27xxx_device_info *di = i2c_get_clientdata(client);
  112. bq27xxx_battery_teardown(di);
  113. mutex_lock(&battery_mutex);
  114. idr_remove(&battery_id, di->id);
  115. mutex_unlock(&battery_mutex);
  116. return 0;
  117. }
  118. static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
  119. { "bq27200", BQ27000 },
  120. { "bq27210", BQ27010 },
  121. { "bq27500", BQ27500 },
  122. { "bq27510", BQ27510 },
  123. { "bq27520", BQ27510 },
  124. { "bq27530", BQ27530 },
  125. { "bq27531", BQ27530 },
  126. { "bq27541", BQ27541 },
  127. { "bq27542", BQ27541 },
  128. { "bq27546", BQ27541 },
  129. { "bq27742", BQ27541 },
  130. { "bq27545", BQ27545 },
  131. { "bq27421", BQ27421 },
  132. { "bq27425", BQ27421 },
  133. { "bq27441", BQ27421 },
  134. { "bq27621", BQ27421 },
  135. {},
  136. };
  137. MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
  138. #ifdef CONFIG_OF
  139. static const struct of_device_id bq27xxx_battery_i2c_of_match_table[] = {
  140. { .compatible = "ti,bq27200" },
  141. { .compatible = "ti,bq27210" },
  142. { .compatible = "ti,bq27500" },
  143. { .compatible = "ti,bq27510" },
  144. { .compatible = "ti,bq27520" },
  145. { .compatible = "ti,bq27530" },
  146. { .compatible = "ti,bq27531" },
  147. { .compatible = "ti,bq27541" },
  148. { .compatible = "ti,bq27542" },
  149. { .compatible = "ti,bq27546" },
  150. { .compatible = "ti,bq27742" },
  151. { .compatible = "ti,bq27545" },
  152. { .compatible = "ti,bq27421" },
  153. { .compatible = "ti,bq27425" },
  154. { .compatible = "ti,bq27441" },
  155. { .compatible = "ti,bq27621" },
  156. {},
  157. };
  158. MODULE_DEVICE_TABLE(of, bq27xxx_battery_i2c_of_match_table);
  159. #endif
  160. static struct i2c_driver bq27xxx_battery_i2c_driver = {
  161. .driver = {
  162. .name = "bq27xxx-battery",
  163. .of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table),
  164. },
  165. .probe = bq27xxx_battery_i2c_probe,
  166. .remove = bq27xxx_battery_i2c_remove,
  167. .id_table = bq27xxx_i2c_id_table,
  168. };
  169. module_i2c_driver(bq27xxx_battery_i2c_driver);
  170. MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
  171. MODULE_DESCRIPTION("BQ27xxx battery monitor i2c driver");
  172. MODULE_LICENSE("GPL");