1 /* 2 * BQ27xxx battery monitor HDQ/1-wire driver 3 * 4 * Copyright (C) 2007-2017 Texas Instruments Incorporated - http://www.ti.com/ 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 11 * kind, whether express or implied; without even the implied warranty 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/device.h> 19 #include <linux/types.h> 20 #include <linux/platform_device.h> 21 #include <linux/mutex.h> 22 #include <linux/power/bq27xxx_battery.h> 23 24 #include <linux/w1.h> 25 26 #define W1_FAMILY_BQ27000 0x01 27 28 #define HDQ_CMD_READ (0 << 7) 29 #define HDQ_CMD_WRITE (1 << 7) 30 31 static int F_ID; 32 module_param(F_ID, int, S_IRUSR); 33 MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ27xxx device"); 34 35 static int w1_bq27000_read(struct w1_slave *sl, unsigned int reg) 36 { 37 u8 val; 38 39 mutex_lock(&sl->master->bus_mutex); 40 w1_write_8(sl->master, HDQ_CMD_READ | reg); 41 val = w1_read_8(sl->master); 42 mutex_unlock(&sl->master->bus_mutex); 43 44 return val; 45 } 46 47 static int bq27xxx_battery_hdq_read(struct bq27xxx_device_info *di, u8 reg, 48 bool single) 49 { 50 struct w1_slave *sl = dev_to_w1_slave(di->dev); 51 unsigned int timeout = 3; 52 int upper, lower; 53 int temp; 54 55 if (!single) { 56 /* 57 * Make sure the value has not changed in between reading the 58 * lower and the upper part 59 */ 60 upper = w1_bq27000_read(sl, reg + 1); 61 do { 62 temp = upper; 63 if (upper < 0) 64 return upper; 65 66 lower = w1_bq27000_read(sl, reg); 67 if (lower < 0) 68 return lower; 69 70 upper = w1_bq27000_read(sl, reg + 1); 71 } while (temp != upper && --timeout); 72 73 if (timeout == 0) 74 return -EIO; 75 76 return (upper << 8) | lower; 77 } 78 79 return w1_bq27000_read(sl, reg); 80 } 81 82 static int bq27xxx_battery_hdq_add_slave(struct w1_slave *sl) 83 { 84 struct bq27xxx_device_info *di; 85 86 di = devm_kzalloc(&sl->dev, sizeof(*di), GFP_KERNEL); 87 if (!di) 88 return -ENOMEM; 89 90 dev_set_drvdata(&sl->dev, di); 91 92 di->dev = &sl->dev; 93 di->chip = BQ27000; 94 di->name = "bq27000-battery"; 95 di->bus.read = bq27xxx_battery_hdq_read; 96 97 return bq27xxx_battery_setup(di); 98 } 99 100 static void bq27xxx_battery_hdq_remove_slave(struct w1_slave *sl) 101 { 102 struct bq27xxx_device_info *di = dev_get_drvdata(&sl->dev); 103 104 bq27xxx_battery_teardown(di); 105 } 106 107 static struct w1_family_ops bq27xxx_battery_hdq_fops = { 108 .add_slave = bq27xxx_battery_hdq_add_slave, 109 .remove_slave = bq27xxx_battery_hdq_remove_slave, 110 }; 111 112 static struct w1_family bq27xxx_battery_hdq_family = { 113 .fid = W1_FAMILY_BQ27000, 114 .fops = &bq27xxx_battery_hdq_fops, 115 }; 116 117 static int __init bq27xxx_battery_hdq_init(void) 118 { 119 if (F_ID) 120 bq27xxx_battery_hdq_family.fid = F_ID; 121 122 return w1_register_family(&bq27xxx_battery_hdq_family); 123 } 124 module_init(bq27xxx_battery_hdq_init); 125 126 static void __exit bq27xxx_battery_hdq_exit(void) 127 { 128 w1_unregister_family(&bq27xxx_battery_hdq_family); 129 } 130 module_exit(bq27xxx_battery_hdq_exit); 131 132 MODULE_AUTHOR("Texas Instruments Ltd"); 133 MODULE_DESCRIPTION("BQ27xxx battery monitor HDQ/1-wire driver"); 134 MODULE_LICENSE("GPL"); 135 MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000)); 136