xref: /linux/drivers/hwmon/max6621.c (revision 92b64580f14b24a3d5cfd1e9dff0b745826a824b)
1*92b64580SVadim Pasternak /*
2*92b64580SVadim Pasternak  * Hardware monitoring driver for Maxim MAX6621
3*92b64580SVadim Pasternak  *
4*92b64580SVadim Pasternak  * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
5*92b64580SVadim Pasternak  * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
6*92b64580SVadim Pasternak  *
7*92b64580SVadim Pasternak  * This program is free software; you can redistribute it and/or modify
8*92b64580SVadim Pasternak  * it under the terms of the GNU General Public License as published by
9*92b64580SVadim Pasternak  * the Free Software Foundation; either version 2 of the License, or
10*92b64580SVadim Pasternak  * (at your option) any later version.
11*92b64580SVadim Pasternak  *
12*92b64580SVadim Pasternak  * This program is distributed in the hope that it will be useful,
13*92b64580SVadim Pasternak  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*92b64580SVadim Pasternak  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*92b64580SVadim Pasternak  * GNU General Public License for more details.
16*92b64580SVadim Pasternak  */
17*92b64580SVadim Pasternak 
18*92b64580SVadim Pasternak #include <linux/bitops.h>
19*92b64580SVadim Pasternak #include <linux/hwmon.h>
20*92b64580SVadim Pasternak #include <linux/hwmon-sysfs.h>
21*92b64580SVadim Pasternak #include <linux/i2c.h>
22*92b64580SVadim Pasternak #include <linux/init.h>
23*92b64580SVadim Pasternak #include <linux/module.h>
24*92b64580SVadim Pasternak #include <linux/of_device.h>
25*92b64580SVadim Pasternak #include <linux/regmap.h>
26*92b64580SVadim Pasternak 
27*92b64580SVadim Pasternak #define MAX6621_DRV_NAME		"max6621"
28*92b64580SVadim Pasternak #define MAX6621_TEMP_INPUT_REG_NUM	9
29*92b64580SVadim Pasternak #define MAX6621_TEMP_INPUT_MIN		-127000
30*92b64580SVadim Pasternak #define MAX6621_TEMP_INPUT_MAX		128000
31*92b64580SVadim Pasternak #define MAX6621_TEMP_ALERT_CHAN_SHIFT	1
32*92b64580SVadim Pasternak 
33*92b64580SVadim Pasternak #define MAX6621_TEMP_S0D0_REG		0x00
34*92b64580SVadim Pasternak #define MAX6621_TEMP_S0D1_REG		0x01
35*92b64580SVadim Pasternak #define MAX6621_TEMP_S1D0_REG		0x02
36*92b64580SVadim Pasternak #define MAX6621_TEMP_S1D1_REG		0x03
37*92b64580SVadim Pasternak #define MAX6621_TEMP_S2D0_REG		0x04
38*92b64580SVadim Pasternak #define MAX6621_TEMP_S2D1_REG		0x05
39*92b64580SVadim Pasternak #define MAX6621_TEMP_S3D0_REG		0x06
40*92b64580SVadim Pasternak #define MAX6621_TEMP_S3D1_REG		0x07
41*92b64580SVadim Pasternak #define MAX6621_TEMP_MAX_REG		0x08
42*92b64580SVadim Pasternak #define MAX6621_TEMP_MAX_ADDR_REG	0x0a
43*92b64580SVadim Pasternak #define MAX6621_TEMP_ALERT_CAUSE_REG	0x0b
44*92b64580SVadim Pasternak #define MAX6621_CONFIG0_REG		0x0c
45*92b64580SVadim Pasternak #define MAX6621_CONFIG1_REG		0x0d
46*92b64580SVadim Pasternak #define MAX6621_CONFIG2_REG		0x0e
47*92b64580SVadim Pasternak #define MAX6621_CONFIG3_REG		0x0f
48*92b64580SVadim Pasternak #define MAX6621_TEMP_S0_ALERT_REG	0x10
49*92b64580SVadim Pasternak #define MAX6621_TEMP_S1_ALERT_REG	0x11
50*92b64580SVadim Pasternak #define MAX6621_TEMP_S2_ALERT_REG	0x12
51*92b64580SVadim Pasternak #define MAX6621_TEMP_S3_ALERT_REG	0x13
52*92b64580SVadim Pasternak #define MAX6621_CLEAR_ALERT_REG		0x15
53*92b64580SVadim Pasternak #define MAX6621_REG_MAX			(MAX6621_CLEAR_ALERT_REG + 1)
54*92b64580SVadim Pasternak #define MAX6621_REG_TEMP_SHIFT		0x06
55*92b64580SVadim Pasternak 
56*92b64580SVadim Pasternak #define MAX6621_ENABLE_TEMP_ALERTS_BIT	4
57*92b64580SVadim Pasternak #define MAX6621_ENABLE_I2C_CRC_BIT	5
58*92b64580SVadim Pasternak #define MAX6621_ENABLE_ALTERNATE_DATA	6
59*92b64580SVadim Pasternak #define MAX6621_ENABLE_LOCKUP_TO	7
60*92b64580SVadim Pasternak #define MAX6621_ENABLE_S0D0_BIT		8
61*92b64580SVadim Pasternak #define MAX6621_ENABLE_S3D1_BIT		15
62*92b64580SVadim Pasternak #define MAX6621_ENABLE_TEMP_ALL		GENMASK(MAX6621_ENABLE_S3D1_BIT, \
63*92b64580SVadim Pasternak 						MAX6621_ENABLE_S0D0_BIT)
64*92b64580SVadim Pasternak #define MAX6621_POLL_DELAY_MASK		0x5
65*92b64580SVadim Pasternak #define MAX6621_CONFIG0_INIT		(MAX6621_ENABLE_TEMP_ALL | \
66*92b64580SVadim Pasternak 					 BIT(MAX6621_ENABLE_LOCKUP_TO) | \
67*92b64580SVadim Pasternak 					 BIT(MAX6621_ENABLE_I2C_CRC_BIT) | \
68*92b64580SVadim Pasternak 					 MAX6621_POLL_DELAY_MASK)
69*92b64580SVadim Pasternak #define MAX6621_PECI_BIT_TIME		0x2
70*92b64580SVadim Pasternak #define MAX6621_PECI_RETRY_NUM		0x3
71*92b64580SVadim Pasternak #define MAX6621_CONFIG1_INIT		((MAX6621_PECI_BIT_TIME << 8) | \
72*92b64580SVadim Pasternak 					 MAX6621_PECI_RETRY_NUM)
73*92b64580SVadim Pasternak 
74*92b64580SVadim Pasternak /* Error codes */
75*92b64580SVadim Pasternak #define MAX6621_TRAN_FAILED	0x8100	/*
76*92b64580SVadim Pasternak 					 * PECI transaction failed for more
77*92b64580SVadim Pasternak 					 * than the configured number of
78*92b64580SVadim Pasternak 					 * consecutive retries.
79*92b64580SVadim Pasternak 					 */
80*92b64580SVadim Pasternak #define MAX6621_POOL_DIS	0x8101	/*
81*92b64580SVadim Pasternak 					 * Polling disabled for requested
82*92b64580SVadim Pasternak 					 * socket/domain.
83*92b64580SVadim Pasternak 					 */
84*92b64580SVadim Pasternak #define MAX6621_POOL_UNCOMPLETE	0x8102	/*
85*92b64580SVadim Pasternak 					 * First poll not yet completed for
86*92b64580SVadim Pasternak 					 * requested socket/domain (on
87*92b64580SVadim Pasternak 					 * startup).
88*92b64580SVadim Pasternak 					 */
89*92b64580SVadim Pasternak #define MAX6621_SD_DIS		0x8103	/*
90*92b64580SVadim Pasternak 					 * Read maximum temperature requested,
91*92b64580SVadim Pasternak 					 * but no sockets/domains enabled or
92*92b64580SVadim Pasternak 					 * all enabled sockets/domains have
93*92b64580SVadim Pasternak 					 * errors; or read maximum temperature
94*92b64580SVadim Pasternak 					 * address requested, but read maximum
95*92b64580SVadim Pasternak 					 * temperature was not called.
96*92b64580SVadim Pasternak 					 */
97*92b64580SVadim Pasternak #define MAX6621_ALERT_DIS	0x8104	/*
98*92b64580SVadim Pasternak 					 * Get alert socket/domain requested,
99*92b64580SVadim Pasternak 					 * but no alert active.
100*92b64580SVadim Pasternak 					 */
101*92b64580SVadim Pasternak #define MAX6621_PECI_ERR_MIN	0x8000	/* Intel spec PECI error min value. */
102*92b64580SVadim Pasternak #define MAX6621_PECI_ERR_MAX	0x80ff	/* Intel spec PECI error max value. */
103*92b64580SVadim Pasternak 
104*92b64580SVadim Pasternak static const u32 max6621_temp_regs[] = {
105*92b64580SVadim Pasternak 	MAX6621_TEMP_MAX_REG, MAX6621_TEMP_S0D0_REG, MAX6621_TEMP_S1D0_REG,
106*92b64580SVadim Pasternak 	MAX6621_TEMP_S2D0_REG, MAX6621_TEMP_S3D0_REG, MAX6621_TEMP_S0D1_REG,
107*92b64580SVadim Pasternak 	MAX6621_TEMP_S1D1_REG, MAX6621_TEMP_S2D1_REG, MAX6621_TEMP_S3D1_REG,
108*92b64580SVadim Pasternak };
109*92b64580SVadim Pasternak 
110*92b64580SVadim Pasternak static const char *const max6621_temp_labels[] = {
111*92b64580SVadim Pasternak 	"maximum",
112*92b64580SVadim Pasternak 	"socket0_0",
113*92b64580SVadim Pasternak 	"socket1_0",
114*92b64580SVadim Pasternak 	"socket2_0",
115*92b64580SVadim Pasternak 	"socket3_0",
116*92b64580SVadim Pasternak 	"socket0_1",
117*92b64580SVadim Pasternak 	"socket1_1",
118*92b64580SVadim Pasternak 	"socket2_1",
119*92b64580SVadim Pasternak 	"socket3_1",
120*92b64580SVadim Pasternak };
121*92b64580SVadim Pasternak 
122*92b64580SVadim Pasternak static const int max6621_temp_alert_chan2reg[] = {
123*92b64580SVadim Pasternak 	MAX6621_TEMP_S0_ALERT_REG,
124*92b64580SVadim Pasternak 	MAX6621_TEMP_S1_ALERT_REG,
125*92b64580SVadim Pasternak 	MAX6621_TEMP_S2_ALERT_REG,
126*92b64580SVadim Pasternak 	MAX6621_TEMP_S3_ALERT_REG,
127*92b64580SVadim Pasternak };
128*92b64580SVadim Pasternak 
129*92b64580SVadim Pasternak /**
130*92b64580SVadim Pasternak  * struct max6621_data - private data:
131*92b64580SVadim Pasternak  *
132*92b64580SVadim Pasternak  * @client: I2C client;
133*92b64580SVadim Pasternak  * @regmap: register map handle;
134*92b64580SVadim Pasternak  * @input_chan2reg: mapping from channel to register;
135*92b64580SVadim Pasternak  */
136*92b64580SVadim Pasternak struct max6621_data {
137*92b64580SVadim Pasternak 	struct i2c_client	*client;
138*92b64580SVadim Pasternak 	struct regmap		*regmap;
139*92b64580SVadim Pasternak 	int			input_chan2reg[MAX6621_TEMP_INPUT_REG_NUM + 1];
140*92b64580SVadim Pasternak };
141*92b64580SVadim Pasternak 
142*92b64580SVadim Pasternak static long max6621_temp_mc2reg(long val)
143*92b64580SVadim Pasternak {
144*92b64580SVadim Pasternak 	return (val / 1000L) << MAX6621_REG_TEMP_SHIFT;
145*92b64580SVadim Pasternak }
146*92b64580SVadim Pasternak 
147*92b64580SVadim Pasternak static umode_t
148*92b64580SVadim Pasternak max6621_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
149*92b64580SVadim Pasternak 		   int channel)
150*92b64580SVadim Pasternak {
151*92b64580SVadim Pasternak 	/* Skip channels which are not physically conncted. */
152*92b64580SVadim Pasternak 	if (((struct max6621_data *)data)->input_chan2reg[channel] < 0)
153*92b64580SVadim Pasternak 		return 0;
154*92b64580SVadim Pasternak 
155*92b64580SVadim Pasternak 	switch (type) {
156*92b64580SVadim Pasternak 	case hwmon_temp:
157*92b64580SVadim Pasternak 		switch (attr) {
158*92b64580SVadim Pasternak 		case hwmon_temp_input:
159*92b64580SVadim Pasternak 		case hwmon_temp_label:
160*92b64580SVadim Pasternak 		case hwmon_temp_crit_alarm:
161*92b64580SVadim Pasternak 			return 0444;
162*92b64580SVadim Pasternak 		case hwmon_temp_offset:
163*92b64580SVadim Pasternak 		case hwmon_temp_crit:
164*92b64580SVadim Pasternak 			return 0644;
165*92b64580SVadim Pasternak 		default:
166*92b64580SVadim Pasternak 			break;
167*92b64580SVadim Pasternak 		}
168*92b64580SVadim Pasternak 
169*92b64580SVadim Pasternak 	default:
170*92b64580SVadim Pasternak 		break;
171*92b64580SVadim Pasternak 	}
172*92b64580SVadim Pasternak 
173*92b64580SVadim Pasternak 	return 0;
174*92b64580SVadim Pasternak }
175*92b64580SVadim Pasternak 
176*92b64580SVadim Pasternak static int max6621_verify_reg_data(struct device *dev, int regval)
177*92b64580SVadim Pasternak {
178*92b64580SVadim Pasternak 	if (regval >= MAX6621_PECI_ERR_MIN &&
179*92b64580SVadim Pasternak 	    regval <= MAX6621_PECI_ERR_MAX) {
180*92b64580SVadim Pasternak 		dev_dbg(dev, "PECI error code - err 0x%04x.\n",
181*92b64580SVadim Pasternak 			regval);
182*92b64580SVadim Pasternak 
183*92b64580SVadim Pasternak 		return -EIO;
184*92b64580SVadim Pasternak 	}
185*92b64580SVadim Pasternak 
186*92b64580SVadim Pasternak 	switch (regval) {
187*92b64580SVadim Pasternak 	case MAX6621_TRAN_FAILED:
188*92b64580SVadim Pasternak 		dev_dbg(dev, "PECI transaction failed - err 0x%04x.\n",
189*92b64580SVadim Pasternak 			regval);
190*92b64580SVadim Pasternak 		return -EIO;
191*92b64580SVadim Pasternak 	case MAX6621_POOL_DIS:
192*92b64580SVadim Pasternak 		dev_dbg(dev, "Polling disabled - err 0x%04x.\n", regval);
193*92b64580SVadim Pasternak 		return -EOPNOTSUPP;
194*92b64580SVadim Pasternak 	case MAX6621_POOL_UNCOMPLETE:
195*92b64580SVadim Pasternak 		dev_dbg(dev, "First poll not completed on startup - err 0x%04x.\n",
196*92b64580SVadim Pasternak 			regval);
197*92b64580SVadim Pasternak 		return -EIO;
198*92b64580SVadim Pasternak 	case MAX6621_SD_DIS:
199*92b64580SVadim Pasternak 		dev_dbg(dev, "Resource is disabled - err 0x%04x.\n", regval);
200*92b64580SVadim Pasternak 		return -EOPNOTSUPP;
201*92b64580SVadim Pasternak 	case MAX6621_ALERT_DIS:
202*92b64580SVadim Pasternak 		dev_dbg(dev, "No alert active - err 0x%04x.\n", regval);
203*92b64580SVadim Pasternak 		return -EOPNOTSUPP;
204*92b64580SVadim Pasternak 	default:
205*92b64580SVadim Pasternak 		return 0;
206*92b64580SVadim Pasternak 	}
207*92b64580SVadim Pasternak }
208*92b64580SVadim Pasternak 
209*92b64580SVadim Pasternak static int
210*92b64580SVadim Pasternak max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
211*92b64580SVadim Pasternak 	     int channel, long *val)
212*92b64580SVadim Pasternak {
213*92b64580SVadim Pasternak 	struct max6621_data *data = dev_get_drvdata(dev);
214*92b64580SVadim Pasternak 	u32 regval;
215*92b64580SVadim Pasternak 	int reg;
216*92b64580SVadim Pasternak 	s8 temp;
217*92b64580SVadim Pasternak 	int ret;
218*92b64580SVadim Pasternak 
219*92b64580SVadim Pasternak 	switch (type) {
220*92b64580SVadim Pasternak 	case hwmon_temp:
221*92b64580SVadim Pasternak 		switch (attr) {
222*92b64580SVadim Pasternak 		case hwmon_temp_input:
223*92b64580SVadim Pasternak 			reg = data->input_chan2reg[channel];
224*92b64580SVadim Pasternak 			ret = regmap_read(data->regmap, reg, &regval);
225*92b64580SVadim Pasternak 			if (ret)
226*92b64580SVadim Pasternak 				return ret;
227*92b64580SVadim Pasternak 
228*92b64580SVadim Pasternak 			ret = max6621_verify_reg_data(dev, regval);
229*92b64580SVadim Pasternak 			if (ret)
230*92b64580SVadim Pasternak 				return ret;
231*92b64580SVadim Pasternak 
232*92b64580SVadim Pasternak 			/*
233*92b64580SVadim Pasternak 			 * Bit MAX6621_REG_TEMP_SHIFT represents 1 degree step.
234*92b64580SVadim Pasternak 			 * The temperature is given in two's complement and 8
235*92b64580SVadim Pasternak 			 * bits is used for the register conversion.
236*92b64580SVadim Pasternak 			 */
237*92b64580SVadim Pasternak 			temp = (regval >> MAX6621_REG_TEMP_SHIFT);
238*92b64580SVadim Pasternak 			*val = temp * 1000L;
239*92b64580SVadim Pasternak 
240*92b64580SVadim Pasternak 			break;
241*92b64580SVadim Pasternak 		case hwmon_temp_offset:
242*92b64580SVadim Pasternak 			ret = regmap_read(data->regmap, MAX6621_CONFIG2_REG,
243*92b64580SVadim Pasternak 					  &regval);
244*92b64580SVadim Pasternak 			if (ret)
245*92b64580SVadim Pasternak 				return ret;
246*92b64580SVadim Pasternak 
247*92b64580SVadim Pasternak 			ret = max6621_verify_reg_data(dev, regval);
248*92b64580SVadim Pasternak 			if (ret)
249*92b64580SVadim Pasternak 				return ret;
250*92b64580SVadim Pasternak 
251*92b64580SVadim Pasternak 			*val = (regval >> MAX6621_REG_TEMP_SHIFT) *
252*92b64580SVadim Pasternak 			       1000L;
253*92b64580SVadim Pasternak 
254*92b64580SVadim Pasternak 			break;
255*92b64580SVadim Pasternak 		case hwmon_temp_crit:
256*92b64580SVadim Pasternak 			channel -= MAX6621_TEMP_ALERT_CHAN_SHIFT;
257*92b64580SVadim Pasternak 			reg = max6621_temp_alert_chan2reg[channel];
258*92b64580SVadim Pasternak 			ret = regmap_read(data->regmap, reg, &regval);
259*92b64580SVadim Pasternak 			if (ret)
260*92b64580SVadim Pasternak 				return ret;
261*92b64580SVadim Pasternak 
262*92b64580SVadim Pasternak 			ret = max6621_verify_reg_data(dev, regval);
263*92b64580SVadim Pasternak 			if (ret)
264*92b64580SVadim Pasternak 				return ret;
265*92b64580SVadim Pasternak 
266*92b64580SVadim Pasternak 			*val = regval * 1000L;
267*92b64580SVadim Pasternak 
268*92b64580SVadim Pasternak 			break;
269*92b64580SVadim Pasternak 		case hwmon_temp_crit_alarm:
270*92b64580SVadim Pasternak 			/*
271*92b64580SVadim Pasternak 			 * Set val to zero to recover the case, when reading
272*92b64580SVadim Pasternak 			 * MAX6621_TEMP_ALERT_CAUSE_REG results in for example
273*92b64580SVadim Pasternak 			 * MAX6621_ALERT_DIS. Reading will return with error,
274*92b64580SVadim Pasternak 			 * but in such case alarm should be returned as 0.
275*92b64580SVadim Pasternak 			 */
276*92b64580SVadim Pasternak 			*val = 0;
277*92b64580SVadim Pasternak 			ret = regmap_read(data->regmap,
278*92b64580SVadim Pasternak 					  MAX6621_TEMP_ALERT_CAUSE_REG,
279*92b64580SVadim Pasternak 					  &regval);
280*92b64580SVadim Pasternak 			if (ret)
281*92b64580SVadim Pasternak 				return ret;
282*92b64580SVadim Pasternak 
283*92b64580SVadim Pasternak 			ret = max6621_verify_reg_data(dev, regval);
284*92b64580SVadim Pasternak 			if (ret) {
285*92b64580SVadim Pasternak 				/* Do not report error if alert is disabled. */
286*92b64580SVadim Pasternak 				if (regval == MAX6621_ALERT_DIS)
287*92b64580SVadim Pasternak 					return 0;
288*92b64580SVadim Pasternak 				else
289*92b64580SVadim Pasternak 					return ret;
290*92b64580SVadim Pasternak 			}
291*92b64580SVadim Pasternak 
292*92b64580SVadim Pasternak 			/*
293*92b64580SVadim Pasternak 			 * Clear the alert automatically, using send-byte
294*92b64580SVadim Pasternak 			 * smbus protocol for clearing alert.
295*92b64580SVadim Pasternak 			 */
296*92b64580SVadim Pasternak 			if (regval) {
297*92b64580SVadim Pasternak 				ret = i2c_smbus_write_byte(data->client,
298*92b64580SVadim Pasternak 						MAX6621_CLEAR_ALERT_REG);
299*92b64580SVadim Pasternak 				if (!ret)
300*92b64580SVadim Pasternak 					return ret;
301*92b64580SVadim Pasternak 			}
302*92b64580SVadim Pasternak 
303*92b64580SVadim Pasternak 			*val = !!regval;
304*92b64580SVadim Pasternak 
305*92b64580SVadim Pasternak 			break;
306*92b64580SVadim Pasternak 		default:
307*92b64580SVadim Pasternak 			return -EOPNOTSUPP;
308*92b64580SVadim Pasternak 		}
309*92b64580SVadim Pasternak 		break;
310*92b64580SVadim Pasternak 
311*92b64580SVadim Pasternak 	default:
312*92b64580SVadim Pasternak 		return -EOPNOTSUPP;
313*92b64580SVadim Pasternak 	}
314*92b64580SVadim Pasternak 
315*92b64580SVadim Pasternak 	return 0;
316*92b64580SVadim Pasternak }
317*92b64580SVadim Pasternak 
318*92b64580SVadim Pasternak static int
319*92b64580SVadim Pasternak max6621_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
320*92b64580SVadim Pasternak 	      int channel, long val)
321*92b64580SVadim Pasternak {
322*92b64580SVadim Pasternak 	struct max6621_data *data = dev_get_drvdata(dev);
323*92b64580SVadim Pasternak 	u32 reg;
324*92b64580SVadim Pasternak 
325*92b64580SVadim Pasternak 	switch (type) {
326*92b64580SVadim Pasternak 	case hwmon_temp:
327*92b64580SVadim Pasternak 		switch (attr) {
328*92b64580SVadim Pasternak 		case hwmon_temp_offset:
329*92b64580SVadim Pasternak 			/* Clamp to allowed range to prevent overflow. */
330*92b64580SVadim Pasternak 			val = clamp_val(val, MAX6621_TEMP_INPUT_MIN,
331*92b64580SVadim Pasternak 					MAX6621_TEMP_INPUT_MAX);
332*92b64580SVadim Pasternak 			val = max6621_temp_mc2reg(val);
333*92b64580SVadim Pasternak 
334*92b64580SVadim Pasternak 			return regmap_write(data->regmap,
335*92b64580SVadim Pasternak 					    MAX6621_CONFIG2_REG, val);
336*92b64580SVadim Pasternak 		case hwmon_temp_crit:
337*92b64580SVadim Pasternak 			channel -= MAX6621_TEMP_ALERT_CHAN_SHIFT;
338*92b64580SVadim Pasternak 			reg = max6621_temp_alert_chan2reg[channel];
339*92b64580SVadim Pasternak 			/* Clamp to allowed range to prevent overflow. */
340*92b64580SVadim Pasternak 			val = clamp_val(val, MAX6621_TEMP_INPUT_MIN,
341*92b64580SVadim Pasternak 					MAX6621_TEMP_INPUT_MAX);
342*92b64580SVadim Pasternak 			val = val / 1000L;
343*92b64580SVadim Pasternak 
344*92b64580SVadim Pasternak 			return regmap_write(data->regmap, reg, val);
345*92b64580SVadim Pasternak 		default:
346*92b64580SVadim Pasternak 			return -EOPNOTSUPP;
347*92b64580SVadim Pasternak 		}
348*92b64580SVadim Pasternak 		break;
349*92b64580SVadim Pasternak 
350*92b64580SVadim Pasternak 	default:
351*92b64580SVadim Pasternak 		return -EOPNOTSUPP;
352*92b64580SVadim Pasternak 	}
353*92b64580SVadim Pasternak 
354*92b64580SVadim Pasternak 	return -EOPNOTSUPP;
355*92b64580SVadim Pasternak }
356*92b64580SVadim Pasternak 
357*92b64580SVadim Pasternak static int
358*92b64580SVadim Pasternak max6621_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
359*92b64580SVadim Pasternak 		    int channel, const char **str)
360*92b64580SVadim Pasternak {
361*92b64580SVadim Pasternak 	switch (type) {
362*92b64580SVadim Pasternak 	case hwmon_temp:
363*92b64580SVadim Pasternak 		switch (attr) {
364*92b64580SVadim Pasternak 		case hwmon_temp_label:
365*92b64580SVadim Pasternak 			*str = max6621_temp_labels[channel];
366*92b64580SVadim Pasternak 			return 0;
367*92b64580SVadim Pasternak 		default:
368*92b64580SVadim Pasternak 			return -EOPNOTSUPP;
369*92b64580SVadim Pasternak 		}
370*92b64580SVadim Pasternak 		break;
371*92b64580SVadim Pasternak 	default:
372*92b64580SVadim Pasternak 		return -EOPNOTSUPP;
373*92b64580SVadim Pasternak 	}
374*92b64580SVadim Pasternak 
375*92b64580SVadim Pasternak 	return -EOPNOTSUPP;
376*92b64580SVadim Pasternak }
377*92b64580SVadim Pasternak 
378*92b64580SVadim Pasternak static bool max6621_writeable_reg(struct device *dev, unsigned int reg)
379*92b64580SVadim Pasternak {
380*92b64580SVadim Pasternak 	switch (reg) {
381*92b64580SVadim Pasternak 	case MAX6621_CONFIG0_REG:
382*92b64580SVadim Pasternak 	case MAX6621_CONFIG1_REG:
383*92b64580SVadim Pasternak 	case MAX6621_CONFIG2_REG:
384*92b64580SVadim Pasternak 	case MAX6621_CONFIG3_REG:
385*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0_ALERT_REG:
386*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1_ALERT_REG:
387*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2_ALERT_REG:
388*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3_ALERT_REG:
389*92b64580SVadim Pasternak 	case MAX6621_TEMP_ALERT_CAUSE_REG:
390*92b64580SVadim Pasternak 		return true;
391*92b64580SVadim Pasternak 	}
392*92b64580SVadim Pasternak 	return false;
393*92b64580SVadim Pasternak }
394*92b64580SVadim Pasternak 
395*92b64580SVadim Pasternak static bool max6621_readable_reg(struct device *dev, unsigned int reg)
396*92b64580SVadim Pasternak {
397*92b64580SVadim Pasternak 	switch (reg) {
398*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0D0_REG:
399*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0D1_REG:
400*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1D0_REG:
401*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1D1_REG:
402*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2D0_REG:
403*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2D1_REG:
404*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3D0_REG:
405*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3D1_REG:
406*92b64580SVadim Pasternak 	case MAX6621_TEMP_MAX_REG:
407*92b64580SVadim Pasternak 	case MAX6621_TEMP_MAX_ADDR_REG:
408*92b64580SVadim Pasternak 	case MAX6621_CONFIG0_REG:
409*92b64580SVadim Pasternak 	case MAX6621_CONFIG1_REG:
410*92b64580SVadim Pasternak 	case MAX6621_CONFIG2_REG:
411*92b64580SVadim Pasternak 	case MAX6621_CONFIG3_REG:
412*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0_ALERT_REG:
413*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1_ALERT_REG:
414*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2_ALERT_REG:
415*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3_ALERT_REG:
416*92b64580SVadim Pasternak 		return true;
417*92b64580SVadim Pasternak 	}
418*92b64580SVadim Pasternak 	return false;
419*92b64580SVadim Pasternak }
420*92b64580SVadim Pasternak 
421*92b64580SVadim Pasternak static bool max6621_volatile_reg(struct device *dev, unsigned int reg)
422*92b64580SVadim Pasternak {
423*92b64580SVadim Pasternak 	switch (reg) {
424*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0D0_REG:
425*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0D1_REG:
426*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1D0_REG:
427*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1D1_REG:
428*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2D0_REG:
429*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2D1_REG:
430*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3D0_REG:
431*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3D1_REG:
432*92b64580SVadim Pasternak 	case MAX6621_TEMP_MAX_REG:
433*92b64580SVadim Pasternak 	case MAX6621_TEMP_S0_ALERT_REG:
434*92b64580SVadim Pasternak 	case MAX6621_TEMP_S1_ALERT_REG:
435*92b64580SVadim Pasternak 	case MAX6621_TEMP_S2_ALERT_REG:
436*92b64580SVadim Pasternak 	case MAX6621_TEMP_S3_ALERT_REG:
437*92b64580SVadim Pasternak 	case MAX6621_TEMP_ALERT_CAUSE_REG:
438*92b64580SVadim Pasternak 		return true;
439*92b64580SVadim Pasternak 	}
440*92b64580SVadim Pasternak 	return false;
441*92b64580SVadim Pasternak }
442*92b64580SVadim Pasternak 
443*92b64580SVadim Pasternak static const struct reg_default max6621_regmap_default[] = {
444*92b64580SVadim Pasternak 	{ MAX6621_CONFIG0_REG, MAX6621_CONFIG0_INIT },
445*92b64580SVadim Pasternak 	{ MAX6621_CONFIG1_REG, MAX6621_CONFIG1_INIT },
446*92b64580SVadim Pasternak };
447*92b64580SVadim Pasternak 
448*92b64580SVadim Pasternak static const struct regmap_config max6621_regmap_config = {
449*92b64580SVadim Pasternak 	.reg_bits = 8,
450*92b64580SVadim Pasternak 	.val_bits = 16,
451*92b64580SVadim Pasternak 	.max_register = MAX6621_REG_MAX,
452*92b64580SVadim Pasternak 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
453*92b64580SVadim Pasternak 	.cache_type = REGCACHE_FLAT,
454*92b64580SVadim Pasternak 	.writeable_reg = max6621_writeable_reg,
455*92b64580SVadim Pasternak 	.readable_reg = max6621_readable_reg,
456*92b64580SVadim Pasternak 	.volatile_reg = max6621_volatile_reg,
457*92b64580SVadim Pasternak 	.reg_defaults = max6621_regmap_default,
458*92b64580SVadim Pasternak 	.num_reg_defaults = ARRAY_SIZE(max6621_regmap_default),
459*92b64580SVadim Pasternak };
460*92b64580SVadim Pasternak 
461*92b64580SVadim Pasternak static u32 max6621_chip_config[] = {
462*92b64580SVadim Pasternak 	HWMON_C_REGISTER_TZ,
463*92b64580SVadim Pasternak 	0
464*92b64580SVadim Pasternak };
465*92b64580SVadim Pasternak 
466*92b64580SVadim Pasternak static const struct hwmon_channel_info max6621_chip = {
467*92b64580SVadim Pasternak 	.type = hwmon_chip,
468*92b64580SVadim Pasternak 	.config = max6621_chip_config,
469*92b64580SVadim Pasternak };
470*92b64580SVadim Pasternak 
471*92b64580SVadim Pasternak static const u32 max6621_temp_config[] = {
472*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
473*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
474*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
475*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
476*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
477*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_LABEL,
478*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_LABEL,
479*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_LABEL,
480*92b64580SVadim Pasternak 	HWMON_T_INPUT | HWMON_T_LABEL,
481*92b64580SVadim Pasternak 	0
482*92b64580SVadim Pasternak };
483*92b64580SVadim Pasternak 
484*92b64580SVadim Pasternak static const struct hwmon_channel_info max6621_temp = {
485*92b64580SVadim Pasternak 	.type = hwmon_temp,
486*92b64580SVadim Pasternak 	.config = max6621_temp_config,
487*92b64580SVadim Pasternak };
488*92b64580SVadim Pasternak 
489*92b64580SVadim Pasternak static const struct hwmon_channel_info *max6621_info[] = {
490*92b64580SVadim Pasternak 	&max6621_chip,
491*92b64580SVadim Pasternak 	&max6621_temp,
492*92b64580SVadim Pasternak 	NULL
493*92b64580SVadim Pasternak };
494*92b64580SVadim Pasternak 
495*92b64580SVadim Pasternak static const struct hwmon_ops max6621_hwmon_ops = {
496*92b64580SVadim Pasternak 	.read = max6621_read,
497*92b64580SVadim Pasternak 	.write = max6621_write,
498*92b64580SVadim Pasternak 	.read_string = max6621_read_string,
499*92b64580SVadim Pasternak 	.is_visible = max6621_is_visible,
500*92b64580SVadim Pasternak };
501*92b64580SVadim Pasternak 
502*92b64580SVadim Pasternak static const struct hwmon_chip_info max6621_chip_info = {
503*92b64580SVadim Pasternak 	.ops = &max6621_hwmon_ops,
504*92b64580SVadim Pasternak 	.info = max6621_info,
505*92b64580SVadim Pasternak };
506*92b64580SVadim Pasternak 
507*92b64580SVadim Pasternak static int max6621_probe(struct i2c_client *client,
508*92b64580SVadim Pasternak 			 const struct i2c_device_id *id)
509*92b64580SVadim Pasternak {
510*92b64580SVadim Pasternak 	struct device *dev = &client->dev;
511*92b64580SVadim Pasternak 	struct max6621_data *data;
512*92b64580SVadim Pasternak 	struct device *hwmon_dev;
513*92b64580SVadim Pasternak 	int i;
514*92b64580SVadim Pasternak 	int ret;
515*92b64580SVadim Pasternak 
516*92b64580SVadim Pasternak 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
517*92b64580SVadim Pasternak 	if (!data)
518*92b64580SVadim Pasternak 		return -ENOMEM;
519*92b64580SVadim Pasternak 
520*92b64580SVadim Pasternak 	data->regmap = devm_regmap_init_i2c(client, &max6621_regmap_config);
521*92b64580SVadim Pasternak 	if (IS_ERR(data->regmap))
522*92b64580SVadim Pasternak 		return PTR_ERR(data->regmap);
523*92b64580SVadim Pasternak 
524*92b64580SVadim Pasternak 	i2c_set_clientdata(client, data);
525*92b64580SVadim Pasternak 	data->client = client;
526*92b64580SVadim Pasternak 
527*92b64580SVadim Pasternak 	/* Set CONFIG0 register masking temperature alerts and PEC. */
528*92b64580SVadim Pasternak 	ret = regmap_write(data->regmap, MAX6621_CONFIG0_REG,
529*92b64580SVadim Pasternak 			   MAX6621_CONFIG0_INIT);
530*92b64580SVadim Pasternak 	if (ret)
531*92b64580SVadim Pasternak 		return ret;
532*92b64580SVadim Pasternak 
533*92b64580SVadim Pasternak 	/* Set CONFIG1 register for PEC access retry number. */
534*92b64580SVadim Pasternak 	ret = regmap_write(data->regmap, MAX6621_CONFIG1_REG,
535*92b64580SVadim Pasternak 			   MAX6621_CONFIG1_INIT);
536*92b64580SVadim Pasternak 	if (ret)
537*92b64580SVadim Pasternak 		return ret;
538*92b64580SVadim Pasternak 
539*92b64580SVadim Pasternak 	/* Sync registers with hardware. */
540*92b64580SVadim Pasternak 	regcache_mark_dirty(data->regmap);
541*92b64580SVadim Pasternak 	ret = regcache_sync(data->regmap);
542*92b64580SVadim Pasternak 	if (ret)
543*92b64580SVadim Pasternak 		return ret;
544*92b64580SVadim Pasternak 
545*92b64580SVadim Pasternak 	/* Verify which temperature input registers are enabled. */
546*92b64580SVadim Pasternak 	for (i = 0; i < MAX6621_TEMP_INPUT_REG_NUM; i++) {
547*92b64580SVadim Pasternak 		ret = i2c_smbus_read_word_data(client, max6621_temp_regs[i]);
548*92b64580SVadim Pasternak 		if (ret < 0)
549*92b64580SVadim Pasternak 			return ret;
550*92b64580SVadim Pasternak 		ret = max6621_verify_reg_data(dev, ret);
551*92b64580SVadim Pasternak 		if (ret) {
552*92b64580SVadim Pasternak 			data->input_chan2reg[i] = -1;
553*92b64580SVadim Pasternak 			continue;
554*92b64580SVadim Pasternak 		}
555*92b64580SVadim Pasternak 
556*92b64580SVadim Pasternak 		data->input_chan2reg[i] = max6621_temp_regs[i];
557*92b64580SVadim Pasternak 	}
558*92b64580SVadim Pasternak 
559*92b64580SVadim Pasternak 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
560*92b64580SVadim Pasternak 							 data,
561*92b64580SVadim Pasternak 							 &max6621_chip_info,
562*92b64580SVadim Pasternak 							 NULL);
563*92b64580SVadim Pasternak 
564*92b64580SVadim Pasternak 	return PTR_ERR_OR_ZERO(hwmon_dev);
565*92b64580SVadim Pasternak }
566*92b64580SVadim Pasternak 
567*92b64580SVadim Pasternak static const struct i2c_device_id max6621_id[] = {
568*92b64580SVadim Pasternak 	{ MAX6621_DRV_NAME, 0 },
569*92b64580SVadim Pasternak 	{ }
570*92b64580SVadim Pasternak };
571*92b64580SVadim Pasternak MODULE_DEVICE_TABLE(i2c, max6621_id);
572*92b64580SVadim Pasternak 
573*92b64580SVadim Pasternak static const struct of_device_id max6621_of_match[] = {
574*92b64580SVadim Pasternak 	{ .compatible = "maxim,max6621" },
575*92b64580SVadim Pasternak 	{ }
576*92b64580SVadim Pasternak };
577*92b64580SVadim Pasternak MODULE_DEVICE_TABLE(of, max6621_of_match);
578*92b64580SVadim Pasternak 
579*92b64580SVadim Pasternak static struct i2c_driver max6621_driver = {
580*92b64580SVadim Pasternak 	.class		= I2C_CLASS_HWMON,
581*92b64580SVadim Pasternak 	.driver = {
582*92b64580SVadim Pasternak 		.name = MAX6621_DRV_NAME,
583*92b64580SVadim Pasternak 		.of_match_table = of_match_ptr(max6621_of_match),
584*92b64580SVadim Pasternak 	},
585*92b64580SVadim Pasternak 	.probe		= max6621_probe,
586*92b64580SVadim Pasternak 	.id_table	= max6621_id,
587*92b64580SVadim Pasternak };
588*92b64580SVadim Pasternak 
589*92b64580SVadim Pasternak module_i2c_driver(max6621_driver);
590*92b64580SVadim Pasternak 
591*92b64580SVadim Pasternak MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
592*92b64580SVadim Pasternak MODULE_DESCRIPTION("Driver for Maxim MAX6621");
593*92b64580SVadim Pasternak MODULE_LICENSE("GPL");
594