brintos

brintos / linux-shallow public Read only

0
0
Text · 25.7 KiB · c28d17c Raw
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