brintos

brintos / linux-shallow public Read only

0
0
Text · 33.1 KiB · ef8dd55 Raw
1268 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * ADXL372 3-Axis Digital Accelerometer core driver4 *5 * Copyright 2018 Analog Devices Inc.6 */7 8#include <linux/bitfield.h>9#include <linux/bitops.h>10#include <linux/interrupt.h>11#include <linux/irq.h>12#include <linux/module.h>13#include <linux/regmap.h>14#include <linux/spi/spi.h>15 16#include <linux/iio/iio.h>17#include <linux/iio/sysfs.h>18#include <linux/iio/buffer.h>19#include <linux/iio/events.h>20#include <linux/iio/trigger.h>21#include <linux/iio/trigger_consumer.h>22#include <linux/iio/triggered_buffer.h>23 24#include "adxl372.h"25 26/* ADXL372 registers definition */27#define ADXL372_DEVID			0x0028#define ADXL372_DEVID_MST		0x0129#define ADXL372_PARTID			0x0230#define ADXL372_STATUS_1		0x0431#define ADXL372_STATUS_2		0x0532#define ADXL372_FIFO_ENTRIES_2		0x0633#define ADXL372_FIFO_ENTRIES_1		0x0734#define ADXL372_X_DATA_H		0x0835#define ADXL372_X_DATA_L		0x0936#define ADXL372_Y_DATA_H		0x0A37#define ADXL372_Y_DATA_L		0x0B38#define ADXL372_Z_DATA_H		0x0C39#define ADXL372_Z_DATA_L		0x0D40#define ADXL372_X_MAXPEAK_H		0x1541#define ADXL372_X_MAXPEAK_L		0x1642#define ADXL372_Y_MAXPEAK_H		0x1743#define ADXL372_Y_MAXPEAK_L		0x1844#define ADXL372_Z_MAXPEAK_H		0x1945#define ADXL372_Z_MAXPEAK_L		0x1A46#define ADXL372_OFFSET_X		0x2047#define ADXL372_OFFSET_Y		0x2148#define ADXL372_OFFSET_Z		0x2249#define ADXL372_X_THRESH_ACT_H		0x2350#define ADXL372_X_THRESH_ACT_L		0x2451#define ADXL372_Y_THRESH_ACT_H		0x2552#define ADXL372_Y_THRESH_ACT_L		0x2653#define ADXL372_Z_THRESH_ACT_H		0x2754#define ADXL372_Z_THRESH_ACT_L		0x2855#define ADXL372_TIME_ACT		0x2956#define ADXL372_X_THRESH_INACT_H	0x2A57#define ADXL372_X_THRESH_INACT_L	0x2B58#define ADXL372_Y_THRESH_INACT_H	0x2C59#define ADXL372_Y_THRESH_INACT_L	0x2D60#define ADXL372_Z_THRESH_INACT_H	0x2E61#define ADXL372_Z_THRESH_INACT_L	0x2F62#define ADXL372_TIME_INACT_H		0x3063#define ADXL372_TIME_INACT_L		0x3164#define ADXL372_X_THRESH_ACT2_H		0x3265#define ADXL372_X_THRESH_ACT2_L		0x3366#define ADXL372_Y_THRESH_ACT2_H		0x3467#define ADXL372_Y_THRESH_ACT2_L		0x3568#define ADXL372_Z_THRESH_ACT2_H		0x3669#define ADXL372_Z_THRESH_ACT2_L		0x3770#define ADXL372_HPF			0x3871#define ADXL372_FIFO_SAMPLES		0x3972#define ADXL372_FIFO_CTL		0x3A73#define ADXL372_INT1_MAP		0x3B74#define ADXL372_INT2_MAP		0x3C75#define ADXL372_TIMING			0x3D76#define ADXL372_MEASURE			0x3E77#define ADXL372_POWER_CTL		0x3F78#define ADXL372_SELF_TEST		0x4079#define ADXL372_RESET			0x4180#define ADXL372_FIFO_DATA		0x4281 82#define ADXL372_DEVID_VAL		0xAD83#define ADXL372_PARTID_VAL		0xFA84#define ADXL372_RESET_CODE		0x5285 86/* ADXL372_POWER_CTL */87#define ADXL372_POWER_CTL_MODE_MSK		GENMASK_ULL(1, 0)88#define ADXL372_POWER_CTL_MODE(x)		(((x) & 0x3) << 0)89 90/* ADXL372_MEASURE */91#define ADXL372_MEASURE_LINKLOOP_MSK		GENMASK_ULL(5, 4)92#define ADXL372_MEASURE_LINKLOOP_MODE(x)	(((x) & 0x3) << 4)93#define ADXL372_MEASURE_BANDWIDTH_MSK		GENMASK_ULL(2, 0)94#define ADXL372_MEASURE_BANDWIDTH_MODE(x)	(((x) & 0x7) << 0)95 96/* ADXL372_TIMING */97#define ADXL372_TIMING_ODR_MSK			GENMASK_ULL(7, 5)98#define ADXL372_TIMING_ODR_MODE(x)		(((x) & 0x7) << 5)99 100/* ADXL372_FIFO_CTL */101#define ADXL372_FIFO_CTL_FORMAT_MSK		GENMASK(5, 3)102#define ADXL372_FIFO_CTL_FORMAT_MODE(x)		(((x) & 0x7) << 3)103#define ADXL372_FIFO_CTL_MODE_MSK		GENMASK(2, 1)104#define ADXL372_FIFO_CTL_MODE_MODE(x)		(((x) & 0x3) << 1)105#define ADXL372_FIFO_CTL_SAMPLES_MSK		BIT(1)106#define ADXL372_FIFO_CTL_SAMPLES_MODE(x)	(((x) > 0xFF) ? 1 : 0)107 108/* ADXL372_STATUS_1 */109#define ADXL372_STATUS_1_DATA_RDY(x)		(((x) >> 0) & 0x1)110#define ADXL372_STATUS_1_FIFO_RDY(x)		(((x) >> 1) & 0x1)111#define ADXL372_STATUS_1_FIFO_FULL(x)		(((x) >> 2) & 0x1)112#define ADXL372_STATUS_1_FIFO_OVR(x)		(((x) >> 3) & 0x1)113#define ADXL372_STATUS_1_USR_NVM_BUSY(x)	(((x) >> 5) & 0x1)114#define ADXL372_STATUS_1_AWAKE(x)		(((x) >> 6) & 0x1)115#define ADXL372_STATUS_1_ERR_USR_REGS(x)	(((x) >> 7) & 0x1)116 117/* ADXL372_STATUS_2 */118#define ADXL372_STATUS_2_INACT(x)		(((x) >> 4) & 0x1)119#define ADXL372_STATUS_2_ACT(x)			(((x) >> 5) & 0x1)120#define ADXL372_STATUS_2_AC2(x)			(((x) >> 6) & 0x1)121 122/* ADXL372_INT1_MAP */123#define ADXL372_INT1_MAP_DATA_RDY_MSK		BIT(0)124#define ADXL372_INT1_MAP_DATA_RDY_MODE(x)	(((x) & 0x1) << 0)125#define ADXL372_INT1_MAP_FIFO_RDY_MSK		BIT(1)126#define ADXL372_INT1_MAP_FIFO_RDY_MODE(x)	(((x) & 0x1) << 1)127#define ADXL372_INT1_MAP_FIFO_FULL_MSK		BIT(2)128#define ADXL372_INT1_MAP_FIFO_FULL_MODE(x)	(((x) & 0x1) << 2)129#define ADXL372_INT1_MAP_FIFO_OVR_MSK		BIT(3)130#define ADXL372_INT1_MAP_FIFO_OVR_MODE(x)	(((x) & 0x1) << 3)131#define ADXL372_INT1_MAP_INACT_MSK		BIT(4)132#define ADXL372_INT1_MAP_INACT_MODE(x)		(((x) & 0x1) << 4)133#define ADXL372_INT1_MAP_ACT_MSK		BIT(5)134#define ADXL372_INT1_MAP_ACT_MODE(x)		(((x) & 0x1) << 5)135#define ADXL372_INT1_MAP_AWAKE_MSK		BIT(6)136#define ADXL372_INT1_MAP_AWAKE_MODE(x)		(((x) & 0x1) << 6)137#define ADXL372_INT1_MAP_LOW_MSK		BIT(7)138#define ADXL372_INT1_MAP_LOW_MODE(x)		(((x) & 0x1) << 7)139 140/* ADX372_THRESH */141#define ADXL372_THRESH_VAL_H_MSK	GENMASK(10, 3)142#define ADXL372_THRESH_VAL_H_SEL(x)	FIELD_GET(ADXL372_THRESH_VAL_H_MSK, x)143#define ADXL372_THRESH_VAL_L_MSK	GENMASK(2, 0)144#define ADXL372_THRESH_VAL_L_SEL(x)	FIELD_GET(ADXL372_THRESH_VAL_L_MSK, x)145 146/* The ADXL372 includes a deep, 512 sample FIFO buffer */147#define ADXL372_FIFO_SIZE			512148#define ADXL372_X_AXIS_EN(x)			((x) & BIT(0))149#define ADXL372_Y_AXIS_EN(x)			((x) & BIT(1))150#define ADXL372_Z_AXIS_EN(x)			((x) & BIT(2))151 152/*153 * At +/- 200g with 12-bit resolution, scale is computed as:154 * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241155 */156#define ADXL372_USCALE	958241157 158enum adxl372_op_mode {159	ADXL372_STANDBY,160	ADXL372_WAKE_UP,161	ADXL372_INSTANT_ON,162	ADXL372_FULL_BW_MEASUREMENT,163};164 165enum adxl372_act_proc_mode {166	ADXL372_DEFAULT,167	ADXL372_LINKED,168	ADXL372_LOOPED,169};170 171enum adxl372_th_activity {172	ADXL372_ACTIVITY,173	ADXL372_ACTIVITY2,174	ADXL372_INACTIVITY,175};176 177enum adxl372_odr {178	ADXL372_ODR_400HZ,179	ADXL372_ODR_800HZ,180	ADXL372_ODR_1600HZ,181	ADXL372_ODR_3200HZ,182	ADXL372_ODR_6400HZ,183};184 185enum adxl372_bandwidth {186	ADXL372_BW_200HZ,187	ADXL372_BW_400HZ,188	ADXL372_BW_800HZ,189	ADXL372_BW_1600HZ,190	ADXL372_BW_3200HZ,191};192 193static const unsigned int adxl372_th_reg_high_addr[3] = {194	[ADXL372_ACTIVITY] = ADXL372_X_THRESH_ACT_H,195	[ADXL372_ACTIVITY2] = ADXL372_X_THRESH_ACT2_H,196	[ADXL372_INACTIVITY] = ADXL372_X_THRESH_INACT_H,197};198 199enum adxl372_fifo_format {200	ADXL372_XYZ_FIFO,201	ADXL372_X_FIFO,202	ADXL372_Y_FIFO,203	ADXL372_XY_FIFO,204	ADXL372_Z_FIFO,205	ADXL372_XZ_FIFO,206	ADXL372_YZ_FIFO,207	ADXL372_XYZ_PEAK_FIFO,208};209 210enum adxl372_fifo_mode {211	ADXL372_FIFO_BYPASSED,212	ADXL372_FIFO_STREAMED,213	ADXL372_FIFO_TRIGGERED,214	ADXL372_FIFO_OLD_SAVED215};216 217static const int adxl372_samp_freq_tbl[5] = {218	400, 800, 1600, 3200, 6400,219};220 221static const int adxl372_bw_freq_tbl[5] = {222	200, 400, 800, 1600, 3200,223};224 225struct adxl372_axis_lookup {226	unsigned int bits;227	enum adxl372_fifo_format fifo_format;228};229 230static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = {231	{ BIT(0), ADXL372_X_FIFO },232	{ BIT(1), ADXL372_Y_FIFO },233	{ BIT(2), ADXL372_Z_FIFO },234	{ BIT(0) | BIT(1), ADXL372_XY_FIFO },235	{ BIT(0) | BIT(2), ADXL372_XZ_FIFO },236	{ BIT(1) | BIT(2), ADXL372_YZ_FIFO },237	{ BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO },238};239 240static const struct iio_event_spec adxl372_events[] = {241	{242		.type = IIO_EV_TYPE_THRESH,243		.dir = IIO_EV_DIR_RISING,244		.mask_separate = BIT(IIO_EV_INFO_VALUE),245		.mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_ENABLE),246	}, {247		.type = IIO_EV_TYPE_THRESH,248		.dir = IIO_EV_DIR_FALLING,249		.mask_separate = BIT(IIO_EV_INFO_VALUE),250		.mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_ENABLE),251	},252};253 254#define ADXL372_ACCEL_CHANNEL(index, reg, axis) {			\255	.type = IIO_ACCEL,						\256	.address = reg,							\257	.modified = 1,							\258	.channel2 = IIO_MOD_##axis,					\259	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\260	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |		\261				    BIT(IIO_CHAN_INFO_SAMP_FREQ) |	\262		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),	\263	.scan_index = index,						\264	.scan_type = {							\265		.sign = 's',						\266		.realbits = 12,						\267		.storagebits = 16,					\268		.shift = 4,						\269		.endianness = IIO_BE,					\270	},								\271	.event_spec = adxl372_events,					\272	.num_event_specs = ARRAY_SIZE(adxl372_events)			\273}274 275static const struct iio_chan_spec adxl372_channels[] = {276	ADXL372_ACCEL_CHANNEL(0, ADXL372_X_DATA_H, X),277	ADXL372_ACCEL_CHANNEL(1, ADXL372_Y_DATA_H, Y),278	ADXL372_ACCEL_CHANNEL(2, ADXL372_Z_DATA_H, Z),279};280 281struct adxl372_state {282	int				irq;283	struct device			*dev;284	struct regmap			*regmap;285	struct iio_trigger		*dready_trig;286	struct iio_trigger		*peak_datardy_trig;287	enum adxl372_fifo_mode		fifo_mode;288	enum adxl372_fifo_format	fifo_format;289	unsigned int			fifo_axis_mask;290	enum adxl372_op_mode		op_mode;291	enum adxl372_act_proc_mode	act_proc_mode;292	enum adxl372_odr		odr;293	enum adxl372_bandwidth		bw;294	u32				act_time_ms;295	u32				inact_time_ms;296	u8				fifo_set_size;297	unsigned long			int1_bitmask;298	unsigned long			int2_bitmask;299	u16				watermark;300	__be16				fifo_buf[ADXL372_FIFO_SIZE];301	bool				peak_fifo_mode_en;302	struct mutex			threshold_m; /* lock for threshold */303};304 305static const unsigned long adxl372_channel_masks[] = {306	BIT(0), BIT(1), BIT(2),307	BIT(0) | BIT(1),308	BIT(0) | BIT(2),309	BIT(1) | BIT(2),310	BIT(0) | BIT(1) | BIT(2),311	0312};313 314static ssize_t adxl372_read_threshold_value(struct iio_dev *indio_dev, unsigned int addr,315					    u16 *threshold)316{317	struct adxl372_state *st = iio_priv(indio_dev);318	__be16 raw_regval;319	u16 regval;320	int ret;321 322	ret = regmap_bulk_read(st->regmap, addr, &raw_regval, sizeof(raw_regval));323	if (ret < 0)324		return ret;325 326	regval = be16_to_cpu(raw_regval);327	regval >>= 5;328 329	*threshold = regval;330 331	return 0;332}333 334static ssize_t adxl372_write_threshold_value(struct iio_dev *indio_dev, unsigned int addr,335					     u16 threshold)336{337	struct adxl372_state *st = iio_priv(indio_dev);338	int ret;339 340	mutex_lock(&st->threshold_m);341	ret = regmap_write(st->regmap, addr, ADXL372_THRESH_VAL_H_SEL(threshold));342	if (ret < 0)343		goto unlock;344 345	ret = regmap_update_bits(st->regmap, addr + 1, GENMASK(7, 5),346				 ADXL372_THRESH_VAL_L_SEL(threshold) << 5);347 348unlock:349	mutex_unlock(&st->threshold_m);350 351	return ret;352}353 354static int adxl372_read_axis(struct adxl372_state *st, u8 addr)355{356	__be16 regval;357	int ret;358 359	ret = regmap_bulk_read(st->regmap, addr, &regval, sizeof(regval));360	if (ret < 0)361		return ret;362 363	return be16_to_cpu(regval);364}365 366static int adxl372_set_op_mode(struct adxl372_state *st,367			       enum adxl372_op_mode op_mode)368{369	int ret;370 371	ret = regmap_update_bits(st->regmap, ADXL372_POWER_CTL,372				 ADXL372_POWER_CTL_MODE_MSK,373				 ADXL372_POWER_CTL_MODE(op_mode));374	if (ret < 0)375		return ret;376 377	st->op_mode = op_mode;378 379	return ret;380}381 382static int adxl372_set_odr(struct adxl372_state *st,383			   enum adxl372_odr odr)384{385	int ret;386 387	ret = regmap_update_bits(st->regmap, ADXL372_TIMING,388				 ADXL372_TIMING_ODR_MSK,389				 ADXL372_TIMING_ODR_MODE(odr));390	if (ret < 0)391		return ret;392 393	st->odr = odr;394 395	return ret;396}397 398static int adxl372_find_closest_match(const int *array,399				      unsigned int size, int val)400{401	int i;402 403	for (i = 0; i < size; i++) {404		if (val <= array[i])405			return i;406	}407 408	return size - 1;409}410 411static int adxl372_set_bandwidth(struct adxl372_state *st,412				 enum adxl372_bandwidth bw)413{414	int ret;415 416	ret = regmap_update_bits(st->regmap, ADXL372_MEASURE,417				 ADXL372_MEASURE_BANDWIDTH_MSK,418				 ADXL372_MEASURE_BANDWIDTH_MODE(bw));419	if (ret < 0)420		return ret;421 422	st->bw = bw;423 424	return ret;425}426 427static int adxl372_set_act_proc_mode(struct adxl372_state *st,428				     enum adxl372_act_proc_mode mode)429{430	int ret;431 432	ret = regmap_update_bits(st->regmap,433				 ADXL372_MEASURE,434				 ADXL372_MEASURE_LINKLOOP_MSK,435				 ADXL372_MEASURE_LINKLOOP_MODE(mode));436	if (ret < 0)437		return ret;438 439	st->act_proc_mode = mode;440 441	return ret;442}443 444static int adxl372_set_activity_threshold(struct adxl372_state *st,445					  enum adxl372_th_activity act,446					  bool ref_en, bool enable,447					  unsigned int threshold)448{449	unsigned char buf[6];450	unsigned char th_reg_high_val, th_reg_low_val, th_reg_high_addr;451 452	/* scale factor is 100 mg/code */453	th_reg_high_val = (threshold / 100) >> 3;454	th_reg_low_val = ((threshold / 100) << 5) | (ref_en << 1) | enable;455	th_reg_high_addr = adxl372_th_reg_high_addr[act];456 457	buf[0] = th_reg_high_val;458	buf[1] = th_reg_low_val;459	buf[2] = th_reg_high_val;460	buf[3] = th_reg_low_val;461	buf[4] = th_reg_high_val;462	buf[5] = th_reg_low_val;463 464	return regmap_bulk_write(st->regmap, th_reg_high_addr,465				 buf, ARRAY_SIZE(buf));466}467 468static int adxl372_set_activity_time_ms(struct adxl372_state *st,469					unsigned int act_time_ms)470{471	unsigned int reg_val, scale_factor;472	int ret;473 474	/*475	 * 3.3 ms per code is the scale factor of the TIME_ACT register for476	 * ODR = 6400 Hz. It is 6.6 ms per code for ODR = 3200 Hz and below.477	 */478	if (st->odr == ADXL372_ODR_6400HZ)479		scale_factor = 3300;480	else481		scale_factor = 6600;482 483	reg_val = DIV_ROUND_CLOSEST(act_time_ms * 1000, scale_factor);484 485	/* TIME_ACT register is 8 bits wide */486	if (reg_val > 0xFF)487		reg_val = 0xFF;488 489	ret = regmap_write(st->regmap, ADXL372_TIME_ACT, reg_val);490	if (ret < 0)491		return ret;492 493	st->act_time_ms = act_time_ms;494 495	return ret;496}497 498static int adxl372_set_inactivity_time_ms(struct adxl372_state *st,499					  unsigned int inact_time_ms)500{501	unsigned int reg_val_h, reg_val_l, res, scale_factor;502	int ret;503 504	/*505	 * 13 ms per code is the scale factor of the TIME_INACT register for506	 * ODR = 6400 Hz. It is 26 ms per code for ODR = 3200 Hz and below.507	 */508	if (st->odr == ADXL372_ODR_6400HZ)509		scale_factor = 13;510	else511		scale_factor = 26;512 513	res = DIV_ROUND_CLOSEST(inact_time_ms, scale_factor);514	reg_val_h = (res >> 8) & 0xFF;515	reg_val_l = res & 0xFF;516 517	ret = regmap_write(st->regmap, ADXL372_TIME_INACT_H, reg_val_h);518	if (ret < 0)519		return ret;520 521	ret = regmap_write(st->regmap, ADXL372_TIME_INACT_L, reg_val_l);522	if (ret < 0)523		return ret;524 525	st->inact_time_ms = inact_time_ms;526 527	return ret;528}529 530static int adxl372_set_interrupts(struct adxl372_state *st,531				  unsigned long int1_bitmask,532				  unsigned long int2_bitmask)533{534	int ret;535 536	ret = regmap_write(st->regmap, ADXL372_INT1_MAP, int1_bitmask);537	if (ret < 0)538		return ret;539 540	return regmap_write(st->regmap, ADXL372_INT2_MAP, int2_bitmask);541}542 543static int adxl372_configure_fifo(struct adxl372_state *st)544{545	unsigned int fifo_samples, fifo_ctl;546	int ret;547 548	/* FIFO must be configured while in standby mode */549	ret = adxl372_set_op_mode(st, ADXL372_STANDBY);550	if (ret < 0)551		return ret;552 553	/*554	 * watermark stores the number of sets; we need to write the FIFO555	 * registers with the number of samples556	 */557	fifo_samples = (st->watermark * st->fifo_set_size);558	fifo_ctl = ADXL372_FIFO_CTL_FORMAT_MODE(st->fifo_format) |559		   ADXL372_FIFO_CTL_MODE_MODE(st->fifo_mode) |560		   ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples);561 562	ret = regmap_write(st->regmap,563			   ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF);564	if (ret < 0)565		return ret;566 567	ret = regmap_write(st->regmap, ADXL372_FIFO_CTL, fifo_ctl);568	if (ret < 0)569		return ret;570 571	return adxl372_set_op_mode(st, ADXL372_FULL_BW_MEASUREMENT);572}573 574static int adxl372_get_status(struct adxl372_state *st,575			      u8 *status1, u8 *status2,576			      u16 *fifo_entries)577{578	__be32 buf;579	u32 val;580	int ret;581 582	/* STATUS1, STATUS2, FIFO_ENTRIES2 and FIFO_ENTRIES are adjacent regs */583	ret = regmap_bulk_read(st->regmap, ADXL372_STATUS_1,584			       &buf, sizeof(buf));585	if (ret < 0)586		return ret;587 588	val = be32_to_cpu(buf);589 590	*status1 = (val >> 24) & 0x0F;591	*status2 = (val >> 16) & 0x0F;592	/*593	 * FIFO_ENTRIES contains the least significant byte, and FIFO_ENTRIES2594	 * contains the two most significant bits595	 */596	*fifo_entries = val & 0x3FF;597 598	return ret;599}600 601static void adxl372_arrange_axis_data(struct adxl372_state *st, __be16 *sample)602{603	__be16	axis_sample[3];604	int i = 0;605 606	memset(axis_sample, 0, 3 * sizeof(__be16));607	if (ADXL372_X_AXIS_EN(st->fifo_axis_mask))608		axis_sample[i++] = sample[0];609	if (ADXL372_Y_AXIS_EN(st->fifo_axis_mask))610		axis_sample[i++] = sample[1];611	if (ADXL372_Z_AXIS_EN(st->fifo_axis_mask))612		axis_sample[i++] = sample[2];613 614	memcpy(sample, axis_sample, 3 * sizeof(__be16));615}616 617static void adxl372_push_event(struct iio_dev *indio_dev, s64 timestamp, u8 status2)618{619	unsigned int ev_dir = IIO_EV_DIR_NONE;620 621	if (ADXL372_STATUS_2_ACT(status2))622		ev_dir = IIO_EV_DIR_RISING;623 624	if (ADXL372_STATUS_2_INACT(status2))625		ev_dir = IIO_EV_DIR_FALLING;626 627	if (ev_dir != IIO_EV_DIR_NONE)628		iio_push_event(indio_dev,629			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,630						  IIO_EV_TYPE_THRESH, ev_dir),631			       timestamp);632}633 634static irqreturn_t adxl372_trigger_handler(int irq, void  *p)635{636	struct iio_poll_func *pf = p;637	struct iio_dev *indio_dev = pf->indio_dev;638	struct adxl372_state *st = iio_priv(indio_dev);639	u8 status1, status2;640	u16 fifo_entries;641	int i, ret;642 643	ret = adxl372_get_status(st, &status1, &status2, &fifo_entries);644	if (ret < 0)645		goto err;646 647	adxl372_push_event(indio_dev, iio_get_time_ns(indio_dev), status2);648 649	if (st->fifo_mode != ADXL372_FIFO_BYPASSED &&650	    ADXL372_STATUS_1_FIFO_FULL(status1)) {651		/*652		 * When reading data from multiple axes from the FIFO,653		 * to ensure that data is not overwritten and stored out654		 * of order at least one sample set must be left in the655		 * FIFO after every read.656		 */657		fifo_entries -= st->fifo_set_size;658 659		/* Read data from the FIFO */660		ret = regmap_noinc_read(st->regmap, ADXL372_FIFO_DATA,661					st->fifo_buf,662					fifo_entries * sizeof(u16));663		if (ret < 0)664			goto err;665 666		/* Each sample is 2 bytes */667		for (i = 0; i < fifo_entries; i += st->fifo_set_size) {668			/* filter peak detection data */669			if (st->peak_fifo_mode_en)670				adxl372_arrange_axis_data(st, &st->fifo_buf[i]);671			iio_push_to_buffers(indio_dev, &st->fifo_buf[i]);672		}673	}674err:675	iio_trigger_notify_done(indio_dev->trig);676	return IRQ_HANDLED;677}678 679static int adxl372_setup(struct adxl372_state *st)680{681	unsigned int regval;682	int ret;683 684	ret = regmap_read(st->regmap, ADXL372_DEVID, &regval);685	if (ret < 0)686		return ret;687 688	if (regval != ADXL372_DEVID_VAL) {689		dev_err(st->dev, "Invalid chip id %x\n", regval);690		return -ENODEV;691	}692 693	/*694	 * Perform a software reset to make sure the device is in a consistent695	 * state after start up.696	 */697	ret = regmap_write(st->regmap, ADXL372_RESET, ADXL372_RESET_CODE);698	if (ret < 0)699		return ret;700 701	ret = adxl372_set_op_mode(st, ADXL372_STANDBY);702	if (ret < 0)703		return ret;704 705	/* Set threshold for activity detection to 1g */706	ret = adxl372_set_activity_threshold(st, ADXL372_ACTIVITY,707					     true, true, 1000);708	if (ret < 0)709		return ret;710 711	/* Set threshold for inactivity detection to 100mg */712	ret = adxl372_set_activity_threshold(st, ADXL372_INACTIVITY,713					     true, true, 100);714	if (ret < 0)715		return ret;716 717	/* Set activity processing in Looped mode */718	ret = adxl372_set_act_proc_mode(st, ADXL372_LOOPED);719	if (ret < 0)720		return ret;721 722	ret = adxl372_set_odr(st, ADXL372_ODR_6400HZ);723	if (ret < 0)724		return ret;725 726	ret = adxl372_set_bandwidth(st, ADXL372_BW_3200HZ);727	if (ret < 0)728		return ret;729 730	/* Set activity timer to 1ms */731	ret = adxl372_set_activity_time_ms(st, 1);732	if (ret < 0)733		return ret;734 735	/* Set inactivity timer to 10s */736	ret = adxl372_set_inactivity_time_ms(st, 10000);737	if (ret < 0)738		return ret;739 740	/* Set the mode of operation to full bandwidth measurement mode */741	return adxl372_set_op_mode(st, ADXL372_FULL_BW_MEASUREMENT);742}743 744static int adxl372_reg_access(struct iio_dev *indio_dev,745			      unsigned int reg,746			      unsigned int writeval,747			      unsigned int *readval)748{749	struct adxl372_state *st = iio_priv(indio_dev);750 751	if (readval)752		return regmap_read(st->regmap, reg, readval);753	else754		return regmap_write(st->regmap, reg, writeval);755}756 757static int adxl372_read_raw(struct iio_dev *indio_dev,758			    struct iio_chan_spec const *chan,759			    int *val, int *val2, long info)760{761	struct adxl372_state *st = iio_priv(indio_dev);762	int ret;763 764	switch (info) {765	case IIO_CHAN_INFO_RAW:766		ret = iio_device_claim_direct_mode(indio_dev);767		if (ret)768			return ret;769 770		ret = adxl372_read_axis(st, chan->address);771		iio_device_release_direct_mode(indio_dev);772		if (ret < 0)773			return ret;774 775		*val = sign_extend32(ret >> chan->scan_type.shift,776				     chan->scan_type.realbits - 1);777		return IIO_VAL_INT;778	case IIO_CHAN_INFO_SCALE:779		*val = 0;780		*val2 = ADXL372_USCALE;781		return IIO_VAL_INT_PLUS_MICRO;782	case IIO_CHAN_INFO_SAMP_FREQ:783		*val = adxl372_samp_freq_tbl[st->odr];784		return IIO_VAL_INT;785	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:786		*val = adxl372_bw_freq_tbl[st->bw];787		return IIO_VAL_INT;788	}789 790	return -EINVAL;791}792 793static int adxl372_write_raw(struct iio_dev *indio_dev,794			     struct iio_chan_spec const *chan,795			     int val, int val2, long info)796{797	struct adxl372_state *st = iio_priv(indio_dev);798	int odr_index, bw_index, ret;799 800	switch (info) {801	case IIO_CHAN_INFO_SAMP_FREQ:802		odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,803					ARRAY_SIZE(adxl372_samp_freq_tbl),804					val);805		ret = adxl372_set_odr(st, odr_index);806		if (ret < 0)807			return ret;808		/*809		 * The timer period depends on the ODR selected.810		 * At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms811		 */812		ret = adxl372_set_activity_time_ms(st, st->act_time_ms);813		if (ret < 0)814			return ret;815		/*816		 * The timer period depends on the ODR selected.817		 * At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms818		 */819		ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);820		if (ret < 0)821			return ret;822		/*823		 * The maximum bandwidth is constrained to at most half of824		 * the ODR to ensure that the Nyquist criteria is not violated825		 */826		if (st->bw > odr_index)827			ret = adxl372_set_bandwidth(st, odr_index);828 829		return ret;830	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:831		bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,832					ARRAY_SIZE(adxl372_bw_freq_tbl),833					val);834		return adxl372_set_bandwidth(st, bw_index);835	default:836		return -EINVAL;837	}838}839 840static int adxl372_read_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,841				    enum iio_event_type type, enum iio_event_direction dir,842				    enum iio_event_info info, int *val, int *val2)843{844	struct adxl372_state *st = iio_priv(indio_dev);845	unsigned int addr;846	u16 raw_value;847	int ret;848 849	switch (info) {850	case IIO_EV_INFO_VALUE:851		switch (dir) {852		case IIO_EV_DIR_RISING:853			addr = ADXL372_X_THRESH_ACT_H + 2 * chan->scan_index;854			ret = adxl372_read_threshold_value(indio_dev, addr, &raw_value);855			if (ret < 0)856				return ret;857			*val = raw_value * ADXL372_USCALE;858			*val2 = 1000000;859			return IIO_VAL_FRACTIONAL;860		case IIO_EV_DIR_FALLING:861			addr = ADXL372_X_THRESH_INACT_H + 2 * chan->scan_index;862			ret =  adxl372_read_threshold_value(indio_dev, addr, &raw_value);863			if (ret < 0)864				return ret;865			*val = raw_value * ADXL372_USCALE;866			*val2 = 1000000;867			return IIO_VAL_FRACTIONAL;868		default:869			return -EINVAL;870		}871	case IIO_EV_INFO_PERIOD:872		switch (dir) {873		case IIO_EV_DIR_RISING:874			*val = st->act_time_ms;875			*val2 = 1000;876			return IIO_VAL_FRACTIONAL;877		case IIO_EV_DIR_FALLING:878			*val = st->inact_time_ms;879			*val2 = 1000;880			return IIO_VAL_FRACTIONAL;881		default:882			return -EINVAL;883		}884	default:885		return -EINVAL;886	}887}888 889static int adxl372_write_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,890				     enum iio_event_type type, enum iio_event_direction dir,891				     enum iio_event_info info, int val, int val2)892{893	struct adxl372_state *st = iio_priv(indio_dev);894	unsigned int val_ms;895	unsigned int addr;896	u16 raw_val;897 898	switch (info) {899	case IIO_EV_INFO_VALUE:900		raw_val = DIV_ROUND_UP(val * 1000000, ADXL372_USCALE);901		switch (dir) {902		case IIO_EV_DIR_RISING:903			addr = ADXL372_X_THRESH_ACT_H + 2 * chan->scan_index;904			return adxl372_write_threshold_value(indio_dev, addr, raw_val);905		case IIO_EV_DIR_FALLING:906			addr = ADXL372_X_THRESH_INACT_H + 2 * chan->scan_index;907			return adxl372_write_threshold_value(indio_dev, addr, raw_val);908		default:909			return -EINVAL;910		}911	case IIO_EV_INFO_PERIOD:912		val_ms = val * 1000 + DIV_ROUND_UP(val2, 1000);913		switch (dir) {914		case IIO_EV_DIR_RISING:915			return adxl372_set_activity_time_ms(st, val_ms);916		case IIO_EV_DIR_FALLING:917			return adxl372_set_inactivity_time_ms(st, val_ms);918		default:919			return -EINVAL;920		}921	default:922		return -EINVAL;923	}924}925 926static int adxl372_read_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,927				     enum iio_event_type type, enum iio_event_direction dir)928{929	struct adxl372_state *st = iio_priv(indio_dev);930 931	switch (dir) {932	case IIO_EV_DIR_RISING:933		return FIELD_GET(ADXL372_INT1_MAP_ACT_MSK, st->int1_bitmask);934	case IIO_EV_DIR_FALLING:935		return FIELD_GET(ADXL372_INT1_MAP_INACT_MSK, st->int1_bitmask);936	default:937		return -EINVAL;938	}939}940 941static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,942				      enum iio_event_type type, enum iio_event_direction dir,943				      int state)944{945	struct adxl372_state *st = iio_priv(indio_dev);946 947	switch (dir) {948	case IIO_EV_DIR_RISING:949		set_mask_bits(&st->int1_bitmask, ADXL372_INT1_MAP_ACT_MSK,950			      ADXL372_INT1_MAP_ACT_MODE(state));951		break;952	case IIO_EV_DIR_FALLING:953		set_mask_bits(&st->int1_bitmask, ADXL372_INT1_MAP_INACT_MSK,954			      ADXL372_INT1_MAP_INACT_MODE(state));955		break;956	default:957		return -EINVAL;958	}959 960	return adxl372_set_interrupts(st, st->int1_bitmask, 0);961}962 963static ssize_t adxl372_show_filter_freq_avail(struct device *dev,964					      struct device_attribute *attr,965					      char *buf)966{967	struct iio_dev *indio_dev = dev_to_iio_dev(dev);968	struct adxl372_state *st = iio_priv(indio_dev);969	int i;970	size_t len = 0;971 972	for (i = 0; i <= st->odr; i++)973		len += scnprintf(buf + len, PAGE_SIZE - len,974				 "%d ", adxl372_bw_freq_tbl[i]);975 976	buf[len - 1] = '\n';977 978	return len;979}980 981static ssize_t adxl372_get_fifo_enabled(struct device *dev,982					  struct device_attribute *attr,983					  char *buf)984{985	struct iio_dev *indio_dev = dev_to_iio_dev(dev);986	struct adxl372_state *st = iio_priv(indio_dev);987 988	return sprintf(buf, "%d\n", st->fifo_mode);989}990 991static ssize_t adxl372_get_fifo_watermark(struct device *dev,992					  struct device_attribute *attr,993					  char *buf)994{995	struct iio_dev *indio_dev = dev_to_iio_dev(dev);996	struct adxl372_state *st = iio_priv(indio_dev);997 998	return sprintf(buf, "%d\n", st->watermark);999}1000 1001IIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_min, "1");1002IIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_max,1003			     __stringify(ADXL372_FIFO_SIZE));1004static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,1005		       adxl372_get_fifo_watermark, NULL, 0);1006static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,1007		       adxl372_get_fifo_enabled, NULL, 0);1008 1009static const struct iio_dev_attr *adxl372_fifo_attributes[] = {1010	&iio_dev_attr_hwfifo_watermark_min,1011	&iio_dev_attr_hwfifo_watermark_max,1012	&iio_dev_attr_hwfifo_watermark,1013	&iio_dev_attr_hwfifo_enabled,1014	NULL,1015};1016 1017static int adxl372_set_watermark(struct iio_dev *indio_dev, unsigned int val)1018{1019	struct adxl372_state *st  = iio_priv(indio_dev);1020 1021	if (val > ADXL372_FIFO_SIZE)1022		val = ADXL372_FIFO_SIZE;1023 1024	st->watermark = val;1025 1026	return 0;1027}1028 1029static int adxl372_buffer_postenable(struct iio_dev *indio_dev)1030{1031	struct adxl372_state *st = iio_priv(indio_dev);1032	unsigned int mask;1033	int i, ret;1034 1035	st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK;1036	ret = adxl372_set_interrupts(st, st->int1_bitmask, 0);1037	if (ret < 0)1038		return ret;1039 1040	mask = *indio_dev->active_scan_mask;1041 1042	for (i = 0; i < ARRAY_SIZE(adxl372_axis_lookup_table); i++) {1043		if (mask == adxl372_axis_lookup_table[i].bits)1044			break;1045	}1046 1047	if (i == ARRAY_SIZE(adxl372_axis_lookup_table))1048		return -EINVAL;1049 1050	st->fifo_format = adxl372_axis_lookup_table[i].fifo_format;1051	st->fifo_axis_mask = adxl372_axis_lookup_table[i].bits;1052	st->fifo_set_size = bitmap_weight(indio_dev->active_scan_mask,1053					  iio_get_masklength(indio_dev));1054 1055	/* Configure the FIFO to store sets of impact event peak. */1056	if (st->peak_fifo_mode_en) {1057		st->fifo_set_size = 3;1058		st->fifo_format = ADXL372_XYZ_PEAK_FIFO;1059	}1060 1061	/*1062	 * The 512 FIFO samples can be allotted in several ways, such as:1063	 * 170 sample sets of concurrent 3-axis data1064	 * 256 sample sets of concurrent 2-axis data (user selectable)1065	 * 512 sample sets of single-axis data1066	 * 170 sets of impact event peak (x, y, z)1067	 */1068	if ((st->watermark * st->fifo_set_size) > ADXL372_FIFO_SIZE)1069		st->watermark = (ADXL372_FIFO_SIZE  / st->fifo_set_size);1070 1071	st->fifo_mode = ADXL372_FIFO_STREAMED;1072 1073	ret = adxl372_configure_fifo(st);1074	if (ret < 0) {1075		st->fifo_mode = ADXL372_FIFO_BYPASSED;1076		st->int1_bitmask &= ~ADXL372_INT1_MAP_FIFO_FULL_MSK;1077		adxl372_set_interrupts(st, st->int1_bitmask, 0);1078		return ret;1079	}1080 1081	return 0;1082}1083 1084static int adxl372_buffer_predisable(struct iio_dev *indio_dev)1085{1086	struct adxl372_state *st = iio_priv(indio_dev);1087 1088	st->int1_bitmask &= ~ADXL372_INT1_MAP_FIFO_FULL_MSK;1089	adxl372_set_interrupts(st, st->int1_bitmask, 0);1090	st->fifo_mode = ADXL372_FIFO_BYPASSED;1091	adxl372_configure_fifo(st);1092 1093	return 0;1094}1095 1096static const struct iio_buffer_setup_ops adxl372_buffer_ops = {1097	.postenable = adxl372_buffer_postenable,1098	.predisable = adxl372_buffer_predisable,1099};1100 1101static int adxl372_dready_trig_set_state(struct iio_trigger *trig,1102					 bool state)1103{1104	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);1105	struct adxl372_state *st = iio_priv(indio_dev);1106 1107	if (state)1108		st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK;1109 1110	return adxl372_set_interrupts(st, st->int1_bitmask, 0);1111}1112 1113static int adxl372_validate_trigger(struct iio_dev *indio_dev,1114				    struct iio_trigger *trig)1115{1116	struct adxl372_state *st = iio_priv(indio_dev);1117 1118	if (st->dready_trig != trig && st->peak_datardy_trig != trig)1119		return -EINVAL;1120 1121	return 0;1122}1123 1124static const struct iio_trigger_ops adxl372_trigger_ops = {1125	.validate_device = &iio_trigger_validate_own_device,1126	.set_trigger_state = adxl372_dready_trig_set_state,1127};1128 1129static int adxl372_peak_dready_trig_set_state(struct iio_trigger *trig,1130					      bool state)1131{1132	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);1133	struct adxl372_state *st = iio_priv(indio_dev);1134 1135	if (state)1136		st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK;1137 1138	st->peak_fifo_mode_en = state;1139 1140	return adxl372_set_interrupts(st, st->int1_bitmask, 0);1141}1142 1143static const struct iio_trigger_ops adxl372_peak_data_trigger_ops = {1144	.validate_device = &iio_trigger_validate_own_device,1145	.set_trigger_state = adxl372_peak_dready_trig_set_state,1146};1147 1148static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");1149static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,1150		       0444, adxl372_show_filter_freq_avail, NULL, 0);1151 1152static struct attribute *adxl372_attributes[] = {1153	&iio_const_attr_sampling_frequency_available.dev_attr.attr,1154	&iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,1155	NULL,1156};1157 1158static const struct attribute_group adxl372_attrs_group = {1159	.attrs = adxl372_attributes,1160};1161 1162static const struct iio_info adxl372_info = {1163	.validate_trigger = &adxl372_validate_trigger,1164	.attrs = &adxl372_attrs_group,1165	.read_raw = adxl372_read_raw,1166	.write_raw = adxl372_write_raw,1167	.read_event_config = adxl372_read_event_config,1168	.write_event_config = adxl372_write_event_config,1169	.read_event_value = adxl372_read_event_value,1170	.write_event_value = adxl372_write_event_value,1171	.debugfs_reg_access = &adxl372_reg_access,1172	.hwfifo_set_watermark = adxl372_set_watermark,1173};1174 1175bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg)1176{1177	return (reg == ADXL372_FIFO_DATA);1178}1179EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, IIO_ADXL372);1180 1181int adxl372_probe(struct device *dev, struct regmap *regmap,1182		  int irq, const char *name)1183{1184	struct iio_dev *indio_dev;1185	struct adxl372_state *st;1186	int ret;1187 1188	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));1189	if (!indio_dev)1190		return -ENOMEM;1191 1192	st = iio_priv(indio_dev);1193	dev_set_drvdata(dev, indio_dev);1194 1195	st->dev = dev;1196	st->regmap = regmap;1197	st->irq = irq;1198 1199	mutex_init(&st->threshold_m);1200 1201	indio_dev->channels = adxl372_channels;1202	indio_dev->num_channels = ARRAY_SIZE(adxl372_channels);1203	indio_dev->available_scan_masks = adxl372_channel_masks;1204	indio_dev->name = name;1205	indio_dev->info = &adxl372_info;1206	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;1207 1208	ret = adxl372_setup(st);1209	if (ret < 0) {1210		dev_err(dev, "ADXL372 setup failed\n");1211		return ret;1212	}1213 1214	ret = devm_iio_triggered_buffer_setup_ext(dev,1215						  indio_dev, NULL,1216						  adxl372_trigger_handler,1217						  IIO_BUFFER_DIRECTION_IN,1218						  &adxl372_buffer_ops,1219						  adxl372_fifo_attributes);1220	if (ret < 0)1221		return ret;1222 1223	if (st->irq) {1224		st->dready_trig = devm_iio_trigger_alloc(dev,1225							 "%s-dev%d",1226							 indio_dev->name,1227							 iio_device_id(indio_dev));1228		if (st->dready_trig == NULL)1229			return -ENOMEM;1230 1231		st->peak_datardy_trig = devm_iio_trigger_alloc(dev,1232							       "%s-dev%d-peak",1233							       indio_dev->name,1234							       iio_device_id(indio_dev));1235		if (!st->peak_datardy_trig)1236			return -ENOMEM;1237 1238		st->dready_trig->ops = &adxl372_trigger_ops;1239		st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops;1240		iio_trigger_set_drvdata(st->dready_trig, indio_dev);1241		iio_trigger_set_drvdata(st->peak_datardy_trig, indio_dev);1242		ret = devm_iio_trigger_register(dev, st->dready_trig);1243		if (ret < 0)1244			return ret;1245 1246		ret = devm_iio_trigger_register(dev, st->peak_datardy_trig);1247		if (ret < 0)1248			return ret;1249 1250		indio_dev->trig = iio_trigger_get(st->dready_trig);1251 1252		ret = devm_request_threaded_irq(dev, st->irq,1253					iio_trigger_generic_data_rdy_poll,1254					NULL,1255					IRQF_TRIGGER_RISING | IRQF_ONESHOT,1256					indio_dev->name, st->dready_trig);1257		if (ret < 0)1258			return ret;1259	}1260 1261	return devm_iio_device_register(dev, indio_dev);1262}1263EXPORT_SYMBOL_NS_GPL(adxl372_probe, IIO_ADXL372);1264 1265MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");1266MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer driver");1267MODULE_LICENSE("GPL");1268