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