root/drivers/hwmon/ltc4260.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ltc4260_get_value
  2. ltc4260_value_show
  3. ltc4260_bool_show
  4. ltc4260_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Driver for Linear Technology LTC4260 I2C Positive Voltage Hot Swap Controller
   4  *
   5  * Copyright (c) 2014 Guenter Roeck
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/err.h>
  11 #include <linux/slab.h>
  12 #include <linux/i2c.h>
  13 #include <linux/hwmon.h>
  14 #include <linux/hwmon-sysfs.h>
  15 #include <linux/jiffies.h>
  16 #include <linux/regmap.h>
  17 
  18 /* chip registers */
  19 #define LTC4260_CONTROL 0x00
  20 #define LTC4260_ALERT   0x01
  21 #define LTC4260_STATUS  0x02
  22 #define LTC4260_FAULT   0x03
  23 #define LTC4260_SENSE   0x04
  24 #define LTC4260_SOURCE  0x05
  25 #define LTC4260_ADIN    0x06
  26 
  27 /*
  28  * Fault register bits
  29  */
  30 #define FAULT_OV        (1 << 0)
  31 #define FAULT_UV        (1 << 1)
  32 #define FAULT_OC        (1 << 2)
  33 #define FAULT_POWER_BAD (1 << 3)
  34 #define FAULT_FET_SHORT (1 << 5)
  35 
  36 /* Return the voltage from the given register in mV or mA */
  37 static int ltc4260_get_value(struct device *dev, u8 reg)
  38 {
  39         struct regmap *regmap = dev_get_drvdata(dev);
  40         unsigned int val;
  41         int ret;
  42 
  43         ret = regmap_read(regmap, reg, &val);
  44         if (ret < 0)
  45                 return ret;
  46 
  47         switch (reg) {
  48         case LTC4260_ADIN:
  49                 /* 10 mV resolution. Convert to mV. */
  50                 val = val * 10;
  51                 break;
  52         case LTC4260_SOURCE:
  53                 /* 400 mV resolution. Convert to mV. */
  54                 val = val * 400;
  55                 break;
  56         case LTC4260_SENSE:
  57                 /*
  58                  * 300 uV resolution. Convert to current as measured with
  59                  * an 1 mOhm sense resistor, in mA. If a different sense
  60                  * resistor is installed, calculate the actual current by
  61                  * dividing the reported current by the sense resistor value
  62                  * in mOhm.
  63                  */
  64                 val = val * 300;
  65                 break;
  66         default:
  67                 return -EINVAL;
  68         }
  69 
  70         return val;
  71 }
  72 
  73 static ssize_t ltc4260_value_show(struct device *dev,
  74                                   struct device_attribute *da, char *buf)
  75 {
  76         struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  77         int value;
  78 
  79         value = ltc4260_get_value(dev, attr->index);
  80         if (value < 0)
  81                 return value;
  82         return snprintf(buf, PAGE_SIZE, "%d\n", value);
  83 }
  84 
  85 static ssize_t ltc4260_bool_show(struct device *dev,
  86                                  struct device_attribute *da, char *buf)
  87 {
  88         struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  89         struct regmap *regmap = dev_get_drvdata(dev);
  90         unsigned int fault;
  91         int ret;
  92 
  93         ret = regmap_read(regmap, LTC4260_FAULT, &fault);
  94         if (ret < 0)
  95                 return ret;
  96 
  97         fault &= attr->index;
  98         if (fault)              /* Clear reported faults in chip register */
  99                 regmap_update_bits(regmap, LTC4260_FAULT, attr->index, 0);
 100 
 101         return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
 102 }
 103 
 104 /* Voltages */
 105 static SENSOR_DEVICE_ATTR_RO(in1_input, ltc4260_value, LTC4260_SOURCE);
 106 static SENSOR_DEVICE_ATTR_RO(in2_input, ltc4260_value, LTC4260_ADIN);
 107 
 108 /*
 109  * Voltage alarms
 110  * UV/OV faults are associated with the input voltage, and the POWER BAD and
 111  * FET SHORT faults are associated with the output voltage.
 112  */
 113 static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ltc4260_bool, FAULT_UV);
 114 static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ltc4260_bool, FAULT_OV);
 115 static SENSOR_DEVICE_ATTR_RO(in2_alarm, ltc4260_bool,
 116                              FAULT_POWER_BAD | FAULT_FET_SHORT);
 117 
 118 /* Current (via sense resistor) */
 119 static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc4260_value, LTC4260_SENSE);
 120 
 121 /* Overcurrent alarm */
 122 static SENSOR_DEVICE_ATTR_RO(curr1_max_alarm, ltc4260_bool, FAULT_OC);
 123 
 124 static struct attribute *ltc4260_attrs[] = {
 125         &sensor_dev_attr_in1_input.dev_attr.attr,
 126         &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
 127         &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
 128         &sensor_dev_attr_in2_input.dev_attr.attr,
 129         &sensor_dev_attr_in2_alarm.dev_attr.attr,
 130 
 131         &sensor_dev_attr_curr1_input.dev_attr.attr,
 132         &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
 133 
 134         NULL,
 135 };
 136 ATTRIBUTE_GROUPS(ltc4260);
 137 
 138 static const struct regmap_config ltc4260_regmap_config = {
 139         .reg_bits = 8,
 140         .val_bits = 8,
 141         .max_register = LTC4260_ADIN,
 142 };
 143 
 144 static int ltc4260_probe(struct i2c_client *client,
 145                          const struct i2c_device_id *id)
 146 {
 147         struct device *dev = &client->dev;
 148         struct device *hwmon_dev;
 149         struct regmap *regmap;
 150 
 151         regmap = devm_regmap_init_i2c(client, &ltc4260_regmap_config);
 152         if (IS_ERR(regmap)) {
 153                 dev_err(dev, "failed to allocate register map\n");
 154                 return PTR_ERR(regmap);
 155         }
 156 
 157         /* Clear faults */
 158         regmap_write(regmap, LTC4260_FAULT, 0x00);
 159 
 160         hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 161                                                            regmap,
 162                                                            ltc4260_groups);
 163         return PTR_ERR_OR_ZERO(hwmon_dev);
 164 }
 165 
 166 static const struct i2c_device_id ltc4260_id[] = {
 167         {"ltc4260", 0},
 168         { }
 169 };
 170 
 171 MODULE_DEVICE_TABLE(i2c, ltc4260_id);
 172 
 173 static struct i2c_driver ltc4260_driver = {
 174         .driver = {
 175                    .name = "ltc4260",
 176                    },
 177         .probe = ltc4260_probe,
 178         .id_table = ltc4260_id,
 179 };
 180 
 181 module_i2c_driver(ltc4260_driver);
 182 
 183 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
 184 MODULE_DESCRIPTION("LTC4260 driver");
 185 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */