brintos

brintos / linux-shallow public Read only

0
0
Text · 57.8 KiB · e1f3b0d Raw
2306 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * IIO core driver for Bosch BMI323 6-Axis IMU.4 *5 * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com>6 *7 * Datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi323-ds000.pdf8 */9 10#include <linux/bitfield.h>11#include <linux/cleanup.h>12#include <linux/device.h>13#include <linux/interrupt.h>14#include <linux/minmax.h>15#include <linux/module.h>16#include <linux/mutex.h>17#include <linux/property.h>18#include <linux/regmap.h>19#include <linux/regulator/consumer.h>20#include <linux/units.h>21 22#include <linux/unaligned.h>23 24#include <linux/iio/buffer.h>25#include <linux/iio/events.h>26#include <linux/iio/iio.h>27#include <linux/iio/sysfs.h>28#include <linux/iio/trigger.h>29#include <linux/iio/trigger_consumer.h>30#include <linux/iio/triggered_buffer.h>31 32#include "bmi323.h"33 34enum bmi323_sensor_type {35	BMI323_ACCEL,36	BMI323_GYRO,37	BMI323_SENSORS_CNT,38};39 40enum bmi323_opr_mode {41	ACC_GYRO_MODE_DISABLE = 0x00,42	GYRO_DRIVE_MODE_ENABLED = 0x01,43	ACC_GYRO_MODE_DUTYCYCLE = 0x03,44	ACC_GYRO_MODE_CONTINOUS = 0x04,45	ACC_GYRO_MODE_HIGH_PERF = 0x07,46};47 48enum bmi323_state {49	BMI323_IDLE,50	BMI323_BUFFER_DRDY_TRIGGERED,51	BMI323_BUFFER_FIFO,52};53 54enum bmi323_irq_pin {55	BMI323_IRQ_DISABLED,56	BMI323_IRQ_INT1,57	BMI323_IRQ_INT2,58};59 60enum bmi323_3db_bw {61	BMI323_BW_ODR_BY_2,62	BMI323_BW_ODR_BY_4,63};64 65enum bmi323_scan {66	BMI323_ACCEL_X,67	BMI323_ACCEL_Y,68	BMI323_ACCEL_Z,69	BMI323_GYRO_X,70	BMI323_GYRO_Y,71	BMI323_GYRO_Z,72	BMI323_CHAN_MAX73};74 75struct bmi323_hw {76	u8 data;77	u8 config;78	const int (*scale_table)[2];79	int scale_table_len;80};81 82/*83 * The accelerometer supports +-2G/4G/8G/16G ranges, and the resolution of84 * each sample is 16 bits, signed.85 * At +-8G the scale can calculated by86 * ((8 + 8) * 9.80665 / (2^16 - 1)) * 10^6 = 2394.23819 scale in micro87 *88 */89static const int bmi323_accel_scale[][2] = {90	{ 0, 598 },91	{ 0, 1197 },92	{ 0, 2394 },93	{ 0, 4788 },94};95 96static const int bmi323_gyro_scale[][2] = {97	{ 0, 66 },98	{ 0, 133 },99	{ 0, 266 },100	{ 0, 532 },101	{ 0, 1065 },102};103 104static const int bmi323_accel_gyro_avrg[] = {0, 2, 4, 8, 16, 32, 64};105 106static const struct bmi323_hw bmi323_hw[2] = {107	[BMI323_ACCEL] = {108		.data = BMI323_ACCEL_X_REG,109		.config = BMI323_ACC_CONF_REG,110		.scale_table = bmi323_accel_scale,111		.scale_table_len = ARRAY_SIZE(bmi323_accel_scale),112	},113	[BMI323_GYRO] = {114		.data = BMI323_GYRO_X_REG,115		.config = BMI323_GYRO_CONF_REG,116		.scale_table = bmi323_gyro_scale,117		.scale_table_len = ARRAY_SIZE(bmi323_gyro_scale),118	},119};120 121static const unsigned int bmi323_reg_savestate[] = {122	BMI323_INT_MAP1_REG,123	BMI323_INT_MAP2_REG,124	BMI323_IO_INT_CTR_REG,125	BMI323_IO_INT_CONF_REG,126	BMI323_ACC_CONF_REG,127	BMI323_GYRO_CONF_REG,128	BMI323_FEAT_IO0_REG,129	BMI323_FIFO_WTRMRK_REG,130	BMI323_FIFO_CONF_REG131};132 133static const unsigned int bmi323_ext_reg_savestate[] = {134	BMI323_GEN_SET1_REG,135	BMI323_TAP1_REG,136	BMI323_TAP2_REG,137	BMI323_TAP3_REG,138	BMI323_FEAT_IO0_S_TAP_MSK,139	BMI323_STEP_SC1_REG,140	BMI323_ANYMO1_REG,141	BMI323_NOMO1_REG,142	BMI323_ANYMO1_REG + BMI323_MO2_OFFSET,143	BMI323_NOMO1_REG + BMI323_MO2_OFFSET,144	BMI323_ANYMO1_REG + BMI323_MO3_OFFSET,145	BMI323_NOMO1_REG + BMI323_MO3_OFFSET146};147 148struct bmi323_regs_runtime_pm {149	unsigned int reg_settings[ARRAY_SIZE(bmi323_reg_savestate)];150	unsigned int ext_reg_settings[ARRAY_SIZE(bmi323_ext_reg_savestate)];151};152 153struct bmi323_data {154	struct device *dev;155	struct regmap *regmap;156	struct iio_mount_matrix orientation;157	enum bmi323_irq_pin irq_pin;158	struct iio_trigger *trig;159	bool drdy_trigger_enabled;160	enum bmi323_state state;161	s64 fifo_tstamp, old_fifo_tstamp;162	u32 odrns[BMI323_SENSORS_CNT];163	u32 odrhz[BMI323_SENSORS_CNT];164	unsigned int feature_events;165	struct bmi323_regs_runtime_pm runtime_pm_status;166 167	/*168	 * Lock to protect the members of device's private data from concurrent169	 * access and also to serialize the access of extended registers.170	 * See bmi323_write_ext_reg(..) for more info.171	 */172	struct mutex mutex;173	int watermark;174	__le16 fifo_buff[BMI323_FIFO_FULL_IN_WORDS] __aligned(IIO_DMA_MINALIGN);175	struct {176		__le16 channels[BMI323_CHAN_MAX];177		s64 ts __aligned(8);178	} buffer;179	__le16 steps_count[BMI323_STEP_LEN];180};181 182static const struct iio_mount_matrix *183bmi323_get_mount_matrix(const struct iio_dev *idev,184			const struct iio_chan_spec *chan)185{186	struct bmi323_data *data = iio_priv(idev);187 188	return &data->orientation;189}190 191static const struct iio_chan_spec_ext_info bmi323_ext_info[] = {192	IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, bmi323_get_mount_matrix),193	{ }194};195 196static const struct iio_event_spec bmi323_step_wtrmrk_event = {197	.type = IIO_EV_TYPE_CHANGE,198	.dir = IIO_EV_DIR_NONE,199	.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |200			       BIT(IIO_EV_INFO_VALUE),201};202 203static const struct iio_event_spec bmi323_accel_event[] = {204	{205		.type = IIO_EV_TYPE_MAG,206		.dir = IIO_EV_DIR_FALLING,207		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |208				       BIT(IIO_EV_INFO_PERIOD) |209				       BIT(IIO_EV_INFO_HYSTERESIS) |210				       BIT(IIO_EV_INFO_ENABLE),211	},212	{213		.type = IIO_EV_TYPE_MAG,214		.dir = IIO_EV_DIR_RISING,215		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |216				       BIT(IIO_EV_INFO_PERIOD) |217				       BIT(IIO_EV_INFO_HYSTERESIS) |218				       BIT(IIO_EV_INFO_ENABLE),219	},220	{221		.type = IIO_EV_TYPE_GESTURE,222		.dir = IIO_EV_DIR_SINGLETAP,223		.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |224				       BIT(IIO_EV_INFO_VALUE) |225				       BIT(IIO_EV_INFO_RESET_TIMEOUT),226	},227	{228		.type = IIO_EV_TYPE_GESTURE,229		.dir = IIO_EV_DIR_DOUBLETAP,230		.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |231				       BIT(IIO_EV_INFO_VALUE) |232				       BIT(IIO_EV_INFO_RESET_TIMEOUT) |233				       BIT(IIO_EV_INFO_TAP2_MIN_DELAY),234	},235};236 237#define BMI323_ACCEL_CHANNEL(_type, _axis, _index) {			\238	.type = _type,							\239	.modified = 1,							\240	.channel2 = IIO_MOD_##_axis,					\241	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\242	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |	\243				    BIT(IIO_CHAN_INFO_SCALE) |		\244				    BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \245	.info_mask_shared_by_type_available =				\246				    BIT(IIO_CHAN_INFO_SAMP_FREQ) |	\247				    BIT(IIO_CHAN_INFO_SCALE) |		\248				    BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \249	.scan_index = _index,						\250	.scan_type = {							\251		.sign = 's',						\252		.realbits = 16,						\253		.storagebits = 16,					\254		.endianness = IIO_LE,					\255	},								\256	.ext_info = bmi323_ext_info,					\257	.event_spec = bmi323_accel_event,				\258	.num_event_specs = ARRAY_SIZE(bmi323_accel_event),		\259}260 261#define BMI323_GYRO_CHANNEL(_type, _axis, _index) {			\262	.type = _type,							\263	.modified = 1,							\264	.channel2 = IIO_MOD_##_axis,					\265	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\266	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |	\267				    BIT(IIO_CHAN_INFO_SCALE) |		\268				    BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \269	.info_mask_shared_by_type_available =				\270				    BIT(IIO_CHAN_INFO_SAMP_FREQ) |	\271				    BIT(IIO_CHAN_INFO_SCALE) |		\272				    BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \273	.scan_index = _index,						\274	.scan_type = {							\275		.sign = 's',						\276		.realbits = 16,						\277		.storagebits = 16,					\278		.endianness = IIO_LE,					\279	},								\280	.ext_info = bmi323_ext_info,					\281}282 283static const struct iio_chan_spec bmi323_channels[] = {284	BMI323_ACCEL_CHANNEL(IIO_ACCEL, X, BMI323_ACCEL_X),285	BMI323_ACCEL_CHANNEL(IIO_ACCEL, Y, BMI323_ACCEL_Y),286	BMI323_ACCEL_CHANNEL(IIO_ACCEL, Z, BMI323_ACCEL_Z),287	BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, X, BMI323_GYRO_X),288	BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, Y, BMI323_GYRO_Y),289	BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, Z, BMI323_GYRO_Z),290	{291		.type = IIO_TEMP,292		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |293				      BIT(IIO_CHAN_INFO_OFFSET) |294				      BIT(IIO_CHAN_INFO_SCALE),295		.scan_index = -1,296	},297	{298		.type = IIO_STEPS,299		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |300				      BIT(IIO_CHAN_INFO_ENABLE),301		.scan_index = -1,302		.event_spec = &bmi323_step_wtrmrk_event,303		.num_event_specs = 1,304 305	},306	IIO_CHAN_SOFT_TIMESTAMP(BMI323_CHAN_MAX),307};308 309static const int bmi323_acc_gyro_odr[][2] = {310	{ 0, 781250 },311	{ 1, 562500 },312	{ 3, 125000 },313	{ 6, 250000 },314	{ 12, 500000 },315	{ 25, 0 },316	{ 50, 0 },317	{ 100, 0 },318	{ 200, 0 },319	{ 400, 0 },320	{ 800, 0 },321};322 323static const int bmi323_acc_gyro_odrns[] = {324	1280 * MEGA,325	640 * MEGA,326	320 * MEGA,327	160 * MEGA,328	80 * MEGA,329	40 * MEGA,330	20 * MEGA,331	10 * MEGA,332	5 * MEGA,333	2500 * KILO,334	1250 * KILO,335};336 337static enum bmi323_sensor_type bmi323_iio_to_sensor(enum iio_chan_type iio_type)338{339	switch (iio_type) {340	case IIO_ACCEL:341		return BMI323_ACCEL;342	case IIO_ANGL_VEL:343		return BMI323_GYRO;344	default:345		return -EINVAL;346	}347}348 349static int bmi323_set_mode(struct bmi323_data *data,350			   enum bmi323_sensor_type sensor,351			   enum bmi323_opr_mode mode)352{353	guard(mutex)(&data->mutex);354	return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,355				  BMI323_ACC_GYRO_CONF_MODE_MSK,356				  FIELD_PREP(BMI323_ACC_GYRO_CONF_MODE_MSK,357					     mode));358}359 360/*361 * When writing data to extended register there must be no communication to362 * any other register before write transaction is complete.363 * See datasheet section 6.2 Extended Register Map Description.364 */365static int bmi323_write_ext_reg(struct bmi323_data *data, unsigned int ext_addr,366				unsigned int ext_data)367{368	int ret, feature_status;369 370	ret = regmap_read(data->regmap, BMI323_FEAT_DATA_STATUS,371			  &feature_status);372	if (ret)373		return ret;374 375	if (!FIELD_GET(BMI323_FEAT_DATA_TX_RDY_MSK, feature_status))376		return -EBUSY;377 378	ret = regmap_write(data->regmap, BMI323_FEAT_DATA_ADDR, ext_addr);379	if (ret)380		return ret;381 382	return regmap_write(data->regmap, BMI323_FEAT_DATA_TX, ext_data);383}384 385/*386 * When reading data from extended register there must be no communication to387 * any other register before read transaction is complete.388 * See datasheet section 6.2 Extended Register Map Description.389 */390static int bmi323_read_ext_reg(struct bmi323_data *data, unsigned int ext_addr,391			       unsigned int *ext_data)392{393	int ret, feature_status;394 395	ret = regmap_read(data->regmap, BMI323_FEAT_DATA_STATUS,396			  &feature_status);397	if (ret)398		return ret;399 400	if (!FIELD_GET(BMI323_FEAT_DATA_TX_RDY_MSK, feature_status))401		return -EBUSY;402 403	ret = regmap_write(data->regmap, BMI323_FEAT_DATA_ADDR, ext_addr);404	if (ret)405		return ret;406 407	return regmap_read(data->regmap, BMI323_FEAT_DATA_TX, ext_data);408}409 410static int bmi323_update_ext_reg(struct bmi323_data *data,411				 unsigned int ext_addr,412				 unsigned int mask, unsigned int ext_data)413{414	unsigned int value;415	int ret;416 417	ret = bmi323_read_ext_reg(data, ext_addr, &value);418	if (ret)419		return ret;420 421	set_mask_bits(&value, mask, ext_data);422 423	return bmi323_write_ext_reg(data, ext_addr, value);424}425 426static int bmi323_get_error_status(struct bmi323_data *data)427{428	int error, ret;429 430	guard(mutex)(&data->mutex);431	ret = regmap_read(data->regmap, BMI323_ERR_REG, &error);432	if (ret)433		return ret;434 435	if (error)436		dev_err(data->dev, "Sensor error 0x%x\n", error);437 438	return error;439}440 441static int bmi323_feature_engine_events(struct bmi323_data *data,442					const unsigned int event_mask,443					bool state)444{445	unsigned int value;446	int ret;447 448	ret = regmap_read(data->regmap, BMI323_FEAT_IO0_REG, &value);449	if (ret)450		return ret;451 452	/* Register must be cleared before changing an active config */453	ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, 0);454	if (ret)455		return ret;456 457	if (state)458		value |= event_mask;459	else460		value &= ~event_mask;461 462	ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, value);463	if (ret)464		return ret;465 466	return regmap_write(data->regmap, BMI323_FEAT_IO_STATUS_REG,467			    BMI323_FEAT_IO_STATUS_MSK);468}469 470static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)471{472	enum bmi323_irq_pin step_irq;473	int ret;474 475	guard(mutex)(&data->mutex);476	if (!FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, data->feature_events))477		return -EINVAL;478 479	if (state)480		step_irq = data->irq_pin;481	else482		step_irq = BMI323_IRQ_DISABLED;483 484	ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,485				    BMI323_STEP_SC1_WTRMRK_MSK,486				    FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,487					       state ? 1 : 0));488	if (ret)489		return ret;490 491	return regmap_update_bits(data->regmap, BMI323_INT_MAP1_REG,492				  BMI323_STEP_CNT_MSK,493				  FIELD_PREP(BMI323_STEP_CNT_MSK, step_irq));494}495 496static int bmi323_motion_config_reg(enum iio_event_direction dir)497{498	switch (dir) {499	case IIO_EV_DIR_RISING:500		return BMI323_ANYMO1_REG;501	case IIO_EV_DIR_FALLING:502		return BMI323_NOMO1_REG;503	default:504		return -EINVAL;505	}506}507 508static int bmi323_motion_event_en(struct bmi323_data *data,509				  enum iio_event_direction dir, int state)510{511	unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0;512	int config, ret, msk, raw, field_value;513	enum bmi323_irq_pin motion_irq;514	int irq_msk, irq_field_val;515 516	if (state)517		motion_irq = data->irq_pin;518	else519		motion_irq = BMI323_IRQ_DISABLED;520 521	switch (dir) {522	case IIO_EV_DIR_RISING:523		msk = BMI323_FEAT_IO0_XYZ_MOTION_MSK;524		raw = 512;525		config = BMI323_ANYMO1_REG;526		irq_msk = BMI323_MOTION_MSK;527		irq_field_val = FIELD_PREP(BMI323_MOTION_MSK, motion_irq);528		field_value = FIELD_PREP(BMI323_FEAT_IO0_XYZ_MOTION_MSK,529					 state_value);530		break;531	case IIO_EV_DIR_FALLING:532		msk = BMI323_FEAT_IO0_XYZ_NOMOTION_MSK;533		raw = 0;534		config = BMI323_NOMO1_REG;535		irq_msk = BMI323_NOMOTION_MSK;536		irq_field_val = FIELD_PREP(BMI323_NOMOTION_MSK, motion_irq);537		field_value = FIELD_PREP(BMI323_FEAT_IO0_XYZ_NOMOTION_MSK,538					 state_value);539		break;540	default:541		return -EINVAL;542	}543 544	guard(mutex)(&data->mutex);545	ret = bmi323_feature_engine_events(data, msk, state);546	if (ret)547		return ret;548 549	ret = bmi323_update_ext_reg(data, config,550				    BMI323_MO1_REF_UP_MSK,551				    FIELD_PREP(BMI323_MO1_REF_UP_MSK, 0));552	if (ret)553		return ret;554 555	/* Set initial value to avoid interrupts while enabling*/556	ret = bmi323_update_ext_reg(data, config,557				    BMI323_MO1_SLOPE_TH_MSK,558				    FIELD_PREP(BMI323_MO1_SLOPE_TH_MSK, raw));559	if (ret)560		return ret;561 562	ret = regmap_update_bits(data->regmap, BMI323_INT_MAP1_REG, irq_msk,563				 irq_field_val);564	if (ret)565		return ret;566 567	set_mask_bits(&data->feature_events, msk, field_value);568 569	return 0;570}571 572static int bmi323_tap_event_en(struct bmi323_data *data,573			       enum iio_event_direction dir, int state)574{575	enum bmi323_irq_pin tap_irq;576	int ret, tap_enabled;577 578	guard(mutex)(&data->mutex);579 580	if (data->odrhz[BMI323_ACCEL] < 200) {581		dev_err(data->dev, "Invalid accelerometer parameter\n");582		return -EINVAL;583	}584 585	switch (dir) {586	case IIO_EV_DIR_SINGLETAP:587		ret = bmi323_feature_engine_events(data,588						   BMI323_FEAT_IO0_S_TAP_MSK,589						   state);590		if (ret)591			return ret;592 593		set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_S_TAP_MSK,594			      FIELD_PREP(BMI323_FEAT_IO0_S_TAP_MSK, state));595		break;596	case IIO_EV_DIR_DOUBLETAP:597		ret = bmi323_feature_engine_events(data,598						   BMI323_FEAT_IO0_D_TAP_MSK,599						   state);600		if (ret)601			return ret;602 603		set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_D_TAP_MSK,604			      FIELD_PREP(BMI323_FEAT_IO0_D_TAP_MSK, state));605		break;606	default:607		return -EINVAL;608	}609 610	tap_enabled = FIELD_GET(BMI323_FEAT_IO0_S_TAP_MSK |611				BMI323_FEAT_IO0_D_TAP_MSK,612				data->feature_events);613 614	if (tap_enabled)615		tap_irq = data->irq_pin;616	else617		tap_irq = BMI323_IRQ_DISABLED;618 619	ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,620				 BMI323_TAP_MSK,621				 FIELD_PREP(BMI323_TAP_MSK, tap_irq));622	if (ret)623		return ret;624 625	if (!state)626		return 0;627 628	ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG,629				    BMI323_TAP1_MAX_PEAKS_MSK,630				    FIELD_PREP(BMI323_TAP1_MAX_PEAKS_MSK,631					       0x04));632	if (ret)633		return ret;634 635	ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG,636				    BMI323_TAP1_AXIS_SEL_MSK,637				    FIELD_PREP(BMI323_TAP1_AXIS_SEL_MSK,638					       BMI323_AXIS_XYZ_MSK));639	if (ret)640		return ret;641 642	return bmi323_update_ext_reg(data, BMI323_TAP1_REG,643				     BMI323_TAP1_TIMOUT_MSK,644				     FIELD_PREP(BMI323_TAP1_TIMOUT_MSK,645						0));646}647 648static ssize_t in_accel_gesture_tap_wait_dur_show(struct device *dev,649						  struct device_attribute *attr,650						  char *buf)651{652	struct iio_dev *indio_dev = dev_to_iio_dev(dev);653	struct bmi323_data *data = iio_priv(indio_dev);654	unsigned int reg_value, raw;655	int ret, val[2];656 657	scoped_guard(mutex, &data->mutex) {658		ret = bmi323_read_ext_reg(data, BMI323_TAP2_REG, &reg_value);659		if (ret)660			return ret;661	}662 663	raw = FIELD_GET(BMI323_TAP2_MAX_DUR_MSK, reg_value);664	val[0] = raw / BMI323_MAX_GES_DUR_SCALE;665	val[1] = BMI323_RAW_TO_MICRO(raw, BMI323_MAX_GES_DUR_SCALE);666 667	return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, ARRAY_SIZE(val),668				val);669}670 671static ssize_t in_accel_gesture_tap_wait_dur_store(struct device *dev,672						   struct device_attribute *attr,673						   const char *buf, size_t len)674{675	struct iio_dev *indio_dev = dev_to_iio_dev(dev);676	struct bmi323_data *data = iio_priv(indio_dev);677	int ret, val_int, val_fract, raw;678 679	ret = iio_str_to_fixpoint(buf, 100000, &val_int, &val_fract);680	if (ret)681		return ret;682 683	raw = BMI323_INT_MICRO_TO_RAW(val_int, val_fract,684				      BMI323_MAX_GES_DUR_SCALE);685	if (!in_range(raw, 0, 64))686		return -EINVAL;687 688	guard(mutex)(&data->mutex);689	ret = bmi323_update_ext_reg(data, BMI323_TAP2_REG,690				    BMI323_TAP2_MAX_DUR_MSK,691				    FIELD_PREP(BMI323_TAP2_MAX_DUR_MSK, raw));692	if (ret)693		return ret;694 695	return len;696}697 698/*699 * Maximum duration from first tap within the second tap is expected to happen.700 * This timeout is applicable only if gesture_tap_wait_timeout is enabled.701 */702static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_wait_dur, 0);703 704static ssize_t in_accel_gesture_tap_wait_timeout_show(struct device *dev,705						      struct device_attribute *attr,706						      char *buf)707{708	struct iio_dev *indio_dev = dev_to_iio_dev(dev);709	struct bmi323_data *data = iio_priv(indio_dev);710	unsigned int reg_value, raw;711	int ret;712 713	scoped_guard(mutex, &data->mutex) {714		ret = bmi323_read_ext_reg(data, BMI323_TAP1_REG, &reg_value);715		if (ret)716			return ret;717	}718 719	raw = FIELD_GET(BMI323_TAP1_TIMOUT_MSK, reg_value);720 721	return iio_format_value(buf, IIO_VAL_INT, 1, &raw);722}723 724static ssize_t in_accel_gesture_tap_wait_timeout_store(struct device *dev,725						       struct device_attribute *attr,726						       const char *buf,727						       size_t len)728{729	struct iio_dev *indio_dev = dev_to_iio_dev(dev);730	struct bmi323_data *data = iio_priv(indio_dev);731	bool val;732	int ret;733 734	ret = kstrtobool(buf, &val);735	if (ret)736		return ret;737 738	guard(mutex)(&data->mutex);739	ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG,740				    BMI323_TAP1_TIMOUT_MSK,741				    FIELD_PREP(BMI323_TAP1_TIMOUT_MSK, val));742	if (ret)743		return ret;744 745	return len;746}747 748/* Enable/disable gesture confirmation with wait time */749static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_wait_timeout, 0);750 751static IIO_CONST_ATTR(in_accel_gesture_tap_wait_dur_available,752		      "[0.0 0.04 2.52]");753 754static IIO_CONST_ATTR(in_accel_gesture_doubletap_tap2_min_delay_available,755		      "[0.005 0.005 0.075]");756 757static IIO_CONST_ATTR(in_accel_gesture_tap_reset_timeout_available,758		      "[0.04 0.04 0.6]");759 760static IIO_CONST_ATTR(in_accel_gesture_tap_value_available, "[0.0 0.002 1.99]");761 762static IIO_CONST_ATTR(in_accel_mag_value_available, "[0.0 0.002 7.99]");763 764static IIO_CONST_ATTR(in_accel_mag_period_available, "[0.0 0.02 162.0]");765 766static IIO_CONST_ATTR(in_accel_mag_hysteresis_available, "[0.0 0.002 1.99]");767 768static struct attribute *bmi323_event_attributes[] = {769	&iio_const_attr_in_accel_gesture_tap_value_available.dev_attr.attr,770	&iio_const_attr_in_accel_gesture_tap_reset_timeout_available.dev_attr.attr,771	&iio_const_attr_in_accel_gesture_doubletap_tap2_min_delay_available.dev_attr.attr,772	&iio_const_attr_in_accel_gesture_tap_wait_dur_available.dev_attr.attr,773	&iio_dev_attr_in_accel_gesture_tap_wait_timeout.dev_attr.attr,774	&iio_dev_attr_in_accel_gesture_tap_wait_dur.dev_attr.attr,775	&iio_const_attr_in_accel_mag_value_available.dev_attr.attr,776	&iio_const_attr_in_accel_mag_period_available.dev_attr.attr,777	&iio_const_attr_in_accel_mag_hysteresis_available.dev_attr.attr,778	NULL779};780 781static const struct attribute_group bmi323_event_attribute_group = {782	.attrs = bmi323_event_attributes,783};784 785static int bmi323_write_event_config(struct iio_dev *indio_dev,786				     const struct iio_chan_spec *chan,787				     enum iio_event_type type,788				     enum iio_event_direction dir, int state)789{790	struct bmi323_data *data = iio_priv(indio_dev);791 792	switch (type) {793	case IIO_EV_TYPE_MAG:794		return bmi323_motion_event_en(data, dir, state);795	case IIO_EV_TYPE_GESTURE:796		return bmi323_tap_event_en(data, dir, state);797	case IIO_EV_TYPE_CHANGE:798		return bmi323_step_wtrmrk_en(data, state);799	default:800		return -EINVAL;801	}802}803 804static int bmi323_read_event_config(struct iio_dev *indio_dev,805				    const struct iio_chan_spec *chan,806				    enum iio_event_type type,807				    enum iio_event_direction dir)808{809	struct bmi323_data *data = iio_priv(indio_dev);810	int ret, value, reg_val;811 812	guard(mutex)(&data->mutex);813 814	switch (chan->type) {815	case IIO_ACCEL:816		switch (dir) {817		case IIO_EV_DIR_SINGLETAP:818			ret = FIELD_GET(BMI323_FEAT_IO0_S_TAP_MSK,819					data->feature_events);820			break;821		case IIO_EV_DIR_DOUBLETAP:822			ret = FIELD_GET(BMI323_FEAT_IO0_D_TAP_MSK,823					data->feature_events);824			break;825		case IIO_EV_DIR_RISING:826			value = FIELD_GET(BMI323_FEAT_IO0_XYZ_MOTION_MSK,827					  data->feature_events);828			ret = value ? 1 : 0;829			break;830		case IIO_EV_DIR_FALLING:831			value = FIELD_GET(BMI323_FEAT_IO0_XYZ_NOMOTION_MSK,832					  data->feature_events);833			ret = value ? 1 : 0;834			break;835		default:836			ret = -EINVAL;837			break;838		}839		return ret;840	case IIO_STEPS:841		ret = regmap_read(data->regmap, BMI323_INT_MAP1_REG, &reg_val);842		if (ret)843			return ret;844 845		return FIELD_GET(BMI323_STEP_CNT_MSK, reg_val) ? 1 : 0;846	default:847		return -EINVAL;848	}849}850 851static int bmi323_write_event_value(struct iio_dev *indio_dev,852				    const struct iio_chan_spec *chan,853				    enum iio_event_type type,854				    enum iio_event_direction dir,855				    enum iio_event_info info,856				    int val, int val2)857{858	struct bmi323_data *data = iio_priv(indio_dev);859	unsigned int raw;860	int reg;861 862	guard(mutex)(&data->mutex);863 864	switch (type) {865	case IIO_EV_TYPE_GESTURE:866		switch (info) {867		case IIO_EV_INFO_VALUE:868			if (!in_range(val, 0, 2))869				return -EINVAL;870 871			raw = BMI323_INT_MICRO_TO_RAW(val, val2,872						      BMI323_TAP_THRES_SCALE);873 874			return bmi323_update_ext_reg(data, BMI323_TAP2_REG,875						     BMI323_TAP2_THRES_MSK,876						     FIELD_PREP(BMI323_TAP2_THRES_MSK,877								raw));878		case IIO_EV_INFO_RESET_TIMEOUT:879			if (val || !in_range(val2, 40000, 560001))880				return -EINVAL;881 882			raw = BMI323_INT_MICRO_TO_RAW(val, val2,883						      BMI323_QUITE_TIM_GES_SCALE);884 885			return bmi323_update_ext_reg(data, BMI323_TAP3_REG,886						     BMI323_TAP3_QT_AFT_GES_MSK,887						     FIELD_PREP(BMI323_TAP3_QT_AFT_GES_MSK,888								raw));889		case IIO_EV_INFO_TAP2_MIN_DELAY:890			if (val || !in_range(val2, 5000, 70001))891				return -EINVAL;892 893			raw = BMI323_INT_MICRO_TO_RAW(val, val2,894						      BMI323_DUR_BW_TAP_SCALE);895 896			return bmi323_update_ext_reg(data, BMI323_TAP3_REG,897						     BMI323_TAP3_QT_BW_TAP_MSK,898						     FIELD_PREP(BMI323_TAP3_QT_BW_TAP_MSK,899								raw));900		default:901			return -EINVAL;902		}903	case IIO_EV_TYPE_MAG:904		reg = bmi323_motion_config_reg(dir);905		if (reg < 0)906			return -EINVAL;907 908		switch (info) {909		case IIO_EV_INFO_VALUE:910			if (!in_range(val, 0, 8))911				return -EINVAL;912 913			raw = BMI323_INT_MICRO_TO_RAW(val, val2,914						      BMI323_MOTION_THRES_SCALE);915 916			return bmi323_update_ext_reg(data, reg,917						     BMI323_MO1_SLOPE_TH_MSK,918						     FIELD_PREP(BMI323_MO1_SLOPE_TH_MSK,919								raw));920		case IIO_EV_INFO_PERIOD:921			if (!in_range(val, 0, 163))922				return -EINVAL;923 924			raw = BMI323_INT_MICRO_TO_RAW(val, val2,925						      BMI323_MOTION_DURAT_SCALE);926 927			return bmi323_update_ext_reg(data,928						     reg + BMI323_MO3_OFFSET,929						     BMI323_MO3_DURA_MSK,930						     FIELD_PREP(BMI323_MO3_DURA_MSK,931								raw));932		case IIO_EV_INFO_HYSTERESIS:933			if (!in_range(val, 0, 2))934				return -EINVAL;935 936			raw = BMI323_INT_MICRO_TO_RAW(val, val2,937						      BMI323_MOTION_HYSTR_SCALE);938 939			return bmi323_update_ext_reg(data,940						     reg + BMI323_MO2_OFFSET,941						     BMI323_MO2_HYSTR_MSK,942						     FIELD_PREP(BMI323_MO2_HYSTR_MSK,943								raw));944		default:945			return -EINVAL;946		}947	case IIO_EV_TYPE_CHANGE:948		if (!in_range(val, 0, 20461))949			return -EINVAL;950 951		raw = val / 20;952		return bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,953					     BMI323_STEP_SC1_WTRMRK_MSK,954					     FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,955							raw));956	default:957		return -EINVAL;958	}959}960 961static int bmi323_read_event_value(struct iio_dev *indio_dev,962				   const struct iio_chan_spec *chan,963				   enum iio_event_type type,964				   enum iio_event_direction dir,965				   enum iio_event_info info,966				   int *val, int *val2)967{968	struct bmi323_data *data = iio_priv(indio_dev);969	unsigned int raw, reg_value;970	int ret, reg;971 972	guard(mutex)(&data->mutex);973 974	switch (type) {975	case IIO_EV_TYPE_GESTURE:976		switch (info) {977		case IIO_EV_INFO_VALUE:978			ret = bmi323_read_ext_reg(data, BMI323_TAP2_REG,979						  &reg_value);980			if (ret)981				return ret;982 983			raw = FIELD_GET(BMI323_TAP2_THRES_MSK, reg_value);984			*val = raw / BMI323_TAP_THRES_SCALE;985			*val2 = BMI323_RAW_TO_MICRO(raw, BMI323_TAP_THRES_SCALE);986			return IIO_VAL_INT_PLUS_MICRO;987		case IIO_EV_INFO_RESET_TIMEOUT:988			ret = bmi323_read_ext_reg(data, BMI323_TAP3_REG,989						  &reg_value);990			if (ret)991				return ret;992 993			raw = FIELD_GET(BMI323_TAP3_QT_AFT_GES_MSK, reg_value);994			*val = 0;995			*val2 = BMI323_RAW_TO_MICRO(raw,996						    BMI323_QUITE_TIM_GES_SCALE);997			return IIO_VAL_INT_PLUS_MICRO;998		case IIO_EV_INFO_TAP2_MIN_DELAY:999			ret = bmi323_read_ext_reg(data, BMI323_TAP3_REG,1000						  &reg_value);1001			if (ret)1002				return ret;1003 1004			raw = FIELD_GET(BMI323_TAP3_QT_BW_TAP_MSK, reg_value);1005			*val = 0;1006			*val2 = BMI323_RAW_TO_MICRO(raw,1007						    BMI323_DUR_BW_TAP_SCALE);1008			return IIO_VAL_INT_PLUS_MICRO;1009		default:1010			return -EINVAL;1011		}1012	case IIO_EV_TYPE_MAG:1013		reg = bmi323_motion_config_reg(dir);1014		if (reg < 0)1015			return -EINVAL;1016 1017		switch (info) {1018		case IIO_EV_INFO_VALUE:1019			ret = bmi323_read_ext_reg(data, reg, &reg_value);1020			if (ret)1021				return ret;1022 1023			raw = FIELD_GET(BMI323_MO1_SLOPE_TH_MSK, reg_value);1024			*val = raw / BMI323_MOTION_THRES_SCALE;1025			*val2 = BMI323_RAW_TO_MICRO(raw,1026						    BMI323_MOTION_THRES_SCALE);1027			return IIO_VAL_INT_PLUS_MICRO;1028		case IIO_EV_INFO_PERIOD:1029			ret = bmi323_read_ext_reg(data,1030						  reg + BMI323_MO3_OFFSET,1031						  &reg_value);1032			if (ret)1033				return ret;1034 1035			raw = FIELD_GET(BMI323_MO3_DURA_MSK, reg_value);1036			*val = raw / BMI323_MOTION_DURAT_SCALE;1037			*val2 = BMI323_RAW_TO_MICRO(raw,1038						    BMI323_MOTION_DURAT_SCALE);1039			return IIO_VAL_INT_PLUS_MICRO;1040		case IIO_EV_INFO_HYSTERESIS:1041			ret = bmi323_read_ext_reg(data,1042						  reg + BMI323_MO2_OFFSET,1043						  &reg_value);1044			if (ret)1045				return ret;1046 1047			raw = FIELD_GET(BMI323_MO2_HYSTR_MSK, reg_value);1048			*val = raw / BMI323_MOTION_HYSTR_SCALE;1049			*val2 = BMI323_RAW_TO_MICRO(raw,1050						    BMI323_MOTION_HYSTR_SCALE);1051			return IIO_VAL_INT_PLUS_MICRO;1052		default:1053			return -EINVAL;1054		}1055	case IIO_EV_TYPE_CHANGE:1056		ret = bmi323_read_ext_reg(data, BMI323_STEP_SC1_REG,1057					  &reg_value);1058		if (ret)1059			return ret;1060 1061		raw = FIELD_GET(BMI323_STEP_SC1_WTRMRK_MSK, reg_value);1062		*val = raw * 20;1063		return IIO_VAL_INT;1064	default:1065		return -EINVAL;1066	}1067}1068 1069static int __bmi323_fifo_flush(struct iio_dev *indio_dev)1070{1071	struct bmi323_data *data = iio_priv(indio_dev);1072	int i, ret, fifo_lvl, frame_count, bit, index;1073	__le16 *frame, *pchannels;1074	u64 sample_period;1075	s64 tstamp;1076 1077	guard(mutex)(&data->mutex);1078	ret = regmap_read(data->regmap, BMI323_FIFO_FILL_LEVEL_REG, &fifo_lvl);1079	if (ret)1080		return ret;1081 1082	fifo_lvl = min(fifo_lvl, BMI323_FIFO_FULL_IN_WORDS);1083 1084	frame_count = fifo_lvl / BMI323_FIFO_FRAME_LENGTH;1085	if (!frame_count)1086		return -EINVAL;1087 1088	if (fifo_lvl % BMI323_FIFO_FRAME_LENGTH)1089		dev_warn(data->dev, "Bad FIFO alignment\n");1090 1091	/*1092	 * Approximate timestamps for each of the sample based on the sampling1093	 * frequency, timestamp for last sample and number of samples.1094	 */1095	if (data->old_fifo_tstamp) {1096		sample_period = data->fifo_tstamp - data->old_fifo_tstamp;1097		do_div(sample_period, frame_count);1098	} else {1099		sample_period = data->odrns[BMI323_ACCEL];1100	}1101 1102	tstamp = data->fifo_tstamp - (frame_count - 1) * sample_period;1103 1104	ret = regmap_noinc_read(data->regmap, BMI323_FIFO_DATA_REG,1105				&data->fifo_buff[0],1106				fifo_lvl * BMI323_BYTES_PER_SAMPLE);1107	if (ret)1108		return ret;1109 1110	for (i = 0; i < frame_count; i++) {1111		frame = &data->fifo_buff[i * BMI323_FIFO_FRAME_LENGTH];1112		pchannels = &data->buffer.channels[0];1113 1114		index = 0;1115		for_each_set_bit(bit, indio_dev->active_scan_mask,1116				 BMI323_CHAN_MAX)1117			pchannels[index++] = frame[bit];1118 1119		iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,1120						   tstamp);1121 1122		tstamp += sample_period;1123	}1124 1125	return frame_count;1126}1127 1128static int bmi323_set_watermark(struct iio_dev *indio_dev, unsigned int val)1129{1130	struct bmi323_data *data = iio_priv(indio_dev);1131 1132	val = min(val, (u32)BMI323_FIFO_FULL_IN_FRAMES);1133 1134	guard(mutex)(&data->mutex);1135	data->watermark = val;1136 1137	return 0;1138}1139 1140static int bmi323_fifo_disable(struct bmi323_data *data)1141{1142	int ret;1143 1144	guard(mutex)(&data->mutex);1145	ret = regmap_write(data->regmap, BMI323_FIFO_CONF_REG, 0);1146	if (ret)1147		return ret;1148 1149	ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,1150				 BMI323_FIFO_WTRMRK_MSK,1151				 FIELD_PREP(BMI323_FIFO_WTRMRK_MSK, 0));1152	if (ret)1153		return ret;1154 1155	data->fifo_tstamp = 0;1156	data->state = BMI323_IDLE;1157 1158	return 0;1159}1160 1161static int bmi323_buffer_predisable(struct iio_dev *indio_dev)1162{1163	struct bmi323_data *data = iio_priv(indio_dev);1164 1165	if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_TRIGGERED)1166		return 0;1167 1168	return bmi323_fifo_disable(data);1169}1170 1171static int bmi323_update_watermark(struct bmi323_data *data)1172{1173	int wtrmrk;1174 1175	wtrmrk = data->watermark * BMI323_FIFO_FRAME_LENGTH;1176 1177	return regmap_write(data->regmap, BMI323_FIFO_WTRMRK_REG, wtrmrk);1178}1179 1180static int bmi323_fifo_enable(struct bmi323_data *data)1181{1182	int ret;1183 1184	guard(mutex)(&data->mutex);1185	ret = regmap_update_bits(data->regmap, BMI323_FIFO_CONF_REG,1186				 BMI323_FIFO_CONF_ACC_GYR_EN_MSK,1187				 FIELD_PREP(BMI323_FIFO_CONF_ACC_GYR_EN_MSK,1188					    BMI323_FIFO_ACC_GYR_MSK));1189	if (ret)1190		return ret;1191 1192	ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,1193				 BMI323_FIFO_WTRMRK_MSK,1194				 FIELD_PREP(BMI323_FIFO_WTRMRK_MSK,1195					    data->irq_pin));1196	if (ret)1197		return ret;1198 1199	ret = bmi323_update_watermark(data);1200	if (ret)1201		return ret;1202 1203	ret = regmap_write(data->regmap, BMI323_FIFO_CTRL_REG,1204			   BMI323_FIFO_FLUSH_MSK);1205	if (ret)1206		return ret;1207 1208	data->state = BMI323_BUFFER_FIFO;1209 1210	return 0;1211}1212 1213static int bmi323_buffer_preenable(struct iio_dev *indio_dev)1214{1215	struct bmi323_data *data = iio_priv(indio_dev);1216 1217	guard(mutex)(&data->mutex);1218	/*1219	 * When the ODR of the accelerometer and gyroscope do not match, the1220	 * maximum ODR value between the accelerometer and gyroscope is used1221	 * for FIFO and the signal with lower ODR will insert dummy frame.1222	 * So allow buffer read only when ODR's of accelero and gyro are equal.1223	 * See datasheet section 5.7 "FIFO Data Buffering".1224	 */1225	if (data->odrns[BMI323_ACCEL] != data->odrns[BMI323_GYRO]) {1226		dev_err(data->dev, "Accelero and Gyro ODR doesn't match\n");1227		return -EINVAL;1228	}1229 1230	return 0;1231}1232 1233static int bmi323_buffer_postenable(struct iio_dev *indio_dev)1234{1235	struct bmi323_data *data = iio_priv(indio_dev);1236 1237	if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_TRIGGERED)1238		return 0;1239 1240	return bmi323_fifo_enable(data);1241}1242 1243static ssize_t hwfifo_watermark_show(struct device *dev,1244				     struct device_attribute *attr, char *buf)1245{1246	struct iio_dev *indio_dev = dev_to_iio_dev(dev);1247	struct bmi323_data *data = iio_priv(indio_dev);1248	int wm;1249 1250	scoped_guard(mutex, &data->mutex)1251		wm = data->watermark;1252 1253	return sysfs_emit(buf, "%d\n", wm);1254}1255static IIO_DEVICE_ATTR_RO(hwfifo_watermark, 0);1256 1257static ssize_t hwfifo_enabled_show(struct device *dev,1258				   struct device_attribute *attr,1259				   char *buf)1260{1261	struct iio_dev *indio_dev = dev_to_iio_dev(dev);1262	struct bmi323_data *data = iio_priv(indio_dev);1263	bool state;1264 1265	scoped_guard(mutex, &data->mutex)1266		state = data->state == BMI323_BUFFER_FIFO;1267 1268	return sysfs_emit(buf, "%d\n", state);1269}1270static IIO_DEVICE_ATTR_RO(hwfifo_enabled, 0);1271 1272static const struct iio_dev_attr *bmi323_fifo_attributes[] = {1273	&iio_dev_attr_hwfifo_watermark,1274	&iio_dev_attr_hwfifo_enabled,1275	NULL1276};1277 1278static const struct iio_buffer_setup_ops bmi323_buffer_ops = {1279	.preenable = bmi323_buffer_preenable,1280	.postenable = bmi323_buffer_postenable,1281	.predisable = bmi323_buffer_predisable,1282};1283 1284static irqreturn_t bmi323_irq_thread_handler(int irq, void *private)1285{1286	struct iio_dev *indio_dev = private;1287	struct bmi323_data *data = iio_priv(indio_dev);1288	unsigned int status_addr, status, feature_event;1289	s64 timestamp = iio_get_time_ns(indio_dev);1290	int ret;1291 1292	if (data->irq_pin == BMI323_IRQ_INT1)1293		status_addr = BMI323_STATUS_INT1_REG;1294	else1295		status_addr = BMI323_STATUS_INT2_REG;1296 1297	scoped_guard(mutex, &data->mutex) {1298		ret = regmap_read(data->regmap, status_addr, &status);1299		if (ret)1300			return IRQ_NONE;1301	}1302 1303	if (!status || FIELD_GET(BMI323_STATUS_ERROR_MSK, status))1304		return IRQ_NONE;1305 1306	if (FIELD_GET(BMI323_STATUS_FIFO_WTRMRK_MSK, status)) {1307		data->old_fifo_tstamp = data->fifo_tstamp;1308		data->fifo_tstamp = iio_get_time_ns(indio_dev);1309		ret = __bmi323_fifo_flush(indio_dev);1310		if (ret < 0)1311			return IRQ_NONE;1312	}1313 1314	if (FIELD_GET(BMI323_STATUS_ACC_GYR_DRDY_MSK, status))1315		iio_trigger_poll_nested(data->trig);1316 1317	if (FIELD_GET(BMI323_STATUS_MOTION_MSK, status))1318		iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,1319							     IIO_MOD_X_OR_Y_OR_Z,1320							     IIO_EV_TYPE_MAG,1321							     IIO_EV_DIR_RISING),1322			       timestamp);1323 1324	if (FIELD_GET(BMI323_STATUS_NOMOTION_MSK, status))1325		iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,1326							     IIO_MOD_X_OR_Y_OR_Z,1327							     IIO_EV_TYPE_MAG,1328							     IIO_EV_DIR_FALLING),1329			       timestamp);1330 1331	if (FIELD_GET(BMI323_STATUS_STP_WTR_MSK, status))1332		iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_STEPS, 0,1333							     IIO_NO_MOD,1334							     IIO_EV_TYPE_CHANGE,1335							     IIO_EV_DIR_NONE),1336			       timestamp);1337 1338	if (FIELD_GET(BMI323_STATUS_TAP_MSK, status)) {1339		scoped_guard(mutex, &data->mutex) {1340			ret = regmap_read(data->regmap,1341					  BMI323_FEAT_EVNT_EXT_REG,1342					  &feature_event);1343			if (ret)1344				return IRQ_NONE;1345		}1346 1347		if (FIELD_GET(BMI323_FEAT_EVNT_EXT_S_MSK, feature_event)) {1348			iio_push_event(indio_dev,1349				       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,1350							  IIO_MOD_X_OR_Y_OR_Z,1351							  IIO_EV_TYPE_GESTURE,1352							  IIO_EV_DIR_SINGLETAP),1353				       timestamp);1354		}1355 1356		if (FIELD_GET(BMI323_FEAT_EVNT_EXT_D_MSK, feature_event))1357			iio_push_event(indio_dev,1358				       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,1359							  IIO_MOD_X_OR_Y_OR_Z,1360							  IIO_EV_TYPE_GESTURE,1361							  IIO_EV_DIR_DOUBLETAP),1362				       timestamp);1363	}1364 1365	return IRQ_HANDLED;1366}1367 1368static int bmi323_set_drdy_irq(struct bmi323_data *data,1369			       enum bmi323_irq_pin irq_pin)1370{1371	int ret;1372 1373	ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,1374				 BMI323_GYR_DRDY_MSK,1375				 FIELD_PREP(BMI323_GYR_DRDY_MSK, irq_pin));1376	if (ret)1377		return ret;1378 1379	return regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,1380				  BMI323_ACC_DRDY_MSK,1381				  FIELD_PREP(BMI323_ACC_DRDY_MSK, irq_pin));1382}1383 1384static int bmi323_data_rdy_trigger_set_state(struct iio_trigger *trig,1385					     bool state)1386{1387	struct bmi323_data *data = iio_trigger_get_drvdata(trig);1388	enum bmi323_irq_pin irq_pin;1389 1390	guard(mutex)(&data->mutex);1391 1392	if (data->state == BMI323_BUFFER_FIFO) {1393		dev_warn(data->dev, "Can't set trigger when FIFO enabled\n");1394		return -EBUSY;1395	}1396 1397	if (state) {1398		data->state = BMI323_BUFFER_DRDY_TRIGGERED;1399		irq_pin = data->irq_pin;1400	} else {1401		data->state = BMI323_IDLE;1402		irq_pin = BMI323_IRQ_DISABLED;1403	}1404 1405	return bmi323_set_drdy_irq(data, irq_pin);1406}1407 1408static const struct iio_trigger_ops bmi323_trigger_ops = {1409	.set_trigger_state = &bmi323_data_rdy_trigger_set_state,1410};1411 1412static irqreturn_t bmi323_trigger_handler(int irq, void *p)1413{1414	struct iio_poll_func *pf = p;1415	struct iio_dev *indio_dev = pf->indio_dev;1416	struct bmi323_data *data = iio_priv(indio_dev);1417	int ret, bit, index = 0;1418 1419	/* Lock to protect the data->buffer */1420	guard(mutex)(&data->mutex);1421 1422	if (*indio_dev->active_scan_mask == BMI323_ALL_CHAN_MSK) {1423		ret = regmap_bulk_read(data->regmap, BMI323_ACCEL_X_REG,1424				       &data->buffer.channels,1425				       ARRAY_SIZE(data->buffer.channels));1426		if (ret)1427			goto out;1428	} else {1429		for_each_set_bit(bit, indio_dev->active_scan_mask,1430				 BMI323_CHAN_MAX) {1431			ret = regmap_raw_read(data->regmap,1432					      BMI323_ACCEL_X_REG + bit,1433					      &data->buffer.channels[index++],1434					      BMI323_BYTES_PER_SAMPLE);1435			if (ret)1436				goto out;1437		}1438	}1439 1440	iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,1441					   iio_get_time_ns(indio_dev));1442 1443out:1444	iio_trigger_notify_done(indio_dev->trig);1445 1446	return IRQ_HANDLED;1447}1448 1449static int bmi323_set_average(struct bmi323_data *data,1450			      enum bmi323_sensor_type sensor, int avg)1451{1452	int raw = ARRAY_SIZE(bmi323_accel_gyro_avrg);1453 1454	while (raw--)1455		if (avg == bmi323_accel_gyro_avrg[raw])1456			break;1457	if (raw < 0)1458		return -EINVAL;1459 1460	guard(mutex)(&data->mutex);1461	return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,1462				 BMI323_ACC_GYRO_CONF_AVG_MSK,1463				 FIELD_PREP(BMI323_ACC_GYRO_CONF_AVG_MSK,1464					    raw));1465}1466 1467static int bmi323_get_average(struct bmi323_data *data,1468			      enum bmi323_sensor_type sensor, int *avg)1469{1470	int ret, value, raw;1471 1472	scoped_guard(mutex, &data->mutex) {1473		ret = regmap_read(data->regmap, bmi323_hw[sensor].config, &value);1474		if (ret)1475			return ret;1476	}1477 1478	raw = FIELD_GET(BMI323_ACC_GYRO_CONF_AVG_MSK, value);1479	*avg = bmi323_accel_gyro_avrg[raw];1480 1481	return IIO_VAL_INT;1482}1483 1484static int bmi323_enable_steps(struct bmi323_data *data, int val)1485{1486	int ret;1487 1488	guard(mutex)(&data->mutex);1489	if (data->odrhz[BMI323_ACCEL] < 200) {1490		dev_err(data->dev, "Invalid accelerometer parameter\n");1491		return -EINVAL;1492	}1493 1494	ret = bmi323_feature_engine_events(data, BMI323_FEAT_IO0_STP_CNT_MSK,1495					   val ? 1 : 0);1496	if (ret)1497		return ret;1498 1499	set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_STP_CNT_MSK,1500		      FIELD_PREP(BMI323_FEAT_IO0_STP_CNT_MSK, val ? 1 : 0));1501 1502	return 0;1503}1504 1505static int bmi323_read_steps(struct bmi323_data *data, int *val)1506{1507	int ret;1508 1509	guard(mutex)(&data->mutex);1510	if (!FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, data->feature_events))1511		return -EINVAL;1512 1513	ret = regmap_bulk_read(data->regmap, BMI323_FEAT_IO2_REG,1514			       data->steps_count,1515			       ARRAY_SIZE(data->steps_count));1516	if (ret)1517		return ret;1518 1519	*val = get_unaligned_le32(data->steps_count);1520 1521	return IIO_VAL_INT;1522}1523 1524static int bmi323_read_axis(struct bmi323_data *data,1525			    struct iio_chan_spec const *chan, int *val)1526{1527	enum bmi323_sensor_type sensor;1528	unsigned int value;1529	u8 addr;1530	int ret;1531 1532	ret = bmi323_get_error_status(data);1533	if (ret)1534		return -EINVAL;1535 1536	sensor = bmi323_iio_to_sensor(chan->type);1537	addr = bmi323_hw[sensor].data + (chan->channel2 - IIO_MOD_X);1538 1539	scoped_guard(mutex, &data->mutex) {1540		ret = regmap_read(data->regmap, addr, &value);1541		if (ret)1542			return ret;1543	}1544 1545	*val = sign_extend32(value, chan->scan_type.realbits - 1);1546 1547	return IIO_VAL_INT;1548}1549 1550static int bmi323_get_temp_data(struct bmi323_data *data, int *val)1551{1552	unsigned int value;1553	int ret;1554 1555	ret = bmi323_get_error_status(data);1556	if (ret)1557		return -EINVAL;1558 1559	scoped_guard(mutex, &data->mutex) {1560		ret = regmap_read(data->regmap, BMI323_TEMP_REG, &value);1561		if (ret)1562			return ret;1563	}1564 1565	*val = sign_extend32(value, 15);1566 1567	return IIO_VAL_INT;1568}1569 1570static int bmi323_get_odr(struct bmi323_data *data,1571			  enum bmi323_sensor_type sensor, int *odr, int *uodr)1572{1573	int ret, value, odr_raw;1574 1575	scoped_guard(mutex, &data->mutex) {1576		ret = regmap_read(data->regmap, bmi323_hw[sensor].config, &value);1577		if (ret)1578			return ret;1579	}1580 1581	odr_raw = FIELD_GET(BMI323_ACC_GYRO_CONF_ODR_MSK, value);1582	*odr = bmi323_acc_gyro_odr[odr_raw - 1][0];1583	*uodr = bmi323_acc_gyro_odr[odr_raw - 1][1];1584 1585	return IIO_VAL_INT_PLUS_MICRO;1586}1587 1588static int bmi323_configure_power_mode(struct bmi323_data *data,1589				       enum bmi323_sensor_type sensor,1590				       int odr_index)1591{1592	enum bmi323_opr_mode mode;1593 1594	if (bmi323_acc_gyro_odr[odr_index][0] > 25)1595		mode = ACC_GYRO_MODE_CONTINOUS;1596	else1597		mode = ACC_GYRO_MODE_DUTYCYCLE;1598 1599	return bmi323_set_mode(data, sensor, mode);1600}1601 1602static int bmi323_set_odr(struct bmi323_data *data,1603			  enum bmi323_sensor_type sensor, int odr, int uodr)1604{1605	int odr_raw, ret;1606 1607	odr_raw = ARRAY_SIZE(bmi323_acc_gyro_odr);1608 1609	while (odr_raw--)1610		if (odr == bmi323_acc_gyro_odr[odr_raw][0] &&1611		    uodr == bmi323_acc_gyro_odr[odr_raw][1])1612			break;1613	if (odr_raw < 0)1614		return -EINVAL;1615 1616	ret = bmi323_configure_power_mode(data, sensor, odr_raw);1617	if (ret)1618		return -EINVAL;1619 1620	guard(mutex)(&data->mutex);1621	data->odrhz[sensor] = bmi323_acc_gyro_odr[odr_raw][0];1622	data->odrns[sensor] = bmi323_acc_gyro_odrns[odr_raw];1623 1624	odr_raw++;1625 1626	return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,1627				  BMI323_ACC_GYRO_CONF_ODR_MSK,1628				  FIELD_PREP(BMI323_ACC_GYRO_CONF_ODR_MSK,1629					     odr_raw));1630}1631 1632static int bmi323_get_scale(struct bmi323_data *data,1633			    enum bmi323_sensor_type sensor, int *val2)1634{1635	int ret, value, scale_raw;1636 1637	scoped_guard(mutex, &data->mutex) {1638		ret = regmap_read(data->regmap, bmi323_hw[sensor].config,1639				  &value);1640		if (ret)1641			return ret;1642	}1643 1644	scale_raw = FIELD_GET(BMI323_ACC_GYRO_CONF_SCL_MSK, value);1645	*val2 = bmi323_hw[sensor].scale_table[scale_raw][1];1646 1647	return IIO_VAL_INT_PLUS_MICRO;1648}1649 1650static int bmi323_set_scale(struct bmi323_data *data,1651			    enum bmi323_sensor_type sensor, int val, int val2)1652{1653	int scale_raw;1654 1655	scale_raw = bmi323_hw[sensor].scale_table_len;1656 1657	while (scale_raw--)1658		if (val == bmi323_hw[sensor].scale_table[scale_raw][0] &&1659		    val2 == bmi323_hw[sensor].scale_table[scale_raw][1])1660			break;1661	if (scale_raw < 0)1662		return -EINVAL;1663 1664	guard(mutex)(&data->mutex);1665	return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,1666				  BMI323_ACC_GYRO_CONF_SCL_MSK,1667				  FIELD_PREP(BMI323_ACC_GYRO_CONF_SCL_MSK,1668					     scale_raw));1669}1670 1671static int bmi323_read_avail(struct iio_dev *indio_dev,1672			     struct iio_chan_spec const *chan,1673			     const int **vals, int *type, int *length,1674			     long mask)1675{1676	enum bmi323_sensor_type sensor;1677 1678	switch (mask) {1679	case IIO_CHAN_INFO_SAMP_FREQ:1680		*type = IIO_VAL_INT_PLUS_MICRO;1681		*vals = (const int *)bmi323_acc_gyro_odr;1682		*length = ARRAY_SIZE(bmi323_acc_gyro_odr) * 2;1683		return IIO_AVAIL_LIST;1684	case IIO_CHAN_INFO_SCALE:1685		sensor = bmi323_iio_to_sensor(chan->type);1686		*type = IIO_VAL_INT_PLUS_MICRO;1687		*vals = (const int *)bmi323_hw[sensor].scale_table;1688		*length = bmi323_hw[sensor].scale_table_len * 2;1689		return IIO_AVAIL_LIST;1690	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:1691		*type = IIO_VAL_INT;1692		*vals = (const int *)bmi323_accel_gyro_avrg;1693		*length = ARRAY_SIZE(bmi323_accel_gyro_avrg);1694		return IIO_AVAIL_LIST;1695	default:1696		return -EINVAL;1697	}1698}1699 1700static int bmi323_write_raw(struct iio_dev *indio_dev,1701			    struct iio_chan_spec const *chan, int val,1702			    int val2, long mask)1703{1704	struct bmi323_data *data = iio_priv(indio_dev);1705 1706	switch (mask) {1707	case IIO_CHAN_INFO_SAMP_FREQ:1708		iio_device_claim_direct_scoped(return -EBUSY, indio_dev)1709			return bmi323_set_odr(data,1710					      bmi323_iio_to_sensor(chan->type),1711					      val, val2);1712		unreachable();1713	case IIO_CHAN_INFO_SCALE:1714		iio_device_claim_direct_scoped(return -EBUSY, indio_dev)1715			return bmi323_set_scale(data,1716						bmi323_iio_to_sensor(chan->type),1717						val, val2);1718		unreachable();1719	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:1720		iio_device_claim_direct_scoped(return -EBUSY, indio_dev)1721			return bmi323_set_average(data,1722						  bmi323_iio_to_sensor(chan->type),1723						  val);1724		unreachable();1725	case IIO_CHAN_INFO_ENABLE:1726		return bmi323_enable_steps(data, val);1727	case IIO_CHAN_INFO_PROCESSED: {1728		guard(mutex)(&data->mutex);1729 1730		if (val || !FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK,1731				      data->feature_events))1732			return -EINVAL;1733 1734		/* Clear step counter value */1735		return bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,1736					     BMI323_STEP_SC1_RST_CNT_MSK,1737					     FIELD_PREP(BMI323_STEP_SC1_RST_CNT_MSK,1738							1));1739	}1740	default:1741		return -EINVAL;1742	}1743}1744 1745static int bmi323_read_raw(struct iio_dev *indio_dev,1746			   struct iio_chan_spec const *chan, int *val,1747			   int *val2, long mask)1748{1749	struct bmi323_data *data = iio_priv(indio_dev);1750 1751	switch (mask) {1752	case IIO_CHAN_INFO_PROCESSED:1753		return bmi323_read_steps(data, val);1754	case IIO_CHAN_INFO_RAW:1755		switch (chan->type) {1756		case IIO_ACCEL:1757		case IIO_ANGL_VEL:1758			iio_device_claim_direct_scoped(return -EBUSY,1759						       indio_dev)1760				return bmi323_read_axis(data, chan, val);1761			unreachable();1762		case IIO_TEMP:1763			return bmi323_get_temp_data(data, val);1764		default:1765			return -EINVAL;1766		}1767	case IIO_CHAN_INFO_SAMP_FREQ:1768		return bmi323_get_odr(data, bmi323_iio_to_sensor(chan->type),1769				      val, val2);1770	case IIO_CHAN_INFO_SCALE:1771		switch (chan->type) {1772		case IIO_ACCEL:1773		case IIO_ANGL_VEL:1774			*val = 0;1775			return bmi323_get_scale(data,1776						bmi323_iio_to_sensor(chan->type),1777						val2);1778		case IIO_TEMP:1779			*val = BMI323_TEMP_SCALE / MEGA;1780			*val2 = BMI323_TEMP_SCALE % MEGA;1781			return IIO_VAL_INT_PLUS_MICRO;1782		default:1783			return -EINVAL;1784		}1785	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:1786		return bmi323_get_average(data,1787					  bmi323_iio_to_sensor(chan->type),1788					  val);1789	case IIO_CHAN_INFO_OFFSET:1790		switch (chan->type) {1791		case IIO_TEMP:1792			*val = BMI323_TEMP_OFFSET;1793			return IIO_VAL_INT;1794		default:1795			return -EINVAL;1796		}1797	case IIO_CHAN_INFO_ENABLE:1798		scoped_guard(mutex, &data->mutex)1799			*val = FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK,1800					 data->feature_events);1801		return IIO_VAL_INT;1802	default:1803		return -EINVAL;1804	}1805}1806 1807static const struct iio_info bmi323_info = {1808	.read_raw = bmi323_read_raw,1809	.write_raw = bmi323_write_raw,1810	.read_avail = bmi323_read_avail,1811	.hwfifo_set_watermark = bmi323_set_watermark,1812	.write_event_config = bmi323_write_event_config,1813	.read_event_config = bmi323_read_event_config,1814	.write_event_value = bmi323_write_event_value,1815	.read_event_value = bmi323_read_event_value,1816	.event_attrs = &bmi323_event_attribute_group,1817};1818 1819#define BMI323_SCAN_MASK_ACCEL_3AXIS		\1820	(BIT(BMI323_ACCEL_X) | BIT(BMI323_ACCEL_Y) | BIT(BMI323_ACCEL_Z))1821 1822#define BMI323_SCAN_MASK_GYRO_3AXIS		\1823	(BIT(BMI323_GYRO_X) | BIT(BMI323_GYRO_Y) | BIT(BMI323_GYRO_Z))1824 1825static const unsigned long bmi323_avail_scan_masks[] = {1826	/* 3-axis accel */1827	BMI323_SCAN_MASK_ACCEL_3AXIS,1828	/* 3-axis gyro */1829	BMI323_SCAN_MASK_GYRO_3AXIS,1830	/* 3-axis accel + 3-axis gyro */1831	BMI323_SCAN_MASK_ACCEL_3AXIS | BMI323_SCAN_MASK_GYRO_3AXIS,1832	01833};1834 1835static int bmi323_int_pin_config(struct bmi323_data *data,1836				 enum bmi323_irq_pin irq_pin,1837				 bool active_high, bool open_drain, bool latch)1838{1839	unsigned int mask, field_value;1840	int ret;1841 1842	ret = regmap_update_bits(data->regmap, BMI323_IO_INT_CONF_REG,1843				 BMI323_IO_INT_LTCH_MSK,1844				 FIELD_PREP(BMI323_IO_INT_LTCH_MSK, latch));1845	if (ret)1846		return ret;1847 1848	ret = bmi323_update_ext_reg(data, BMI323_GEN_SET1_REG,1849				    BMI323_GEN_HOLD_DUR_MSK,1850				    FIELD_PREP(BMI323_GEN_HOLD_DUR_MSK, 0));1851	if (ret)1852		return ret;1853 1854	switch (irq_pin) {1855	case BMI323_IRQ_INT1:1856		mask = BMI323_IO_INT1_LVL_OD_OP_MSK;1857 1858		field_value = FIELD_PREP(BMI323_IO_INT1_LVL_MSK, active_high) |1859			      FIELD_PREP(BMI323_IO_INT1_OD_MSK, open_drain) |1860			      FIELD_PREP(BMI323_IO_INT1_OP_EN_MSK, 1);1861		break;1862	case BMI323_IRQ_INT2:1863		mask = BMI323_IO_INT2_LVL_OD_OP_MSK;1864 1865		field_value = FIELD_PREP(BMI323_IO_INT2_LVL_MSK, active_high) |1866			      FIELD_PREP(BMI323_IO_INT2_OD_MSK, open_drain) |1867			      FIELD_PREP(BMI323_IO_INT2_OP_EN_MSK, 1);1868		break;1869	default:1870		return -EINVAL;1871	}1872 1873	return regmap_update_bits(data->regmap, BMI323_IO_INT_CTR_REG, mask,1874				  field_value);1875}1876 1877static int bmi323_trigger_probe(struct bmi323_data *data,1878				struct iio_dev *indio_dev)1879{1880	bool open_drain, active_high, latch;1881	struct fwnode_handle *fwnode;1882	enum bmi323_irq_pin irq_pin;1883	int ret, irq, irq_type;1884	struct irq_data *desc;1885 1886	fwnode = dev_fwnode(data->dev);1887	if (!fwnode)1888		return -ENODEV;1889 1890	irq = fwnode_irq_get_byname(fwnode, "INT1");1891	if (irq > 0) {1892		irq_pin = BMI323_IRQ_INT1;1893	} else {1894		irq = fwnode_irq_get_byname(fwnode, "INT2");1895		if (irq < 0)1896			return 0;1897 1898		irq_pin = BMI323_IRQ_INT2;1899	}1900 1901	desc = irq_get_irq_data(irq);1902	if (!desc)1903		return dev_err_probe(data->dev, -EINVAL,1904				     "Could not find IRQ %d\n", irq);1905 1906	irq_type = irqd_get_trigger_type(desc);1907	switch (irq_type) {1908	case IRQF_TRIGGER_RISING:1909		latch = false;1910		active_high = true;1911		break;1912	case IRQF_TRIGGER_HIGH:1913		latch = true;1914		active_high = true;1915		break;1916	case IRQF_TRIGGER_FALLING:1917		latch = false;1918		active_high = false;1919		break;1920	case IRQF_TRIGGER_LOW:1921		latch = true;1922		active_high = false;1923		break;1924	default:1925		return dev_err_probe(data->dev, -EINVAL,1926				     "Invalid interrupt type 0x%x specified\n",1927				     irq_type);1928	}1929 1930	open_drain = fwnode_property_read_bool(fwnode, "drive-open-drain");1931 1932	ret = bmi323_int_pin_config(data, irq_pin, active_high, open_drain,1933				    latch);1934	if (ret)1935		return dev_err_probe(data->dev, ret,1936				     "Failed to configure irq line\n");1937 1938	data->trig = devm_iio_trigger_alloc(data->dev, "%s-trig-%d",1939					    indio_dev->name, irq_pin);1940	if (!data->trig)1941		return -ENOMEM;1942 1943	data->trig->ops = &bmi323_trigger_ops;1944	iio_trigger_set_drvdata(data->trig, data);1945 1946	ret = devm_request_threaded_irq(data->dev, irq, NULL,1947					bmi323_irq_thread_handler,1948					IRQF_ONESHOT, "bmi323-int", indio_dev);1949	if (ret)1950		return dev_err_probe(data->dev, ret, "Failed to request IRQ\n");1951 1952	ret = devm_iio_trigger_register(data->dev, data->trig);1953	if (ret)1954		return dev_err_probe(data->dev, ret,1955				     "Trigger registration failed\n");1956 1957	data->irq_pin = irq_pin;1958 1959	return 0;1960}1961 1962static int bmi323_feature_engine_enable(struct bmi323_data *data, bool en)1963{1964	unsigned int feature_status;1965	int ret;1966 1967	if (!en)1968		return regmap_write(data->regmap, BMI323_FEAT_CTRL_REG, 0);1969 1970	ret = regmap_write(data->regmap, BMI323_FEAT_IO2_REG, 0x012c);1971	if (ret)1972		return ret;1973 1974	ret = regmap_write(data->regmap, BMI323_FEAT_IO_STATUS_REG,1975			   BMI323_FEAT_IO_STATUS_MSK);1976	if (ret)1977		return ret;1978 1979	ret = regmap_write(data->regmap, BMI323_FEAT_CTRL_REG,1980			   BMI323_FEAT_ENG_EN_MSK);1981	if (ret)1982		return ret;1983 1984	/*1985	 * It takes around 4 msec to enable the Feature engine, so check1986	 * the status of the feature engine every 2 msec for a maximum1987	 * of 5 trials.1988	 */1989	ret = regmap_read_poll_timeout(data->regmap, BMI323_FEAT_IO1_REG,1990				       feature_status,1991				       FIELD_GET(BMI323_FEAT_IO1_ERR_MSK,1992						 feature_status) == 1,1993				       BMI323_FEAT_ENG_POLL,1994				       BMI323_FEAT_ENG_TIMEOUT);1995	if (ret)1996		return dev_err_probe(data->dev, -EINVAL,1997				"Failed to enable feature engine\n");1998 1999	return 0;2000}2001 2002static void bmi323_disable(void *data_ptr)2003{2004	struct bmi323_data *data = data_ptr;2005 2006	bmi323_set_mode(data, BMI323_ACCEL, ACC_GYRO_MODE_DISABLE);2007	bmi323_set_mode(data, BMI323_GYRO, ACC_GYRO_MODE_DISABLE);2008 2009	/*2010	 * Place the peripheral in its lowest power consuming state.2011	 */2012	regmap_write(data->regmap, BMI323_CMD_REG, BMI323_RST_VAL);2013}2014 2015static int bmi323_set_bw(struct bmi323_data *data,2016			 enum bmi323_sensor_type sensor, enum bmi323_3db_bw bw)2017{2018	return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,2019				  BMI323_ACC_GYRO_CONF_BW_MSK,2020				  FIELD_PREP(BMI323_ACC_GYRO_CONF_BW_MSK, bw));2021}2022 2023static int bmi323_init(struct bmi323_data *data)2024{2025	int ret, val;2026 2027	/*2028	 * Perform soft reset to make sure the device is in a known state after2029	 * start up. A delay of 1.5 ms is required after reset.2030	 * See datasheet section 5.17 "Soft Reset".2031	 */2032	ret = regmap_write(data->regmap, BMI323_CMD_REG, BMI323_RST_VAL);2033	if (ret)2034		return ret;2035 2036	usleep_range(1500, 2000);2037 2038	/*2039	 * Dummy read is required to enable SPI interface after reset.2040	 * See datasheet section 7.2.1 "Protocol Selection".2041	 */2042	regmap_read(data->regmap, BMI323_CHIP_ID_REG, &val);2043 2044	ret = regmap_read(data->regmap, BMI323_STATUS_REG, &val);2045	if (ret)2046		return ret;2047 2048	if (!FIELD_GET(BMI323_STATUS_POR_MSK, val))2049		return dev_err_probe(data->dev, -EINVAL,2050				     "Sensor initialization error\n");2051 2052	ret = regmap_read(data->regmap, BMI323_CHIP_ID_REG, &val);2053	if (ret)2054		return ret;2055 2056	if (FIELD_GET(BMI323_CHIP_ID_MSK, val) != BMI323_CHIP_ID_VAL)2057		return dev_err_probe(data->dev, -EINVAL, "Chip ID mismatch\n");2058 2059	ret = bmi323_feature_engine_enable(data, true);2060	if (ret)2061		return ret;2062 2063	ret = regmap_read(data->regmap, BMI323_ERR_REG, &val);2064	if (ret)2065		return ret;2066 2067	if (val)2068		return dev_err_probe(data->dev, -EINVAL,2069				     "Sensor power error = 0x%x\n", val);2070 2071	return 0;2072}2073 2074static int bmi323_init_reset(struct bmi323_data *data)2075{2076	int ret;2077 2078	/*2079	 * Set the Bandwidth coefficient which defines the 3 dB cutoff2080	 * frequency in relation to the ODR.2081	 */2082	ret = bmi323_set_bw(data, BMI323_ACCEL, BMI323_BW_ODR_BY_2);2083	if (ret)2084		return ret;2085 2086	ret = bmi323_set_bw(data, BMI323_GYRO, BMI323_BW_ODR_BY_2);2087	if (ret)2088		return ret;2089 2090	ret = bmi323_set_odr(data, BMI323_ACCEL, 25, 0);2091	if (ret)2092		return ret;2093 2094	ret = bmi323_set_odr(data, BMI323_GYRO, 25, 0);2095	if (ret)2096		return ret;2097 2098	return devm_add_action_or_reset(data->dev, bmi323_disable, data);2099}2100 2101int bmi323_core_probe(struct device *dev)2102{2103	static const char * const regulator_names[] = { "vdd", "vddio" };2104	struct iio_dev *indio_dev;2105	struct bmi323_data *data;2106	struct regmap *regmap;2107	int ret;2108 2109	regmap = dev_get_regmap(dev, NULL);2110	if (!regmap)2111		return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n");2112 2113	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));2114	if (!indio_dev)2115		return dev_err_probe(dev, -ENOMEM,2116				     "Failed to allocate device\n");2117 2118	ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),2119					     regulator_names);2120	if (ret)2121		return dev_err_probe(dev, ret, "Failed to enable regulators\n");2122 2123	data = iio_priv(indio_dev);2124	data->dev = dev;2125	data->regmap = regmap;2126	data->irq_pin = BMI323_IRQ_DISABLED;2127	data->state = BMI323_IDLE;2128	mutex_init(&data->mutex);2129 2130	ret = bmi323_init(data);2131	if (ret)2132		return -EINVAL;2133 2134	ret = bmi323_init_reset(data);2135	if (ret)2136		return -EINVAL;2137 2138	if (!iio_read_acpi_mount_matrix(dev, &data->orientation, "ROTM")) {2139		ret = iio_read_mount_matrix(dev, &data->orientation);2140		if (ret)2141			return ret;2142	}2143 2144	indio_dev->name = "bmi323-imu";2145	indio_dev->info = &bmi323_info;2146	indio_dev->channels = bmi323_channels;2147	indio_dev->num_channels = ARRAY_SIZE(bmi323_channels);2148	indio_dev->available_scan_masks = bmi323_avail_scan_masks;2149	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;2150	dev_set_drvdata(data->dev, indio_dev);2151 2152	ret = bmi323_trigger_probe(data, indio_dev);2153	if (ret)2154		return -EINVAL;2155 2156	ret = devm_iio_triggered_buffer_setup_ext(data->dev, indio_dev,2157						  &iio_pollfunc_store_time,2158						  bmi323_trigger_handler,2159						  IIO_BUFFER_DIRECTION_IN,2160						  &bmi323_buffer_ops,2161						  bmi323_fifo_attributes);2162	if (ret)2163		return dev_err_probe(data->dev, ret,2164				     "Failed to setup trigger buffer\n");2165 2166	ret = devm_iio_device_register(data->dev, indio_dev);2167	if (ret)2168		return dev_err_probe(data->dev, ret,2169				     "Unable to register iio device\n");2170 2171	return bmi323_fifo_disable(data);2172}2173EXPORT_SYMBOL_NS_GPL(bmi323_core_probe, IIO_BMI323);2174 2175static int bmi323_core_runtime_suspend(struct device *dev)2176{2177	struct iio_dev *indio_dev = dev_get_drvdata(dev);2178	struct bmi323_data *data = iio_priv(indio_dev);2179	struct bmi323_regs_runtime_pm *savestate = &data->runtime_pm_status;2180	int ret;2181 2182	guard(mutex)(&data->mutex);2183 2184	ret = iio_device_suspend_triggering(indio_dev);2185	if (ret)2186		return ret;2187 2188	/* Save registers meant to be restored by resume pm callback. */2189	for (unsigned int i = 0; i < ARRAY_SIZE(bmi323_reg_savestate); i++) {2190		ret = regmap_read(data->regmap, bmi323_reg_savestate[i],2191				  &savestate->reg_settings[i]);2192		if (ret) {2193			dev_err(data->dev,2194				"Error reading bmi323 reg 0x%x: %d\n",2195				bmi323_reg_savestate[i], ret);2196			return ret;2197		}2198	}2199 2200	for (unsigned int i = 0; i < ARRAY_SIZE(bmi323_ext_reg_savestate); i++) {2201		ret = bmi323_read_ext_reg(data, bmi323_ext_reg_savestate[i],2202					  &savestate->ext_reg_settings[i]);2203		if (ret) {2204			dev_err(data->dev,2205				"Error reading bmi323 external reg 0x%x: %d\n",2206				bmi323_ext_reg_savestate[i], ret);2207			return ret;2208		}2209	}2210 2211	/* Perform soft reset to place the device in its lowest power state. */2212	ret = regmap_write(data->regmap, BMI323_CMD_REG, BMI323_RST_VAL);2213	if (ret)2214		return ret;2215 2216	return 0;2217}2218 2219static int bmi323_core_runtime_resume(struct device *dev)2220{2221	struct iio_dev *indio_dev = dev_get_drvdata(dev);2222	struct bmi323_data *data = iio_priv(indio_dev);2223	struct bmi323_regs_runtime_pm *savestate = &data->runtime_pm_status;2224	unsigned int val;2225	int ret;2226 2227	guard(mutex)(&data->mutex);2228 2229	/*2230	 * Perform the device power-on and initial setup once again2231	 * after being reset in the lower power state by runtime-pm.2232	 */2233	ret = bmi323_init(data);2234	if (ret) {2235		dev_err(data->dev, "Device power-on and init failed: %d", ret);2236		return ret;2237	}2238 2239	/* Register must be cleared before changing an active config */2240	ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, 0);2241	if (ret) {2242		dev_err(data->dev, "Error stopping feature engine\n");2243		return ret;2244	}2245 2246	for (unsigned int i = 0; i < ARRAY_SIZE(bmi323_ext_reg_savestate); i++) {2247		ret = bmi323_write_ext_reg(data, bmi323_ext_reg_savestate[i],2248					   savestate->ext_reg_settings[i]);2249		if (ret) {2250			dev_err(data->dev,2251				"Error writing bmi323 external reg 0x%x: %d\n",2252				bmi323_ext_reg_savestate[i], ret);2253			return ret;2254		}2255	}2256 2257	for (unsigned int i = 0; i < ARRAY_SIZE(bmi323_reg_savestate); i++) {2258		ret = regmap_write(data->regmap, bmi323_reg_savestate[i],2259				   savestate->reg_settings[i]);2260		if (ret) {2261			dev_err(data->dev,2262				"Error writing bmi323 reg 0x%x: %d\n",2263				bmi323_reg_savestate[i], ret);2264			return ret;2265		}2266	}2267 2268	/*2269	 * Clear old FIFO samples that might be generated before suspend2270	 * or generated from a peripheral state not equal to the saved one.2271	 */2272	if (data->state == BMI323_BUFFER_FIFO) {2273		ret = regmap_write(data->regmap, BMI323_FIFO_CTRL_REG,2274				   BMI323_FIFO_FLUSH_MSK);2275		if (ret) {2276			dev_err(data->dev, "Error flushing FIFO buffer: %d\n", ret);2277			return ret;2278		}2279	}2280 2281	ret = regmap_read(data->regmap, BMI323_ERR_REG, &val);2282	if (ret) {2283		dev_err(data->dev,2284			"Error reading bmi323 error register: %d\n", ret);2285		return ret;2286	}2287 2288	if (val) {2289		dev_err(data->dev,2290			"Sensor power error in PM = 0x%x\n", val);2291		return -EINVAL;2292	}2293 2294	return iio_device_resume_triggering(indio_dev);2295}2296 2297const struct dev_pm_ops bmi323_core_pm_ops = {2298	RUNTIME_PM_OPS(bmi323_core_runtime_suspend,2299		       bmi323_core_runtime_resume, NULL)2300};2301EXPORT_SYMBOL_NS_GPL(bmi323_core_pm_ops, IIO_BMI323);2302 2303MODULE_DESCRIPTION("Bosch BMI323 IMU driver");2304MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");2305MODULE_LICENSE("GPL");2306