Re: [PATCH 2/2] iio: Add AS3935 lightning sensor support

From: Marek Vasut
Date: Fri Jan 31 2014 - 22:13:04 EST


On Friday, January 31, 2014 at 04:38:23 PM, Matt Ranostay wrote:

[...]

> diff --git a/Documentation/devicetree/bindings/iio/distance/as3935.txt
> b/Documentation/devicetree/bindings/iio/distance/as3935.txt new file mode
> 100644
> index 0000000..af35827
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/distance/as3935.txt
> @@ -0,0 +1,25 @@
> +Austrian Microsystems AS3935 Franklin lightning sensor device driver
> +
> +Required properties:
> + - compatible: must be "ams,as3935"
> + - reg: SPI chip select number for the device
> + - spi-max-frequency: Max SPI frequency to use
> + - spi-cpha: SPI Mode 1
> + - gpios: GPIO input of interrupt line from IRQ pin of AS3935 IC
> +
> +Optional properties:
> + - ams,tune-cap: Calibration tuning capacitor stepping value 0 - 15.
> + Range of 0 to 120 pF, 8pF steps. This will require using the
> calibration + data from the manufacturer.
> +
> +
> +Example:
> +
> + as3935@0 {
> + compatible = "ams,as3935";
> + reg = <0>;
> + spi-max-frequency = <100000>;
> + spi-cpha;
> + ams,tune-cap = /bits/ 8 <10>;
> + gpios = <&gpio1 16 10>;
> + };

You should CC devicetree-discuss with new bindings! Such a grave flub ;-)

[...]

> +config AS3935
> + tristate "AS3935 Franklin lightning sensor"
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> + depends on SPI
> + help
> + If you say yes here you get support for the Austrian Microsystems
> + AS3935 lightning detection sensor.
> +
> + This driver can also be built as a module. If so, the module
> + will be called as3935

Fullstop's missing at the end of the above sentence .

[...]

> +#define AS3935_AFE_GAIN 0x00
> +#define AS3935_AFE_MASK 0x3F
> +#define AS3935_AFE_GAIN_MAX 0x1F
> +
> +#define AS3935_INT 0x03
> +#define AS3935_INT_MASK 0x07
> +#define AS3935_DATA 0x07
> +#define AS3935_DATA_MASK 0x1F
> +
> +#define AS3935_TUNE_CAP 0x08
> +#define AS3935_CALIBRATE 0x3D
> +
> +#define AS3935_WRITE_DATA (0x1 << 15)
> +#define AS3935_READ_DATA (0x1 << 14)
> +#define AS3935_ADDRESS(x) (x << 8)

((x) << 8)

[...]

> +static int as3935_write(struct as3935_state *st,
> + unsigned int reg,
> + unsigned int val)
> +{
> + u8 buf[2];
> + int ret;
> +
> + mutex_lock(&st->lock);

You don't need to protect the writes to buf[] with a mutex, since the buf[] is
on stack here. Each thread will have it's own local copy of that. DTTO for $reg
variable.

Actually, I think you don't even need mutex around all of the the SPI sync
stuff. The SPI framework already has a mutex in it.

> + buf[0] = AS3935_WRITE_DATA | AS3935_ADDRESS(reg) >> 8;
> + buf[1] = val;
> +
> + ret = spi_write(st->spi, (u8 *) &buf, 2);
> + mutex_unlock(&st->lock);
> +
> + return ret;
> +};
> +

[...]

> +static int as3935_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val,
> + int *val2,
> + long m)
> +{
> + struct as3935_state *st = iio_priv(indio_dev);
> +
> + if (m == IIO_CHAN_INFO_RAW) {

if (m != IIO...)
return -EINVAL;

... rest of the code ...

This will cut down on the depth of indent.

> + int ret;
> + *val2 = 0;
> + ret = as3935_read(st, AS3935_DATA, val);
> + if (ret)
> + return ret;
> + return IIO_VAL_INT;
> + }
> +
> + return -EINVAL;
> +}

[...]

> +#ifdef CONFIG_PM_SLEEP
> +static int as3935_suspend(struct spi_device *spi, pm_message_t msg)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct as3935_state *st = iio_priv(indio_dev);
> + int val, ret;
> +
> + ret = as3935_read(st, AS3935_AFE_GAIN, &val);
> + if (ret)
> + return ret;
> + val |= 0x01;

What's this hexadecimal magic constant here?

> +
> + return as3935_write(st, AS3935_AFE_GAIN, val);
> +}
> +
> +static int as3935_resume(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct as3935_state *st = iio_priv(indio_dev);
> + int val, ret;
> +
> + ret = as3935_read(st, AS3935_AFE_GAIN, &val);
> + if (ret)
> + return ret;
> + val &= ~1;

What's this decimal magic constant here?

> + return as3935_write(st, AS3935_AFE_GAIN, val);
> +}
> +#else
> +#define as3935_suspend NULL
> +#define as3935_resume NULL
> +#endif
> +
> +static int as3935_probe(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev;
> + struct iio_trigger *trig;
> + struct as3935_state *st;
> + struct device_node *np = spi->dev.of_node;
> + int gpio;
> + int irq;
> + int ret;
> +
> + /* Grab the GPIO to use for lightning event interrupt */
> + if (np)
> + gpio = of_get_gpio(spi->dev.of_node, 0);
> + else {
> + dev_err(&spi->dev, "unable to get interrupt gpio\n");
> + return -EINVAL;
> + }

The logic is a bit weird here. Why don't you check this like so:

if (!np) {
... bail ...
}

gpio = ...

> + /* GPIO event setup */
> + ret = devm_gpio_request(&spi->dev, gpio, "as3935");
> + if (ret) {
> + dev_err(&spi->dev, "failed to request GPIO %u\n", gpio);
> + return ret;
> + }
> +
> + ret = gpio_direction_input(gpio);
> + if (ret) {
> + dev_err(&spi->dev, "failed to set pin direction\n");
> + return -EINVAL;
> + }
> +
> + /* IRQ setup */
> + irq = gpio_to_irq(gpio);
> + if (irq < 0) {
> + dev_err(&spi->dev, "failed to map GPIO to IRQ: %d\n", irq);
> + return -EINVAL;
> + }
> +
> + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + st->spi = spi;
> + st->tune_cap = 0;
> + spi_set_drvdata(spi, indio_dev);
> + mutex_init(&st->lock);
> + INIT_DELAYED_WORK(&st->work, as3935_event_work);
> +
> + of_property_read_u8(np, "ams,tune-cap", &st->tune_cap);

This can fail, check the retval please.

> + if (st->tune_cap > 15) {
> + dev_err(&spi->dev,
> + "wrong tune_cap setting of %d\n", st->tune_cap);
> + return -EINVAL;
> + }

[...]

> +
> +MODULE_AUTHOR("Matt Ranostay <mranostay@xxxxxxxxx>");
> +MODULE_DESCRIPTION("AS3935 lightning sensor");
> +MODULE_LICENSE("GPL");

MODULE_ALIAS() is missing , no?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/