xref: /linux/drivers/hwmon/tsc1641.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1*0c7d530aSIgor Reznichenko // SPDX-License-Identifier: GPL-2.0
2*0c7d530aSIgor Reznichenko /*
3*0c7d530aSIgor Reznichenko  * Driver for ST Microelectronics TSC1641 I2C power monitor
4*0c7d530aSIgor Reznichenko  *
5*0c7d530aSIgor Reznichenko  * 60 V, 16-bit high-precision power monitor with I2C and MIPI I3C interface
6*0c7d530aSIgor Reznichenko  * Datasheet: https://www.st.com/resource/en/datasheet/tsc1641.pdf
7*0c7d530aSIgor Reznichenko  *
8*0c7d530aSIgor Reznichenko  * Copyright (C) 2025 Igor Reznichenko <igor@reznichenko.net>
9*0c7d530aSIgor Reznichenko  */
10*0c7d530aSIgor Reznichenko 
11*0c7d530aSIgor Reznichenko #include <linux/bitfield.h>
12*0c7d530aSIgor Reznichenko #include <linux/bits.h>
13*0c7d530aSIgor Reznichenko #include <linux/device.h>
14*0c7d530aSIgor Reznichenko #include <linux/err.h>
15*0c7d530aSIgor Reznichenko #include <linux/hwmon.h>
16*0c7d530aSIgor Reznichenko #include <linux/i2c.h>
17*0c7d530aSIgor Reznichenko #include <linux/module.h>
18*0c7d530aSIgor Reznichenko #include <linux/regmap.h>
19*0c7d530aSIgor Reznichenko #include <linux/sysfs.h>
20*0c7d530aSIgor Reznichenko #include <linux/util_macros.h>
21*0c7d530aSIgor Reznichenko 
22*0c7d530aSIgor Reznichenko /* I2C registers */
23*0c7d530aSIgor Reznichenko #define TSC1641_CONFIG		0x00
24*0c7d530aSIgor Reznichenko #define TSC1641_SHUNT_VOLTAGE	0x01
25*0c7d530aSIgor Reznichenko #define TSC1641_LOAD_VOLTAGE	0x02
26*0c7d530aSIgor Reznichenko #define TSC1641_POWER		0x03
27*0c7d530aSIgor Reznichenko #define TSC1641_CURRENT		0x04
28*0c7d530aSIgor Reznichenko #define TSC1641_TEMP		0x05
29*0c7d530aSIgor Reznichenko #define TSC1641_MASK		0x06
30*0c7d530aSIgor Reznichenko #define TSC1641_FLAG		0x07
31*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT		0x08 /* Shunt resistance */
32*0c7d530aSIgor Reznichenko #define TSC1641_SOL		0x09
33*0c7d530aSIgor Reznichenko #define TSC1641_SUL		0x0A
34*0c7d530aSIgor Reznichenko #define TSC1641_LOL		0x0B
35*0c7d530aSIgor Reznichenko #define TSC1641_LUL		0x0C
36*0c7d530aSIgor Reznichenko #define TSC1641_POL		0x0D
37*0c7d530aSIgor Reznichenko #define TSC1641_TOL		0x0E
38*0c7d530aSIgor Reznichenko #define TSC1641_MANUF_ID	0xFE /* 0x0006 */
39*0c7d530aSIgor Reznichenko #define TSC1641_DIE_ID		0xFF /* 0x1000 */
40*0c7d530aSIgor Reznichenko #define TSC1641_MAX_REG		0xFF
41*0c7d530aSIgor Reznichenko 
42*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_DEFAULT	1000   /* 1mOhm */
43*0c7d530aSIgor Reznichenko #define TSC1641_CONFIG_DEFAULT	0x003F /* Default mode and temperature sensor */
44*0c7d530aSIgor Reznichenko #define TSC1641_MASK_DEFAULT	0xFC00 /* Unmask all alerts */
45*0c7d530aSIgor Reznichenko 
46*0c7d530aSIgor Reznichenko /* Bit mask for conversion time in the configuration register */
47*0c7d530aSIgor Reznichenko #define TSC1641_CONV_TIME_MASK	GENMASK(7, 4)
48*0c7d530aSIgor Reznichenko 
49*0c7d530aSIgor Reznichenko #define TSC1641_CONV_TIME_DEFAULT	1024
50*0c7d530aSIgor Reznichenko #define TSC1641_MIN_UPDATE_INTERVAL	1024
51*0c7d530aSIgor Reznichenko 
52*0c7d530aSIgor Reznichenko /* LSB value of different registers */
53*0c7d530aSIgor Reznichenko #define TSC1641_VLOAD_LSB_MVOLT		2
54*0c7d530aSIgor Reznichenko #define TSC1641_POWER_LSB_UWATT		25000
55*0c7d530aSIgor Reznichenko #define TSC1641_VSHUNT_LSB_NVOLT	2500 /* Use nanovolts to make it integer */
56*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_LSB_UOHM		10
57*0c7d530aSIgor Reznichenko #define TSC1641_TEMP_LSB_MDEGC		500
58*0c7d530aSIgor Reznichenko 
59*0c7d530aSIgor Reznichenko /* Limits based on datasheet */
60*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_MIN_UOHM		100
61*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_MAX_UOHM		655350
62*0c7d530aSIgor Reznichenko #define TSC1641_CURR_ABS_MAX_MAMP	819200 /* Max current at 100uOhm*/
63*0c7d530aSIgor Reznichenko 
64*0c7d530aSIgor Reznichenko #define TSC1641_ALERT_POL_MASK		BIT(1)
65*0c7d530aSIgor Reznichenko #define TSC1641_ALERT_LATCH_EN_MASK	BIT(0)
66*0c7d530aSIgor Reznichenko 
67*0c7d530aSIgor Reznichenko /* Flags indicating alerts in TSC1641_FLAG register*/
68*0c7d530aSIgor Reznichenko #define TSC1641_SAT_FLAG		BIT(13)
69*0c7d530aSIgor Reznichenko #define TSC1641_SHUNT_OV_FLAG		BIT(6)
70*0c7d530aSIgor Reznichenko #define TSC1641_SHUNT_UV_FLAG		BIT(5)
71*0c7d530aSIgor Reznichenko #define TSC1641_LOAD_OV_FLAG		BIT(4)
72*0c7d530aSIgor Reznichenko #define TSC1641_LOAD_UV_FLAG		BIT(3)
73*0c7d530aSIgor Reznichenko #define TSC1641_POWER_OVER_FLAG		BIT(2)
74*0c7d530aSIgor Reznichenko #define TSC1641_TEMP_OVER_FLAG		BIT(1)
75*0c7d530aSIgor Reznichenko 
76*0c7d530aSIgor Reznichenko static bool tsc1641_writeable_reg(struct device *dev, unsigned int reg)
77*0c7d530aSIgor Reznichenko {
78*0c7d530aSIgor Reznichenko 	switch (reg) {
79*0c7d530aSIgor Reznichenko 	case TSC1641_CONFIG:
80*0c7d530aSIgor Reznichenko 	case TSC1641_MASK:
81*0c7d530aSIgor Reznichenko 	case TSC1641_RSHUNT:
82*0c7d530aSIgor Reznichenko 	case TSC1641_SOL:
83*0c7d530aSIgor Reznichenko 	case TSC1641_SUL:
84*0c7d530aSIgor Reznichenko 	case TSC1641_LOL:
85*0c7d530aSIgor Reznichenko 	case TSC1641_LUL:
86*0c7d530aSIgor Reznichenko 	case TSC1641_POL:
87*0c7d530aSIgor Reznichenko 	case TSC1641_TOL:
88*0c7d530aSIgor Reznichenko 		return true;
89*0c7d530aSIgor Reznichenko 	default:
90*0c7d530aSIgor Reznichenko 		return false;
91*0c7d530aSIgor Reznichenko 	}
92*0c7d530aSIgor Reznichenko }
93*0c7d530aSIgor Reznichenko 
94*0c7d530aSIgor Reznichenko static bool tsc1641_volatile_reg(struct device *dev, unsigned int reg)
95*0c7d530aSIgor Reznichenko {
96*0c7d530aSIgor Reznichenko 	switch (reg) {
97*0c7d530aSIgor Reznichenko 	case TSC1641_SHUNT_VOLTAGE:
98*0c7d530aSIgor Reznichenko 	case TSC1641_LOAD_VOLTAGE:
99*0c7d530aSIgor Reznichenko 	case TSC1641_POWER:
100*0c7d530aSIgor Reznichenko 	case TSC1641_CURRENT:
101*0c7d530aSIgor Reznichenko 	case TSC1641_TEMP:
102*0c7d530aSIgor Reznichenko 	case TSC1641_FLAG:
103*0c7d530aSIgor Reznichenko 	case TSC1641_MANUF_ID:
104*0c7d530aSIgor Reznichenko 	case TSC1641_DIE_ID:
105*0c7d530aSIgor Reznichenko 		return true;
106*0c7d530aSIgor Reznichenko 	default:
107*0c7d530aSIgor Reznichenko 		return false;
108*0c7d530aSIgor Reznichenko 	}
109*0c7d530aSIgor Reznichenko }
110*0c7d530aSIgor Reznichenko 
111*0c7d530aSIgor Reznichenko static const struct regmap_config tsc1641_regmap_config = {
112*0c7d530aSIgor Reznichenko 	.reg_bits = 8,
113*0c7d530aSIgor Reznichenko 	.val_bits = 16,
114*0c7d530aSIgor Reznichenko 	.use_single_write = true,
115*0c7d530aSIgor Reznichenko 	.use_single_read = true,
116*0c7d530aSIgor Reznichenko 	.max_register = TSC1641_MAX_REG,
117*0c7d530aSIgor Reznichenko 	.cache_type = REGCACHE_MAPLE,
118*0c7d530aSIgor Reznichenko 	.volatile_reg = tsc1641_volatile_reg,
119*0c7d530aSIgor Reznichenko 	.writeable_reg = tsc1641_writeable_reg,
120*0c7d530aSIgor Reznichenko };
121*0c7d530aSIgor Reznichenko 
122*0c7d530aSIgor Reznichenko struct tsc1641_data {
123*0c7d530aSIgor Reznichenko 	long rshunt_uohm;
124*0c7d530aSIgor Reznichenko 	long current_lsb_ua;
125*0c7d530aSIgor Reznichenko 	struct regmap *regmap;
126*0c7d530aSIgor Reznichenko };
127*0c7d530aSIgor Reznichenko 
128*0c7d530aSIgor Reznichenko /*
129*0c7d530aSIgor Reznichenko  * Upper limit due to chip 16-bit shunt register, lower limit to
130*0c7d530aSIgor Reznichenko  * prevent current and power registers overflow
131*0c7d530aSIgor Reznichenko  */
132*0c7d530aSIgor Reznichenko static inline int tsc1641_validate_shunt(u32 val)
133*0c7d530aSIgor Reznichenko {
134*0c7d530aSIgor Reznichenko 	if (val < TSC1641_RSHUNT_MIN_UOHM || val > TSC1641_RSHUNT_MAX_UOHM)
135*0c7d530aSIgor Reznichenko 		return -EINVAL;
136*0c7d530aSIgor Reznichenko 	return 0;
137*0c7d530aSIgor Reznichenko }
138*0c7d530aSIgor Reznichenko 
139*0c7d530aSIgor Reznichenko static int tsc1641_set_shunt(struct tsc1641_data *data, u32 val)
140*0c7d530aSIgor Reznichenko {
141*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
142*0c7d530aSIgor Reznichenko 	long rshunt_reg;
143*0c7d530aSIgor Reznichenko 
144*0c7d530aSIgor Reznichenko 	/* RSHUNT register LSB is 10uOhm so need to divide further */
145*0c7d530aSIgor Reznichenko 	rshunt_reg = DIV_ROUND_CLOSEST(val, TSC1641_RSHUNT_LSB_UOHM);
146*0c7d530aSIgor Reznichenko 	/*
147*0c7d530aSIgor Reznichenko 	 * Clamp value to the nearest multiple of TSC1641_RSHUNT_LSB_UOHM
148*0c7d530aSIgor Reznichenko 	 * in case shunt value provided was not a multiple
149*0c7d530aSIgor Reznichenko 	 */
150*0c7d530aSIgor Reznichenko 	data->rshunt_uohm = rshunt_reg * TSC1641_RSHUNT_LSB_UOHM;
151*0c7d530aSIgor Reznichenko 	data->current_lsb_ua = DIV_ROUND_CLOSEST(TSC1641_VSHUNT_LSB_NVOLT * 1000,
152*0c7d530aSIgor Reznichenko 						 data->rshunt_uohm);
153*0c7d530aSIgor Reznichenko 
154*0c7d530aSIgor Reznichenko 	return regmap_write(regmap, TSC1641_RSHUNT, rshunt_reg);
155*0c7d530aSIgor Reznichenko }
156*0c7d530aSIgor Reznichenko 
157*0c7d530aSIgor Reznichenko /*
158*0c7d530aSIgor Reznichenko  * Conversion times in uS, value in CONFIG[CT3:CT0] corresponds to index in this array
159*0c7d530aSIgor Reznichenko  * See "Table 14. CT3 to CT0: conversion time" in:
160*0c7d530aSIgor Reznichenko  * https://www.st.com/resource/en/datasheet/tsc1641.pdf
161*0c7d530aSIgor Reznichenko  */
162*0c7d530aSIgor Reznichenko static const int tsc1641_conv_times[] = { 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };
163*0c7d530aSIgor Reznichenko 
164*0c7d530aSIgor Reznichenko static int tsc1641_reg_to_upd_interval(u16 config)
165*0c7d530aSIgor Reznichenko {
166*0c7d530aSIgor Reznichenko 	int idx = FIELD_GET(TSC1641_CONV_TIME_MASK, config);
167*0c7d530aSIgor Reznichenko 
168*0c7d530aSIgor Reznichenko 	idx = clamp_val(idx, 0, ARRAY_SIZE(tsc1641_conv_times) - 1);
169*0c7d530aSIgor Reznichenko 	int conv_time = tsc1641_conv_times[idx];
170*0c7d530aSIgor Reznichenko 
171*0c7d530aSIgor Reznichenko 	/* Don't support sub-millisecond update interval as it's not supported in hwmon */
172*0c7d530aSIgor Reznichenko 	conv_time = max(conv_time, TSC1641_MIN_UPDATE_INTERVAL);
173*0c7d530aSIgor Reznichenko 	/* Return nearest value in milliseconds */
174*0c7d530aSIgor Reznichenko 	return DIV_ROUND_CLOSEST(conv_time, 1000);
175*0c7d530aSIgor Reznichenko }
176*0c7d530aSIgor Reznichenko 
177*0c7d530aSIgor Reznichenko static u16 tsc1641_upd_interval_to_reg(long interval)
178*0c7d530aSIgor Reznichenko {
179*0c7d530aSIgor Reznichenko 	/* Supported interval is 1ms - 33ms */
180*0c7d530aSIgor Reznichenko 	interval = clamp_val(interval, 1, 33);
181*0c7d530aSIgor Reznichenko 
182*0c7d530aSIgor Reznichenko 	int conv = interval * 1000;
183*0c7d530aSIgor Reznichenko 	int conv_bits = find_closest(conv, tsc1641_conv_times,
184*0c7d530aSIgor Reznichenko 				     ARRAY_SIZE(tsc1641_conv_times));
185*0c7d530aSIgor Reznichenko 
186*0c7d530aSIgor Reznichenko 	return FIELD_PREP(TSC1641_CONV_TIME_MASK, conv_bits);
187*0c7d530aSIgor Reznichenko }
188*0c7d530aSIgor Reznichenko 
189*0c7d530aSIgor Reznichenko static int tsc1641_chip_write(struct device *dev, u32 attr, long val)
190*0c7d530aSIgor Reznichenko {
191*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
192*0c7d530aSIgor Reznichenko 
193*0c7d530aSIgor Reznichenko 	switch (attr) {
194*0c7d530aSIgor Reznichenko 	case hwmon_chip_update_interval:
195*0c7d530aSIgor Reznichenko 		return regmap_update_bits(data->regmap, TSC1641_CONFIG,
196*0c7d530aSIgor Reznichenko 					  TSC1641_CONV_TIME_MASK,
197*0c7d530aSIgor Reznichenko 					  tsc1641_upd_interval_to_reg(val));
198*0c7d530aSIgor Reznichenko 	default:
199*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
200*0c7d530aSIgor Reznichenko 	}
201*0c7d530aSIgor Reznichenko }
202*0c7d530aSIgor Reznichenko 
203*0c7d530aSIgor Reznichenko static int tsc1641_chip_read(struct device *dev, u32 attr, long *val)
204*0c7d530aSIgor Reznichenko {
205*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
206*0c7d530aSIgor Reznichenko 	u32 regval;
207*0c7d530aSIgor Reznichenko 	int ret;
208*0c7d530aSIgor Reznichenko 
209*0c7d530aSIgor Reznichenko 	switch (attr) {
210*0c7d530aSIgor Reznichenko 	case hwmon_chip_update_interval:
211*0c7d530aSIgor Reznichenko 		ret = regmap_read(data->regmap, TSC1641_CONFIG, &regval);
212*0c7d530aSIgor Reznichenko 		if (ret)
213*0c7d530aSIgor Reznichenko 			return ret;
214*0c7d530aSIgor Reznichenko 
215*0c7d530aSIgor Reznichenko 		*val = tsc1641_reg_to_upd_interval(regval);
216*0c7d530aSIgor Reznichenko 		return 0;
217*0c7d530aSIgor Reznichenko 	default:
218*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
219*0c7d530aSIgor Reznichenko 	}
220*0c7d530aSIgor Reznichenko }
221*0c7d530aSIgor Reznichenko 
222*0c7d530aSIgor Reznichenko static int tsc1641_flag_read(struct regmap *regmap, u32 flag, long *val)
223*0c7d530aSIgor Reznichenko {
224*0c7d530aSIgor Reznichenko 	unsigned int regval;
225*0c7d530aSIgor Reznichenko 	int ret;
226*0c7d530aSIgor Reznichenko 
227*0c7d530aSIgor Reznichenko 	ret = regmap_read_bypassed(regmap, TSC1641_FLAG, &regval);
228*0c7d530aSIgor Reznichenko 	if (ret)
229*0c7d530aSIgor Reznichenko 		return ret;
230*0c7d530aSIgor Reznichenko 
231*0c7d530aSIgor Reznichenko 	*val = !!(regval & flag);
232*0c7d530aSIgor Reznichenko 	return 0;
233*0c7d530aSIgor Reznichenko }
234*0c7d530aSIgor Reznichenko 
235*0c7d530aSIgor Reznichenko static int tsc1641_in_read(struct device *dev, u32 attr, long *val)
236*0c7d530aSIgor Reznichenko {
237*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
238*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
239*0c7d530aSIgor Reznichenko 	unsigned int regval;
240*0c7d530aSIgor Reznichenko 	int ret, reg;
241*0c7d530aSIgor Reznichenko 	long sat_flag;
242*0c7d530aSIgor Reznichenko 
243*0c7d530aSIgor Reznichenko 	switch (attr) {
244*0c7d530aSIgor Reznichenko 	case hwmon_in_input:
245*0c7d530aSIgor Reznichenko 		reg = TSC1641_LOAD_VOLTAGE;
246*0c7d530aSIgor Reznichenko 		break;
247*0c7d530aSIgor Reznichenko 	case hwmon_in_min:
248*0c7d530aSIgor Reznichenko 		reg = TSC1641_LUL;
249*0c7d530aSIgor Reznichenko 		break;
250*0c7d530aSIgor Reznichenko 	case hwmon_in_max:
251*0c7d530aSIgor Reznichenko 		reg = TSC1641_LOL;
252*0c7d530aSIgor Reznichenko 		break;
253*0c7d530aSIgor Reznichenko 	case hwmon_in_min_alarm:
254*0c7d530aSIgor Reznichenko 		return tsc1641_flag_read(regmap, TSC1641_LOAD_UV_FLAG, val);
255*0c7d530aSIgor Reznichenko 	case hwmon_in_max_alarm:
256*0c7d530aSIgor Reznichenko 		return tsc1641_flag_read(regmap, TSC1641_LOAD_OV_FLAG, val);
257*0c7d530aSIgor Reznichenko 	default:
258*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
259*0c7d530aSIgor Reznichenko 	}
260*0c7d530aSIgor Reznichenko 
261*0c7d530aSIgor Reznichenko 	ret = regmap_read(regmap, reg, &regval);
262*0c7d530aSIgor Reznichenko 	if (ret)
263*0c7d530aSIgor Reznichenko 		return ret;
264*0c7d530aSIgor Reznichenko 
265*0c7d530aSIgor Reznichenko 	/* Check if load voltage is out of range */
266*0c7d530aSIgor Reznichenko 	if (reg == TSC1641_LOAD_VOLTAGE) {
267*0c7d530aSIgor Reznichenko 		/* Register is 15-bit max */
268*0c7d530aSIgor Reznichenko 		if (regval & 0x8000)
269*0c7d530aSIgor Reznichenko 			return -ENODATA;
270*0c7d530aSIgor Reznichenko 
271*0c7d530aSIgor Reznichenko 		ret  = tsc1641_flag_read(regmap, TSC1641_SAT_FLAG, &sat_flag);
272*0c7d530aSIgor Reznichenko 		if (ret)
273*0c7d530aSIgor Reznichenko 			return ret;
274*0c7d530aSIgor Reznichenko 		/* Out of range conditions per datasheet */
275*0c7d530aSIgor Reznichenko 		if (sat_flag && (regval == 0x7FFF || !regval))
276*0c7d530aSIgor Reznichenko 			return -ENODATA;
277*0c7d530aSIgor Reznichenko 	}
278*0c7d530aSIgor Reznichenko 
279*0c7d530aSIgor Reznichenko 	*val = regval * TSC1641_VLOAD_LSB_MVOLT;
280*0c7d530aSIgor Reznichenko 	return 0;
281*0c7d530aSIgor Reznichenko }
282*0c7d530aSIgor Reznichenko 
283*0c7d530aSIgor Reznichenko /* Chip supports bidirectional (positive or negative) current */
284*0c7d530aSIgor Reznichenko static int tsc1641_curr_read(struct device *dev, u32 attr, long *val)
285*0c7d530aSIgor Reznichenko {
286*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
287*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
288*0c7d530aSIgor Reznichenko 	int regval;
289*0c7d530aSIgor Reznichenko 	int ret, reg;
290*0c7d530aSIgor Reznichenko 	long sat_flag;
291*0c7d530aSIgor Reznichenko 
292*0c7d530aSIgor Reznichenko 	/* Current limits are the shunt under/over voltage limits */
293*0c7d530aSIgor Reznichenko 	switch (attr) {
294*0c7d530aSIgor Reznichenko 	case hwmon_curr_input:
295*0c7d530aSIgor Reznichenko 		reg = TSC1641_CURRENT;
296*0c7d530aSIgor Reznichenko 		break;
297*0c7d530aSIgor Reznichenko 	case hwmon_curr_min:
298*0c7d530aSIgor Reznichenko 		reg = TSC1641_SUL;
299*0c7d530aSIgor Reznichenko 		break;
300*0c7d530aSIgor Reznichenko 	case hwmon_curr_max:
301*0c7d530aSIgor Reznichenko 		reg = TSC1641_SOL;
302*0c7d530aSIgor Reznichenko 		break;
303*0c7d530aSIgor Reznichenko 	case hwmon_curr_min_alarm:
304*0c7d530aSIgor Reznichenko 		return tsc1641_flag_read(regmap, TSC1641_SHUNT_UV_FLAG, val);
305*0c7d530aSIgor Reznichenko 	case hwmon_curr_max_alarm:
306*0c7d530aSIgor Reznichenko 		return tsc1641_flag_read(regmap, TSC1641_SHUNT_OV_FLAG, val);
307*0c7d530aSIgor Reznichenko 	default:
308*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
309*0c7d530aSIgor Reznichenko 	}
310*0c7d530aSIgor Reznichenko 	/*
311*0c7d530aSIgor Reznichenko 	 * Current uses shunt voltage, so check if it's out of range.
312*0c7d530aSIgor Reznichenko 	 * We report current register in sysfs to stay consistent with internal
313*0c7d530aSIgor Reznichenko 	 * power calculations which use current register values
314*0c7d530aSIgor Reznichenko 	 */
315*0c7d530aSIgor Reznichenko 	if (reg == TSC1641_CURRENT) {
316*0c7d530aSIgor Reznichenko 		ret = regmap_read(regmap, TSC1641_SHUNT_VOLTAGE, &regval);
317*0c7d530aSIgor Reznichenko 		if (ret)
318*0c7d530aSIgor Reznichenko 			return ret;
319*0c7d530aSIgor Reznichenko 
320*0c7d530aSIgor Reznichenko 		ret = tsc1641_flag_read(regmap, TSC1641_SAT_FLAG, &sat_flag);
321*0c7d530aSIgor Reznichenko 		if (ret)
322*0c7d530aSIgor Reznichenko 			return ret;
323*0c7d530aSIgor Reznichenko 
324*0c7d530aSIgor Reznichenko 		if (sat_flag && (regval == 0x7FFF || regval == 0x8000))
325*0c7d530aSIgor Reznichenko 			return -ENODATA;
326*0c7d530aSIgor Reznichenko 	}
327*0c7d530aSIgor Reznichenko 
328*0c7d530aSIgor Reznichenko 	ret = regmap_read(regmap, reg, &regval);
329*0c7d530aSIgor Reznichenko 	if (ret)
330*0c7d530aSIgor Reznichenko 		return ret;
331*0c7d530aSIgor Reznichenko 
332*0c7d530aSIgor Reznichenko 	/* Current in milliamps, signed */
333*0c7d530aSIgor Reznichenko 	*val = DIV_ROUND_CLOSEST((s16)regval * data->current_lsb_ua, 1000);
334*0c7d530aSIgor Reznichenko 	return 0;
335*0c7d530aSIgor Reznichenko }
336*0c7d530aSIgor Reznichenko 
337*0c7d530aSIgor Reznichenko static int tsc1641_power_read(struct device *dev, u32 attr, long *val)
338*0c7d530aSIgor Reznichenko {
339*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
340*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
341*0c7d530aSIgor Reznichenko 	unsigned int regval;
342*0c7d530aSIgor Reznichenko 	int ret, reg;
343*0c7d530aSIgor Reznichenko 
344*0c7d530aSIgor Reznichenko 	switch (attr) {
345*0c7d530aSIgor Reznichenko 	case hwmon_power_input:
346*0c7d530aSIgor Reznichenko 		reg = TSC1641_POWER;
347*0c7d530aSIgor Reznichenko 		break;
348*0c7d530aSIgor Reznichenko 	case hwmon_power_max:
349*0c7d530aSIgor Reznichenko 		reg = TSC1641_POL;
350*0c7d530aSIgor Reznichenko 		break;
351*0c7d530aSIgor Reznichenko 	case hwmon_power_max_alarm:
352*0c7d530aSIgor Reznichenko 		return tsc1641_flag_read(regmap, TSC1641_POWER_OVER_FLAG, val);
353*0c7d530aSIgor Reznichenko 	default:
354*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
355*0c7d530aSIgor Reznichenko 	}
356*0c7d530aSIgor Reznichenko 
357*0c7d530aSIgor Reznichenko 	ret = regmap_read(regmap, reg, &regval);
358*0c7d530aSIgor Reznichenko 	if (ret)
359*0c7d530aSIgor Reznichenko 		return ret;
360*0c7d530aSIgor Reznichenko 
361*0c7d530aSIgor Reznichenko 	*val = regval * TSC1641_POWER_LSB_UWATT;
362*0c7d530aSIgor Reznichenko 	return 0;
363*0c7d530aSIgor Reznichenko }
364*0c7d530aSIgor Reznichenko 
365*0c7d530aSIgor Reznichenko static int tsc1641_temp_read(struct device *dev, u32 attr, long *val)
366*0c7d530aSIgor Reznichenko {
367*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
368*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
369*0c7d530aSIgor Reznichenko 	unsigned int regval;
370*0c7d530aSIgor Reznichenko 	int ret, reg;
371*0c7d530aSIgor Reznichenko 
372*0c7d530aSIgor Reznichenko 	switch (attr) {
373*0c7d530aSIgor Reznichenko 	case hwmon_temp_input:
374*0c7d530aSIgor Reznichenko 		reg = TSC1641_TEMP;
375*0c7d530aSIgor Reznichenko 		break;
376*0c7d530aSIgor Reznichenko 	case hwmon_temp_max:
377*0c7d530aSIgor Reznichenko 		reg = TSC1641_TOL;
378*0c7d530aSIgor Reznichenko 		break;
379*0c7d530aSIgor Reznichenko 	case hwmon_temp_max_alarm:
380*0c7d530aSIgor Reznichenko 		return tsc1641_flag_read(regmap, TSC1641_TEMP_OVER_FLAG, val);
381*0c7d530aSIgor Reznichenko 	default:
382*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
383*0c7d530aSIgor Reznichenko 	}
384*0c7d530aSIgor Reznichenko 
385*0c7d530aSIgor Reznichenko 	ret = regmap_read(regmap, reg, &regval);
386*0c7d530aSIgor Reznichenko 	if (ret)
387*0c7d530aSIgor Reznichenko 		return ret;
388*0c7d530aSIgor Reznichenko 
389*0c7d530aSIgor Reznichenko 	/* 0x8000 means that TEMP measurement not enabled */
390*0c7d530aSIgor Reznichenko 	if (reg == TSC1641_TEMP && regval == 0x8000)
391*0c7d530aSIgor Reznichenko 		return -ENODATA;
392*0c7d530aSIgor Reznichenko 
393*0c7d530aSIgor Reznichenko 	/* Both temperature and limit registers are signed */
394*0c7d530aSIgor Reznichenko 	*val = (s16)regval * TSC1641_TEMP_LSB_MDEGC;
395*0c7d530aSIgor Reznichenko 	return 0;
396*0c7d530aSIgor Reznichenko }
397*0c7d530aSIgor Reznichenko 
398*0c7d530aSIgor Reznichenko static int tsc1641_in_write(struct device *dev, u32 attr, long val)
399*0c7d530aSIgor Reznichenko {
400*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
401*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
402*0c7d530aSIgor Reznichenko 	unsigned int regval;
403*0c7d530aSIgor Reznichenko 	int reg;
404*0c7d530aSIgor Reznichenko 
405*0c7d530aSIgor Reznichenko 	switch (attr) {
406*0c7d530aSIgor Reznichenko 	case hwmon_in_min:
407*0c7d530aSIgor Reznichenko 		reg = TSC1641_LUL;
408*0c7d530aSIgor Reznichenko 		break;
409*0c7d530aSIgor Reznichenko 	case hwmon_in_max:
410*0c7d530aSIgor Reznichenko 		reg = TSC1641_LOL;
411*0c7d530aSIgor Reznichenko 		break;
412*0c7d530aSIgor Reznichenko 	default:
413*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
414*0c7d530aSIgor Reznichenko 	}
415*0c7d530aSIgor Reznichenko 	/* Clamp to full register range */
416*0c7d530aSIgor Reznichenko 	val = clamp_val(val, 0, TSC1641_VLOAD_LSB_MVOLT * USHRT_MAX);
417*0c7d530aSIgor Reznichenko 	regval = DIV_ROUND_CLOSEST(val, TSC1641_VLOAD_LSB_MVOLT);
418*0c7d530aSIgor Reznichenko 
419*0c7d530aSIgor Reznichenko 	return regmap_write(regmap, reg, regval);
420*0c7d530aSIgor Reznichenko }
421*0c7d530aSIgor Reznichenko 
422*0c7d530aSIgor Reznichenko static int tsc1641_curr_write(struct device *dev, u32 attr, long val)
423*0c7d530aSIgor Reznichenko {
424*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
425*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
426*0c7d530aSIgor Reznichenko 	int reg, regval;
427*0c7d530aSIgor Reznichenko 
428*0c7d530aSIgor Reznichenko 	switch (attr) {
429*0c7d530aSIgor Reznichenko 	case hwmon_curr_min:
430*0c7d530aSIgor Reznichenko 		reg = TSC1641_SUL;
431*0c7d530aSIgor Reznichenko 		break;
432*0c7d530aSIgor Reznichenko 	case hwmon_curr_max:
433*0c7d530aSIgor Reznichenko 		reg = TSC1641_SOL;
434*0c7d530aSIgor Reznichenko 		break;
435*0c7d530aSIgor Reznichenko 	default:
436*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
437*0c7d530aSIgor Reznichenko 	}
438*0c7d530aSIgor Reznichenko 
439*0c7d530aSIgor Reznichenko 	/* Clamp to prevent over/underflow below */
440*0c7d530aSIgor Reznichenko 	val = clamp_val(val, -TSC1641_CURR_ABS_MAX_MAMP, TSC1641_CURR_ABS_MAX_MAMP);
441*0c7d530aSIgor Reznichenko 	/* Convert val in milliamps to register */
442*0c7d530aSIgor Reznichenko 	regval = DIV_ROUND_CLOSEST(val * 1000, data->current_lsb_ua);
443*0c7d530aSIgor Reznichenko 	/*
444*0c7d530aSIgor Reznichenko 	 * Prevent signed 16-bit overflow.
445*0c7d530aSIgor Reznichenko 	 * Integer arithmetic and shunt scaling can quantize values near 0x7FFF/0x8000,
446*0c7d530aSIgor Reznichenko 	 * so reading and writing back may not preserve the exact original register value.
447*0c7d530aSIgor Reznichenko 	 */
448*0c7d530aSIgor Reznichenko 	regval = clamp_val(regval, SHRT_MIN, SHRT_MAX);
449*0c7d530aSIgor Reznichenko 	/* SUL and SOL registers are signed */
450*0c7d530aSIgor Reznichenko 	return regmap_write(regmap, reg, regval & 0xFFFF);
451*0c7d530aSIgor Reznichenko }
452*0c7d530aSIgor Reznichenko 
453*0c7d530aSIgor Reznichenko static int tsc1641_power_write(struct device *dev, u32 attr, long val)
454*0c7d530aSIgor Reznichenko {
455*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
456*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
457*0c7d530aSIgor Reznichenko 	unsigned int regval;
458*0c7d530aSIgor Reznichenko 
459*0c7d530aSIgor Reznichenko 	switch (attr) {
460*0c7d530aSIgor Reznichenko 	case hwmon_power_max:
461*0c7d530aSIgor Reznichenko 		/* Clamp to full register range */
462*0c7d530aSIgor Reznichenko 		val = clamp_val(val, 0, TSC1641_POWER_LSB_UWATT * USHRT_MAX);
463*0c7d530aSIgor Reznichenko 		regval = DIV_ROUND_CLOSEST(val, TSC1641_POWER_LSB_UWATT);
464*0c7d530aSIgor Reznichenko 		return regmap_write(regmap, TSC1641_POL, regval);
465*0c7d530aSIgor Reznichenko 	default:
466*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
467*0c7d530aSIgor Reznichenko 	}
468*0c7d530aSIgor Reznichenko }
469*0c7d530aSIgor Reznichenko 
470*0c7d530aSIgor Reznichenko static int tsc1641_temp_write(struct device *dev, u32 attr, long val)
471*0c7d530aSIgor Reznichenko {
472*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
473*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
474*0c7d530aSIgor Reznichenko 	int regval;
475*0c7d530aSIgor Reznichenko 
476*0c7d530aSIgor Reznichenko 	switch (attr) {
477*0c7d530aSIgor Reznichenko 	case hwmon_temp_max:
478*0c7d530aSIgor Reznichenko 		/* Clamp to full register range */
479*0c7d530aSIgor Reznichenko 		val = clamp_val(val, TSC1641_TEMP_LSB_MDEGC * SHRT_MIN,
480*0c7d530aSIgor Reznichenko 				TSC1641_TEMP_LSB_MDEGC * SHRT_MAX);
481*0c7d530aSIgor Reznichenko 		regval = DIV_ROUND_CLOSEST(val, TSC1641_TEMP_LSB_MDEGC);
482*0c7d530aSIgor Reznichenko 		/* TOL register is signed */
483*0c7d530aSIgor Reznichenko 		return regmap_write(regmap, TSC1641_TOL, regval & 0xFFFF);
484*0c7d530aSIgor Reznichenko 	default:
485*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
486*0c7d530aSIgor Reznichenko 	}
487*0c7d530aSIgor Reznichenko }
488*0c7d530aSIgor Reznichenko 
489*0c7d530aSIgor Reznichenko static umode_t tsc1641_is_visible(const void *data, enum hwmon_sensor_types type,
490*0c7d530aSIgor Reznichenko 				  u32 attr, int channel)
491*0c7d530aSIgor Reznichenko {
492*0c7d530aSIgor Reznichenko 	switch (type) {
493*0c7d530aSIgor Reznichenko 	case hwmon_chip:
494*0c7d530aSIgor Reznichenko 		switch (attr) {
495*0c7d530aSIgor Reznichenko 		case hwmon_chip_update_interval:
496*0c7d530aSIgor Reznichenko 			return 0644;
497*0c7d530aSIgor Reznichenko 		default:
498*0c7d530aSIgor Reznichenko 			break;
499*0c7d530aSIgor Reznichenko 		}
500*0c7d530aSIgor Reznichenko 		break;
501*0c7d530aSIgor Reznichenko 	case hwmon_in:
502*0c7d530aSIgor Reznichenko 		switch (attr) {
503*0c7d530aSIgor Reznichenko 		case hwmon_in_input:
504*0c7d530aSIgor Reznichenko 			return 0444;
505*0c7d530aSIgor Reznichenko 		case hwmon_in_min:
506*0c7d530aSIgor Reznichenko 		case hwmon_in_max:
507*0c7d530aSIgor Reznichenko 			return 0644;
508*0c7d530aSIgor Reznichenko 		case hwmon_in_min_alarm:
509*0c7d530aSIgor Reznichenko 		case hwmon_in_max_alarm:
510*0c7d530aSIgor Reznichenko 			return 0444;
511*0c7d530aSIgor Reznichenko 		default:
512*0c7d530aSIgor Reznichenko 			break;
513*0c7d530aSIgor Reznichenko 		}
514*0c7d530aSIgor Reznichenko 		break;
515*0c7d530aSIgor Reznichenko 	case hwmon_curr:
516*0c7d530aSIgor Reznichenko 		switch (attr) {
517*0c7d530aSIgor Reznichenko 		case hwmon_curr_input:
518*0c7d530aSIgor Reznichenko 			return 0444;
519*0c7d530aSIgor Reznichenko 		case hwmon_curr_min:
520*0c7d530aSIgor Reznichenko 		case hwmon_curr_max:
521*0c7d530aSIgor Reznichenko 			return 0644;
522*0c7d530aSIgor Reznichenko 		case hwmon_curr_min_alarm:
523*0c7d530aSIgor Reznichenko 		case hwmon_curr_max_alarm:
524*0c7d530aSIgor Reznichenko 			return 0444;
525*0c7d530aSIgor Reznichenko 		default:
526*0c7d530aSIgor Reznichenko 			break;
527*0c7d530aSIgor Reznichenko 		}
528*0c7d530aSIgor Reznichenko 		break;
529*0c7d530aSIgor Reznichenko 	case hwmon_power:
530*0c7d530aSIgor Reznichenko 		switch (attr) {
531*0c7d530aSIgor Reznichenko 		case hwmon_power_input:
532*0c7d530aSIgor Reznichenko 			return 0444;
533*0c7d530aSIgor Reznichenko 		case hwmon_power_max:
534*0c7d530aSIgor Reznichenko 			return 0644;
535*0c7d530aSIgor Reznichenko 		case hwmon_power_max_alarm:
536*0c7d530aSIgor Reznichenko 			return 0444;
537*0c7d530aSIgor Reznichenko 		default:
538*0c7d530aSIgor Reznichenko 			break;
539*0c7d530aSIgor Reznichenko 		}
540*0c7d530aSIgor Reznichenko 		break;
541*0c7d530aSIgor Reznichenko 	case hwmon_temp:
542*0c7d530aSIgor Reznichenko 		switch (attr) {
543*0c7d530aSIgor Reznichenko 		case hwmon_temp_input:
544*0c7d530aSIgor Reznichenko 			return 0444;
545*0c7d530aSIgor Reznichenko 		case hwmon_temp_max:
546*0c7d530aSIgor Reznichenko 			return 0644;
547*0c7d530aSIgor Reznichenko 		case hwmon_temp_max_alarm:
548*0c7d530aSIgor Reznichenko 			return 0444;
549*0c7d530aSIgor Reznichenko 		default:
550*0c7d530aSIgor Reznichenko 			break;
551*0c7d530aSIgor Reznichenko 		}
552*0c7d530aSIgor Reznichenko 		break;
553*0c7d530aSIgor Reznichenko 	default:
554*0c7d530aSIgor Reznichenko 		break;
555*0c7d530aSIgor Reznichenko 	}
556*0c7d530aSIgor Reznichenko 	return 0;
557*0c7d530aSIgor Reznichenko }
558*0c7d530aSIgor Reznichenko 
559*0c7d530aSIgor Reznichenko static int tsc1641_read(struct device *dev, enum hwmon_sensor_types type,
560*0c7d530aSIgor Reznichenko 			u32 attr, int channel, long *val)
561*0c7d530aSIgor Reznichenko {
562*0c7d530aSIgor Reznichenko 	switch (type) {
563*0c7d530aSIgor Reznichenko 	case hwmon_chip:
564*0c7d530aSIgor Reznichenko 		return tsc1641_chip_read(dev, attr, val);
565*0c7d530aSIgor Reznichenko 	case hwmon_in:
566*0c7d530aSIgor Reznichenko 		return tsc1641_in_read(dev, attr, val);
567*0c7d530aSIgor Reznichenko 	case hwmon_curr:
568*0c7d530aSIgor Reznichenko 		return tsc1641_curr_read(dev, attr, val);
569*0c7d530aSIgor Reznichenko 	case hwmon_power:
570*0c7d530aSIgor Reznichenko 		return tsc1641_power_read(dev, attr, val);
571*0c7d530aSIgor Reznichenko 	case hwmon_temp:
572*0c7d530aSIgor Reznichenko 		return tsc1641_temp_read(dev, attr, val);
573*0c7d530aSIgor Reznichenko 	default:
574*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
575*0c7d530aSIgor Reznichenko 	}
576*0c7d530aSIgor Reznichenko }
577*0c7d530aSIgor Reznichenko 
578*0c7d530aSIgor Reznichenko static int tsc1641_write(struct device *dev, enum hwmon_sensor_types type,
579*0c7d530aSIgor Reznichenko 			 u32 attr, int channel, long val)
580*0c7d530aSIgor Reznichenko {
581*0c7d530aSIgor Reznichenko 	switch (type) {
582*0c7d530aSIgor Reznichenko 	case hwmon_chip:
583*0c7d530aSIgor Reznichenko 		return tsc1641_chip_write(dev, attr, val);
584*0c7d530aSIgor Reznichenko 	case hwmon_in:
585*0c7d530aSIgor Reznichenko 		return tsc1641_in_write(dev, attr, val);
586*0c7d530aSIgor Reznichenko 	case hwmon_curr:
587*0c7d530aSIgor Reznichenko 		return tsc1641_curr_write(dev, attr, val);
588*0c7d530aSIgor Reznichenko 	case hwmon_power:
589*0c7d530aSIgor Reznichenko 		return tsc1641_power_write(dev, attr, val);
590*0c7d530aSIgor Reznichenko 	case hwmon_temp:
591*0c7d530aSIgor Reznichenko 		return tsc1641_temp_write(dev, attr, val);
592*0c7d530aSIgor Reznichenko 	default:
593*0c7d530aSIgor Reznichenko 		return -EOPNOTSUPP;
594*0c7d530aSIgor Reznichenko 	}
595*0c7d530aSIgor Reznichenko }
596*0c7d530aSIgor Reznichenko 
597*0c7d530aSIgor Reznichenko static const struct hwmon_channel_info * const tsc1641_info[] = {
598*0c7d530aSIgor Reznichenko 	HWMON_CHANNEL_INFO(chip,
599*0c7d530aSIgor Reznichenko 			   HWMON_C_UPDATE_INTERVAL),
600*0c7d530aSIgor Reznichenko 	HWMON_CHANNEL_INFO(in,
601*0c7d530aSIgor Reznichenko 			   HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_MAX_ALARM |
602*0c7d530aSIgor Reznichenko 			   HWMON_I_MIN | HWMON_I_MIN_ALARM),
603*0c7d530aSIgor Reznichenko 	HWMON_CHANNEL_INFO(curr,
604*0c7d530aSIgor Reznichenko 			   HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_MAX_ALARM |
605*0c7d530aSIgor Reznichenko 			   HWMON_C_MIN | HWMON_C_MIN_ALARM),
606*0c7d530aSIgor Reznichenko 	HWMON_CHANNEL_INFO(power,
607*0c7d530aSIgor Reznichenko 			   HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM),
608*0c7d530aSIgor Reznichenko 	HWMON_CHANNEL_INFO(temp,
609*0c7d530aSIgor Reznichenko 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM),
610*0c7d530aSIgor Reznichenko 	NULL
611*0c7d530aSIgor Reznichenko };
612*0c7d530aSIgor Reznichenko 
613*0c7d530aSIgor Reznichenko static ssize_t shunt_resistor_show(struct device *dev,
614*0c7d530aSIgor Reznichenko 				   struct device_attribute *da, char *buf)
615*0c7d530aSIgor Reznichenko {
616*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
617*0c7d530aSIgor Reznichenko 
618*0c7d530aSIgor Reznichenko 	return sysfs_emit(buf, "%li\n", data->rshunt_uohm);
619*0c7d530aSIgor Reznichenko }
620*0c7d530aSIgor Reznichenko 
621*0c7d530aSIgor Reznichenko static ssize_t shunt_resistor_store(struct device *dev,
622*0c7d530aSIgor Reznichenko 				    struct device_attribute *da,
623*0c7d530aSIgor Reznichenko 				    const char *buf, size_t count)
624*0c7d530aSIgor Reznichenko {
625*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data = dev_get_drvdata(dev);
626*0c7d530aSIgor Reznichenko 	unsigned int val;
627*0c7d530aSIgor Reznichenko 	int ret;
628*0c7d530aSIgor Reznichenko 
629*0c7d530aSIgor Reznichenko 	ret = kstrtouint(buf, 10, &val);
630*0c7d530aSIgor Reznichenko 	if (ret < 0)
631*0c7d530aSIgor Reznichenko 		return ret;
632*0c7d530aSIgor Reznichenko 
633*0c7d530aSIgor Reznichenko 	ret = tsc1641_validate_shunt(val);
634*0c7d530aSIgor Reznichenko 	if (ret < 0)
635*0c7d530aSIgor Reznichenko 		return ret;
636*0c7d530aSIgor Reznichenko 
637*0c7d530aSIgor Reznichenko 	ret = tsc1641_set_shunt(data, val);
638*0c7d530aSIgor Reznichenko 	if (ret < 0)
639*0c7d530aSIgor Reznichenko 		return ret;
640*0c7d530aSIgor Reznichenko 	return count;
641*0c7d530aSIgor Reznichenko }
642*0c7d530aSIgor Reznichenko 
643*0c7d530aSIgor Reznichenko static const struct hwmon_ops tsc1641_hwmon_ops = {
644*0c7d530aSIgor Reznichenko 	.is_visible = tsc1641_is_visible,
645*0c7d530aSIgor Reznichenko 	.read = tsc1641_read,
646*0c7d530aSIgor Reznichenko 	.write = tsc1641_write,
647*0c7d530aSIgor Reznichenko };
648*0c7d530aSIgor Reznichenko 
649*0c7d530aSIgor Reznichenko static const struct hwmon_chip_info tsc1641_chip_info = {
650*0c7d530aSIgor Reznichenko 	.ops = &tsc1641_hwmon_ops,
651*0c7d530aSIgor Reznichenko 	.info = tsc1641_info,
652*0c7d530aSIgor Reznichenko };
653*0c7d530aSIgor Reznichenko 
654*0c7d530aSIgor Reznichenko static DEVICE_ATTR_RW(shunt_resistor);
655*0c7d530aSIgor Reznichenko 
656*0c7d530aSIgor Reznichenko /* Shunt resistor value is exposed via sysfs attribute */
657*0c7d530aSIgor Reznichenko static struct attribute *tsc1641_attrs[] = {
658*0c7d530aSIgor Reznichenko 	&dev_attr_shunt_resistor.attr,
659*0c7d530aSIgor Reznichenko 	NULL,
660*0c7d530aSIgor Reznichenko };
661*0c7d530aSIgor Reznichenko ATTRIBUTE_GROUPS(tsc1641);
662*0c7d530aSIgor Reznichenko 
663*0c7d530aSIgor Reznichenko static int tsc1641_init(struct device *dev, struct tsc1641_data *data)
664*0c7d530aSIgor Reznichenko {
665*0c7d530aSIgor Reznichenko 	struct regmap *regmap = data->regmap;
666*0c7d530aSIgor Reznichenko 	bool active_high;
667*0c7d530aSIgor Reznichenko 	u32 shunt;
668*0c7d530aSIgor Reznichenko 	int ret;
669*0c7d530aSIgor Reznichenko 
670*0c7d530aSIgor Reznichenko 	if (device_property_read_u32(dev, "shunt-resistor-micro-ohms", &shunt) < 0)
671*0c7d530aSIgor Reznichenko 		shunt = TSC1641_RSHUNT_DEFAULT;
672*0c7d530aSIgor Reznichenko 
673*0c7d530aSIgor Reznichenko 	if (tsc1641_validate_shunt(shunt) < 0) {
674*0c7d530aSIgor Reznichenko 		dev_err(dev, "invalid shunt resistor value %u\n", shunt);
675*0c7d530aSIgor Reznichenko 		return -EINVAL;
676*0c7d530aSIgor Reznichenko 	}
677*0c7d530aSIgor Reznichenko 
678*0c7d530aSIgor Reznichenko 	ret = tsc1641_set_shunt(data, shunt);
679*0c7d530aSIgor Reznichenko 	if (ret < 0)
680*0c7d530aSIgor Reznichenko 		return ret;
681*0c7d530aSIgor Reznichenko 
682*0c7d530aSIgor Reznichenko 	ret = regmap_write(regmap, TSC1641_CONFIG, TSC1641_CONFIG_DEFAULT);
683*0c7d530aSIgor Reznichenko 	if (ret < 0)
684*0c7d530aSIgor Reznichenko 		return ret;
685*0c7d530aSIgor Reznichenko 
686*0c7d530aSIgor Reznichenko 	active_high = device_property_read_bool(dev, "st,alert-polarity-active-high");
687*0c7d530aSIgor Reznichenko 
688*0c7d530aSIgor Reznichenko 	return regmap_write(regmap, TSC1641_MASK, TSC1641_MASK_DEFAULT |
689*0c7d530aSIgor Reznichenko 			    FIELD_PREP(TSC1641_ALERT_POL_MASK, active_high));
690*0c7d530aSIgor Reznichenko }
691*0c7d530aSIgor Reznichenko 
692*0c7d530aSIgor Reznichenko static int tsc1641_probe(struct i2c_client *client)
693*0c7d530aSIgor Reznichenko {
694*0c7d530aSIgor Reznichenko 	struct device *dev = &client->dev;
695*0c7d530aSIgor Reznichenko 	struct tsc1641_data *data;
696*0c7d530aSIgor Reznichenko 	struct device *hwmon_dev;
697*0c7d530aSIgor Reznichenko 	int ret;
698*0c7d530aSIgor Reznichenko 
699*0c7d530aSIgor Reznichenko 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
700*0c7d530aSIgor Reznichenko 	if (!data)
701*0c7d530aSIgor Reznichenko 		return -ENOMEM;
702*0c7d530aSIgor Reznichenko 
703*0c7d530aSIgor Reznichenko 	data->regmap = devm_regmap_init_i2c(client, &tsc1641_regmap_config);
704*0c7d530aSIgor Reznichenko 	if (IS_ERR(data->regmap))
705*0c7d530aSIgor Reznichenko 		return dev_err_probe(dev, PTR_ERR(data->regmap),
706*0c7d530aSIgor Reznichenko 				     "failed to allocate register map\n");
707*0c7d530aSIgor Reznichenko 
708*0c7d530aSIgor Reznichenko 	ret = tsc1641_init(dev, data);
709*0c7d530aSIgor Reznichenko 	if (ret < 0)
710*0c7d530aSIgor Reznichenko 		return dev_err_probe(dev, ret, "failed to configure device\n");
711*0c7d530aSIgor Reznichenko 
712*0c7d530aSIgor Reznichenko 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
713*0c7d530aSIgor Reznichenko 							 data, &tsc1641_chip_info, tsc1641_groups);
714*0c7d530aSIgor Reznichenko 	if (IS_ERR(hwmon_dev))
715*0c7d530aSIgor Reznichenko 		return PTR_ERR(hwmon_dev);
716*0c7d530aSIgor Reznichenko 
717*0c7d530aSIgor Reznichenko 	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
718*0c7d530aSIgor Reznichenko 		 client->name, data->rshunt_uohm);
719*0c7d530aSIgor Reznichenko 
720*0c7d530aSIgor Reznichenko 	return 0;
721*0c7d530aSIgor Reznichenko }
722*0c7d530aSIgor Reznichenko 
723*0c7d530aSIgor Reznichenko static const struct i2c_device_id tsc1641_id[] = {
724*0c7d530aSIgor Reznichenko 	{ "tsc1641", 0 },
725*0c7d530aSIgor Reznichenko 	{ }
726*0c7d530aSIgor Reznichenko };
727*0c7d530aSIgor Reznichenko MODULE_DEVICE_TABLE(i2c, tsc1641_id);
728*0c7d530aSIgor Reznichenko 
729*0c7d530aSIgor Reznichenko static const struct of_device_id __maybe_unused tsc1641_of_match[] = {
730*0c7d530aSIgor Reznichenko 	{ .compatible = "st,tsc1641" },
731*0c7d530aSIgor Reznichenko 	{ },
732*0c7d530aSIgor Reznichenko };
733*0c7d530aSIgor Reznichenko MODULE_DEVICE_TABLE(of, tsc1641_of_match);
734*0c7d530aSIgor Reznichenko 
735*0c7d530aSIgor Reznichenko static struct i2c_driver tsc1641_driver = {
736*0c7d530aSIgor Reznichenko 	.driver = {
737*0c7d530aSIgor Reznichenko 		.name = "tsc1641",
738*0c7d530aSIgor Reznichenko 		.of_match_table = of_match_ptr(tsc1641_of_match),
739*0c7d530aSIgor Reznichenko 	},
740*0c7d530aSIgor Reznichenko 	.probe = tsc1641_probe,
741*0c7d530aSIgor Reznichenko 	.id_table = tsc1641_id,
742*0c7d530aSIgor Reznichenko };
743*0c7d530aSIgor Reznichenko 
744*0c7d530aSIgor Reznichenko module_i2c_driver(tsc1641_driver);
745*0c7d530aSIgor Reznichenko 
746*0c7d530aSIgor Reznichenko MODULE_AUTHOR("Igor Reznichenko <igor@reznichenko.net>");
747*0c7d530aSIgor Reznichenko MODULE_DESCRIPTION("tsc1641 driver");
748*0c7d530aSIgor Reznichenko MODULE_LICENSE("GPL");
749