xref: /linux/drivers/iio/magnetometer/si7210.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
1*15dbaed4SAntoni Pokusinski // SPDX-License-Identifier: GPL-2.0
2*15dbaed4SAntoni Pokusinski /*
3*15dbaed4SAntoni Pokusinski  * Silicon Labs Si7210 Hall Effect sensor driver
4*15dbaed4SAntoni Pokusinski  *
5*15dbaed4SAntoni Pokusinski  * Copyright (c) 2024 Antoni Pokusinski <apokusinski01@gmail.com>
6*15dbaed4SAntoni Pokusinski  *
7*15dbaed4SAntoni Pokusinski  * Datasheet:
8*15dbaed4SAntoni Pokusinski  *  https://www.silabs.com/documents/public/data-sheets/si7210-datasheet.pdf
9*15dbaed4SAntoni Pokusinski  */
10*15dbaed4SAntoni Pokusinski 
11*15dbaed4SAntoni Pokusinski #include <linux/array_size.h>
12*15dbaed4SAntoni Pokusinski #include <linux/bitfield.h>
13*15dbaed4SAntoni Pokusinski #include <linux/bits.h>
14*15dbaed4SAntoni Pokusinski #include <linux/cleanup.h>
15*15dbaed4SAntoni Pokusinski #include <linux/err.h>
16*15dbaed4SAntoni Pokusinski #include <linux/i2c.h>
17*15dbaed4SAntoni Pokusinski #include <linux/iio/iio.h>
18*15dbaed4SAntoni Pokusinski #include <linux/math64.h>
19*15dbaed4SAntoni Pokusinski #include <linux/mod_devicetable.h>
20*15dbaed4SAntoni Pokusinski #include <linux/mutex.h>
21*15dbaed4SAntoni Pokusinski #include <linux/regmap.h>
22*15dbaed4SAntoni Pokusinski #include <linux/regulator/consumer.h>
23*15dbaed4SAntoni Pokusinski #include <linux/types.h>
24*15dbaed4SAntoni Pokusinski #include <linux/units.h>
25*15dbaed4SAntoni Pokusinski #include <asm/byteorder.h>
26*15dbaed4SAntoni Pokusinski 
27*15dbaed4SAntoni Pokusinski /* Registers offsets and masks */
28*15dbaed4SAntoni Pokusinski #define SI7210_REG_DSPSIGM	0xC1
29*15dbaed4SAntoni Pokusinski #define SI7210_REG_DSPSIGL	0xC2
30*15dbaed4SAntoni Pokusinski 
31*15dbaed4SAntoni Pokusinski #define SI7210_MASK_DSPSIGSEL	GENMASK(2, 0)
32*15dbaed4SAntoni Pokusinski #define SI7210_REG_DSPSIGSEL	0xC3
33*15dbaed4SAntoni Pokusinski 
34*15dbaed4SAntoni Pokusinski #define SI7210_MASK_STOP	BIT(1)
35*15dbaed4SAntoni Pokusinski #define SI7210_MASK_ONEBURST	BIT(2)
36*15dbaed4SAntoni Pokusinski #define SI7210_REG_POWER_CTRL	0xC4
37*15dbaed4SAntoni Pokusinski 
38*15dbaed4SAntoni Pokusinski #define SI7210_MASK_ARAUTOINC	BIT(0)
39*15dbaed4SAntoni Pokusinski #define SI7210_REG_ARAUTOINC	0xC5
40*15dbaed4SAntoni Pokusinski 
41*15dbaed4SAntoni Pokusinski #define SI7210_REG_A0		0xCA
42*15dbaed4SAntoni Pokusinski #define SI7210_REG_A1		0xCB
43*15dbaed4SAntoni Pokusinski #define SI7210_REG_A2		0xCC
44*15dbaed4SAntoni Pokusinski #define SI7210_REG_A3		0xCE
45*15dbaed4SAntoni Pokusinski #define SI7210_REG_A4		0xCF
46*15dbaed4SAntoni Pokusinski #define SI7210_REG_A5		0xD0
47*15dbaed4SAntoni Pokusinski 
48*15dbaed4SAntoni Pokusinski #define SI7210_REG_OTP_ADDR	0xE1
49*15dbaed4SAntoni Pokusinski #define SI7210_REG_OTP_DATA	0xE2
50*15dbaed4SAntoni Pokusinski 
51*15dbaed4SAntoni Pokusinski #define SI7210_MASK_OTP_READ_EN	BIT(1)
52*15dbaed4SAntoni Pokusinski #define SI7210_REG_OTP_CTRL	0xE3
53*15dbaed4SAntoni Pokusinski 
54*15dbaed4SAntoni Pokusinski /* OTP data registers offsets */
55*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_TMP_OFF	0x1D
56*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_TMP_GAIN	0x1E
57*15dbaed4SAntoni Pokusinski 
58*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A0_20	0x21
59*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A1_20	0x22
60*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A2_20	0x23
61*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A3_20	0x24
62*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A4_20	0x25
63*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A5_20	0x26
64*15dbaed4SAntoni Pokusinski 
65*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A0_200	0x27
66*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A1_200	0x28
67*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A2_200	0x29
68*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A3_200	0x2A
69*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A4_200	0x2B
70*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A5_200	0x2C
71*15dbaed4SAntoni Pokusinski 
72*15dbaed4SAntoni Pokusinski #define A_REGS_COUNT 6
73*15dbaed4SAntoni Pokusinski 
74*15dbaed4SAntoni Pokusinski static const unsigned int a20_otp_regs[A_REGS_COUNT] = {
75*15dbaed4SAntoni Pokusinski 	SI7210_OTPREG_A0_20, SI7210_OTPREG_A1_20, SI7210_OTPREG_A2_20,
76*15dbaed4SAntoni Pokusinski 	SI7210_OTPREG_A3_20, SI7210_OTPREG_A4_20, SI7210_OTPREG_A5_20,
77*15dbaed4SAntoni Pokusinski };
78*15dbaed4SAntoni Pokusinski 
79*15dbaed4SAntoni Pokusinski static const unsigned int a200_otp_regs[A_REGS_COUNT] = {
80*15dbaed4SAntoni Pokusinski 	SI7210_OTPREG_A0_200, SI7210_OTPREG_A1_200, SI7210_OTPREG_A2_200,
81*15dbaed4SAntoni Pokusinski 	SI7210_OTPREG_A3_200, SI7210_OTPREG_A4_200, SI7210_OTPREG_A5_200,
82*15dbaed4SAntoni Pokusinski };
83*15dbaed4SAntoni Pokusinski 
84*15dbaed4SAntoni Pokusinski static const struct regmap_range si7210_read_reg_ranges[] = {
85*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_DSPSIGM, SI7210_REG_ARAUTOINC),
86*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_A0, SI7210_REG_A2),
87*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_A3, SI7210_REG_A5),
88*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_OTP_ADDR, SI7210_REG_OTP_CTRL),
89*15dbaed4SAntoni Pokusinski };
90*15dbaed4SAntoni Pokusinski 
91*15dbaed4SAntoni Pokusinski static const struct regmap_access_table si7210_readable_regs = {
92*15dbaed4SAntoni Pokusinski 	.yes_ranges = si7210_read_reg_ranges,
93*15dbaed4SAntoni Pokusinski 	.n_yes_ranges = ARRAY_SIZE(si7210_read_reg_ranges),
94*15dbaed4SAntoni Pokusinski };
95*15dbaed4SAntoni Pokusinski 
96*15dbaed4SAntoni Pokusinski static const struct regmap_range si7210_write_reg_ranges[] = {
97*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_DSPSIGSEL, SI7210_REG_ARAUTOINC),
98*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_A0, SI7210_REG_A2),
99*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_A3, SI7210_REG_A5),
100*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_OTP_ADDR, SI7210_REG_OTP_CTRL),
101*15dbaed4SAntoni Pokusinski };
102*15dbaed4SAntoni Pokusinski 
103*15dbaed4SAntoni Pokusinski static const struct regmap_access_table si7210_writeable_regs = {
104*15dbaed4SAntoni Pokusinski 	.yes_ranges = si7210_write_reg_ranges,
105*15dbaed4SAntoni Pokusinski 	.n_yes_ranges = ARRAY_SIZE(si7210_write_reg_ranges),
106*15dbaed4SAntoni Pokusinski };
107*15dbaed4SAntoni Pokusinski 
108*15dbaed4SAntoni Pokusinski static const struct regmap_range si7210_volatile_reg_ranges[] = {
109*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_DSPSIGM, SI7210_REG_DSPSIGL),
110*15dbaed4SAntoni Pokusinski 	regmap_reg_range(SI7210_REG_POWER_CTRL, SI7210_REG_POWER_CTRL),
111*15dbaed4SAntoni Pokusinski };
112*15dbaed4SAntoni Pokusinski 
113*15dbaed4SAntoni Pokusinski static const struct regmap_access_table si7210_volatile_regs = {
114*15dbaed4SAntoni Pokusinski 	.yes_ranges = si7210_volatile_reg_ranges,
115*15dbaed4SAntoni Pokusinski 	.n_yes_ranges = ARRAY_SIZE(si7210_volatile_reg_ranges),
116*15dbaed4SAntoni Pokusinski };
117*15dbaed4SAntoni Pokusinski 
118*15dbaed4SAntoni Pokusinski static const struct regmap_config si7210_regmap_conf = {
119*15dbaed4SAntoni Pokusinski 	.reg_bits = 8,
120*15dbaed4SAntoni Pokusinski 	.val_bits = 8,
121*15dbaed4SAntoni Pokusinski 	.max_register = SI7210_REG_OTP_CTRL,
122*15dbaed4SAntoni Pokusinski 
123*15dbaed4SAntoni Pokusinski 	.rd_table = &si7210_readable_regs,
124*15dbaed4SAntoni Pokusinski 	.wr_table = &si7210_writeable_regs,
125*15dbaed4SAntoni Pokusinski 	.volatile_table = &si7210_volatile_regs,
126*15dbaed4SAntoni Pokusinski };
127*15dbaed4SAntoni Pokusinski 
128*15dbaed4SAntoni Pokusinski struct si7210_data {
129*15dbaed4SAntoni Pokusinski 	struct regmap *regmap;
130*15dbaed4SAntoni Pokusinski 	struct i2c_client *client;
131*15dbaed4SAntoni Pokusinski 	struct regulator *vdd;
132*15dbaed4SAntoni Pokusinski 	struct mutex fetch_lock; /* lock for a single measurement fetch */
133*15dbaed4SAntoni Pokusinski 	s8 temp_offset;
134*15dbaed4SAntoni Pokusinski 	s8 temp_gain;
135*15dbaed4SAntoni Pokusinski 	s8 scale_20_a[A_REGS_COUNT];
136*15dbaed4SAntoni Pokusinski 	s8 scale_200_a[A_REGS_COUNT];
137*15dbaed4SAntoni Pokusinski 	u8 curr_scale;
138*15dbaed4SAntoni Pokusinski };
139*15dbaed4SAntoni Pokusinski 
140*15dbaed4SAntoni Pokusinski static const struct iio_chan_spec si7210_channels[] = {
141*15dbaed4SAntoni Pokusinski 	{
142*15dbaed4SAntoni Pokusinski 		.type = IIO_MAGN,
143*15dbaed4SAntoni Pokusinski 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
144*15dbaed4SAntoni Pokusinski 			BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
145*15dbaed4SAntoni Pokusinski 	}, {
146*15dbaed4SAntoni Pokusinski 		.type = IIO_TEMP,
147*15dbaed4SAntoni Pokusinski 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
148*15dbaed4SAntoni Pokusinski 	},
149*15dbaed4SAntoni Pokusinski };
150*15dbaed4SAntoni Pokusinski 
151*15dbaed4SAntoni Pokusinski static int si7210_fetch_measurement(struct si7210_data *data,
152*15dbaed4SAntoni Pokusinski 				    struct iio_chan_spec const *chan,
153*15dbaed4SAntoni Pokusinski 				    u16 *buf)
154*15dbaed4SAntoni Pokusinski {
155*15dbaed4SAntoni Pokusinski 	u8 dspsigsel = chan->type == IIO_MAGN ? 0 : 1;
156*15dbaed4SAntoni Pokusinski 	int ret;
157*15dbaed4SAntoni Pokusinski 	__be16 result;
158*15dbaed4SAntoni Pokusinski 
159*15dbaed4SAntoni Pokusinski 	guard(mutex)(&data->fetch_lock);
160*15dbaed4SAntoni Pokusinski 
161*15dbaed4SAntoni Pokusinski 	ret = regmap_update_bits(data->regmap, SI7210_REG_DSPSIGSEL,
162*15dbaed4SAntoni Pokusinski 				 SI7210_MASK_DSPSIGSEL, dspsigsel);
163*15dbaed4SAntoni Pokusinski 	if (ret)
164*15dbaed4SAntoni Pokusinski 		return ret;
165*15dbaed4SAntoni Pokusinski 
166*15dbaed4SAntoni Pokusinski 	ret = regmap_update_bits(data->regmap, SI7210_REG_POWER_CTRL,
167*15dbaed4SAntoni Pokusinski 				 SI7210_MASK_ONEBURST | SI7210_MASK_STOP,
168*15dbaed4SAntoni Pokusinski 				 SI7210_MASK_ONEBURST & ~SI7210_MASK_STOP);
169*15dbaed4SAntoni Pokusinski 	if (ret)
170*15dbaed4SAntoni Pokusinski 		return ret;
171*15dbaed4SAntoni Pokusinski 
172*15dbaed4SAntoni Pokusinski 	/*
173*15dbaed4SAntoni Pokusinski 	 * Read the contents of the
174*15dbaed4SAntoni Pokusinski 	 * registers containing the result: DSPSIGM, DSPSIGL
175*15dbaed4SAntoni Pokusinski 	 */
176*15dbaed4SAntoni Pokusinski 	ret = regmap_bulk_read(data->regmap, SI7210_REG_DSPSIGM,
177*15dbaed4SAntoni Pokusinski 			       &result, sizeof(result));
178*15dbaed4SAntoni Pokusinski 	if (ret)
179*15dbaed4SAntoni Pokusinski 		return ret;
180*15dbaed4SAntoni Pokusinski 
181*15dbaed4SAntoni Pokusinski 	*buf = be16_to_cpu(result);
182*15dbaed4SAntoni Pokusinski 
183*15dbaed4SAntoni Pokusinski 	return 0;
184*15dbaed4SAntoni Pokusinski }
185*15dbaed4SAntoni Pokusinski 
186*15dbaed4SAntoni Pokusinski static int si7210_read_raw(struct iio_dev *indio_dev,
187*15dbaed4SAntoni Pokusinski 			   struct iio_chan_spec const *chan,
188*15dbaed4SAntoni Pokusinski 			   int *val, int *val2, long mask)
189*15dbaed4SAntoni Pokusinski {
190*15dbaed4SAntoni Pokusinski 	struct si7210_data *data = iio_priv(indio_dev);
191*15dbaed4SAntoni Pokusinski 	long long temp;
192*15dbaed4SAntoni Pokusinski 	u16 dspsig;
193*15dbaed4SAntoni Pokusinski 	int ret;
194*15dbaed4SAntoni Pokusinski 
195*15dbaed4SAntoni Pokusinski 	switch (mask) {
196*15dbaed4SAntoni Pokusinski 	case IIO_CHAN_INFO_RAW:
197*15dbaed4SAntoni Pokusinski 		ret = si7210_fetch_measurement(data, chan, &dspsig);
198*15dbaed4SAntoni Pokusinski 		if (ret)
199*15dbaed4SAntoni Pokusinski 			return ret;
200*15dbaed4SAntoni Pokusinski 
201*15dbaed4SAntoni Pokusinski 		*val = dspsig & GENMASK(14, 0);
202*15dbaed4SAntoni Pokusinski 		return IIO_VAL_INT;
203*15dbaed4SAntoni Pokusinski 	case IIO_CHAN_INFO_SCALE:
204*15dbaed4SAntoni Pokusinski 		*val = 0;
205*15dbaed4SAntoni Pokusinski 		if (data->curr_scale == 20)
206*15dbaed4SAntoni Pokusinski 			*val2 = 12500;
207*15dbaed4SAntoni Pokusinski 		else /* data->curr_scale == 200 */
208*15dbaed4SAntoni Pokusinski 			*val2 = 125000;
209*15dbaed4SAntoni Pokusinski 		return IIO_VAL_INT_PLUS_MICRO;
210*15dbaed4SAntoni Pokusinski 	case IIO_CHAN_INFO_OFFSET:
211*15dbaed4SAntoni Pokusinski 		*val = -16384;
212*15dbaed4SAntoni Pokusinski 		return IIO_VAL_INT;
213*15dbaed4SAntoni Pokusinski 	case IIO_CHAN_INFO_PROCESSED:
214*15dbaed4SAntoni Pokusinski 		ret = si7210_fetch_measurement(data, chan, &dspsig);
215*15dbaed4SAntoni Pokusinski 		if (ret)
216*15dbaed4SAntoni Pokusinski 			return ret;
217*15dbaed4SAntoni Pokusinski 
218*15dbaed4SAntoni Pokusinski 		/* temp = 32 * Dspsigm[6:0] + (Dspsigl[7:0] >> 3) */
219*15dbaed4SAntoni Pokusinski 		temp = FIELD_GET(GENMASK(14, 3), dspsig);
220*15dbaed4SAntoni Pokusinski 		temp = div_s64(-383 * temp * temp, 100) + 160940 * temp - 279800000;
221*15dbaed4SAntoni Pokusinski 		temp *= (1 + (data->temp_gain / 2048));
222*15dbaed4SAntoni Pokusinski 		temp += (int)(MICRO / 16) * data->temp_offset;
223*15dbaed4SAntoni Pokusinski 
224*15dbaed4SAntoni Pokusinski 		ret = regulator_get_voltage(data->vdd);
225*15dbaed4SAntoni Pokusinski 		if (ret < 0)
226*15dbaed4SAntoni Pokusinski 			return ret;
227*15dbaed4SAntoni Pokusinski 
228*15dbaed4SAntoni Pokusinski 		/* temp -= 0.222 * VDD */
229*15dbaed4SAntoni Pokusinski 		temp -= 222 * div_s64(ret, MILLI);
230*15dbaed4SAntoni Pokusinski 
231*15dbaed4SAntoni Pokusinski 		*val = div_s64(temp, MILLI);
232*15dbaed4SAntoni Pokusinski 
233*15dbaed4SAntoni Pokusinski 		return IIO_VAL_INT;
234*15dbaed4SAntoni Pokusinski 	default:
235*15dbaed4SAntoni Pokusinski 		return -EINVAL;
236*15dbaed4SAntoni Pokusinski 	}
237*15dbaed4SAntoni Pokusinski }
238*15dbaed4SAntoni Pokusinski 
239*15dbaed4SAntoni Pokusinski static int si7210_set_scale(struct si7210_data *data, unsigned int scale)
240*15dbaed4SAntoni Pokusinski {
241*15dbaed4SAntoni Pokusinski 	s8 *a_otp_values;
242*15dbaed4SAntoni Pokusinski 	int ret;
243*15dbaed4SAntoni Pokusinski 
244*15dbaed4SAntoni Pokusinski 	if (scale == 20)
245*15dbaed4SAntoni Pokusinski 		a_otp_values = data->scale_20_a;
246*15dbaed4SAntoni Pokusinski 	else if (scale == 200)
247*15dbaed4SAntoni Pokusinski 		a_otp_values = data->scale_200_a;
248*15dbaed4SAntoni Pokusinski 	else
249*15dbaed4SAntoni Pokusinski 		return -EINVAL;
250*15dbaed4SAntoni Pokusinski 
251*15dbaed4SAntoni Pokusinski 	guard(mutex)(&data->fetch_lock);
252*15dbaed4SAntoni Pokusinski 
253*15dbaed4SAntoni Pokusinski 	/* Write the registers 0xCA - 0xCC */
254*15dbaed4SAntoni Pokusinski 	ret = regmap_bulk_write(data->regmap, SI7210_REG_A0, a_otp_values, 3);
255*15dbaed4SAntoni Pokusinski 	if (ret)
256*15dbaed4SAntoni Pokusinski 		return ret;
257*15dbaed4SAntoni Pokusinski 
258*15dbaed4SAntoni Pokusinski 	/* Write the registers 0xCE - 0xD0 */
259*15dbaed4SAntoni Pokusinski 	ret = regmap_bulk_write(data->regmap, SI7210_REG_A3, &a_otp_values[3], 3);
260*15dbaed4SAntoni Pokusinski 	if (ret)
261*15dbaed4SAntoni Pokusinski 		return ret;
262*15dbaed4SAntoni Pokusinski 
263*15dbaed4SAntoni Pokusinski 	data->curr_scale = scale;
264*15dbaed4SAntoni Pokusinski 
265*15dbaed4SAntoni Pokusinski 	return 0;
266*15dbaed4SAntoni Pokusinski }
267*15dbaed4SAntoni Pokusinski 
268*15dbaed4SAntoni Pokusinski static int si7210_write_raw(struct iio_dev *indio_dev,
269*15dbaed4SAntoni Pokusinski 			    struct iio_chan_spec const *chan,
270*15dbaed4SAntoni Pokusinski 			    int val, int val2, long mask)
271*15dbaed4SAntoni Pokusinski {
272*15dbaed4SAntoni Pokusinski 	struct si7210_data *data = iio_priv(indio_dev);
273*15dbaed4SAntoni Pokusinski 	unsigned int scale;
274*15dbaed4SAntoni Pokusinski 
275*15dbaed4SAntoni Pokusinski 	switch (mask) {
276*15dbaed4SAntoni Pokusinski 	case IIO_CHAN_INFO_SCALE:
277*15dbaed4SAntoni Pokusinski 		if (val == 0 && val2 == 12500)
278*15dbaed4SAntoni Pokusinski 			scale = 20;
279*15dbaed4SAntoni Pokusinski 		else if (val == 0 && val2 == 125000)
280*15dbaed4SAntoni Pokusinski 			scale = 200;
281*15dbaed4SAntoni Pokusinski 		else
282*15dbaed4SAntoni Pokusinski 			return -EINVAL;
283*15dbaed4SAntoni Pokusinski 
284*15dbaed4SAntoni Pokusinski 		return si7210_set_scale(data, scale);
285*15dbaed4SAntoni Pokusinski 	default:
286*15dbaed4SAntoni Pokusinski 		return -EINVAL;
287*15dbaed4SAntoni Pokusinski 	}
288*15dbaed4SAntoni Pokusinski }
289*15dbaed4SAntoni Pokusinski 
290*15dbaed4SAntoni Pokusinski static int si7210_read_otpreg_val(struct si7210_data *data, unsigned int otpreg, u8 *val)
291*15dbaed4SAntoni Pokusinski {
292*15dbaed4SAntoni Pokusinski 	int ret;
293*15dbaed4SAntoni Pokusinski 	unsigned int otpdata;
294*15dbaed4SAntoni Pokusinski 
295*15dbaed4SAntoni Pokusinski 	ret = regmap_write(data->regmap, SI7210_REG_OTP_ADDR, otpreg);
296*15dbaed4SAntoni Pokusinski 	if (ret)
297*15dbaed4SAntoni Pokusinski 		return ret;
298*15dbaed4SAntoni Pokusinski 
299*15dbaed4SAntoni Pokusinski 	ret = regmap_update_bits(data->regmap, SI7210_REG_OTP_CTRL,
300*15dbaed4SAntoni Pokusinski 				 SI7210_MASK_OTP_READ_EN, SI7210_MASK_OTP_READ_EN);
301*15dbaed4SAntoni Pokusinski 	if (ret)
302*15dbaed4SAntoni Pokusinski 		return ret;
303*15dbaed4SAntoni Pokusinski 
304*15dbaed4SAntoni Pokusinski 	ret = regmap_read(data->regmap, SI7210_REG_OTP_DATA, &otpdata);
305*15dbaed4SAntoni Pokusinski 	if (ret)
306*15dbaed4SAntoni Pokusinski 		return ret;
307*15dbaed4SAntoni Pokusinski 
308*15dbaed4SAntoni Pokusinski 	*val = otpdata;
309*15dbaed4SAntoni Pokusinski 
310*15dbaed4SAntoni Pokusinski 	return 0;
311*15dbaed4SAntoni Pokusinski }
312*15dbaed4SAntoni Pokusinski 
313*15dbaed4SAntoni Pokusinski /*
314*15dbaed4SAntoni Pokusinski  * According to the datasheet, the primary method to wake up a
315*15dbaed4SAntoni Pokusinski  * device is to send an empty write. However this is not feasible
316*15dbaed4SAntoni Pokusinski  * using the current API so we use the other method i.e. read a single
317*15dbaed4SAntoni Pokusinski  * byte. The device should respond with 0xFF.
318*15dbaed4SAntoni Pokusinski  */
319*15dbaed4SAntoni Pokusinski static int si7210_device_wake(struct si7210_data *data)
320*15dbaed4SAntoni Pokusinski {
321*15dbaed4SAntoni Pokusinski 	int ret;
322*15dbaed4SAntoni Pokusinski 
323*15dbaed4SAntoni Pokusinski 	ret = i2c_smbus_read_byte(data->client);
324*15dbaed4SAntoni Pokusinski 	if (ret < 0)
325*15dbaed4SAntoni Pokusinski 		return ret;
326*15dbaed4SAntoni Pokusinski 
327*15dbaed4SAntoni Pokusinski 	if (ret != 0xFF)
328*15dbaed4SAntoni Pokusinski 		return -EIO;
329*15dbaed4SAntoni Pokusinski 
330*15dbaed4SAntoni Pokusinski 	return 0;
331*15dbaed4SAntoni Pokusinski }
332*15dbaed4SAntoni Pokusinski 
333*15dbaed4SAntoni Pokusinski static int si7210_device_init(struct si7210_data *data)
334*15dbaed4SAntoni Pokusinski {
335*15dbaed4SAntoni Pokusinski 	int ret;
336*15dbaed4SAntoni Pokusinski 	unsigned int i;
337*15dbaed4SAntoni Pokusinski 
338*15dbaed4SAntoni Pokusinski 	ret = si7210_device_wake(data);
339*15dbaed4SAntoni Pokusinski 	if (ret)
340*15dbaed4SAntoni Pokusinski 		return ret;
341*15dbaed4SAntoni Pokusinski 
342*15dbaed4SAntoni Pokusinski 	fsleep(1000);
343*15dbaed4SAntoni Pokusinski 
344*15dbaed4SAntoni Pokusinski 	ret = si7210_read_otpreg_val(data, SI7210_OTPREG_TMP_GAIN, &data->temp_gain);
345*15dbaed4SAntoni Pokusinski 	if (ret)
346*15dbaed4SAntoni Pokusinski 		return ret;
347*15dbaed4SAntoni Pokusinski 
348*15dbaed4SAntoni Pokusinski 	ret = si7210_read_otpreg_val(data, SI7210_OTPREG_TMP_OFF, &data->temp_offset);
349*15dbaed4SAntoni Pokusinski 	if (ret)
350*15dbaed4SAntoni Pokusinski 		return ret;
351*15dbaed4SAntoni Pokusinski 
352*15dbaed4SAntoni Pokusinski 	for (i = 0; i < A_REGS_COUNT; i++) {
353*15dbaed4SAntoni Pokusinski 		ret = si7210_read_otpreg_val(data, a20_otp_regs[i], &data->scale_20_a[i]);
354*15dbaed4SAntoni Pokusinski 		if (ret)
355*15dbaed4SAntoni Pokusinski 			return ret;
356*15dbaed4SAntoni Pokusinski 	}
357*15dbaed4SAntoni Pokusinski 
358*15dbaed4SAntoni Pokusinski 	for (i = 0; i < A_REGS_COUNT; i++) {
359*15dbaed4SAntoni Pokusinski 		ret = si7210_read_otpreg_val(data, a200_otp_regs[i], &data->scale_200_a[i]);
360*15dbaed4SAntoni Pokusinski 		if (ret)
361*15dbaed4SAntoni Pokusinski 			return ret;
362*15dbaed4SAntoni Pokusinski 	}
363*15dbaed4SAntoni Pokusinski 
364*15dbaed4SAntoni Pokusinski 	ret = regmap_update_bits(data->regmap, SI7210_REG_ARAUTOINC,
365*15dbaed4SAntoni Pokusinski 				 SI7210_MASK_ARAUTOINC, SI7210_MASK_ARAUTOINC);
366*15dbaed4SAntoni Pokusinski 	if (ret)
367*15dbaed4SAntoni Pokusinski 		return ret;
368*15dbaed4SAntoni Pokusinski 
369*15dbaed4SAntoni Pokusinski 	return si7210_set_scale(data, 20);
370*15dbaed4SAntoni Pokusinski }
371*15dbaed4SAntoni Pokusinski 
372*15dbaed4SAntoni Pokusinski static const struct iio_info si7210_info = {
373*15dbaed4SAntoni Pokusinski 	.read_raw = si7210_read_raw,
374*15dbaed4SAntoni Pokusinski 	.write_raw = si7210_write_raw,
375*15dbaed4SAntoni Pokusinski };
376*15dbaed4SAntoni Pokusinski 
377*15dbaed4SAntoni Pokusinski static int si7210_probe(struct i2c_client *client)
378*15dbaed4SAntoni Pokusinski {
379*15dbaed4SAntoni Pokusinski 	struct si7210_data *data;
380*15dbaed4SAntoni Pokusinski 	struct iio_dev *indio_dev;
381*15dbaed4SAntoni Pokusinski 	int ret;
382*15dbaed4SAntoni Pokusinski 
383*15dbaed4SAntoni Pokusinski 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
384*15dbaed4SAntoni Pokusinski 	if (!indio_dev)
385*15dbaed4SAntoni Pokusinski 		return -ENOMEM;
386*15dbaed4SAntoni Pokusinski 
387*15dbaed4SAntoni Pokusinski 	data = iio_priv(indio_dev);
388*15dbaed4SAntoni Pokusinski 	data->client = client;
389*15dbaed4SAntoni Pokusinski 
390*15dbaed4SAntoni Pokusinski 	ret = devm_mutex_init(&client->dev, &data->fetch_lock);
391*15dbaed4SAntoni Pokusinski 	if (ret)
392*15dbaed4SAntoni Pokusinski 		return ret;
393*15dbaed4SAntoni Pokusinski 
394*15dbaed4SAntoni Pokusinski 	data->regmap = devm_regmap_init_i2c(client, &si7210_regmap_conf);
395*15dbaed4SAntoni Pokusinski 	if (IS_ERR(data->regmap))
396*15dbaed4SAntoni Pokusinski 		return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
397*15dbaed4SAntoni Pokusinski 				     "failed to register regmap\n");
398*15dbaed4SAntoni Pokusinski 
399*15dbaed4SAntoni Pokusinski 	data->vdd = devm_regulator_get(&client->dev, "vdd");
400*15dbaed4SAntoni Pokusinski 	if (IS_ERR(data->vdd))
401*15dbaed4SAntoni Pokusinski 		return dev_err_probe(&client->dev, PTR_ERR(data->vdd),
402*15dbaed4SAntoni Pokusinski 				     "failed to get VDD regulator\n");
403*15dbaed4SAntoni Pokusinski 
404*15dbaed4SAntoni Pokusinski 	ret = regulator_enable(data->vdd);
405*15dbaed4SAntoni Pokusinski 	if (ret)
406*15dbaed4SAntoni Pokusinski 		return ret;
407*15dbaed4SAntoni Pokusinski 
408*15dbaed4SAntoni Pokusinski 	indio_dev->name = dev_name(&client->dev);
409*15dbaed4SAntoni Pokusinski 	indio_dev->modes = INDIO_DIRECT_MODE;
410*15dbaed4SAntoni Pokusinski 	indio_dev->info = &si7210_info;
411*15dbaed4SAntoni Pokusinski 	indio_dev->channels = si7210_channels;
412*15dbaed4SAntoni Pokusinski 	indio_dev->num_channels = ARRAY_SIZE(si7210_channels);
413*15dbaed4SAntoni Pokusinski 
414*15dbaed4SAntoni Pokusinski 	ret = si7210_device_init(data);
415*15dbaed4SAntoni Pokusinski 	if (ret)
416*15dbaed4SAntoni Pokusinski 		return dev_err_probe(&client->dev, ret,
417*15dbaed4SAntoni Pokusinski 				     "device initialization failed\n");
418*15dbaed4SAntoni Pokusinski 
419*15dbaed4SAntoni Pokusinski 	return devm_iio_device_register(&client->dev, indio_dev);
420*15dbaed4SAntoni Pokusinski }
421*15dbaed4SAntoni Pokusinski 
422*15dbaed4SAntoni Pokusinski static const struct i2c_device_id si7210_id[] = {
423*15dbaed4SAntoni Pokusinski 	{ "si7210" },
424*15dbaed4SAntoni Pokusinski 	{ }
425*15dbaed4SAntoni Pokusinski };
426*15dbaed4SAntoni Pokusinski MODULE_DEVICE_TABLE(i2c, si7210_id);
427*15dbaed4SAntoni Pokusinski 
428*15dbaed4SAntoni Pokusinski static const struct of_device_id si7210_dt_ids[] = {
429*15dbaed4SAntoni Pokusinski 	{ .compatible = "silabs,si7210" },
430*15dbaed4SAntoni Pokusinski 	{ }
431*15dbaed4SAntoni Pokusinski };
432*15dbaed4SAntoni Pokusinski MODULE_DEVICE_TABLE(of, si7210_dt_ids);
433*15dbaed4SAntoni Pokusinski 
434*15dbaed4SAntoni Pokusinski static struct i2c_driver si7210_driver = {
435*15dbaed4SAntoni Pokusinski 	.driver = {
436*15dbaed4SAntoni Pokusinski 		.name = "si7210",
437*15dbaed4SAntoni Pokusinski 		.of_match_table = si7210_dt_ids,
438*15dbaed4SAntoni Pokusinski 	},
439*15dbaed4SAntoni Pokusinski 	.probe = si7210_probe,
440*15dbaed4SAntoni Pokusinski 	.id_table = si7210_id,
441*15dbaed4SAntoni Pokusinski };
442*15dbaed4SAntoni Pokusinski module_i2c_driver(si7210_driver);
443*15dbaed4SAntoni Pokusinski 
444*15dbaed4SAntoni Pokusinski MODULE_AUTHOR("Antoni Pokusinski <apokusinski01@gmail.com>");
445*15dbaed4SAntoni Pokusinski MODULE_DESCRIPTION("Silicon Labs Si7210 Hall Effect sensor I2C driver");
446*15dbaed4SAntoni Pokusinski MODULE_LICENSE("GPL");
447