1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2020 InvenSense, Inc.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Driver for InvenSense ICP-1010xx barometric pressure and temperature sensor.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Datasheet:
8*4882a593Smuzhiyun * http://www.invensense.com/wp-content/uploads/2018/01/DS-000186-ICP-101xx-v1.2.pdf
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/device.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
14*4882a593Smuzhiyun #include <linux/i2c.h>
15*4882a593Smuzhiyun #include <linux/pm_runtime.h>
16*4882a593Smuzhiyun #include <linux/crc8.h>
17*4882a593Smuzhiyun #include <linux/mutex.h>
18*4882a593Smuzhiyun #include <linux/delay.h>
19*4882a593Smuzhiyun #include <linux/log2.h>
20*4882a593Smuzhiyun #include <linux/math64.h>
21*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
22*4882a593Smuzhiyun #include <linux/iio/iio.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define ICP10100_ID_REG_GET(_reg) ((_reg) & 0x003F)
25*4882a593Smuzhiyun #define ICP10100_ID_REG 0x08
26*4882a593Smuzhiyun #define ICP10100_RESPONSE_WORD_LENGTH 3
27*4882a593Smuzhiyun #define ICP10100_CRC8_WORD_LENGTH 2
28*4882a593Smuzhiyun #define ICP10100_CRC8_POLYNOMIAL 0x31
29*4882a593Smuzhiyun #define ICP10100_CRC8_INIT 0xFF
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun enum icp10100_mode {
32*4882a593Smuzhiyun ICP10100_MODE_LP, /* Low power mode: 1x sampling */
33*4882a593Smuzhiyun ICP10100_MODE_N, /* Normal mode: 2x sampling */
34*4882a593Smuzhiyun ICP10100_MODE_LN, /* Low noise mode: 4x sampling */
35*4882a593Smuzhiyun ICP10100_MODE_ULN, /* Ultra low noise mode: 8x sampling */
36*4882a593Smuzhiyun ICP10100_MODE_NB,
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun struct icp10100_state {
40*4882a593Smuzhiyun struct mutex lock;
41*4882a593Smuzhiyun struct i2c_client *client;
42*4882a593Smuzhiyun struct regulator *vdd;
43*4882a593Smuzhiyun enum icp10100_mode mode;
44*4882a593Smuzhiyun int16_t cal[4];
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun struct icp10100_command {
48*4882a593Smuzhiyun __be16 cmd;
49*4882a593Smuzhiyun unsigned long wait_us;
50*4882a593Smuzhiyun unsigned long wait_max_us;
51*4882a593Smuzhiyun size_t response_word_nb;
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static const struct icp10100_command icp10100_cmd_soft_reset = {
55*4882a593Smuzhiyun .cmd = cpu_to_be16(0x805D),
56*4882a593Smuzhiyun .wait_us = 170,
57*4882a593Smuzhiyun .wait_max_us = 200,
58*4882a593Smuzhiyun .response_word_nb = 0,
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun static const struct icp10100_command icp10100_cmd_read_id = {
62*4882a593Smuzhiyun .cmd = cpu_to_be16(0xEFC8),
63*4882a593Smuzhiyun .wait_us = 0,
64*4882a593Smuzhiyun .response_word_nb = 1,
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun static const struct icp10100_command icp10100_cmd_read_otp = {
68*4882a593Smuzhiyun .cmd = cpu_to_be16(0xC7F7),
69*4882a593Smuzhiyun .wait_us = 0,
70*4882a593Smuzhiyun .response_word_nb = 1,
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static const struct icp10100_command icp10100_cmd_measure[] = {
74*4882a593Smuzhiyun [ICP10100_MODE_LP] = {
75*4882a593Smuzhiyun .cmd = cpu_to_be16(0x401A),
76*4882a593Smuzhiyun .wait_us = 1800,
77*4882a593Smuzhiyun .wait_max_us = 2000,
78*4882a593Smuzhiyun .response_word_nb = 3,
79*4882a593Smuzhiyun },
80*4882a593Smuzhiyun [ICP10100_MODE_N] = {
81*4882a593Smuzhiyun .cmd = cpu_to_be16(0x48A3),
82*4882a593Smuzhiyun .wait_us = 6300,
83*4882a593Smuzhiyun .wait_max_us = 6500,
84*4882a593Smuzhiyun .response_word_nb = 3,
85*4882a593Smuzhiyun },
86*4882a593Smuzhiyun [ICP10100_MODE_LN] = {
87*4882a593Smuzhiyun .cmd = cpu_to_be16(0x5059),
88*4882a593Smuzhiyun .wait_us = 23800,
89*4882a593Smuzhiyun .wait_max_us = 24000,
90*4882a593Smuzhiyun .response_word_nb = 3,
91*4882a593Smuzhiyun },
92*4882a593Smuzhiyun [ICP10100_MODE_ULN] = {
93*4882a593Smuzhiyun .cmd = cpu_to_be16(0x58E0),
94*4882a593Smuzhiyun .wait_us = 94500,
95*4882a593Smuzhiyun .wait_max_us = 94700,
96*4882a593Smuzhiyun .response_word_nb = 3,
97*4882a593Smuzhiyun },
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun static const uint8_t icp10100_switch_mode_otp[] =
101*4882a593Smuzhiyun {0xC5, 0x95, 0x00, 0x66, 0x9c};
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun DECLARE_CRC8_TABLE(icp10100_crc8_table);
104*4882a593Smuzhiyun
icp10100_i2c_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)105*4882a593Smuzhiyun static inline int icp10100_i2c_xfer(struct i2c_adapter *adap,
106*4882a593Smuzhiyun struct i2c_msg *msgs, int num)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun int ret;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun ret = i2c_transfer(adap, msgs, num);
111*4882a593Smuzhiyun if (ret < 0)
112*4882a593Smuzhiyun return ret;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (ret != num)
115*4882a593Smuzhiyun return -EIO;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
icp10100_send_cmd(struct icp10100_state * st,const struct icp10100_command * cmd,__be16 * buf,size_t buf_len)120*4882a593Smuzhiyun static int icp10100_send_cmd(struct icp10100_state *st,
121*4882a593Smuzhiyun const struct icp10100_command *cmd,
122*4882a593Smuzhiyun __be16 *buf, size_t buf_len)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun size_t size = cmd->response_word_nb * ICP10100_RESPONSE_WORD_LENGTH;
125*4882a593Smuzhiyun uint8_t data[16];
126*4882a593Smuzhiyun uint8_t *ptr;
127*4882a593Smuzhiyun uint8_t *buf_ptr = (uint8_t *)buf;
128*4882a593Smuzhiyun struct i2c_msg msgs[2] = {
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun .addr = st->client->addr,
131*4882a593Smuzhiyun .flags = 0,
132*4882a593Smuzhiyun .len = 2,
133*4882a593Smuzhiyun .buf = (uint8_t *)&cmd->cmd,
134*4882a593Smuzhiyun }, {
135*4882a593Smuzhiyun .addr = st->client->addr,
136*4882a593Smuzhiyun .flags = I2C_M_RD,
137*4882a593Smuzhiyun .len = size,
138*4882a593Smuzhiyun .buf = data,
139*4882a593Smuzhiyun },
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun uint8_t crc;
142*4882a593Smuzhiyun unsigned int i;
143*4882a593Smuzhiyun int ret;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun if (size > sizeof(data))
146*4882a593Smuzhiyun return -EINVAL;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (cmd->response_word_nb > 0 &&
149*4882a593Smuzhiyun (buf == NULL || buf_len < (cmd->response_word_nb * 2)))
150*4882a593Smuzhiyun return -EINVAL;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun dev_dbg(&st->client->dev, "sending cmd %#x\n", be16_to_cpu(cmd->cmd));
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun if (cmd->response_word_nb > 0 && cmd->wait_us == 0) {
155*4882a593Smuzhiyun /* direct command-response without waiting */
156*4882a593Smuzhiyun ret = icp10100_i2c_xfer(st->client->adapter, msgs,
157*4882a593Smuzhiyun ARRAY_SIZE(msgs));
158*4882a593Smuzhiyun if (ret)
159*4882a593Smuzhiyun return ret;
160*4882a593Smuzhiyun } else {
161*4882a593Smuzhiyun /* transfer command write */
162*4882a593Smuzhiyun ret = icp10100_i2c_xfer(st->client->adapter, &msgs[0], 1);
163*4882a593Smuzhiyun if (ret)
164*4882a593Smuzhiyun return ret;
165*4882a593Smuzhiyun if (cmd->wait_us > 0)
166*4882a593Smuzhiyun usleep_range(cmd->wait_us, cmd->wait_max_us);
167*4882a593Smuzhiyun /* transfer response read if needed */
168*4882a593Smuzhiyun if (cmd->response_word_nb > 0) {
169*4882a593Smuzhiyun ret = icp10100_i2c_xfer(st->client->adapter, &msgs[1], 1);
170*4882a593Smuzhiyun if (ret)
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun } else {
173*4882a593Smuzhiyun return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* process read words with crc checking */
178*4882a593Smuzhiyun for (i = 0; i < cmd->response_word_nb; ++i) {
179*4882a593Smuzhiyun ptr = &data[i * ICP10100_RESPONSE_WORD_LENGTH];
180*4882a593Smuzhiyun crc = crc8(icp10100_crc8_table, ptr, ICP10100_CRC8_WORD_LENGTH,
181*4882a593Smuzhiyun ICP10100_CRC8_INIT);
182*4882a593Smuzhiyun if (crc != ptr[ICP10100_CRC8_WORD_LENGTH]) {
183*4882a593Smuzhiyun dev_err(&st->client->dev, "crc error recv=%#x calc=%#x\n",
184*4882a593Smuzhiyun ptr[ICP10100_CRC8_WORD_LENGTH], crc);
185*4882a593Smuzhiyun return -EIO;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun *buf_ptr++ = ptr[0];
188*4882a593Smuzhiyun *buf_ptr++ = ptr[1];
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
icp10100_read_cal_otp(struct icp10100_state * st)194*4882a593Smuzhiyun static int icp10100_read_cal_otp(struct icp10100_state *st)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun __be16 val;
197*4882a593Smuzhiyun int i;
198*4882a593Smuzhiyun int ret;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun /* switch into OTP read mode */
201*4882a593Smuzhiyun ret = i2c_master_send(st->client, icp10100_switch_mode_otp,
202*4882a593Smuzhiyun ARRAY_SIZE(icp10100_switch_mode_otp));
203*4882a593Smuzhiyun if (ret < 0)
204*4882a593Smuzhiyun return ret;
205*4882a593Smuzhiyun if (ret != ARRAY_SIZE(icp10100_switch_mode_otp))
206*4882a593Smuzhiyun return -EIO;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* read 4 calibration values */
209*4882a593Smuzhiyun for (i = 0; i < 4; ++i) {
210*4882a593Smuzhiyun ret = icp10100_send_cmd(st, &icp10100_cmd_read_otp,
211*4882a593Smuzhiyun &val, sizeof(val));
212*4882a593Smuzhiyun if (ret)
213*4882a593Smuzhiyun return ret;
214*4882a593Smuzhiyun st->cal[i] = be16_to_cpu(val);
215*4882a593Smuzhiyun dev_dbg(&st->client->dev, "cal[%d] = %d\n", i, st->cal[i]);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
icp10100_init_chip(struct icp10100_state * st)221*4882a593Smuzhiyun static int icp10100_init_chip(struct icp10100_state *st)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun __be16 val;
224*4882a593Smuzhiyun uint16_t id;
225*4882a593Smuzhiyun int ret;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* read and check id */
228*4882a593Smuzhiyun ret = icp10100_send_cmd(st, &icp10100_cmd_read_id, &val, sizeof(val));
229*4882a593Smuzhiyun if (ret)
230*4882a593Smuzhiyun return ret;
231*4882a593Smuzhiyun id = ICP10100_ID_REG_GET(be16_to_cpu(val));
232*4882a593Smuzhiyun if (id != ICP10100_ID_REG) {
233*4882a593Smuzhiyun dev_err(&st->client->dev, "invalid id %#x\n", id);
234*4882a593Smuzhiyun return -ENODEV;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /* read calibration data from OTP */
238*4882a593Smuzhiyun ret = icp10100_read_cal_otp(st);
239*4882a593Smuzhiyun if (ret)
240*4882a593Smuzhiyun return ret;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* reset chip */
243*4882a593Smuzhiyun return icp10100_send_cmd(st, &icp10100_cmd_soft_reset, NULL, 0);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
icp10100_get_measures(struct icp10100_state * st,uint32_t * pressure,uint16_t * temperature)246*4882a593Smuzhiyun static int icp10100_get_measures(struct icp10100_state *st,
247*4882a593Smuzhiyun uint32_t *pressure, uint16_t *temperature)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun const struct icp10100_command *cmd;
250*4882a593Smuzhiyun __be16 measures[3];
251*4882a593Smuzhiyun int ret;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun pm_runtime_get_sync(&st->client->dev);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun mutex_lock(&st->lock);
256*4882a593Smuzhiyun cmd = &icp10100_cmd_measure[st->mode];
257*4882a593Smuzhiyun ret = icp10100_send_cmd(st, cmd, measures, sizeof(measures));
258*4882a593Smuzhiyun mutex_unlock(&st->lock);
259*4882a593Smuzhiyun if (ret)
260*4882a593Smuzhiyun goto error_measure;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun *pressure = (be16_to_cpu(measures[0]) << 8) |
263*4882a593Smuzhiyun (be16_to_cpu(measures[1]) >> 8);
264*4882a593Smuzhiyun *temperature = be16_to_cpu(measures[2]);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun pm_runtime_mark_last_busy(&st->client->dev);
267*4882a593Smuzhiyun error_measure:
268*4882a593Smuzhiyun pm_runtime_put_autosuspend(&st->client->dev);
269*4882a593Smuzhiyun return ret;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
icp10100_get_pressure(struct icp10100_state * st,uint32_t raw_pressure,uint16_t raw_temp)272*4882a593Smuzhiyun static uint32_t icp10100_get_pressure(struct icp10100_state *st,
273*4882a593Smuzhiyun uint32_t raw_pressure, uint16_t raw_temp)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun static int32_t p_calib[] = {45000, 80000, 105000};
276*4882a593Smuzhiyun static int32_t lut_lower = 3670016;
277*4882a593Smuzhiyun static int32_t lut_upper = 12058624;
278*4882a593Smuzhiyun static int32_t inv_quadr_factor = 16777216;
279*4882a593Smuzhiyun static int32_t offset_factor = 2048;
280*4882a593Smuzhiyun int64_t val1, val2;
281*4882a593Smuzhiyun int32_t p_lut[3];
282*4882a593Smuzhiyun int32_t t, t_square;
283*4882a593Smuzhiyun int64_t a, b, c;
284*4882a593Smuzhiyun uint32_t pressure_mPa;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun dev_dbg(&st->client->dev, "raw: pressure = %u, temp = %u\n",
287*4882a593Smuzhiyun raw_pressure, raw_temp);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* compute p_lut values */
290*4882a593Smuzhiyun t = (int32_t)raw_temp - 32768;
291*4882a593Smuzhiyun t_square = t * t;
292*4882a593Smuzhiyun val1 = (int64_t)st->cal[0] * (int64_t)t_square;
293*4882a593Smuzhiyun p_lut[0] = lut_lower + (int32_t)div_s64(val1, inv_quadr_factor);
294*4882a593Smuzhiyun val1 = (int64_t)st->cal[1] * (int64_t)t_square;
295*4882a593Smuzhiyun p_lut[1] = offset_factor * st->cal[3] +
296*4882a593Smuzhiyun (int32_t)div_s64(val1, inv_quadr_factor);
297*4882a593Smuzhiyun val1 = (int64_t)st->cal[2] * (int64_t)t_square;
298*4882a593Smuzhiyun p_lut[2] = lut_upper + (int32_t)div_s64(val1, inv_quadr_factor);
299*4882a593Smuzhiyun dev_dbg(&st->client->dev, "p_lut = [%d, %d, %d]\n",
300*4882a593Smuzhiyun p_lut[0], p_lut[1], p_lut[2]);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /* compute a, b, c factors */
303*4882a593Smuzhiyun val1 = (int64_t)p_lut[0] * (int64_t)p_lut[1] *
304*4882a593Smuzhiyun (int64_t)(p_calib[0] - p_calib[1]) +
305*4882a593Smuzhiyun (int64_t)p_lut[1] * (int64_t)p_lut[2] *
306*4882a593Smuzhiyun (int64_t)(p_calib[1] - p_calib[2]) +
307*4882a593Smuzhiyun (int64_t)p_lut[2] * (int64_t)p_lut[0] *
308*4882a593Smuzhiyun (int64_t)(p_calib[2] - p_calib[0]);
309*4882a593Smuzhiyun val2 = (int64_t)p_lut[2] * (int64_t)(p_calib[0] - p_calib[1]) +
310*4882a593Smuzhiyun (int64_t)p_lut[0] * (int64_t)(p_calib[1] - p_calib[2]) +
311*4882a593Smuzhiyun (int64_t)p_lut[1] * (int64_t)(p_calib[2] - p_calib[0]);
312*4882a593Smuzhiyun c = div64_s64(val1, val2);
313*4882a593Smuzhiyun dev_dbg(&st->client->dev, "val1 = %lld, val2 = %lld, c = %lld\n",
314*4882a593Smuzhiyun val1, val2, c);
315*4882a593Smuzhiyun val1 = (int64_t)p_calib[0] * (int64_t)p_lut[0] -
316*4882a593Smuzhiyun (int64_t)p_calib[1] * (int64_t)p_lut[1] -
317*4882a593Smuzhiyun (int64_t)(p_calib[1] - p_calib[0]) * c;
318*4882a593Smuzhiyun val2 = (int64_t)p_lut[0] - (int64_t)p_lut[1];
319*4882a593Smuzhiyun a = div64_s64(val1, val2);
320*4882a593Smuzhiyun dev_dbg(&st->client->dev, "val1 = %lld, val2 = %lld, a = %lld\n",
321*4882a593Smuzhiyun val1, val2, a);
322*4882a593Smuzhiyun b = ((int64_t)p_calib[0] - a) * ((int64_t)p_lut[0] + c);
323*4882a593Smuzhiyun dev_dbg(&st->client->dev, "b = %lld\n", b);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun /*
326*4882a593Smuzhiyun * pressure_Pa = a + (b / (c + raw_pressure))
327*4882a593Smuzhiyun * pressure_mPa = 1000 * pressure_Pa
328*4882a593Smuzhiyun */
329*4882a593Smuzhiyun pressure_mPa = 1000LL * a + div64_s64(1000LL * b, c + raw_pressure);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun return pressure_mPa;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
icp10100_read_raw_measures(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2)334*4882a593Smuzhiyun static int icp10100_read_raw_measures(struct iio_dev *indio_dev,
335*4882a593Smuzhiyun struct iio_chan_spec const *chan,
336*4882a593Smuzhiyun int *val, int *val2)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun struct icp10100_state *st = iio_priv(indio_dev);
339*4882a593Smuzhiyun uint32_t raw_pressure;
340*4882a593Smuzhiyun uint16_t raw_temp;
341*4882a593Smuzhiyun uint32_t pressure_mPa;
342*4882a593Smuzhiyun int ret;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun ret = iio_device_claim_direct_mode(indio_dev);
345*4882a593Smuzhiyun if (ret)
346*4882a593Smuzhiyun return ret;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun ret = icp10100_get_measures(st, &raw_pressure, &raw_temp);
349*4882a593Smuzhiyun if (ret)
350*4882a593Smuzhiyun goto error_release;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun switch (chan->type) {
353*4882a593Smuzhiyun case IIO_PRESSURE:
354*4882a593Smuzhiyun pressure_mPa = icp10100_get_pressure(st, raw_pressure,
355*4882a593Smuzhiyun raw_temp);
356*4882a593Smuzhiyun /* mPa to kPa */
357*4882a593Smuzhiyun *val = pressure_mPa / 1000000;
358*4882a593Smuzhiyun *val2 = pressure_mPa % 1000000;
359*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
360*4882a593Smuzhiyun break;
361*4882a593Smuzhiyun case IIO_TEMP:
362*4882a593Smuzhiyun *val = raw_temp;
363*4882a593Smuzhiyun ret = IIO_VAL_INT;
364*4882a593Smuzhiyun break;
365*4882a593Smuzhiyun default:
366*4882a593Smuzhiyun ret = -EINVAL;
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun error_release:
371*4882a593Smuzhiyun iio_device_release_direct_mode(indio_dev);
372*4882a593Smuzhiyun return ret;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
icp10100_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)375*4882a593Smuzhiyun static int icp10100_read_raw(struct iio_dev *indio_dev,
376*4882a593Smuzhiyun struct iio_chan_spec const *chan,
377*4882a593Smuzhiyun int *val, int *val2, long mask)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun struct icp10100_state *st = iio_priv(indio_dev);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun switch (mask) {
382*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
383*4882a593Smuzhiyun case IIO_CHAN_INFO_PROCESSED:
384*4882a593Smuzhiyun return icp10100_read_raw_measures(indio_dev, chan, val, val2);
385*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
386*4882a593Smuzhiyun switch (chan->type) {
387*4882a593Smuzhiyun case IIO_TEMP:
388*4882a593Smuzhiyun /* 1000 * 175°C / 65536 in m°C */
389*4882a593Smuzhiyun *val = 2;
390*4882a593Smuzhiyun *val2 = 670288;
391*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_MICRO;
392*4882a593Smuzhiyun default:
393*4882a593Smuzhiyun return -EINVAL;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun break;
396*4882a593Smuzhiyun case IIO_CHAN_INFO_OFFSET:
397*4882a593Smuzhiyun switch (chan->type) {
398*4882a593Smuzhiyun case IIO_TEMP:
399*4882a593Smuzhiyun /* 1000 * -45°C in m°C */
400*4882a593Smuzhiyun *val = -45000;
401*4882a593Smuzhiyun return IIO_VAL_INT;
402*4882a593Smuzhiyun default:
403*4882a593Smuzhiyun return -EINVAL;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun break;
406*4882a593Smuzhiyun case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
407*4882a593Smuzhiyun mutex_lock(&st->lock);
408*4882a593Smuzhiyun *val = 1 << st->mode;
409*4882a593Smuzhiyun mutex_unlock(&st->lock);
410*4882a593Smuzhiyun return IIO_VAL_INT;
411*4882a593Smuzhiyun default:
412*4882a593Smuzhiyun return -EINVAL;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
icp10100_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)416*4882a593Smuzhiyun static int icp10100_read_avail(struct iio_dev *indio_dev,
417*4882a593Smuzhiyun struct iio_chan_spec const *chan,
418*4882a593Smuzhiyun const int **vals, int *type, int *length,
419*4882a593Smuzhiyun long mask)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun static int oversamplings[] = {1, 2, 4, 8};
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun switch (mask) {
424*4882a593Smuzhiyun case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
425*4882a593Smuzhiyun *vals = oversamplings;
426*4882a593Smuzhiyun *type = IIO_VAL_INT;
427*4882a593Smuzhiyun *length = ARRAY_SIZE(oversamplings);
428*4882a593Smuzhiyun return IIO_AVAIL_LIST;
429*4882a593Smuzhiyun default:
430*4882a593Smuzhiyun return -EINVAL;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
icp10100_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)434*4882a593Smuzhiyun static int icp10100_write_raw(struct iio_dev *indio_dev,
435*4882a593Smuzhiyun struct iio_chan_spec const *chan,
436*4882a593Smuzhiyun int val, int val2, long mask)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun struct icp10100_state *st = iio_priv(indio_dev);
439*4882a593Smuzhiyun unsigned int mode;
440*4882a593Smuzhiyun int ret;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun switch (mask) {
443*4882a593Smuzhiyun case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
444*4882a593Smuzhiyun /* oversampling is always positive and a power of 2 */
445*4882a593Smuzhiyun if (val <= 0 || !is_power_of_2(val))
446*4882a593Smuzhiyun return -EINVAL;
447*4882a593Smuzhiyun mode = ilog2(val);
448*4882a593Smuzhiyun if (mode >= ICP10100_MODE_NB)
449*4882a593Smuzhiyun return -EINVAL;
450*4882a593Smuzhiyun ret = iio_device_claim_direct_mode(indio_dev);
451*4882a593Smuzhiyun if (ret)
452*4882a593Smuzhiyun return ret;
453*4882a593Smuzhiyun mutex_lock(&st->lock);
454*4882a593Smuzhiyun st->mode = mode;
455*4882a593Smuzhiyun mutex_unlock(&st->lock);
456*4882a593Smuzhiyun iio_device_release_direct_mode(indio_dev);
457*4882a593Smuzhiyun return 0;
458*4882a593Smuzhiyun default:
459*4882a593Smuzhiyun return -EINVAL;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
icp10100_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long mask)463*4882a593Smuzhiyun static int icp10100_write_raw_get_fmt(struct iio_dev *indio_dev,
464*4882a593Smuzhiyun struct iio_chan_spec const *chan,
465*4882a593Smuzhiyun long mask)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun switch (mask) {
468*4882a593Smuzhiyun case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
469*4882a593Smuzhiyun return IIO_VAL_INT;
470*4882a593Smuzhiyun default:
471*4882a593Smuzhiyun return -EINVAL;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun static const struct iio_info icp10100_info = {
476*4882a593Smuzhiyun .read_raw = icp10100_read_raw,
477*4882a593Smuzhiyun .read_avail = icp10100_read_avail,
478*4882a593Smuzhiyun .write_raw = icp10100_write_raw,
479*4882a593Smuzhiyun .write_raw_get_fmt = icp10100_write_raw_get_fmt,
480*4882a593Smuzhiyun };
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun static const struct iio_chan_spec icp10100_channels[] = {
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun .type = IIO_PRESSURE,
485*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
486*4882a593Smuzhiyun .info_mask_shared_by_all =
487*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
488*4882a593Smuzhiyun .info_mask_shared_by_all_available =
489*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
490*4882a593Smuzhiyun }, {
491*4882a593Smuzhiyun .type = IIO_TEMP,
492*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
493*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_SCALE) |
494*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OFFSET),
495*4882a593Smuzhiyun .info_mask_shared_by_all =
496*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
497*4882a593Smuzhiyun .info_mask_shared_by_all_available =
498*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
499*4882a593Smuzhiyun },
500*4882a593Smuzhiyun };
501*4882a593Smuzhiyun
icp10100_enable_regulator(struct icp10100_state * st)502*4882a593Smuzhiyun static int icp10100_enable_regulator(struct icp10100_state *st)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun int ret;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun ret = regulator_enable(st->vdd);
507*4882a593Smuzhiyun if (ret)
508*4882a593Smuzhiyun return ret;
509*4882a593Smuzhiyun msleep(100);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun return 0;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
icp10100_disable_regulator_action(void * data)514*4882a593Smuzhiyun static void icp10100_disable_regulator_action(void *data)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun struct icp10100_state *st = data;
517*4882a593Smuzhiyun int ret;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun ret = regulator_disable(st->vdd);
520*4882a593Smuzhiyun if (ret)
521*4882a593Smuzhiyun dev_err(&st->client->dev, "error %d disabling vdd\n", ret);
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
icp10100_pm_disable(void * data)524*4882a593Smuzhiyun static void icp10100_pm_disable(void *data)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun struct device *dev = data;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun pm_runtime_put_sync_suspend(dev);
529*4882a593Smuzhiyun pm_runtime_disable(dev);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
icp10100_probe(struct i2c_client * client,const struct i2c_device_id * id)532*4882a593Smuzhiyun static int icp10100_probe(struct i2c_client *client,
533*4882a593Smuzhiyun const struct i2c_device_id *id)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun struct iio_dev *indio_dev;
536*4882a593Smuzhiyun struct icp10100_state *st;
537*4882a593Smuzhiyun int ret;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
540*4882a593Smuzhiyun dev_err(&client->dev, "plain i2c transactions not supported\n");
541*4882a593Smuzhiyun return -ENODEV;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
545*4882a593Smuzhiyun if (!indio_dev)
546*4882a593Smuzhiyun return -ENOMEM;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun i2c_set_clientdata(client, indio_dev);
549*4882a593Smuzhiyun indio_dev->name = client->name;
550*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
551*4882a593Smuzhiyun indio_dev->channels = icp10100_channels;
552*4882a593Smuzhiyun indio_dev->num_channels = ARRAY_SIZE(icp10100_channels);
553*4882a593Smuzhiyun indio_dev->info = &icp10100_info;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun st = iio_priv(indio_dev);
556*4882a593Smuzhiyun mutex_init(&st->lock);
557*4882a593Smuzhiyun st->client = client;
558*4882a593Smuzhiyun st->mode = ICP10100_MODE_N;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun st->vdd = devm_regulator_get(&client->dev, "vdd");
561*4882a593Smuzhiyun if (IS_ERR(st->vdd))
562*4882a593Smuzhiyun return PTR_ERR(st->vdd);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun ret = icp10100_enable_regulator(st);
565*4882a593Smuzhiyun if (ret)
566*4882a593Smuzhiyun return ret;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun ret = devm_add_action_or_reset(&client->dev,
569*4882a593Smuzhiyun icp10100_disable_regulator_action, st);
570*4882a593Smuzhiyun if (ret)
571*4882a593Smuzhiyun return ret;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* has to be done before the first i2c communication */
574*4882a593Smuzhiyun crc8_populate_msb(icp10100_crc8_table, ICP10100_CRC8_POLYNOMIAL);
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun ret = icp10100_init_chip(st);
577*4882a593Smuzhiyun if (ret) {
578*4882a593Smuzhiyun dev_err(&client->dev, "init chip error %d\n", ret);
579*4882a593Smuzhiyun return ret;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun /* enable runtime pm with autosuspend delay of 2s */
583*4882a593Smuzhiyun pm_runtime_get_noresume(&client->dev);
584*4882a593Smuzhiyun pm_runtime_set_active(&client->dev);
585*4882a593Smuzhiyun pm_runtime_enable(&client->dev);
586*4882a593Smuzhiyun pm_runtime_set_autosuspend_delay(&client->dev, 2000);
587*4882a593Smuzhiyun pm_runtime_use_autosuspend(&client->dev);
588*4882a593Smuzhiyun pm_runtime_put(&client->dev);
589*4882a593Smuzhiyun ret = devm_add_action_or_reset(&client->dev, icp10100_pm_disable,
590*4882a593Smuzhiyun &client->dev);
591*4882a593Smuzhiyun if (ret)
592*4882a593Smuzhiyun return ret;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun return devm_iio_device_register(&client->dev, indio_dev);
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun
icp10100_suspend(struct device * dev)597*4882a593Smuzhiyun static int __maybe_unused icp10100_suspend(struct device *dev)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun struct icp10100_state *st = iio_priv(dev_get_drvdata(dev));
600*4882a593Smuzhiyun int ret;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun mutex_lock(&st->lock);
603*4882a593Smuzhiyun ret = regulator_disable(st->vdd);
604*4882a593Smuzhiyun mutex_unlock(&st->lock);
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun return ret;
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun
icp10100_resume(struct device * dev)609*4882a593Smuzhiyun static int __maybe_unused icp10100_resume(struct device *dev)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun struct icp10100_state *st = iio_priv(dev_get_drvdata(dev));
612*4882a593Smuzhiyun int ret;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun mutex_lock(&st->lock);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun ret = icp10100_enable_regulator(st);
617*4882a593Smuzhiyun if (ret)
618*4882a593Smuzhiyun goto out_unlock;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun /* reset chip */
621*4882a593Smuzhiyun ret = icp10100_send_cmd(st, &icp10100_cmd_soft_reset, NULL, 0);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun out_unlock:
624*4882a593Smuzhiyun mutex_unlock(&st->lock);
625*4882a593Smuzhiyun return ret;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun static UNIVERSAL_DEV_PM_OPS(icp10100_pm, icp10100_suspend, icp10100_resume,
629*4882a593Smuzhiyun NULL);
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun static const struct of_device_id icp10100_of_match[] = {
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun .compatible = "invensense,icp10100",
634*4882a593Smuzhiyun },
635*4882a593Smuzhiyun { }
636*4882a593Smuzhiyun };
637*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, icp10100_of_match);
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun static const struct i2c_device_id icp10100_id[] = {
640*4882a593Smuzhiyun { "icp10100", 0 },
641*4882a593Smuzhiyun { }
642*4882a593Smuzhiyun };
643*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, icp10100_id);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun static struct i2c_driver icp10100_driver = {
646*4882a593Smuzhiyun .driver = {
647*4882a593Smuzhiyun .name = "icp10100",
648*4882a593Smuzhiyun .pm = &icp10100_pm,
649*4882a593Smuzhiyun .of_match_table = icp10100_of_match,
650*4882a593Smuzhiyun },
651*4882a593Smuzhiyun .probe = icp10100_probe,
652*4882a593Smuzhiyun .id_table = icp10100_id,
653*4882a593Smuzhiyun };
654*4882a593Smuzhiyun module_i2c_driver(icp10100_driver);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun MODULE_AUTHOR("InvenSense, Inc.");
657*4882a593Smuzhiyun MODULE_DESCRIPTION("InvenSense icp10100 driver");
658*4882a593Smuzhiyun MODULE_LICENSE("GPL");
659