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 17 #include <linux/i2c.h> 18 #include <linux/interrupt.h> 19 #include <linux/module.h> 20 #include <asm/unaligned.h> 21 22 #include <linux/power/bq27xxx_battery.h> 23 24 static DEFINE_IDR(battery_id); 25 static DEFINE_MUTEX(battery_mutex); 26 27 static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) 28 { 29 struct bq27xxx_device_info *di = data; 30 31 bq27xxx_battery_update(di); 32 33 return IRQ_HANDLED; 34 } 35 36 static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, 37 bool single) 38 { 39 struct i2c_client *client = to_i2c_client(di->dev); 40 struct i2c_msg msg[2]; 41 unsigned char data[2]; 42 int ret; 43 44 if (!client->adapter) 45 return -ENODEV; 46 47 msg[0].addr = client->addr; 48 msg[0].flags = 0; 49 msg[0].buf = ® 50 msg[0].len = sizeof(reg); 51 msg[1].addr = client->addr; 52 msg[1].flags = I2C_M_RD; 53 msg[1].buf = data; 54 if (single) 55 msg[1].len = 1; 56 else 57 msg[1].len = 2; 58 59 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 60 if (ret < 0) 61 return ret; 62 63 if (!single) 64 ret = get_unaligned_le16(data); 65 else 66 ret = data[0]; 67 68 return ret; 69 } 70 71 static int bq27xxx_battery_i2c_probe(struct i2c_client *client, 72 const struct i2c_device_id *id) 73 { 74 struct bq27xxx_device_info *di; 75 int ret; 76 char *name; 77 int num; 78 79 /* Get new ID for the new battery device */ 80 mutex_lock(&battery_mutex); 81 num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); 82 mutex_unlock(&battery_mutex); 83 if (num < 0) 84 return num; 85 86 name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); 87 if (!name) 88 goto err_mem; 89 90 di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); 91 if (!di) 92 goto err_mem; 93 94 di->id = num; 95 di->dev = &client->dev; 96 di->chip = id->driver_data; 97 di->name = name; 98 di->bus.read = bq27xxx_battery_i2c_read; 99 100 ret = bq27xxx_battery_setup(di); 101 if (ret) 102 goto err_failed; 103 104 /* Schedule a polling after about 1 min */ 105 schedule_delayed_work(&di->work, 60 * HZ); 106 107 i2c_set_clientdata(client, di); 108 109 if (client->irq) { 110 ret = devm_request_threaded_irq(&client->dev, client->irq, 111 NULL, bq27xxx_battery_irq_handler_thread, 112 IRQF_ONESHOT, 113 di->name, di); 114 if (ret) { 115 dev_err(&client->dev, 116 "Unable to register IRQ %d error %d\n", 117 client->irq, ret); 118 return ret; 119 } 120 } 121 122 return 0; 123 124 err_mem: 125 ret = -ENOMEM; 126 127 err_failed: 128 mutex_lock(&battery_mutex); 129 idr_remove(&battery_id, num); 130 mutex_unlock(&battery_mutex); 131 132 return ret; 133 } 134 135 static int bq27xxx_battery_i2c_remove(struct i2c_client *client) 136 { 137 struct bq27xxx_device_info *di = i2c_get_clientdata(client); 138 139 bq27xxx_battery_teardown(di); 140 141 mutex_lock(&battery_mutex); 142 idr_remove(&battery_id, di->id); 143 mutex_unlock(&battery_mutex); 144 145 return 0; 146 } 147 148 static const struct i2c_device_id bq27xxx_i2c_id_table[] = { 149 { "bq27200", BQ27000 }, 150 { "bq27210", BQ27010 }, 151 { "bq27500", BQ2750X }, 152 { "bq27510", BQ2751X }, 153 { "bq27520", BQ2751X }, 154 { "bq27500-1", BQ27500 }, 155 { "bq27510g1", BQ27510G1 }, 156 { "bq27510g2", BQ27510G2 }, 157 { "bq27510g3", BQ27510G3 }, 158 { "bq27520g1", BQ27520G1 }, 159 { "bq27520g2", BQ27520G2 }, 160 { "bq27520g3", BQ27520G3 }, 161 { "bq27520g4", BQ27520G4 }, 162 { "bq27530", BQ27530 }, 163 { "bq27531", BQ27530 }, 164 { "bq27541", BQ27541 }, 165 { "bq27542", BQ27541 }, 166 { "bq27546", BQ27541 }, 167 { "bq27742", BQ27541 }, 168 { "bq27545", BQ27545 }, 169 { "bq27421", BQ27421 }, 170 { "bq27425", BQ27421 }, 171 { "bq27441", BQ27421 }, 172 { "bq27621", BQ27421 }, 173 {}, 174 }; 175 MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table); 176 177 #ifdef CONFIG_OF 178 static const struct of_device_id bq27xxx_battery_i2c_of_match_table[] = { 179 { .compatible = "ti,bq27200" }, 180 { .compatible = "ti,bq27210" }, 181 { .compatible = "ti,bq27500" }, 182 { .compatible = "ti,bq27510" }, 183 { .compatible = "ti,bq27520" }, 184 { .compatible = "ti,bq27500-1" }, 185 { .compatible = "ti,bq27510g1" }, 186 { .compatible = "ti,bq27510g2" }, 187 { .compatible = "ti,bq27510g3" }, 188 { .compatible = "ti,bq27520g1" }, 189 { .compatible = "ti,bq27520g2" }, 190 { .compatible = "ti,bq27520g3" }, 191 { .compatible = "ti,bq27520g4" }, 192 { .compatible = "ti,bq27530" }, 193 { .compatible = "ti,bq27531" }, 194 { .compatible = "ti,bq27541" }, 195 { .compatible = "ti,bq27542" }, 196 { .compatible = "ti,bq27546" }, 197 { .compatible = "ti,bq27742" }, 198 { .compatible = "ti,bq27545" }, 199 { .compatible = "ti,bq27421" }, 200 { .compatible = "ti,bq27425" }, 201 { .compatible = "ti,bq27441" }, 202 { .compatible = "ti,bq27621" }, 203 {}, 204 }; 205 MODULE_DEVICE_TABLE(of, bq27xxx_battery_i2c_of_match_table); 206 #endif 207 208 static struct i2c_driver bq27xxx_battery_i2c_driver = { 209 .driver = { 210 .name = "bq27xxx-battery", 211 .of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table), 212 }, 213 .probe = bq27xxx_battery_i2c_probe, 214 .remove = bq27xxx_battery_i2c_remove, 215 .id_table = bq27xxx_i2c_id_table, 216 }; 217 module_i2c_driver(bq27xxx_battery_i2c_driver); 218 219 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); 220 MODULE_DESCRIPTION("BQ27xxx battery monitor i2c driver"); 221 MODULE_LICENSE("GPL"); 222