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