On Fri, Jun 21, 2024 at 10:44 AM Yasin Lee <yasin.lee.x@xxxxxxxxx> wrote: > > A SAR sensor from NanjingTianyihexin Electronics Ltd. > > The device has the following entry points: > > Usual frequency: > - sampling_frequency > > Instant reading of current values for different sensors: > - in_proximity0_raw > - in_proximity1_raw > - in_proximity2_raw > - in_proximity3_raw > - in_proximity4_raw > and associated events in events/ > Hello :) > Signed-off-by: Yasin Lee <yasin.lee.x@xxxxxxxxx> > --- > drivers/iio/proximity/Kconfig | 14 + > drivers/iio/proximity/Makefile | 1 + > drivers/iio/proximity/hx9023s.c | 1150 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 1165 insertions(+) > > diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig > index 2ca3b0bc5eba..0694f625b432 100644 > --- a/drivers/iio/proximity/Kconfig > +++ b/drivers/iio/proximity/Kconfig > @@ -32,6 +32,20 @@ config CROS_EC_MKBP_PROXIMITY > To compile this driver as a module, choose M here: the > module will be called cros_ec_mkbp_proximity. > > +config HX9023S > + tristate "TYHX HX9023S SAR sensor" > + select IIO_BUFFER > + select IIO_TRIGGERED_BUFFER > + select REGMAP_I2C > + depends on I2C > + help > + Say Y here to build a driver for TYHX HX9023S capacitive SAR sensor. > + This driver supports the TYHX HX9023S capacitive > + SAR sensors. This sensors is used for proximity detection applications. > + > + To compile this driver as a module, choose M here: the > + module will be called hx9023s. > + > config IRSD200 > tristate "Murata IRS-D200 PIR sensor" > select IIO_BUFFER > diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile > index f36598380446..ab381cd27dbb 100644 > --- a/drivers/iio/proximity/Makefile > +++ b/drivers/iio/proximity/Makefile > @@ -6,6 +6,7 @@ > # When adding new entries keep the list in alphabetical order > obj-$(CONFIG_AS3935) += as3935.o > obj-$(CONFIG_CROS_EC_MKBP_PROXIMITY) += cros_ec_mkbp_proximity.o > +obj-$(CONFIG_HX9023S) += hx9023s.o > obj-$(CONFIG_IRSD200) += irsd200.o > obj-$(CONFIG_ISL29501) += isl29501.o > obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o > diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c > new file mode 100644 > index 000000000000..1d8cb9a05d8a > --- /dev/null > +++ b/drivers/iio/proximity/hx9023s.c > @@ -0,0 +1,1150 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2024 NanjingTianyihexin Electronics Ltd. > + * http://www.tianyihexin.com > + * > + * Driver for NanjingTianyihexin HX9023S Cap Sensor. > + * Datasheet available at: > + * http://www.tianyihexin.com/ueditor/php/upload/file/20240614/1718336303992081.pdf > + */ > + > +#include <linux/array_size.h> > +#include <linux/bitfield.h> > +#include <linux/bitops.h> > +#include <linux/delay.h> > +#include <linux/device.h> > +#include <linux/errno.h> > +#include <linux/i2c.h> > +#include <linux/interrupt.h> > +#include <linux/irqreturn.h> > +#include <linux/math.h> > +#include <linux/mod_devicetable.h> > +#include <linux/module.h> > +#include <linux/mutex.h> > +#include <linux/pm.h> > +#include <linux/property.h> > +#include <linux/regmap.h> > +#include <linux/regulator/consumer.h> > +#include <linux/types.h> > +#include <linux/units.h> > + > +#include <asm/byteorder.h> > +#include <asm/unaligned.h> > + > +#include <linux/iio/buffer.h> > +#include <linux/iio/events.h> > +#include <linux/iio/iio.h> > +#include <linux/iio/trigger.h> > +#include <linux/iio/triggered_buffer.h> > +#include <linux/iio/trigger_consumer.h> > +#include <linux/iio/types.h> A first question is: are all these headers required? Looks like some of them could be removed. > + > +#define HX9023S_CHIP_ID 0x1D > +#define HX9023S_CH_NUM 5 > +#define HX9023S_2BYTES 2 > +#define HX9023S_3BYTES 3 > +#define HX9023S_BYTES_MAX HX9023S_3BYTES > +#define HX9023S_POS 0x03 > +#define HX9023S_NEG 0x02 > +#define HX9023S_NOT_CONNECTED 16 > + > +#define HX9023S_GLOBAL_CTRL0 0x00 > +#define HX9023S_PRF_CFG 0x02 > +#define HX9023S_CH0_CFG_7_0 0x03 > +#define HX9023S_CH4_CFG_9_8 0x0C > +#define HX9023S_RANGE_7_0 0x0D > +#define HX9023S_RANGE_9_8 0x0E > +#define HX9023S_RANGE_18_16 0x0F > +#define HX9023S_AVG0_NOSR0_CFG 0x10 > +#define HX9023S_NOSR12_CFG 0x11 > +#define HX9023S_NOSR34_CFG 0x12 > +#define HX9023S_AVG12_CFG 0x13 > +#define HX9023S_AVG34_CFG 0x14 > +#define HX9023S_OFFSET_DAC0_7_0 0x15 > +#define HX9023S_OFFSET_DAC4_9_8 0x1E > +#define HX9023S_SAMPLE_NUM_7_0 0x1F > +#define HX9023S_INTEGRATION_NUM_7_0 0x21 > +#define HX9023S_CH_NUM_CFG 0x24 > +#define HX9023S_LP_ALP_4_CFG 0x29 > +#define HX9023S_LP_ALP_1_0_CFG 0x2A > +#define HX9023S_LP_ALP_3_2_CFG 0x2B > +#define HX9023S_UP_ALP_1_0_CFG 0x2C > +#define HX9023S_UP_ALP_3_2_CFG 0x2D > +#define HX9023S_DN_UP_ALP_0_4_CFG 0x2E > +#define HX9023S_DN_ALP_2_1_CFG 0x2F > +#define HX9023S_DN_ALP_4_3_CFG 0x30 > +#define HX9023S_RAW_BL_RD_CFG 0x38 > +#define HX9023S_INTERRUPT_CFG 0x39 > +#define HX9023S_INTERRUPT_CFG1 0x3A > +#define HX9023S_CALI_DIFF_CFG 0x3B > +#define HX9023S_DITHER_CFG 0x3C > +#define HX9023S_DEVICE_ID 0x60 > +#define HX9023S_PROX_STATUS 0x6B > +#define HX9023S_PROX_INT_HIGH_CFG 0x6C > +#define HX9023S_PROX_INT_LOW_CFG 0x6D > +#define HX9023S_PROX_HIGH_DIFF_CFG_CH0_0 0x80 > +#define HX9023S_PROX_LOW_DIFF_CFG_CH0_0 0x88 > +#define HX9023S_PROX_LOW_DIFF_CFG_CH3_1 0x8F > +#define HX9023S_PROX_HIGH_DIFF_CFG_CH4_0 0x9E > +#define HX9023S_PROX_HIGH_DIFF_CFG_CH4_1 0x9F > +#define HX9023S_PROX_LOW_DIFF_CFG_CH4_0 0xA2 > +#define HX9023S_PROX_LOW_DIFF_CFG_CH4_1 0xA3 > +#define HX9023S_CAP_INI_CH4_0 0xB3 > +#define HX9023S_LP_DIFF_CH4_2 0xBA > +#define HX9023S_RAW_BL_CH4_0 0xB5 > +#define HX9023S_LP_DIFF_CH4_0 0xB8 > +#define HX9023S_DSP_CONFIG_CTRL1 0xC8 > +#define HX9023S_CAP_INI_CH0_0 0xE0 > +#define HX9023S_RAW_BL_CH0_0 0xE8 > +#define HX9023S_LP_DIFF_CH0_0 0xF4 > +#define HX9023S_LP_DIFF_CH3_2 0xFF > + > +#define HX9023S_DATA_LOCK_MASK BIT(4) > +#define HX9023S_INTERRUPT_MASK GENMASK(9, 0) > +#define HX9023S_PROX_DEBOUNCE_MASK GENMASK(3, 0) > + > +struct hx9023s_addr_val_pair { > + u8 addr; > + u8 val; > +}; This looks like: struct reg_sequence { unsigned int reg; unsigned int def; unsigned int delay_us; }; This is defined in include/linux/regmap.h > + > +struct hx9023s_ch_data { > + int raw; /* Raw Data*/ > + int lp; /* Low Pass Filter Data*/ > + int bl; /* Base Line Data */ > + int diff; /* difference of Low Pass Data and Base Line Data */ > + > + struct { > + unsigned int near; > + unsigned int far; > + } thres; > + > + u16 dac; > + u8 channel_positive; > + u8 channel_negative; > + bool sel_bl; > + bool sel_raw; > + bool sel_diff; > + bool sel_lp; > + bool enable; > +}; > + > +struct hx9023s_data { > + struct iio_trigger *trig; > + struct regmap *regmap; > + unsigned long chan_prox_stat; > + unsigned long chan_read; > + unsigned long chan_event; > + unsigned long ch_en_stat; > + unsigned long chan_in_use; > + unsigned int prox_state_reg; > + bool trigger_enabled; > + > + struct { > + __le16 channels[HX9023S_CH_NUM]; > + s64 ts __aligned(8); > + } buffer; > + > + struct mutex mutex; > + struct hx9023s_ch_data ch_data[HX9023S_CH_NUM]; > +}; > + > +static struct hx9023s_addr_val_pair hx9023s_reg_init_list[] = { Globals like this should be `static const` Also, it would be a good idea to define this as `static const struct reg_sequence ` Then the `regmap_multi_reg_write()` function could be used. > + /* scan period */ > + { HX9023S_PRF_CFG, 0x17 }, > + > + /* full scale of conversion phase of each channel */ > + { HX9023S_RANGE_7_0, 0x11 }, > + { HX9023S_RANGE_9_8, 0x02 }, > + { HX9023S_RANGE_18_16, 0x00 }, > + > + /* ADC average number and OSR number of each channel */ > + { HX9023S_AVG0_NOSR0_CFG, 0x71 }, > + { HX9023S_NOSR12_CFG, 0x44 }, > + { HX9023S_NOSR34_CFG, 0x00 }, > + { HX9023S_AVG12_CFG, 0x33 }, > + { HX9023S_AVG34_CFG, 0x00 }, > + > + /* sample & integration frequency of the ADC */ > + { HX9023S_SAMPLE_NUM_7_0, 0x65 }, > + { HX9023S_INTEGRATION_NUM_7_0, 0x65 }, > + > + /* coefficient of the first order low pass filter during each channel */ > + { HX9023S_LP_ALP_1_0_CFG, 0x22 }, > + { HX9023S_LP_ALP_3_2_CFG, 0x22 }, > + { HX9023S_LP_ALP_4_CFG, 0x02 }, > + > + /* up coefficient of the first order low pass filter during each channel */ > + { HX9023S_UP_ALP_1_0_CFG, 0x88 }, > + { HX9023S_UP_ALP_3_2_CFG, 0x88 }, > + { HX9023S_DN_UP_ALP_0_4_CFG, 0x18 }, > + > + /* down coefficient of the first order low pass filter during each channel */ > + { HX9023S_DN_ALP_2_1_CFG, 0x11 }, > + { HX9023S_DN_ALP_4_3_CFG, 0x11 }, > + > + /* selection of data for the Data Mux Register to output data */ > + { HX9023S_RAW_BL_RD_CFG, 0xF0 }, > + > + /* enable the interrupt function */ > + { HX9023S_INTERRUPT_CFG, 0xFF }, > + { HX9023S_INTERRUPT_CFG1, 0x3B }, > + { HX9023S_DITHER_CFG, 0x21 }, > + > + /* threshold of the offset compensation */ > + { HX9023S_CALI_DIFF_CFG, 0x07 }, > + > + /* proximity persistency number(near & far) */ > + { HX9023S_PROX_INT_HIGH_CFG, 0x01 }, > + { HX9023S_PROX_INT_LOW_CFG, 0x01 }, > + > + /* disable the data lock */ > + { HX9023S_DSP_CONFIG_CTRL1, 0x00 }, > +}; > + > +static const struct iio_event_spec hx9023s_events[] = { > + { > + .type = IIO_EV_TYPE_THRESH, > + .dir = IIO_EV_DIR_RISING, > + .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD), > + .mask_separate = BIT(IIO_EV_INFO_VALUE), > + }, > + { > + .type = IIO_EV_TYPE_THRESH, > + .dir = IIO_EV_DIR_FALLING, > + .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD), > + .mask_separate = BIT(IIO_EV_INFO_VALUE), > + > + }, > + { > + .type = IIO_EV_TYPE_THRESH, > + .dir = IIO_EV_DIR_EITHER, > + .mask_separate = BIT(IIO_EV_INFO_ENABLE), > + }, > +}; > + > +#define HX9023S_CHANNEL(idx) \ > +{ \ > + .type = IIO_PROXIMITY, \ > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ > + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ > + .indexed = 1, \ > + .channel = idx, \ > + .address = 0, \ > + .event_spec = hx9023s_events, \ > + .num_event_specs = ARRAY_SIZE(hx9023s_events), \ > + .scan_index = idx, \ > + .scan_type = { \ > + .sign = 's', \ > + .realbits = 16, \ > + .storagebits = 16, \ > + .endianness = IIO_BE, \ > + }, \ > +} > + > +static const struct iio_chan_spec hx9023s_channels[] = { > + HX9023S_CHANNEL(0), > + HX9023S_CHANNEL(1), > + HX9023S_CHANNEL(2), > + HX9023S_CHANNEL(3), > + HX9023S_CHANNEL(4), > + IIO_CHAN_SOFT_TIMESTAMP(5), > +}; > + > +static const unsigned int hx9023s_samp_freq_table[] = { > + 2, 2, 4, 6, 8, 10, 14, 18, 22, 26, > + 30, 34, 38, 42, 46, 50, 56, 62, 68, 74, > + 80, 90, 100, 200, 300, 400, 600, 800, 1000, 2000, > + 3000, 4000, > +}; > + > +static const struct regmap_range hx9023s_rd_reg_ranges[] = { > + regmap_reg_range(HX9023S_GLOBAL_CTRL0, HX9023S_LP_DIFF_CH3_2), > +}; > + > +static const struct regmap_range hx9023s_wr_reg_ranges[] = { > + regmap_reg_range(HX9023S_GLOBAL_CTRL0, HX9023S_LP_DIFF_CH3_2), > +}; > + > +static const struct regmap_range hx9023s_volatile_reg_ranges[] = { > + regmap_reg_range(HX9023S_CAP_INI_CH4_0, HX9023S_LP_DIFF_CH4_2), > + regmap_reg_range(HX9023S_CAP_INI_CH0_0, HX9023S_LP_DIFF_CH3_2), > + regmap_reg_range(HX9023S_PROX_STATUS, HX9023S_PROX_STATUS), > +}; > + > +static const struct regmap_access_table hx9023s_rd_regs = { > + .yes_ranges = hx9023s_rd_reg_ranges, > + .n_yes_ranges = ARRAY_SIZE(hx9023s_rd_reg_ranges), > +}; > + > +static const struct regmap_access_table hx9023s_wr_regs = { > + .yes_ranges = hx9023s_wr_reg_ranges, > + .n_yes_ranges = ARRAY_SIZE(hx9023s_wr_reg_ranges), > +}; > + > +static const struct regmap_access_table hx9023s_volatile_regs = { > + .yes_ranges = hx9023s_volatile_reg_ranges, > + .n_yes_ranges = ARRAY_SIZE(hx9023s_volatile_reg_ranges), > +}; > + > +static const struct regmap_config hx9023s_regmap_config = { > + .reg_bits = 8, > + .val_bits = 8, > + .cache_type = REGCACHE_MAPLE, > + .rd_table = &hx9023s_rd_regs, > + .wr_table = &hx9023s_wr_regs, > + .volatile_table = &hx9023s_volatile_regs, > +}; > + > +static int hx9023s_interrupt_enable(struct hx9023s_data *data) > +{ > + return regmap_update_bits(data->regmap, HX9023S_INTERRUPT_CFG, > + HX9023S_INTERRUPT_MASK, HX9023S_INTERRUPT_MASK); > +} > + > +static int hx9023s_interrupt_disable(struct hx9023s_data *data) > +{ > + return regmap_update_bits(data->regmap, HX9023S_INTERRUPT_CFG, > + HX9023S_INTERRUPT_MASK, 0x00); > +} > + > +static int hx9023s_data_lock(struct hx9023s_data *data, bool locked) > +{ > + if (locked) > + return regmap_update_bits(data->regmap, HX9023S_DSP_CONFIG_CTRL1, > + HX9023S_DATA_LOCK_MASK, HX9023S_DATA_LOCK_MASK); > + else > + return regmap_update_bits(data->regmap, HX9023S_DSP_CONFIG_CTRL1, > + HX9023S_DATA_LOCK_MASK, 0); > +} > + > +static int hx9023s_ch_cfg(struct hx9023s_data *data) > +{ > + unsigned int i; > + u16 reg; > + u8 reg_list[HX9023S_CH_NUM * 2]; > + u8 ch_pos[HX9023S_CH_NUM]; > + u8 ch_neg[HX9023S_CH_NUM]; > + /* Bit positions corresponding to input pin connections */ > + u8 conn_cs[HX9023S_CH_NUM] = {0, 2, 4, 6, 8}; > + > + for (i = 0; i < HX9023S_CH_NUM; i++) { See comment [1] > + ch_pos[i] = data->ch_data[i].channel_positive == HX9023S_NOT_CONNECTED ? > + HX9023S_NOT_CONNECTED : conn_cs[data->ch_data[i].channel_positive]; > + ch_neg[i] = data->ch_data[i].channel_negative == HX9023S_NOT_CONNECTED ? > + HX9023S_NOT_CONNECTED : conn_cs[data->ch_data[i].channel_negative]; > + > + reg = (HX9023S_POS << ch_pos[i]) | (HX9023S_NEG << ch_neg[i]); > + put_unaligned_le16(reg, ®_list[i * 2]); > + } > + > + return regmap_bulk_write(data->regmap, HX9023S_CH0_CFG_7_0, reg_list, HX9023S_CH_NUM * 2); > +} > + > +static int hx9023s_reg_init(struct hx9023s_data *data) > +{ > + unsigned int i = 0; > + int ret; > + > + for (i = 0; i < (int)ARRAY_SIZE(hx9023s_reg_init_list); i++) { > + ret = regmap_write(data->regmap, hx9023s_reg_init_list[i].addr, > + hx9023s_reg_init_list[i].val); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int hx9023s_write_far_debounce(struct hx9023s_data *data, int val) > +{ > + guard(mutex)(&data->mutex); > + return regmap_update_bits(data->regmap, HX9023S_PROX_INT_LOW_CFG, > + HX9023S_PROX_DEBOUNCE_MASK, > + FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, val)); > +} > + > +static int hx9023s_write_near_debounce(struct hx9023s_data *data, int val) > +{ > + guard(mutex)(&data->mutex); > + return regmap_update_bits(data->regmap, HX9023S_PROX_INT_HIGH_CFG, > + HX9023S_PROX_DEBOUNCE_MASK, > + FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, val)); > +} > + > +static int hx9023s_read_far_debounce(struct hx9023s_data *data, int *val) > +{ > + int ret; > + > + ret = regmap_read(data->regmap, HX9023S_PROX_INT_LOW_CFG, val); > + if (ret) > + return ret; > + > + *val = FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, *val); > + > + return IIO_VAL_INT; > +} > + > +static int hx9023s_read_near_debounce(struct hx9023s_data *data, int *val) > +{ > + int ret; > + > + ret = regmap_read(data->regmap, HX9023S_PROX_INT_HIGH_CFG, val); > + if (ret) > + return ret; > + > + *val = FIELD_GET(HX9023S_PROX_DEBOUNCE_MASK, *val); > + > + return IIO_VAL_INT; > +} > + > +static int hx9023s_get_thres_near(struct hx9023s_data *data, u8 ch, int *val) > +{ > + int ret; > + u8 buf[2]; > + unsigned int reg, tmp; > + > + reg = (ch == 4) ? HX9023S_PROX_HIGH_DIFF_CFG_CH4_0 : > + HX9023S_PROX_HIGH_DIFF_CFG_CH0_0 + (ch * HX9023S_2BYTES); > + > + ret = regmap_bulk_read(data->regmap, reg, buf, sizeof(buf)); > + if (ret) > + return ret; > + > + tmp = (get_unaligned_le16(buf) & GENMASK(9, 0)) * 32; > + data->ch_data[ch].thres.near = tmp; > + *val = tmp; > + > + return IIO_VAL_INT; > +} > + > +static int hx9023s_get_thres_far(struct hx9023s_data *data, u8 ch, int *val) > +{ > + int ret; > + u8 buf[2]; > + unsigned int reg, tmp; > + > + reg = (ch == 4) ? HX9023S_PROX_LOW_DIFF_CFG_CH4_0 : > + HX9023S_PROX_LOW_DIFF_CFG_CH0_0 + (ch * HX9023S_2BYTES); > + > + ret = regmap_bulk_read(data->regmap, reg, buf, sizeof(buf)); > + if (ret) > + return ret; > + > + tmp = (get_unaligned_le16(buf) & GENMASK(9, 0)) * 32; > + data->ch_data[ch].thres.far = tmp; > + *val = tmp; > + > + return IIO_VAL_INT; > +} > + > +static int hx9023s_set_thres_near(struct hx9023s_data *data, u8 ch, int val) > +{ > + __le16 val_le16 = cpu_to_le16((val / 32) & GENMASK(9, 0)); > + unsigned int reg; > + > + data->ch_data[ch].thres.near = ((val / 32) & GENMASK(9, 0)) * 32; > + reg = (ch == 4) ? HX9023S_PROX_HIGH_DIFF_CFG_CH4_0 : > + HX9023S_PROX_HIGH_DIFF_CFG_CH0_0 + (ch * HX9023S_2BYTES); > + > + return regmap_bulk_write(data->regmap, reg, &val_le16, sizeof(val_le16)); > +} > + > +static int hx9023s_set_thres_far(struct hx9023s_data *data, u8 ch, int val) > +{ > + __le16 val_le16 = cpu_to_le16((val / 32) & GENMASK(9, 0)); > + unsigned int reg; > + > + data->ch_data[ch].thres.far = ((val / 32) & GENMASK(9, 0)) * 32; > + reg = (ch == 4) ? HX9023S_PROX_LOW_DIFF_CFG_CH4_0 : > + HX9023S_PROX_LOW_DIFF_CFG_CH0_0 + (ch * HX9023S_2BYTES); > + > + return regmap_bulk_write(data->regmap, reg, &val_le16, sizeof(val_le16)); > +} > + > +static int hx9023s_get_prox_state(struct hx9023s_data *data) > +{ > + return regmap_read(data->regmap, HX9023S_PROX_STATUS, &data->prox_state_reg); > +} > + > +static int hx9023s_data_select(struct hx9023s_data *data) > +{ > + int ret; > + unsigned int i, buf; > + unsigned long tmp; > + > + ret = regmap_read(data->regmap, HX9023S_RAW_BL_RD_CFG, &buf); > + if (ret) > + return ret; > + > + tmp = buf; > + for (i = 0; i < 4; i++) { > + data->ch_data[i].sel_diff = test_bit(i, &tmp); > + data->ch_data[i].sel_lp = !data->ch_data[i].sel_diff; > + data->ch_data[i].sel_bl = test_bit(i + 4, &tmp); > + data->ch_data[i].sel_raw = !data->ch_data[i].sel_bl; > + } > + > + ret = regmap_read(data->regmap, HX9023S_INTERRUPT_CFG1, &buf); > + if (ret) > + return ret; > + > + tmp = buf; > + data->ch_data[4].sel_diff = test_bit(2, &tmp); > + data->ch_data[4].sel_lp = !data->ch_data[4].sel_diff; > + data->ch_data[4].sel_bl = test_bit(3, &tmp); > + data->ch_data[4].sel_raw = !data->ch_data[4].sel_bl; > + > + return 0; > +} > + > +static int hx9023s_sample(struct hx9023s_data *data) > +{ > + int ret, value; > + unsigned int i; > + u8 data_size, offset_data_size, *p, size, rx_buf[HX9023S_CH_NUM * HX9023S_BYTES_MAX]; > + > + ret = hx9023s_data_lock(data, true); > + if (ret) > + return ret; > + > + ret = hx9023s_data_select(data); > + if (ret) > + return ret;