brintos

brintos / linux-shallow public Read only

0
0
Text · 30.3 KiB · d8fb340 Raw
1145 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2024 NanjingTianyihexin Electronics Ltd.4 * http://www.tianyihexin.com5 *6 * Driver for NanjingTianyihexin HX9023S Cap Sensor.7 * Datasheet available at:8 * http://www.tianyihexin.com/ueditor/php/upload/file/20240614/1718336303992081.pdf9 */10 11#include <linux/array_size.h>12#include <linux/bitfield.h>13#include <linux/bitops.h>14#include <linux/cleanup.h>15#include <linux/device.h>16#include <linux/errno.h>17#include <linux/i2c.h>18#include <linux/interrupt.h>19#include <linux/irqreturn.h>20#include <linux/math64.h>21#include <linux/mod_devicetable.h>22#include <linux/module.h>23#include <linux/mutex.h>24#include <linux/pm.h>25#include <linux/property.h>26#include <linux/regmap.h>27#include <linux/regulator/consumer.h>28#include <linux/types.h>29#include <linux/units.h>30 31#include <asm/byteorder.h>32#include <linux/unaligned.h>33 34#include <linux/iio/buffer.h>35#include <linux/iio/events.h>36#include <linux/iio/iio.h>37#include <linux/iio/trigger.h>38#include <linux/iio/triggered_buffer.h>39#include <linux/iio/trigger_consumer.h>40#include <linux/iio/types.h>41 42#define HX9023S_CHIP_ID 0x1D43#define HX9023S_CH_NUM 544#define HX9023S_POS 0x0345#define HX9023S_NEG 0x0246#define HX9023S_NOT_CONNECTED 1647 48#define HX9023S_GLOBAL_CTRL0                   0x0049#define HX9023S_PRF_CFG                        0x0250#define HX9023S_CH0_CFG_7_0                    0x0351#define HX9023S_CH4_CFG_9_8                    0x0C52#define HX9023S_RANGE_7_0                      0x0D53#define HX9023S_RANGE_9_8                      0x0E54#define HX9023S_RANGE_18_16                    0x0F55#define HX9023S_AVG0_NOSR0_CFG                 0x1056#define HX9023S_NOSR12_CFG                     0x1157#define HX9023S_NOSR34_CFG                     0x1258#define HX9023S_AVG12_CFG                      0x1359#define HX9023S_AVG34_CFG                      0x1460#define HX9023S_OFFSET_DAC0_7_0                0x1561#define HX9023S_OFFSET_DAC4_9_8                0x1E62#define HX9023S_SAMPLE_NUM_7_0                 0x1F63#define HX9023S_INTEGRATION_NUM_7_0            0x2164#define HX9023S_CH_NUM_CFG                     0x2465#define HX9023S_LP_ALP_4_CFG                   0x2966#define HX9023S_LP_ALP_1_0_CFG                 0x2A67#define HX9023S_LP_ALP_3_2_CFG                 0x2B68#define HX9023S_UP_ALP_1_0_CFG                 0x2C69#define HX9023S_UP_ALP_3_2_CFG                 0x2D70#define HX9023S_DN_UP_ALP_0_4_CFG              0x2E71#define HX9023S_DN_ALP_2_1_CFG                 0x2F72#define HX9023S_DN_ALP_4_3_CFG                 0x3073#define HX9023S_RAW_BL_RD_CFG                  0x3874#define HX9023S_INTERRUPT_CFG                  0x3975#define HX9023S_INTERRUPT_CFG1                 0x3A76#define HX9023S_CALI_DIFF_CFG                  0x3B77#define HX9023S_DITHER_CFG                     0x3C78#define HX9023S_DEVICE_ID                      0x6079#define HX9023S_PROX_STATUS                    0x6B80#define HX9023S_PROX_INT_HIGH_CFG              0x6C81#define HX9023S_PROX_INT_LOW_CFG               0x6D82#define HX9023S_PROX_HIGH_DIFF_CFG_CH0_0       0x8083#define HX9023S_PROX_LOW_DIFF_CFG_CH0_0        0x8884#define HX9023S_PROX_LOW_DIFF_CFG_CH3_1        0x8F85#define HX9023S_PROX_HIGH_DIFF_CFG_CH4_0       0x9E86#define HX9023S_PROX_HIGH_DIFF_CFG_CH4_1       0x9F87#define HX9023S_PROX_LOW_DIFF_CFG_CH4_0        0xA288#define HX9023S_PROX_LOW_DIFF_CFG_CH4_1        0xA389#define HX9023S_CAP_INI_CH4_0                  0xB390#define HX9023S_LP_DIFF_CH4_2                  0xBA91#define HX9023S_RAW_BL_CH4_0                   0xB592#define HX9023S_LP_DIFF_CH4_0                  0xB893#define HX9023S_DSP_CONFIG_CTRL1               0xC894#define HX9023S_CAP_INI_CH0_0                  0xE095#define HX9023S_RAW_BL_CH0_0                   0xE896#define HX9023S_LP_DIFF_CH0_0                  0xF497#define HX9023S_LP_DIFF_CH3_2                  0xFF98 99#define HX9023S_DATA_LOCK_MASK BIT(4)100#define HX9023S_INTERRUPT_MASK GENMASK(9, 0)101#define HX9023S_PROX_DEBOUNCE_MASK GENMASK(3, 0)102 103struct hx9023s_ch_data {104	s16 raw; /* Raw Data*/105	s16 lp; /* Low Pass Filter Data*/106	s16 bl; /* Base Line Data */107	s16 diff; /* Difference of Low Pass Data and Base Line Data */108 109	struct {110		unsigned int near;111		unsigned int far;112	} thres;113 114	u16 dac;115	u8 channel_positive;116	u8 channel_negative;117	bool sel_bl;118	bool sel_raw;119	bool sel_diff;120	bool sel_lp;121	bool enable;122};123 124struct hx9023s_data {125	struct iio_trigger *trig;126	struct regmap *regmap;127	unsigned long chan_prox_stat;128	unsigned long chan_read;129	unsigned long chan_event;130	unsigned long ch_en_stat;131	unsigned long chan_in_use;132	unsigned int prox_state_reg;133	bool trigger_enabled;134 135	struct {136		__le16 channels[HX9023S_CH_NUM];137		s64 ts __aligned(8);138	} buffer;139 140	/*141	 * Serialize access to registers below:142	 * HX9023S_PROX_INT_LOW_CFG,143	 * HX9023S_PROX_INT_HIGH_CFG,144	 * HX9023S_INTERRUPT_CFG,145	 * HX9023S_CH_NUM_CFG146	 * Serialize access to channel configuration in147	 * hx9023s_push_events and hx9023s_trigger_handler.148	 */149	struct mutex mutex;150	struct hx9023s_ch_data ch_data[HX9023S_CH_NUM];151};152 153static const struct reg_sequence hx9023s_reg_init_list[] = {154	/* scan period */155	REG_SEQ0(HX9023S_PRF_CFG, 0x17),156 157	/* full scale of conversion phase of each channel */158	REG_SEQ0(HX9023S_RANGE_7_0, 0x11),159	REG_SEQ0(HX9023S_RANGE_9_8, 0x02),160	REG_SEQ0(HX9023S_RANGE_18_16, 0x00),161 162	/* ADC average number and OSR number of each channel */163	REG_SEQ0(HX9023S_AVG0_NOSR0_CFG, 0x71),164	REG_SEQ0(HX9023S_NOSR12_CFG, 0x44),165	REG_SEQ0(HX9023S_NOSR34_CFG, 0x00),166	REG_SEQ0(HX9023S_AVG12_CFG, 0x33),167	REG_SEQ0(HX9023S_AVG34_CFG, 0x00),168 169	/* sample & integration frequency of the ADC */170	REG_SEQ0(HX9023S_SAMPLE_NUM_7_0, 0x65),171	REG_SEQ0(HX9023S_INTEGRATION_NUM_7_0, 0x65),172 173	/* coefficient of the first order low pass filter during each channel */174	REG_SEQ0(HX9023S_LP_ALP_1_0_CFG, 0x22),175	REG_SEQ0(HX9023S_LP_ALP_3_2_CFG, 0x22),176	REG_SEQ0(HX9023S_LP_ALP_4_CFG, 0x02),177 178	/* up coefficient of the first order low pass filter during each channel */179	REG_SEQ0(HX9023S_UP_ALP_1_0_CFG, 0x88),180	REG_SEQ0(HX9023S_UP_ALP_3_2_CFG, 0x88),181	REG_SEQ0(HX9023S_DN_UP_ALP_0_4_CFG, 0x18),182 183	/* down coefficient of the first order low pass filter during each channel */184	REG_SEQ0(HX9023S_DN_ALP_2_1_CFG, 0x11),185	REG_SEQ0(HX9023S_DN_ALP_4_3_CFG, 0x11),186 187	/* selection of data for the Data Mux Register to output data */188	REG_SEQ0(HX9023S_RAW_BL_RD_CFG, 0xF0),189 190	/* enable the interrupt function */191	REG_SEQ0(HX9023S_INTERRUPT_CFG, 0xFF),192	REG_SEQ0(HX9023S_INTERRUPT_CFG1, 0x3B),193	REG_SEQ0(HX9023S_DITHER_CFG, 0x21),194 195	/* threshold of the offset compensation */196	REG_SEQ0(HX9023S_CALI_DIFF_CFG, 0x07),197 198	/* proximity persistency number(near & far) */199	REG_SEQ0(HX9023S_PROX_INT_HIGH_CFG, 0x01),200	REG_SEQ0(HX9023S_PROX_INT_LOW_CFG, 0x01),201 202	/* disable the data lock */203	REG_SEQ0(HX9023S_DSP_CONFIG_CTRL1, 0x00),204};205 206static const struct iio_event_spec hx9023s_events[] = {207	{208		.type = IIO_EV_TYPE_THRESH,209		.dir = IIO_EV_DIR_RISING,210		.mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD),211		.mask_separate = BIT(IIO_EV_INFO_VALUE),212	},213	{214		.type = IIO_EV_TYPE_THRESH,215		.dir = IIO_EV_DIR_FALLING,216		.mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD),217		.mask_separate = BIT(IIO_EV_INFO_VALUE),218 219	},220	{221		.type = IIO_EV_TYPE_THRESH,222		.dir = IIO_EV_DIR_EITHER,223		.mask_separate = BIT(IIO_EV_INFO_ENABLE),224	},225};226 227#define HX9023S_CHANNEL(idx)					\228{								\229	.type = IIO_PROXIMITY,					\230	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\231	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\232	.indexed = 1,						\233	.channel = idx,						\234	.address = 0,						\235	.event_spec = hx9023s_events,				\236	.num_event_specs = ARRAY_SIZE(hx9023s_events),		\237	.scan_index = idx,					\238	.scan_type = {						\239		.sign = 's',					\240		.realbits = 16,					\241		.storagebits = 16,				\242		.endianness = IIO_BE,				\243	},							\244}245 246static const struct iio_chan_spec hx9023s_channels[] = {247	HX9023S_CHANNEL(0),248	HX9023S_CHANNEL(1),249	HX9023S_CHANNEL(2),250	HX9023S_CHANNEL(3),251	HX9023S_CHANNEL(4),252	IIO_CHAN_SOFT_TIMESTAMP(5),253};254 255static const unsigned int hx9023s_samp_freq_table[] = {256	2, 2, 4, 6, 8, 10, 14, 18, 22, 26,257	30, 34, 38, 42, 46, 50, 56, 62, 68, 74,258	80, 90, 100, 200, 300, 400, 600, 800, 1000, 2000,259	3000, 4000,260};261 262static const struct regmap_range hx9023s_rd_reg_ranges[] = {263	regmap_reg_range(HX9023S_GLOBAL_CTRL0, HX9023S_LP_DIFF_CH3_2),264};265 266static const struct regmap_range hx9023s_wr_reg_ranges[] = {267	regmap_reg_range(HX9023S_GLOBAL_CTRL0, HX9023S_LP_DIFF_CH3_2),268};269 270static const struct regmap_range hx9023s_volatile_reg_ranges[] = {271	regmap_reg_range(HX9023S_CAP_INI_CH4_0, HX9023S_LP_DIFF_CH4_2),272	regmap_reg_range(HX9023S_CAP_INI_CH0_0, HX9023S_LP_DIFF_CH3_2),273	regmap_reg_range(HX9023S_PROX_STATUS, HX9023S_PROX_STATUS),274};275 276static const struct regmap_access_table hx9023s_rd_regs = {277	.yes_ranges = hx9023s_rd_reg_ranges,278	.n_yes_ranges = ARRAY_SIZE(hx9023s_rd_reg_ranges),279};280 281static const struct regmap_access_table hx9023s_wr_regs = {282	.yes_ranges = hx9023s_wr_reg_ranges,283	.n_yes_ranges = ARRAY_SIZE(hx9023s_wr_reg_ranges),284};285 286static const struct regmap_access_table hx9023s_volatile_regs = {287	.yes_ranges = hx9023s_volatile_reg_ranges,288	.n_yes_ranges = ARRAY_SIZE(hx9023s_volatile_reg_ranges),289};290 291static const struct regmap_config hx9023s_regmap_config = {292	.reg_bits = 8,293	.val_bits = 8,294	.cache_type = REGCACHE_MAPLE,295	.rd_table = &hx9023s_rd_regs,296	.wr_table = &hx9023s_wr_regs,297	.volatile_table = &hx9023s_volatile_regs,298};299 300static int hx9023s_interrupt_enable(struct hx9023s_data *data)301{302	return regmap_update_bits(data->regmap, HX9023S_INTERRUPT_CFG,303				HX9023S_INTERRUPT_MASK, HX9023S_INTERRUPT_MASK);304}305 306static int hx9023s_interrupt_disable(struct hx9023s_data *data)307{308	return regmap_update_bits(data->regmap, HX9023S_INTERRUPT_CFG,309				HX9023S_INTERRUPT_MASK, 0x00);310}311 312static int hx9023s_data_lock(struct hx9023s_data *data, bool locked)313{314	if (locked)315		return regmap_update_bits(data->regmap,316					  HX9023S_DSP_CONFIG_CTRL1,317					  HX9023S_DATA_LOCK_MASK,318					  HX9023S_DATA_LOCK_MASK);319	else320		return regmap_update_bits(data->regmap,321					  HX9023S_DSP_CONFIG_CTRL1,322					  HX9023S_DATA_LOCK_MASK, 0);323}324 325static int hx9023s_ch_cfg(struct hx9023s_data *data)326{327	__le16 reg_list[HX9023S_CH_NUM];328	u8 ch_pos[HX9023S_CH_NUM];329	u8 ch_neg[HX9023S_CH_NUM];330	/* Bit positions corresponding to input pin connections */331	u8 conn_cs[HX9023S_CH_NUM] = { 0, 2, 4, 6, 8 };332	unsigned int i;333	u16 reg;334 335	for (i = 0; i < HX9023S_CH_NUM; i++) {336		ch_pos[i] = data->ch_data[i].channel_positive == HX9023S_NOT_CONNECTED ?337			HX9023S_NOT_CONNECTED : conn_cs[data->ch_data[i].channel_positive];338		ch_neg[i] = data->ch_data[i].channel_negative == HX9023S_NOT_CONNECTED ?339			HX9023S_NOT_CONNECTED : conn_cs[data->ch_data[i].channel_negative];340 341		reg = (HX9023S_POS << ch_pos[i]) | (HX9023S_NEG << ch_neg[i]);342		reg_list[i] = cpu_to_le16(reg);343	}344 345	return regmap_bulk_write(data->regmap, HX9023S_CH0_CFG_7_0, reg_list,346				 sizeof(reg_list));347}348 349static int hx9023s_write_far_debounce(struct hx9023s_data *data, int val)350{351	guard(mutex)(&data->mutex);352	return regmap_update_bits(data->regmap, HX9023S_PROX_INT_LOW_CFG,353				HX9023S_PROX_DEBOUNCE_MASK,354				FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, val));355}356 357static int hx9023s_write_near_debounce(struct hx9023s_data *data, int val)358{359	guard(mutex)(&data->mutex);360	return regmap_update_bits(data->regmap, HX9023S_PROX_INT_HIGH_CFG,361				HX9023S_PROX_DEBOUNCE_MASK,362				FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, val));363}364 365static int hx9023s_read_far_debounce(struct hx9023s_data *data, int *val)366{367	int ret;368 369	ret = regmap_read(data->regmap, HX9023S_PROX_INT_LOW_CFG, val);370	if (ret)371		return ret;372 373	*val = FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, *val);374 375	return IIO_VAL_INT;376}377 378static int hx9023s_read_near_debounce(struct hx9023s_data *data, int *val)379{380	int ret;381 382	ret = regmap_read(data->regmap, HX9023S_PROX_INT_HIGH_CFG, val);383	if (ret)384		return ret;385 386	*val = FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, *val);387 388	return IIO_VAL_INT;389}390 391static int hx9023s_get_thres_near(struct hx9023s_data *data, u8 ch, int *val)392{393	int ret;394	__le16 buf;395	unsigned int reg, tmp;396 397	reg = (ch == 4) ? HX9023S_PROX_HIGH_DIFF_CFG_CH4_0 :398		HX9023S_PROX_HIGH_DIFF_CFG_CH0_0 + (ch * 2);399 400	ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf));401	if (ret)402		return ret;403 404	tmp = (le16_to_cpu(buf) & GENMASK(9, 0)) * 32;405	data->ch_data[ch].thres.near = tmp;406	*val = tmp;407 408	return IIO_VAL_INT;409}410 411static int hx9023s_get_thres_far(struct hx9023s_data *data, u8 ch, int *val)412{413	int ret;414	__le16 buf;415	unsigned int reg, tmp;416 417	reg = (ch == 4) ? HX9023S_PROX_LOW_DIFF_CFG_CH4_0 :418		HX9023S_PROX_LOW_DIFF_CFG_CH0_0 + (ch * 2);419 420	ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf));421	if (ret)422		return ret;423 424	tmp = (le16_to_cpu(buf) & GENMASK(9, 0)) * 32;425	data->ch_data[ch].thres.far = tmp;426	*val = tmp;427 428	return IIO_VAL_INT;429}430 431static int hx9023s_set_thres_near(struct hx9023s_data *data, u8 ch, int val)432{433	__le16 val_le16 = cpu_to_le16((val / 32) & GENMASK(9, 0));434	unsigned int reg;435 436	data->ch_data[ch].thres.near = ((val / 32) & GENMASK(9, 0)) * 32;437	reg = (ch == 4) ? HX9023S_PROX_HIGH_DIFF_CFG_CH4_0 :438		HX9023S_PROX_HIGH_DIFF_CFG_CH0_0 + (ch * 2);439 440	return regmap_bulk_write(data->regmap, reg, &val_le16, sizeof(val_le16));441}442 443static int hx9023s_set_thres_far(struct hx9023s_data *data, u8 ch, int val)444{445	__le16 val_le16 = cpu_to_le16((val / 32) & GENMASK(9, 0));446	unsigned int reg;447 448	data->ch_data[ch].thres.far = ((val / 32) & GENMASK(9, 0)) * 32;449	reg = (ch == 4) ? HX9023S_PROX_LOW_DIFF_CFG_CH4_0 :450		HX9023S_PROX_LOW_DIFF_CFG_CH0_0 + (ch * 2);451 452	return regmap_bulk_write(data->regmap, reg, &val_le16, sizeof(val_le16));453}454 455static int hx9023s_get_prox_state(struct hx9023s_data *data)456{457	return regmap_read(data->regmap, HX9023S_PROX_STATUS, &data->prox_state_reg);458}459 460static int hx9023s_data_select(struct hx9023s_data *data)461{462	int ret;463	unsigned int i, buf;464	unsigned long tmp;465 466	ret = regmap_read(data->regmap, HX9023S_RAW_BL_RD_CFG, &buf);467	if (ret)468		return ret;469 470	tmp = buf;471	for (i = 0; i < 4; i++) {472		data->ch_data[i].sel_diff = test_bit(i, &tmp);473		data->ch_data[i].sel_lp = !data->ch_data[i].sel_diff;474		data->ch_data[i].sel_bl = test_bit(i + 4, &tmp);475		data->ch_data[i].sel_raw = !data->ch_data[i].sel_bl;476	}477 478	ret = regmap_read(data->regmap, HX9023S_INTERRUPT_CFG1, &buf);479	if (ret)480		return ret;481 482	tmp = buf;483	data->ch_data[4].sel_diff = test_bit(2, &tmp);484	data->ch_data[4].sel_lp = !data->ch_data[4].sel_diff;485	data->ch_data[4].sel_bl = test_bit(3, &tmp);486	data->ch_data[4].sel_raw = !data->ch_data[4].sel_bl;487 488	return 0;489}490 491static int hx9023s_sample(struct hx9023s_data *data)492{493	int ret;494	unsigned int i;495	u8 buf[HX9023S_CH_NUM * 3];496	u16 value;497 498	ret = hx9023s_data_lock(data, true);499	if (ret)500		return ret;501 502	ret = hx9023s_data_select(data);503	if (ret)504		goto err;505 506	/* 3 bytes for each of channels 0 to 3 which have contiguous registers */507	ret = regmap_bulk_read(data->regmap, HX9023S_RAW_BL_CH0_0, buf, 12);508	if (ret)509		goto err;510 511	/* 3 bytes for channel 4 */512	ret = regmap_bulk_read(data->regmap, HX9023S_RAW_BL_CH4_0, buf + 12, 3);513	if (ret)514		goto err;515 516	for (i = 0; i < HX9023S_CH_NUM; i++) {517		value = get_unaligned_le16(&buf[i * 3 + 1]);518		data->ch_data[i].raw = 0;519		data->ch_data[i].bl = 0;520		if (data->ch_data[i].sel_raw)521			data->ch_data[i].raw = value;522		if (data->ch_data[i].sel_bl)523			data->ch_data[i].bl = value;524	}525 526	/* 3 bytes for each of channels 0 to 3 which have contiguous registers */527	ret = regmap_bulk_read(data->regmap, HX9023S_LP_DIFF_CH0_0, buf, 12);528	if (ret)529		goto err;530 531	/* 3 bytes for channel 4 */532	ret = regmap_bulk_read(data->regmap, HX9023S_LP_DIFF_CH4_0, buf + 12, 3);533	if (ret)534		goto err;535 536	for (i = 0; i < HX9023S_CH_NUM; i++) {537		value = get_unaligned_le16(&buf[i * 3 + 1]);538		data->ch_data[i].lp = 0;539		data->ch_data[i].diff = 0;540		if (data->ch_data[i].sel_lp)541			data->ch_data[i].lp = value;542		if (data->ch_data[i].sel_diff)543			data->ch_data[i].diff = value;544	}545 546	for (i = 0; i < HX9023S_CH_NUM; i++) {547		if (data->ch_data[i].sel_lp && data->ch_data[i].sel_bl)548			data->ch_data[i].diff = data->ch_data[i].lp - data->ch_data[i].bl;549	}550 551	/* 2 bytes for each of channels 0 to 4 which have contiguous registers */552	ret = regmap_bulk_read(data->regmap, HX9023S_OFFSET_DAC0_7_0, buf, 10);553	if (ret)554		goto err;555 556	for (i = 0; i < HX9023S_CH_NUM; i++) {557		value = get_unaligned_le16(&buf[i * 2]);558		value = FIELD_GET(GENMASK(11, 0), value);559		data->ch_data[i].dac = value;560	}561 562err:563	return hx9023s_data_lock(data, false);564}565 566static int hx9023s_ch_en(struct hx9023s_data *data, u8 ch_id, bool en)567{568	int ret;569	unsigned int buf;570 571	ret = regmap_read(data->regmap, HX9023S_CH_NUM_CFG, &buf);572	if (ret)573		return ret;574 575	data->ch_en_stat = buf;576	if (en && data->ch_en_stat == 0)577		data->prox_state_reg = 0;578 579	data->ch_data[ch_id].enable = en;580	__assign_bit(ch_id, &data->ch_en_stat, en);581 582	return regmap_write(data->regmap, HX9023S_CH_NUM_CFG, data->ch_en_stat);583}584 585static int hx9023s_property_get(struct hx9023s_data *data)586{587	struct device *dev = regmap_get_device(data->regmap);588	u32 array[2];589	u32 i, reg, temp;590	int ret;591 592	data->chan_in_use = 0;593	for (i = 0; i < HX9023S_CH_NUM; i++) {594		data->ch_data[i].channel_positive = HX9023S_NOT_CONNECTED;595		data->ch_data[i].channel_negative = HX9023S_NOT_CONNECTED;596	}597 598	device_for_each_child_node_scoped(dev, child) {599		ret = fwnode_property_read_u32(child, "reg", &reg);600		if (ret || reg >= HX9023S_CH_NUM)601			return dev_err_probe(dev, ret < 0 ? ret : -EINVAL,602					     "Failed to read reg\n");603		__set_bit(reg, &data->chan_in_use);604 605		ret = fwnode_property_read_u32(child, "single-channel", &temp);606		if (ret == 0) {607			data->ch_data[reg].channel_positive = temp;608			data->ch_data[reg].channel_negative = HX9023S_NOT_CONNECTED;609		} else {610			ret = fwnode_property_read_u32_array(child, "diff-channels",611							     array, ARRAY_SIZE(array));612			if (ret == 0) {613				data->ch_data[reg].channel_positive = array[0];614				data->ch_data[reg].channel_negative = array[1];615			} else {616				return dev_err_probe(dev, ret,617						     "Property read failed: %d\n",618						     reg);619			}620		}621	}622 623	return 0;624}625 626static int hx9023s_update_chan_en(struct hx9023s_data *data,627				  unsigned long chan_read,628				  unsigned long chan_event)629{630	unsigned int i;631	unsigned long channels = chan_read | chan_event;632 633	if ((data->chan_read | data->chan_event) != channels) {634		for_each_set_bit(i, &channels, HX9023S_CH_NUM)635			hx9023s_ch_en(data, i, test_bit(i, &data->chan_in_use));636		for_each_clear_bit(i, &channels, HX9023S_CH_NUM)637			hx9023s_ch_en(data, i, false);638	}639 640	data->chan_read = chan_read;641	data->chan_event = chan_event;642 643	return 0;644}645 646static int hx9023s_get_proximity(struct hx9023s_data *data,647				 const struct iio_chan_spec *chan,648				 int *val)649{650	int ret;651 652	ret = hx9023s_sample(data);653	if (ret)654		return ret;655 656	ret = hx9023s_get_prox_state(data);657	if (ret)658		return ret;659 660	*val = data->ch_data[chan->channel].diff;661	return IIO_VAL_INT;662}663 664static int hx9023s_get_samp_freq(struct hx9023s_data *data, int *val, int *val2)665{666	int ret;667	unsigned int odr, index;668 669	ret = regmap_read(data->regmap, HX9023S_PRF_CFG, &index);670	if (ret)671		return ret;672 673	odr = hx9023s_samp_freq_table[index];674	*val = KILO / odr;675	*val2 = div_u64((KILO % odr) * MICRO, odr);676 677	return IIO_VAL_INT_PLUS_MICRO;678}679 680static int hx9023s_read_raw(struct iio_dev *indio_dev,681			    const struct iio_chan_spec *chan,682			    int *val, int *val2, long mask)683{684	struct hx9023s_data *data = iio_priv(indio_dev);685	int ret;686 687	if (chan->type != IIO_PROXIMITY)688		return -EINVAL;689 690	switch (mask) {691	case IIO_CHAN_INFO_RAW:692		ret = iio_device_claim_direct_mode(indio_dev);693		if (ret)694			return ret;695 696		ret = hx9023s_get_proximity(data, chan, val);697		iio_device_release_direct_mode(indio_dev);698		return ret;699	case IIO_CHAN_INFO_SAMP_FREQ:700		return hx9023s_get_samp_freq(data, val, val2);701	default:702		return -EINVAL;703	}704}705 706static int hx9023s_set_samp_freq(struct hx9023s_data *data, int val, int val2)707{708	struct device *dev = regmap_get_device(data->regmap);709	unsigned int i, period_ms;710 711	period_ms = div_u64(NANO, (val * MEGA + val2));712 713	for (i = 0; i < ARRAY_SIZE(hx9023s_samp_freq_table); i++) {714		if (period_ms == hx9023s_samp_freq_table[i])715			break;716	}717	if (i == ARRAY_SIZE(hx9023s_samp_freq_table)) {718		dev_err(dev, "Period:%dms NOT found!\n", period_ms);719		return -EINVAL;720	}721 722	return regmap_write(data->regmap, HX9023S_PRF_CFG, i);723}724 725static int hx9023s_write_raw(struct iio_dev *indio_dev,726			     const struct iio_chan_spec *chan,727			     int val, int val2, long mask)728{729	struct hx9023s_data *data = iio_priv(indio_dev);730 731	if (chan->type != IIO_PROXIMITY)732		return -EINVAL;733 734	if (mask != IIO_CHAN_INFO_SAMP_FREQ)735		return -EINVAL;736 737	return hx9023s_set_samp_freq(data, val, val2);738}739 740static irqreturn_t hx9023s_irq_handler(int irq, void *private)741{742	struct iio_dev *indio_dev = private;743	struct hx9023s_data *data = iio_priv(indio_dev);744 745	if (data->trigger_enabled)746		iio_trigger_poll(data->trig);747 748	return IRQ_WAKE_THREAD;749}750 751static void hx9023s_push_events(struct iio_dev *indio_dev)752{753	struct hx9023s_data *data = iio_priv(indio_dev);754	s64 timestamp = iio_get_time_ns(indio_dev);755	unsigned long prox_changed;756	unsigned int chan;757	int ret;758 759	ret = hx9023s_sample(data);760	if (ret)761		return;762 763	ret = hx9023s_get_prox_state(data);764	if (ret)765		return;766 767	prox_changed = (data->chan_prox_stat ^ data->prox_state_reg) & data->chan_event;768	for_each_set_bit(chan, &prox_changed, HX9023S_CH_NUM) {769		unsigned int dir;770 771		dir = (data->prox_state_reg & BIT(chan)) ?772			IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING;773 774		iio_push_event(indio_dev,775			       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan,776						    IIO_EV_TYPE_THRESH, dir),777			       timestamp);778	}779	data->chan_prox_stat = data->prox_state_reg;780}781 782static irqreturn_t hx9023s_irq_thread_handler(int irq, void *private)783{784	struct iio_dev *indio_dev = private;785	struct hx9023s_data *data = iio_priv(indio_dev);786 787	guard(mutex)(&data->mutex);788	hx9023s_push_events(indio_dev);789 790	return IRQ_HANDLED;791}792 793static int hx9023s_read_event_val(struct iio_dev *indio_dev,794				  const struct iio_chan_spec *chan,795				  enum iio_event_type type,796				  enum iio_event_direction dir,797				  enum iio_event_info info, int *val, int *val2)798{799	struct hx9023s_data *data = iio_priv(indio_dev);800 801	if (chan->type != IIO_PROXIMITY)802		return -EINVAL;803 804	switch (info) {805	case IIO_EV_INFO_VALUE:806		switch (dir) {807		case IIO_EV_DIR_RISING:808			return hx9023s_get_thres_far(data, chan->channel, val);809		case IIO_EV_DIR_FALLING:810			return hx9023s_get_thres_near(data, chan->channel, val);811		default:812			return -EINVAL;813		}814	case IIO_EV_INFO_PERIOD:815		switch (dir) {816		case IIO_EV_DIR_RISING:817			return hx9023s_read_far_debounce(data, val);818		case IIO_EV_DIR_FALLING:819			return hx9023s_read_near_debounce(data, val);820		default:821			return -EINVAL;822		}823	default:824		return -EINVAL;825	}826}827 828static int hx9023s_write_event_val(struct iio_dev *indio_dev,829				   const struct iio_chan_spec *chan,830				   enum iio_event_type type,831				   enum iio_event_direction dir,832				   enum iio_event_info info, int val, int val2)833{834	struct hx9023s_data *data = iio_priv(indio_dev);835 836	if (chan->type != IIO_PROXIMITY)837		return -EINVAL;838 839	switch (info) {840	case IIO_EV_INFO_VALUE:841		switch (dir) {842		case IIO_EV_DIR_RISING:843			return hx9023s_set_thres_far(data, chan->channel, val);844		case IIO_EV_DIR_FALLING:845			return hx9023s_set_thres_near(data, chan->channel, val);846		default:847			return -EINVAL;848		}849	case IIO_EV_INFO_PERIOD:850		switch (dir) {851		case IIO_EV_DIR_RISING:852			return hx9023s_write_far_debounce(data, val);853		case IIO_EV_DIR_FALLING:854			return hx9023s_write_near_debounce(data, val);855		default:856			return -EINVAL;857		}858	default:859		return -EINVAL;860	}861}862 863static int hx9023s_read_event_config(struct iio_dev *indio_dev,864				     const struct iio_chan_spec *chan,865				     enum iio_event_type type,866				     enum iio_event_direction dir)867{868	struct hx9023s_data *data = iio_priv(indio_dev);869 870	return test_bit(chan->channel, &data->chan_event);871}872 873static int hx9023s_write_event_config(struct iio_dev *indio_dev,874				      const struct iio_chan_spec *chan,875				      enum iio_event_type type,876				      enum iio_event_direction dir,877				      int state)878{879	struct hx9023s_data *data = iio_priv(indio_dev);880 881	if (test_bit(chan->channel, &data->chan_in_use)) {882		hx9023s_ch_en(data, chan->channel, !!state);883		__assign_bit(chan->channel, &data->chan_event,884			     data->ch_data[chan->channel].enable);885	}886 887	return 0;888}889 890static const struct iio_info hx9023s_info = {891	.read_raw = hx9023s_read_raw,892	.write_raw = hx9023s_write_raw,893	.read_event_value = hx9023s_read_event_val,894	.write_event_value = hx9023s_write_event_val,895	.read_event_config = hx9023s_read_event_config,896	.write_event_config = hx9023s_write_event_config,897};898 899static int hx9023s_set_trigger_state(struct iio_trigger *trig, bool state)900{901	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);902	struct hx9023s_data *data = iio_priv(indio_dev);903 904	guard(mutex)(&data->mutex);905	if (state)906		hx9023s_interrupt_enable(data);907	else if (!data->chan_read)908		hx9023s_interrupt_disable(data);909	data->trigger_enabled = state;910 911	return 0;912}913 914static const struct iio_trigger_ops hx9023s_trigger_ops = {915	.set_trigger_state = hx9023s_set_trigger_state,916};917 918static irqreturn_t hx9023s_trigger_handler(int irq, void *private)919{920	struct iio_poll_func *pf = private;921	struct iio_dev *indio_dev = pf->indio_dev;922	struct hx9023s_data *data = iio_priv(indio_dev);923	struct device *dev = regmap_get_device(data->regmap);924	unsigned int bit, index, i = 0;925	int ret;926 927	guard(mutex)(&data->mutex);928	ret = hx9023s_sample(data);929	if (ret) {930		dev_warn(dev, "sampling failed\n");931		goto out;932	}933 934	ret = hx9023s_get_prox_state(data);935	if (ret) {936		dev_warn(dev, "get prox failed\n");937		goto out;938	}939 940	iio_for_each_active_channel(indio_dev, bit) {941		index = indio_dev->channels[bit].channel;942		data->buffer.channels[i++] = cpu_to_le16(data->ch_data[index].diff);943	}944 945	iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,946					   pf->timestamp);947 948out:949	iio_trigger_notify_done(indio_dev->trig);950 951	return IRQ_HANDLED;952}953 954static int hx9023s_buffer_preenable(struct iio_dev *indio_dev)955{956	struct hx9023s_data *data = iio_priv(indio_dev);957	unsigned long channels = 0;958	unsigned int bit;959 960	guard(mutex)(&data->mutex);961	iio_for_each_active_channel(indio_dev, bit)962		__set_bit(indio_dev->channels[bit].channel, &channels);963 964	hx9023s_update_chan_en(data, channels, data->chan_event);965 966	return 0;967}968 969static int hx9023s_buffer_postdisable(struct iio_dev *indio_dev)970{971	struct hx9023s_data *data = iio_priv(indio_dev);972 973	guard(mutex)(&data->mutex);974	hx9023s_update_chan_en(data, 0, data->chan_event);975 976	return 0;977}978 979static const struct iio_buffer_setup_ops hx9023s_buffer_setup_ops = {980	.preenable = hx9023s_buffer_preenable,981	.postdisable = hx9023s_buffer_postdisable,982};983 984static int hx9023s_id_check(struct iio_dev *indio_dev)985{986	struct hx9023s_data *data = iio_priv(indio_dev);987	struct device *dev = regmap_get_device(data->regmap);988	unsigned int id;989	int ret;990 991	ret = regmap_read(data->regmap, HX9023S_DEVICE_ID, &id);992	if (ret)993		return ret;994 995	if (id != HX9023S_CHIP_ID)996		dev_warn(dev, "Unexpected chip ID, assuming compatible\n");997 998	return 0;999}1000 1001static int hx9023s_probe(struct i2c_client *client)1002{1003	struct device *dev = &client->dev;1004	struct iio_dev *indio_dev;1005	struct hx9023s_data *data;1006	int ret;1007 1008	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));1009	if (!indio_dev)1010		return -ENOMEM;1011 1012	data = iio_priv(indio_dev);1013	mutex_init(&data->mutex);1014 1015	data->regmap = devm_regmap_init_i2c(client, &hx9023s_regmap_config);1016	if (IS_ERR(data->regmap))1017		return dev_err_probe(dev, PTR_ERR(data->regmap),1018				     "regmap init failed\n");1019 1020	ret = hx9023s_property_get(data);1021	if (ret)1022		return dev_err_probe(dev, ret, "dts phase failed\n");1023 1024	ret = devm_regulator_get_enable(dev, "vdd");1025	if (ret)1026		return dev_err_probe(dev, ret, "regulator get failed\n");1027 1028	ret = hx9023s_id_check(indio_dev);1029	if (ret)1030		return dev_err_probe(dev, ret, "id check failed\n");1031 1032	indio_dev->name = "hx9023s";1033	indio_dev->channels = hx9023s_channels;1034	indio_dev->num_channels = ARRAY_SIZE(hx9023s_channels);1035	indio_dev->info = &hx9023s_info;1036	indio_dev->modes = INDIO_DIRECT_MODE;1037	i2c_set_clientdata(client, indio_dev);1038 1039	ret = regmap_multi_reg_write(data->regmap, hx9023s_reg_init_list,1040				     ARRAY_SIZE(hx9023s_reg_init_list));1041	if (ret)1042		return dev_err_probe(dev, ret, "device init failed\n");1043 1044	ret = hx9023s_ch_cfg(data);1045	if (ret)1046		return dev_err_probe(dev, ret, "channel config failed\n");1047 1048	ret = regcache_sync(data->regmap);1049	if (ret)1050		return dev_err_probe(dev, ret, "regcache sync failed\n");1051 1052	if (client->irq) {1053		ret = devm_request_threaded_irq(dev, client->irq,1054						hx9023s_irq_handler,1055						hx9023s_irq_thread_handler,1056						IRQF_ONESHOT,1057						"hx9023s_event", indio_dev);1058		if (ret)1059			return dev_err_probe(dev, ret, "irq request failed\n");1060 1061		data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",1062						    indio_dev->name,1063						    iio_device_id(indio_dev));1064		if (!data->trig)1065			return dev_err_probe(dev, -ENOMEM,1066					     "iio trigger alloc failed\n");1067 1068		data->trig->ops = &hx9023s_trigger_ops;1069		iio_trigger_set_drvdata(data->trig, indio_dev);1070 1071		ret = devm_iio_trigger_register(dev, data->trig);1072		if (ret)1073			return dev_err_probe(dev, ret,1074					     "iio trigger register failed\n");1075	}1076 1077	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,1078					      iio_pollfunc_store_time,1079					      hx9023s_trigger_handler,1080					      &hx9023s_buffer_setup_ops);1081	if (ret)1082		return dev_err_probe(dev, ret,1083				"iio triggered buffer setup failed\n");1084 1085	return devm_iio_device_register(dev, indio_dev);1086}1087 1088static int hx9023s_suspend(struct device *dev)1089{1090	struct hx9023s_data *data = iio_priv(dev_get_drvdata(dev));1091 1092	guard(mutex)(&data->mutex);1093	hx9023s_interrupt_disable(data);1094 1095	return 0;1096}1097 1098static int hx9023s_resume(struct device *dev)1099{1100	struct hx9023s_data *data = iio_priv(dev_get_drvdata(dev));1101 1102	guard(mutex)(&data->mutex);1103	if (data->trigger_enabled)1104		hx9023s_interrupt_enable(data);1105 1106	return 0;1107}1108 1109static DEFINE_SIMPLE_DEV_PM_OPS(hx9023s_pm_ops, hx9023s_suspend,1110				hx9023s_resume);1111 1112static const struct of_device_id hx9023s_of_match[] = {1113	{ .compatible = "tyhx,hx9023s" },1114	{}1115};1116MODULE_DEVICE_TABLE(of, hx9023s_of_match);1117 1118static const struct i2c_device_id hx9023s_id[] = {1119	{ "hx9023s" },1120	{}1121};1122MODULE_DEVICE_TABLE(i2c, hx9023s_id);1123 1124static struct i2c_driver hx9023s_driver = {1125	.driver = {1126		.name = "hx9023s",1127		.of_match_table = hx9023s_of_match,1128		.pm = &hx9023s_pm_ops,1129 1130		/*1131		 * The I2C operations in hx9023s_reg_init() and hx9023s_ch_cfg()1132		 * are time-consuming. Prefer async so we don't delay boot1133		 * if we're builtin to the kernel.1134		 */1135		.probe_type = PROBE_PREFER_ASYNCHRONOUS,1136	},1137	.probe = hx9023s_probe,1138	.id_table = hx9023s_id,1139};1140module_i2c_driver(hx9023s_driver);1141 1142MODULE_AUTHOR("Yasin Lee <yasin.lee.x@gmail.com>");1143MODULE_DESCRIPTION("Driver for TYHX HX9023S SAR sensor");1144MODULE_LICENSE("GPL");1145