xref: /linux/drivers/hwmon/pmbus/sq24860.c (revision 7acf90feab8b009fde7def08ff2c622d0f10e99f)
1*93ab13d8SZiming Zhu // SPDX-License-Identifier: GPL-2.0
2*93ab13d8SZiming Zhu /*
3*93ab13d8SZiming Zhu  * Author: Ziming Zhu <ziming.zhu@silergycorp.com>
4*93ab13d8SZiming Zhu  */
5*93ab13d8SZiming Zhu 
6*93ab13d8SZiming Zhu #include <linux/bitfield.h>
7*93ab13d8SZiming Zhu #include <linux/err.h>
8*93ab13d8SZiming Zhu #include <linux/i2c.h>
9*93ab13d8SZiming Zhu #include <linux/init.h>
10*93ab13d8SZiming Zhu #include <linux/kernel.h>
11*93ab13d8SZiming Zhu #include <linux/module.h>
12*93ab13d8SZiming Zhu #include <linux/math64.h>
13*93ab13d8SZiming Zhu 
14*93ab13d8SZiming Zhu #include "pmbus.h"
15*93ab13d8SZiming Zhu 
16*93ab13d8SZiming Zhu #define SQ24860_IIN_CAL_GAIN		0x38
17*93ab13d8SZiming Zhu #define SQ24860_READ_VAUX		0xd0
18*93ab13d8SZiming Zhu #define SQ24860_READ_VIN_MIN		0xd1
19*93ab13d8SZiming Zhu #define SQ24860_READ_VIN_PEAK		0xd2
20*93ab13d8SZiming Zhu #define SQ24860_READ_IIN_PEAK		0xd4
21*93ab13d8SZiming Zhu #define SQ24860_READ_PIN_PEAK		0xd5
22*93ab13d8SZiming Zhu #define SQ24860_READ_TEMP_AVG		0xd6
23*93ab13d8SZiming Zhu #define SQ24860_READ_TEMP_PEAK		0xd7
24*93ab13d8SZiming Zhu #define SQ24860_READ_VOUT_MIN		0xda
25*93ab13d8SZiming Zhu #define SQ24860_READ_VIN_AVG		0xdc
26*93ab13d8SZiming Zhu #define SQ24860_READ_VOUT_AVG		0xdd
27*93ab13d8SZiming Zhu #define SQ24860_READ_IIN_AVG		0xde
28*93ab13d8SZiming Zhu #define SQ24860_READ_PIN_AVG		0xdf
29*93ab13d8SZiming Zhu #define SQ24860_VIREF			0xe0
30*93ab13d8SZiming Zhu #define SQ24860_PK_MIN_AVG		0xea
31*93ab13d8SZiming Zhu #define PK_MIN_AVG_RST_PEAK		BIT(7)
32*93ab13d8SZiming Zhu #define PK_MIN_AVG_RST_AVG		BIT(6)
33*93ab13d8SZiming Zhu #define PK_MIN_AVG_RST_MIN		BIT(5)
34*93ab13d8SZiming Zhu #define PK_MIN_AVG_AVG_CNT		GENMASK(2, 0)
35*93ab13d8SZiming Zhu #define SQ24860_MFR_WRITE_PROTECT	0xf8
36*93ab13d8SZiming Zhu #define SQ24860_UNLOCKED		BIT(7)
37*93ab13d8SZiming Zhu 
38*93ab13d8SZiming Zhu #define SQ24860_8B_SHIFT		2
39*93ab13d8SZiming Zhu #define SQ24860_IIN_OCF_NUM		1000000
40*93ab13d8SZiming Zhu #define SQ24860_IIN_OCF_DIV		129278
41*93ab13d8SZiming Zhu #define SQ24860_IIN_OCF_OFF		165
42*93ab13d8SZiming Zhu 
43*93ab13d8SZiming Zhu #define PK_MIN_AVG_RST_MASK		(PK_MIN_AVG_RST_PEAK | \
44*93ab13d8SZiming Zhu 					 PK_MIN_AVG_RST_AVG  | \
45*93ab13d8SZiming Zhu 					 PK_MIN_AVG_RST_MIN)
46*93ab13d8SZiming Zhu #define SQ24860_MAX_SAMPLES		BIT(FIELD_MAX(PK_MIN_AVG_AVG_CNT))
47*93ab13d8SZiming Zhu /*
48*93ab13d8SZiming Zhu  * Arbitrary default Rimon value: 1.6kOhm
49*93ab13d8SZiming Zhu  */
50*93ab13d8SZiming Zhu #define SQ24860_DEFAULT_RIMON		1600000000
51*93ab13d8SZiming Zhu #define SQ24860_GIMON			18180
52*93ab13d8SZiming Zhu 
53*93ab13d8SZiming Zhu #define SQ24860_VAUX_DIV		20
54*93ab13d8SZiming Zhu 
55*93ab13d8SZiming Zhu static int sq24860_write_iin_cal_gain(struct i2c_client *client, u32 rimon)
56*93ab13d8SZiming Zhu {
57*93ab13d8SZiming Zhu 	u64 temp = 6400ULL * 1000000000ULL * 1000ULL;
58*93ab13d8SZiming Zhu 	u64 denom;
59*93ab13d8SZiming Zhu 	u64 word;
60*93ab13d8SZiming Zhu 
61*93ab13d8SZiming Zhu 	if (!rimon)
62*93ab13d8SZiming Zhu 		return -EINVAL;
63*93ab13d8SZiming Zhu 
64*93ab13d8SZiming Zhu 	denom = (u64)rimon * SQ24860_GIMON;
65*93ab13d8SZiming Zhu 	word = div64_u64(temp, denom);
66*93ab13d8SZiming Zhu 	if (!word || word > U16_MAX)
67*93ab13d8SZiming Zhu 		return -EINVAL;
68*93ab13d8SZiming Zhu 
69*93ab13d8SZiming Zhu 	return i2c_smbus_write_word_data(client, SQ24860_IIN_CAL_GAIN,
70*93ab13d8SZiming Zhu 					(u16)word);
71*93ab13d8SZiming Zhu }
72*93ab13d8SZiming Zhu 
73*93ab13d8SZiming Zhu static int sq24860_mfr_write_protect_set(struct i2c_client *client,
74*93ab13d8SZiming Zhu 					 u8 protect)
75*93ab13d8SZiming Zhu {
76*93ab13d8SZiming Zhu 	u8 val;
77*93ab13d8SZiming Zhu 
78*93ab13d8SZiming Zhu 	switch (protect) {
79*93ab13d8SZiming Zhu 	case 0:
80*93ab13d8SZiming Zhu 		val = 0xa2;
81*93ab13d8SZiming Zhu 		break;
82*93ab13d8SZiming Zhu 	case PB_WP_ALL:
83*93ab13d8SZiming Zhu 		val = 0x0;
84*93ab13d8SZiming Zhu 		break;
85*93ab13d8SZiming Zhu 	default:
86*93ab13d8SZiming Zhu 		return -EINVAL;
87*93ab13d8SZiming Zhu 	}
88*93ab13d8SZiming Zhu 
89*93ab13d8SZiming Zhu 	return pmbus_write_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT,
90*93ab13d8SZiming Zhu 				     val);
91*93ab13d8SZiming Zhu }
92*93ab13d8SZiming Zhu 
93*93ab13d8SZiming Zhu static int sq24860_mfr_write_protect_get(struct i2c_client *client)
94*93ab13d8SZiming Zhu {
95*93ab13d8SZiming Zhu 	int ret = pmbus_read_byte_data(client, -1, SQ24860_MFR_WRITE_PROTECT);
96*93ab13d8SZiming Zhu 
97*93ab13d8SZiming Zhu 	if (ret < 0)
98*93ab13d8SZiming Zhu 		return ret;
99*93ab13d8SZiming Zhu 
100*93ab13d8SZiming Zhu 	return (ret & SQ24860_UNLOCKED) ? 0 : PB_WP_ALL;
101*93ab13d8SZiming Zhu }
102*93ab13d8SZiming Zhu 
103*93ab13d8SZiming Zhu static int sq24860_read_word_data(struct i2c_client *client,
104*93ab13d8SZiming Zhu 				  int page, int phase, int reg)
105*93ab13d8SZiming Zhu {
106*93ab13d8SZiming Zhu 	int ret;
107*93ab13d8SZiming Zhu 
108*93ab13d8SZiming Zhu 	switch (reg) {
109*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_VIN_MAX:
110*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
111*93ab13d8SZiming Zhu 					   SQ24860_READ_VIN_PEAK);
112*93ab13d8SZiming Zhu 		break;
113*93ab13d8SZiming Zhu 
114*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_VIN_MIN:
115*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
116*93ab13d8SZiming Zhu 					   SQ24860_READ_VIN_MIN);
117*93ab13d8SZiming Zhu 		break;
118*93ab13d8SZiming Zhu 
119*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_VIN_AVG:
120*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
121*93ab13d8SZiming Zhu 					   SQ24860_READ_VIN_AVG);
122*93ab13d8SZiming Zhu 		break;
123*93ab13d8SZiming Zhu 
124*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_VOUT_MIN:
125*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
126*93ab13d8SZiming Zhu 					   SQ24860_READ_VOUT_MIN);
127*93ab13d8SZiming Zhu 		break;
128*93ab13d8SZiming Zhu 
129*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_VOUT_AVG:
130*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
131*93ab13d8SZiming Zhu 					   SQ24860_READ_VOUT_AVG);
132*93ab13d8SZiming Zhu 		break;
133*93ab13d8SZiming Zhu 
134*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_IIN_AVG:
135*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
136*93ab13d8SZiming Zhu 					   SQ24860_READ_IIN_AVG);
137*93ab13d8SZiming Zhu 		break;
138*93ab13d8SZiming Zhu 
139*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_IIN_MAX:
140*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
141*93ab13d8SZiming Zhu 					   SQ24860_READ_IIN_PEAK);
142*93ab13d8SZiming Zhu 		break;
143*93ab13d8SZiming Zhu 
144*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_TEMP_AVG:
145*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
146*93ab13d8SZiming Zhu 					   SQ24860_READ_TEMP_AVG);
147*93ab13d8SZiming Zhu 		break;
148*93ab13d8SZiming Zhu 
149*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_TEMP_MAX:
150*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
151*93ab13d8SZiming Zhu 					   SQ24860_READ_TEMP_PEAK);
152*93ab13d8SZiming Zhu 		break;
153*93ab13d8SZiming Zhu 
154*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_PIN_AVG:
155*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
156*93ab13d8SZiming Zhu 					   SQ24860_READ_PIN_AVG);
157*93ab13d8SZiming Zhu 		break;
158*93ab13d8SZiming Zhu 
159*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_PIN_MAX:
160*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
161*93ab13d8SZiming Zhu 					   SQ24860_READ_PIN_PEAK);
162*93ab13d8SZiming Zhu 		break;
163*93ab13d8SZiming Zhu 
164*93ab13d8SZiming Zhu 	case PMBUS_VIRT_READ_VMON:
165*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase,
166*93ab13d8SZiming Zhu 					   SQ24860_READ_VAUX);
167*93ab13d8SZiming Zhu 		if (ret < 0)
168*93ab13d8SZiming Zhu 			break;
169*93ab13d8SZiming Zhu 		ret = DIV_ROUND_CLOSEST(ret, SQ24860_VAUX_DIV);
170*93ab13d8SZiming Zhu 		break;
171*93ab13d8SZiming Zhu 
172*93ab13d8SZiming Zhu 	case PMBUS_VIN_UV_WARN_LIMIT:
173*93ab13d8SZiming Zhu 	case PMBUS_VIN_UV_FAULT_LIMIT:
174*93ab13d8SZiming Zhu 	case PMBUS_VIN_OV_WARN_LIMIT:
175*93ab13d8SZiming Zhu 	case PMBUS_VIN_OV_FAULT_LIMIT:
176*93ab13d8SZiming Zhu 	case PMBUS_VOUT_UV_WARN_LIMIT:
177*93ab13d8SZiming Zhu 	case PMBUS_IIN_OC_WARN_LIMIT:
178*93ab13d8SZiming Zhu 	case PMBUS_OT_WARN_LIMIT:
179*93ab13d8SZiming Zhu 	case PMBUS_OT_FAULT_LIMIT:
180*93ab13d8SZiming Zhu 	case PMBUS_PIN_OP_WARN_LIMIT:
181*93ab13d8SZiming Zhu 		/*
182*93ab13d8SZiming Zhu 		 * These registers provide an 8 bits value instead of a
183*93ab13d8SZiming Zhu 		 * 10bits one. Just shifting twice the register value is
184*93ab13d8SZiming Zhu 		 * enough to make the sensor type conversion work, even
185*93ab13d8SZiming Zhu 		 * if the datasheet provides different m, b and R for
186*93ab13d8SZiming Zhu 		 * those.
187*93ab13d8SZiming Zhu 		 */
188*93ab13d8SZiming Zhu 		ret = pmbus_read_word_data(client, page, phase, reg);
189*93ab13d8SZiming Zhu 		if (ret < 0)
190*93ab13d8SZiming Zhu 			break;
191*93ab13d8SZiming Zhu 		ret <<= SQ24860_8B_SHIFT;
192*93ab13d8SZiming Zhu 		break;
193*93ab13d8SZiming Zhu 
194*93ab13d8SZiming Zhu 	case PMBUS_IIN_OC_FAULT_LIMIT:
195*93ab13d8SZiming Zhu 		/*
196*93ab13d8SZiming Zhu 		 * VIREF directly sets the over-current limit at which the eFuse
197*93ab13d8SZiming Zhu 		 * will turn the FET off and trigger a fault. Expose it through
198*93ab13d8SZiming Zhu 		 * this generic property instead of a manufacturer specific one.
199*93ab13d8SZiming Zhu 		 */
200*93ab13d8SZiming Zhu 		ret = pmbus_read_byte_data(client, page, SQ24860_VIREF);
201*93ab13d8SZiming Zhu 		if (ret < 0)
202*93ab13d8SZiming Zhu 			break;
203*93ab13d8SZiming Zhu 		ret = DIV_ROUND_CLOSEST(ret * SQ24860_IIN_OCF_NUM,
204*93ab13d8SZiming Zhu 					SQ24860_IIN_OCF_DIV);
205*93ab13d8SZiming Zhu 		ret += SQ24860_IIN_OCF_OFF;
206*93ab13d8SZiming Zhu 		break;
207*93ab13d8SZiming Zhu 
208*93ab13d8SZiming Zhu 	case PMBUS_VIRT_SAMPLES:
209*93ab13d8SZiming Zhu 		ret = pmbus_read_byte_data(client, page, SQ24860_PK_MIN_AVG);
210*93ab13d8SZiming Zhu 		if (ret < 0)
211*93ab13d8SZiming Zhu 			break;
212*93ab13d8SZiming Zhu 		ret = BIT(FIELD_GET(PK_MIN_AVG_AVG_CNT, ret));
213*93ab13d8SZiming Zhu 		break;
214*93ab13d8SZiming Zhu 
215*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_TEMP_HISTORY:
216*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_VIN_HISTORY:
217*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_IIN_HISTORY:
218*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_PIN_HISTORY:
219*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
220*93ab13d8SZiming Zhu 		ret = 0;
221*93ab13d8SZiming Zhu 		break;
222*93ab13d8SZiming Zhu 
223*93ab13d8SZiming Zhu 	default:
224*93ab13d8SZiming Zhu 		ret = -ENODATA;
225*93ab13d8SZiming Zhu 		break;
226*93ab13d8SZiming Zhu 	}
227*93ab13d8SZiming Zhu 
228*93ab13d8SZiming Zhu 	return ret;
229*93ab13d8SZiming Zhu }
230*93ab13d8SZiming Zhu 
231*93ab13d8SZiming Zhu static int sq24860_write_word_data(struct i2c_client *client,
232*93ab13d8SZiming Zhu 				   int page, int reg, u16 value)
233*93ab13d8SZiming Zhu {
234*93ab13d8SZiming Zhu 	int ret;
235*93ab13d8SZiming Zhu 
236*93ab13d8SZiming Zhu 	switch (reg) {
237*93ab13d8SZiming Zhu 	case PMBUS_VIN_UV_WARN_LIMIT:
238*93ab13d8SZiming Zhu 	case PMBUS_VIN_UV_FAULT_LIMIT:
239*93ab13d8SZiming Zhu 	case PMBUS_VIN_OV_WARN_LIMIT:
240*93ab13d8SZiming Zhu 	case PMBUS_VIN_OV_FAULT_LIMIT:
241*93ab13d8SZiming Zhu 	case PMBUS_VOUT_UV_WARN_LIMIT:
242*93ab13d8SZiming Zhu 	case PMBUS_IIN_OC_WARN_LIMIT:
243*93ab13d8SZiming Zhu 	case PMBUS_OT_WARN_LIMIT:
244*93ab13d8SZiming Zhu 	case PMBUS_OT_FAULT_LIMIT:
245*93ab13d8SZiming Zhu 	case PMBUS_PIN_OP_WARN_LIMIT:
246*93ab13d8SZiming Zhu 		value = max_t(s16, (s16)value, 0);
247*93ab13d8SZiming Zhu 		value >>= SQ24860_8B_SHIFT;
248*93ab13d8SZiming Zhu 		value = clamp_val(value, 0, 0xff);
249*93ab13d8SZiming Zhu 		ret = pmbus_write_word_data(client, page, reg, value);
250*93ab13d8SZiming Zhu 		break;
251*93ab13d8SZiming Zhu 
252*93ab13d8SZiming Zhu 	case PMBUS_IIN_OC_FAULT_LIMIT:
253*93ab13d8SZiming Zhu 		value = max_t(s16, (s16)value, SQ24860_IIN_OCF_OFF);
254*93ab13d8SZiming Zhu 		value -= SQ24860_IIN_OCF_OFF;
255*93ab13d8SZiming Zhu 		value = DIV_ROUND_CLOSEST(((unsigned int)value) * SQ24860_IIN_OCF_DIV,
256*93ab13d8SZiming Zhu 					  SQ24860_IIN_OCF_NUM);
257*93ab13d8SZiming Zhu 		value = clamp_val(value, 0, 0x3f);
258*93ab13d8SZiming Zhu 		ret = pmbus_write_byte_data(client, page, SQ24860_VIREF, value);
259*93ab13d8SZiming Zhu 		break;
260*93ab13d8SZiming Zhu 
261*93ab13d8SZiming Zhu 	case PMBUS_VIRT_SAMPLES:
262*93ab13d8SZiming Zhu 		value = clamp_val(value, 1, SQ24860_MAX_SAMPLES);
263*93ab13d8SZiming Zhu 		value = ilog2(value);
264*93ab13d8SZiming Zhu 		ret = pmbus_update_byte_data(client, page, SQ24860_PK_MIN_AVG,
265*93ab13d8SZiming Zhu 					     PK_MIN_AVG_AVG_CNT,
266*93ab13d8SZiming Zhu 					     FIELD_PREP(PK_MIN_AVG_AVG_CNT, value));
267*93ab13d8SZiming Zhu 		break;
268*93ab13d8SZiming Zhu 
269*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_TEMP_HISTORY:
270*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_VIN_HISTORY:
271*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_IIN_HISTORY:
272*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_PIN_HISTORY:
273*93ab13d8SZiming Zhu 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
274*93ab13d8SZiming Zhu 		/*
275*93ab13d8SZiming Zhu 		 * SQ24860 has history resets based on MIN/AVG/PEAK instead of per
276*93ab13d8SZiming Zhu 		 * sensor type. Exposing this quirk in hwmon is not desirable so
277*93ab13d8SZiming Zhu 		 * reset MIN, AVG and PEAK together. Even is there effectively only
278*93ab13d8SZiming Zhu 		 * one reset, which resets everything, expose the 5 entries so
279*93ab13d8SZiming Zhu 		 * userspace is not required map a sensor type to another to trigger
280*93ab13d8SZiming Zhu 		 * a reset
281*93ab13d8SZiming Zhu 		 */
282*93ab13d8SZiming Zhu 		ret = pmbus_update_byte_data(client, 0, SQ24860_PK_MIN_AVG,
283*93ab13d8SZiming Zhu 					     PK_MIN_AVG_RST_MASK,
284*93ab13d8SZiming Zhu 					     PK_MIN_AVG_RST_MASK);
285*93ab13d8SZiming Zhu 		break;
286*93ab13d8SZiming Zhu 
287*93ab13d8SZiming Zhu 	default:
288*93ab13d8SZiming Zhu 		ret = -ENODATA;
289*93ab13d8SZiming Zhu 		break;
290*93ab13d8SZiming Zhu 	}
291*93ab13d8SZiming Zhu 
292*93ab13d8SZiming Zhu 	return ret;
293*93ab13d8SZiming Zhu }
294*93ab13d8SZiming Zhu 
295*93ab13d8SZiming Zhu static int sq24860_read_byte_data(struct i2c_client *client,
296*93ab13d8SZiming Zhu 				  int page, int reg)
297*93ab13d8SZiming Zhu {
298*93ab13d8SZiming Zhu 	int ret;
299*93ab13d8SZiming Zhu 
300*93ab13d8SZiming Zhu 	switch (reg) {
301*93ab13d8SZiming Zhu 	case PMBUS_WRITE_PROTECT:
302*93ab13d8SZiming Zhu 		ret = sq24860_mfr_write_protect_get(client);
303*93ab13d8SZiming Zhu 		break;
304*93ab13d8SZiming Zhu 
305*93ab13d8SZiming Zhu 	default:
306*93ab13d8SZiming Zhu 		ret = -ENODATA;
307*93ab13d8SZiming Zhu 		break;
308*93ab13d8SZiming Zhu 	}
309*93ab13d8SZiming Zhu 
310*93ab13d8SZiming Zhu 	return ret;
311*93ab13d8SZiming Zhu }
312*93ab13d8SZiming Zhu 
313*93ab13d8SZiming Zhu static int sq24860_write_byte_data(struct i2c_client *client,
314*93ab13d8SZiming Zhu 				   int page, int reg, u8 byte)
315*93ab13d8SZiming Zhu {
316*93ab13d8SZiming Zhu 	int ret;
317*93ab13d8SZiming Zhu 
318*93ab13d8SZiming Zhu 	switch (reg) {
319*93ab13d8SZiming Zhu 	case PMBUS_WRITE_PROTECT:
320*93ab13d8SZiming Zhu 		ret = sq24860_mfr_write_protect_set(client, byte);
321*93ab13d8SZiming Zhu 		break;
322*93ab13d8SZiming Zhu 
323*93ab13d8SZiming Zhu 	default:
324*93ab13d8SZiming Zhu 		ret = -ENODATA;
325*93ab13d8SZiming Zhu 		break;
326*93ab13d8SZiming Zhu 	}
327*93ab13d8SZiming Zhu 
328*93ab13d8SZiming Zhu 	return ret;
329*93ab13d8SZiming Zhu }
330*93ab13d8SZiming Zhu 
331*93ab13d8SZiming Zhu #if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
332*93ab13d8SZiming Zhu static const struct regulator_desc sq24860_reg_desc[] = {
333*93ab13d8SZiming Zhu 	PMBUS_REGULATOR_ONE_NODE("vout"),
334*93ab13d8SZiming Zhu };
335*93ab13d8SZiming Zhu #endif
336*93ab13d8SZiming Zhu 
337*93ab13d8SZiming Zhu static const struct pmbus_driver_info sq24860_base_info = {
338*93ab13d8SZiming Zhu 	.pages = 1,
339*93ab13d8SZiming Zhu 	.format[PSC_VOLTAGE_IN] = direct,
340*93ab13d8SZiming Zhu 	.m[PSC_VOLTAGE_IN] = 64,
341*93ab13d8SZiming Zhu 	.b[PSC_VOLTAGE_IN] = 0,
342*93ab13d8SZiming Zhu 	.R[PSC_VOLTAGE_IN] = 0,
343*93ab13d8SZiming Zhu 	.format[PSC_VOLTAGE_OUT] = direct,
344*93ab13d8SZiming Zhu 	.m[PSC_VOLTAGE_OUT] = 64,
345*93ab13d8SZiming Zhu 	.b[PSC_VOLTAGE_OUT] = 0,
346*93ab13d8SZiming Zhu 	.R[PSC_VOLTAGE_OUT] = 0,
347*93ab13d8SZiming Zhu 	.format[PSC_TEMPERATURE] = direct,
348*93ab13d8SZiming Zhu 	.m[PSC_TEMPERATURE] = 1,
349*93ab13d8SZiming Zhu 	.b[PSC_TEMPERATURE] = 0,
350*93ab13d8SZiming Zhu 	.R[PSC_TEMPERATURE] = 0,
351*93ab13d8SZiming Zhu 	/*
352*93ab13d8SZiming Zhu 	 * Current and power measurements depend on the calibration gain
353*93ab13d8SZiming Zhu 	 * programmed from the board-specific IMON resistor value.
354*93ab13d8SZiming Zhu 	 */
355*93ab13d8SZiming Zhu 	.format[PSC_CURRENT_IN] = direct,
356*93ab13d8SZiming Zhu 	.m[PSC_CURRENT_IN] = 16,
357*93ab13d8SZiming Zhu 	.b[PSC_CURRENT_IN] = 0,
358*93ab13d8SZiming Zhu 	.R[PSC_CURRENT_IN] = 0,
359*93ab13d8SZiming Zhu 	.format[PSC_POWER] = direct,
360*93ab13d8SZiming Zhu 	.m[PSC_POWER] = 2,
361*93ab13d8SZiming Zhu 	.b[PSC_POWER] = 0,
362*93ab13d8SZiming Zhu 	.R[PSC_POWER] = 0,
363*93ab13d8SZiming Zhu 	.func[0] = PMBUS_HAVE_VIN |
364*93ab13d8SZiming Zhu 		   PMBUS_HAVE_VOUT |
365*93ab13d8SZiming Zhu 		   PMBUS_HAVE_VMON |
366*93ab13d8SZiming Zhu 		   PMBUS_HAVE_IIN |
367*93ab13d8SZiming Zhu 		   PMBUS_HAVE_PIN |
368*93ab13d8SZiming Zhu 		   PMBUS_HAVE_TEMP |
369*93ab13d8SZiming Zhu 		   PMBUS_HAVE_STATUS_VOUT |
370*93ab13d8SZiming Zhu 		   PMBUS_HAVE_STATUS_IOUT |
371*93ab13d8SZiming Zhu 		   PMBUS_HAVE_STATUS_INPUT |
372*93ab13d8SZiming Zhu 		   PMBUS_HAVE_STATUS_TEMP |
373*93ab13d8SZiming Zhu 		   PMBUS_HAVE_SAMPLES,
374*93ab13d8SZiming Zhu 	.read_word_data = sq24860_read_word_data,
375*93ab13d8SZiming Zhu 	.write_word_data = sq24860_write_word_data,
376*93ab13d8SZiming Zhu 	.read_byte_data = sq24860_read_byte_data,
377*93ab13d8SZiming Zhu 	.write_byte_data = sq24860_write_byte_data,
378*93ab13d8SZiming Zhu 
379*93ab13d8SZiming Zhu #if IS_ENABLED(CONFIG_SENSORS_SQ24860_REGULATOR)
380*93ab13d8SZiming Zhu 	.reg_desc = sq24860_reg_desc,
381*93ab13d8SZiming Zhu 	.num_regulators = ARRAY_SIZE(sq24860_reg_desc),
382*93ab13d8SZiming Zhu #endif
383*93ab13d8SZiming Zhu };
384*93ab13d8SZiming Zhu 
385*93ab13d8SZiming Zhu static const struct i2c_device_id sq24860_i2c_id[] = {
386*93ab13d8SZiming Zhu 	{ "sq24860" },
387*93ab13d8SZiming Zhu 	{}
388*93ab13d8SZiming Zhu };
389*93ab13d8SZiming Zhu MODULE_DEVICE_TABLE(i2c, sq24860_i2c_id);
390*93ab13d8SZiming Zhu 
391*93ab13d8SZiming Zhu static const struct of_device_id sq24860_of_match[] = {
392*93ab13d8SZiming Zhu 	{ .compatible = "silergy,sq24860" },
393*93ab13d8SZiming Zhu 	{}
394*93ab13d8SZiming Zhu };
395*93ab13d8SZiming Zhu MODULE_DEVICE_TABLE(of, sq24860_of_match);
396*93ab13d8SZiming Zhu 
397*93ab13d8SZiming Zhu static int sq24860_probe(struct i2c_client *client)
398*93ab13d8SZiming Zhu {
399*93ab13d8SZiming Zhu 	struct device *dev = &client->dev;
400*93ab13d8SZiming Zhu 	struct pmbus_driver_info *info;
401*93ab13d8SZiming Zhu 	u32 rimon;
402*93ab13d8SZiming Zhu 	int ret;
403*93ab13d8SZiming Zhu 
404*93ab13d8SZiming Zhu 	if (device_property_read_u32(dev, "silergy,rimon-micro-ohms", &rimon))
405*93ab13d8SZiming Zhu 		rimon = SQ24860_DEFAULT_RIMON;
406*93ab13d8SZiming Zhu 	ret = sq24860_write_iin_cal_gain(client, rimon);
407*93ab13d8SZiming Zhu 	if (ret < 0)
408*93ab13d8SZiming Zhu 		return dev_err_probe(&client->dev, ret,
409*93ab13d8SZiming Zhu 					     "Failed to set gain\n");
410*93ab13d8SZiming Zhu 	info = devm_kmemdup(dev, &sq24860_base_info, sizeof(*info), GFP_KERNEL);
411*93ab13d8SZiming Zhu 	if (!info)
412*93ab13d8SZiming Zhu 		return -ENOMEM;
413*93ab13d8SZiming Zhu 
414*93ab13d8SZiming Zhu 	return pmbus_do_probe(client, info);
415*93ab13d8SZiming Zhu }
416*93ab13d8SZiming Zhu 
417*93ab13d8SZiming Zhu static struct i2c_driver sq24860_driver = {
418*93ab13d8SZiming Zhu 	.driver = {
419*93ab13d8SZiming Zhu 		.name = "sq24860",
420*93ab13d8SZiming Zhu 		.of_match_table = sq24860_of_match,
421*93ab13d8SZiming Zhu 	},
422*93ab13d8SZiming Zhu 	.probe = sq24860_probe,
423*93ab13d8SZiming Zhu 	.id_table = sq24860_i2c_id,
424*93ab13d8SZiming Zhu };
425*93ab13d8SZiming Zhu module_i2c_driver(sq24860_driver);
426*93ab13d8SZiming Zhu 
427*93ab13d8SZiming Zhu MODULE_AUTHOR("Ziming Zhu <ziming.zhu@silergycorp.com>");
428*93ab13d8SZiming Zhu MODULE_DESCRIPTION("PMBUS driver for SQ24860 eFuse");
429*93ab13d8SZiming Zhu MODULE_LICENSE("GPL");
430*93ab13d8SZiming Zhu MODULE_IMPORT_NS("PMBUS");
431