brintos

brintos / linux-shallow public Read only

0
0
Text · 15.2 KiB · 3e0e0e0 Raw
531 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Linear Technology LTC2945 I2C Power Monitor4 *5 * Copyright (c) 2014 Guenter Roeck6 */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 LTC2945_CONTROL			0x0020#define LTC2945_ALERT			0x0121#define LTC2945_STATUS			0x0222#define LTC2945_FAULT			0x0323#define LTC2945_POWER_H			0x0524#define LTC2945_MAX_POWER_H		0x0825#define LTC2945_MIN_POWER_H		0x0b26#define LTC2945_MAX_POWER_THRES_H	0x0e27#define LTC2945_MIN_POWER_THRES_H	0x1128#define LTC2945_SENSE_H			0x1429#define LTC2945_MAX_SENSE_H		0x1630#define LTC2945_MIN_SENSE_H		0x1831#define LTC2945_MAX_SENSE_THRES_H	0x1a32#define LTC2945_MIN_SENSE_THRES_H	0x1c33#define LTC2945_VIN_H			0x1e34#define LTC2945_MAX_VIN_H		0x2035#define LTC2945_MIN_VIN_H		0x2236#define LTC2945_MAX_VIN_THRES_H		0x2437#define LTC2945_MIN_VIN_THRES_H		0x2638#define LTC2945_ADIN_H			0x2839#define LTC2945_MAX_ADIN_H		0x2a40#define LTC2945_MIN_ADIN_H		0x2c41#define LTC2945_MAX_ADIN_THRES_H	0x2e42#define LTC2945_MIN_ADIN_THRES_H	0x3043#define LTC2945_MIN_ADIN_THRES_L	0x3144 45/* Fault register bits */46 47#define FAULT_ADIN_UV		(1 << 0)48#define FAULT_ADIN_OV		(1 << 1)49#define FAULT_VIN_UV		(1 << 2)50#define FAULT_VIN_OV		(1 << 3)51#define FAULT_SENSE_UV		(1 << 4)52#define FAULT_SENSE_OV		(1 << 5)53#define FAULT_POWER_UV		(1 << 6)54#define FAULT_POWER_OV		(1 << 7)55 56/* Control register bits */57 58#define CONTROL_MULT_SELECT	(1 << 0)59#define CONTROL_TEST_MODE	(1 << 4)60 61static const struct of_device_id __maybe_unused ltc2945_of_match[] = {62	{ .compatible = "adi,ltc2945" },63	{ }64};65MODULE_DEVICE_TABLE(of, ltc2945_of_match);66 67/**68 * struct ltc2945_data - LTC2945 device data69 * @regmap: regmap device70 * @shunt_resistor: shunt resistor value in micro ohms (1000 by default)71 */72struct ltc2945_data {73	struct regmap *regmap;74	u32 shunt_resistor;75};76 77static inline bool is_power_reg(u8 reg)78{79	return reg < LTC2945_SENSE_H;80}81 82/* Return the value from the given register in uW, mV, or mA */83static long long ltc2945_reg_to_val(struct device *dev, u8 reg)84{85	struct ltc2945_data *data = dev_get_drvdata(dev);86	struct regmap *regmap = data->regmap;87	u32 shunt_resistor = data->shunt_resistor;88	unsigned int control;89	u8 buf[3];90	long long val;91	int ret;92 93	ret = regmap_bulk_read(regmap, reg, buf,94			       is_power_reg(reg) ? 3 : 2);95	if (ret < 0)96		return ret;97 98	if (is_power_reg(reg)) {99		/* 24-bit power */100		val = (buf[0] << 16) + (buf[1] << 8) + buf[2];101	} else {102		/* 12-bit current, voltage */103		val = (buf[0] << 4) + (buf[1] >> 4);104	}105 106	switch (reg) {107	case LTC2945_POWER_H:108	case LTC2945_MAX_POWER_H:109	case LTC2945_MIN_POWER_H:110	case LTC2945_MAX_POWER_THRES_H:111	case LTC2945_MIN_POWER_THRES_H:112		/*113		 * Convert to uW114		 * Control register bit 0 selects if voltage at SENSE+/VDD115		 * or voltage at ADIN is used to measure power.116		 */117		ret = regmap_read(regmap, LTC2945_CONTROL, &control);118		if (ret < 0)119			return ret;120		if (control & CONTROL_MULT_SELECT) {121			/* 25 mV * 25 uV = 0.625 uV resolution. */122			val *= 625LL;123		} else {124			/* 0.5 mV * 25 uV = 0.0125 uV resolution. */125			val = (val * 25LL) >> 1;126		}127		val *= 1000;128		/* Overflow check: Assuming max 24-bit power, val is at most 53 bits right now. */129		val = DIV_ROUND_CLOSEST_ULL(val, shunt_resistor);130		/*131		 * Overflow check: After division, depending on shunt resistor,132		 * val can still be > 32 bits so returning long long makes sense133		 */134 135		break;136	case LTC2945_VIN_H:137	case LTC2945_MAX_VIN_H:138	case LTC2945_MIN_VIN_H:139	case LTC2945_MAX_VIN_THRES_H:140	case LTC2945_MIN_VIN_THRES_H:141		/* 25 mV resolution. Convert to mV. */142		val *= 25;143		break;144	case LTC2945_ADIN_H:145	case LTC2945_MAX_ADIN_H:146	case LTC2945_MIN_ADIN_THRES_H:147	case LTC2945_MAX_ADIN_THRES_H:148	case LTC2945_MIN_ADIN_H:149		/* 0.5mV resolution. Convert to mV. */150		val = val >> 1;151		break;152	case LTC2945_SENSE_H:153	case LTC2945_MAX_SENSE_H:154	case LTC2945_MIN_SENSE_H:155	case LTC2945_MAX_SENSE_THRES_H:156	case LTC2945_MIN_SENSE_THRES_H:157		/* 25 uV resolution. Convert to mA. */158		val *= 25 * 1000;159		/* Overflow check: Assuming max 12-bit sense, val is at most 27 bits right now */160		val = DIV_ROUND_CLOSEST_ULL(val, shunt_resistor);161		/* Overflow check: After division, <= 27 bits */162		break;163	default:164		return -EINVAL;165	}166	return val;167}168 169static long long ltc2945_val_to_reg(struct device *dev, u8 reg,170				    unsigned long long val)171{172	struct ltc2945_data *data = dev_get_drvdata(dev);173	struct regmap *regmap = data->regmap;174	u32 shunt_resistor = data->shunt_resistor;175	unsigned int control;176	int ret;177 178	/* Ensure we don't overflow */179	val = clamp_val(val, 0, U32_MAX);180 181	switch (reg) {182	case LTC2945_POWER_H:183	case LTC2945_MAX_POWER_H:184	case LTC2945_MIN_POWER_H:185	case LTC2945_MAX_POWER_THRES_H:186	case LTC2945_MIN_POWER_THRES_H:187		/*188		 * Control register bit 0 selects if voltage at SENSE+/VDD189		 * or voltage at ADIN is used to measure power, which in turn190		 * determines register calculations.191		 */192		ret = regmap_read(regmap, LTC2945_CONTROL, &control);193		if (ret < 0)194			return ret;195		if (control & CONTROL_MULT_SELECT) {196			/* 25 mV * 25 uV = 0.625 uV resolution. */197			val *= shunt_resistor;198			/* Overflow check: Assuming 32-bit val and shunt resistor, val <= 64bits */199			val = DIV_ROUND_CLOSEST_ULL(val, 625 * 1000);200			/* Overflow check: val is now <= 44 bits */201		} else {202			/* 0.5 mV * 25 uV = 0.0125 uV resolution. */203			val *= shunt_resistor;204			/* Overflow check: Assuming 32-bit val and shunt resistor, val <= 64bits */205			val = DIV_ROUND_CLOSEST_ULL(val, 25 * 1000) * 2;206			/* Overflow check: val is now <= 51 bits */207		}208		break;209	case LTC2945_VIN_H:210	case LTC2945_MAX_VIN_H:211	case LTC2945_MIN_VIN_H:212	case LTC2945_MAX_VIN_THRES_H:213	case LTC2945_MIN_VIN_THRES_H:214		/* 25 mV resolution. */215		val = DIV_ROUND_CLOSEST_ULL(val, 25);216		break;217	case LTC2945_ADIN_H:218	case LTC2945_MAX_ADIN_H:219	case LTC2945_MIN_ADIN_THRES_H:220	case LTC2945_MAX_ADIN_THRES_H:221	case LTC2945_MIN_ADIN_H:222		/* 0.5mV resolution. */223		val *= 2;224		break;225	case LTC2945_SENSE_H:226	case LTC2945_MAX_SENSE_H:227	case LTC2945_MIN_SENSE_H:228	case LTC2945_MAX_SENSE_THRES_H:229	case LTC2945_MIN_SENSE_THRES_H:230		/* 25 uV resolution. Convert to  mA. */231		val *= shunt_resistor;232		/* Overflow check: Assuming 32-bit val and 32-bit shunt resistor, val is 64bits */233		val = DIV_ROUND_CLOSEST_ULL(val, 25 * 1000);234		/* Overflow check: val is now <= 50 bits */235		break;236	default:237		return -EINVAL;238	}239	return val;240}241 242static ssize_t ltc2945_value_show(struct device *dev,243				  struct device_attribute *da, char *buf)244{245	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);246	long long value;247 248	value = ltc2945_reg_to_val(dev, attr->index);249	if (value < 0)250		return value;251	return sysfs_emit(buf, "%lld\n", value);252}253 254static ssize_t ltc2945_value_store(struct device *dev,255				   struct device_attribute *da,256				   const char *buf, size_t count)257{258	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);259	struct ltc2945_data *data = dev_get_drvdata(dev);260	struct regmap *regmap = data->regmap;261	u8 reg = attr->index;262	unsigned int val;263	u8 regbuf[3];264	int num_regs;265	long long regval;266	int ret;267 268	ret = kstrtouint(buf, 10, &val);269	if (ret)270		return ret;271 272	/* convert to register value, then clamp and write result */273	regval = ltc2945_val_to_reg(dev, reg, val);274	if (regval < 0)275		return regval;276	if (is_power_reg(reg)) {277		regval = clamp_val(regval, 0, 0xffffff);278		regbuf[0] = regval >> 16;279		regbuf[1] = (regval >> 8) & 0xff;280		regbuf[2] = regval;281		num_regs = 3;282	} else {283		regval = clamp_val(regval, 0, 0xfff) << 4;284		regbuf[0] = regval >> 8;285		regbuf[1] = regval & 0xff;286		num_regs = 2;287	}288	ret = regmap_bulk_write(regmap, reg, regbuf, num_regs);289	return ret < 0 ? ret : count;290}291 292static ssize_t ltc2945_history_store(struct device *dev,293				     struct device_attribute *da,294				     const char *buf, size_t count)295{296	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);297	struct ltc2945_data *data = dev_get_drvdata(dev);298	struct regmap *regmap = data->regmap;299	u8 reg = attr->index;300	int num_regs = is_power_reg(reg) ? 3 : 2;301	u8 buf_min[3] = { 0xff, 0xff, 0xff };302	u8 buf_max[3] = { 0, 0, 0 };303	unsigned long val;304	int ret;305 306	ret = kstrtoul(buf, 10, &val);307	if (ret)308		return ret;309	if (val != 1)310		return -EINVAL;311 312	ret = regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE,313				 CONTROL_TEST_MODE);314 315	/* Reset minimum */316	ret = regmap_bulk_write(regmap, reg, buf_min, num_regs);317	if (ret)318		return ret;319 320	switch (reg) {321	case LTC2945_MIN_POWER_H:322		reg = LTC2945_MAX_POWER_H;323		break;324	case LTC2945_MIN_SENSE_H:325		reg = LTC2945_MAX_SENSE_H;326		break;327	case LTC2945_MIN_VIN_H:328		reg = LTC2945_MAX_VIN_H;329		break;330	case LTC2945_MIN_ADIN_H:331		reg = LTC2945_MAX_ADIN_H;332		break;333	default:334		WARN_ONCE(1, "Bad register: 0x%x\n", reg);335		return -EINVAL;336	}337	/* Reset maximum */338	ret = regmap_bulk_write(regmap, reg, buf_max, num_regs);339 340	/* Try resetting test mode even if there was an error */341	regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE, 0);342 343	return ret ? : count;344}345 346static ssize_t ltc2945_bool_show(struct device *dev,347				 struct device_attribute *da, char *buf)348{349	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);350	struct ltc2945_data *data = dev_get_drvdata(dev);351	struct regmap *regmap = data->regmap;352	unsigned int fault;353	int ret;354 355	ret = regmap_read(regmap, LTC2945_FAULT, &fault);356	if (ret < 0)357		return ret;358 359	fault &= attr->index;360	if (fault)		/* Clear reported faults in chip register */361		regmap_update_bits(regmap, LTC2945_FAULT, attr->index, 0);362 363	return sysfs_emit(buf, "%d\n", !!fault);364}365 366/* Input voltages */367 368static SENSOR_DEVICE_ATTR_RO(in1_input, ltc2945_value, LTC2945_VIN_H);369static SENSOR_DEVICE_ATTR_RW(in1_min, ltc2945_value, LTC2945_MIN_VIN_THRES_H);370static SENSOR_DEVICE_ATTR_RW(in1_max, ltc2945_value, LTC2945_MAX_VIN_THRES_H);371static SENSOR_DEVICE_ATTR_RO(in1_lowest, ltc2945_value, LTC2945_MIN_VIN_H);372static SENSOR_DEVICE_ATTR_RO(in1_highest, ltc2945_value, LTC2945_MAX_VIN_H);373static SENSOR_DEVICE_ATTR_WO(in1_reset_history, ltc2945_history,374			     LTC2945_MIN_VIN_H);375 376static SENSOR_DEVICE_ATTR_RO(in2_input, ltc2945_value, LTC2945_ADIN_H);377static SENSOR_DEVICE_ATTR_RW(in2_min, ltc2945_value, LTC2945_MIN_ADIN_THRES_H);378static SENSOR_DEVICE_ATTR_RW(in2_max, ltc2945_value, LTC2945_MAX_ADIN_THRES_H);379static SENSOR_DEVICE_ATTR_RO(in2_lowest, ltc2945_value, LTC2945_MIN_ADIN_H);380static SENSOR_DEVICE_ATTR_RO(in2_highest, ltc2945_value, LTC2945_MAX_ADIN_H);381static SENSOR_DEVICE_ATTR_WO(in2_reset_history, ltc2945_history,382			     LTC2945_MIN_ADIN_H);383 384/* Voltage alarms */385 386static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ltc2945_bool, FAULT_VIN_UV);387static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ltc2945_bool, FAULT_VIN_OV);388static SENSOR_DEVICE_ATTR_RO(in2_min_alarm, ltc2945_bool, FAULT_ADIN_UV);389static SENSOR_DEVICE_ATTR_RO(in2_max_alarm, ltc2945_bool, FAULT_ADIN_OV);390 391/* Currents (via sense resistor) */392 393static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc2945_value, LTC2945_SENSE_H);394static SENSOR_DEVICE_ATTR_RW(curr1_min, ltc2945_value,395			     LTC2945_MIN_SENSE_THRES_H);396static SENSOR_DEVICE_ATTR_RW(curr1_max, ltc2945_value,397			     LTC2945_MAX_SENSE_THRES_H);398static SENSOR_DEVICE_ATTR_RO(curr1_lowest, ltc2945_value, LTC2945_MIN_SENSE_H);399static SENSOR_DEVICE_ATTR_RO(curr1_highest, ltc2945_value,400			     LTC2945_MAX_SENSE_H);401static SENSOR_DEVICE_ATTR_WO(curr1_reset_history, ltc2945_history,402			     LTC2945_MIN_SENSE_H);403 404/* Current alarms */405 406static SENSOR_DEVICE_ATTR_RO(curr1_min_alarm, ltc2945_bool, FAULT_SENSE_UV);407static SENSOR_DEVICE_ATTR_RO(curr1_max_alarm, ltc2945_bool, FAULT_SENSE_OV);408 409/* Power */410 411static SENSOR_DEVICE_ATTR_RO(power1_input, ltc2945_value, LTC2945_POWER_H);412static SENSOR_DEVICE_ATTR_RW(power1_min, ltc2945_value,413			     LTC2945_MIN_POWER_THRES_H);414static SENSOR_DEVICE_ATTR_RW(power1_max, ltc2945_value,415			     LTC2945_MAX_POWER_THRES_H);416static SENSOR_DEVICE_ATTR_RO(power1_input_lowest, ltc2945_value,417			     LTC2945_MIN_POWER_H);418static SENSOR_DEVICE_ATTR_RO(power1_input_highest, ltc2945_value,419			     LTC2945_MAX_POWER_H);420static SENSOR_DEVICE_ATTR_WO(power1_reset_history, ltc2945_history,421			     LTC2945_MIN_POWER_H);422 423/* Power alarms */424 425static SENSOR_DEVICE_ATTR_RO(power1_min_alarm, ltc2945_bool, FAULT_POWER_UV);426static SENSOR_DEVICE_ATTR_RO(power1_max_alarm, ltc2945_bool, FAULT_POWER_OV);427 428static struct attribute *ltc2945_attrs[] = {429	&sensor_dev_attr_in1_input.dev_attr.attr,430	&sensor_dev_attr_in1_min.dev_attr.attr,431	&sensor_dev_attr_in1_max.dev_attr.attr,432	&sensor_dev_attr_in1_lowest.dev_attr.attr,433	&sensor_dev_attr_in1_highest.dev_attr.attr,434	&sensor_dev_attr_in1_reset_history.dev_attr.attr,435	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,436	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,437 438	&sensor_dev_attr_in2_input.dev_attr.attr,439	&sensor_dev_attr_in2_min.dev_attr.attr,440	&sensor_dev_attr_in2_max.dev_attr.attr,441	&sensor_dev_attr_in2_lowest.dev_attr.attr,442	&sensor_dev_attr_in2_highest.dev_attr.attr,443	&sensor_dev_attr_in2_reset_history.dev_attr.attr,444	&sensor_dev_attr_in2_min_alarm.dev_attr.attr,445	&sensor_dev_attr_in2_max_alarm.dev_attr.attr,446 447	&sensor_dev_attr_curr1_input.dev_attr.attr,448	&sensor_dev_attr_curr1_min.dev_attr.attr,449	&sensor_dev_attr_curr1_max.dev_attr.attr,450	&sensor_dev_attr_curr1_lowest.dev_attr.attr,451	&sensor_dev_attr_curr1_highest.dev_attr.attr,452	&sensor_dev_attr_curr1_reset_history.dev_attr.attr,453	&sensor_dev_attr_curr1_min_alarm.dev_attr.attr,454	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,455 456	&sensor_dev_attr_power1_input.dev_attr.attr,457	&sensor_dev_attr_power1_min.dev_attr.attr,458	&sensor_dev_attr_power1_max.dev_attr.attr,459	&sensor_dev_attr_power1_input_lowest.dev_attr.attr,460	&sensor_dev_attr_power1_input_highest.dev_attr.attr,461	&sensor_dev_attr_power1_reset_history.dev_attr.attr,462	&sensor_dev_attr_power1_min_alarm.dev_attr.attr,463	&sensor_dev_attr_power1_max_alarm.dev_attr.attr,464 465	NULL,466};467ATTRIBUTE_GROUPS(ltc2945);468 469static const struct regmap_config ltc2945_regmap_config = {470	.reg_bits = 8,471	.val_bits = 8,472	.max_register = LTC2945_MIN_ADIN_THRES_L,473};474 475static int ltc2945_probe(struct i2c_client *client)476{477	struct device *dev = &client->dev;478	struct device *hwmon_dev;479	struct regmap *regmap;480	struct ltc2945_data *data;481 482	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);483	if (!data)484		return -ENOMEM;485	dev_set_drvdata(dev, data);486 487	regmap = devm_regmap_init_i2c(client, &ltc2945_regmap_config);488	if (IS_ERR(regmap)) {489		dev_err(dev, "failed to allocate register map\n");490		return PTR_ERR(regmap);491	}492 493	data->regmap = regmap;494	if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",495				     &data->shunt_resistor))496		data->shunt_resistor = 1000;497 498	if (data->shunt_resistor == 0)499		return -EINVAL;500 501	/* Clear faults */502	regmap_write(regmap, LTC2945_FAULT, 0x00);503 504	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,505							   data,506							   ltc2945_groups);507	return PTR_ERR_OR_ZERO(hwmon_dev);508}509 510static const struct i2c_device_id ltc2945_id[] = {511	{"ltc2945"},512	{ }513};514 515MODULE_DEVICE_TABLE(i2c, ltc2945_id);516 517static struct i2c_driver ltc2945_driver = {518	.driver = {519		.name = "ltc2945",520		.of_match_table = of_match_ptr(ltc2945_of_match),521	},522	.probe = ltc2945_probe,523	.id_table = ltc2945_id,524};525 526module_i2c_driver(ltc2945_driver);527 528MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");529MODULE_DESCRIPTION("LTC2945 driver");530MODULE_LICENSE("GPL");531