1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * BQ27xxx battery monitor I2C driver
4 *
5 * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
6 * Andrew F. Davis <afd@ti.com>
7 */
8
9 #include <linux/delay.h>
10 #include <linux/i2c.h>
11 #include <linux/interrupt.h>
12 #include <linux/module.h>
13 #include <asm/unaligned.h>
14
15 #include <linux/power/bq27xxx_battery.h>
16
17 static DEFINE_IDR(battery_id);
18 static DEFINE_MUTEX(battery_mutex);
19
bq27xxx_battery_irq_handler_thread(int irq,void * data)20 static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
21 {
22 struct bq27xxx_device_info *di = data;
23
24 bq27xxx_battery_update(di);
25
26 return IRQ_HANDLED;
27 }
28
bq27xxx_battery_i2c_read(struct bq27xxx_device_info * di,u8 reg,bool single)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 u8 data[2];
35 int ret;
36 int retry = 0;
37
38 if (!client->adapter)
39 return -ENODEV;
40
41 msg[0].addr = client->addr;
42 msg[0].flags = 0;
43 msg[0].buf = ®
44 msg[0].len = sizeof(reg);
45 msg[1].addr = client->addr;
46 msg[1].flags = I2C_M_RD;
47 msg[1].buf = data;
48 if (single)
49 msg[1].len = 1;
50 else
51 msg[1].len = 2;
52
53 do {
54 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
55 if (ret == -EBUSY && ++retry < 3) {
56 /* sleep 10 milliseconds when busy */
57 usleep_range(10000, 11000);
58 continue;
59 }
60 break;
61 } while (1);
62
63 if (ret < 0)
64 return ret;
65
66 if (!single)
67 ret = get_unaligned_le16(data);
68 else
69 ret = data[0];
70
71 return ret;
72 }
73
bq27xxx_battery_i2c_write(struct bq27xxx_device_info * di,u8 reg,int value,bool single)74 static int bq27xxx_battery_i2c_write(struct bq27xxx_device_info *di, u8 reg,
75 int value, bool single)
76 {
77 struct i2c_client *client = to_i2c_client(di->dev);
78 struct i2c_msg msg;
79 u8 data[4];
80 int ret;
81
82 if (!client->adapter)
83 return -ENODEV;
84
85 data[0] = reg;
86 if (single) {
87 data[1] = (u8) value;
88 msg.len = 2;
89 } else {
90 put_unaligned_le16(value, &data[1]);
91 msg.len = 3;
92 }
93
94 msg.buf = data;
95 msg.addr = client->addr;
96 msg.flags = 0;
97
98 ret = i2c_transfer(client->adapter, &msg, 1);
99 if (ret < 0)
100 return ret;
101 if (ret != 1)
102 return -EINVAL;
103 return 0;
104 }
105
bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info * di,u8 reg,u8 * data,int len)106 static int bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info *di, u8 reg,
107 u8 *data, int len)
108 {
109 struct i2c_client *client = to_i2c_client(di->dev);
110 int ret;
111
112 if (!client->adapter)
113 return -ENODEV;
114
115 ret = i2c_smbus_read_i2c_block_data(client, reg, len, data);
116 if (ret < 0)
117 return ret;
118 if (ret != len)
119 return -EINVAL;
120 return 0;
121 }
122
bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info * di,u8 reg,u8 * data,int len)123 static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
124 u8 reg, u8 *data, int len)
125 {
126 struct i2c_client *client = to_i2c_client(di->dev);
127 struct i2c_msg msg;
128 u8 buf[33];
129 int ret;
130
131 if (!client->adapter)
132 return -ENODEV;
133
134 buf[0] = reg;
135 memcpy(&buf[1], data, len);
136
137 msg.buf = buf;
138 msg.addr = client->addr;
139 msg.flags = 0;
140 msg.len = len + 1;
141
142 ret = i2c_transfer(client->adapter, &msg, 1);
143 if (ret < 0)
144 return ret;
145 if (ret != 1)
146 return -EINVAL;
147 return 0;
148 }
149
bq27xxx_battery_i2c_probe(struct i2c_client * client)150 static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
151 {
152 const struct i2c_device_id *id = i2c_client_get_device_id(client);
153 struct bq27xxx_device_info *di;
154 int ret;
155 char *name;
156 int num;
157
158 /* Get new ID for the new battery device */
159 mutex_lock(&battery_mutex);
160 num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
161 mutex_unlock(&battery_mutex);
162 if (num < 0)
163 return num;
164
165 name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
166 if (!name)
167 goto err_mem;
168
169 di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
170 if (!di)
171 goto err_mem;
172
173 di->id = num;
174 di->dev = &client->dev;
175 di->chip = id->driver_data;
176 di->name = name;
177
178 di->bus.read = bq27xxx_battery_i2c_read;
179 di->bus.write = bq27xxx_battery_i2c_write;
180 di->bus.read_bulk = bq27xxx_battery_i2c_bulk_read;
181 di->bus.write_bulk = bq27xxx_battery_i2c_bulk_write;
182
183 ret = bq27xxx_battery_setup(di);
184 if (ret)
185 goto err_failed;
186
187 /* Schedule a polling after about 1 min */
188 schedule_delayed_work(&di->work, 60 * HZ);
189
190 i2c_set_clientdata(client, di);
191
192 if (client->irq) {
193 ret = request_threaded_irq(client->irq,
194 NULL, bq27xxx_battery_irq_handler_thread,
195 IRQF_ONESHOT,
196 di->name, di);
197 if (ret) {
198 dev_err(&client->dev,
199 "Unable to register IRQ %d error %d\n",
200 client->irq, ret);
201 bq27xxx_battery_teardown(di);
202 goto err_failed;
203 }
204 }
205
206 return 0;
207
208 err_mem:
209 ret = -ENOMEM;
210
211 err_failed:
212 mutex_lock(&battery_mutex);
213 idr_remove(&battery_id, num);
214 mutex_unlock(&battery_mutex);
215
216 return ret;
217 }
218
bq27xxx_battery_i2c_remove(struct i2c_client * client)219 static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
220 {
221 struct bq27xxx_device_info *di = i2c_get_clientdata(client);
222
223 if (client->irq)
224 free_irq(client->irq, di);
225
226 bq27xxx_battery_teardown(di);
227
228 mutex_lock(&battery_mutex);
229 idr_remove(&battery_id, di->id);
230 mutex_unlock(&battery_mutex);
231 }
232
233 static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
234 { "bq27200", BQ27000 },
235 { "bq27210", BQ27010 },
236 { "bq27500", BQ2750X },
237 { "bq27510", BQ2751X },
238 { "bq27520", BQ2752X },
239 { "bq27500-1", BQ27500 },
240 { "bq27510g1", BQ27510G1 },
241 { "bq27510g2", BQ27510G2 },
242 { "bq27510g3", BQ27510G3 },
243 { "bq27520g1", BQ27520G1 },
244 { "bq27520g2", BQ27520G2 },
245 { "bq27520g3", BQ27520G3 },
246 { "bq27520g4", BQ27520G4 },
247 { "bq27521", BQ27521 },
248 { "bq27530", BQ27530 },
249 { "bq27531", BQ27531 },
250 { "bq27541", BQ27541 },
251 { "bq27542", BQ27542 },
252 { "bq27546", BQ27546 },
253 { "bq27742", BQ27742 },
254 { "bq27545", BQ27545 },
255 { "bq27411", BQ27411 },
256 { "bq27421", BQ27421 },
257 { "bq27425", BQ27425 },
258 { "bq27426", BQ27426 },
259 { "bq27441", BQ27441 },
260 { "bq27621", BQ27621 },
261 { "bq27z561", BQ27Z561 },
262 { "bq28z610", BQ28Z610 },
263 { "bq34z100", BQ34Z100 },
264 { "bq78z100", BQ78Z100 },
265 {},
266 };
267 MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
268
269 #ifdef CONFIG_OF
270 static const struct of_device_id bq27xxx_battery_i2c_of_match_table[] = {
271 { .compatible = "ti,bq27200" },
272 { .compatible = "ti,bq27210" },
273 { .compatible = "ti,bq27500" },
274 { .compatible = "ti,bq27510" },
275 { .compatible = "ti,bq27520" },
276 { .compatible = "ti,bq27500-1" },
277 { .compatible = "ti,bq27510g1" },
278 { .compatible = "ti,bq27510g2" },
279 { .compatible = "ti,bq27510g3" },
280 { .compatible = "ti,bq27520g1" },
281 { .compatible = "ti,bq27520g2" },
282 { .compatible = "ti,bq27520g3" },
283 { .compatible = "ti,bq27520g4" },
284 { .compatible = "ti,bq27521" },
285 { .compatible = "ti,bq27530" },
286 { .compatible = "ti,bq27531" },
287 { .compatible = "ti,bq27541" },
288 { .compatible = "ti,bq27542" },
289 { .compatible = "ti,bq27546" },
290 { .compatible = "ti,bq27742" },
291 { .compatible = "ti,bq27545" },
292 { .compatible = "ti,bq27411" },
293 { .compatible = "ti,bq27421" },
294 { .compatible = "ti,bq27425" },
295 { .compatible = "ti,bq27426" },
296 { .compatible = "ti,bq27441" },
297 { .compatible = "ti,bq27621" },
298 { .compatible = "ti,bq27z561" },
299 { .compatible = "ti,bq28z610" },
300 { .compatible = "ti,bq34z100" },
301 { .compatible = "ti,bq78z100" },
302 {},
303 };
304 MODULE_DEVICE_TABLE(of, bq27xxx_battery_i2c_of_match_table);
305 #endif
306
307 static struct i2c_driver bq27xxx_battery_i2c_driver = {
308 .driver = {
309 .name = "bq27xxx-battery",
310 .of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table),
311 },
312 .probe = bq27xxx_battery_i2c_probe,
313 .remove = bq27xxx_battery_i2c_remove,
314 .id_table = bq27xxx_i2c_id_table,
315 };
316 module_i2c_driver(bq27xxx_battery_i2c_driver);
317
318 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
319 MODULE_DESCRIPTION("BQ27xxx battery monitor i2c driver");
320 MODULE_LICENSE("GPL");
321