File Index
Files and directories
Sign in
FILE

sx9310.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/proximity/sx9310.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2018 Google LLC.
   4 *
   5 * Driver for Semtech's SX9310/SX9311 capacitive proximity/button solution.
   6 * Based on SX9500 driver and Semtech driver using the input framework
   7 * <https://my.syncplicity.com/share/teouwsim8niiaud/
   8 *          linux-driver-SX9310_NoSmartHSensing>.
   9 * Reworked in April 2019 by Evan Green <evgreen@chromium.org>
  10 * and in January 2020 by Daniel Campello <campello@chromium.org>.
  11 */
  12
  13#include <linux/bitfield.h>
  14#include <linux/delay.h>
  15#include <linux/i2c.h>
  16#include <linux/interrupt.h>
  17#include <linux/kernel.h>
  18#include <linux/log2.h>
  19#include <linux/mod_devicetable.h>
  20#include <linux/module.h>
  21#include <linux/pm.h>
  22#include <linux/property.h>
  23#include <linux/regmap.h>
  24#include <linux/iio/iio.h>
  25
  26#include "sx_common.h"
  27
  28/* Register definitions. */
  29#define SX9310_REG_IRQ_SRC				SX_COMMON_REG_IRQ_SRC
  30#define SX9310_REG_STAT0				0x01
  31#define SX9310_REG_STAT1				0x02
  32#define SX9310_REG_STAT1_COMPSTAT_MASK			GENMASK(3, 0)
  33#define SX9310_REG_IRQ_MSK				0x03
  34#define   SX9310_CONVDONE_IRQ				BIT(3)
  35#define   SX9310_FAR_IRQ				BIT(5)
  36#define   SX9310_CLOSE_IRQ				BIT(6)
  37#define SX9310_REG_IRQ_FUNC				0x04
  38
  39#define SX9310_REG_PROX_CTRL0				0x10
  40#define   SX9310_REG_PROX_CTRL0_SENSOREN_MASK		GENMASK(3, 0)
  41#define   SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK		GENMASK(7, 4)
  42#define   SX9310_REG_PROX_CTRL0_SCANPERIOD_15MS		0x01
  43#define SX9310_REG_PROX_CTRL1				0x11
  44#define SX9310_REG_PROX_CTRL2				0x12
  45#define   SX9310_REG_PROX_CTRL2_COMBMODE_MASK		GENMASK(7, 6)
  46#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3 (0x03 << 6)
  47#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2	(0x02 << 6)
  48#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1	(0x01 << 6)
  49#define   SX9310_REG_PROX_CTRL2_COMBMODE_CS3		(0x00 << 6)
  50#define   SX9310_REG_PROX_CTRL2_SHIELDEN_MASK		GENMASK(3, 2)
  51#define   SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC	(0x01 << 2)
  52#define   SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND		(0x02 << 2)
  53#define SX9310_REG_PROX_CTRL3				0x13
  54#define   SX9310_REG_PROX_CTRL3_GAIN0_MASK		GENMASK(3, 2)
  55#define   SX9310_REG_PROX_CTRL3_GAIN0_X8		(0x03 << 2)
  56#define   SX9310_REG_PROX_CTRL3_GAIN12_MASK		GENMASK(1, 0)
  57#define   SX9310_REG_PROX_CTRL3_GAIN12_X4		0x02
  58#define SX9310_REG_PROX_CTRL4				0x14
  59#define   SX9310_REG_PROX_CTRL4_RESOLUTION_MASK		GENMASK(2, 0)
  60#define   SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST	0x07
  61#define   SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_FINE	0x06
  62#define   SX9310_REG_PROX_CTRL4_RESOLUTION_FINE		0x05
  63#define   SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM	0x04
  64#define   SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM_COARSE 0x03
  65#define   SX9310_REG_PROX_CTRL4_RESOLUTION_COARSE	0x02
  66#define   SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_COARSE	0x01
  67#define   SX9310_REG_PROX_CTRL4_RESOLUTION_COARSEST	0x00
  68#define SX9310_REG_PROX_CTRL5				0x15
  69#define   SX9310_REG_PROX_CTRL5_RANGE_SMALL		(0x03 << 6)
  70#define   SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK	GENMASK(3, 2)
  71#define   SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1		(0x01 << 2)
  72#define   SX9310_REG_PROX_CTRL5_RAWFILT_MASK		GENMASK(1, 0)
  73#define   SX9310_REG_PROX_CTRL5_RAWFILT_SHIFT		0
  74#define   SX9310_REG_PROX_CTRL5_RAWFILT_1P25		0x02
  75#define SX9310_REG_PROX_CTRL6				0x16
  76#define   SX9310_REG_PROX_CTRL6_AVGTHRESH_DEFAULT	0x20
  77#define SX9310_REG_PROX_CTRL7				0x17
  78#define   SX9310_REG_PROX_CTRL7_AVGNEGFILT_2		(0x01 << 3)
  79#define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK		GENMASK(2, 0)
  80#define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_SHIFT	0
  81#define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_512		0x05
  82#define SX9310_REG_PROX_CTRL8				0x18
  83#define   SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK		GENMASK(7, 3)
  84#define SX9310_REG_PROX_CTRL9				0x19
  85#define   SX9310_REG_PROX_CTRL8_9_PTHRESH_28		(0x08 << 3)
  86#define   SX9310_REG_PROX_CTRL8_9_PTHRESH_96		(0x11 << 3)
  87#define   SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900	0x03
  88#define   SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500	0x05
  89#define SX9310_REG_PROX_CTRL10				0x1a
  90#define   SX9310_REG_PROX_CTRL10_HYST_MASK		GENMASK(5, 4)
  91#define   SX9310_REG_PROX_CTRL10_HYST_6PCT		(0x01 << 4)
  92#define   SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK	GENMASK(3, 2)
  93#define   SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK	GENMASK(1, 0)
  94#define   SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2		0x01
  95#define SX9310_REG_PROX_CTRL11				0x1b
  96#define SX9310_REG_PROX_CTRL12				0x1c
  97#define SX9310_REG_PROX_CTRL13				0x1d
  98#define SX9310_REG_PROX_CTRL14				0x1e
  99#define SX9310_REG_PROX_CTRL15				0x1f
 100#define SX9310_REG_PROX_CTRL16				0x20
 101#define SX9310_REG_PROX_CTRL17				0x21
 102#define SX9310_REG_PROX_CTRL18				0x22
 103#define SX9310_REG_PROX_CTRL19				0x23
 104#define SX9310_REG_SAR_CTRL0				0x2a
 105#define   SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES		(0x02 << 5)
 106#define   SX9310_REG_SAR_CTRL0_SARHYST_8		(0x02 << 3)
 107#define SX9310_REG_SAR_CTRL1				0x2b
 108/* Each increment of the slope register is 0.0078125. */
 109#define   SX9310_REG_SAR_CTRL1_SLOPE(_hnslope)		(_hnslope / 78125)
 110#define SX9310_REG_SAR_CTRL2				0x2c
 111#define   SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT	0x3c
 112
 113#define SX9310_REG_SENSOR_SEL				0x30
 114#define SX9310_REG_USE_MSB				0x31
 115#define SX9310_REG_USE_LSB				0x32
 116#define SX9310_REG_AVG_MSB				0x33
 117#define SX9310_REG_AVG_LSB				0x34
 118#define SX9310_REG_DIFF_MSB				0x35
 119#define SX9310_REG_DIFF_LSB				0x36
 120#define SX9310_REG_OFFSET_MSB				0x37
 121#define SX9310_REG_OFFSET_LSB				0x38
 122#define SX9310_REG_SAR_MSB				0x39
 123#define SX9310_REG_SAR_LSB				0x3a
 124#define SX9310_REG_I2C_ADDR				0x40
 125#define SX9310_REG_PAUSE				0x41
 126#define SX9310_REG_WHOAMI				0x42
 127#define   SX9310_WHOAMI_VALUE				0x01
 128#define   SX9311_WHOAMI_VALUE				0x02
 129#define SX9310_REG_RESET				0x7f
 130
 131
 132/* 4 hardware channels, as defined in STAT0: COMB, CS2, CS1 and CS0. */
 133#define SX9310_NUM_CHANNELS				4
 134static_assert(SX9310_NUM_CHANNELS <= SX_COMMON_MAX_NUM_CHANNELS);
 135
 136#define SX9310_NAMED_CHANNEL(idx, name)				 \
 137{								 \
 138	.type = IIO_PROXIMITY,					 \
 139	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		 \
 140			      BIT(IIO_CHAN_INFO_HARDWAREGAIN),   \
 141	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 142	.info_mask_separate_available =				 \
 143		BIT(IIO_CHAN_INFO_HARDWAREGAIN),		 \
 144	.info_mask_shared_by_all_available =			 \
 145		BIT(IIO_CHAN_INFO_SAMP_FREQ),			 \
 146	.indexed = 1,						 \
 147	.channel = idx,						 \
 148	.extend_name = name,					 \
 149	.address = SX9310_REG_DIFF_MSB,				 \
 150	.event_spec = sx_common_events,				 \
 151	.num_event_specs = ARRAY_SIZE(sx_common_events),	 \
 152	.scan_index = idx,					 \
 153	.scan_type = {						 \
 154		.sign = 's',					 \
 155		.realbits = 12,					 \
 156		.storagebits = 16,				 \
 157		.endianness = IIO_BE,				 \
 158	},							 \
 159}
 160#define SX9310_CHANNEL(idx) SX9310_NAMED_CHANNEL(idx, NULL)
 161
 162struct sx931x_info {
 163	const char *name;
 164	unsigned int whoami;
 165};
 166
 167static const struct iio_chan_spec sx9310_channels[] = {
 168	SX9310_CHANNEL(0),			/* CS0 */
 169	SX9310_CHANNEL(1),			/* CS1 */
 170	SX9310_CHANNEL(2),			/* CS2 */
 171	SX9310_NAMED_CHANNEL(3, "comb"),	/* COMB */
 172
 173	IIO_CHAN_SOFT_TIMESTAMP(4),
 174};
 175
 176/*
 177 * Each entry contains the integer part (val) and the fractional part, in micro
 178 * seconds. It conforms to the IIO output IIO_VAL_INT_PLUS_MICRO.
 179 */
 180static const struct {
 181	int val;
 182	int val2;
 183} sx9310_samp_freq_table[] = {
 184	{ 500, 0 }, /* 0000: Min (no idle time) */
 185	{ 66, 666666 }, /* 0001: 15 ms */
 186	{ 33, 333333 }, /* 0010: 30 ms (Typ.) */
 187	{ 22, 222222 }, /* 0011: 45 ms */
 188	{ 16, 666666 }, /* 0100: 60 ms */
 189	{ 11, 111111 }, /* 0101: 90 ms */
 190	{ 8, 333333 }, /* 0110: 120 ms */
 191	{ 5, 0 }, /* 0111: 200 ms */
 192	{ 2, 500000 }, /* 1000: 400 ms */
 193	{ 1, 666666 }, /* 1001: 600 ms */
 194	{ 1, 250000 }, /* 1010: 800 ms */
 195	{ 1, 0 }, /* 1011: 1 s */
 196	{ 0, 500000 }, /* 1100: 2 s */
 197	{ 0, 333333 }, /* 1101: 3 s */
 198	{ 0, 250000 }, /* 1110: 4 s */
 199	{ 0, 200000 }, /* 1111: 5 s */
 200};
 201static const unsigned int sx9310_scan_period_table[] = {
 202	2,   15,  30,  45,   60,   90,	 120,  200,
 203	400, 600, 800, 1000, 2000, 3000, 4000, 5000,
 204};
 205
 206static const struct regmap_range sx9310_writable_reg_ranges[] = {
 207	regmap_reg_range(SX9310_REG_IRQ_MSK, SX9310_REG_IRQ_FUNC),
 208	regmap_reg_range(SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL19),
 209	regmap_reg_range(SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL2),
 210	regmap_reg_range(SX9310_REG_SENSOR_SEL, SX9310_REG_SENSOR_SEL),
 211	regmap_reg_range(SX9310_REG_OFFSET_MSB, SX9310_REG_OFFSET_LSB),
 212	regmap_reg_range(SX9310_REG_PAUSE, SX9310_REG_PAUSE),
 213	regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET),
 214};
 215
 216static const struct regmap_access_table sx9310_writeable_regs = {
 217	.yes_ranges = sx9310_writable_reg_ranges,
 218	.n_yes_ranges = ARRAY_SIZE(sx9310_writable_reg_ranges),
 219};
 220
 221static const struct regmap_range sx9310_readable_reg_ranges[] = {
 222	regmap_reg_range(SX9310_REG_IRQ_SRC, SX9310_REG_IRQ_FUNC),
 223	regmap_reg_range(SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL19),
 224	regmap_reg_range(SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL2),
 225	regmap_reg_range(SX9310_REG_SENSOR_SEL, SX9310_REG_SAR_LSB),
 226	regmap_reg_range(SX9310_REG_I2C_ADDR, SX9310_REG_WHOAMI),
 227	regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET),
 228};
 229
 230static const struct regmap_access_table sx9310_readable_regs = {
 231	.yes_ranges = sx9310_readable_reg_ranges,
 232	.n_yes_ranges = ARRAY_SIZE(sx9310_readable_reg_ranges),
 233};
 234
 235static const struct regmap_range sx9310_volatile_reg_ranges[] = {
 236	regmap_reg_range(SX9310_REG_IRQ_SRC, SX9310_REG_STAT1),
 237	regmap_reg_range(SX9310_REG_USE_MSB, SX9310_REG_DIFF_LSB),
 238	regmap_reg_range(SX9310_REG_SAR_MSB, SX9310_REG_SAR_LSB),
 239	regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET),
 240};
 241
 242static const struct regmap_access_table sx9310_volatile_regs = {
 243	.yes_ranges = sx9310_volatile_reg_ranges,
 244	.n_yes_ranges = ARRAY_SIZE(sx9310_volatile_reg_ranges),
 245};
 246
 247static const struct regmap_config sx9310_regmap_config = {
 248	.reg_bits = 8,
 249	.val_bits = 8,
 250
 251	.max_register = SX9310_REG_RESET,
 252	.cache_type = REGCACHE_RBTREE,
 253
 254	.wr_table = &sx9310_writeable_regs,
 255	.rd_table = &sx9310_readable_regs,
 256	.volatile_table = &sx9310_volatile_regs,
 257};
 258
 259static int sx9310_read_prox_data(struct sx_common_data *data,
 260				 const struct iio_chan_spec *chan, __be16 *val)
 261{
 262	int ret;
 263
 264	ret = regmap_write(data->regmap, SX9310_REG_SENSOR_SEL, chan->channel);
 265	if (ret)
 266		return ret;
 267
 268	return regmap_bulk_read(data->regmap, chan->address, val, sizeof(*val));
 269}
 270
 271/*
 272 * If we have no interrupt support, we have to wait for a scan period
 273 * after enabling a channel to get a result.
 274 */
 275static int sx9310_wait_for_sample(struct sx_common_data *data)
 276{
 277	int ret;
 278	unsigned int val;
 279
 280	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &val);
 281	if (ret)
 282		return ret;
 283
 284	val = FIELD_GET(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, val);
 285
 286	msleep(sx9310_scan_period_table[val]);
 287
 288	return 0;
 289}
 290
 291static int sx9310_read_gain(struct sx_common_data *data,
 292			    const struct iio_chan_spec *chan, int *val)
 293{
 294	unsigned int regval, gain;
 295	int ret;
 296
 297	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL3, &regval);
 298	if (ret)
 299		return ret;
 300
 301	switch (chan->channel) {
 302	case 0:
 303	case 3:
 304		gain = FIELD_GET(SX9310_REG_PROX_CTRL3_GAIN0_MASK, regval);
 305		break;
 306	case 1:
 307	case 2:
 308		gain = FIELD_GET(SX9310_REG_PROX_CTRL3_GAIN12_MASK, regval);
 309		break;
 310	default:
 311		return -EINVAL;
 312	}
 313
 314	*val = 1 << gain;
 315
 316	return IIO_VAL_INT;
 317}
 318
 319static int sx9310_read_samp_freq(struct sx_common_data *data, int *val, int *val2)
 320{
 321	unsigned int regval;
 322	int ret;
 323
 324	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &regval);
 325	if (ret)
 326		return ret;
 327
 328	regval = FIELD_GET(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, regval);
 329	*val = sx9310_samp_freq_table[regval].val;
 330	*val2 = sx9310_samp_freq_table[regval].val2;
 331
 332	return IIO_VAL_INT_PLUS_MICRO;
 333}
 334
 335static int sx9310_read_raw(struct iio_dev *indio_dev,
 336			   const struct iio_chan_spec *chan, int *val,
 337			   int *val2, long mask)
 338{
 339	struct sx_common_data *data = iio_priv(indio_dev);
 340	int ret;
 341
 342	if (chan->type != IIO_PROXIMITY)
 343		return -EINVAL;
 344
 345	switch (mask) {
 346	case IIO_CHAN_INFO_RAW:
 347		if (!iio_device_claim_direct(indio_dev))
 348			return -EBUSY;
 349
 350		ret = sx_common_read_proximity(data, chan, val);
 351		iio_device_release_direct(indio_dev);
 352		return ret;
 353	case IIO_CHAN_INFO_HARDWAREGAIN:
 354		if (!iio_device_claim_direct(indio_dev))
 355			return -EBUSY;
 356
 357		ret = sx9310_read_gain(data, chan, val);
 358		iio_device_release_direct(indio_dev);
 359		return ret;
 360	case IIO_CHAN_INFO_SAMP_FREQ:
 361		return sx9310_read_samp_freq(data, val, val2);
 362	default:
 363		return -EINVAL;
 364	}
 365}
 366
 367static const int sx9310_gain_vals[] = { 1, 2, 4, 8 };
 368
 369static int sx9310_read_avail(struct iio_dev *indio_dev,
 370			     struct iio_chan_spec const *chan,
 371			     const int **vals, int *type, int *length,
 372			     long mask)
 373{
 374	if (chan->type != IIO_PROXIMITY)
 375		return -EINVAL;
 376
 377	switch (mask) {
 378	case IIO_CHAN_INFO_HARDWAREGAIN:
 379		*type = IIO_VAL_INT;
 380		*length = ARRAY_SIZE(sx9310_gain_vals);
 381		*vals = sx9310_gain_vals;
 382		return IIO_AVAIL_LIST;
 383	case IIO_CHAN_INFO_SAMP_FREQ:
 384		*type = IIO_VAL_INT_PLUS_MICRO;
 385		*length = ARRAY_SIZE(sx9310_samp_freq_table) * 2;
 386		*vals = (int *)sx9310_samp_freq_table;
 387		return IIO_AVAIL_LIST;
 388	default:
 389		return -EINVAL;
 390	}
 391}
 392
 393static const unsigned int sx9310_pthresh_codes[] = {
 394	2, 4, 6, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 72, 80, 88, 96, 112,
 395	128, 144, 160, 192, 224, 256, 320, 384, 512, 640, 768, 1024, 1536
 396};
 397
 398static int sx9310_get_thresh_reg(unsigned int channel)
 399{
 400	switch (channel) {
 401	case 0:
 402	case 3:
 403		return SX9310_REG_PROX_CTRL8;
 404	case 1:
 405	case 2:
 406		return SX9310_REG_PROX_CTRL9;
 407	default:
 408		return -EINVAL;
 409	}
 410}
 411
 412static int sx9310_read_thresh(struct sx_common_data *data,
 413			      const struct iio_chan_spec *chan, int *val)
 414{
 415	unsigned int reg;
 416	unsigned int regval;
 417	int ret;
 418
 419	reg = ret = sx9310_get_thresh_reg(chan->channel);
 420	if (ret < 0)
 421		return ret;
 422
 423	ret = regmap_read(data->regmap, reg, &regval);
 424	if (ret)
 425		return ret;
 426
 427	regval = FIELD_GET(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
 428	if (regval >= ARRAY_SIZE(sx9310_pthresh_codes))
 429		return -EINVAL;
 430
 431	*val = sx9310_pthresh_codes[regval];
 432	return IIO_VAL_INT;
 433}
 434
 435static int sx9310_read_hysteresis(struct sx_common_data *data,
 436				  const struct iio_chan_spec *chan, int *val)
 437{
 438	unsigned int regval, pthresh;
 439	int ret;
 440
 441	ret = sx9310_read_thresh(data, chan, &pthresh);
 442	if (ret < 0)
 443		return ret;
 444
 445	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, &regval);
 446	if (ret)
 447		return ret;
 448
 449	regval = FIELD_GET(SX9310_REG_PROX_CTRL10_HYST_MASK, regval);
 450	if (!regval)
 451		regval = 5;
 452
 453	/* regval is at most 5 */
 454	*val = pthresh >> (5 - regval);
 455
 456	return IIO_VAL_INT;
 457}
 458
 459static int sx9310_read_far_debounce(struct sx_common_data *data, int *val)
 460{
 461	unsigned int regval;
 462	int ret;
 463
 464	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, &regval);
 465	if (ret)
 466		return ret;
 467
 468	regval = FIELD_GET(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, regval);
 469	if (regval)
 470		*val = 1 << regval;
 471	else
 472		*val = 0;
 473
 474	return IIO_VAL_INT;
 475}
 476
 477static int sx9310_read_close_debounce(struct sx_common_data *data, int *val)
 478{
 479	unsigned int regval;
 480	int ret;
 481
 482	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, &regval);
 483	if (ret)
 484		return ret;
 485
 486	regval = FIELD_GET(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, regval);
 487	if (regval)
 488		*val = 1 << regval;
 489	else
 490		*val = 0;
 491
 492	return IIO_VAL_INT;
 493}
 494
 495static int sx9310_read_event_val(struct iio_dev *indio_dev,
 496				 const struct iio_chan_spec *chan,
 497				 enum iio_event_type type,
 498				 enum iio_event_direction dir,
 499				 enum iio_event_info info, int *val, int *val2)
 500{
 501	struct sx_common_data *data = iio_priv(indio_dev);
 502
 503	if (chan->type != IIO_PROXIMITY)
 504		return -EINVAL;
 505
 506	switch (info) {
 507	case IIO_EV_INFO_VALUE:
 508		return sx9310_read_thresh(data, chan, val);
 509	case IIO_EV_INFO_PERIOD:
 510		switch (dir) {
 511		case IIO_EV_DIR_RISING:
 512			return sx9310_read_far_debounce(data, val);
 513		case IIO_EV_DIR_FALLING:
 514			return sx9310_read_close_debounce(data, val);
 515		default:
 516			return -EINVAL;
 517		}
 518	case IIO_EV_INFO_HYSTERESIS:
 519		return sx9310_read_hysteresis(data, chan, val);
 520	default:
 521		return -EINVAL;
 522	}
 523}
 524
 525static int sx9310_write_thresh(struct sx_common_data *data,
 526			       const struct iio_chan_spec *chan, int val)
 527{
 528	unsigned int reg;
 529	unsigned int regval;
 530	int ret, i;
 531
 532	reg = ret = sx9310_get_thresh_reg(chan->channel);
 533	if (ret < 0)
 534		return ret;
 535
 536	for (i = 0; i < ARRAY_SIZE(sx9310_pthresh_codes); i++) {
 537		if (sx9310_pthresh_codes[i] == val) {
 538			regval = i;
 539			break;
 540		}
 541	}
 542
 543	if (i == ARRAY_SIZE(sx9310_pthresh_codes))
 544		return -EINVAL;
 545
 546	regval = FIELD_PREP(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
 547
 548	guard(mutex)(&data->mutex);
 549	return regmap_update_bits(data->regmap, reg,
 550				  SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
 551}
 552
 553static int sx9310_write_hysteresis(struct sx_common_data *data,
 554				   const struct iio_chan_spec *chan, int _val)
 555{
 556	unsigned int hyst, val = _val;
 557	int ret, pthresh;
 558
 559	ret = sx9310_read_thresh(data, chan, &pthresh);
 560	if (ret < 0)
 561		return ret;
 562
 563	if (val == 0)
 564		hyst = 0;
 565	else if (val == pthresh >> 2)
 566		hyst = 3;
 567	else if (val == pthresh >> 3)
 568		hyst = 2;
 569	else if (val == pthresh >> 4)
 570		hyst = 1;
 571	else
 572		return -EINVAL;
 573
 574	hyst = FIELD_PREP(SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
 575
 576	guard(mutex)(&data->mutex);
 577	return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
 578				  SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
 579}
 580
 581static int sx9310_write_far_debounce(struct sx_common_data *data, int val)
 582{
 583	unsigned int regval;
 584
 585	if (val > 0)
 586		val = ilog2(val);
 587	if (!FIELD_FIT(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val))
 588		return -EINVAL;
 589
 590	regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val);
 591
 592	guard(mutex)(&data->mutex);
 593	return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
 594				  SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK,
 595				  regval);
 596}
 597
 598static int sx9310_write_close_debounce(struct sx_common_data *data, int val)
 599{
 600	unsigned int regval;
 601
 602	if (val > 0)
 603		val = ilog2(val);
 604	if (!FIELD_FIT(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val))
 605		return -EINVAL;
 606
 607	regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val);
 608
 609	guard(mutex)(&data->mutex);
 610	return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
 611				  SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK,
 612				  regval);
 613}
 614
 615static int sx9310_write_event_val(struct iio_dev *indio_dev,
 616				  const struct iio_chan_spec *chan,
 617				  enum iio_event_type type,
 618				  enum iio_event_direction dir,
 619				  enum iio_event_info info, int val, int val2)
 620{
 621	struct sx_common_data *data = iio_priv(indio_dev);
 622
 623	if (chan->type != IIO_PROXIMITY)
 624		return -EINVAL;
 625
 626	switch (info) {
 627	case IIO_EV_INFO_VALUE:
 628		return sx9310_write_thresh(data, chan, val);
 629	case IIO_EV_INFO_PERIOD:
 630		switch (dir) {
 631		case IIO_EV_DIR_RISING:
 632			return sx9310_write_far_debounce(data, val);
 633		case IIO_EV_DIR_FALLING:
 634			return sx9310_write_close_debounce(data, val);
 635		default:
 636			return -EINVAL;
 637		}
 638	case IIO_EV_INFO_HYSTERESIS:
 639		return sx9310_write_hysteresis(data, chan, val);
 640	default:
 641		return -EINVAL;
 642	}
 643}
 644
 645static int sx9310_set_samp_freq(struct sx_common_data *data, int val, int val2)
 646{
 647	int i;
 648
 649	for (i = 0; i < ARRAY_SIZE(sx9310_samp_freq_table); i++)
 650		if (val == sx9310_samp_freq_table[i].val &&
 651		    val2 == sx9310_samp_freq_table[i].val2)
 652			break;
 653
 654	if (i == ARRAY_SIZE(sx9310_samp_freq_table))
 655		return -EINVAL;
 656
 657	guard(mutex)(&data->mutex);
 658	return regmap_update_bits(
 659		data->regmap, SX9310_REG_PROX_CTRL0,
 660		SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK,
 661		FIELD_PREP(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, i));
 662}
 663
 664static int sx9310_write_gain(struct sx_common_data *data,
 665			     const struct iio_chan_spec *chan, int val)
 666{
 667	unsigned int gain, mask;
 668
 669	gain = ilog2(val);
 670
 671	switch (chan->channel) {
 672	case 0:
 673	case 3:
 674		mask = SX9310_REG_PROX_CTRL3_GAIN0_MASK;
 675		gain = FIELD_PREP(SX9310_REG_PROX_CTRL3_GAIN0_MASK, gain);
 676		break;
 677	case 1:
 678	case 2:
 679		mask = SX9310_REG_PROX_CTRL3_GAIN12_MASK;
 680		gain = FIELD_PREP(SX9310_REG_PROX_CTRL3_GAIN12_MASK, gain);
 681		break;
 682	default:
 683		return -EINVAL;
 684	}
 685
 686	guard(mutex)(&data->mutex);
 687	return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL3, mask,
 688				  gain);
 689}
 690
 691static int sx9310_write_raw(struct iio_dev *indio_dev,
 692			    const struct iio_chan_spec *chan, int val, int val2,
 693			    long mask)
 694{
 695	struct sx_common_data *data = iio_priv(indio_dev);
 696
 697	if (chan->type != IIO_PROXIMITY)
 698		return -EINVAL;
 699
 700	switch (mask) {
 701	case IIO_CHAN_INFO_SAMP_FREQ:
 702		return sx9310_set_samp_freq(data, val, val2);
 703	case IIO_CHAN_INFO_HARDWAREGAIN:
 704		return sx9310_write_gain(data, chan, val);
 705	default:
 706		return -EINVAL;
 707	}
 708}
 709
 710static const struct sx_common_reg_default sx9310_default_regs[] = {
 711	{ SX9310_REG_IRQ_MSK, 0x00 },
 712	{ SX9310_REG_IRQ_FUNC, 0x00 },
 713	/*
 714	 * The lower 4 bits should not be set as it enable sensors measurements.
 715	 * Turning the detection on before the configuration values are set to
 716	 * good values can cause the device to return erroneous readings.
 717	 */
 718	{ SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL0_SCANPERIOD_15MS },
 719	{ SX9310_REG_PROX_CTRL1, 0x00 },
 720	{ SX9310_REG_PROX_CTRL2, SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2 |
 721				 SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC },
 722	{ SX9310_REG_PROX_CTRL3, SX9310_REG_PROX_CTRL3_GAIN0_X8 |
 723				 SX9310_REG_PROX_CTRL3_GAIN12_X4 },
 724	{ SX9310_REG_PROX_CTRL4, SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST },
 725	{ SX9310_REG_PROX_CTRL5, SX9310_REG_PROX_CTRL5_RANGE_SMALL |
 726				 SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 |
 727				 SX9310_REG_PROX_CTRL5_RAWFILT_1P25 },
 728	{ SX9310_REG_PROX_CTRL6, SX9310_REG_PROX_CTRL6_AVGTHRESH_DEFAULT },
 729	{ SX9310_REG_PROX_CTRL7, SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 |
 730				 SX9310_REG_PROX_CTRL7_AVGPOSFILT_512 },
 731	{ SX9310_REG_PROX_CTRL8, SX9310_REG_PROX_CTRL8_9_PTHRESH_96 |
 732				 SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500 },
 733	{ SX9310_REG_PROX_CTRL9, SX9310_REG_PROX_CTRL8_9_PTHRESH_28 |
 734				 SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900 },
 735	{ SX9310_REG_PROX_CTRL10, SX9310_REG_PROX_CTRL10_HYST_6PCT |
 736				  SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2 },
 737	{ SX9310_REG_PROX_CTRL11, 0x00 },
 738	{ SX9310_REG_PROX_CTRL12, 0x00 },
 739	{ SX9310_REG_PROX_CTRL13, 0x00 },
 740	{ SX9310_REG_PROX_CTRL14, 0x00 },
 741	{ SX9310_REG_PROX_CTRL15, 0x00 },
 742	{ SX9310_REG_PROX_CTRL16, 0x00 },
 743	{ SX9310_REG_PROX_CTRL17, 0x00 },
 744	{ SX9310_REG_PROX_CTRL18, 0x00 },
 745	{ SX9310_REG_PROX_CTRL19, 0x00 },
 746	{ SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES |
 747				SX9310_REG_SAR_CTRL0_SARHYST_8 },
 748	{ SX9310_REG_SAR_CTRL1, SX9310_REG_SAR_CTRL1_SLOPE(10781250) },
 749	{ SX9310_REG_SAR_CTRL2, SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT },
 750};
 751
 752/* Activate all channels and perform an initial compensation. */
 753static int sx9310_init_compensation(struct iio_dev *indio_dev)
 754{
 755	struct sx_common_data *data = iio_priv(indio_dev);
 756	int ret;
 757	unsigned int val;
 758	unsigned int ctrl0;
 759
 760	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &ctrl0);
 761	if (ret)
 762		return ret;
 763
 764	/* run the compensation phase on all channels */
 765	ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
 766			   ctrl0 | SX9310_REG_PROX_CTRL0_SENSOREN_MASK);
 767	if (ret)
 768		return ret;
 769
 770	ret = regmap_read_poll_timeout(data->regmap, SX9310_REG_STAT1, val,
 771				       !(val & SX9310_REG_STAT1_COMPSTAT_MASK),
 772				       20000, 2000000);
 773	if (ret)
 774		return ret;
 775
 776	regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
 777	return ret;
 778}
 779
 780static const struct sx_common_reg_default *
 781sx9310_get_default_reg(struct device *dev, int idx,
 782		       struct sx_common_reg_default *reg_def)
 783{
 784	u32 combined[SX9310_NUM_CHANNELS];
 785	u32 start = 0, raw = 0, pos = 0;
 786	unsigned long comb_mask = 0;
 787	int ret, i, count;
 788	const char *res;
 789
 790	memcpy(reg_def, &sx9310_default_regs[idx], sizeof(*reg_def));
 791	switch (reg_def->reg) {
 792	case SX9310_REG_PROX_CTRL2:
 793		if (device_property_read_bool(dev, "semtech,cs0-ground")) {
 794			reg_def->def &= ~SX9310_REG_PROX_CTRL2_SHIELDEN_MASK;
 795			reg_def->def |= SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND;
 796		}
 797
 798		count = device_property_count_u32(dev, "semtech,combined-sensors");
 799		if (count < 0 || count > ARRAY_SIZE(combined))
 800			break;
 801		ret = device_property_read_u32_array(dev, "semtech,combined-sensors",
 802				combined, count);
 803		if (ret)
 804			break;
 805
 806		for (i = 0; i < count; i++)
 807			comb_mask |= BIT(combined[i]);
 808
 809		reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK;
 810		if (comb_mask == (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
 811			reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3;
 812		else if (comb_mask == (BIT(1) | BIT(2)))
 813			reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2;
 814		else if (comb_mask == (BIT(0) | BIT(1)))
 815			reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1;
 816		else if (comb_mask == BIT(3))
 817			reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS3;
 818
 819		break;
 820	case SX9310_REG_PROX_CTRL4:
 821		ret = device_property_read_string(dev, "semtech,resolution", &res);
 822		if (ret)
 823			break;
 824
 825		reg_def->def &= ~SX9310_REG_PROX_CTRL4_RESOLUTION_MASK;
 826		if (!strcmp(res, "coarsest"))
 827			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_COARSEST;
 828		else if (!strcmp(res, "very-coarse"))
 829			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_COARSE;
 830		else if (!strcmp(res, "coarse"))
 831			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_COARSE;
 832		else if (!strcmp(res, "medium-coarse"))
 833			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM_COARSE;
 834		else if (!strcmp(res, "medium"))
 835			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM;
 836		else if (!strcmp(res, "fine"))
 837			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_FINE;
 838		else if (!strcmp(res, "very-fine"))
 839			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_FINE;
 840		else if (!strcmp(res, "finest"))
 841			reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST;
 842
 843		break;
 844	case SX9310_REG_PROX_CTRL5:
 845		ret = device_property_read_u32(dev, "semtech,startup-sensor", &start);
 846		if (ret) {
 847			start = FIELD_GET(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
 848					  reg_def->def);
 849		}
 850
 851		reg_def->def &= ~SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK;
 852		reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
 853					   start);
 854
 855		ret = device_property_read_u32(dev, "semtech,proxraw-strength", &raw);
 856		if (ret) {
 857			raw = FIELD_GET(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
 858					reg_def->def);
 859		} else {
 860			raw = ilog2(raw);
 861		}
 862
 863		reg_def->def &= ~SX9310_REG_PROX_CTRL5_RAWFILT_MASK;
 864		reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
 865					   raw);
 866		break;
 867	case SX9310_REG_PROX_CTRL7:
 868		ret = device_property_read_u32(dev, "semtech,avg-pos-strength", &pos);
 869		if (ret)
 870			break;
 871
 872		/* Powers of 2, except for a gap between 16 and 64 */
 873		pos = clamp(ilog2(pos), 3, 11) - (pos >= 32 ? 4 : 3);
 874		reg_def->def &= ~SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK;
 875		reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK,
 876					   pos);
 877		break;
 878	}
 879
 880	return reg_def;
 881}
 882
 883static int sx9310_check_whoami(struct device *dev,
 884			       struct iio_dev *indio_dev)
 885{
 886	struct sx_common_data *data = iio_priv(indio_dev);
 887	const struct sx931x_info *ddata;
 888	unsigned int whoami;
 889	int ret;
 890
 891	ret = regmap_read(data->regmap, SX9310_REG_WHOAMI, &whoami);
 892	if (ret)
 893		return ret;
 894
 895	ddata = device_get_match_data(dev);
 896	if (ddata->whoami != whoami)
 897		return -ENODEV;
 898
 899	indio_dev->name = ddata->name;
 900
 901	return 0;
 902}
 903
 904static const struct sx_common_chip_info sx9310_chip_info = {
 905	.reg_stat = SX9310_REG_STAT0,
 906	.reg_irq_msk = SX9310_REG_IRQ_MSK,
 907	.reg_enable_chan = SX9310_REG_PROX_CTRL0,
 908	.reg_reset = SX9310_REG_RESET,
 909
 910	.mask_enable_chan = SX9310_REG_STAT1_COMPSTAT_MASK,
 911	.irq_msk_offset = 3,
 912	.num_channels = SX9310_NUM_CHANNELS,
 913	.num_default_regs = ARRAY_SIZE(sx9310_default_regs),
 914
 915	.ops = {
 916		.read_prox_data = sx9310_read_prox_data,
 917		.check_whoami = sx9310_check_whoami,
 918		.init_compensation = sx9310_init_compensation,
 919		.wait_for_sample = sx9310_wait_for_sample,
 920		.get_default_reg = sx9310_get_default_reg,
 921	},
 922
 923	.iio_channels = sx9310_channels,
 924	.num_iio_channels = ARRAY_SIZE(sx9310_channels),
 925	.iio_info =  {
 926		.read_raw = sx9310_read_raw,
 927		.read_avail = sx9310_read_avail,
 928		.read_event_value = sx9310_read_event_val,
 929		.write_event_value = sx9310_write_event_val,
 930		.write_raw = sx9310_write_raw,
 931		.read_event_config = sx_common_read_event_config,
 932		.write_event_config = sx_common_write_event_config,
 933	},
 934};
 935
 936static int sx9310_probe(struct i2c_client *client)
 937{
 938	return sx_common_probe(client, &sx9310_chip_info, &sx9310_regmap_config);
 939}
 940
 941static int sx9310_suspend(struct device *dev)
 942{
 943	struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
 944	u8 ctrl0;
 945	int ret;
 946
 947	disable_irq_nosync(data->client->irq);
 948
 949	guard(mutex)(&data->mutex);
 950	ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0,
 951			  &data->suspend_ctrl);
 952	if (ret)
 953		return ret;
 954
 955	ctrl0 = data->suspend_ctrl & ~SX9310_REG_PROX_CTRL0_SENSOREN_MASK;
 956	ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
 957	if (ret)
 958		return ret;
 959
 960	return regmap_write(data->regmap, SX9310_REG_PAUSE, 0);
 961}
 962
 963static int sx9310_resume(struct device *dev)
 964{
 965	struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
 966	int ret;
 967
 968	scoped_guard(mutex, &data->mutex) {
 969		ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 1);
 970		if (ret)
 971			return ret;
 972
 973		ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
 974				   data->suspend_ctrl);
 975		if (ret)
 976			return ret;
 977	}
 978
 979	enable_irq(data->client->irq);
 980	return 0;
 981}
 982
 983static DEFINE_SIMPLE_DEV_PM_OPS(sx9310_pm_ops, sx9310_suspend, sx9310_resume);
 984
 985static const struct sx931x_info sx9310_info = {
 986	.name = "sx9310",
 987	.whoami = SX9310_WHOAMI_VALUE,
 988};
 989
 990static const struct sx931x_info sx9311_info = {
 991	.name = "sx9311",
 992	.whoami = SX9311_WHOAMI_VALUE,
 993};
 994
 995static const struct acpi_device_id sx9310_acpi_match[] = {
 996	{ "STH9310", (kernel_ulong_t)&sx9310_info },
 997	{ "STH9311", (kernel_ulong_t)&sx9311_info },
 998	{ }
 999};
1000MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match);
1001
1002static const struct of_device_id sx9310_of_match[] = {
1003	{ .compatible = "semtech,sx9310", &sx9310_info },
1004	{ .compatible = "semtech,sx9311", &sx9311_info },
1005	{ }
1006};
1007MODULE_DEVICE_TABLE(of, sx9310_of_match);
1008
1009static const struct i2c_device_id sx9310_id[] = {
1010	{ "sx9310", (kernel_ulong_t)&sx9310_info },
1011	{ "sx9311", (kernel_ulong_t)&sx9311_info },
1012	{ }
1013};
1014MODULE_DEVICE_TABLE(i2c, sx9310_id);
1015
1016static struct i2c_driver sx9310_driver = {
1017	.driver = {
1018		.name	= "sx9310",
1019		.acpi_match_table = sx9310_acpi_match,
1020		.of_match_table = sx9310_of_match,
1021		.pm = pm_sleep_ptr(&sx9310_pm_ops),
1022
1023		/*
1024		 * Lots of i2c transfers in probe + over 200 ms waiting in
1025		 * sx9310_init_compensation() mean a slow probe; prefer async
1026		 * so we don't delay boot if we're builtin to the kernel.
1027		 */
1028		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
1029	},
1030	.probe		= sx9310_probe,
1031	.id_table	= sx9310_id,
1032};
1033module_i2c_driver(sx9310_driver);
1034
1035MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
1036MODULE_AUTHOR("Daniel Campello <campello@chromium.org>");
1037MODULE_DESCRIPTION("Driver for Semtech SX9310/SX9311 proximity sensor");
1038MODULE_LICENSE("GPL v2");
1039MODULE_IMPORT_NS("SEMTECH_PROX");
~/ Read-only file preview.