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
134 static_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
162 struct sx931x_info {
163 const char *name;
164 unsigned int whoami;
165 };
166
167 static 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 */
180 static 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 };
201 static 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
206 static 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
216 static 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
221 static 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
230 static 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
235 static 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
242 static 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
247 static 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
sx9310_read_prox_data(struct sx_common_data * data,const struct iio_chan_spec * chan,__be16 * val)259 static 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 */
sx9310_wait_for_sample(struct sx_common_data * data)275 static 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
sx9310_read_gain(struct sx_common_data * data,const struct iio_chan_spec * chan,int * val)291 static 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, ®val);
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
sx9310_read_samp_freq(struct sx_common_data * data,int * val,int * val2)319 static 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, ®val);
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
sx9310_read_raw(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int * val,int * val2,long mask)335 static 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
341 if (chan->type != IIO_PROXIMITY)
342 return -EINVAL;
343
344 switch (mask) {
345 case IIO_CHAN_INFO_RAW:
346 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
347 return sx_common_read_proximity(data, chan, val);
348 unreachable();
349 case IIO_CHAN_INFO_HARDWAREGAIN:
350 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
351 return sx9310_read_gain(data, chan, val);
352 unreachable();
353 case IIO_CHAN_INFO_SAMP_FREQ:
354 return sx9310_read_samp_freq(data, val, val2);
355 default:
356 return -EINVAL;
357 }
358 }
359
360 static const int sx9310_gain_vals[] = { 1, 2, 4, 8 };
361
sx9310_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)362 static int sx9310_read_avail(struct iio_dev *indio_dev,
363 struct iio_chan_spec const *chan,
364 const int **vals, int *type, int *length,
365 long mask)
366 {
367 if (chan->type != IIO_PROXIMITY)
368 return -EINVAL;
369
370 switch (mask) {
371 case IIO_CHAN_INFO_HARDWAREGAIN:
372 *type = IIO_VAL_INT;
373 *length = ARRAY_SIZE(sx9310_gain_vals);
374 *vals = sx9310_gain_vals;
375 return IIO_AVAIL_LIST;
376 case IIO_CHAN_INFO_SAMP_FREQ:
377 *type = IIO_VAL_INT_PLUS_MICRO;
378 *length = ARRAY_SIZE(sx9310_samp_freq_table) * 2;
379 *vals = (int *)sx9310_samp_freq_table;
380 return IIO_AVAIL_LIST;
381 default:
382 return -EINVAL;
383 }
384 }
385
386 static const unsigned int sx9310_pthresh_codes[] = {
387 2, 4, 6, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 72, 80, 88, 96, 112,
388 128, 144, 160, 192, 224, 256, 320, 384, 512, 640, 768, 1024, 1536
389 };
390
sx9310_get_thresh_reg(unsigned int channel)391 static int sx9310_get_thresh_reg(unsigned int channel)
392 {
393 switch (channel) {
394 case 0:
395 case 3:
396 return SX9310_REG_PROX_CTRL8;
397 case 1:
398 case 2:
399 return SX9310_REG_PROX_CTRL9;
400 default:
401 return -EINVAL;
402 }
403 }
404
sx9310_read_thresh(struct sx_common_data * data,const struct iio_chan_spec * chan,int * val)405 static int sx9310_read_thresh(struct sx_common_data *data,
406 const struct iio_chan_spec *chan, int *val)
407 {
408 unsigned int reg;
409 unsigned int regval;
410 int ret;
411
412 reg = ret = sx9310_get_thresh_reg(chan->channel);
413 if (ret < 0)
414 return ret;
415
416 ret = regmap_read(data->regmap, reg, ®val);
417 if (ret)
418 return ret;
419
420 regval = FIELD_GET(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
421 if (regval >= ARRAY_SIZE(sx9310_pthresh_codes))
422 return -EINVAL;
423
424 *val = sx9310_pthresh_codes[regval];
425 return IIO_VAL_INT;
426 }
427
sx9310_read_hysteresis(struct sx_common_data * data,const struct iio_chan_spec * chan,int * val)428 static int sx9310_read_hysteresis(struct sx_common_data *data,
429 const struct iio_chan_spec *chan, int *val)
430 {
431 unsigned int regval, pthresh;
432 int ret;
433
434 ret = sx9310_read_thresh(data, chan, &pthresh);
435 if (ret < 0)
436 return ret;
437
438 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, ®val);
439 if (ret)
440 return ret;
441
442 regval = FIELD_GET(SX9310_REG_PROX_CTRL10_HYST_MASK, regval);
443 if (!regval)
444 regval = 5;
445
446 /* regval is at most 5 */
447 *val = pthresh >> (5 - regval);
448
449 return IIO_VAL_INT;
450 }
451
sx9310_read_far_debounce(struct sx_common_data * data,int * val)452 static int sx9310_read_far_debounce(struct sx_common_data *data, int *val)
453 {
454 unsigned int regval;
455 int ret;
456
457 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, ®val);
458 if (ret)
459 return ret;
460
461 regval = FIELD_GET(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, regval);
462 if (regval)
463 *val = 1 << regval;
464 else
465 *val = 0;
466
467 return IIO_VAL_INT;
468 }
469
sx9310_read_close_debounce(struct sx_common_data * data,int * val)470 static int sx9310_read_close_debounce(struct sx_common_data *data, int *val)
471 {
472 unsigned int regval;
473 int ret;
474
475 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, ®val);
476 if (ret)
477 return ret;
478
479 regval = FIELD_GET(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, regval);
480 if (regval)
481 *val = 1 << regval;
482 else
483 *val = 0;
484
485 return IIO_VAL_INT;
486 }
487
sx9310_read_event_val(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)488 static int sx9310_read_event_val(struct iio_dev *indio_dev,
489 const struct iio_chan_spec *chan,
490 enum iio_event_type type,
491 enum iio_event_direction dir,
492 enum iio_event_info info, int *val, int *val2)
493 {
494 struct sx_common_data *data = iio_priv(indio_dev);
495
496 if (chan->type != IIO_PROXIMITY)
497 return -EINVAL;
498
499 switch (info) {
500 case IIO_EV_INFO_VALUE:
501 return sx9310_read_thresh(data, chan, val);
502 case IIO_EV_INFO_PERIOD:
503 switch (dir) {
504 case IIO_EV_DIR_RISING:
505 return sx9310_read_far_debounce(data, val);
506 case IIO_EV_DIR_FALLING:
507 return sx9310_read_close_debounce(data, val);
508 default:
509 return -EINVAL;
510 }
511 case IIO_EV_INFO_HYSTERESIS:
512 return sx9310_read_hysteresis(data, chan, val);
513 default:
514 return -EINVAL;
515 }
516 }
517
sx9310_write_thresh(struct sx_common_data * data,const struct iio_chan_spec * chan,int val)518 static int sx9310_write_thresh(struct sx_common_data *data,
519 const struct iio_chan_spec *chan, int val)
520 {
521 unsigned int reg;
522 unsigned int regval;
523 int ret, i;
524
525 reg = ret = sx9310_get_thresh_reg(chan->channel);
526 if (ret < 0)
527 return ret;
528
529 for (i = 0; i < ARRAY_SIZE(sx9310_pthresh_codes); i++) {
530 if (sx9310_pthresh_codes[i] == val) {
531 regval = i;
532 break;
533 }
534 }
535
536 if (i == ARRAY_SIZE(sx9310_pthresh_codes))
537 return -EINVAL;
538
539 regval = FIELD_PREP(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
540
541 guard(mutex)(&data->mutex);
542 return regmap_update_bits(data->regmap, reg,
543 SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
544 }
545
sx9310_write_hysteresis(struct sx_common_data * data,const struct iio_chan_spec * chan,int _val)546 static int sx9310_write_hysteresis(struct sx_common_data *data,
547 const struct iio_chan_spec *chan, int _val)
548 {
549 unsigned int hyst, val = _val;
550 int ret, pthresh;
551
552 ret = sx9310_read_thresh(data, chan, &pthresh);
553 if (ret < 0)
554 return ret;
555
556 if (val == 0)
557 hyst = 0;
558 else if (val == pthresh >> 2)
559 hyst = 3;
560 else if (val == pthresh >> 3)
561 hyst = 2;
562 else if (val == pthresh >> 4)
563 hyst = 1;
564 else
565 return -EINVAL;
566
567 hyst = FIELD_PREP(SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
568
569 guard(mutex)(&data->mutex);
570 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
571 SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
572 }
573
sx9310_write_far_debounce(struct sx_common_data * data,int val)574 static int sx9310_write_far_debounce(struct sx_common_data *data, int val)
575 {
576 unsigned int regval;
577
578 if (val > 0)
579 val = ilog2(val);
580 if (!FIELD_FIT(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val))
581 return -EINVAL;
582
583 regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val);
584
585 guard(mutex)(&data->mutex);
586 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
587 SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK,
588 regval);
589 }
590
sx9310_write_close_debounce(struct sx_common_data * data,int val)591 static int sx9310_write_close_debounce(struct sx_common_data *data, int val)
592 {
593 unsigned int regval;
594
595 if (val > 0)
596 val = ilog2(val);
597 if (!FIELD_FIT(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val))
598 return -EINVAL;
599
600 regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val);
601
602 guard(mutex)(&data->mutex);
603 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
604 SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK,
605 regval);
606 }
607
sx9310_write_event_val(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)608 static int sx9310_write_event_val(struct iio_dev *indio_dev,
609 const struct iio_chan_spec *chan,
610 enum iio_event_type type,
611 enum iio_event_direction dir,
612 enum iio_event_info info, int val, int val2)
613 {
614 struct sx_common_data *data = iio_priv(indio_dev);
615
616 if (chan->type != IIO_PROXIMITY)
617 return -EINVAL;
618
619 switch (info) {
620 case IIO_EV_INFO_VALUE:
621 return sx9310_write_thresh(data, chan, val);
622 case IIO_EV_INFO_PERIOD:
623 switch (dir) {
624 case IIO_EV_DIR_RISING:
625 return sx9310_write_far_debounce(data, val);
626 case IIO_EV_DIR_FALLING:
627 return sx9310_write_close_debounce(data, val);
628 default:
629 return -EINVAL;
630 }
631 case IIO_EV_INFO_HYSTERESIS:
632 return sx9310_write_hysteresis(data, chan, val);
633 default:
634 return -EINVAL;
635 }
636 }
637
sx9310_set_samp_freq(struct sx_common_data * data,int val,int val2)638 static int sx9310_set_samp_freq(struct sx_common_data *data, int val, int val2)
639 {
640 int i;
641
642 for (i = 0; i < ARRAY_SIZE(sx9310_samp_freq_table); i++)
643 if (val == sx9310_samp_freq_table[i].val &&
644 val2 == sx9310_samp_freq_table[i].val2)
645 break;
646
647 if (i == ARRAY_SIZE(sx9310_samp_freq_table))
648 return -EINVAL;
649
650 guard(mutex)(&data->mutex);
651 return regmap_update_bits(
652 data->regmap, SX9310_REG_PROX_CTRL0,
653 SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK,
654 FIELD_PREP(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, i));
655 }
656
sx9310_write_gain(struct sx_common_data * data,const struct iio_chan_spec * chan,int val)657 static int sx9310_write_gain(struct sx_common_data *data,
658 const struct iio_chan_spec *chan, int val)
659 {
660 unsigned int gain, mask;
661
662 gain = ilog2(val);
663
664 switch (chan->channel) {
665 case 0:
666 case 3:
667 mask = SX9310_REG_PROX_CTRL3_GAIN0_MASK;
668 gain = FIELD_PREP(SX9310_REG_PROX_CTRL3_GAIN0_MASK, gain);
669 break;
670 case 1:
671 case 2:
672 mask = SX9310_REG_PROX_CTRL3_GAIN12_MASK;
673 gain = FIELD_PREP(SX9310_REG_PROX_CTRL3_GAIN12_MASK, gain);
674 break;
675 default:
676 return -EINVAL;
677 }
678
679 guard(mutex)(&data->mutex);
680 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL3, mask,
681 gain);
682 }
683
sx9310_write_raw(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int val,int val2,long mask)684 static int sx9310_write_raw(struct iio_dev *indio_dev,
685 const struct iio_chan_spec *chan, int val, int val2,
686 long mask)
687 {
688 struct sx_common_data *data = iio_priv(indio_dev);
689
690 if (chan->type != IIO_PROXIMITY)
691 return -EINVAL;
692
693 switch (mask) {
694 case IIO_CHAN_INFO_SAMP_FREQ:
695 return sx9310_set_samp_freq(data, val, val2);
696 case IIO_CHAN_INFO_HARDWAREGAIN:
697 return sx9310_write_gain(data, chan, val);
698 default:
699 return -EINVAL;
700 }
701 }
702
703 static const struct sx_common_reg_default sx9310_default_regs[] = {
704 { SX9310_REG_IRQ_MSK, 0x00 },
705 { SX9310_REG_IRQ_FUNC, 0x00 },
706 /*
707 * The lower 4 bits should not be set as it enable sensors measurements.
708 * Turning the detection on before the configuration values are set to
709 * good values can cause the device to return erroneous readings.
710 */
711 { SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL0_SCANPERIOD_15MS },
712 { SX9310_REG_PROX_CTRL1, 0x00 },
713 { SX9310_REG_PROX_CTRL2, SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2 |
714 SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC },
715 { SX9310_REG_PROX_CTRL3, SX9310_REG_PROX_CTRL3_GAIN0_X8 |
716 SX9310_REG_PROX_CTRL3_GAIN12_X4 },
717 { SX9310_REG_PROX_CTRL4, SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST },
718 { SX9310_REG_PROX_CTRL5, SX9310_REG_PROX_CTRL5_RANGE_SMALL |
719 SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 |
720 SX9310_REG_PROX_CTRL5_RAWFILT_1P25 },
721 { SX9310_REG_PROX_CTRL6, SX9310_REG_PROX_CTRL6_AVGTHRESH_DEFAULT },
722 { SX9310_REG_PROX_CTRL7, SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 |
723 SX9310_REG_PROX_CTRL7_AVGPOSFILT_512 },
724 { SX9310_REG_PROX_CTRL8, SX9310_REG_PROX_CTRL8_9_PTHRESH_96 |
725 SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500 },
726 { SX9310_REG_PROX_CTRL9, SX9310_REG_PROX_CTRL8_9_PTHRESH_28 |
727 SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900 },
728 { SX9310_REG_PROX_CTRL10, SX9310_REG_PROX_CTRL10_HYST_6PCT |
729 SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2 },
730 { SX9310_REG_PROX_CTRL11, 0x00 },
731 { SX9310_REG_PROX_CTRL12, 0x00 },
732 { SX9310_REG_PROX_CTRL13, 0x00 },
733 { SX9310_REG_PROX_CTRL14, 0x00 },
734 { SX9310_REG_PROX_CTRL15, 0x00 },
735 { SX9310_REG_PROX_CTRL16, 0x00 },
736 { SX9310_REG_PROX_CTRL17, 0x00 },
737 { SX9310_REG_PROX_CTRL18, 0x00 },
738 { SX9310_REG_PROX_CTRL19, 0x00 },
739 { SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES |
740 SX9310_REG_SAR_CTRL0_SARHYST_8 },
741 { SX9310_REG_SAR_CTRL1, SX9310_REG_SAR_CTRL1_SLOPE(10781250) },
742 { SX9310_REG_SAR_CTRL2, SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT },
743 };
744
745 /* Activate all channels and perform an initial compensation. */
sx9310_init_compensation(struct iio_dev * indio_dev)746 static int sx9310_init_compensation(struct iio_dev *indio_dev)
747 {
748 struct sx_common_data *data = iio_priv(indio_dev);
749 int ret;
750 unsigned int val;
751 unsigned int ctrl0;
752
753 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &ctrl0);
754 if (ret)
755 return ret;
756
757 /* run the compensation phase on all channels */
758 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
759 ctrl0 | SX9310_REG_PROX_CTRL0_SENSOREN_MASK);
760 if (ret)
761 return ret;
762
763 ret = regmap_read_poll_timeout(data->regmap, SX9310_REG_STAT1, val,
764 !(val & SX9310_REG_STAT1_COMPSTAT_MASK),
765 20000, 2000000);
766 if (ret)
767 return ret;
768
769 regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
770 return ret;
771 }
772
773 static const struct sx_common_reg_default *
sx9310_get_default_reg(struct device * dev,int idx,struct sx_common_reg_default * reg_def)774 sx9310_get_default_reg(struct device *dev, int idx,
775 struct sx_common_reg_default *reg_def)
776 {
777 u32 combined[SX9310_NUM_CHANNELS];
778 u32 start = 0, raw = 0, pos = 0;
779 unsigned long comb_mask = 0;
780 int ret, i, count;
781 const char *res;
782
783 memcpy(reg_def, &sx9310_default_regs[idx], sizeof(*reg_def));
784 switch (reg_def->reg) {
785 case SX9310_REG_PROX_CTRL2:
786 if (device_property_read_bool(dev, "semtech,cs0-ground")) {
787 reg_def->def &= ~SX9310_REG_PROX_CTRL2_SHIELDEN_MASK;
788 reg_def->def |= SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND;
789 }
790
791 count = device_property_count_u32(dev, "semtech,combined-sensors");
792 if (count < 0 || count > ARRAY_SIZE(combined))
793 break;
794 ret = device_property_read_u32_array(dev, "semtech,combined-sensors",
795 combined, count);
796 if (ret)
797 break;
798
799 for (i = 0; i < count; i++)
800 comb_mask |= BIT(combined[i]);
801
802 reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK;
803 if (comb_mask == (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
804 reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3;
805 else if (comb_mask == (BIT(1) | BIT(2)))
806 reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2;
807 else if (comb_mask == (BIT(0) | BIT(1)))
808 reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1;
809 else if (comb_mask == BIT(3))
810 reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS3;
811
812 break;
813 case SX9310_REG_PROX_CTRL4:
814 ret = device_property_read_string(dev, "semtech,resolution", &res);
815 if (ret)
816 break;
817
818 reg_def->def &= ~SX9310_REG_PROX_CTRL4_RESOLUTION_MASK;
819 if (!strcmp(res, "coarsest"))
820 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_COARSEST;
821 else if (!strcmp(res, "very-coarse"))
822 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_COARSE;
823 else if (!strcmp(res, "coarse"))
824 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_COARSE;
825 else if (!strcmp(res, "medium-coarse"))
826 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM_COARSE;
827 else if (!strcmp(res, "medium"))
828 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_MEDIUM;
829 else if (!strcmp(res, "fine"))
830 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_FINE;
831 else if (!strcmp(res, "very-fine"))
832 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_VERY_FINE;
833 else if (!strcmp(res, "finest"))
834 reg_def->def |= SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST;
835
836 break;
837 case SX9310_REG_PROX_CTRL5:
838 ret = device_property_read_u32(dev, "semtech,startup-sensor", &start);
839 if (ret) {
840 start = FIELD_GET(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
841 reg_def->def);
842 }
843
844 reg_def->def &= ~SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK;
845 reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
846 start);
847
848 ret = device_property_read_u32(dev, "semtech,proxraw-strength", &raw);
849 if (ret) {
850 raw = FIELD_GET(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
851 reg_def->def);
852 } else {
853 raw = ilog2(raw);
854 }
855
856 reg_def->def &= ~SX9310_REG_PROX_CTRL5_RAWFILT_MASK;
857 reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
858 raw);
859 break;
860 case SX9310_REG_PROX_CTRL7:
861 ret = device_property_read_u32(dev, "semtech,avg-pos-strength", &pos);
862 if (ret)
863 break;
864
865 /* Powers of 2, except for a gap between 16 and 64 */
866 pos = clamp(ilog2(pos), 3, 11) - (pos >= 32 ? 4 : 3);
867 reg_def->def &= ~SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK;
868 reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL7_AVGPOSFILT_MASK,
869 pos);
870 break;
871 }
872
873 return reg_def;
874 }
875
sx9310_check_whoami(struct device * dev,struct iio_dev * indio_dev)876 static int sx9310_check_whoami(struct device *dev,
877 struct iio_dev *indio_dev)
878 {
879 struct sx_common_data *data = iio_priv(indio_dev);
880 const struct sx931x_info *ddata;
881 unsigned int whoami;
882 int ret;
883
884 ret = regmap_read(data->regmap, SX9310_REG_WHOAMI, &whoami);
885 if (ret)
886 return ret;
887
888 ddata = device_get_match_data(dev);
889 if (ddata->whoami != whoami)
890 return -ENODEV;
891
892 indio_dev->name = ddata->name;
893
894 return 0;
895 }
896
897 static const struct sx_common_chip_info sx9310_chip_info = {
898 .reg_stat = SX9310_REG_STAT0,
899 .reg_irq_msk = SX9310_REG_IRQ_MSK,
900 .reg_enable_chan = SX9310_REG_PROX_CTRL0,
901 .reg_reset = SX9310_REG_RESET,
902
903 .mask_enable_chan = SX9310_REG_STAT1_COMPSTAT_MASK,
904 .irq_msk_offset = 3,
905 .num_channels = SX9310_NUM_CHANNELS,
906 .num_default_regs = ARRAY_SIZE(sx9310_default_regs),
907
908 .ops = {
909 .read_prox_data = sx9310_read_prox_data,
910 .check_whoami = sx9310_check_whoami,
911 .init_compensation = sx9310_init_compensation,
912 .wait_for_sample = sx9310_wait_for_sample,
913 .get_default_reg = sx9310_get_default_reg,
914 },
915
916 .iio_channels = sx9310_channels,
917 .num_iio_channels = ARRAY_SIZE(sx9310_channels),
918 .iio_info = {
919 .read_raw = sx9310_read_raw,
920 .read_avail = sx9310_read_avail,
921 .read_event_value = sx9310_read_event_val,
922 .write_event_value = sx9310_write_event_val,
923 .write_raw = sx9310_write_raw,
924 .read_event_config = sx_common_read_event_config,
925 .write_event_config = sx_common_write_event_config,
926 },
927 };
928
sx9310_probe(struct i2c_client * client)929 static int sx9310_probe(struct i2c_client *client)
930 {
931 return sx_common_probe(client, &sx9310_chip_info, &sx9310_regmap_config);
932 }
933
sx9310_suspend(struct device * dev)934 static int sx9310_suspend(struct device *dev)
935 {
936 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
937 u8 ctrl0;
938 int ret;
939
940 disable_irq_nosync(data->client->irq);
941
942 guard(mutex)(&data->mutex);
943 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0,
944 &data->suspend_ctrl);
945 if (ret)
946 return ret;
947
948 ctrl0 = data->suspend_ctrl & ~SX9310_REG_PROX_CTRL0_SENSOREN_MASK;
949 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
950 if (ret)
951 return ret;
952
953 return regmap_write(data->regmap, SX9310_REG_PAUSE, 0);
954 }
955
sx9310_resume(struct device * dev)956 static int sx9310_resume(struct device *dev)
957 {
958 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
959 int ret;
960
961 scoped_guard(mutex, &data->mutex) {
962 ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 1);
963 if (ret)
964 return ret;
965
966 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
967 data->suspend_ctrl);
968 if (ret)
969 return ret;
970 }
971
972 enable_irq(data->client->irq);
973 return 0;
974 }
975
976 static DEFINE_SIMPLE_DEV_PM_OPS(sx9310_pm_ops, sx9310_suspend, sx9310_resume);
977
978 static const struct sx931x_info sx9310_info = {
979 .name = "sx9310",
980 .whoami = SX9310_WHOAMI_VALUE,
981 };
982
983 static const struct sx931x_info sx9311_info = {
984 .name = "sx9311",
985 .whoami = SX9311_WHOAMI_VALUE,
986 };
987
988 static const struct acpi_device_id sx9310_acpi_match[] = {
989 { "STH9310", (kernel_ulong_t)&sx9310_info },
990 { "STH9311", (kernel_ulong_t)&sx9311_info },
991 {}
992 };
993 MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match);
994
995 static const struct of_device_id sx9310_of_match[] = {
996 { .compatible = "semtech,sx9310", &sx9310_info },
997 { .compatible = "semtech,sx9311", &sx9311_info },
998 {}
999 };
1000 MODULE_DEVICE_TABLE(of, sx9310_of_match);
1001
1002 static const struct i2c_device_id sx9310_id[] = {
1003 { "sx9310", (kernel_ulong_t)&sx9310_info },
1004 { "sx9311", (kernel_ulong_t)&sx9311_info },
1005 {}
1006 };
1007 MODULE_DEVICE_TABLE(i2c, sx9310_id);
1008
1009 static struct i2c_driver sx9310_driver = {
1010 .driver = {
1011 .name = "sx9310",
1012 .acpi_match_table = sx9310_acpi_match,
1013 .of_match_table = sx9310_of_match,
1014 .pm = pm_sleep_ptr(&sx9310_pm_ops),
1015
1016 /*
1017 * Lots of i2c transfers in probe + over 200 ms waiting in
1018 * sx9310_init_compensation() mean a slow probe; prefer async
1019 * so we don't delay boot if we're builtin to the kernel.
1020 */
1021 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
1022 },
1023 .probe = sx9310_probe,
1024 .id_table = sx9310_id,
1025 };
1026 module_i2c_driver(sx9310_driver);
1027
1028 MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
1029 MODULE_AUTHOR("Daniel Campello <campello@chromium.org>");
1030 MODULE_DESCRIPTION("Driver for Semtech SX9310/SX9311 proximity sensor");
1031 MODULE_LICENSE("GPL v2");
1032 MODULE_IMPORT_NS("SEMTECH_PROX");
1033