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