iio: proximity: as3935: noise detection + threshold changes

Most applications are too noisy to allow the default noise and
watchdog settings, and thus need to be configurable via DT
properties.

Also default settings to POR defaults on a reset, and register
distuber interrupts as noise since it prevents proper usage.

Cc: devicetree@vger.kernel.org
Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by Matt Ranostay and committed by Jonathan Cameron eb35279d b2e31206

+53 -3
+8
Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
··· 14 Show or set the gain boost of the amp, from 0-31 range. 15 18 = indoors (default) 16 14 = outdoors
··· 14 Show or set the gain boost of the amp, from 0-31 range. 15 18 = indoors (default) 16 14 = outdoors 17 + 18 + What /sys/bus/iio/devices/iio:deviceX/noise_level_tripped 19 + Date: May 2017 20 + KernelVersion: 4.13 21 + Contact: Matt Ranostay <matt.ranostay@konsulko.com> 22 + Description: 23 + When 1 the noise level is over the trip level and not reporting 24 + valid data
+5
Documentation/devicetree/bindings/iio/proximity/as3935.txt
··· 16 - ams,tuning-capacitor-pf: Calibration tuning capacitor stepping 17 value 0 - 120pF. This will require using the calibration data from 18 the manufacturer. 19 20 Example: 21 ··· 31 interrupt-parent = <&gpio1>; 32 interrupts = <16 1>; 33 ams,tuning-capacitor-pf = <80>; 34 };
··· 16 - ams,tuning-capacitor-pf: Calibration tuning capacitor stepping 17 value 0 - 120pF. This will require using the calibration data from 18 the manufacturer. 19 + - ams,nflwdth: Set the noise and watchdog threshold register on 20 + startup. This will need to set according to the noise from the 21 + MCU board, and possibly the local environment. Refer to the 22 + datasheet for the threshold settings. 23 24 Example: 25 ··· 27 interrupt-parent = <&gpio1>; 28 interrupts = <16 1>; 29 ams,tuning-capacitor-pf = <80>; 30 + ams,nflwdth = <0x44>; 31 };
+40 -3
drivers/iio/proximity/as3935.c
··· 39 #define AS3935_AFE_GAIN_MAX 0x1F 40 #define AS3935_AFE_PWR_BIT BIT(0) 41 42 #define AS3935_INT 0x03 43 #define AS3935_INT_MASK 0x0f 44 #define AS3935_EVENT_INT BIT(3) 45 #define AS3935_NOISE_INT BIT(0) 46 ··· 52 #define AS3935_DATA_MASK 0x3F 53 54 #define AS3935_TUNE_CAP 0x08 55 #define AS3935_CALIBRATE 0x3D 56 57 #define AS3935_READ_DATA BIT(14) ··· 67 struct mutex lock; 68 struct delayed_work work; 69 70 u32 tune_cap; 71 u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ 72 u8 buf[2] ____cacheline_aligned; 73 }; ··· 152 return len; 153 } 154 155 static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, 156 as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0); 157 158 159 static struct attribute *as3935_attributes[] = { 160 &iio_dev_attr_sensor_sensitivity.dev_attr.attr, 161 NULL, 162 }; 163 ··· 270 case AS3935_EVENT_INT: 271 iio_trigger_poll_chained(st->trig); 272 break; 273 case AS3935_NOISE_INT: 274 dev_warn(&st->spi->dev, "noise level is too high\n"); 275 break; 276 } ··· 297 298 static void calibrate_as3935(struct as3935_state *st) 299 { 300 - /* mask disturber interrupt bit */ 301 - as3935_write(st, AS3935_INT, BIT(5)); 302 - 303 as3935_write(st, AS3935_CALIBRATE, 0x96); 304 as3935_write(st, AS3935_TUNE_CAP, 305 BIT(5) | (st->tune_cap / TUNE_CAP_DIV)); 306 307 mdelay(2); 308 as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); 309 } 310 311 #ifdef CONFIG_PM_SLEEP ··· 397 return -EINVAL; 398 } 399 400 indio_dev->dev.parent = &spi->dev; 401 indio_dev->name = spi_get_device_id(spi)->name; 402 indio_dev->channels = as3935_channels; ··· 420 return -ENOMEM; 421 422 st->trig = trig; 423 trig->dev.parent = indio_dev->dev.parent; 424 iio_trigger_set_drvdata(trig, indio_dev); 425 trig->ops = &iio_interrupt_trigger_ops;
··· 39 #define AS3935_AFE_GAIN_MAX 0x1F 40 #define AS3935_AFE_PWR_BIT BIT(0) 41 42 + #define AS3935_NFLWDTH 0x01 43 + #define AS3935_NFLWDTH_MASK 0x7f 44 + 45 #define AS3935_INT 0x03 46 #define AS3935_INT_MASK 0x0f 47 + #define AS3935_DISTURB_INT BIT(2) 48 #define AS3935_EVENT_INT BIT(3) 49 #define AS3935_NOISE_INT BIT(0) 50 ··· 48 #define AS3935_DATA_MASK 0x3F 49 50 #define AS3935_TUNE_CAP 0x08 51 + #define AS3935_DEFAULTS 0x3C 52 #define AS3935_CALIBRATE 0x3D 53 54 #define AS3935_READ_DATA BIT(14) ··· 62 struct mutex lock; 63 struct delayed_work work; 64 65 + unsigned long noise_tripped; 66 u32 tune_cap; 67 + u32 nflwdth_reg; 68 u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ 69 u8 buf[2] ____cacheline_aligned; 70 }; ··· 145 return len; 146 } 147 148 + static ssize_t as3935_noise_level_tripped_show(struct device *dev, 149 + struct device_attribute *attr, 150 + char *buf) 151 + { 152 + struct as3935_state *st = iio_priv(dev_to_iio_dev(dev)); 153 + int ret; 154 + 155 + mutex_lock(&st->lock); 156 + ret = sprintf(buf, "%d\n", !time_after(jiffies, st->noise_tripped + HZ)); 157 + mutex_unlock(&st->lock); 158 + 159 + return ret; 160 + } 161 + 162 static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, 163 as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0); 164 165 + static IIO_DEVICE_ATTR(noise_level_tripped, S_IRUGO, 166 + as3935_noise_level_tripped_show, NULL, 0); 167 168 static struct attribute *as3935_attributes[] = { 169 &iio_dev_attr_sensor_sensitivity.dev_attr.attr, 170 + &iio_dev_attr_noise_level_tripped.dev_attr.attr, 171 NULL, 172 }; 173 ··· 246 case AS3935_EVENT_INT: 247 iio_trigger_poll_chained(st->trig); 248 break; 249 + case AS3935_DISTURB_INT: 250 case AS3935_NOISE_INT: 251 + mutex_lock(&st->lock); 252 + st->noise_tripped = jiffies; 253 + mutex_unlock(&st->lock); 254 dev_warn(&st->spi->dev, "noise level is too high\n"); 255 break; 256 } ··· 269 270 static void calibrate_as3935(struct as3935_state *st) 271 { 272 + as3935_write(st, AS3935_DEFAULTS, 0x96); 273 as3935_write(st, AS3935_CALIBRATE, 0x96); 274 as3935_write(st, AS3935_TUNE_CAP, 275 BIT(5) | (st->tune_cap / TUNE_CAP_DIV)); 276 277 mdelay(2); 278 as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); 279 + as3935_write(st, AS3935_NFLWDTH, st->nflwdth_reg); 280 } 281 282 #ifdef CONFIG_PM_SLEEP ··· 370 return -EINVAL; 371 } 372 373 + ret = of_property_read_u32(np, 374 + "ams,nflwdth", &st->nflwdth_reg); 375 + if (!ret && st->nflwdth_reg > AS3935_NFLWDTH_MASK) { 376 + dev_err(&spi->dev, 377 + "invalid nflwdth setting of %d\n", 378 + st->nflwdth_reg); 379 + return -EINVAL; 380 + } 381 + 382 indio_dev->dev.parent = &spi->dev; 383 indio_dev->name = spi_get_device_id(spi)->name; 384 indio_dev->channels = as3935_channels; ··· 384 return -ENOMEM; 385 386 st->trig = trig; 387 + st->noise_tripped = jiffies - HZ; 388 trig->dev.parent = indio_dev->dev.parent; 389 iio_trigger_set_drvdata(trig, indio_dev); 390 trig->ops = &iio_interrupt_trigger_ops;