• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &reg;
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