Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * as3935.c - Support for AS3935 Franklin lightning sensor
0004  *
0005  * Copyright (C) 2014, 2017-2018
0006  * Author: Matt Ranostay <matt.ranostay@konsulko.com>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/mod_devicetable.h>
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/delay.h>
0014 #include <linux/workqueue.h>
0015 #include <linux/devm-helpers.h>
0016 #include <linux/mutex.h>
0017 #include <linux/err.h>
0018 #include <linux/irq.h>
0019 #include <linux/spi/spi.h>
0020 #include <linux/iio/iio.h>
0021 #include <linux/iio/sysfs.h>
0022 #include <linux/iio/trigger.h>
0023 #include <linux/iio/trigger_consumer.h>
0024 #include <linux/iio/buffer.h>
0025 #include <linux/iio/triggered_buffer.h>
0026 
0027 #define AS3935_AFE_GAIN     0x00
0028 #define AS3935_AFE_MASK     0x3F
0029 #define AS3935_AFE_GAIN_MAX 0x1F
0030 #define AS3935_AFE_PWR_BIT  BIT(0)
0031 
0032 #define AS3935_NFLWDTH      0x01
0033 #define AS3935_NFLWDTH_MASK 0x7f
0034 
0035 #define AS3935_INT      0x03
0036 #define AS3935_INT_MASK     0x0f
0037 #define AS3935_DISTURB_INT  BIT(2)
0038 #define AS3935_EVENT_INT    BIT(3)
0039 #define AS3935_NOISE_INT    BIT(0)
0040 
0041 #define AS3935_DATA     0x07
0042 #define AS3935_DATA_MASK    0x3F
0043 
0044 #define AS3935_TUNE_CAP     0x08
0045 #define AS3935_DEFAULTS     0x3C
0046 #define AS3935_CALIBRATE    0x3D
0047 
0048 #define AS3935_READ_DATA    BIT(14)
0049 #define AS3935_ADDRESS(x)   ((x) << 8)
0050 
0051 #define MAX_PF_CAP      120
0052 #define TUNE_CAP_DIV        8
0053 
0054 struct as3935_state {
0055     struct spi_device *spi;
0056     struct iio_trigger *trig;
0057     struct mutex lock;
0058     struct delayed_work work;
0059 
0060     unsigned long noise_tripped;
0061     u32 tune_cap;
0062     u32 nflwdth_reg;
0063     /* Ensure timestamp is naturally aligned */
0064     struct {
0065         u8 chan;
0066         s64 timestamp __aligned(8);
0067     } scan;
0068     u8 buf[2] __aligned(IIO_DMA_MINALIGN);
0069 };
0070 
0071 static const struct iio_chan_spec as3935_channels[] = {
0072     {
0073         .type           = IIO_PROXIMITY,
0074         .info_mask_separate =
0075             BIT(IIO_CHAN_INFO_RAW) |
0076             BIT(IIO_CHAN_INFO_PROCESSED) |
0077             BIT(IIO_CHAN_INFO_SCALE),
0078         .scan_index     = 0,
0079         .scan_type = {
0080             .sign           = 'u',
0081             .realbits       = 6,
0082             .storagebits    = 8,
0083         },
0084     },
0085     IIO_CHAN_SOFT_TIMESTAMP(1),
0086 };
0087 
0088 static int as3935_read(struct as3935_state *st, unsigned int reg, int *val)
0089 {
0090     u8 cmd;
0091     int ret;
0092 
0093     cmd = (AS3935_READ_DATA | AS3935_ADDRESS(reg)) >> 8;
0094     ret = spi_w8r8(st->spi, cmd);
0095     if (ret < 0)
0096         return ret;
0097     *val = ret;
0098 
0099     return 0;
0100 }
0101 
0102 static int as3935_write(struct as3935_state *st,
0103                 unsigned int reg,
0104                 unsigned int val)
0105 {
0106     u8 *buf = st->buf;
0107 
0108     buf[0] = AS3935_ADDRESS(reg) >> 8;
0109     buf[1] = val;
0110 
0111     return spi_write(st->spi, buf, 2);
0112 }
0113 
0114 static ssize_t as3935_sensor_sensitivity_show(struct device *dev,
0115                     struct device_attribute *attr,
0116                     char *buf)
0117 {
0118     struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
0119     int val, ret;
0120 
0121     ret = as3935_read(st, AS3935_AFE_GAIN, &val);
0122     if (ret)
0123         return ret;
0124     val = (val & AS3935_AFE_MASK) >> 1;
0125 
0126     return sysfs_emit(buf, "%d\n", val);
0127 }
0128 
0129 static ssize_t as3935_sensor_sensitivity_store(struct device *dev,
0130                     struct device_attribute *attr,
0131                     const char *buf, size_t len)
0132 {
0133     struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
0134     unsigned long val;
0135     int ret;
0136 
0137     ret = kstrtoul(buf, 10, &val);
0138     if (ret)
0139         return -EINVAL;
0140 
0141     if (val > AS3935_AFE_GAIN_MAX)
0142         return -EINVAL;
0143 
0144     as3935_write(st, AS3935_AFE_GAIN, val << 1);
0145 
0146     return len;
0147 }
0148 
0149 static ssize_t as3935_noise_level_tripped_show(struct device *dev,
0150                     struct device_attribute *attr,
0151                     char *buf)
0152 {
0153     struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
0154     int ret;
0155 
0156     mutex_lock(&st->lock);
0157     ret = sysfs_emit(buf, "%d\n", !time_after(jiffies, st->noise_tripped + HZ));
0158     mutex_unlock(&st->lock);
0159 
0160     return ret;
0161 }
0162 
0163 static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
0164     as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0);
0165 
0166 static IIO_DEVICE_ATTR(noise_level_tripped, S_IRUGO,
0167     as3935_noise_level_tripped_show, NULL, 0);
0168 
0169 static struct attribute *as3935_attributes[] = {
0170     &iio_dev_attr_sensor_sensitivity.dev_attr.attr,
0171     &iio_dev_attr_noise_level_tripped.dev_attr.attr,
0172     NULL,
0173 };
0174 
0175 static const struct attribute_group as3935_attribute_group = {
0176     .attrs = as3935_attributes,
0177 };
0178 
0179 static int as3935_read_raw(struct iio_dev *indio_dev,
0180                struct iio_chan_spec const *chan,
0181                int *val,
0182                int *val2,
0183                long m)
0184 {
0185     struct as3935_state *st = iio_priv(indio_dev);
0186     int ret;
0187 
0188 
0189     switch (m) {
0190     case IIO_CHAN_INFO_PROCESSED:
0191     case IIO_CHAN_INFO_RAW:
0192         *val2 = 0;
0193         ret = as3935_read(st, AS3935_DATA, val);
0194         if (ret)
0195             return ret;
0196 
0197         /* storm out of range */
0198         if (*val == AS3935_DATA_MASK)
0199             return -EINVAL;
0200 
0201         if (m == IIO_CHAN_INFO_RAW)
0202             return IIO_VAL_INT;
0203 
0204         if (m == IIO_CHAN_INFO_PROCESSED)
0205             *val *= 1000;
0206         break;
0207     case IIO_CHAN_INFO_SCALE:
0208         *val = 1000;
0209         break;
0210     default:
0211         return -EINVAL;
0212     }
0213 
0214     return IIO_VAL_INT;
0215 }
0216 
0217 static const struct iio_info as3935_info = {
0218     .attrs = &as3935_attribute_group,
0219     .read_raw = &as3935_read_raw,
0220 };
0221 
0222 static irqreturn_t as3935_trigger_handler(int irq, void *private)
0223 {
0224     struct iio_poll_func *pf = private;
0225     struct iio_dev *indio_dev = pf->indio_dev;
0226     struct as3935_state *st = iio_priv(indio_dev);
0227     int val, ret;
0228 
0229     ret = as3935_read(st, AS3935_DATA, &val);
0230     if (ret)
0231         goto err_read;
0232 
0233     st->scan.chan = val & AS3935_DATA_MASK;
0234     iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
0235                        iio_get_time_ns(indio_dev));
0236 err_read:
0237     iio_trigger_notify_done(indio_dev->trig);
0238 
0239     return IRQ_HANDLED;
0240 }
0241 
0242 static void as3935_event_work(struct work_struct *work)
0243 {
0244     struct as3935_state *st;
0245     int val;
0246     int ret;
0247 
0248     st = container_of(work, struct as3935_state, work.work);
0249 
0250     ret = as3935_read(st, AS3935_INT, &val);
0251     if (ret) {
0252         dev_warn(&st->spi->dev, "read error\n");
0253         return;
0254     }
0255 
0256     val &= AS3935_INT_MASK;
0257 
0258     switch (val) {
0259     case AS3935_EVENT_INT:
0260         iio_trigger_poll_chained(st->trig);
0261         break;
0262     case AS3935_DISTURB_INT:
0263     case AS3935_NOISE_INT:
0264         mutex_lock(&st->lock);
0265         st->noise_tripped = jiffies;
0266         mutex_unlock(&st->lock);
0267         dev_warn(&st->spi->dev, "noise level is too high\n");
0268         break;
0269     }
0270 }
0271 
0272 static irqreturn_t as3935_interrupt_handler(int irq, void *private)
0273 {
0274     struct iio_dev *indio_dev = private;
0275     struct as3935_state *st = iio_priv(indio_dev);
0276 
0277     /*
0278      * Delay work for >2 milliseconds after an interrupt to allow
0279      * estimated distance to recalculated.
0280      */
0281 
0282     schedule_delayed_work(&st->work, msecs_to_jiffies(3));
0283 
0284     return IRQ_HANDLED;
0285 }
0286 
0287 static void calibrate_as3935(struct as3935_state *st)
0288 {
0289     as3935_write(st, AS3935_DEFAULTS, 0x96);
0290     as3935_write(st, AS3935_CALIBRATE, 0x96);
0291     as3935_write(st, AS3935_TUNE_CAP,
0292         BIT(5) | (st->tune_cap / TUNE_CAP_DIV));
0293 
0294     mdelay(2);
0295     as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
0296     as3935_write(st, AS3935_NFLWDTH, st->nflwdth_reg);
0297 }
0298 
0299 static int as3935_suspend(struct device *dev)
0300 {
0301     struct iio_dev *indio_dev = dev_get_drvdata(dev);
0302     struct as3935_state *st = iio_priv(indio_dev);
0303     int val, ret;
0304 
0305     mutex_lock(&st->lock);
0306     ret = as3935_read(st, AS3935_AFE_GAIN, &val);
0307     if (ret)
0308         goto err_suspend;
0309     val |= AS3935_AFE_PWR_BIT;
0310 
0311     ret = as3935_write(st, AS3935_AFE_GAIN, val);
0312 
0313 err_suspend:
0314     mutex_unlock(&st->lock);
0315 
0316     return ret;
0317 }
0318 
0319 static int as3935_resume(struct device *dev)
0320 {
0321     struct iio_dev *indio_dev = dev_get_drvdata(dev);
0322     struct as3935_state *st = iio_priv(indio_dev);
0323     int val, ret;
0324 
0325     mutex_lock(&st->lock);
0326     ret = as3935_read(st, AS3935_AFE_GAIN, &val);
0327     if (ret)
0328         goto err_resume;
0329     val &= ~AS3935_AFE_PWR_BIT;
0330     ret = as3935_write(st, AS3935_AFE_GAIN, val);
0331 
0332     calibrate_as3935(st);
0333 
0334 err_resume:
0335     mutex_unlock(&st->lock);
0336 
0337     return ret;
0338 }
0339 
0340 static DEFINE_SIMPLE_DEV_PM_OPS(as3935_pm_ops, as3935_suspend, as3935_resume);
0341 
0342 static int as3935_probe(struct spi_device *spi)
0343 {
0344     struct device *dev = &spi->dev;
0345     struct iio_dev *indio_dev;
0346     struct iio_trigger *trig;
0347     struct as3935_state *st;
0348     int ret;
0349 
0350     /* Be sure lightning event interrupt is specified */
0351     if (!spi->irq) {
0352         dev_err(dev, "unable to get event interrupt\n");
0353         return -EINVAL;
0354     }
0355 
0356     indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
0357     if (!indio_dev)
0358         return -ENOMEM;
0359 
0360     st = iio_priv(indio_dev);
0361     st->spi = spi;
0362 
0363     spi_set_drvdata(spi, indio_dev);
0364     mutex_init(&st->lock);
0365 
0366     ret = device_property_read_u32(dev,
0367             "ams,tuning-capacitor-pf", &st->tune_cap);
0368     if (ret) {
0369         st->tune_cap = 0;
0370         dev_warn(dev, "no tuning-capacitor-pf set, defaulting to %d",
0371             st->tune_cap);
0372     }
0373 
0374     if (st->tune_cap > MAX_PF_CAP) {
0375         dev_err(dev, "wrong tuning-capacitor-pf setting of %d\n",
0376             st->tune_cap);
0377         return -EINVAL;
0378     }
0379 
0380     ret = device_property_read_u32(dev,
0381             "ams,nflwdth", &st->nflwdth_reg);
0382     if (!ret && st->nflwdth_reg > AS3935_NFLWDTH_MASK) {
0383         dev_err(dev, "invalid nflwdth setting of %d\n",
0384             st->nflwdth_reg);
0385         return -EINVAL;
0386     }
0387 
0388     indio_dev->name = spi_get_device_id(spi)->name;
0389     indio_dev->channels = as3935_channels;
0390     indio_dev->num_channels = ARRAY_SIZE(as3935_channels);
0391     indio_dev->modes = INDIO_DIRECT_MODE;
0392     indio_dev->info = &as3935_info;
0393 
0394     trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
0395                       indio_dev->name,
0396                       iio_device_id(indio_dev));
0397 
0398     if (!trig)
0399         return -ENOMEM;
0400 
0401     st->trig = trig;
0402     st->noise_tripped = jiffies - HZ;
0403     iio_trigger_set_drvdata(trig, indio_dev);
0404 
0405     ret = devm_iio_trigger_register(dev, trig);
0406     if (ret) {
0407         dev_err(dev, "failed to register trigger\n");
0408         return ret;
0409     }
0410 
0411     ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
0412                           iio_pollfunc_store_time,
0413                           as3935_trigger_handler, NULL);
0414 
0415     if (ret) {
0416         dev_err(dev, "cannot setup iio trigger\n");
0417         return ret;
0418     }
0419 
0420     calibrate_as3935(st);
0421 
0422     ret = devm_delayed_work_autocancel(dev, &st->work, as3935_event_work);
0423     if (ret)
0424         return ret;
0425 
0426     ret = devm_request_irq(dev, spi->irq,
0427                 &as3935_interrupt_handler,
0428                 IRQF_TRIGGER_RISING,
0429                 dev_name(dev),
0430                 indio_dev);
0431 
0432     if (ret) {
0433         dev_err(dev, "unable to request irq\n");
0434         return ret;
0435     }
0436 
0437     ret = devm_iio_device_register(dev, indio_dev);
0438     if (ret < 0) {
0439         dev_err(dev, "unable to register device\n");
0440         return ret;
0441     }
0442     return 0;
0443 }
0444 
0445 static const struct of_device_id as3935_of_match[] = {
0446     { .compatible = "ams,as3935", },
0447     { /* sentinel */ },
0448 };
0449 MODULE_DEVICE_TABLE(of, as3935_of_match);
0450 
0451 static const struct spi_device_id as3935_id[] = {
0452     {"as3935", 0},
0453     {},
0454 };
0455 MODULE_DEVICE_TABLE(spi, as3935_id);
0456 
0457 static struct spi_driver as3935_driver = {
0458     .driver = {
0459         .name   = "as3935",
0460         .of_match_table = as3935_of_match,
0461         .pm = pm_sleep_ptr(&as3935_pm_ops),
0462     },
0463     .probe      = as3935_probe,
0464     .id_table   = as3935_id,
0465 };
0466 module_spi_driver(as3935_driver);
0467 
0468 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
0469 MODULE_DESCRIPTION("AS3935 lightning sensor");
0470 MODULE_LICENSE("GPL");