0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/acpi.h>
0011 #include <linux/bits.h>
0012 #include <linux/bitfield.h>
0013 #include <linux/delay.h>
0014 #include <linux/i2c.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/kernel.h>
0017 #include <linux/log2.h>
0018 #include <linux/mod_devicetable.h>
0019 #include <linux/module.h>
0020 #include <linux/pm.h>
0021 #include <linux/property.h>
0022 #include <linux/regmap.h>
0023
0024 #include <linux/iio/iio.h>
0025
0026 #include "sx_common.h"
0027
0028
0029 #define SX9360_FOSC_MHZ 4
0030 #define SX9360_FOSC_HZ (SX9360_FOSC_MHZ * 1000000)
0031
0032
0033 #define SX9360_REG_IRQ_SRC SX_COMMON_REG_IRQ_SRC
0034 #define SX9360_REG_STAT 0x01
0035 #define SX9360_REG_STAT_COMPSTAT_MASK GENMASK(2, 1)
0036 #define SX9360_REG_IRQ_MSK 0x02
0037 #define SX9360_CONVDONE_IRQ BIT(0)
0038 #define SX9360_FAR_IRQ BIT(2)
0039 #define SX9360_CLOSE_IRQ BIT(3)
0040 #define SX9360_REG_IRQ_CFG 0x03
0041
0042 #define SX9360_REG_GNRL_CTRL0 0x10
0043 #define SX9360_REG_GNRL_CTRL0_PHEN_MASK GENMASK(1, 0)
0044 #define SX9360_REG_GNRL_CTRL1 0x11
0045 #define SX9360_REG_GNRL_CTRL1_SCANPERIOD_MASK GENMASK(2, 0)
0046 #define SX9360_REG_GNRL_CTRL2 0x12
0047 #define SX9360_REG_GNRL_CTRL2_PERIOD_102MS 0x32
0048 #define SX9360_REG_GNRL_REG_2_PERIOD_MS(_r) \
0049 (((_r) * 8192) / (SX9360_FOSC_HZ / 1000))
0050 #define SX9360_REG_GNRL_FREQ_2_REG(_f) (((_f) * 8192) / SX9360_FOSC_HZ)
0051 #define SX9360_REG_GNRL_REG_2_FREQ(_r) (SX9360_FOSC_HZ / ((_r) * 8192))
0052
0053 #define SX9360_REG_AFE_CTRL1 0x21
0054 #define SX9360_REG_AFE_CTRL1_RESFILTIN_MASK GENMASK(3, 0)
0055 #define SX9360_REG_AFE_CTRL1_RESFILTIN_0OHMS 0
0056 #define SX9360_REG_AFE_PARAM0_PHR 0x22
0057 #define SX9360_REG_AFE_PARAM1_PHR 0x23
0058 #define SX9360_REG_AFE_PARAM0_PHM 0x24
0059 #define SX9360_REG_AFE_PARAM0_RSVD 0x08
0060 #define SX9360_REG_AFE_PARAM0_RESOLUTION_MASK GENMASK(2, 0)
0061 #define SX9360_REG_AFE_PARAM0_RESOLUTION_128 0x02
0062 #define SX9360_REG_AFE_PARAM1_PHM 0x25
0063 #define SX9360_REG_AFE_PARAM1_AGAIN_PHM_6PF 0x40
0064 #define SX9360_REG_AFE_PARAM1_FREQ_83_33HZ 0x06
0065
0066 #define SX9360_REG_PROX_CTRL0_PHR 0x40
0067 #define SX9360_REG_PROX_CTRL0_PHM 0x41
0068 #define SX9360_REG_PROX_CTRL0_GAIN_MASK GENMASK(5, 3)
0069 #define SX9360_REG_PROX_CTRL0_GAIN_1 0x80
0070 #define SX9360_REG_PROX_CTRL0_RAWFILT_MASK GENMASK(2, 0)
0071 #define SX9360_REG_PROX_CTRL0_RAWFILT_1P50 0x01
0072 #define SX9360_REG_PROX_CTRL1 0x42
0073 #define SX9360_REG_PROX_CTRL1_AVGNEG_THRESH_MASK GENMASK(5, 3)
0074 #define SX9360_REG_PROX_CTRL1_AVGNEG_THRESH_16K 0x20
0075 #define SX9360_REG_PROX_CTRL2 0x43
0076 #define SX9360_REG_PROX_CTRL2_AVGDEB_MASK GENMASK(7, 6)
0077 #define SX9360_REG_PROX_CTRL2_AVGDEB_2SAMPLES 0x40
0078 #define SX9360_REG_PROX_CTRL2_AVGPOS_THRESH_16K 0x20
0079 #define SX9360_REG_PROX_CTRL3 0x44
0080 #define SX9360_REG_PROX_CTRL3_AVGNEG_FILT_MASK GENMASK(5, 3)
0081 #define SX9360_REG_PROX_CTRL3_AVGNEG_FILT_2 0x08
0082 #define SX9360_REG_PROX_CTRL3_AVGPOS_FILT_MASK GENMASK(2, 0)
0083 #define SX9360_REG_PROX_CTRL3_AVGPOS_FILT_256 0x04
0084 #define SX9360_REG_PROX_CTRL4 0x45
0085 #define SX9360_REG_PROX_CTRL4_HYST_MASK GENMASK(5, 4)
0086 #define SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK GENMASK(3, 2)
0087 #define SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK GENMASK(1, 0)
0088 #define SX9360_REG_PROX_CTRL5 0x46
0089 #define SX9360_REG_PROX_CTRL5_PROXTHRESH_32 0x08
0090
0091 #define SX9360_REG_REF_CORR0 0x60
0092 #define SX9360_REG_REF_CORR1 0x61
0093
0094 #define SX9360_REG_USEFUL_PHR_MSB 0x90
0095 #define SX9360_REG_USEFUL_PHR_LSB 0x91
0096
0097 #define SX9360_REG_OFFSET_PMR_MSB 0x92
0098 #define SX9360_REG_OFFSET_PMR_LSB 0x93
0099
0100 #define SX9360_REG_USEFUL_PHM_MSB 0x94
0101 #define SX9360_REG_USEFUL_PHM_LSB 0x95
0102
0103 #define SX9360_REG_AVG_PHM_MSB 0x96
0104 #define SX9360_REG_AVG_PHM_LSB 0x97
0105
0106 #define SX9360_REG_DIFF_PHM_MSB 0x98
0107 #define SX9360_REG_DIFF_PHM_LSB 0x99
0108
0109 #define SX9360_REG_OFFSET_PHM_MSB 0x9a
0110 #define SX9360_REG_OFFSET_PHM_LSB 0x9b
0111
0112 #define SX9360_REG_USE_FILTER_MSB 0x9a
0113 #define SX9360_REG_USE_FILTER_LSB 0x9b
0114
0115 #define SX9360_REG_RESET 0xcf
0116
0117 #define SX9360_SOFT_RESET 0xde
0118
0119 #define SX9360_REG_WHOAMI 0xfa
0120 #define SX9360_WHOAMI_VALUE 0x60
0121
0122 #define SX9360_REG_REVISION 0xfe
0123
0124
0125 #define SX9360_NUM_CHANNELS 2
0126
0127 static const struct iio_chan_spec sx9360_channels[] = {
0128 {
0129 .type = IIO_PROXIMITY,
0130 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0131 BIT(IIO_CHAN_INFO_HARDWAREGAIN),
0132 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
0133 .info_mask_separate_available =
0134 BIT(IIO_CHAN_INFO_HARDWAREGAIN),
0135 .info_mask_shared_by_all_available =
0136 BIT(IIO_CHAN_INFO_SAMP_FREQ),
0137 .indexed = 1,
0138 .address = SX9360_REG_USEFUL_PHR_MSB,
0139 .channel = 0,
0140 .scan_index = 0,
0141 .scan_type = {
0142 .sign = 's',
0143 .realbits = 12,
0144 .storagebits = 16,
0145 .endianness = IIO_BE,
0146 },
0147 },
0148 {
0149 .type = IIO_PROXIMITY,
0150 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0151 BIT(IIO_CHAN_INFO_HARDWAREGAIN),
0152 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
0153 .info_mask_separate_available =
0154 BIT(IIO_CHAN_INFO_HARDWAREGAIN),
0155 .info_mask_shared_by_all_available =
0156 BIT(IIO_CHAN_INFO_SAMP_FREQ),
0157 .indexed = 1,
0158 .address = SX9360_REG_USEFUL_PHM_MSB,
0159 .event_spec = sx_common_events,
0160 .num_event_specs = ARRAY_SIZE(sx_common_events),
0161 .channel = 1,
0162 .scan_index = 1,
0163 .scan_type = {
0164 .sign = 's',
0165 .realbits = 12,
0166 .storagebits = 16,
0167 .endianness = IIO_BE,
0168 },
0169 },
0170 IIO_CHAN_SOFT_TIMESTAMP(2),
0171 };
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 static const struct {
0184 int val;
0185 int val2;
0186 } sx9360_samp_freq_interval[] = {
0187 { 0, 281250 },
0188 { 0, 281250 },
0189 { 448, 281250 },
0190 };
0191
0192 static const struct regmap_range sx9360_writable_reg_ranges[] = {
0193
0194
0195
0196
0197 regmap_reg_range(SX9360_REG_STAT, SX9360_REG_IRQ_CFG),
0198 regmap_reg_range(SX9360_REG_GNRL_CTRL0, SX9360_REG_GNRL_CTRL2),
0199 regmap_reg_range(SX9360_REG_AFE_CTRL1, SX9360_REG_AFE_PARAM1_PHM),
0200 regmap_reg_range(SX9360_REG_PROX_CTRL0_PHR, SX9360_REG_PROX_CTRL5),
0201 regmap_reg_range(SX9360_REG_REF_CORR0, SX9360_REG_REF_CORR1),
0202 regmap_reg_range(SX9360_REG_OFFSET_PMR_MSB, SX9360_REG_OFFSET_PMR_LSB),
0203 regmap_reg_range(SX9360_REG_RESET, SX9360_REG_RESET),
0204 };
0205
0206 static const struct regmap_access_table sx9360_writeable_regs = {
0207 .yes_ranges = sx9360_writable_reg_ranges,
0208 .n_yes_ranges = ARRAY_SIZE(sx9360_writable_reg_ranges),
0209 };
0210
0211
0212
0213
0214
0215 static const struct regmap_range sx9360_non_readable_reg_ranges[] = {
0216 regmap_reg_range(SX9360_REG_IRQ_CFG + 1, SX9360_REG_GNRL_CTRL0 - 1),
0217 regmap_reg_range(SX9360_REG_GNRL_CTRL2 + 1, SX9360_REG_AFE_CTRL1 - 1),
0218 regmap_reg_range(SX9360_REG_AFE_PARAM1_PHM + 1,
0219 SX9360_REG_PROX_CTRL0_PHR - 1),
0220 regmap_reg_range(SX9360_REG_PROX_CTRL5 + 1, SX9360_REG_REF_CORR0 - 1),
0221 regmap_reg_range(SX9360_REG_REF_CORR1 + 1,
0222 SX9360_REG_USEFUL_PHR_MSB - 1),
0223 regmap_reg_range(SX9360_REG_USE_FILTER_LSB + 1, SX9360_REG_RESET - 1),
0224 regmap_reg_range(SX9360_REG_RESET + 1, SX9360_REG_WHOAMI - 1),
0225 regmap_reg_range(SX9360_REG_WHOAMI + 1, SX9360_REG_REVISION - 1),
0226 };
0227
0228 static const struct regmap_access_table sx9360_readable_regs = {
0229 .no_ranges = sx9360_non_readable_reg_ranges,
0230 .n_no_ranges = ARRAY_SIZE(sx9360_non_readable_reg_ranges),
0231 };
0232
0233 static const struct regmap_range sx9360_volatile_reg_ranges[] = {
0234 regmap_reg_range(SX9360_REG_IRQ_SRC, SX9360_REG_STAT),
0235 regmap_reg_range(SX9360_REG_USEFUL_PHR_MSB, SX9360_REG_USE_FILTER_LSB),
0236 regmap_reg_range(SX9360_REG_WHOAMI, SX9360_REG_WHOAMI),
0237 regmap_reg_range(SX9360_REG_REVISION, SX9360_REG_REVISION),
0238 };
0239
0240 static const struct regmap_access_table sx9360_volatile_regs = {
0241 .yes_ranges = sx9360_volatile_reg_ranges,
0242 .n_yes_ranges = ARRAY_SIZE(sx9360_volatile_reg_ranges),
0243 };
0244
0245 static const struct regmap_config sx9360_regmap_config = {
0246 .reg_bits = 8,
0247 .val_bits = 8,
0248
0249 .max_register = SX9360_REG_REVISION,
0250 .cache_type = REGCACHE_RBTREE,
0251
0252 .wr_table = &sx9360_writeable_regs,
0253 .rd_table = &sx9360_readable_regs,
0254 .volatile_table = &sx9360_volatile_regs,
0255 };
0256
0257 static int sx9360_read_prox_data(struct sx_common_data *data,
0258 const struct iio_chan_spec *chan,
0259 __be16 *val)
0260 {
0261 return regmap_bulk_read(data->regmap, chan->address, val, sizeof(*val));
0262 }
0263
0264
0265
0266
0267
0268 static int sx9360_wait_for_sample(struct sx_common_data *data)
0269 {
0270 int ret;
0271 __be16 buf;
0272
0273 ret = regmap_bulk_read(data->regmap, SX9360_REG_GNRL_CTRL1,
0274 &buf, sizeof(buf));
0275 if (ret < 0)
0276 return ret;
0277 msleep(SX9360_REG_GNRL_REG_2_PERIOD_MS(be16_to_cpu(buf)));
0278
0279 return 0;
0280 }
0281
0282 static int sx9360_read_gain(struct sx_common_data *data,
0283 const struct iio_chan_spec *chan, int *val)
0284 {
0285 unsigned int reg, regval;
0286 int ret;
0287
0288 reg = SX9360_REG_PROX_CTRL0_PHR + chan->channel;
0289 ret = regmap_read(data->regmap, reg, ®val);
0290 if (ret)
0291 return ret;
0292
0293 *val = 1 << FIELD_GET(SX9360_REG_PROX_CTRL0_GAIN_MASK, regval);
0294
0295 return IIO_VAL_INT;
0296 }
0297
0298 static int sx9360_read_samp_freq(struct sx_common_data *data,
0299 int *val, int *val2)
0300 {
0301 int ret, divisor;
0302 __be16 buf;
0303
0304 ret = regmap_bulk_read(data->regmap, SX9360_REG_GNRL_CTRL1,
0305 &buf, sizeof(buf));
0306 if (ret < 0)
0307 return ret;
0308 divisor = be16_to_cpu(buf);
0309 if (divisor == 0) {
0310 *val = 0;
0311 return IIO_VAL_INT;
0312 }
0313
0314 *val = SX9360_FOSC_HZ;
0315 *val2 = divisor * 8192;
0316
0317 return IIO_VAL_FRACTIONAL;
0318 }
0319
0320 static int sx9360_read_raw(struct iio_dev *indio_dev,
0321 const struct iio_chan_spec *chan,
0322 int *val, int *val2, long mask)
0323 {
0324 struct sx_common_data *data = iio_priv(indio_dev);
0325 int ret;
0326
0327 switch (mask) {
0328 case IIO_CHAN_INFO_RAW:
0329 ret = iio_device_claim_direct_mode(indio_dev);
0330 if (ret)
0331 return ret;
0332
0333 ret = sx_common_read_proximity(data, chan, val);
0334 iio_device_release_direct_mode(indio_dev);
0335 return ret;
0336 case IIO_CHAN_INFO_HARDWAREGAIN:
0337 ret = iio_device_claim_direct_mode(indio_dev);
0338 if (ret)
0339 return ret;
0340
0341 ret = sx9360_read_gain(data, chan, val);
0342 iio_device_release_direct_mode(indio_dev);
0343 return ret;
0344 case IIO_CHAN_INFO_SAMP_FREQ:
0345 return sx9360_read_samp_freq(data, val, val2);
0346 default:
0347 return -EINVAL;
0348 }
0349 }
0350
0351 static const char *sx9360_channel_labels[SX9360_NUM_CHANNELS] = {
0352 "reference", "main",
0353 };
0354
0355 static int sx9360_read_label(struct iio_dev *iio_dev, const struct iio_chan_spec *chan,
0356 char *label)
0357 {
0358 return sysfs_emit(label, "%s\n", sx9360_channel_labels[chan->channel]);
0359 }
0360
0361 static const int sx9360_gain_vals[] = { 1, 2, 4, 8 };
0362
0363 static int sx9360_read_avail(struct iio_dev *indio_dev,
0364 struct iio_chan_spec const *chan,
0365 const int **vals, int *type, int *length,
0366 long mask)
0367 {
0368 if (chan->type != IIO_PROXIMITY)
0369 return -EINVAL;
0370
0371 switch (mask) {
0372 case IIO_CHAN_INFO_HARDWAREGAIN:
0373 *type = IIO_VAL_INT;
0374 *length = ARRAY_SIZE(sx9360_gain_vals);
0375 *vals = sx9360_gain_vals;
0376 return IIO_AVAIL_LIST;
0377 case IIO_CHAN_INFO_SAMP_FREQ:
0378 *type = IIO_VAL_INT_PLUS_MICRO;
0379 *length = ARRAY_SIZE(sx9360_samp_freq_interval) * 2;
0380 *vals = (int *)sx9360_samp_freq_interval;
0381 return IIO_AVAIL_RANGE;
0382 default:
0383 return -EINVAL;
0384 }
0385 }
0386
0387 static int sx9360_set_samp_freq(struct sx_common_data *data,
0388 int val, int val2)
0389 {
0390 int ret, reg;
0391 __be16 buf;
0392
0393 reg = val * 8192 / SX9360_FOSC_HZ + val2 * 8192 / (SX9360_FOSC_MHZ);
0394 buf = cpu_to_be16(reg);
0395 mutex_lock(&data->mutex);
0396
0397 ret = regmap_bulk_write(data->regmap, SX9360_REG_GNRL_CTRL1, &buf,
0398 sizeof(buf));
0399
0400 mutex_unlock(&data->mutex);
0401
0402 return ret;
0403 }
0404
0405 static int sx9360_read_thresh(struct sx_common_data *data, int *val)
0406 {
0407 unsigned int regval;
0408 int ret;
0409
0410 ret = regmap_read(data->regmap, SX9360_REG_PROX_CTRL5, ®val);
0411 if (ret)
0412 return ret;
0413
0414 if (regval <= 1)
0415 *val = regval;
0416 else
0417 *val = (regval * regval) / 2;
0418
0419 return IIO_VAL_INT;
0420 }
0421
0422 static int sx9360_read_hysteresis(struct sx_common_data *data, int *val)
0423 {
0424 unsigned int regval, pthresh;
0425 int ret;
0426
0427 ret = sx9360_read_thresh(data, &pthresh);
0428 if (ret < 0)
0429 return ret;
0430
0431 ret = regmap_read(data->regmap, SX9360_REG_PROX_CTRL4, ®val);
0432 if (ret)
0433 return ret;
0434
0435 regval = FIELD_GET(SX9360_REG_PROX_CTRL4_HYST_MASK, regval);
0436 if (!regval)
0437 *val = 0;
0438 else
0439 *val = pthresh >> (5 - regval);
0440
0441 return IIO_VAL_INT;
0442 }
0443
0444 static int sx9360_read_far_debounce(struct sx_common_data *data, int *val)
0445 {
0446 unsigned int regval;
0447 int ret;
0448
0449 ret = regmap_read(data->regmap, SX9360_REG_PROX_CTRL4, ®val);
0450 if (ret)
0451 return ret;
0452
0453 regval = FIELD_GET(SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK, regval);
0454 if (regval)
0455 *val = 1 << regval;
0456 else
0457 *val = 0;
0458
0459 return IIO_VAL_INT;
0460 }
0461
0462 static int sx9360_read_close_debounce(struct sx_common_data *data, int *val)
0463 {
0464 unsigned int regval;
0465 int ret;
0466
0467 ret = regmap_read(data->regmap, SX9360_REG_PROX_CTRL4, ®val);
0468 if (ret)
0469 return ret;
0470
0471 regval = FIELD_GET(SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK, regval);
0472 if (regval)
0473 *val = 1 << regval;
0474 else
0475 *val = 0;
0476
0477 return IIO_VAL_INT;
0478 }
0479
0480 static int sx9360_read_event_val(struct iio_dev *indio_dev,
0481 const struct iio_chan_spec *chan,
0482 enum iio_event_type type,
0483 enum iio_event_direction dir,
0484 enum iio_event_info info, int *val, int *val2)
0485 {
0486 struct sx_common_data *data = iio_priv(indio_dev);
0487
0488 if (chan->type != IIO_PROXIMITY)
0489 return -EINVAL;
0490
0491 switch (info) {
0492 case IIO_EV_INFO_VALUE:
0493 return sx9360_read_thresh(data, val);
0494 case IIO_EV_INFO_PERIOD:
0495 switch (dir) {
0496 case IIO_EV_DIR_RISING:
0497 return sx9360_read_far_debounce(data, val);
0498 case IIO_EV_DIR_FALLING:
0499 return sx9360_read_close_debounce(data, val);
0500 default:
0501 return -EINVAL;
0502 }
0503 case IIO_EV_INFO_HYSTERESIS:
0504 return sx9360_read_hysteresis(data, val);
0505 default:
0506 return -EINVAL;
0507 }
0508 }
0509
0510 static int sx9360_write_thresh(struct sx_common_data *data, int _val)
0511 {
0512 unsigned int val = _val;
0513 int ret;
0514
0515 if (val >= 1)
0516 val = int_sqrt(2 * val);
0517
0518 if (val > 0xff)
0519 return -EINVAL;
0520
0521 mutex_lock(&data->mutex);
0522 ret = regmap_write(data->regmap, SX9360_REG_PROX_CTRL5, val);
0523 mutex_unlock(&data->mutex);
0524
0525 return ret;
0526 }
0527
0528 static int sx9360_write_hysteresis(struct sx_common_data *data, int _val)
0529 {
0530 unsigned int hyst, val = _val;
0531 int ret, pthresh;
0532
0533 ret = sx9360_read_thresh(data, &pthresh);
0534 if (ret < 0)
0535 return ret;
0536
0537 if (val == 0)
0538 hyst = 0;
0539 else if (val >= pthresh >> 2)
0540 hyst = 3;
0541 else if (val >= pthresh >> 3)
0542 hyst = 2;
0543 else if (val >= pthresh >> 4)
0544 hyst = 1;
0545 else
0546 return -EINVAL;
0547
0548 hyst = FIELD_PREP(SX9360_REG_PROX_CTRL4_HYST_MASK, hyst);
0549 mutex_lock(&data->mutex);
0550 ret = regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,
0551 SX9360_REG_PROX_CTRL4_HYST_MASK, hyst);
0552 mutex_unlock(&data->mutex);
0553
0554 return ret;
0555 }
0556
0557 static int sx9360_write_far_debounce(struct sx_common_data *data, int _val)
0558 {
0559 unsigned int regval, val = _val;
0560 int ret;
0561
0562 if (val > 0)
0563 val = ilog2(val);
0564 if (!FIELD_FIT(SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK, val))
0565 return -EINVAL;
0566
0567 regval = FIELD_PREP(SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK, val);
0568
0569 mutex_lock(&data->mutex);
0570 ret = regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,
0571 SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK,
0572 regval);
0573 mutex_unlock(&data->mutex);
0574
0575 return ret;
0576 }
0577
0578 static int sx9360_write_close_debounce(struct sx_common_data *data, int _val)
0579 {
0580 unsigned int regval, val = _val;
0581 int ret;
0582
0583 if (val > 0)
0584 val = ilog2(val);
0585 if (!FIELD_FIT(SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK, val))
0586 return -EINVAL;
0587
0588 regval = FIELD_PREP(SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK, val);
0589
0590 mutex_lock(&data->mutex);
0591 ret = regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,
0592 SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK,
0593 regval);
0594 mutex_unlock(&data->mutex);
0595
0596 return ret;
0597 }
0598
0599 static int sx9360_write_event_val(struct iio_dev *indio_dev,
0600 const struct iio_chan_spec *chan,
0601 enum iio_event_type type,
0602 enum iio_event_direction dir,
0603 enum iio_event_info info, int val, int val2)
0604 {
0605 struct sx_common_data *data = iio_priv(indio_dev);
0606
0607 if (chan->type != IIO_PROXIMITY)
0608 return -EINVAL;
0609
0610 switch (info) {
0611 case IIO_EV_INFO_VALUE:
0612 return sx9360_write_thresh(data, val);
0613 case IIO_EV_INFO_PERIOD:
0614 switch (dir) {
0615 case IIO_EV_DIR_RISING:
0616 return sx9360_write_far_debounce(data, val);
0617 case IIO_EV_DIR_FALLING:
0618 return sx9360_write_close_debounce(data, val);
0619 default:
0620 return -EINVAL;
0621 }
0622 case IIO_EV_INFO_HYSTERESIS:
0623 return sx9360_write_hysteresis(data, val);
0624 default:
0625 return -EINVAL;
0626 }
0627 }
0628
0629 static int sx9360_write_gain(struct sx_common_data *data,
0630 const struct iio_chan_spec *chan, int val)
0631 {
0632 unsigned int gain, reg;
0633 int ret;
0634
0635 gain = ilog2(val);
0636 reg = SX9360_REG_PROX_CTRL0_PHR + chan->channel;
0637 gain = FIELD_PREP(SX9360_REG_PROX_CTRL0_GAIN_MASK, gain);
0638
0639 mutex_lock(&data->mutex);
0640 ret = regmap_update_bits(data->regmap, reg,
0641 SX9360_REG_PROX_CTRL0_GAIN_MASK,
0642 gain);
0643 mutex_unlock(&data->mutex);
0644
0645 return ret;
0646 }
0647
0648 static int sx9360_write_raw(struct iio_dev *indio_dev,
0649 const struct iio_chan_spec *chan, int val, int val2,
0650 long mask)
0651 {
0652 struct sx_common_data *data = iio_priv(indio_dev);
0653
0654 switch (mask) {
0655 case IIO_CHAN_INFO_SAMP_FREQ:
0656 return sx9360_set_samp_freq(data, val, val2);
0657 case IIO_CHAN_INFO_HARDWAREGAIN:
0658 return sx9360_write_gain(data, chan, val);
0659 default:
0660 return -EINVAL;
0661 }
0662 }
0663
0664 static const struct sx_common_reg_default sx9360_default_regs[] = {
0665 { SX9360_REG_IRQ_MSK, 0x00 },
0666 { SX9360_REG_IRQ_CFG, 0x00 },
0667
0668
0669
0670
0671
0672 { SX9360_REG_GNRL_CTRL0, 0x00 },
0673 { SX9360_REG_GNRL_CTRL1, 0x00 },
0674 { SX9360_REG_GNRL_CTRL2, SX9360_REG_GNRL_CTRL2_PERIOD_102MS },
0675
0676 { SX9360_REG_AFE_CTRL1, SX9360_REG_AFE_CTRL1_RESFILTIN_0OHMS },
0677 { SX9360_REG_AFE_PARAM0_PHR, SX9360_REG_AFE_PARAM0_RSVD |
0678 SX9360_REG_AFE_PARAM0_RESOLUTION_128 },
0679 { SX9360_REG_AFE_PARAM1_PHR, SX9360_REG_AFE_PARAM1_AGAIN_PHM_6PF |
0680 SX9360_REG_AFE_PARAM1_FREQ_83_33HZ },
0681 { SX9360_REG_AFE_PARAM0_PHM, SX9360_REG_AFE_PARAM0_RSVD |
0682 SX9360_REG_AFE_PARAM0_RESOLUTION_128 },
0683 { SX9360_REG_AFE_PARAM1_PHM, SX9360_REG_AFE_PARAM1_AGAIN_PHM_6PF |
0684 SX9360_REG_AFE_PARAM1_FREQ_83_33HZ },
0685
0686 { SX9360_REG_PROX_CTRL0_PHR, SX9360_REG_PROX_CTRL0_GAIN_1 |
0687 SX9360_REG_PROX_CTRL0_RAWFILT_1P50 },
0688 { SX9360_REG_PROX_CTRL0_PHM, SX9360_REG_PROX_CTRL0_GAIN_1 |
0689 SX9360_REG_PROX_CTRL0_RAWFILT_1P50 },
0690 { SX9360_REG_PROX_CTRL1, SX9360_REG_PROX_CTRL1_AVGNEG_THRESH_16K },
0691 { SX9360_REG_PROX_CTRL2, SX9360_REG_PROX_CTRL2_AVGDEB_2SAMPLES |
0692 SX9360_REG_PROX_CTRL2_AVGPOS_THRESH_16K },
0693 { SX9360_REG_PROX_CTRL3, SX9360_REG_PROX_CTRL3_AVGNEG_FILT_2 |
0694 SX9360_REG_PROX_CTRL3_AVGPOS_FILT_256 },
0695 { SX9360_REG_PROX_CTRL4, 0x00 },
0696 { SX9360_REG_PROX_CTRL5, SX9360_REG_PROX_CTRL5_PROXTHRESH_32 },
0697 };
0698
0699
0700 static int sx9360_init_compensation(struct iio_dev *indio_dev)
0701 {
0702 struct sx_common_data *data = iio_priv(indio_dev);
0703 unsigned int val;
0704 int ret;
0705
0706
0707 ret = regmap_update_bits(data->regmap, SX9360_REG_STAT,
0708 SX9360_REG_STAT_COMPSTAT_MASK,
0709 SX9360_REG_STAT_COMPSTAT_MASK);
0710 if (ret)
0711 return ret;
0712
0713 return regmap_read_poll_timeout(data->regmap, SX9360_REG_STAT, val,
0714 !(val & SX9360_REG_STAT_COMPSTAT_MASK),
0715 20000, 2000000);
0716 }
0717
0718 static const struct sx_common_reg_default *
0719 sx9360_get_default_reg(struct device *dev, int idx,
0720 struct sx_common_reg_default *reg_def)
0721 {
0722 u32 raw = 0, pos = 0;
0723 int ret;
0724
0725 memcpy(reg_def, &sx9360_default_regs[idx], sizeof(*reg_def));
0726 switch (reg_def->reg) {
0727 case SX9360_REG_AFE_CTRL1:
0728 ret = device_property_read_u32(dev,
0729 "semtech,input-precharge-resistor-ohms",
0730 &raw);
0731 if (ret)
0732 break;
0733
0734 reg_def->def &= ~SX9360_REG_AFE_CTRL1_RESFILTIN_MASK;
0735 reg_def->def |= FIELD_PREP(SX9360_REG_AFE_CTRL1_RESFILTIN_MASK,
0736 raw / 2000);
0737 break;
0738 case SX9360_REG_AFE_PARAM0_PHR:
0739 case SX9360_REG_AFE_PARAM0_PHM:
0740 ret = device_property_read_u32(dev, "semtech,resolution", &raw);
0741 if (ret)
0742 break;
0743
0744 raw = ilog2(raw) - 3;
0745
0746 reg_def->def &= ~SX9360_REG_AFE_PARAM0_RESOLUTION_MASK;
0747 reg_def->def |= FIELD_PREP(SX9360_REG_AFE_PARAM0_RESOLUTION_MASK, raw);
0748 break;
0749 case SX9360_REG_PROX_CTRL0_PHR:
0750 case SX9360_REG_PROX_CTRL0_PHM:
0751 ret = device_property_read_u32(dev, "semtech,proxraw-strength", &raw);
0752 if (ret)
0753 break;
0754
0755 reg_def->def &= ~SX9360_REG_PROX_CTRL0_RAWFILT_MASK;
0756 reg_def->def |= FIELD_PREP(SX9360_REG_PROX_CTRL0_RAWFILT_MASK, raw);
0757 break;
0758 case SX9360_REG_PROX_CTRL3:
0759 ret = device_property_read_u32(dev, "semtech,avg-pos-strength",
0760 &pos);
0761 if (ret)
0762 break;
0763
0764
0765 raw = clamp(ilog2(pos), 3, 11) - (pos >= 32 ? 4 : 3);
0766 reg_def->def &= ~SX9360_REG_PROX_CTRL3_AVGPOS_FILT_MASK;
0767 reg_def->def |= FIELD_PREP(SX9360_REG_PROX_CTRL3_AVGPOS_FILT_MASK, raw);
0768 break;
0769 }
0770
0771 return reg_def;
0772 }
0773
0774 static int sx9360_check_whoami(struct device *dev, struct iio_dev *indio_dev)
0775 {
0776
0777
0778
0779
0780 indio_dev->name = "sx9360";
0781 return 0;
0782 }
0783
0784 static const struct sx_common_chip_info sx9360_chip_info = {
0785 .reg_stat = SX9360_REG_STAT,
0786 .reg_irq_msk = SX9360_REG_IRQ_MSK,
0787 .reg_enable_chan = SX9360_REG_GNRL_CTRL0,
0788 .reg_reset = SX9360_REG_RESET,
0789
0790 .mask_enable_chan = SX9360_REG_GNRL_CTRL0_PHEN_MASK,
0791 .stat_offset = 2,
0792 .num_channels = SX9360_NUM_CHANNELS,
0793 .num_default_regs = ARRAY_SIZE(sx9360_default_regs),
0794
0795 .ops = {
0796 .read_prox_data = sx9360_read_prox_data,
0797 .check_whoami = sx9360_check_whoami,
0798 .init_compensation = sx9360_init_compensation,
0799 .wait_for_sample = sx9360_wait_for_sample,
0800 .get_default_reg = sx9360_get_default_reg,
0801 },
0802
0803 .iio_channels = sx9360_channels,
0804 .num_iio_channels = ARRAY_SIZE(sx9360_channels),
0805 .iio_info = {
0806 .read_raw = sx9360_read_raw,
0807 .read_avail = sx9360_read_avail,
0808 .read_label = sx9360_read_label,
0809 .read_event_value = sx9360_read_event_val,
0810 .write_event_value = sx9360_write_event_val,
0811 .write_raw = sx9360_write_raw,
0812 .read_event_config = sx_common_read_event_config,
0813 .write_event_config = sx_common_write_event_config,
0814 },
0815 };
0816
0817 static int sx9360_probe(struct i2c_client *client)
0818 {
0819 return sx_common_probe(client, &sx9360_chip_info, &sx9360_regmap_config);
0820 }
0821
0822 static int __maybe_unused sx9360_suspend(struct device *dev)
0823 {
0824 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
0825 unsigned int regval;
0826 int ret;
0827
0828 disable_irq_nosync(data->client->irq);
0829
0830 mutex_lock(&data->mutex);
0831 ret = regmap_read(data->regmap, SX9360_REG_GNRL_CTRL0, ®val);
0832
0833 data->suspend_ctrl =
0834 FIELD_GET(SX9360_REG_GNRL_CTRL0_PHEN_MASK, regval);
0835
0836 if (ret < 0)
0837 goto out;
0838
0839
0840 ret = regmap_write(data->regmap, SX9360_REG_GNRL_CTRL0, 0);
0841
0842 out:
0843 mutex_unlock(&data->mutex);
0844 return ret;
0845 }
0846
0847 static int __maybe_unused sx9360_resume(struct device *dev)
0848 {
0849 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
0850 int ret;
0851
0852 mutex_lock(&data->mutex);
0853 ret = regmap_update_bits(data->regmap, SX9360_REG_GNRL_CTRL0,
0854 SX9360_REG_GNRL_CTRL0_PHEN_MASK,
0855 data->suspend_ctrl);
0856 mutex_unlock(&data->mutex);
0857 if (ret)
0858 return ret;
0859
0860 enable_irq(data->client->irq);
0861 return 0;
0862 }
0863
0864 static SIMPLE_DEV_PM_OPS(sx9360_pm_ops, sx9360_suspend, sx9360_resume);
0865
0866 static const struct acpi_device_id sx9360_acpi_match[] = {
0867 { "STH9360", SX9360_WHOAMI_VALUE },
0868 { }
0869 };
0870 MODULE_DEVICE_TABLE(acpi, sx9360_acpi_match);
0871
0872 static const struct of_device_id sx9360_of_match[] = {
0873 { .compatible = "semtech,sx9360", (void *)SX9360_WHOAMI_VALUE },
0874 { }
0875 };
0876 MODULE_DEVICE_TABLE(of, sx9360_of_match);
0877
0878 static const struct i2c_device_id sx9360_id[] = {
0879 {"sx9360", SX9360_WHOAMI_VALUE },
0880 { }
0881 };
0882 MODULE_DEVICE_TABLE(i2c, sx9360_id);
0883
0884 static struct i2c_driver sx9360_driver = {
0885 .driver = {
0886 .name = "sx9360",
0887 .acpi_match_table = sx9360_acpi_match,
0888 .of_match_table = sx9360_of_match,
0889 .pm = &sx9360_pm_ops,
0890
0891
0892
0893
0894
0895
0896 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0897 },
0898 .probe_new = sx9360_probe,
0899 .id_table = sx9360_id,
0900 };
0901 module_i2c_driver(sx9360_driver);
0902
0903 MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
0904 MODULE_DESCRIPTION("Driver for Semtech SX9360 proximity sensor");
0905 MODULE_LICENSE("GPL v2");
0906 MODULE_IMPORT_NS(SEMTECH_PROX);