brintos

brintos / linux-shallow public Read only

0
0
Text · 22.4 KiB · 707ba0a Raw
847 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * AWINIC aw96103 proximity sensor driver4 *5 * Author: Wang Shuaijie <wangshuaijie@awinic.com>6 *7 * Copyright (c) 2024 awinic Technology CO., LTD8 */9#include <linux/bits.h>10#include <linux/bitfield.h>11#include <linux/delay.h>12#include <linux/firmware.h>13#include <linux/i2c.h>14#include <linux/interrupt.h>15#include <linux/iio/events.h>16#include <linux/iio/iio.h>17#include <linux/regulator/consumer.h>18#include <linux/regmap.h>19#include <linux/slab.h>20#include <linux/unaligned.h>21 22#define AW_DATA_PROCESS_FACTOR			102423#define AW96103_CHIP_ID				0xa96124#define AW96103_BIN_VALID_DATA_OFFSET		6425#define AW96103_BIN_DATA_LEN_OFFSET		1626#define AW96103_BIN_DATA_REG_NUM_SIZE		427#define AW96103_BIN_CHIP_TYPE_SIZE		828#define AW96103_BIN_CHIP_TYPE_OFFSET		2429 30#define AW96103_REG_SCANCTRL0			0x000031#define AW96103_REG_STAT0			0x009032#define AW96103_REG_BLFILT_CH0			0x00A833#define AW96103_REG_BLRSTRNG_CH0		0x00B434#define AW96103_REG_DIFF_CH0			0x024035#define AW96103_REG_FWVER2			0x041036#define AW96103_REG_CMD				0xF00837#define AW96103_REG_IRQSRC			0xF08038#define AW96103_REG_IRQEN			0xF08439#define AW96103_REG_RESET			0xFF0C40#define AW96103_REG_CHIPID			0xFF1041#define AW96103_REG_EEDA0			0x040842#define AW96103_REG_EEDA1			0x040C43#define AW96103_REG_PROXCTRL_CH0		0x00B044#define AW96103_REG_PROXTH0_CH0			0x00B845#define AW96103_PROXTH_CH_STEP			0x3C46#define AW96103_THHYST_MASK			GENMASK(13, 12)47#define AW96103_INDEB_MASK			GENMASK(11, 10)48#define AW96103_OUTDEB_MASK			GENMASK(9, 8)49#define AW96103_INITOVERIRQ_MASK		BIT(0)50#define AW96103_BLFILT_CH_STEP			0x3C51#define AW96103_BLRSTRNG_MASK			GENMASK(5, 0)52#define AW96103_CHIPID_MASK			GENMASK(31, 16)53#define AW96103_BLERRTRIG_MASK			BIT(25)54#define AW96103_CHAN_EN_MASK			GENMASK(5, 0)55#define AW96103_REG_PROXCTRL_CH(x)		\56		(AW96103_REG_PROXCTRL_CH0 + (x) * AW96103_PROXTH_CH_STEP)57 58#define AW96103_REG_PROXTH0_CH(x)		\59		(AW96103_REG_PROXTH0_CH0 + (x) * AW96103_PROXTH_CH_STEP)60 61/**62 * struct aw_bin - Store the data obtained from parsing the configuration file.63 * @chip_type: Frame header information-chip type64 * @valid_data_len: Length of valid data obtained after parsing65 * @valid_data_addr: The offset address of the valid data obtained66 *		     after parsing relative to info67 * @len: The size of the bin file obtained from the firmware68 * @data: Store the bin file obtained from the firmware69 */70struct aw_bin {71	unsigned char chip_type[8];72	unsigned int valid_data_len;73	unsigned int valid_data_addr;74	unsigned int len;75	unsigned char data[] __counted_by(len);76};77 78enum aw96103_sar_vers {79	AW96103 = 2,80	AW96103A = 6,81	AW96103B = 0xa,82};83 84enum aw96103_operation_mode {85	AW96103_ACTIVE_MODE = 1,86	AW96103_SLEEP_MODE = 2,87	AW96103_DEEPSLEEP_MODE = 3,88	AW96103B_DEEPSLEEP_MODE = 4,89};90 91enum aw96103_sensor_type {92	AW96103_VAL,93	AW96105_VAL,94};95 96struct aw_channels_info {97	bool used;98	unsigned int old_irq_status;99};100 101struct aw_chip_info {102	const char *name;103	struct iio_chan_spec const *channels;104	int num_channels;105};106 107struct aw96103 {108	unsigned int hostirqen;109	struct regmap *regmap;110	struct device *dev;111	/*112	 * There is one more logical channel than the actual channels,113	 * and the extra logical channel is used for temperature detection114	 * but not for status detection. The specific channel used for115	 * temperature detection is determined by the register configuration.116	 */117	struct aw_channels_info channels_arr[6];118	unsigned int max_channels;119	unsigned int chan_en;120};121 122static const unsigned int aw96103_reg_default[] = {123	0x0000, 0x00003f3f, 0x0004, 0x00000064, 0x0008, 0x0017c11e,124	0x000c, 0x05000000, 0x0010, 0x00093ffd, 0x0014, 0x19240009,125	0x0018, 0xd81c0207, 0x001c, 0xff000000, 0x0020, 0x00241900,126	0x0024, 0x00093ff7, 0x0028, 0x58020009, 0x002c, 0xd81c0207,127	0x0030, 0xff000000, 0x0034, 0x00025800, 0x0038, 0x00093fdf,128	0x003c, 0x7d3b0009, 0x0040, 0xd81c0207,	0x0044, 0xff000000,129	0x0048, 0x003b7d00, 0x004c, 0x00093f7f, 0x0050, 0xe9310009,130	0x0054, 0xd81c0207, 0x0058, 0xff000000,	0x005c, 0x0031e900,131	0x0060, 0x00093dff, 0x0064, 0x1a0c0009,	0x0068, 0xd81c0207,132	0x006c, 0xff000000, 0x0070, 0x000c1a00,	0x0074, 0x80093fff,133	0x0078, 0x043d0009, 0x007c, 0xd81c0207,	0x0080, 0xff000000,134	0x0084, 0x003d0400, 0x00a0, 0xe6400000,	0x00a4, 0x00000000,135	0x00a8, 0x010408d2, 0x00ac, 0x00000000,	0x00b0, 0x00000000,136	0x00b8, 0x00005fff, 0x00bc, 0x00000000,	0x00c0, 0x00000000,137	0x00c4, 0x00000000, 0x00c8, 0x00000000,	0x00cc, 0x00000000,138	0x00d0, 0x00000000, 0x00d4, 0x00000000, 0x00d8, 0x00000000,139	0x00dc, 0xe6447800, 0x00e0, 0x78000000,	0x00e4, 0x010408d2,140	0x00e8, 0x00000000, 0x00ec, 0x00000000,	0x00f4, 0x00005fff,141	0x00f8, 0x00000000, 0x00fc, 0x00000000,	0x0100, 0x00000000,142	0x0104, 0x00000000, 0x0108, 0x00000000,	0x010c, 0x02000000,143	0x0110, 0x00000000, 0x0114, 0x00000000,	0x0118, 0xe6447800,144	0x011c, 0x78000000, 0x0120, 0x010408d2,	0x0124, 0x00000000,145	0x0128, 0x00000000, 0x0130, 0x00005fff,	0x0134, 0x00000000,146	0x0138, 0x00000000, 0x013c, 0x00000000,	0x0140, 0x00000000,147	0x0144, 0x00000000, 0x0148, 0x02000000,	0x014c, 0x00000000,148	0x0150, 0x00000000, 0x0154, 0xe6447800,	0x0158, 0x78000000,149	0x015c, 0x010408d2, 0x0160, 0x00000000,	0x0164, 0x00000000,150	0x016c, 0x00005fff, 0x0170, 0x00000000,	0x0174, 0x00000000,151	0x0178, 0x00000000, 0x017c, 0x00000000,	0x0180, 0x00000000,152	0x0184, 0x02000000, 0x0188, 0x00000000,	0x018c, 0x00000000,153	0x0190, 0xe6447800, 0x0194, 0x78000000,	0x0198, 0x010408d2,154	0x019c, 0x00000000, 0x01a0, 0x00000000,	0x01a8, 0x00005fff,155	0x01ac, 0x00000000, 0x01b0, 0x00000000,	0x01b4, 0x00000000,156	0x01b8, 0x00000000, 0x01bc, 0x00000000,	0x01c0, 0x02000000,157	0x01c4, 0x00000000, 0x01c8, 0x00000000,	0x01cc, 0xe6407800,158	0x01d0, 0x78000000, 0x01d4, 0x010408d2,	0x01d8, 0x00000000,159	0x01dc, 0x00000000, 0x01e4, 0x00005fff,	0x01e8, 0x00000000,160	0x01ec, 0x00000000, 0x01f0, 0x00000000,	0x01f4, 0x00000000,161	0x01f8, 0x00000000, 0x01fc, 0x02000000,	0x0200, 0x00000000,162	0x0204, 0x00000000, 0x0208, 0x00000008,	0x020c, 0x0000000d,163	0x41fc, 0x00000000, 0x4400, 0x00000000,	0x4410, 0x00000000,164	0x4420, 0x00000000, 0x4430, 0x00000000,	0x4440, 0x00000000,165	0x4450, 0x00000000, 0x4460, 0x00000000,	0x4470, 0x00000000,166	0xf080, 0x00003018, 0xf084, 0x00000fff,	0xf800, 0x00000000,167	0xf804, 0x00002e00, 0xf8d0, 0x00000001,	0xf8d4, 0x00000000,168	0xff00, 0x00000301, 0xff0c, 0x01000000,	0xffe0, 0x00000000,169	0xfff4, 0x00004011, 0x0090, 0x00000000,	0x0094, 0x00000000,170	0x0098, 0x00000000, 0x009c, 0x3f3f3f3f,171};172 173static const struct iio_event_spec aw_common_events[3] = {174	{175		.type = IIO_EV_TYPE_THRESH,176		.dir = IIO_EV_DIR_RISING,177		.mask_separate = BIT(IIO_EV_INFO_PERIOD),178	},179	{180		.type = IIO_EV_TYPE_THRESH,181		.dir = IIO_EV_DIR_FALLING,182		.mask_separate = BIT(IIO_EV_INFO_PERIOD),183	},184	{185		.type = IIO_EV_TYPE_THRESH,186		.dir = IIO_EV_DIR_EITHER,187		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |188			BIT(IIO_EV_INFO_HYSTERESIS) |189			BIT(IIO_EV_INFO_VALUE),190	}191};192 193#define AW_IIO_CHANNEL(idx)			\194{								\195	.type = IIO_PROXIMITY,				\196	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\197	.indexed = 1,			\198	.channel = idx,			\199	.event_spec = aw_common_events,		\200	.num_event_specs = ARRAY_SIZE(aw_common_events),	\201}							\202 203static const struct iio_chan_spec aw96103_channels[] = {204	AW_IIO_CHANNEL(0),205	AW_IIO_CHANNEL(1),206	AW_IIO_CHANNEL(2),207	AW_IIO_CHANNEL(3),208};209 210static const struct iio_chan_spec aw96105_channels[] = {211	AW_IIO_CHANNEL(0),212	AW_IIO_CHANNEL(1),213	AW_IIO_CHANNEL(2),214	AW_IIO_CHANNEL(3),215	AW_IIO_CHANNEL(4),216	AW_IIO_CHANNEL(5),217};218 219static const struct aw_chip_info aw_chip_info_tbl[] = {220	[AW96103_VAL] = {221		.name = "aw96103_sensor",222		.channels = aw96103_channels,223		.num_channels = ARRAY_SIZE(aw96103_channels),224	},225	[AW96105_VAL] = {226		.name = "aw96105_sensor",227		.channels = aw96105_channels,228		.num_channels = ARRAY_SIZE(aw96105_channels),229	},230};231 232static void aw96103_parsing_bin_file(struct aw_bin *bin)233{234	bin->valid_data_addr = AW96103_BIN_VALID_DATA_OFFSET;235	bin->valid_data_len =236		*(unsigned int *)(bin->data + AW96103_BIN_DATA_LEN_OFFSET) -237		AW96103_BIN_DATA_REG_NUM_SIZE;238	memcpy(bin->chip_type, bin->data + AW96103_BIN_CHIP_TYPE_OFFSET,239	       AW96103_BIN_CHIP_TYPE_SIZE);240}241 242static const struct regmap_config aw96103_regmap_confg = {243	.reg_bits = 16,244	.val_bits = 32,245};246 247static int aw96103_get_diff_raw(struct aw96103 *aw96103, unsigned int chan,248				int *buf)249{250	u32 data;251	int ret;252 253	ret = regmap_read(aw96103->regmap,254			  AW96103_REG_DIFF_CH0 + chan * 4, &data);255	if (ret)256		return ret;257	*buf = (int)(data / AW_DATA_PROCESS_FACTOR);258 259	return 0;260}261 262static int aw96103_read_raw(struct iio_dev *indio_dev,263			    const struct iio_chan_spec *chan,264			    int *val, int *val2, long mask)265{266	struct aw96103 *aw96103 = iio_priv(indio_dev);267	int ret;268 269	switch (mask) {270	case IIO_CHAN_INFO_RAW:271		ret = aw96103_get_diff_raw(aw96103, chan->channel, val);272		if (ret)273			return ret;274 275		return IIO_VAL_INT;276	default:277		return -EINVAL;278	}279}280 281static int aw96103_read_thresh(struct aw96103 *aw96103,282			       const struct iio_chan_spec *chan, int *val)283{284	int ret;285 286	ret = regmap_read(aw96103->regmap,287			  AW96103_REG_PROXTH0_CH(chan->channel), val);288	if (ret)289		return ret;290 291	return IIO_VAL_INT;292}293 294static int aw96103_read_out_debounce(struct aw96103 *aw96103,295				     const struct iio_chan_spec *chan,296				     int *val)297{298	unsigned int reg_val;299	int ret;300 301	ret = regmap_read(aw96103->regmap,302			  AW96103_REG_PROXCTRL_CH(chan->channel), &reg_val);303	if (ret)304		return ret;305	*val = FIELD_GET(AW96103_OUTDEB_MASK, reg_val);306 307	return IIO_VAL_INT;308}309 310static int aw96103_read_in_debounce(struct aw96103 *aw96103,311				    const struct iio_chan_spec *chan, int *val)312{313	unsigned int reg_val;314	int ret;315 316	ret = regmap_read(aw96103->regmap,317			  AW96103_REG_PROXCTRL_CH(chan->channel), &reg_val);318	if (ret)319		return ret;320	*val = FIELD_GET(AW96103_INDEB_MASK, reg_val);321 322	return IIO_VAL_INT;323}324 325static int aw96103_read_hysteresis(struct aw96103 *aw96103,326				   const struct iio_chan_spec *chan, int *val)327{328	unsigned int reg_val;329	int ret;330 331	ret = regmap_read(aw96103->regmap,332			  AW96103_REG_PROXCTRL_CH(chan->channel), &reg_val);333	if (ret)334		return ret;335	*val = FIELD_GET(AW96103_THHYST_MASK, reg_val);336 337	return IIO_VAL_INT;338}339 340static int aw96103_read_event_val(struct iio_dev *indio_dev,341				  const struct iio_chan_spec *chan,342				  enum iio_event_type type,343				  enum iio_event_direction dir,344				  enum iio_event_info info,345				  int *val, int *val2)346{347	struct aw96103 *aw96103 = iio_priv(indio_dev);348 349	if (chan->type != IIO_PROXIMITY)350		return -EINVAL;351 352	switch (info) {353	case IIO_EV_INFO_VALUE:354		return aw96103_read_thresh(aw96103, chan, val);355	case IIO_EV_INFO_PERIOD:356		switch (dir) {357		case IIO_EV_DIR_RISING:358			return aw96103_read_out_debounce(aw96103, chan, val);359		case IIO_EV_DIR_FALLING:360			return aw96103_read_in_debounce(aw96103, chan, val);361		default:362			return -EINVAL;363		}364	case IIO_EV_INFO_HYSTERESIS:365		return aw96103_read_hysteresis(aw96103, chan, val);366	default:367		return -EINVAL;368	}369}370 371static int aw96103_write_event_val(struct iio_dev *indio_dev,372				   const struct iio_chan_spec *chan,373				   enum iio_event_type type,374				   enum iio_event_direction dir,375				   enum iio_event_info info, int val, int val2)376{377	struct aw96103 *aw96103 = iio_priv(indio_dev);378 379	if (chan->type != IIO_PROXIMITY)380		return -EINVAL;381 382	switch (info) {383	case IIO_EV_INFO_VALUE:384		return regmap_write(aw96103->regmap,385				    AW96103_REG_PROXTH0_CH(chan->channel), val);386	case IIO_EV_INFO_PERIOD:387		switch (dir) {388		case IIO_EV_DIR_RISING:389			return regmap_update_bits(aw96103->regmap,390					AW96103_REG_PROXCTRL_CH(chan->channel),391					AW96103_OUTDEB_MASK,392					FIELD_PREP(AW96103_OUTDEB_MASK, val));393 394		case IIO_EV_DIR_FALLING:395			return regmap_update_bits(aw96103->regmap,396				AW96103_REG_PROXCTRL_CH(chan->channel),397				AW96103_INDEB_MASK,398				FIELD_PREP(AW96103_INDEB_MASK, val));399		default:400			return -EINVAL;401		}402	case IIO_EV_INFO_HYSTERESIS:403		return regmap_update_bits(aw96103->regmap,404					AW96103_REG_PROXCTRL_CH(chan->channel),405					AW96103_THHYST_MASK,406					FIELD_PREP(AW96103_THHYST_MASK, val));407	default:408		return -EINVAL;409	}410}411 412static int aw96103_read_event_config(struct iio_dev *indio_dev,413				     const struct iio_chan_spec *chan,414				     enum iio_event_type type,415				     enum iio_event_direction dir)416{417	struct aw96103 *aw96103 = iio_priv(indio_dev);418 419	return aw96103->channels_arr[chan->channel].used;420}421 422static int aw96103_write_event_config(struct iio_dev *indio_dev,423				      const struct iio_chan_spec *chan,424				      enum iio_event_type type,425				      enum iio_event_direction dir, int state)426{427	struct aw96103 *aw96103 = iio_priv(indio_dev);428 429	aw96103->channels_arr[chan->channel].used = !!state;430 431	return regmap_update_bits(aw96103->regmap, AW96103_REG_SCANCTRL0,432				  BIT(chan->channel),433				  state ? BIT(chan->channel) : 0);434}435 436static struct iio_info iio_info = {437	.read_raw = aw96103_read_raw,438	.read_event_value = aw96103_read_event_val,439	.write_event_value = aw96103_write_event_val,440	.read_event_config = aw96103_read_event_config,441	.write_event_config = aw96103_write_event_config,442};443 444static int aw96103_channel_scan_start(struct aw96103 *aw96103)445{446	int ret;447 448	ret = regmap_write(aw96103->regmap, AW96103_REG_CMD,449			   AW96103_ACTIVE_MODE);450	if (ret)451		return ret;452 453	return regmap_write(aw96103->regmap, AW96103_REG_IRQEN,454			    aw96103->hostirqen);455}456 457static int aw96103_reg_version_comp(struct aw96103 *aw96103,458				    struct aw_bin *aw_bin)459{460	u32 blfilt1_data, fw_ver;461	unsigned char i;462	int ret;463 464	ret = regmap_read(aw96103->regmap, AW96103_REG_FWVER2, &fw_ver);465	if (ret)466		return ret;467	/*468	 * If the chip version is AW96103A and the loaded register469	 * configuration file is for AW96103, special handling of the470	 * AW96103_REG_BLRSTRNG_CH0 register is required.471	 */472	if ((fw_ver != AW96103A) || (aw_bin->chip_type[7] != '\0'))473		return 0;474 475	for (i = 0; i < aw96103->max_channels; i++) {476		ret = regmap_read(aw96103->regmap,477			AW96103_REG_BLFILT_CH0 + (AW96103_BLFILT_CH_STEP * i),478			&blfilt1_data);479		if (ret)480			return ret;481		if (FIELD_GET(AW96103_BLERRTRIG_MASK, blfilt1_data) != 1)482			return 0;483 484		ret = regmap_update_bits(aw96103->regmap,485			AW96103_REG_BLRSTRNG_CH0 + (AW96103_BLFILT_CH_STEP * i),486			AW96103_BLRSTRNG_MASK, 1 << i);487		if (ret)488			return ret;489	}490 491	return 0;492}493 494static int aw96103_bin_valid_loaded(struct aw96103 *aw96103,495				    struct aw_bin *aw_bin_data_s)496{497	unsigned int start_addr = aw_bin_data_s->valid_data_addr;498	u32 i, reg_data;499	u16 reg_addr;500	int ret;501 502	for (i = 0; i < aw_bin_data_s->valid_data_len;503	     i += 6, start_addr += 6) {504		reg_addr = get_unaligned_le16(aw_bin_data_s->data + start_addr);505		reg_data = get_unaligned_le32(aw_bin_data_s->data +506					      start_addr + 2);507		if ((reg_addr == AW96103_REG_EEDA0) ||508		    (reg_addr == AW96103_REG_EEDA1))509			continue;510		if (reg_addr == AW96103_REG_IRQEN) {511			aw96103->hostirqen = reg_data;512			continue;513		}514		if (reg_addr == AW96103_REG_SCANCTRL0)515			aw96103->chan_en = FIELD_GET(AW96103_CHAN_EN_MASK,516						     reg_data);517 518		ret = regmap_write(aw96103->regmap, reg_addr, reg_data);519		if (ret < 0)520			return ret;521	}522 523	ret = aw96103_reg_version_comp(aw96103, aw_bin_data_s);524	if (ret)525		return ret;526 527	return aw96103_channel_scan_start(aw96103);528}529 530static int aw96103_para_loaded(struct aw96103 *aw96103)531{532	int i, ret;533 534	for (i = 0; i < ARRAY_SIZE(aw96103_reg_default); i += 2) {535		ret = regmap_write(aw96103->regmap,536				   (u16)aw96103_reg_default[i],537				   (u32)aw96103_reg_default[i + 1]);538		if (ret)539			return ret;540		if (aw96103_reg_default[i] == AW96103_REG_IRQEN)541			aw96103->hostirqen = aw96103_reg_default[i + 1];542		else if (aw96103_reg_default[i] == AW96103_REG_SCANCTRL0)543			aw96103->chan_en = FIELD_GET(AW96103_CHAN_EN_MASK,544					   aw96103_reg_default[i + 1]);545	}546 547	return aw96103_channel_scan_start(aw96103);548}549 550static int aw96103_cfg_all_loaded(const struct firmware *cont,551				  struct aw96103 *aw96103)552{553	if (!cont)554		return -EINVAL;555 556	struct aw_bin *aw_bin __free(kfree) =557		kzalloc(cont->size + sizeof(*aw_bin), GFP_KERNEL);558	if (!aw_bin)559		return -ENOMEM;560 561	aw_bin->len = cont->size;562	memcpy(aw_bin->data, cont->data, cont->size);563	release_firmware(cont);564	aw96103_parsing_bin_file(aw_bin);565 566	return aw96103_bin_valid_loaded(aw96103, aw_bin);567}568 569static void aw96103_cfg_update(const struct firmware *fw, void *data)570{571	struct aw96103 *aw96103 = data;572	int ret, i;573 574	if (!fw || !fw->data) {575		dev_err(aw96103->dev, "No firmware.\n");576		return;577	}578 579	ret = aw96103_cfg_all_loaded(fw, aw96103);580	/*581	 * If loading the register configuration file fails,582	 * load the default register configuration in the driver to583	 * ensure the basic functionality of the device.584	 */585	if (ret) {586		ret = aw96103_para_loaded(aw96103);587		if (ret) {588			dev_err(aw96103->dev, "load param error.\n");589			return;590		}591	}592 593	for (i = 0; i < aw96103->max_channels; i++) {594		if ((aw96103->chan_en >> i) & 0x01)595			aw96103->channels_arr[i].used = true;596		else597			aw96103->channels_arr[i].used = false;598	}599}600 601static int aw96103_sw_reset(struct aw96103 *aw96103)602{603	int ret;604 605	ret = regmap_write(aw96103->regmap, AW96103_REG_RESET, 0);606	/*607	 * After reset, the initialization process starts to perform and608	 * it will last for a bout 20ms.609	 */610	msleep(20);611 612	return ret;613}614 615enum aw96103_irq_trigger_position {616	FAR = 0,617	TRIGGER_TH0 = 0x01,618	TRIGGER_TH1 = 0x03,619	TRIGGER_TH2 = 0x07,620	TRIGGER_TH3 = 0x0f,621};622 623static irqreturn_t aw96103_irq(int irq, void *data)624{625	unsigned int irq_status, curr_status_val, curr_status;626	struct iio_dev *indio_dev = data;627	struct aw96103 *aw96103 = iio_priv(indio_dev);628	int ret, i;629 630	ret = regmap_read(aw96103->regmap, AW96103_REG_IRQSRC, &irq_status);631	if (ret)632		return IRQ_HANDLED;633 634	ret = regmap_read(aw96103->regmap, AW96103_REG_STAT0, &curr_status_val);635	if (ret)636		return IRQ_HANDLED;637 638	/*639	 * Iteratively analyze the interrupt status of different channels,640	 * with each channel having 4 interrupt states.641	 */642	for (i = 0; i < aw96103->max_channels; i++) {643		if (!aw96103->channels_arr[i].used)644			continue;645 646		curr_status = (((curr_status_val >> (24 + i)) & 0x1)) |647			      (((curr_status_val >> (16 + i)) & 0x1) << 1) |648			      (((curr_status_val >> (8 + i)) & 0x1) << 2) |649			      (((curr_status_val >> i) & 0x1) << 3);650		if (aw96103->channels_arr[i].old_irq_status == curr_status)651			continue;652 653		switch (curr_status) {654		case FAR:655			iio_push_event(indio_dev,656				       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, i,657							    IIO_EV_TYPE_THRESH,658							    IIO_EV_DIR_RISING),659				       iio_get_time_ns(indio_dev));660			break;661		case TRIGGER_TH0:662		case TRIGGER_TH1:663		case TRIGGER_TH2:664		case TRIGGER_TH3:665			iio_push_event(indio_dev,666				       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, i,667							    IIO_EV_TYPE_THRESH,668							    IIO_EV_DIR_FALLING),669				       iio_get_time_ns(indio_dev));670			break;671		default:672			return IRQ_HANDLED;673		}674		aw96103->channels_arr[i].old_irq_status = curr_status;675	}676 677	return IRQ_HANDLED;678}679 680static int aw96103_interrupt_init(struct iio_dev *indio_dev,681				  struct i2c_client *i2c)682{683	struct aw96103 *aw96103 = iio_priv(indio_dev);684	unsigned int irq_status;685	int ret;686 687	ret = regmap_write(aw96103->regmap, AW96103_REG_IRQEN, 0);688	if (ret)689		return ret;690	ret = regmap_read(aw96103->regmap, AW96103_REG_IRQSRC, &irq_status);691	if (ret)692		return ret;693	ret = devm_request_threaded_irq(aw96103->dev, i2c->irq, NULL,694					aw96103_irq, IRQF_ONESHOT,695					"aw96103_irq", indio_dev);696	if (ret)697		return ret;698 699	return regmap_write(aw96103->regmap, AW96103_REG_IRQEN,700			    aw96103->hostirqen);701}702 703static int aw96103_wait_chip_init(struct aw96103 *aw96103)704{705	unsigned int cnt = 20;706	u32 reg_data;707	int ret;708 709	while (cnt--) {710		/*711		 * The device should generate an initialization completion712		 * interrupt within 20ms.713		 */714		ret = regmap_read(aw96103->regmap, AW96103_REG_IRQSRC,715				  &reg_data);716		if (ret)717			return ret;718 719		if (FIELD_GET(AW96103_INITOVERIRQ_MASK, reg_data))720			return 0;721		fsleep(1000);722	}723 724	return -ETIMEDOUT;725}726 727static int aw96103_read_chipid(struct aw96103 *aw96103)728{729	unsigned char cnt = 0;730	u32 reg_val = 0;731	int ret;732 733	while (cnt < 3) {734		/*735		 * This retry mechanism and the subsequent delay are just736		 * attempts to read the chip ID as much as possible,737		 * preventing occasional communication failures from causing738		 * the chip ID read to fail.739		 */740		ret = regmap_read(aw96103->regmap, AW96103_REG_CHIPID,741				  &reg_val);742		if (ret < 0) {743			cnt++;744			fsleep(2000);745			continue;746		}747		break;748	}749	if (cnt == 3)750		return -ETIMEDOUT;751 752	if (FIELD_GET(AW96103_CHIPID_MASK, reg_val) != AW96103_CHIP_ID)753		dev_info(aw96103->dev,754			 "unexpected chipid, id=0x%08X\n", reg_val);755 756	return 0;757}758 759static int aw96103_i2c_probe(struct i2c_client *i2c)760{761	const struct aw_chip_info *chip_info;762	struct iio_dev *indio_dev;763	struct aw96103 *aw96103;764	int ret;765 766	indio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*aw96103));767	if (!indio_dev)768		return -ENOMEM;769 770	aw96103 = iio_priv(indio_dev);771	aw96103->dev = &i2c->dev;772	chip_info = i2c_get_match_data(i2c);773	aw96103->max_channels = chip_info->num_channels;774 775	aw96103->regmap = devm_regmap_init_i2c(i2c, &aw96103_regmap_confg);776	if (IS_ERR(aw96103->regmap))777		return PTR_ERR(aw96103->regmap);778 779	ret = devm_regulator_get_enable(aw96103->dev, "vcc");780	if (ret < 0)781		return ret;782 783	ret = aw96103_read_chipid(aw96103);784	if (ret)785		return ret;786 787	ret = aw96103_sw_reset(aw96103);788	if (ret)789		return ret;790 791	ret = aw96103_wait_chip_init(aw96103);792	if (ret)793		return ret;794 795	ret = request_firmware_nowait(THIS_MODULE, true, "aw96103_0.bin",796				      aw96103->dev, GFP_KERNEL, aw96103,797				      aw96103_cfg_update);798	if (ret)799		return ret;800 801	ret = aw96103_interrupt_init(indio_dev, i2c);802	if (ret)803		return ret;804 805	indio_dev->modes = INDIO_DIRECT_MODE;806	indio_dev->num_channels = chip_info->num_channels;807	indio_dev->channels = chip_info->channels;808	indio_dev->info = &iio_info;809	indio_dev->name = chip_info->name;810 811	return devm_iio_device_register(aw96103->dev, indio_dev);812}813 814static const struct of_device_id aw96103_dt_match[] = {815	{816		.compatible = "awinic,aw96103",817		.data = &aw_chip_info_tbl[AW96103_VAL]818	},819	{820		.compatible = "awinic,aw96105",821		.data = &aw_chip_info_tbl[AW96105_VAL]822	},823	{ }824};825MODULE_DEVICE_TABLE(of, aw96103_dt_match);826 827static const struct i2c_device_id aw96103_i2c_id[] = {828	{ "aw96103", (kernel_ulong_t)&aw_chip_info_tbl[AW96103_VAL] },829	{ "aw96105", (kernel_ulong_t)&aw_chip_info_tbl[AW96105_VAL] },830	{ }831};832MODULE_DEVICE_TABLE(i2c, aw96103_i2c_id);833 834static struct i2c_driver aw96103_i2c_driver = {835	.driver = {836		.name = "aw96103_sensor",837		.of_match_table = aw96103_dt_match,838	},839	.probe = aw96103_i2c_probe,840	.id_table = aw96103_i2c_id,841};842module_i2c_driver(aw96103_i2c_driver);843 844MODULE_AUTHOR("Wang Shuaijie <wangshuaijie@awinic.com>");845MODULE_DESCRIPTION("Driver for Awinic AW96103 proximity sensor");846MODULE_LICENSE("GPL v2");847