1059 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for NXP FXAS21002C Gyroscope - Core4 *5 * Copyright (C) 2019 Linaro Ltd.6 */7 8#include <linux/interrupt.h>9#include <linux/module.h>10#include <linux/pm.h>11#include <linux/pm_runtime.h>12#include <linux/property.h>13#include <linux/regmap.h>14#include <linux/regulator/consumer.h>15 16#include <linux/iio/events.h>17#include <linux/iio/iio.h>18#include <linux/iio/buffer.h>19#include <linux/iio/sysfs.h>20#include <linux/iio/trigger.h>21#include <linux/iio/trigger_consumer.h>22#include <linux/iio/triggered_buffer.h>23 24#include "fxas21002c.h"25 26#define FXAS21002C_CHIP_ID_1 0xD627#define FXAS21002C_CHIP_ID_2 0xD728 29enum fxas21002c_mode_state {30 FXAS21002C_MODE_STANDBY,31 FXAS21002C_MODE_READY,32 FXAS21002C_MODE_ACTIVE,33};34 35#define FXAS21002C_STANDBY_ACTIVE_TIME_MS 6236#define FXAS21002C_READY_ACTIVE_TIME_MS 737 38#define FXAS21002C_ODR_LIST_MAX 1039 40#define FXAS21002C_SCALE_FRACTIONAL 3241#define FXAS21002C_RANGE_LIMIT_DOUBLE 200042 43#define FXAS21002C_AXIS_TO_REG(axis) (FXAS21002C_REG_OUT_X_MSB + ((axis) * 2))44 45static const struct reg_field fxas21002c_reg_fields[] = {46 [F_DR_STATUS] = REG_FIELD(FXAS21002C_REG_STATUS, 0, 7),47 [F_OUT_X_MSB] = REG_FIELD(FXAS21002C_REG_OUT_X_MSB, 0, 7),48 [F_OUT_X_LSB] = REG_FIELD(FXAS21002C_REG_OUT_X_LSB, 0, 7),49 [F_OUT_Y_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_MSB, 0, 7),50 [F_OUT_Y_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_LSB, 0, 7),51 [F_OUT_Z_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_MSB, 0, 7),52 [F_OUT_Z_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_LSB, 0, 7),53 [F_ZYX_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 7, 7),54 [F_Z_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 6, 6),55 [F_Y_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 5, 5),56 [F_X_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 4, 4),57 [F_ZYX_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 3, 3),58 [F_Z_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 2, 2),59 [F_Y_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 1, 1),60 [F_X_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 0, 0),61 [F_OVF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 7, 7),62 [F_WMKF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 6, 6),63 [F_CNT] = REG_FIELD(FXAS21002C_REG_F_STATUS, 0, 5),64 [F_MODE] = REG_FIELD(FXAS21002C_REG_F_SETUP, 6, 7),65 [F_WMRK] = REG_FIELD(FXAS21002C_REG_F_SETUP, 0, 5),66 [F_EVENT] = REG_FIELD(FXAS21002C_REG_F_EVENT, 5, 5),67 [FE_TIME] = REG_FIELD(FXAS21002C_REG_F_EVENT, 0, 4),68 [F_BOOTEND] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 3, 3),69 [F_SRC_FIFO] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 2, 2),70 [F_SRC_RT] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 1, 1),71 [F_SRC_DRDY] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 0, 0),72 [F_WHO_AM_I] = REG_FIELD(FXAS21002C_REG_WHO_AM_I, 0, 7),73 [F_BW] = REG_FIELD(FXAS21002C_REG_CTRL0, 6, 7),74 [F_SPIW] = REG_FIELD(FXAS21002C_REG_CTRL0, 5, 5),75 [F_SEL] = REG_FIELD(FXAS21002C_REG_CTRL0, 3, 4),76 [F_HPF_EN] = REG_FIELD(FXAS21002C_REG_CTRL0, 2, 2),77 [F_FS] = REG_FIELD(FXAS21002C_REG_CTRL0, 0, 1),78 [F_ELE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 3, 3),79 [F_ZTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 2, 2),80 [F_YTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 1, 1),81 [F_XTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 0, 0),82 [F_EA] = REG_FIELD(FXAS21002C_REG_RT_SRC, 6, 6),83 [F_ZRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 5, 5),84 [F_ZRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 4, 4),85 [F_YRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 3, 3),86 [F_YRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 2, 2),87 [F_XRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 1, 1),88 [F_XRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 0),89 [F_DBCNTM] = REG_FIELD(FXAS21002C_REG_RT_THS, 7, 7),90 [F_THS] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 6),91 [F_RT_COUNT] = REG_FIELD(FXAS21002C_REG_RT_COUNT, 0, 7),92 [F_TEMP] = REG_FIELD(FXAS21002C_REG_TEMP, 0, 7),93 [F_RST] = REG_FIELD(FXAS21002C_REG_CTRL1, 6, 6),94 [F_ST] = REG_FIELD(FXAS21002C_REG_CTRL1, 5, 5),95 [F_DR] = REG_FIELD(FXAS21002C_REG_CTRL1, 2, 4),96 [F_ACTIVE] = REG_FIELD(FXAS21002C_REG_CTRL1, 1, 1),97 [F_READY] = REG_FIELD(FXAS21002C_REG_CTRL1, 0, 0),98 [F_INT_CFG_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 7, 7),99 [F_INT_EN_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 6, 6),100 [F_INT_CFG_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 5, 5),101 [F_INT_EN_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 4, 4),102 [F_INT_CFG_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 3, 3),103 [F_INT_EN_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 2, 2),104 [F_IPOL] = REG_FIELD(FXAS21002C_REG_CTRL2, 1, 1),105 [F_PP_OD] = REG_FIELD(FXAS21002C_REG_CTRL2, 0, 0),106 [F_WRAPTOONE] = REG_FIELD(FXAS21002C_REG_CTRL3, 3, 3),107 [F_EXTCTRLEN] = REG_FIELD(FXAS21002C_REG_CTRL3, 2, 2),108 [F_FS_DOUBLE] = REG_FIELD(FXAS21002C_REG_CTRL3, 0, 0),109};110 111static const int fxas21002c_odr_values[] = {112 800, 400, 200, 100, 50, 25, 12, 12113};114 115/*116 * These values are taken from the low-pass filter cutoff frequency calculated117 * ODR * 0.lpf_values. So, for ODR = 800Hz with a lpf value = 0.32118 * => LPF cutoff frequency = 800 * 0.32 = 256 Hz119 */120static const int fxas21002c_lpf_values[] = {121 32, 16, 8122};123 124/*125 * These values are taken from the high-pass filter cutoff frequency calculated126 * ODR * 0.0hpf_values. So, for ODR = 800Hz with a hpf value = 0.018750127 * => HPF cutoff frequency = 800 * 0.018750 = 15 Hz128 */129static const int fxas21002c_hpf_values[] = {130 18750, 9625, 4875, 2475131};132 133static const int fxas21002c_range_values[] = {134 4000, 2000, 1000, 500, 250135};136 137struct fxas21002c_data {138 u8 chip_id;139 enum fxas21002c_mode_state mode;140 enum fxas21002c_mode_state prev_mode;141 142 struct mutex lock; /* serialize data access */143 struct regmap *regmap;144 struct regmap_field *regmap_fields[F_MAX_FIELDS];145 struct iio_trigger *dready_trig;146 s64 timestamp;147 int irq;148 149 struct regulator *vdd;150 struct regulator *vddio;151 152 /*153 * DMA (thus cache coherency maintenance) may require the154 * transfer buffers live in their own cache lines.155 */156 s16 buffer[8] __aligned(IIO_DMA_MINALIGN);157};158 159enum fxas21002c_channel_index {160 CHANNEL_SCAN_INDEX_X,161 CHANNEL_SCAN_INDEX_Y,162 CHANNEL_SCAN_INDEX_Z,163 CHANNEL_SCAN_MAX,164};165 166static int fxas21002c_odr_hz_from_value(struct fxas21002c_data *data, u8 value)167{168 int odr_value_max = ARRAY_SIZE(fxas21002c_odr_values) - 1;169 170 value = min_t(u8, value, odr_value_max);171 172 return fxas21002c_odr_values[value];173}174 175static int fxas21002c_odr_value_from_hz(struct fxas21002c_data *data,176 unsigned int hz)177{178 int odr_table_size = ARRAY_SIZE(fxas21002c_odr_values);179 int i;180 181 for (i = 0; i < odr_table_size; i++)182 if (fxas21002c_odr_values[i] == hz)183 return i;184 185 return -EINVAL;186}187 188static int fxas21002c_lpf_bw_from_value(struct fxas21002c_data *data, u8 value)189{190 int lpf_value_max = ARRAY_SIZE(fxas21002c_lpf_values) - 1;191 192 value = min_t(u8, value, lpf_value_max);193 194 return fxas21002c_lpf_values[value];195}196 197static int fxas21002c_lpf_value_from_bw(struct fxas21002c_data *data,198 unsigned int hz)199{200 int lpf_table_size = ARRAY_SIZE(fxas21002c_lpf_values);201 int i;202 203 for (i = 0; i < lpf_table_size; i++)204 if (fxas21002c_lpf_values[i] == hz)205 return i;206 207 return -EINVAL;208}209 210static int fxas21002c_hpf_sel_from_value(struct fxas21002c_data *data, u8 value)211{212 int hpf_value_max = ARRAY_SIZE(fxas21002c_hpf_values) - 1;213 214 value = min_t(u8, value, hpf_value_max);215 216 return fxas21002c_hpf_values[value];217}218 219static int fxas21002c_hpf_value_from_sel(struct fxas21002c_data *data,220 unsigned int hz)221{222 int hpf_table_size = ARRAY_SIZE(fxas21002c_hpf_values);223 int i;224 225 for (i = 0; i < hpf_table_size; i++)226 if (fxas21002c_hpf_values[i] == hz)227 return i;228 229 return -EINVAL;230}231 232static int fxas21002c_range_fs_from_value(struct fxas21002c_data *data,233 u8 value)234{235 int range_value_max = ARRAY_SIZE(fxas21002c_range_values) - 1;236 unsigned int fs_double;237 int ret;238 239 /* We need to check if FS_DOUBLE is enabled to offset the value */240 ret = regmap_field_read(data->regmap_fields[F_FS_DOUBLE], &fs_double);241 if (ret < 0)242 return ret;243 244 if (!fs_double)245 value += 1;246 247 value = min_t(u8, value, range_value_max);248 249 return fxas21002c_range_values[value];250}251 252static int fxas21002c_range_value_from_fs(struct fxas21002c_data *data,253 unsigned int range)254{255 int range_table_size = ARRAY_SIZE(fxas21002c_range_values);256 bool found = false;257 int fs_double = 0;258 int ret;259 int i;260 261 for (i = 0; i < range_table_size; i++)262 if (fxas21002c_range_values[i] == range) {263 found = true;264 break;265 }266 267 if (!found)268 return -EINVAL;269 270 if (range > FXAS21002C_RANGE_LIMIT_DOUBLE)271 fs_double = 1;272 273 ret = regmap_field_write(data->regmap_fields[F_FS_DOUBLE], fs_double);274 if (ret < 0)275 return ret;276 277 return i;278}279 280static int fxas21002c_mode_get(struct fxas21002c_data *data)281{282 unsigned int active;283 unsigned int ready;284 int ret;285 286 ret = regmap_field_read(data->regmap_fields[F_ACTIVE], &active);287 if (ret < 0)288 return ret;289 if (active)290 return FXAS21002C_MODE_ACTIVE;291 292 ret = regmap_field_read(data->regmap_fields[F_READY], &ready);293 if (ret < 0)294 return ret;295 if (ready)296 return FXAS21002C_MODE_READY;297 298 return FXAS21002C_MODE_STANDBY;299}300 301static int fxas21002c_mode_set(struct fxas21002c_data *data,302 enum fxas21002c_mode_state mode)303{304 int ret;305 306 if (mode == data->mode)307 return 0;308 309 if (mode == FXAS21002C_MODE_READY)310 ret = regmap_field_write(data->regmap_fields[F_READY], 1);311 else312 ret = regmap_field_write(data->regmap_fields[F_READY], 0);313 if (ret < 0)314 return ret;315 316 if (mode == FXAS21002C_MODE_ACTIVE)317 ret = regmap_field_write(data->regmap_fields[F_ACTIVE], 1);318 else319 ret = regmap_field_write(data->regmap_fields[F_ACTIVE], 0);320 if (ret < 0)321 return ret;322 323 /* if going to active wait the setup times */324 if (mode == FXAS21002C_MODE_ACTIVE &&325 data->mode == FXAS21002C_MODE_STANDBY)326 msleep_interruptible(FXAS21002C_STANDBY_ACTIVE_TIME_MS);327 328 if (data->mode == FXAS21002C_MODE_READY)329 msleep_interruptible(FXAS21002C_READY_ACTIVE_TIME_MS);330 331 data->prev_mode = data->mode;332 data->mode = mode;333 334 return ret;335}336 337static int fxas21002c_write(struct fxas21002c_data *data,338 enum fxas21002c_fields field, int bits)339{340 int actual_mode;341 int ret;342 343 mutex_lock(&data->lock);344 345 actual_mode = fxas21002c_mode_get(data);346 if (actual_mode < 0) {347 ret = actual_mode;348 goto out_unlock;349 }350 351 ret = fxas21002c_mode_set(data, FXAS21002C_MODE_READY);352 if (ret < 0)353 goto out_unlock;354 355 ret = regmap_field_write(data->regmap_fields[field], bits);356 if (ret < 0)357 goto out_unlock;358 359 ret = fxas21002c_mode_set(data, data->prev_mode);360 361out_unlock:362 mutex_unlock(&data->lock);363 364 return ret;365}366 367static int fxas21002c_pm_get(struct fxas21002c_data *data)368{369 return pm_runtime_resume_and_get(regmap_get_device(data->regmap));370}371 372static int fxas21002c_pm_put(struct fxas21002c_data *data)373{374 struct device *dev = regmap_get_device(data->regmap);375 376 pm_runtime_mark_last_busy(dev);377 378 return pm_runtime_put_autosuspend(dev);379}380 381static int fxas21002c_temp_get(struct fxas21002c_data *data, int *val)382{383 struct device *dev = regmap_get_device(data->regmap);384 unsigned int temp;385 int ret;386 387 mutex_lock(&data->lock);388 ret = fxas21002c_pm_get(data);389 if (ret < 0)390 goto data_unlock;391 392 ret = regmap_field_read(data->regmap_fields[F_TEMP], &temp);393 if (ret < 0) {394 dev_err(dev, "failed to read temp: %d\n", ret);395 fxas21002c_pm_put(data);396 goto data_unlock;397 }398 399 *val = sign_extend32(temp, 7);400 401 ret = fxas21002c_pm_put(data);402 if (ret < 0)403 goto data_unlock;404 405 ret = IIO_VAL_INT;406 407data_unlock:408 mutex_unlock(&data->lock);409 410 return ret;411}412 413static int fxas21002c_axis_get(struct fxas21002c_data *data,414 int index, int *val)415{416 struct device *dev = regmap_get_device(data->regmap);417 __be16 axis_be;418 int ret;419 420 mutex_lock(&data->lock);421 ret = fxas21002c_pm_get(data);422 if (ret < 0)423 goto data_unlock;424 425 ret = regmap_bulk_read(data->regmap, FXAS21002C_AXIS_TO_REG(index),426 &axis_be, sizeof(axis_be));427 if (ret < 0) {428 dev_err(dev, "failed to read axis: %d: %d\n", index, ret);429 fxas21002c_pm_put(data);430 goto data_unlock;431 }432 433 *val = sign_extend32(be16_to_cpu(axis_be), 15);434 435 ret = fxas21002c_pm_put(data);436 if (ret < 0)437 goto data_unlock;438 439 ret = IIO_VAL_INT;440 441data_unlock:442 mutex_unlock(&data->lock);443 444 return ret;445}446 447static int fxas21002c_odr_get(struct fxas21002c_data *data, int *odr)448{449 unsigned int odr_bits;450 int ret;451 452 mutex_lock(&data->lock);453 ret = regmap_field_read(data->regmap_fields[F_DR], &odr_bits);454 if (ret < 0)455 goto data_unlock;456 457 *odr = fxas21002c_odr_hz_from_value(data, odr_bits);458 459 ret = IIO_VAL_INT;460 461data_unlock:462 mutex_unlock(&data->lock);463 464 return ret;465}466 467static int fxas21002c_odr_set(struct fxas21002c_data *data, int odr)468{469 int odr_bits;470 471 odr_bits = fxas21002c_odr_value_from_hz(data, odr);472 if (odr_bits < 0)473 return odr_bits;474 475 return fxas21002c_write(data, F_DR, odr_bits);476}477 478static int fxas21002c_lpf_get(struct fxas21002c_data *data, int *val2)479{480 unsigned int bw_bits;481 int ret;482 483 mutex_lock(&data->lock);484 ret = regmap_field_read(data->regmap_fields[F_BW], &bw_bits);485 if (ret < 0)486 goto data_unlock;487 488 *val2 = fxas21002c_lpf_bw_from_value(data, bw_bits) * 10000;489 490 ret = IIO_VAL_INT_PLUS_MICRO;491 492data_unlock:493 mutex_unlock(&data->lock);494 495 return ret;496}497 498static int fxas21002c_lpf_set(struct fxas21002c_data *data, int bw)499{500 int bw_bits;501 int odr;502 int ret;503 504 bw_bits = fxas21002c_lpf_value_from_bw(data, bw);505 if (bw_bits < 0)506 return bw_bits;507 508 /*509 * From table 33 of the device spec, for ODR = 25Hz and 12.5 value 0.08510 * is not allowed and for ODR = 12.5 value 0.16 is also not allowed511 */512 ret = fxas21002c_odr_get(data, &odr);513 if (ret < 0)514 return -EINVAL;515 516 if ((odr == 25 && bw_bits > 0x01) || (odr == 12 && bw_bits > 0))517 return -EINVAL;518 519 return fxas21002c_write(data, F_BW, bw_bits);520}521 522static int fxas21002c_hpf_get(struct fxas21002c_data *data, int *val2)523{524 unsigned int sel_bits;525 int ret;526 527 mutex_lock(&data->lock);528 ret = regmap_field_read(data->regmap_fields[F_SEL], &sel_bits);529 if (ret < 0)530 goto data_unlock;531 532 *val2 = fxas21002c_hpf_sel_from_value(data, sel_bits);533 534 ret = IIO_VAL_INT_PLUS_MICRO;535 536data_unlock:537 mutex_unlock(&data->lock);538 539 return ret;540}541 542static int fxas21002c_hpf_set(struct fxas21002c_data *data, int sel)543{544 int sel_bits;545 546 sel_bits = fxas21002c_hpf_value_from_sel(data, sel);547 if (sel_bits < 0)548 return sel_bits;549 550 return fxas21002c_write(data, F_SEL, sel_bits);551}552 553static int fxas21002c_scale_get(struct fxas21002c_data *data, int *val)554{555 int fs_bits;556 int scale;557 int ret;558 559 mutex_lock(&data->lock);560 ret = regmap_field_read(data->regmap_fields[F_FS], &fs_bits);561 if (ret < 0)562 goto data_unlock;563 564 scale = fxas21002c_range_fs_from_value(data, fs_bits);565 if (scale < 0) {566 ret = scale;567 goto data_unlock;568 }569 570 *val = scale;571 572data_unlock:573 mutex_unlock(&data->lock);574 575 return ret;576}577 578static int fxas21002c_scale_set(struct fxas21002c_data *data, int range)579{580 int fs_bits;581 582 fs_bits = fxas21002c_range_value_from_fs(data, range);583 if (fs_bits < 0)584 return fs_bits;585 586 return fxas21002c_write(data, F_FS, fs_bits);587}588 589static int fxas21002c_read_raw(struct iio_dev *indio_dev,590 struct iio_chan_spec const *chan, int *val,591 int *val2, long mask)592{593 struct fxas21002c_data *data = iio_priv(indio_dev);594 int ret;595 596 switch (mask) {597 case IIO_CHAN_INFO_RAW:598 switch (chan->type) {599 case IIO_TEMP:600 return fxas21002c_temp_get(data, val);601 case IIO_ANGL_VEL:602 return fxas21002c_axis_get(data, chan->scan_index, val);603 default:604 return -EINVAL;605 }606 case IIO_CHAN_INFO_SCALE:607 switch (chan->type) {608 case IIO_ANGL_VEL:609 *val2 = FXAS21002C_SCALE_FRACTIONAL;610 ret = fxas21002c_scale_get(data, val);611 if (ret < 0)612 return ret;613 614 return IIO_VAL_FRACTIONAL;615 default:616 return -EINVAL;617 }618 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:619 *val = 0;620 return fxas21002c_lpf_get(data, val2);621 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:622 *val = 0;623 return fxas21002c_hpf_get(data, val2);624 case IIO_CHAN_INFO_SAMP_FREQ:625 *val2 = 0;626 return fxas21002c_odr_get(data, val);627 default:628 return -EINVAL;629 }630}631 632static int fxas21002c_write_raw(struct iio_dev *indio_dev,633 struct iio_chan_spec const *chan, int val,634 int val2, long mask)635{636 struct fxas21002c_data *data = iio_priv(indio_dev);637 int range;638 639 switch (mask) {640 case IIO_CHAN_INFO_SAMP_FREQ:641 if (val2)642 return -EINVAL;643 644 return fxas21002c_odr_set(data, val);645 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:646 if (val)647 return -EINVAL;648 649 val2 = val2 / 10000;650 return fxas21002c_lpf_set(data, val2);651 case IIO_CHAN_INFO_SCALE:652 switch (chan->type) {653 case IIO_ANGL_VEL:654 range = (((val * 1000 + val2 / 1000) *655 FXAS21002C_SCALE_FRACTIONAL) / 1000);656 return fxas21002c_scale_set(data, range);657 default:658 return -EINVAL;659 }660 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:661 return fxas21002c_hpf_set(data, val2);662 default:663 return -EINVAL;664 }665}666 667static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("12.5 25 50 100 200 400 800");668 669static IIO_CONST_ATTR(in_anglvel_filter_low_pass_3db_frequency_available,670 "0.32 0.16 0.08");671 672static IIO_CONST_ATTR(in_anglvel_filter_high_pass_3db_frequency_available,673 "0.018750 0.009625 0.004875 0.002475");674 675static IIO_CONST_ATTR(in_anglvel_scale_available,676 "125.0 62.5 31.25 15.625 7.8125");677 678static struct attribute *fxas21002c_attributes[] = {679 &iio_const_attr_sampling_frequency_available.dev_attr.attr,680 &iio_const_attr_in_anglvel_filter_low_pass_3db_frequency_available.dev_attr.attr,681 &iio_const_attr_in_anglvel_filter_high_pass_3db_frequency_available.dev_attr.attr,682 &iio_const_attr_in_anglvel_scale_available.dev_attr.attr,683 NULL,684};685 686static const struct attribute_group fxas21002c_attrs_group = {687 .attrs = fxas21002c_attributes,688};689 690#define FXAS21002C_CHANNEL(_axis) { \691 .type = IIO_ANGL_VEL, \692 .modified = 1, \693 .channel2 = IIO_MOD_##_axis, \694 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \695 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \696 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \697 BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) | \698 BIT(IIO_CHAN_INFO_SAMP_FREQ), \699 .scan_index = CHANNEL_SCAN_INDEX_##_axis, \700 .scan_type = { \701 .sign = 's', \702 .realbits = 16, \703 .storagebits = 16, \704 .endianness = IIO_BE, \705 }, \706}707 708static const struct iio_chan_spec fxas21002c_channels[] = {709 {710 .type = IIO_TEMP,711 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),712 .scan_index = -1,713 },714 FXAS21002C_CHANNEL(X),715 FXAS21002C_CHANNEL(Y),716 FXAS21002C_CHANNEL(Z),717};718 719static const struct iio_info fxas21002c_info = {720 .attrs = &fxas21002c_attrs_group,721 .read_raw = &fxas21002c_read_raw,722 .write_raw = &fxas21002c_write_raw,723};724 725static irqreturn_t fxas21002c_trigger_handler(int irq, void *p)726{727 struct iio_poll_func *pf = p;728 struct iio_dev *indio_dev = pf->indio_dev;729 struct fxas21002c_data *data = iio_priv(indio_dev);730 int ret;731 732 mutex_lock(&data->lock);733 ret = regmap_bulk_read(data->regmap, FXAS21002C_REG_OUT_X_MSB,734 data->buffer, CHANNEL_SCAN_MAX * sizeof(s16));735 if (ret < 0)736 goto out_unlock;737 738 iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,739 data->timestamp);740 741out_unlock:742 mutex_unlock(&data->lock);743 744 iio_trigger_notify_done(indio_dev->trig);745 746 return IRQ_HANDLED;747}748 749static int fxas21002c_chip_init(struct fxas21002c_data *data)750{751 struct device *dev = regmap_get_device(data->regmap);752 unsigned int chip_id;753 int ret;754 755 ret = regmap_field_read(data->regmap_fields[F_WHO_AM_I], &chip_id);756 if (ret < 0)757 return ret;758 759 if (chip_id != FXAS21002C_CHIP_ID_1 &&760 chip_id != FXAS21002C_CHIP_ID_2) {761 dev_err(dev, "chip id 0x%02x is not supported\n", chip_id);762 return -EINVAL;763 }764 765 data->chip_id = chip_id;766 767 ret = fxas21002c_mode_set(data, FXAS21002C_MODE_STANDBY);768 if (ret < 0)769 return ret;770 771 /* Set ODR to 200HZ as default */772 ret = fxas21002c_odr_set(data, 200);773 if (ret < 0)774 dev_err(dev, "failed to set ODR: %d\n", ret);775 776 return ret;777}778 779static int fxas21002c_data_rdy_trigger_set_state(struct iio_trigger *trig,780 bool state)781{782 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);783 struct fxas21002c_data *data = iio_priv(indio_dev);784 785 return regmap_field_write(data->regmap_fields[F_INT_EN_DRDY], state);786}787 788static const struct iio_trigger_ops fxas21002c_trigger_ops = {789 .set_trigger_state = &fxas21002c_data_rdy_trigger_set_state,790};791 792static irqreturn_t fxas21002c_data_rdy_handler(int irq, void *private)793{794 struct iio_dev *indio_dev = private;795 struct fxas21002c_data *data = iio_priv(indio_dev);796 797 data->timestamp = iio_get_time_ns(indio_dev);798 799 return IRQ_WAKE_THREAD;800}801 802static irqreturn_t fxas21002c_data_rdy_thread(int irq, void *private)803{804 struct iio_dev *indio_dev = private;805 struct fxas21002c_data *data = iio_priv(indio_dev);806 unsigned int data_ready;807 int ret;808 809 ret = regmap_field_read(data->regmap_fields[F_SRC_DRDY], &data_ready);810 if (ret < 0)811 return IRQ_NONE;812 813 if (!data_ready)814 return IRQ_NONE;815 816 iio_trigger_poll_nested(data->dready_trig);817 818 return IRQ_HANDLED;819}820 821static int fxas21002c_trigger_probe(struct fxas21002c_data *data)822{823 struct device *dev = regmap_get_device(data->regmap);824 struct iio_dev *indio_dev = dev_get_drvdata(dev);825 unsigned long irq_trig;826 bool irq_open_drain;827 int irq1;828 int ret;829 830 if (!data->irq)831 return 0;832 833 irq1 = fwnode_irq_get_byname(dev_fwnode(dev), "INT1");834 if (irq1 == data->irq) {835 dev_info(dev, "using interrupt line INT1\n");836 ret = regmap_field_write(data->regmap_fields[F_INT_CFG_DRDY],837 1);838 if (ret < 0)839 return ret;840 }841 842 dev_info(dev, "using interrupt line INT2\n");843 844 irq_open_drain = device_property_read_bool(dev, "drive-open-drain");845 846 data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d",847 indio_dev->name,848 iio_device_id(indio_dev));849 if (!data->dready_trig)850 return -ENOMEM;851 852 irq_trig = irqd_get_trigger_type(irq_get_irq_data(data->irq));853 854 if (irq_trig == IRQF_TRIGGER_RISING) {855 ret = regmap_field_write(data->regmap_fields[F_IPOL], 1);856 if (ret < 0)857 return ret;858 }859 860 if (irq_open_drain)861 irq_trig |= IRQF_SHARED;862 863 ret = devm_request_threaded_irq(dev, data->irq,864 fxas21002c_data_rdy_handler,865 fxas21002c_data_rdy_thread,866 irq_trig, "fxas21002c_data_ready",867 indio_dev);868 if (ret < 0)869 return ret;870 871 data->dready_trig->ops = &fxas21002c_trigger_ops;872 iio_trigger_set_drvdata(data->dready_trig, indio_dev);873 874 return devm_iio_trigger_register(dev, data->dready_trig);875}876 877static int fxas21002c_power_enable(struct fxas21002c_data *data)878{879 int ret;880 881 ret = regulator_enable(data->vdd);882 if (ret < 0)883 return ret;884 885 ret = regulator_enable(data->vddio);886 if (ret < 0) {887 regulator_disable(data->vdd);888 return ret;889 }890 891 return 0;892}893 894static void fxas21002c_power_disable(struct fxas21002c_data *data)895{896 regulator_disable(data->vdd);897 regulator_disable(data->vddio);898}899 900static void fxas21002c_power_disable_action(void *_data)901{902 struct fxas21002c_data *data = _data;903 904 fxas21002c_power_disable(data);905}906 907static int fxas21002c_regulators_get(struct fxas21002c_data *data)908{909 struct device *dev = regmap_get_device(data->regmap);910 911 data->vdd = devm_regulator_get(dev->parent, "vdd");912 if (IS_ERR(data->vdd))913 return PTR_ERR(data->vdd);914 915 data->vddio = devm_regulator_get(dev->parent, "vddio");916 917 return PTR_ERR_OR_ZERO(data->vddio);918}919 920int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq,921 const char *name)922{923 struct fxas21002c_data *data;924 struct iio_dev *indio_dev;925 struct regmap_field *f;926 int i;927 int ret;928 929 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));930 if (!indio_dev)931 return -ENOMEM;932 933 data = iio_priv(indio_dev);934 dev_set_drvdata(dev, indio_dev);935 data->irq = irq;936 data->regmap = regmap;937 938 for (i = 0; i < F_MAX_FIELDS; i++) {939 f = devm_regmap_field_alloc(dev, data->regmap,940 fxas21002c_reg_fields[i]);941 if (IS_ERR(f))942 return PTR_ERR(f);943 944 data->regmap_fields[i] = f;945 }946 947 mutex_init(&data->lock);948 949 ret = fxas21002c_regulators_get(data);950 if (ret < 0)951 return ret;952 953 ret = fxas21002c_power_enable(data);954 if (ret < 0)955 return ret;956 957 ret = devm_add_action_or_reset(dev, fxas21002c_power_disable_action,958 data);959 if (ret < 0)960 return ret;961 962 ret = fxas21002c_chip_init(data);963 if (ret < 0)964 return ret;965 966 indio_dev->channels = fxas21002c_channels;967 indio_dev->num_channels = ARRAY_SIZE(fxas21002c_channels);968 indio_dev->name = name;969 indio_dev->modes = INDIO_DIRECT_MODE;970 indio_dev->info = &fxas21002c_info;971 972 ret = fxas21002c_trigger_probe(data);973 if (ret < 0)974 return ret;975 976 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,977 fxas21002c_trigger_handler, NULL);978 if (ret < 0)979 return ret;980 981 ret = pm_runtime_set_active(dev);982 if (ret)983 return ret;984 985 pm_runtime_enable(dev);986 pm_runtime_set_autosuspend_delay(dev, 2000);987 pm_runtime_use_autosuspend(dev);988 989 ret = iio_device_register(indio_dev);990 if (ret < 0)991 goto pm_disable;992 993 return 0;994 995pm_disable:996 pm_runtime_disable(dev);997 pm_runtime_set_suspended(dev);998 999 return ret;1000}1001EXPORT_SYMBOL_NS_GPL(fxas21002c_core_probe, IIO_FXAS21002C);1002 1003void fxas21002c_core_remove(struct device *dev)1004{1005 struct iio_dev *indio_dev = dev_get_drvdata(dev);1006 1007 iio_device_unregister(indio_dev);1008 1009 pm_runtime_disable(dev);1010 pm_runtime_set_suspended(dev);1011}1012EXPORT_SYMBOL_NS_GPL(fxas21002c_core_remove, IIO_FXAS21002C);1013 1014static int fxas21002c_suspend(struct device *dev)1015{1016 struct fxas21002c_data *data = iio_priv(dev_get_drvdata(dev));1017 1018 fxas21002c_mode_set(data, FXAS21002C_MODE_STANDBY);1019 fxas21002c_power_disable(data);1020 1021 return 0;1022}1023 1024static int fxas21002c_resume(struct device *dev)1025{1026 struct fxas21002c_data *data = iio_priv(dev_get_drvdata(dev));1027 int ret;1028 1029 ret = fxas21002c_power_enable(data);1030 if (ret < 0)1031 return ret;1032 1033 return fxas21002c_mode_set(data, data->prev_mode);1034}1035 1036static int fxas21002c_runtime_suspend(struct device *dev)1037{1038 struct fxas21002c_data *data = iio_priv(dev_get_drvdata(dev));1039 1040 return fxas21002c_mode_set(data, FXAS21002C_MODE_READY);1041}1042 1043static int fxas21002c_runtime_resume(struct device *dev)1044{1045 struct fxas21002c_data *data = iio_priv(dev_get_drvdata(dev));1046 1047 return fxas21002c_mode_set(data, FXAS21002C_MODE_ACTIVE);1048}1049 1050EXPORT_NS_GPL_DEV_PM_OPS(fxas21002c_pm_ops, IIO_FXAS21002C) = {1051 SYSTEM_SLEEP_PM_OPS(fxas21002c_suspend, fxas21002c_resume)1052 RUNTIME_PM_OPS(fxas21002c_runtime_suspend, fxas21002c_runtime_resume,1053 NULL)1054};1055 1056MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>");1057MODULE_LICENSE("GPL v2");1058MODULE_DESCRIPTION("FXAS21002C Gyro driver");1059