1*79ffe859SGuenter Roeck /* 2*79ffe859SGuenter Roeck * Driver for Linear Technology LTC4222 Dual Hot Swap controller 3*79ffe859SGuenter Roeck * 4*79ffe859SGuenter Roeck * Copyright (c) 2014 Guenter Roeck 5*79ffe859SGuenter Roeck * 6*79ffe859SGuenter Roeck * This program is free software; you can redistribute it and/or modify 7*79ffe859SGuenter Roeck * it under the terms of the GNU General Public License as published by 8*79ffe859SGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 9*79ffe859SGuenter Roeck * (at your option) any later version. 10*79ffe859SGuenter Roeck * 11*79ffe859SGuenter Roeck * This program is distributed in the hope that it will be useful, 12*79ffe859SGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*79ffe859SGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*79ffe859SGuenter Roeck * GNU General Public License for more details. 15*79ffe859SGuenter Roeck */ 16*79ffe859SGuenter Roeck 17*79ffe859SGuenter Roeck #include <linux/kernel.h> 18*79ffe859SGuenter Roeck #include <linux/module.h> 19*79ffe859SGuenter Roeck #include <linux/err.h> 20*79ffe859SGuenter Roeck #include <linux/slab.h> 21*79ffe859SGuenter Roeck #include <linux/bitops.h> 22*79ffe859SGuenter Roeck #include <linux/i2c.h> 23*79ffe859SGuenter Roeck #include <linux/hwmon.h> 24*79ffe859SGuenter Roeck #include <linux/hwmon-sysfs.h> 25*79ffe859SGuenter Roeck #include <linux/jiffies.h> 26*79ffe859SGuenter Roeck #include <linux/regmap.h> 27*79ffe859SGuenter Roeck 28*79ffe859SGuenter Roeck /* chip registers */ 29*79ffe859SGuenter Roeck 30*79ffe859SGuenter Roeck #define LTC4222_CONTROL1 0xd0 31*79ffe859SGuenter Roeck #define LTC4222_ALERT1 0xd1 32*79ffe859SGuenter Roeck #define LTC4222_STATUS1 0xd2 33*79ffe859SGuenter Roeck #define LTC4222_FAULT1 0xd3 34*79ffe859SGuenter Roeck #define LTC4222_CONTROL2 0xd4 35*79ffe859SGuenter Roeck #define LTC4222_ALERT2 0xd5 36*79ffe859SGuenter Roeck #define LTC4222_STATUS2 0xd6 37*79ffe859SGuenter Roeck #define LTC4222_FAULT2 0xd7 38*79ffe859SGuenter Roeck #define LTC4222_SOURCE1 0xd8 39*79ffe859SGuenter Roeck #define LTC4222_SOURCE2 0xda 40*79ffe859SGuenter Roeck #define LTC4222_ADIN1 0xdc 41*79ffe859SGuenter Roeck #define LTC4222_ADIN2 0xde 42*79ffe859SGuenter Roeck #define LTC4222_SENSE1 0xe0 43*79ffe859SGuenter Roeck #define LTC4222_SENSE2 0xe2 44*79ffe859SGuenter Roeck #define LTC4222_ADC_CONTROL 0xe4 45*79ffe859SGuenter Roeck 46*79ffe859SGuenter Roeck /* 47*79ffe859SGuenter Roeck * Fault register bits 48*79ffe859SGuenter Roeck */ 49*79ffe859SGuenter Roeck #define FAULT_OV BIT(0) 50*79ffe859SGuenter Roeck #define FAULT_UV BIT(1) 51*79ffe859SGuenter Roeck #define FAULT_OC BIT(2) 52*79ffe859SGuenter Roeck #define FAULT_POWER_BAD BIT(3) 53*79ffe859SGuenter Roeck #define FAULT_FET_BAD BIT(5) 54*79ffe859SGuenter Roeck 55*79ffe859SGuenter Roeck /* Return the voltage from the given register in mV or mA */ 56*79ffe859SGuenter Roeck static int ltc4222_get_value(struct device *dev, u8 reg) 57*79ffe859SGuenter Roeck { 58*79ffe859SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 59*79ffe859SGuenter Roeck unsigned int val; 60*79ffe859SGuenter Roeck u8 buf[2]; 61*79ffe859SGuenter Roeck int ret; 62*79ffe859SGuenter Roeck 63*79ffe859SGuenter Roeck ret = regmap_bulk_read(regmap, reg, buf, 2); 64*79ffe859SGuenter Roeck if (ret < 0) 65*79ffe859SGuenter Roeck return ret; 66*79ffe859SGuenter Roeck 67*79ffe859SGuenter Roeck val = ((buf[0] << 8) + buf[1]) >> 6; 68*79ffe859SGuenter Roeck 69*79ffe859SGuenter Roeck switch (reg) { 70*79ffe859SGuenter Roeck case LTC4222_ADIN1: 71*79ffe859SGuenter Roeck case LTC4222_ADIN2: 72*79ffe859SGuenter Roeck /* 1.25 mV resolution. Convert to mV. */ 73*79ffe859SGuenter Roeck val = DIV_ROUND_CLOSEST(val * 5, 4); 74*79ffe859SGuenter Roeck break; 75*79ffe859SGuenter Roeck case LTC4222_SOURCE1: 76*79ffe859SGuenter Roeck case LTC4222_SOURCE2: 77*79ffe859SGuenter Roeck /* 31.25 mV resolution. Convert to mV. */ 78*79ffe859SGuenter Roeck val = DIV_ROUND_CLOSEST(val * 125, 4); 79*79ffe859SGuenter Roeck break; 80*79ffe859SGuenter Roeck case LTC4222_SENSE1: 81*79ffe859SGuenter Roeck case LTC4222_SENSE2: 82*79ffe859SGuenter Roeck /* 83*79ffe859SGuenter Roeck * 62.5 uV resolution. Convert to current as measured with 84*79ffe859SGuenter Roeck * an 1 mOhm sense resistor, in mA. If a different sense 85*79ffe859SGuenter Roeck * resistor is installed, calculate the actual current by 86*79ffe859SGuenter Roeck * dividing the reported current by the sense resistor value 87*79ffe859SGuenter Roeck * in mOhm. 88*79ffe859SGuenter Roeck */ 89*79ffe859SGuenter Roeck val = DIV_ROUND_CLOSEST(val * 125, 2); 90*79ffe859SGuenter Roeck break; 91*79ffe859SGuenter Roeck default: 92*79ffe859SGuenter Roeck return -EINVAL; 93*79ffe859SGuenter Roeck } 94*79ffe859SGuenter Roeck return val; 95*79ffe859SGuenter Roeck } 96*79ffe859SGuenter Roeck 97*79ffe859SGuenter Roeck static ssize_t ltc4222_show_value(struct device *dev, 98*79ffe859SGuenter Roeck struct device_attribute *da, char *buf) 99*79ffe859SGuenter Roeck { 100*79ffe859SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 101*79ffe859SGuenter Roeck int value; 102*79ffe859SGuenter Roeck 103*79ffe859SGuenter Roeck value = ltc4222_get_value(dev, attr->index); 104*79ffe859SGuenter Roeck if (value < 0) 105*79ffe859SGuenter Roeck return value; 106*79ffe859SGuenter Roeck return snprintf(buf, PAGE_SIZE, "%d\n", value); 107*79ffe859SGuenter Roeck } 108*79ffe859SGuenter Roeck 109*79ffe859SGuenter Roeck static ssize_t ltc4222_show_bool(struct device *dev, 110*79ffe859SGuenter Roeck struct device_attribute *da, char *buf) 111*79ffe859SGuenter Roeck { 112*79ffe859SGuenter Roeck struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); 113*79ffe859SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 114*79ffe859SGuenter Roeck unsigned int fault; 115*79ffe859SGuenter Roeck int ret; 116*79ffe859SGuenter Roeck 117*79ffe859SGuenter Roeck ret = regmap_read(regmap, attr->nr, &fault); 118*79ffe859SGuenter Roeck if (ret < 0) 119*79ffe859SGuenter Roeck return ret; 120*79ffe859SGuenter Roeck fault &= attr->index; 121*79ffe859SGuenter Roeck if (fault) /* Clear reported faults in chip register */ 122*79ffe859SGuenter Roeck regmap_update_bits(regmap, attr->nr, attr->index, 0); 123*79ffe859SGuenter Roeck 124*79ffe859SGuenter Roeck return snprintf(buf, PAGE_SIZE, "%d\n", !!fault); 125*79ffe859SGuenter Roeck } 126*79ffe859SGuenter Roeck 127*79ffe859SGuenter Roeck /* Voltages */ 128*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4222_show_value, NULL, 129*79ffe859SGuenter Roeck LTC4222_SOURCE1); 130*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4222_show_value, NULL, 131*79ffe859SGuenter Roeck LTC4222_ADIN1); 132*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4222_show_value, NULL, 133*79ffe859SGuenter Roeck LTC4222_SOURCE2); 134*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4222_show_value, NULL, 135*79ffe859SGuenter Roeck LTC4222_ADIN2); 136*79ffe859SGuenter Roeck 137*79ffe859SGuenter Roeck /* 138*79ffe859SGuenter Roeck * Voltage alarms 139*79ffe859SGuenter Roeck * UV/OV faults are associated with the input voltage, and power bad and fet 140*79ffe859SGuenter Roeck * faults are associated with the output voltage. 141*79ffe859SGuenter Roeck */ 142*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4222_show_bool, NULL, 143*79ffe859SGuenter Roeck LTC4222_FAULT1, FAULT_UV); 144*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(in1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, 145*79ffe859SGuenter Roeck LTC4222_FAULT1, FAULT_OV); 146*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, ltc4222_show_bool, NULL, 147*79ffe859SGuenter Roeck LTC4222_FAULT1, FAULT_POWER_BAD | FAULT_FET_BAD); 148*79ffe859SGuenter Roeck 149*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4222_show_bool, NULL, 150*79ffe859SGuenter Roeck LTC4222_FAULT2, FAULT_UV); 151*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(in3_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, 152*79ffe859SGuenter Roeck LTC4222_FAULT2, FAULT_OV); 153*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, ltc4222_show_bool, NULL, 154*79ffe859SGuenter Roeck LTC4222_FAULT2, FAULT_POWER_BAD | FAULT_FET_BAD); 155*79ffe859SGuenter Roeck 156*79ffe859SGuenter Roeck /* Current (via sense resistor) */ 157*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4222_show_value, NULL, 158*79ffe859SGuenter Roeck LTC4222_SENSE1); 159*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4222_show_value, NULL, 160*79ffe859SGuenter Roeck LTC4222_SENSE2); 161*79ffe859SGuenter Roeck 162*79ffe859SGuenter Roeck /* Overcurrent alarm */ 163*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, 164*79ffe859SGuenter Roeck LTC4222_FAULT1, FAULT_OC); 165*79ffe859SGuenter Roeck static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4222_show_bool, NULL, 166*79ffe859SGuenter Roeck LTC4222_FAULT2, FAULT_OC); 167*79ffe859SGuenter Roeck 168*79ffe859SGuenter Roeck static struct attribute *ltc4222_attrs[] = { 169*79ffe859SGuenter Roeck &sensor_dev_attr_in1_input.dev_attr.attr, 170*79ffe859SGuenter Roeck &sensor_dev_attr_in1_min_alarm.dev_attr.attr, 171*79ffe859SGuenter Roeck &sensor_dev_attr_in1_max_alarm.dev_attr.attr, 172*79ffe859SGuenter Roeck &sensor_dev_attr_in2_input.dev_attr.attr, 173*79ffe859SGuenter Roeck &sensor_dev_attr_in2_alarm.dev_attr.attr, 174*79ffe859SGuenter Roeck &sensor_dev_attr_in3_input.dev_attr.attr, 175*79ffe859SGuenter Roeck &sensor_dev_attr_in3_min_alarm.dev_attr.attr, 176*79ffe859SGuenter Roeck &sensor_dev_attr_in3_max_alarm.dev_attr.attr, 177*79ffe859SGuenter Roeck &sensor_dev_attr_in4_input.dev_attr.attr, 178*79ffe859SGuenter Roeck &sensor_dev_attr_in4_alarm.dev_attr.attr, 179*79ffe859SGuenter Roeck 180*79ffe859SGuenter Roeck &sensor_dev_attr_curr1_input.dev_attr.attr, 181*79ffe859SGuenter Roeck &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, 182*79ffe859SGuenter Roeck &sensor_dev_attr_curr2_input.dev_attr.attr, 183*79ffe859SGuenter Roeck &sensor_dev_attr_curr2_max_alarm.dev_attr.attr, 184*79ffe859SGuenter Roeck 185*79ffe859SGuenter Roeck NULL, 186*79ffe859SGuenter Roeck }; 187*79ffe859SGuenter Roeck ATTRIBUTE_GROUPS(ltc4222); 188*79ffe859SGuenter Roeck 189*79ffe859SGuenter Roeck static struct regmap_config ltc4222_regmap_config = { 190*79ffe859SGuenter Roeck .reg_bits = 8, 191*79ffe859SGuenter Roeck .val_bits = 8, 192*79ffe859SGuenter Roeck .max_register = LTC4222_ADC_CONTROL, 193*79ffe859SGuenter Roeck }; 194*79ffe859SGuenter Roeck 195*79ffe859SGuenter Roeck static int ltc4222_probe(struct i2c_client *client, 196*79ffe859SGuenter Roeck const struct i2c_device_id *id) 197*79ffe859SGuenter Roeck { 198*79ffe859SGuenter Roeck struct device *dev = &client->dev; 199*79ffe859SGuenter Roeck struct device *hwmon_dev; 200*79ffe859SGuenter Roeck struct regmap *regmap; 201*79ffe859SGuenter Roeck 202*79ffe859SGuenter Roeck regmap = devm_regmap_init_i2c(client, <c4222_regmap_config); 203*79ffe859SGuenter Roeck if (IS_ERR(regmap)) { 204*79ffe859SGuenter Roeck dev_err(dev, "failed to allocate register map\n"); 205*79ffe859SGuenter Roeck return PTR_ERR(regmap); 206*79ffe859SGuenter Roeck } 207*79ffe859SGuenter Roeck 208*79ffe859SGuenter Roeck /* Clear faults */ 209*79ffe859SGuenter Roeck regmap_write(regmap, LTC4222_FAULT1, 0x00); 210*79ffe859SGuenter Roeck regmap_write(regmap, LTC4222_FAULT2, 0x00); 211*79ffe859SGuenter Roeck 212*79ffe859SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 213*79ffe859SGuenter Roeck regmap, 214*79ffe859SGuenter Roeck ltc4222_groups); 215*79ffe859SGuenter Roeck return PTR_ERR_OR_ZERO(hwmon_dev); 216*79ffe859SGuenter Roeck } 217*79ffe859SGuenter Roeck 218*79ffe859SGuenter Roeck static const struct i2c_device_id ltc4222_id[] = { 219*79ffe859SGuenter Roeck {"ltc4222", 0}, 220*79ffe859SGuenter Roeck { } 221*79ffe859SGuenter Roeck }; 222*79ffe859SGuenter Roeck 223*79ffe859SGuenter Roeck MODULE_DEVICE_TABLE(i2c, ltc4222_id); 224*79ffe859SGuenter Roeck 225*79ffe859SGuenter Roeck static struct i2c_driver ltc4222_driver = { 226*79ffe859SGuenter Roeck .driver = { 227*79ffe859SGuenter Roeck .name = "ltc4222", 228*79ffe859SGuenter Roeck }, 229*79ffe859SGuenter Roeck .probe = ltc4222_probe, 230*79ffe859SGuenter Roeck .id_table = ltc4222_id, 231*79ffe859SGuenter Roeck }; 232*79ffe859SGuenter Roeck 233*79ffe859SGuenter Roeck module_i2c_driver(ltc4222_driver); 234*79ffe859SGuenter Roeck 235*79ffe859SGuenter Roeck MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); 236*79ffe859SGuenter Roeck MODULE_DESCRIPTION("LTC4222 driver"); 237*79ffe859SGuenter Roeck MODULE_LICENSE("GPL"); 238