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 14 Show or set the gain boost of the amp, from 0-31 range. 15 15 18 = indoors (default) 16 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 16 - ams,tuning-capacitor-pf: Calibration tuning capacitor stepping 17 17 value 0 - 120pF. This will require using the calibration data from 18 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. 19 23 20 24 Example: 21 25 ··· 31 27 interrupt-parent = <&gpio1>; 32 28 interrupts = <16 1>; 33 29 ams,tuning-capacitor-pf = <80>; 30 + ams,nflwdth = <0x44>; 34 31 };
+40 -3
drivers/iio/proximity/as3935.c
··· 39 39 #define AS3935_AFE_GAIN_MAX 0x1F 40 40 #define AS3935_AFE_PWR_BIT BIT(0) 41 41 42 + #define AS3935_NFLWDTH 0x01 43 + #define AS3935_NFLWDTH_MASK 0x7f 44 + 42 45 #define AS3935_INT 0x03 43 46 #define AS3935_INT_MASK 0x0f 47 + #define AS3935_DISTURB_INT BIT(2) 44 48 #define AS3935_EVENT_INT BIT(3) 45 49 #define AS3935_NOISE_INT BIT(0) 46 50 ··· 52 48 #define AS3935_DATA_MASK 0x3F 53 49 54 50 #define AS3935_TUNE_CAP 0x08 51 + #define AS3935_DEFAULTS 0x3C 55 52 #define AS3935_CALIBRATE 0x3D 56 53 57 54 #define AS3935_READ_DATA BIT(14) ··· 67 62 struct mutex lock; 68 63 struct delayed_work work; 69 64 65 + unsigned long noise_tripped; 70 66 u32 tune_cap; 67 + u32 nflwdth_reg; 71 68 u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ 72 69 u8 buf[2] ____cacheline_aligned; 73 70 }; ··· 152 145 return len; 153 146 } 154 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 + 155 162 static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, 156 163 as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0); 157 164 165 + static IIO_DEVICE_ATTR(noise_level_tripped, S_IRUGO, 166 + as3935_noise_level_tripped_show, NULL, 0); 158 167 159 168 static struct attribute *as3935_attributes[] = { 160 169 &iio_dev_attr_sensor_sensitivity.dev_attr.attr, 170 + &iio_dev_attr_noise_level_tripped.dev_attr.attr, 161 171 NULL, 162 172 }; 163 173 ··· 270 246 case AS3935_EVENT_INT: 271 247 iio_trigger_poll_chained(st->trig); 272 248 break; 249 + case AS3935_DISTURB_INT: 273 250 case AS3935_NOISE_INT: 251 + mutex_lock(&st->lock); 252 + st->noise_tripped = jiffies; 253 + mutex_unlock(&st->lock); 274 254 dev_warn(&st->spi->dev, "noise level is too high\n"); 275 255 break; 276 256 } ··· 297 269 298 270 static void calibrate_as3935(struct as3935_state *st) 299 271 { 300 - /* mask disturber interrupt bit */ 301 - as3935_write(st, AS3935_INT, BIT(5)); 302 - 272 + as3935_write(st, AS3935_DEFAULTS, 0x96); 303 273 as3935_write(st, AS3935_CALIBRATE, 0x96); 304 274 as3935_write(st, AS3935_TUNE_CAP, 305 275 BIT(5) | (st->tune_cap / TUNE_CAP_DIV)); 306 276 307 277 mdelay(2); 308 278 as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); 279 + as3935_write(st, AS3935_NFLWDTH, st->nflwdth_reg); 309 280 } 310 281 311 282 #ifdef CONFIG_PM_SLEEP ··· 397 370 return -EINVAL; 398 371 } 399 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 + 400 382 indio_dev->dev.parent = &spi->dev; 401 383 indio_dev->name = spi_get_device_id(spi)->name; 402 384 indio_dev->channels = as3935_channels; ··· 420 384 return -ENOMEM; 421 385 422 386 st->trig = trig; 387 + st->noise_tripped = jiffies - HZ; 423 388 trig->dev.parent = indio_dev->dev.parent; 424 389 iio_trigger_set_drvdata(trig, indio_dev); 425 390 trig->ops = &iio_interrupt_trigger_ops;