ltc4260.c 5.2 KB

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