diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-25 18:07:31 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-25 18:07:31 +0200 |
| commit | 5e667ac2dddafacce7d08d5b786338ad72e91270 (patch) | |
| tree | 87a403fe996606d727b3edb69534c2384bd63762 | |
| parent | 385637ffe058ef42d51b3150a39c8945bbe894ff (diff) | |
| parent | 96c92d42e9c93b2647d55b84ad883b11baa76307 (diff) | |
| download | linux-5e667ac2dddafacce7d08d5b786338ad72e91270.tar.bz2 | |
Merge tag 'iio-for-4.18b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
Second set of new device support, features and cleanup for IIO in the 4.18 cycle
Usual mixture of new devices support and other stuff. A couple of
staging graduations in here and some old driver drops.
New device support
* ad5686
- Add support for AD5691R, AD5692R, AD5693 and AD5693R i2c DACs
- Add support for AD5681R, AD5682R, AD5683 and AD5683R SPI DACs
* lmp91000
- Add ID for LMP91002
* stm32-dfsdm
- Add support for the stm32mp1 devices.
Drivers dropped
* ADE7753
- No longer easily available, no users came forward and needs a lot
of work to move out of staging.
* ADE7754
* ADE7758
* ADE7759
Staging graduations
- ad2s1200 - good cleanup from David Veenstra.
- tsl2772 (was tsl2x7x) - Brian's quest is at an end and
staging/iio/light is no more!
Features
* tools
- loop forever on a negative number of loops being specified.
* ltc 2632
- add of_match_table
- support an external reference regulator.
* mag3110
- Support continuous mode when running fast as it increases the
posssible sampling rate.
* ti-ads8688
- Add trigger and buffer support to this ADC.
Cleanups / minor tweaks.
* tools
- tidy up types in iio_generic_buffer.
* ad2s1200
- Whitespace cleanup.
- Drop pointless initializations.
- Improve kernel docs.
- Reorder to setup the SPI prior to device registration (race fix).
- Change to modern gpiod framework.
- Drop platform data and move to DT bindings. There are no in
kernel users of the platform data. Any out of tree boards will
need changes.
- Add an explicit compatible table.
- Provide _scale for angular velocity and angle channels.
- Add David Veenstra to copyright notice as this cleanup was non
trivial.
* ade8366
- Avoid a race by ensuring channel init is before registration
with the subsystem.
* afe
- binding spelling fix.
* imx7d-adc
- typo fix in Freescale
* inv_mpu6050
- tidy up an ugly loop to take advantage of known entry condition.
- add a comment explaining why the sensible sampling frequencies
are more limited than might be immediately apparent (aliasing).
* mma8452
- reduce the sleep time on data not ready when running at high
frequency.
* stm32-dfsdm
- add missing header.
* tsl2583
- fix integration_time_availabe which was in microsecs rather the
millisecs.
* tsl2x7x/tsl2772
- Whitespace cleanup.
- Change to direct returns where sensible.
- Turn the chip off in the registration error path.
- Use macro to reduce repition when setting up the device_info
structures.
- Change the _available attributes over to read_avail callback,
and the range definitions that supports.
- Fix some wrong period values.
- Add some range checkign for _write_raw.
- Rename the driver to tsl2772 to avoid wild card clash problems
in future.
47 files changed, 1152 insertions, 3939 deletions
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.txt index ed7520d1d051..75ba25d062e1 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.txt +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.txt @@ -8,14 +8,16 @@ It is mainly targeted for: - PDM microphones (audio digital microphone) It features up to 8 serial digital interfaces (SPI or Manchester) and -up to 4 filters on stm32h7. +up to 4 filters on stm32h7 or 6 filters on stm32mp1. Each child node match with a filter instance. Contents of a STM32 DFSDM root node: ------------------------------------ Required properties: -- compatible: Should be "st,stm32h7-dfsdm". +- compatible: Should be one of: + "st,stm32h7-dfsdm" + "st,stm32mp1-dfsdm" - reg: Offset and length of the DFSDM block register set. - clocks: IP and serial interfaces clocking. Should be set according to rcc clock ID and "clock-names". @@ -45,6 +47,7 @@ Required properties: "st,stm32-dfsdm-adc" for sigma delta ADCs "st,stm32-dfsdm-dmic" for audio digital microphone. - reg: Specifies the DFSDM filter instance used. + Valid values are from 0 to 3 on stm32h7, 0 to 5 on stm32mp1. - interrupts: IRQ lines connected to each DFSDM filter instance. - st,adc-channels: List of single-ended channels muxed for this ADC. valid values: diff --git a/Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.txt b/Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.txt index 0ddbaebba8ce..821b61b8c542 100644 --- a/Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.txt +++ b/Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.txt @@ -2,7 +2,7 @@ Current Sense Amplifier ======================= When an io-channel measures the output voltage from a current sense -amplifier, the interesting mesaurement is almost always the current +amplifier, the interesting measurement is almost always the current through the sense resistor, not the voltage output. This binding describes such a current sense circuit. diff --git a/Documentation/devicetree/bindings/iio/afe/current-sense-shunt.txt b/Documentation/devicetree/bindings/iio/afe/current-sense-shunt.txt index 8e7b3e408a52..0f67108a07b6 100644 --- a/Documentation/devicetree/bindings/iio/afe/current-sense-shunt.txt +++ b/Documentation/devicetree/bindings/iio/afe/current-sense-shunt.txt @@ -2,7 +2,7 @@ Current Sense Shunt =================== When an io-channel measures the voltage over a current sense shunt, -the interesting mesaurement is almost always the current through the +the interesting measurement is almost always the current through the shunt, not the voltage over it. This binding describes such a current sense circuit. diff --git a/Documentation/devicetree/bindings/iio/dac/ltc2632.txt b/Documentation/devicetree/bindings/iio/dac/ltc2632.txt index eb911e5a8ab4..e0d5fea33031 100644 --- a/Documentation/devicetree/bindings/iio/dac/ltc2632.txt +++ b/Documentation/devicetree/bindings/iio/dac/ltc2632.txt @@ -12,12 +12,26 @@ Required properties: Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt apply. In particular, "reg" and "spi-max-frequency" properties must be given. +Optional properties: + - vref-supply: Phandle to the external reference voltage supply. This should + only be set if there is an external reference voltage connected to the VREF + pin. If the property is not set the internal reference is used. + Example: + vref: regulator-vref { + compatible = "regulator-fixed"; + regulator-name = "vref-ltc2632"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + }; + spi_master { dac: ltc2632@0 { compatible = "lltc,ltc2632-l12"; reg = <0>; /* CS0 */ spi-max-frequency = <1000000>; + vref-supply = <&vref>; /* optional */ }; }; diff --git a/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt b/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt index b9b621e94cd7..e6d0c2eb345c 100644 --- a/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt +++ b/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt @@ -1,10 +1,13 @@ -* Texas Instruments LMP91000 potentiostat +* Texas Instruments LMP91000 series of potentiostats -http://www.ti.com/lit/ds/symlink/lmp91000.pdf +LMP91000: http://www.ti.com/lit/ds/symlink/lmp91000.pdf +LMP91002: http://www.ti.com/lit/ds/symlink/lmp91002.pdf Required properties: - - compatible: should be "ti,lmp91000" + - compatible: should be one of the following: + "ti,lmp91000" + "ti,lmp91002" - reg: the I2C address of the device - io-channels: the phandle of the iio provider diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index d69e85a8bdc3..d08aeb41cd07 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -93,6 +93,7 @@ source "drivers/iio/potentiometer/Kconfig" source "drivers/iio/potentiostat/Kconfig" source "drivers/iio/pressure/Kconfig" source "drivers/iio/proximity/Kconfig" +source "drivers/iio/resolver/Kconfig" source "drivers/iio/temperature/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index d8cba9c229c0..cb5993251381 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -36,5 +36,6 @@ obj-y += potentiometer/ obj-y += potentiostat/ obj-y += pressure/ obj-y += proximity/ +obj-y += resolver/ obj-y += temperature/ obj-y += trigger/ diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 7a2da7f9d4dc..7e3d82cff3d5 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -106,6 +106,7 @@ struct mma8452_data { u8 ctrl_reg1; u8 data_cfg; const struct mma_chip_info *chip_info; + int sleep_val; }; /** @@ -193,7 +194,11 @@ static int mma8452_drdy(struct mma8452_data *data) if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY) return 0; - msleep(20); + if (data->sleep_val <= 20) + usleep_range(data->sleep_val * 250, + data->sleep_val * 500); + else + msleep(20); } dev_err(&data->client->dev, "data not ready\n"); @@ -544,6 +549,18 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int mma8452_calculate_sleep(struct mma8452_data *data) +{ + int ret, i = mma8452_get_odr_index(data); + + if (mma8452_samp_freq[i][0] > 0) + ret = 1000 / mma8452_samp_freq[i][0]; + else + ret = 1000; + + return ret == 0 ? 1 : ret; +} + static int mma8452_standby(struct mma8452_data *data) { return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1, @@ -700,6 +717,8 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK; data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT; + data->sleep_val = mma8452_calculate_sleep(data); + ret = mma8452_change_config(data, MMA8452_CTRL_REG1, data->ctrl_reg1); break; @@ -1593,6 +1612,9 @@ static int mma8452_probe(struct i2c_client *client, data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); + + data->sleep_val = mma8452_calculate_sleep(data); + ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1, data->ctrl_reg1); if (ret < 0) diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index cfab31162845..ad6764fb2a23 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -604,5 +604,5 @@ static struct platform_driver imx7d_adc_driver = { module_platform_driver(imx7d_adc_driver); MODULE_AUTHOR("Haibo Chen <haibo.chen@freescale.com>"); -MODULE_DESCRIPTION("Freeacale IMX7D ADC driver"); +MODULE_DESCRIPTION("Freescale IMX7D ADC driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 1b78becaba5d..31462aef7238 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -8,11 +8,11 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> -#include <linux/interrupt.h> +#include <linux/iio/adc/stm32-dfsdm-adc.h> #include <linux/iio/buffer.h> #include <linux/iio/hw-consumer.h> -#include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/platform_device.h> diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index 1d0d8238d9b5..bf089f5d6225 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -25,6 +25,8 @@ struct stm32_dfsdm_dev_data { #define STM32H7_DFSDM_NUM_FILTERS 4 #define STM32H7_DFSDM_NUM_CHANNELS 8 +#define STM32MP1_DFSDM_NUM_FILTERS 6 +#define STM32MP1_DFSDM_NUM_CHANNELS 8 static bool stm32_dfsdm_volatile_reg(struct device *dev, unsigned int reg) { @@ -61,6 +63,21 @@ static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_data = { .regmap_cfg = &stm32h7_dfsdm_regmap_cfg, }; +static const struct regmap_config stm32mp1_dfsdm_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = sizeof(u32), + .max_register = 0x7fc, + .volatile_reg = stm32_dfsdm_volatile_reg, + .fast_io = true, +}; + +static const struct stm32_dfsdm_dev_data stm32mp1_dfsdm_data = { + .num_filters = STM32MP1_DFSDM_NUM_FILTERS, + .num_channels = STM32MP1_DFSDM_NUM_CHANNELS, + .regmap_cfg = &stm32mp1_dfsdm_regmap_cfg, +}; + struct dfsdm_priv { struct platform_device *pdev; /* platform device */ @@ -248,6 +265,10 @@ static const struct of_device_id stm32_dfsdm_of_match[] = { .compatible = "st,stm32h7-dfsdm", .data = &stm32h7_dfsdm_data, }, + { + .compatible = "st,stm32mp1-dfsdm", + .data = &stm32mp1_dfsdm_data, + }, {} }; MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match); diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 079f133144b0..184d686ebd99 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -17,6 +17,9 @@ #include <linux/of.h> #include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> #include <linux/iio/sysfs.h> #define ADS8688_CMD_REG(x) (x << 8) @@ -155,6 +158,13 @@ static const struct attribute_group ads8688_attribute_group = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ | BIT(IIO_CHAN_INFO_SCALE) \ | BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ } static const struct iio_chan_spec ads8684_channels[] = { @@ -371,6 +381,28 @@ static const struct iio_info ads8688_info = { .attrs = &ads8688_attribute_group, }; +static irqreturn_t ads8688_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + u16 buffer[8]; + int i, j = 0; + + for (i = 0; i < indio_dev->masklength; i++) { + if (!test_bit(i, indio_dev->active_scan_mask)) + continue; + buffer[j] = ads8688_read(indio_dev, i); + j++; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static const struct ads8688_chip_info ads8688_chip_info_tbl[] = { [ID_ADS8684] = { .channels = ads8684_channels, @@ -402,7 +434,7 @@ static int ads8688_probe(struct spi_device *spi) ret = regulator_get_voltage(st->reg); if (ret < 0) - goto error_out; + goto err_regulator_disable; st->vref_mv = ret / 1000; } else { @@ -430,13 +462,22 @@ static int ads8688_probe(struct spi_device *spi) mutex_init(&st->lock); + ret = iio_triggered_buffer_setup(indio_dev, NULL, ads8688_trigger_handler, NULL); + if (ret < 0) { + dev_err(&spi->dev, "iio triggered buffer setup failed\n"); + goto err_regulator_disable; + } + ret = iio_device_register(indio_dev); if (ret) - goto error_out; + goto err_buffer_cleanup; return 0; -error_out: +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + +err_regulator_disable: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -449,6 +490,7 @@ static int ads8688_remove(struct spi_device *spi) struct ads8688_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index 43667866321e..0138337aedd1 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -161,12 +161,14 @@ static int ad8366_probe(struct spi_device *spi) indio_dev->channels = ad8366_channels; indio_dev->num_channels = ARRAY_SIZE(ad8366_channels); + ret = ad8366_write(indio_dev, 0 , 0); + if (ret < 0) + goto error_disable_reg; + ret = iio_device_register(indio_dev); if (ret) goto error_disable_reg; - ad8366_write(indio_dev, 0, 0); - return 0; error_disable_reg: diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index 6bb09e9259e6..1df9143f55e9 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R + * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R, + * AD5684, AD5684R, AD5685R, AD5686, AD5686R * Digital to analog converters driver * * Copyright 2018 Analog Devices Inc. @@ -15,12 +16,27 @@ static int ad5686_spi_write(struct ad5686_state *st, u8 cmd, u8 addr, u16 val) { struct spi_device *spi = to_spi_device(st->dev); - - st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | - AD5686_ADDR(addr) | - val); - - return spi_write(spi, &st->data[0].d8[1], 3); + u8 tx_len, *buf; + + switch (st->chip_info->regmap_type) { + case AD5683_REGMAP: + st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | + AD5683_DATA(val)); + buf = &st->data[0].d8[1]; + tx_len = 3; + break; + case AD5686_REGMAP: + st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | + AD5686_ADDR(addr) | + val); + buf = &st->data[0].d8[1]; + tx_len = 3; + break; + default: + return -EINVAL; + } + + return spi_write(spi, buf, tx_len); } static int ad5686_spi_read(struct ad5686_state *st, u8 addr) @@ -37,9 +53,15 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr) }, }; struct spi_device *spi = to_spi_device(st->dev); + u8 cmd = 0; int ret; - st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) | + if (st->chip_info->regmap_type == AD5686_REGMAP) + cmd = AD5686_CMD_READBACK_ENABLE; + else if (st->chip_info->regmap_type == AD5683_REGMAP) + cmd = AD5686_CMD_READBACK_ENABLE_V2; + + st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5686_ADDR(addr)); st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP)); @@ -67,6 +89,10 @@ static const struct spi_device_id ad5686_spi_id[] = { {"ad5672r", ID_AD5672R}, {"ad5676", ID_AD5676}, {"ad5676r", ID_AD5676R}, + {"ad5681r", ID_AD5681R}, + {"ad5682r", ID_AD5682R}, + {"ad5683", ID_AD5683}, + {"ad5683r", ID_AD5683R}, {"ad5684", ID_AD5684}, {"ad5684r", ID_AD5684R}, {"ad5685", ID_AD5685R}, /* Does not exist */ diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 89c5f089ae7f..e136f0fd38f0 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -70,6 +70,8 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, bool readin; int ret; struct ad5686_state *st = iio_priv(indio_dev); + unsigned int val, ref_bit_msk; + u8 shift; ret = strtobool(buf, &readin); if (ret) @@ -80,9 +82,28 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, else st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); - ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0, - st->pwr_down_mask & st->pwr_down_mode); + switch (st->chip_info->regmap_type) { + case AD5683_REGMAP: + shift = 13; + ref_bit_msk = AD5683_REF_BIT_MSK; + break; + case AD5686_REGMAP: + shift = 0; + ref_bit_msk = 0; + break; + case AD5693_REGMAP: + shift = 13; + ref_bit_msk = AD5693_REF_BIT_MSK; + break; + default: + return -EINVAL; + } + val = ((st->pwr_down_mask & st->pwr_down_mode) << shift); + if (!st->use_internal_vref) + val |= ref_bit_msk; + + ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0, val); return ret ? ret : len; } @@ -175,6 +196,11 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { .ext_info = ad5686_ext_info, \ } +#define DECLARE_AD5693_CHANNELS(name, bits, _shift) \ +static struct iio_chan_spec name[] = { \ + AD5868_CHANNEL(0, 0, bits, _shift), \ +} + #define DECLARE_AD5686_CHANNELS(name, bits, _shift) \ static struct iio_chan_spec name[] = { \ AD5868_CHANNEL(0, 1, bits, _shift), \ @@ -200,72 +226,135 @@ DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0); DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4); DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2); DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0); +DECLARE_AD5693_CHANNELS(ad5693_channels, 16, 0); +DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2); +DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4); static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { [ID_AD5671R] = { .channels = ad5672_channels, .int_vref_mv = 2500, .num_channels = 8, + .regmap_type = AD5686_REGMAP, }, [ID_AD5672R] = { .channels = ad5672_channels, .int_vref_mv = 2500, .num_channels = 8, + .regmap_type = AD5686_REGMAP, }, [ID_AD5675R] = { .channels = ad5676_channels, .int_vref_mv = 2500, .num_channels = 8, + .regmap_type = AD5686_REGMAP, }, [ID_AD5676] = { .channels = ad5676_channels, .num_channels = 8, + .regmap_type = AD5686_REGMAP, }, [ID_AD5676R] = { .channels = ad5676_channels, .int_vref_mv = 2500, .num_channels = 8, + .regmap_type = AD5686_REGMAP, + }, + [ID_AD5681R] = { + .channels = ad5691r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, + }, + [ID_AD5682R] = { + .channels = ad5692r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, + }, + [ID_AD5683] = { + .channels = ad5693_channels, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, + }, + [ID_AD5683R] = { + .channels = ad5693_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, }, [ID_AD5684] = { .channels = ad5684_channels, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5684R] = { .channels = ad5684_channels, .int_vref_mv = 2500, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5685R] = { .channels = ad5685r_channels, .int_vref_mv = 2500, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5686] = { .channels = ad5686_channels, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5686R] = { .channels = ad5686_channels, .int_vref_mv = 2500, .num_channels = 4, + .regmap_type = AD5686_REGMAP, + }, + [ID_AD5691R] = { + .channels = ad5691r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5693_REGMAP, + }, + [ID_AD5692R] = { + .channels = ad5692r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5693_REGMAP, + }, + [ID_AD5693] = { + .channels = ad5693_channels, + .num_channels = 1, + .regmap_type = AD5693_REGMAP, + }, + [ID_AD5693R] = { + .channels = ad5693_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5693_REGMAP, }, [ID_AD5694] = { .channels = ad5684_channels, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5694R] = { .channels = ad5684_channels, .int_vref_mv = 2500, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5696] = { .channels = ad5686_channels, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, [ID_AD5696R] = { .channels = ad5686_channels, .int_vref_mv = 2500, .num_channels = 4, + .regmap_type = AD5686_REGMAP, }, }; @@ -276,7 +365,9 @@ int ad5686_probe(struct device *dev, { struct ad5686_state *st; struct iio_dev *indio_dev; - int ret, voltage_uv = 0; + unsigned int val, ref_bit_msk; + u8 cmd; + int ret, i, voltage_uv = 0; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (indio_dev == NULL) @@ -310,7 +401,8 @@ int ad5686_probe(struct device *dev, st->vref_mv = st->chip_info->int_vref_mv; /* Set all the power down mode for all channels to 1K pulldown */ - st->pwr_down_mode = 0x55; + for (i = 0; i < st->chip_info->num_channels; i++) + st->pwr_down_mode |= (0x01 << (i * 2)); indio_dev->dev.parent = dev; indio_dev->name = name; @@ -319,8 +411,29 @@ int ad5686_probe(struct device *dev, indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; - ret = st->write(st, AD5686_CMD_INTERNAL_REFER_SETUP, - 0, !!voltage_uv); + switch (st->chip_info->regmap_type) { + case AD5683_REGMAP: + cmd = AD5686_CMD_CONTROL_REG; + ref_bit_msk = AD5683_REF_BIT_MSK; + st->use_internal_vref = !voltage_uv; + break; + case AD5686_REGMAP: + cmd = AD5686_CMD_INTERNAL_REFER_SETUP; + ref_bit_msk = 0; + break; + case AD5693_REGMAP: + cmd = AD5686_CMD_CONTROL_REG; + ref_bit_msk = AD5693_REF_BIT_MSK; + st->use_internal_vref = !voltage_uv; + break; + default: + ret = -EINVAL; + goto error_disable_reg; + } + + val = (voltage_uv | ref_bit_msk); + + ret = st->write(st, cmd, 0, !!val); if (ret) goto error_disable_reg; diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h index 05f0ce9d2de1..d05cda9f1edd 100644 --- a/drivers/iio/dac/ad5686.h +++ b/drivers/iio/dac/ad5686.h @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/kernel.h> +#define AD5683_DATA(x) ((x) << 4) #define AD5686_ADDR(x) ((x) << 16) #define AD5686_CMD(x) ((x) << 20) @@ -35,6 +36,11 @@ #define AD5686_LDAC_PWRDN_100K 0x2 #define AD5686_LDAC_PWRDN_3STATE 0x3 +#define AD5686_CMD_CONTROL_REG 0x4 +#define AD5686_CMD_READBACK_ENABLE_V2 0x5 +#define AD5683_REF_BIT_MSK BIT(12) +#define AD5693_REF_BIT_MSK BIT(12) + /** * ad5686_supported_device_ids: */ @@ -44,11 +50,19 @@ enum ad5686_supported_device_ids { ID_AD5675R, ID_AD5676, ID_AD5676R, + ID_AD5681R, + ID_AD5682R, + ID_AD5683, + ID_AD5683R, ID_AD5684, ID_AD5684R, ID_AD5685R, ID_AD5686, ID_AD5686R, + ID_AD5691R, + ID_AD5692R, + ID_AD5693, + ID_AD5693R, ID_AD5694, ID_AD5694R, ID_AD5695R, @@ -56,6 +70,12 @@ enum ad5686_supported_device_ids { ID_AD5696R, }; +enum ad5686_regmap_type { + AD5683_REGMAP, + AD5686_REGMAP, + AD5693_REGMAP +}; + struct ad5686_state; typedef int (*ad5686_write_func)(struct ad5686_state *st, @@ -68,12 +88,14 @@ typedef int (*ad5686_read_func)(struct ad5686_state *st, u8 addr); * @int_vref_mv: AD5620/40/60: the internal reference voltage * @num_channels: number of channels * @channel: channel specification + * @regmap_type: register map layout variant */ struct ad5686_chip_info { u16 int_vref_mv; unsigned int num_channels; struct iio_chan_spec *channels; + enum ad5686_regmap_type regmap_type; }; /** @@ -84,6 +106,7 @@ struct ad5686_chip_info { * @vref_mv: actual reference voltage used * @pwr_down_mask: power down mask * @pwr_down_mode: current power down mode + * @use_internal_vref: set to true if the internal reference voltage is used * @data: spi transfer buffers */ @@ -96,6 +119,7 @@ struct ad5686_state { unsigned int pwr_down_mode; ad5686_write_func write; ad5686_read_func read; + bool use_internal_vref; /* * DMA (thus cache coherency maintenance) requires the diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c index 275e0321bcf8..d18735d7d938 100644 --- a/drivers/iio/dac/ad5696-i2c.c +++ b/drivers/iio/dac/ad5696-i2c.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * AD5671R, AD5675R, AD5694, AD5694R, AD5695R, AD5696, AD5696R + * AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R, + * AD5694, AD5694R, AD5695R, AD5696, AD5696R * Digital to analog converters driver * * Copyright 2018 Analog Devices Inc. @@ -72,6 +73,10 @@ static int ad5686_i2c_remove(struct i2c_client *i2c) static const struct i2c_device_id ad5686_i2c_id[] = { {"ad5671r", ID_AD5671R}, {"ad5675r", ID_AD5675R}, + {"ad5691r", ID_AD5691R}, + {"ad5692r", ID_AD5692R}, + {"ad5693", ID_AD5693}, + {"ad5693r", ID_AD5693R}, {"ad5694", ID_AD5694}, {"ad5694r", ID_AD5694R}, {"ad5695r", ID_AD5695R}, diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index af2ddd0dd341..cca278eaa138 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -2,6 +2,7 @@ * LTC2632 Digital to analog convertors spi driver * * Copyright 2017 Maxime Roussin-Bélanger + * expanded by Silvan Murer <silvan.murer@gmail.com> * * Licensed under the GPL-2. */ @@ -10,6 +11,7 @@ #include <linux/spi/spi.h> #include <linux/module.h> #include <linux/iio/iio.h> +#include <linux/regulator/consumer.h> #define LTC2632_DAC_CHANNELS 2 @@ -28,7 +30,7 @@ /** * struct ltc2632_chip_info - chip specific information * @channels: channel spec for the DAC - * @vref_mv: reference voltage + * @vref_mv: internal reference voltage */ struct ltc2632_chip_info { const struct iio_chan_spec *channels; @@ -39,10 +41,14 @@ struct ltc2632_chip_info { * struct ltc2632_state - driver instance specific data * @spi_dev: pointer to the spi_device struct * @powerdown_cache_mask used to show current channel powerdown state + * @vref_mv used reference voltage (internal or external) + * @vref_reg regulator for the reference voltage */ struct ltc2632_state { struct spi_device *spi_dev; unsigned int powerdown_cache_mask; + int vref_mv; + struct regulator *vref_reg; }; enum ltc2632_supported_device_ids { @@ -90,7 +96,7 @@ static int ltc2632_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_SCALE: - *val = chip_info->vref_mv; + *val = st->vref_mv; *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; } @@ -246,6 +252,45 @@ static int ltc2632_probe(struct spi_device *spi) chip_info = (struct ltc2632_chip_info *) spi_get_device_id(spi)->driver_data; + st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); + if (PTR_ERR(st->vref_reg) == -ENODEV) { + /* use internal reference voltage */ + st->vref_reg = NULL; + st->vref_mv = chip_info->vref_mv; + + ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, + 0, 0, 0); + if (ret) { + dev_err(&spi->dev, + "Set internal reference command failed, %d\n", + ret); + return ret; + } + } else if (IS_ERR(st->vref_reg)) { + dev_err(&spi->dev, + "Error getting voltage reference regulator\n"); + return PTR_ERR(st->vref_reg); + } else { + /* use external reference voltage */ + ret = regulator_enable(st->vref_reg); + if (ret) { + dev_err(&spi->dev, + "enable reference regulator failed, %d\n", + ret); + return ret; + } + st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000; + + ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER, + 0, 0, 0); + if (ret) { + dev_err(&spi->dev, + "Set external reference command failed, %d\n", + ret); + return ret; + } + } + indio_dev->dev.parent = &spi->dev; indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name : spi_get_device_id(spi)->name; @@ -254,14 +299,20 @@ static int ltc2632_probe(struct spi_device *spi) indio_dev->channels = chip_info->channels; indio_dev->num_channels = LTC2632_DAC_CHANNELS; - ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 0, 0, 0); - if (ret) { - dev_err(&spi->dev, - "Set internal reference command failed, %d\n", ret); - return ret; - } + return iio_device_register(indio_dev); +} - return devm_iio_device_register(&spi->dev, indio_dev); +static int ltc2632_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ltc2632_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (st->vref_reg) + regulator_disable(st->vref_reg); + + return 0; } static const struct spi_device_id ltc2632_id[] = { @@ -275,15 +326,6 @@ static const struct spi_device_id ltc2632_id[] = { }; MODULE_DEVICE_TABLE(spi, ltc2632_id); -static struct spi_driver ltc2632_driver = { - .driver = { - .name = "ltc2632", - }, - .probe = ltc2632_probe, - .id_table = ltc2632_id, -}; -module_spi_driver(ltc2632_driver); - static const struct of_device_id ltc2632_of_match[] = { { .compatible = "lltc,ltc2632-l12", @@ -308,6 +350,17 @@ static const struct of_device_id ltc2632_of_match[] = { }; MODULE_DEVICE_TABLE(of, ltc2632_of_match); +static struct spi_driver ltc2632_driver = { + .driver = { + .name = "ltc2632", + .of_match_table = of_match_ptr(ltc2632_of_match), + }, + .probe = ltc2632_probe, + .remove = ltc2632_remove, + .id_table = ltc2632_id, +}; +module_spi_driver(ltc2632_driver); + MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>"); MODULE_DESCRIPTION("LTC2632 DAC SPI driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 43fba5f7532b..f9c0624505a2 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -798,7 +798,14 @@ static const struct iio_chan_spec inv_mpu_channels[] = { INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), }; -/* constant IIO attribute */ +/* + * The user can choose any frequency between INV_MPU6050_MIN_FIFO_RATE and + * INV_MPU6050_MAX_FIFO_RATE, but only these frequencies are matched by the + * low-pass filter. Specifically, each of these sampling rates are about twice + * the bandwidth of a corresponding low-pass filter, which should eliminate + * aliasing following the Nyquist principle. By picking a frequency different + * from these, the user risks aliasing effects. + */ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500"); static IIO_CONST_ATTR(in_anglvel_scale_available, "0.000133090 0.000266181 0.000532362 0.001064724"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 97d965181635..1795418438e4 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -175,7 +175,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) if (kfifo_len(&st->timestamps) > fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR) goto flush_fifo; - while (fifo_count >= bytes_per_datum) { + do { result = regmap_bulk_read(st->map, st->reg->fifo_r_w, data, bytes_per_datum); if (result) @@ -194,7 +194,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) timestamp); fifo_count -= bytes_per_datum; - } + } while (fifo_count >= bytes_per_datum); end_session: mutex_unlock(&st->lock); diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 074e50657366..c7ef8d1862d6 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -409,6 +409,14 @@ config TSL2583 Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. Access ALS data via iio, sysfs. +config TSL2772 + tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" + depends on I2C + help + Support for: tsl2571, tsl2671, tmd2671, tsl2771, tmd2771, tsl2572, tsl2672, + tmd2672, tsl2772, tmd2772 devices. + Provides iio_events and direct access via sysfs. + config TSL4531 tristate "TAOS TSL4531 ambient light sensors" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index f1777036d4f8..80943af5d627 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_ST_UVIS25_SPI) += st_uvis25_spi.o obj-$(CONFIG_TCS3414) += tcs3414.o obj-$(CONFIG_TCS3472) += tcs3472.o obj-$(CONFIG_TSL2583) += tsl2583.o +obj-$(CONFIG_TSL2772) += tsl2772.o obj-$(CONFIG_TSL4531) += tsl4531.o obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_VCNL4000) += vcnl4000.o diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index f2e50edaa242..4b5d9988f025 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -600,7 +600,7 @@ done: static IIO_CONST_ATTR(in_illuminance_calibscale_available, "1 8 16 111"); static IIO_CONST_ATTR(in_illuminance_integration_time_available, - "0.000050 0.000100 0.000150 0.000200 0.000250 0.000300 0.000350 0.000400 0.000450 0.000500 0.000550 0.000600 0.000650"); + "0.050 0.100 0.150 0.200 0.250 0.300 0.350 0.400 0.450 0.500 0.550 0.600 0.650"); static IIO_DEVICE_ATTR_RW(in_illuminance_input_target, 0); static IIO_DEVICE_ATTR_WO(in_illuminance_calibrate, 0); static IIO_DEVICE_ATTR_RW(in_illuminance_lux_table, 0); diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/iio/light/tsl2772.c index cc863e8927f5..34d42a2504c9 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/iio/light/tsl2772.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Device driver for monitoring ambient light intensity in (lux) and proximity - * detection (prox) within the TAOS TSL2X7X family of devices. + * detection (prox) within the TAOS TSL2571, TSL2671, TMD2671, TSL2771, TMD2771, + * TSL2572, TSL2672, TMD2672, TSL2772, and TMD2772 devices. * * Copyright (c) 2012, TAOS Corporation. * Copyright (c) 2017-2018 Brian Masney <masneyb@onstation.org> @@ -18,94 +19,95 @@ #include <linux/iio/events.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include "tsl2x7x.h" +#include <linux/platform_data/tsl2772.h> /* Cal defs */ #define PROX_STAT_CAL 0 #define PROX_STAT_SAMP 1 #define MAX_SAMPLES_CAL 200 -/* TSL2X7X Device ID */ +/* TSL2772 Device ID */ #define TRITON_ID 0x00 #define SWORDFISH_ID 0x30 #define HALIBUT_ID 0x20 /* Lux calculation constants */ -#define TSL2X7X_LUX_CALC_OVER_FLOW 65535 +#define TSL2772_LUX_CALC_OVER_FLOW 65535 /* * TAOS Register definitions - Note: depending on device, some of these register * are not used and the register address is benign. */ -/* 2X7X register offsets */ -#define TSL2X7X_MAX_CONFIG_REG 16 +/* Register offsets */ +#define TSL2772_MAX_CONFIG_REG 16 /* Device Registers and Masks */ -#define TSL2X7X_CNTRL 0x00 -#define TSL2X7X_ALS_TIME 0X01 -#define TSL2X7X_PRX_TIME 0x02 -#define TSL2X7X_WAIT_TIME 0x03 -#define TSL2X7X_ALS_MINTHRESHLO 0X04 -#define TSL2X7X_ALS_MINTHRESHHI 0X05 -#define TSL2X7X_ALS_MAXTHRESHLO 0X06 -#define TSL2X7X_ALS_MAXTHRESHHI 0X07 -#define TSL2X7X_PRX_MINTHRESHLO 0X08 -#define TSL2X7X_PRX_MINTHRESHHI 0X09 -#define TSL2X7X_PRX_MAXTHRESHLO 0X0A -#define TSL2X7X_PRX_MAXTHRESHHI 0X0B -#define TSL2X7X_PERSISTENCE 0x0C -#define TSL2X7X_ALS_PRX_CONFIG 0x0D -#define TSL2X7X_PRX_COUNT 0x0E -#define TSL2X7X_GAIN 0x0F -#define TSL2X7X_NOTUSED 0x10 -#define TSL2X7X_REVID 0x11 -#define TSL2X7X_CHIPID 0x12 -#define TSL2X7X_STATUS 0x13 -#define TSL2X7X_ALS_CHAN0LO 0x14 -#define TSL2X7X_ALS_CHAN0HI 0x15 -#define TSL2X7X_ALS_CHAN1LO 0x16 -#define TSL2X7X_ALS_CHAN1HI 0x17 -#define TSL2X7X_PRX_LO 0x18 -#define TSL2X7X_PRX_HI 0x19 - -/* tsl2X7X cmd reg masks */ -#define TSL2X7X_CMD_REG 0x80 -#define TSL2X7X_CMD_SPL_FN 0x60 -#define TSL2X7X_CMD_REPEAT_PROTO 0x00 -#define TSL2X7X_CMD_AUTOINC_PROTO 0x20 - -#define TSL2X7X_CMD_PROX_INT_CLR 0X05 -#define TSL2X7X_CMD_ALS_INT_CLR 0x06 -#define TSL2X7X_CMD_PROXALS_INT_CLR 0X07 - -/* tsl2X7X cntrl reg masks */ -#define TSL2X7X_CNTL_ADC_ENBL 0x02 -#define TSL2X7X_CNTL_PWR_ON 0x01 - -/* tsl2X7X status reg masks */ -#define TSL2X7X_STA_ADC_VALID 0x01 -#define TSL2X7X_STA_PRX_VALID 0x02 -#define TSL2X7X_STA_ADC_PRX_VALID (TSL2X7X_STA_ADC_VALID | \ - TSL2X7X_STA_PRX_VALID) -#define TSL2X7X_STA_ALS_INTR 0x10 -#define TSL2X7X_STA_PRX_INTR 0x20 - -/* tsl2X7X cntrl reg masks */ -#define TSL2X7X_CNTL_REG_CLEAR 0x00 -#define TSL2X7X_CNTL_PROX_INT_ENBL 0X20 -#define TSL2X7X_CNTL_ALS_INT_ENBL 0X10 -#define TSL2X7X_CNTL_WAIT_TMR_ENBL 0X08 -#define TSL2X7X_CNTL_PROX_DET_ENBL 0X04 -#define TSL2X7X_CNTL_PWRON 0x01 -#define TSL2X7X_CNTL_ALSPON_ENBL 0x03 -#define TSL2X7X_CNTL_INTALSPON_ENBL 0x13 -#define TSL2X7X_CNTL_PROXPON_ENBL 0x0F -#define TSL2X7X_CNTL_INTPROXPON_ENBL 0x2F - -#define TSL2X7X_MIN_ITIME 3 - -/* TAOS txx2x7x Device family members */ +#define TSL2772_CNTRL 0x00 +#define TSL2772_ALS_TIME 0X01 +#define TSL2772_PRX_TIME 0x02 +#define TSL2772_WAIT_TIME 0x03 +#define TSL2772_ALS_MINTHRESHLO 0X04 +#define TSL2772_ALS_MINTHRESHHI 0X05 +#define TSL2772_ALS_MAXTHRESHLO 0X06 +#define TSL2772_ALS_MAXTHRESHHI 0X07 +#define TSL2772_PRX_MINTHRESHLO 0X08 +#define TSL2772_PRX_MINTHRESHHI 0X09 +#define TSL2772_PRX_MAXTHRESHLO 0X0A +#define TSL2772_PRX_MAXTHRESHHI 0X0B +#define TSL2772_PERSISTENCE 0x0C +#define TSL2772_ALS_PRX_CONFIG 0x0D +#define TSL2772_PRX_COUNT 0x0E +#define TSL2772_GAIN 0x0F +#define TSL2772_NOTUSED 0x10 +#define TSL2772_REVID 0x11 +#define TSL2772_CHIPID 0x12 +#define TSL2772_STATUS 0x13 +#define TSL2772_ALS_CHAN0LO 0x14 +#define TSL2772_ALS_CHAN0HI 0x15 +#define TSL2772_ALS_CHAN1LO 0x16 +#define TSL2772_ALS_CHAN1HI 0x17 +#define TSL2772_PRX_LO 0x18 +#define TSL2772_PRX_HI 0x19 + +/* tsl2772 cmd reg masks */ +#define TSL2772_CMD_REG 0x80 +#define TSL2772_CMD_SPL_FN 0x60 +#define TSL2772_CMD_REPEAT_PROTO 0x00 +#define TSL2772_CMD_AUTOINC_PROTO 0x20 + +#define TSL2772_CMD_PROX_INT_CLR 0X05 +#define TSL2772_CMD_ALS_INT_CLR 0x06 +#define TSL2772_CMD_PROXALS_INT_CLR 0X07 + +/* tsl2772 cntrl reg masks */ +#define TSL2772_CNTL_ADC_ENBL 0x02 +#define TSL2772_CNTL_PWR_ON 0x01 + +/* tsl2772 status reg masks */ +#define TSL2772_STA_ADC_VALID 0x01 +#define TSL2772_STA_PRX_VALID 0x02 +#define TSL2772_STA_ADC_PRX_VALID (TSL2772_STA_ADC_VALID | \ + TSL2772_STA_PRX_VALID) +#define TSL2772_STA_ALS_INTR 0x10 +#define TSL2772_STA_PRX_INTR 0x20 + +/* tsl2772 cntrl reg masks */ +#define TSL2772_CNTL_REG_CLEAR 0x00 +#define TSL2772_CNTL_PROX_INT_ENBL 0X20 +#define TSL2772_CNTL_ALS_INT_ENBL 0X10 +#define TSL2772_CNTL_WAIT_TMR_ENBL 0X08 +#define TSL2772_CNTL_PROX_DET_ENBL 0X04 +#define TSL2772_CNTL_PWRON 0x01 +#define TSL2772_CNTL_ALSPON_ENBL 0x03 +#define TSL2772_CNTL_INTALSPON_ENBL 0x13 +#define TSL2772_CNTL_PROXPON_ENBL 0x0F +#define TSL2772_CNTL_INTPROXPON_ENBL 0x2F + +#define TSL2772_ALS_GAIN_TRIM_MIN 250 +#define TSL2772_ALS_GAIN_TRIM_MAX 4000 + +/* Device family members */ enum { tsl2571, tsl2671, @@ -120,39 +122,39 @@ enum { }; enum { - TSL2X7X_CHIP_UNKNOWN = 0, - TSL2X7X_CHIP_WORKING = 1, - TSL2X7X_CHIP_SUSPENDED = 2 + TSL2772_CHIP_UNKNOWN = 0, + TSL2772_CHIP_WORKING = 1, + TSL2772_CHIP_SUSPENDED = 2 }; /* Per-device data */ -struct tsl2x7x_als_info { +struct tsl2772_als_info { u16 als_ch0; u16 als_ch1; u16 lux; }; -struct tsl2x7x_chip_info { +struct tsl2772_chip_info { int chan_table_elements; struct iio_chan_spec channel_with_events[4]; struct iio_chan_spec channel_without_events[4]; const struct iio_info *info; }; -struct tsl2X7X_chip { +struct tsl2772_chip { kernel_ulong_t id; struct mutex prox_mutex; struct mutex als_mutex; struct i2c_client *client; u16 prox_data; - struct tsl2x7x_als_info als_cur_info; - struct tsl2x7x_settings settings; - struct tsl2X7X_platform_data *pdata; + struct tsl2772_als_info als_cur_info; + struct tsl2772_settings settings; + struct tsl2772_platform_data *pdata; int als_gain_time_scale; int als_saturation; - int tsl2x7x_chip_status; - u8 tsl2x7x_config[TSL2X7X_MAX_CONFIG_REG]; - const struct tsl2x7x_chip_info *chip_info; + int tsl2772_chip_status; + u8 tsl2772_config[TSL2772_MAX_CONFIG_REG]; + const struct tsl2772_chip_info *chip_info; const struct iio_info *info; s64 event_timestamp; /* @@ -160,7 +162,7 @@ struct tsl2X7X_chip { * updates via sysfs. * Sized to 9 = max 8 segments + 1 termination segment */ - struct tsl2x7x_lux tsl2x7x_device_lux[TSL2X7X_MAX_LUX_TABLE_SIZE]; + struct tsl2772_lux tsl2772_device_lux[TSL2772_MAX_LUX_TABLE_SIZE]; }; /* @@ -171,47 +173,47 @@ struct tsl2X7X_chip { * The two rows in each table correspond to the Lux1 and Lux2 equations from * the datasheets. */ -static const struct tsl2x7x_lux tsl2x71_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { +static const struct tsl2772_lux tsl2x71_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { { 53000, 106000 }, { 31800, 53000 }, { 0, 0 }, }; -static const struct tsl2x7x_lux tmd2x71_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { +static const struct tsl2772_lux tmd2x71_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { { 24000, 48000 }, { 14400, 24000 }, { 0, 0 }, }; -static const struct tsl2x7x_lux tsl2x72_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { +static const struct tsl2772_lux tsl2x72_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { { 60000, 112200 }, { 37800, 60000 }, { 0, 0 }, }; -static const struct tsl2x7x_lux tmd2x72_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { +static const struct tsl2772_lux tmd2x72_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { { 20000, 35000 }, { 12600, 20000 }, { 0, 0 }, }; -static const struct tsl2x7x_lux *tsl2x7x_default_lux_table_group[] = { - [tsl2571] = tsl2x71_lux_table, - [tsl2671] = tsl2x71_lux_table, - [tmd2671] = tmd2x71_lux_table, - [tsl2771] = tsl2x71_lux_table, - [tmd2771] = tmd2x71_lux_table, - [tsl2572] = tsl2x72_lux_table, - [tsl2672] = tsl2x72_lux_table, - [tmd2672] = tmd2x72_lux_table, - [tsl2772] = tsl2x72_lux_table, - [tmd2772] = tmd2x72_lux_table, +static const struct tsl2772_lux *tsl2772_default_lux_table_group[] = { + [tsl2571] = tsl2x71_lux_table, + [tsl2671] = tsl2x71_lux_table, + [tmd2671] = tmd2x71_lux_table, + [tsl2771] = tsl2x71_lux_table, + [tmd2771] = tmd2x71_lux_table, + [tsl2572] = tsl2x72_lux_table, + [tsl2672] = tsl2x72_lux_table, + [tmd2672] = tmd2x72_lux_table, + [tsl2772] = tsl2x72_lux_table, + [tmd2772] = tmd2x72_lux_table, }; -static const struct tsl2x7x_settings tsl2x7x_default_settings = { - .als_time = 255, /* 2.73 ms */ +static const struct tsl2772_settings tsl2772_default_settings = { + .als_time = 255, /* 2.72 / 2.73 ms */ .als_gain = 0, - .prox_time = 255, /* 2.73 ms */ + .prox_time = 255, /* 2.72 / 2.73 ms */ .prox_gain = 0, .wait_time = 255, .als_prox_config = 0, @@ -227,24 +229,41 @@ static const struct tsl2x7x_settings tsl2x7x_default_settings = { .prox_thres_high = 512, .prox_max_samples_cal = 30, .prox_pulse_count = 8, - .prox_diode = TSL2X7X_DIODE1, - .prox_power = TSL2X7X_100_mA + .prox_diode = TSL2772_DIODE1, + .prox_power = TSL2772_100_mA }; -static const s16 tsl2x7x_als_gain[] = { +static const s16 tsl2772_als_gain[] = { 1, 8, 16, 120 }; -static const s16 tsl2x7x_prox_gain[] = { +static const s16 tsl2772_prox_gain[] = { 1, 2, 4, 8 }; +static const int tsl2772_int_time_avail[][6] = { + [tsl2571] = { 0, 2720, 0, 2720, 0, 696000 }, + [tsl2671] = { 0, 2720, 0, 2720, 0, 696000 }, + [tmd2671] = { 0, 2720, 0, 2720, 0, 696000 }, + [tsl2771] = { 0, 2720, 0, 2720, 0, 696000 }, + [tmd2771] = { 0, 2720, 0, 2720, 0, 696000 }, + [tsl2572] = { 0, 2730, 0, 2730, 0, 699000 }, + [tsl2672] = { 0, 2730, 0, 2730, 0, 699000 }, + [tmd2672] = { 0, 2730, 0, 2730, 0, 699000 }, + [tsl2772] = { 0, 2730, 0, 2730, 0, 699000 }, + [tmd2772] = { 0, 2730, 0, 2730, 0, 699000 }, +}; + +static int tsl2772_int_calibscale_avail[] = { 1, 8, 16, 120 }; + +static int tsl2772_prox_calibscale_avail[] = { 1, 2, 4, 8 }; + /* Channel variations */ enum { ALS, @@ -267,12 +286,12 @@ static const u8 device_channel_config[] = { [tmd2772] = ALSPRX2 }; -static int tsl2x7x_read_status(struct tsl2X7X_chip *chip) +static int tsl2772_read_status(struct tsl2772_chip *chip) { int ret; ret = i2c_smbus_read_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_STATUS); + TSL2772_CMD_REG | TSL2772_STATUS); if (ret < 0) dev_err(&chip->client->dev, "%s: failed to read STATUS register: %d\n", __func__, @@ -281,12 +300,12 @@ static int tsl2x7x_read_status(struct tsl2X7X_chip *chip) return ret; } -static int tsl2x7x_write_control_reg(struct tsl2X7X_chip *chip, u8 data) +static int tsl2772_write_control_reg(struct tsl2772_chip *chip, u8 data) { int ret; ret = i2c_smbus_write_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CNTRL, data); + TSL2772_CMD_REG | TSL2772_CNTRL, data); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed to write to control register %x: %d\n", @@ -296,14 +315,14 @@ static int tsl2x7x_write_control_reg(struct tsl2X7X_chip *chip, u8 data) return ret; } -static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, +static int tsl2772_read_autoinc_regs(struct tsl2772_chip *chip, int lower_reg, int upper_reg) { u8 buf[2]; int ret; ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_AUTOINC_PROTO | + TSL2772_CMD_REG | TSL2772_CMD_AUTOINC_PROTO | lower_reg); if (ret < 0) { dev_err(&chip->client->dev, @@ -313,7 +332,7 @@ static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, } ret = i2c_smbus_read_byte_data(chip->client, - TSL2X7X_CMD_REG | lower_reg); + TSL2772_CMD_REG | lower_reg); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed to read from register %x: %d\n", __func__, @@ -323,7 +342,7 @@ static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, buf[0] = ret; ret = i2c_smbus_read_byte_data(chip->client, - TSL2X7X_CMD_REG | upper_reg); + TSL2772_CMD_REG | upper_reg); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed to read from register %x: %d\n", __func__, @@ -333,7 +352,7 @@ static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, buf[1] = ret; ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_REPEAT_PROTO | + TSL2772_CMD_REG | TSL2772_CMD_REPEAT_PROTO | lower_reg); if (ret < 0) { dev_err(&chip->client->dev, @@ -346,7 +365,7 @@ static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, } /** - * tsl2x7x_get_lux() - Reads and calculates current lux value. + * tsl2772_get_lux() - Reads and calculates current lux value. * @indio_dev: pointer to IIO device * * The raw ch0 and ch1 values of the ambient light sensed in the last @@ -356,47 +375,47 @@ static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, * coefficients. A lux gain trim is applied to each lux equation, and then the * maximum lux within the interval 0..65535 is selected. */ -static int tsl2x7x_get_lux(struct iio_dev *indio_dev) +static int tsl2772_get_lux(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - struct tsl2x7x_lux *p; + struct tsl2772_chip *chip = iio_priv(indio_dev); + struct tsl2772_lux *p; int max_lux, ret; bool overflow; mutex_lock(&chip->als_mutex); - if (chip->tsl2x7x_chip_status != TSL2X7X_CHIP_WORKING) { + if (chip->tsl2772_chip_status != TSL2772_CHIP_WORKING) { dev_err(&chip->client->dev, "%s: device is not enabled\n", __func__); ret = -EBUSY; goto out_unlock; } - ret = tsl2x7x_read_status(chip); + ret = tsl2772_read_status(chip); if (ret < 0) goto out_unlock; - if (!(ret & TSL2X7X_STA_ADC_VALID)) { + if (!(ret & TSL2772_STA_ADC_VALID)) { dev_err(&chip->client->dev, "%s: data not valid yet\n", __func__); ret = chip->als_cur_info.lux; /* return LAST VALUE */ goto out_unlock; } - ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_ALS_CHAN0LO, - TSL2X7X_ALS_CHAN0HI); + ret = tsl2772_read_autoinc_regs(chip, TSL2772_ALS_CHAN0LO, + TSL2772_ALS_CHAN0HI); if (ret < 0) goto out_unlock; chip->als_cur_info.als_ch0 = ret; - ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_ALS_CHAN1LO, - TSL2X7X_ALS_CHAN1HI); + ret = tsl2772_read_autoinc_regs(chip, TSL2772_ALS_CHAN1LO, + TSL2772_ALS_CHAN1HI); if (ret < 0) goto out_unlock; chip->als_cur_info.als_ch1 = ret; if (chip->als_cur_info.als_ch0 >= chip->als_saturation) { - max_lux = TSL2X7X_LUX_CALC_OVER_FLOW; + max_lux = TSL2772_LUX_CALC_OVER_FLOW; goto update_struct_with_max_lux; } @@ -408,7 +427,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) max_lux = 0; overflow = false; - for (p = (struct tsl2x7x_lux *)chip->tsl2x7x_device_lux; p->ch0 != 0; + for (p = (struct tsl2772_lux *)chip->tsl2772_device_lux; p->ch0 != 0; p++) { int lux; @@ -424,7 +443,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) */ lux = (lux * chip->settings.als_gain_trim) / 1000; - if (lux > TSL2X7X_LUX_CALC_OVER_FLOW) { + if (lux > TSL2772_LUX_CALC_OVER_FLOW) { overflow = true; continue; } @@ -433,7 +452,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) } if (overflow && max_lux == 0) - max_lux = TSL2X7X_LUX_CALC_OVER_FLOW; + max_lux = TSL2772_LUX_CALC_OVER_FLOW; update_struct_with_max_lux: chip->als_cur_info.lux = max_lux; @@ -446,19 +465,19 @@ out_unlock: } /** - * tsl2x7x_get_prox() - Reads proximity data registers and updates + * tsl2772_get_prox() - Reads proximity data registers and updates * chip->prox_data. * * @indio_dev: pointer to IIO device */ -static int tsl2x7x_get_prox(struct iio_dev *indio_dev) +static int tsl2772_get_prox(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); int ret; mutex_lock(&chip->prox_mutex); - ret = tsl2x7x_read_status(chip); + ret = tsl2772_read_status(chip); if (ret < 0) goto prox_poll_err; @@ -468,7 +487,7 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) case tmd2671: case tsl2771: case tmd2771: - if (!(ret & TSL2X7X_STA_ADC_VALID)) { + if (!(ret & TSL2772_STA_ADC_VALID)) { ret = -EINVAL; goto prox_poll_err; } @@ -478,14 +497,14 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) case tmd2672: case tsl2772: case tmd2772: - if (!(ret & TSL2X7X_STA_PRX_VALID)) { + if (!(ret & TSL2772_STA_PRX_VALID)) { ret = -EINVAL; goto prox_poll_err; } break; } - ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_PRX_LO, TSL2X7X_PRX_HI); + ret = tsl2772_read_autoinc_regs(chip, TSL2772_PRX_LO, TSL2772_PRX_HI); if (ret < 0) goto prox_poll_err; chip->prox_data = ret; @@ -497,46 +516,46 @@ prox_poll_err: } /** - * tsl2x7x_defaults() - Populates the device nominal operating parameters + * tsl2772_defaults() - Populates the device nominal operating parameters * with those provided by a 'platform' data struct or * with prefined defaults. * * @chip: pointer to device structure. */ -static void tsl2x7x_defaults(struct tsl2X7X_chip *chip) +static void tsl2772_defaults(struct tsl2772_chip *chip) { /* If Operational settings defined elsewhere.. */ if (chip->pdata && chip->pdata->platform_default_settings) memcpy(&chip->settings, chip->pdata->platform_default_settings, - sizeof(tsl2x7x_default_settings)); + sizeof(tsl2772_default_settings)); else - memcpy(&chip->settings, &tsl2x7x_default_settings, - sizeof(tsl2x7x_default_settings)); + memcpy(&chip->settings, &tsl2772_default_settings, + sizeof(tsl2772_default_settings)); /* Load up the proper lux table. */ if (chip->pdata && chip->pdata->platform_lux_table[0].ch0 != 0) - memcpy(chip->tsl2x7x_device_lux, + memcpy(chip->tsl2772_device_lux, chip->pdata->platform_lux_table, sizeof(chip->pdata->platform_lux_table)); else - memcpy(chip->tsl2x7x_device_lux, - tsl2x7x_default_lux_table_group[chip->id], - TSL2X7X_DEFAULT_TABLE_BYTES); + memcpy(chip->tsl2772_device_lux, + tsl2772_default_lux_table_group[chip->id], + TSL2772_DEFAULT_TABLE_BYTES); } /** - * tsl2x7x_als_calibrate() - Obtain single reading and calculate + * tsl2772_als_calibrate() - Obtain single reading and calculate * the als_gain_trim. * * @indio_dev: pointer to IIO device */ -static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) +static int tsl2772_als_calibrate(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); int ret, lux_val; ret = i2c_smbus_read_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CNTRL); + TSL2772_CMD_REG | TSL2772_CNTRL); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed to read from the CNTRL register\n", @@ -544,20 +563,20 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) return ret; } - if ((ret & (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) - != (TSL2X7X_CNTL_ADC_ENBL | TSL2X7X_CNTL_PWR_ON)) { + if ((ret & (TSL2772_CNTL_ADC_ENBL | TSL2772_CNTL_PWR_ON)) + != (TSL2772_CNTL_ADC_ENBL | TSL2772_CNTL_PWR_ON)) { dev_err(&chip->client->dev, "%s: Device is not powered on and/or ADC is not enabled\n", __func__); return -EINVAL; - } else if ((ret & TSL2X7X_STA_ADC_VALID) != TSL2X7X_STA_ADC_VALID) { + } else if ((ret & TSL2772_STA_ADC_VALID) != TSL2772_STA_ADC_VALID) { dev_err(&chip->client->dev, "%s: The two ADC channels have not completed an integration cycle\n", __func__); return -ENODATA; } - lux_val = tsl2x7x_get_lux(indio_dev); + lux_val = tsl2772_get_lux(indio_dev); if (lux_val < 0) { dev_err(&chip->client->dev, "%s: failed to get lux\n", __func__); @@ -566,7 +585,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) ret = (chip->settings.als_cal_target * chip->settings.als_gain_trim) / lux_val; - if (ret < 250 || ret > 4000) + if (ret < TSL2772_ALS_GAIN_TRIM_MIN || ret > TSL2772_ALS_GAIN_TRIM_MAX) return -ERANGE; chip->settings.als_gain_trim = ret; @@ -574,51 +593,51 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) return ret; } -static int tsl2x7x_chip_on(struct iio_dev *indio_dev) +static int tsl2772_chip_on(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); int ret, i, als_count, als_time_us; u8 *dev_reg, reg_val; /* Non calculated parameters */ - chip->tsl2x7x_config[TSL2X7X_ALS_TIME] = chip->settings.als_time; - chip->tsl2x7x_config[TSL2X7X_PRX_TIME] = chip->settings.prox_time; - chip->tsl2x7x_config[TSL2X7X_WAIT_TIME] = chip->settings.wait_time; - chip->tsl2x7x_config[TSL2X7X_ALS_PRX_CONFIG] = + chip->tsl2772_config[TSL2772_ALS_TIME] = chip->settings.als_time; + chip->tsl2772_config[TSL2772_PRX_TIME] = chip->settings.prox_time; + chip->tsl2772_config[TSL2772_WAIT_TIME] = chip->settings.wait_time; + chip->tsl2772_config[TSL2772_ALS_PRX_CONFIG] = chip->settings.als_prox_config; - chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHLO] = + chip->tsl2772_config[TSL2772_ALS_MINTHRESHLO] = (chip->settings.als_thresh_low) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHHI] = + chip->tsl2772_config[TSL2772_ALS_MINTHRESHHI] = (chip->settings.als_thresh_low >> 8) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHLO] = + chip->tsl2772_config[TSL2772_ALS_MAXTHRESHLO] = (chip->settings.als_thresh_high) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHHI] = + chip->tsl2772_config[TSL2772_ALS_MAXTHRESHHI] = (chip->settings.als_thresh_high >> 8) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_PERSISTENCE] = + chip->tsl2772_config[TSL2772_PERSISTENCE] = (chip->settings.prox_persistence & 0xFF) << 4 | (chip->settings.als_persistence & 0xFF); - chip->tsl2x7x_config[TSL2X7X_PRX_COUNT] = + chip->tsl2772_config[TSL2772_PRX_COUNT] = chip->settings.prox_pulse_count; - chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHLO] = + chip->tsl2772_config[TSL2772_PRX_MINTHRESHLO] = (chip->settings.prox_thres_low) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_PRX_MINTHRESHHI] = + chip->tsl2772_config[TSL2772_PRX_MINTHRESHHI] = (chip->settings.prox_thres_low >> 8) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHLO] = + chip->tsl2772_config[TSL2772_PRX_MAXTHRESHLO] = (chip->settings.prox_thres_high) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_PRX_MAXTHRESHHI] = + chip->tsl2772_config[TSL2772_PRX_MAXTHRESHHI] = (chip->settings.prox_thres_high >> 8) & 0xFF; /* and make sure we're not already on */ - if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { + if (chip->tsl2772_chip_status == TSL2772_CHIP_WORKING) { /* if forcing a register update - turn off, then on */ dev_info(&chip->client->dev, "device is already enabled\n"); return -EINVAL; } - /* Set the gain based on tsl2x7x_settings struct */ - chip->tsl2x7x_config[TSL2X7X_GAIN] = + /* Set the gain based on tsl2772_settings struct */ + chip->tsl2772_config[TSL2772_GAIN] = (chip->settings.als_gain & 0xFF) | ((chip->settings.prox_gain & 0xFF) << 2) | (chip->settings.prox_diode << 4) | @@ -626,16 +645,16 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) /* set chip time scaling and saturation */ als_count = 256 - chip->settings.als_time; - als_time_us = als_count * 2720; + als_time_us = als_count * tsl2772_int_time_avail[chip->id][3]; chip->als_saturation = als_count * 768; /* 75% of full scale */ chip->als_gain_time_scale = als_time_us * - tsl2x7x_als_gain[chip->settings.als_gain]; + tsl2772_als_gain[chip->settings.als_gain]; /* - * TSL2X7X Specific power-on / adc enable sequence + * TSL2772 Specific power-on / adc enable sequence * Power on the device 1st. */ - ret = tsl2x7x_write_control_reg(chip, TSL2X7X_CNTL_PWR_ON); + ret = tsl2772_write_control_reg(chip, TSL2772_CNTL_PWR_ON); if (ret < 0) return ret; @@ -643,9 +662,9 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) * Use the following shadow copy for our delay before enabling ADC. * Write all the registers. */ - for (i = 0, dev_reg = chip->tsl2x7x_config; - i < TSL2X7X_MAX_CONFIG_REG; i++) { - int reg = TSL2X7X_CMD_REG + i; + for (i = 0, dev_reg = chip->tsl2772_config; + i < TSL2772_MAX_CONFIG_REG; i++) { + int reg = TSL2772_CMD_REG + i; ret = i2c_smbus_write_byte_data(chip->client, reg, *dev_reg++); @@ -660,20 +679,20 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) /* Power-on settling time */ usleep_range(3000, 3500); - reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL | - TSL2X7X_CNTL_PROX_DET_ENBL; + reg_val = TSL2772_CNTL_PWR_ON | TSL2772_CNTL_ADC_ENBL | + TSL2772_CNTL_PROX_DET_ENBL; if (chip->settings.als_interrupt_en) - reg_val |= TSL2X7X_CNTL_ALS_INT_ENBL; + reg_val |= TSL2772_CNTL_ALS_INT_ENBL; if (chip->settings.prox_interrupt_en) - reg_val |= TSL2X7X_CNTL_PROX_INT_ENBL; + reg_val |= TSL2772_CNTL_PROX_INT_ENBL; - ret = tsl2x7x_write_control_reg(chip, reg_val); + ret = tsl2772_write_control_reg(chip, reg_val); if (ret < 0) return ret; ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | - TSL2X7X_CMD_PROXALS_INT_CLR); + TSL2772_CMD_REG | TSL2772_CMD_SPL_FN | + TSL2772_CMD_PROXALS_INT_CLR); if (ret < 0) { dev_err(&chip->client->dev, "%s: failed to clear interrupt status: %d\n", @@ -681,22 +700,22 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) return ret; } - chip->tsl2x7x_chip_status = TSL2X7X_CHIP_WORKING; + chip->tsl2772_chip_status = TSL2772_CHIP_WORKING; return ret; } -static int tsl2x7x_chip_off(struct iio_dev *indio_dev) +static int tsl2772_chip_off(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); /* turn device off */ - chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED; - return tsl2x7x_write_control_reg(chip, 0x00); + chip->tsl2772_chip_status = TSL2772_CHIP_SUSPENDED; + return tsl2772_write_control_reg(chip, 0x00); } /** - * tsl2x7x_invoke_change - power cycle the device to implement the user + * tsl2772_invoke_change - power cycle the device to implement the user * parameters * @indio_dev: pointer to IIO device * @@ -704,22 +723,22 @@ static int tsl2x7x_chip_off(struct iio_dev *indio_dev) * (On/Off), cycle device to implement updated parameter, put device back into * proper state, and unlock resource. */ -static int tsl2x7x_invoke_change(struct iio_dev *indio_dev) +static int tsl2772_invoke_change(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int device_status = chip->tsl2x7x_chip_status; + struct tsl2772_chip *chip = iio_priv(indio_dev); + int device_status = chip->tsl2772_chip_status; int ret; mutex_lock(&chip->als_mutex); mutex_lock(&chip->prox_mutex); - if (device_status == TSL2X7X_CHIP_WORKING) { - ret = tsl2x7x_chip_off(indio_dev); + if (device_status == TSL2772_CHIP_WORKING) { + ret = tsl2772_chip_off(indio_dev); if (ret < 0) goto unlock; } - ret = tsl2x7x_chip_on(indio_dev); + ret = tsl2772_chip_on(indio_dev); unlock: mutex_unlock(&chip->prox_mutex); @@ -728,9 +747,9 @@ unlock: return ret; } -static int tsl2x7x_prox_cal(struct iio_dev *indio_dev) +static int tsl2772_prox_cal(struct iio_dev *indio_dev) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); int prox_history[MAX_SAMPLES_CAL + 1]; int i, ret, mean, max, sample_sum; @@ -740,7 +759,7 @@ static int tsl2x7x_prox_cal(struct iio_dev *indio_dev) for (i = 0; i < chip->settings.prox_max_samples_cal; i++) { usleep_range(15000, 17500); - ret = tsl2x7x_get_prox(indio_dev); + ret = tsl2772_get_prox(indio_dev); if (ret < 0) return ret; @@ -757,21 +776,42 @@ static int tsl2x7x_prox_cal(struct iio_dev *indio_dev) chip->settings.prox_thres_high = (max << 1) - mean; - return tsl2x7x_invoke_change(indio_dev); + return tsl2772_invoke_change(indio_dev); } -static IIO_CONST_ATTR(in_intensity0_calibscale_available, "1 8 16 120"); +static int tsl2772_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct tsl2772_chip *chip = iio_priv(indio_dev); -static IIO_CONST_ATTR(in_proximity0_calibscale_available, "1 2 4 8"); + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_INTENSITY) { + *length = ARRAY_SIZE(tsl2772_int_calibscale_avail); + *vals = tsl2772_int_calibscale_avail; + } else { + *length = ARRAY_SIZE(tsl2772_prox_calibscale_avail); + *vals = tsl2772_prox_calibscale_avail; + } + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(tsl2772_int_time_avail[chip->id]); + *vals = tsl2772_int_time_avail[chip->id]; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_RANGE; + } -static IIO_CONST_ATTR(in_intensity0_integration_time_available, - ".00272 - .696"); + return -EINVAL; +} static ssize_t in_illuminance0_target_input_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + struct tsl2772_chip *chip = iio_priv(dev_to_iio_dev(dev)); return snprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target); } @@ -781,7 +821,7 @@ static ssize_t in_illuminance0_target_input_store(struct device *dev, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); u16 value; int ret; @@ -789,7 +829,7 @@ static ssize_t in_illuminance0_target_input_store(struct device *dev, return -EINVAL; chip->settings.als_cal_target = value; - ret = tsl2x7x_invoke_change(indio_dev); + ret = tsl2772_invoke_change(indio_dev); if (ret < 0) return ret; @@ -807,11 +847,11 @@ static ssize_t in_illuminance0_calibrate_store(struct device *dev, if (kstrtobool(buf, &value) || !value) return -EINVAL; - ret = tsl2x7x_als_calibrate(indio_dev); + ret = tsl2772_als_calibrate(indio_dev); if (ret < 0) return ret; - ret = tsl2x7x_invoke_change(indio_dev); + ret = tsl2772_invoke_change(indio_dev); if (ret < 0) return ret; @@ -822,15 +862,15 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); + struct tsl2772_chip *chip = iio_priv(dev_to_iio_dev(dev)); int i = 0; int offset = 0; - while (i < TSL2X7X_MAX_LUX_TABLE_SIZE) { + while (i < TSL2772_MAX_LUX_TABLE_SIZE) { offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,", - chip->tsl2x7x_device_lux[i].ch0, - chip->tsl2x7x_device_lux[i].ch1); - if (chip->tsl2x7x_device_lux[i].ch0 == 0) { + chip->tsl2772_device_lux[i].ch0, + chip->tsl2772_device_lux[i].ch1); + if (chip->tsl2772_device_lux[i].ch0 == 0) { /* * We just printed the first "0" entry. * Now get rid of the extra "," and break. @@ -850,8 +890,8 @@ static ssize_t in_illuminance0_lux_table_store(struct device *dev, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int value[ARRAY_SIZE(chip->tsl2x7x_device_lux) * 2 + 1]; + struct tsl2772_chip *chip = iio_priv(indio_dev); + int value[ARRAY_SIZE(chip->tsl2772_device_lux) * 2 + 1]; int n, ret; get_options(buf, ARRAY_SIZE(value), value); @@ -864,23 +904,23 @@ static ssize_t in_illuminance0_lux_table_store(struct device *dev, */ n = value[0]; if ((n % 2) || n < 4 || - n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 2)) + n > ((ARRAY_SIZE(chip->tsl2772_device_lux) - 1) * 2)) return -EINVAL; if ((value[(n - 1)] | value[n]) != 0) return -EINVAL; - if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { - ret = tsl2x7x_chip_off(indio_dev); + if (chip->tsl2772_chip_status == TSL2772_CHIP_WORKING) { + ret = tsl2772_chip_off(indio_dev); if (ret < 0) return ret; } /* Zero out the table */ - memset(chip->tsl2x7x_device_lux, 0, sizeof(chip->tsl2x7x_device_lux)); - memcpy(chip->tsl2x7x_device_lux, &value[1], (value[0] * 4)); + memset(chip->tsl2772_device_lux, 0, sizeof(chip->tsl2772_device_lux)); + memcpy(chip->tsl2772_device_lux, &value[1], (value[0] * 4)); - ret = tsl2x7x_invoke_change(indio_dev); + ret = tsl2772_invoke_change(indio_dev); if (ret < 0) return ret; @@ -898,23 +938,23 @@ static ssize_t in_proximity0_calibrate_store(struct device *dev, if (kstrtobool(buf, &value) || !value) return -EINVAL; - ret = tsl2x7x_prox_cal(indio_dev); + ret = tsl2772_prox_cal(indio_dev); if (ret < 0) return ret; - ret = tsl2x7x_invoke_change(indio_dev); + ret = tsl2772_invoke_change(indio_dev); if (ret < 0) return ret; return len; } -static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev, +static int tsl2772_read_interrupt_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); if (chan->type == IIO_INTENSITY) return chip->settings.als_interrupt_en; @@ -922,31 +962,31 @@ static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev, return chip->settings.prox_interrupt_en; } -static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, +static int tsl2772_write_interrupt_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, int val) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); if (chan->type == IIO_INTENSITY) chip->settings.als_interrupt_en = val ? true : false; else chip->settings.prox_interrupt_en = val ? true : false; - return tsl2x7x_invoke_change(indio_dev); + return tsl2772_invoke_change(indio_dev); } -static int tsl2x7x_write_event_value(struct iio_dev *indio_dev, +static int tsl2772_write_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int val, int val2) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret = -EINVAL, y, z, filter_delay; + struct tsl2772_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL, count, persistence; u8 time; switch (info) { @@ -985,15 +1025,20 @@ static int tsl2x7x_write_event_value(struct iio_dev *indio_dev, else time = chip->settings.prox_time; - y = (TSL2X7X_MAX_TIMER_CNT - time) + 1; - z = y * TSL2X7X_MIN_ITIME; + count = 256 - time; + persistence = ((val * 1000000) + val2) / + (count * tsl2772_int_time_avail[chip->id][3]); + + if (chan->type == IIO_INTENSITY) { + /* ALS filter values are 1, 2, 3, 5, 10, 15, ..., 60 */ + if (persistence > 3) + persistence = (persistence / 5) + 3; - filter_delay = DIV_ROUND_UP((val * 1000) + val2, z); + chip->settings.als_persistence = persistence; + } else { + chip->settings.prox_persistence = persistence; + } - if (chan->type == IIO_INTENSITY) - chip->settings.als_persistence = filter_delay; - else - chip->settings.prox_persistence = filter_delay; ret = 0; break; default: @@ -1003,18 +1048,18 @@ static int tsl2x7x_write_event_value(struct iio_dev *indio_dev, if (ret < 0) return ret; - return tsl2x7x_invoke_change(indio_dev); + return tsl2772_invoke_change(indio_dev); } -static int tsl2x7x_read_event_value(struct iio_dev *indio_dev, +static int tsl2772_read_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int *val, int *val2) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret = -EINVAL, filter_delay, mult; + struct tsl2772_chip *chip = iio_priv(indio_dev); + int filter_delay, persistence; u8 time; switch (info) { @@ -1023,124 +1068,111 @@ static int tsl2x7x_read_event_value(struct iio_dev *indio_dev, switch (dir) { case IIO_EV_DIR_RISING: *val = chip->settings.als_thresh_high; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_EV_DIR_FALLING: *val = chip->settings.als_thresh_low; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - break; + return -EINVAL; } } else { switch (dir) { case IIO_EV_DIR_RISING: *val = chip->settings.prox_thres_high; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_EV_DIR_FALLING: *val = chip->settings.prox_thres_low; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - break; + return -EINVAL; } } break; case IIO_EV_INFO_PERIOD: if (chan->type == IIO_INTENSITY) { time = chip->settings.als_time; - mult = chip->settings.als_persistence; + persistence = chip->settings.als_persistence; + + /* ALS filter values are 1, 2, 3, 5, 10, 15, ..., 60 */ + if (persistence > 3) + persistence = (persistence - 3) * 5; } else { time = chip->settings.prox_time; - mult = chip->settings.prox_persistence; + persistence = chip->settings.prox_persistence; } - /* Determine integration time */ - *val = (TSL2X7X_MAX_TIMER_CNT - time) + 1; - *val2 = *val * TSL2X7X_MIN_ITIME; - filter_delay = *val2 * mult; - *val = filter_delay / 1000; - *val2 = filter_delay % 1000; - ret = IIO_VAL_INT_PLUS_MICRO; - break; + filter_delay = persistence * (256 - time) * + tsl2772_int_time_avail[chip->id][3]; + + *val = filter_delay / 1000000; + *val2 = filter_delay % 1000000; + return IIO_VAL_INT_PLUS_MICRO; default: - break; + return -EINVAL; } - - return ret; } -static int tsl2x7x_read_raw(struct iio_dev *indio_dev, +static int tsl2772_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret = -EINVAL; + struct tsl2772_chip *chip = iio_priv(indio_dev); switch (mask) { case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_LIGHT: - tsl2x7x_get_lux(indio_dev); + tsl2772_get_lux(indio_dev); *val = chip->als_cur_info.lux; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: return -EINVAL; } - break; case IIO_CHAN_INFO_RAW: switch (chan->type) { case IIO_INTENSITY: - tsl2x7x_get_lux(indio_dev); + tsl2772_get_lux(indio_dev); if (chan->channel == 0) *val = chip->als_cur_info.als_ch0; else *val = chip->als_cur_info.als_ch1; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_PROXIMITY: - tsl2x7x_get_prox(indio_dev); + tsl2772_get_prox(indio_dev); *val = chip->prox_data; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: return -EINVAL; } break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) - *val = tsl2x7x_als_gain[chip->settings.als_gain]; + *val = tsl2772_als_gain[chip->settings.als_gain]; else - *val = tsl2x7x_prox_gain[chip->settings.prox_gain]; - ret = IIO_VAL_INT; - break; + *val = tsl2772_prox_gain[chip->settings.prox_gain]; + return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: *val = chip->settings.als_gain_trim; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: *val = 0; - *val2 = (256 - chip->settings.als_time) * 2720; - ret = IIO_VAL_INT_PLUS_MICRO; - break; + *val2 = (256 - chip->settings.als_time) * + tsl2772_int_time_avail[chip->id][3]; + return IIO_VAL_INT_PLUS_MICRO; default: - ret = -EINVAL; + return -EINVAL; } - - return ret; } -static int tsl2x7x_write_raw(struct iio_dev *indio_dev, +static int tsl2772_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -1181,16 +1213,25 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_CALIBBIAS: + if (val < TSL2772_ALS_GAIN_TRIM_MIN || + val > TSL2772_ALS_GAIN_TRIM_MAX) + return -EINVAL; + chip->settings.als_gain_trim = val; break; case IIO_CHAN_INFO_INT_TIME: - chip->settings.als_time = 256 - (val2 / 2720); + if (val != 0 || val2 < tsl2772_int_time_avail[chip->id][1] || + val2 > tsl2772_int_time_avail[chip->id][5]) + return -EINVAL; + + chip->settings.als_time = 256 - + (val2 / tsl2772_int_time_avail[chip->id][3]); break; default: return -EINVAL; } - return tsl2x7x_invoke_change(indio_dev); + return tsl2772_invoke_change(indio_dev); } static DEVICE_ATTR_RW(in_illuminance0_target_input); @@ -1202,7 +1243,7 @@ static DEVICE_ATTR_WO(in_proximity0_calibrate); static DEVICE_ATTR_RW(in_illuminance0_lux_table); /* Use the default register values to identify the Taos device */ -static int tsl2x7x_device_id_verif(int id, int target) +static int tsl2772_device_id_verif(int id, int target) { switch (target) { case tsl2571: @@ -1223,28 +1264,28 @@ static int tsl2x7x_device_id_verif(int id, int target) return -EINVAL; } -static irqreturn_t tsl2x7x_event_handler(int irq, void *private) +static irqreturn_t tsl2772_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; - struct tsl2X7X_chip *chip = iio_priv(indio_dev); + struct tsl2772_chip *chip = iio_priv(indio_dev); s64 timestamp = iio_get_time_ns(indio_dev); int ret; - ret = tsl2x7x_read_status(chip); + ret = tsl2772_read_status(chip); if (ret < 0) return IRQ_HANDLED; /* What type of interrupt do we need to process */ - if (ret & TSL2X7X_STA_PRX_INTR) { + if (ret & TSL2772_STA_PRX_INTR) { iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), - timestamp); + timestamp); } - if (ret & TSL2X7X_STA_ALS_INTR) { + if (ret & TSL2772_STA_ALS_INTR) { iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, @@ -1254,8 +1295,8 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) } ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | - TSL2X7X_CMD_PROXALS_INT_CLR); + TSL2772_CMD_REG | TSL2772_CMD_SPL_FN | + TSL2772_CMD_PROXALS_INT_CLR); if (ret < 0) dev_err(&chip->client->dev, "%s: failed to clear interrupt status: %d\n", @@ -1264,113 +1305,77 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) return IRQ_HANDLED; } -static struct attribute *tsl2x7x_ALS_device_attrs[] = { - &iio_const_attr_in_intensity0_calibscale_available.dev_attr.attr, - &iio_const_attr_in_intensity0_integration_time_available.dev_attr.attr, +static struct attribute *tsl2772_ALS_device_attrs[] = { &dev_attr_in_illuminance0_target_input.attr, &dev_attr_in_illuminance0_calibrate.attr, &dev_attr_in_illuminance0_lux_table.attr, NULL }; -static struct attribute *tsl2x7x_PRX_device_attrs[] = { +static struct attribute *tsl2772_PRX_device_attrs[] = { &dev_attr_in_proximity0_calibrate.attr, NULL }; -static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = { - &iio_const_attr_in_intensity0_calibscale_available.dev_attr.attr, - &iio_const_attr_in_intensity0_integration_time_available.dev_attr.attr, +static struct attribute *tsl2772_ALSPRX_device_attrs[] = { &dev_attr_in_illuminance0_target_input.attr, &dev_attr_in_illuminance0_calibrate.attr, &dev_attr_in_illuminance0_lux_table.attr, NULL }; -static struct attribute *tsl2x7x_PRX2_device_attrs[] = { +static struct attribute *tsl2772_PRX2_device_attrs[] = { &dev_attr_in_proximity0_calibrate.attr, - &iio_const_attr_in_proximity0_calibscale_available.dev_attr.attr, NULL }; -static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = { - &iio_const_attr_in_intensity0_calibscale_available.dev_attr.attr, - &iio_const_attr_in_intensity0_integration_time_available.dev_attr.attr, +static struct attribute *tsl2772_ALSPRX2_device_attrs[] = { &dev_attr_in_illuminance0_target_input.attr, &dev_attr_in_illuminance0_calibrate.attr, &dev_attr_in_illuminance0_lux_table.attr, &dev_attr_in_proximity0_calibrate.attr, - &iio_const_attr_in_proximity0_calibscale_available.dev_attr.attr, NULL }; -static const struct attribute_group tsl2X7X_device_attr_group_tbl[] = { +static const struct attribute_group tsl2772_device_attr_group_tbl[] = { [ALS] = { - .attrs = tsl2x7x_ALS_device_attrs, + .attrs = tsl2772_ALS_device_attrs, }, [PRX] = { - .attrs = tsl2x7x_PRX_device_attrs, + .attrs = tsl2772_PRX_device_attrs, }, [ALSPRX] = { - .attrs = tsl2x7x_ALSPRX_device_attrs, + .attrs = tsl2772_ALSPRX_device_attrs, }, [PRX2] = { - .attrs = tsl2x7x_PRX2_device_attrs, + .attrs = tsl2772_PRX2_device_attrs, }, [ALSPRX2] = { - .attrs = tsl2x7x_ALSPRX2_device_attrs, + .attrs = tsl2772_ALSPRX2_device_attrs, }, }; -static const struct iio_info tsl2X7X_device_info[] = { - [ALS] = { - .attrs = &tsl2X7X_device_attr_group_tbl[ALS], - .read_raw = &tsl2x7x_read_raw, - .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_event_value, - .write_event_value = &tsl2x7x_write_event_value, - .read_event_config = &tsl2x7x_read_interrupt_config, - .write_event_config = &tsl2x7x_write_interrupt_config, - }, - [PRX] = { - .attrs = &tsl2X7X_device_attr_group_tbl[PRX], - .read_raw = &tsl2x7x_read_raw, - .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_event_value, - .write_event_value = &tsl2x7x_write_event_value, - .read_event_config = &tsl2x7x_read_interrupt_config, - .write_event_config = &tsl2x7x_write_interrupt_config, - }, - [ALSPRX] = { - .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX], - .read_raw = &tsl2x7x_read_raw, - .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_event_value, - .write_event_value = &tsl2x7x_write_event_value, - .read_event_config = &tsl2x7x_read_interrupt_config, - .write_event_config = &tsl2x7x_write_interrupt_config, - }, - [PRX2] = { - .attrs = &tsl2X7X_device_attr_group_tbl[PRX2], - .read_raw = &tsl2x7x_read_raw, - .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_event_value, - .write_event_value = &tsl2x7x_write_event_value, - .read_event_config = &tsl2x7x_read_interrupt_config, - .write_event_config = &tsl2x7x_write_interrupt_config, - }, - [ALSPRX2] = { - .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX2], - .read_raw = &tsl2x7x_read_raw, - .write_raw = &tsl2x7x_write_raw, - .read_event_value = &tsl2x7x_read_event_value, - .write_event_value = &tsl2x7x_write_event_value, - .read_event_config = &tsl2x7x_read_interrupt_config, - .write_event_config = &tsl2x7x_write_interrupt_config, - }, +#define TSL2772_DEVICE_INFO(type)[type] = \ + { \ + .attrs = &tsl2772_device_attr_group_tbl[type], \ + .read_raw = &tsl2772_read_raw, \ + .read_avail = &tsl2772_read_avail, \ + .write_raw = &tsl2772_write_raw, \ + .read_event_value = &tsl2772_read_event_value, \ + .write_event_value = &tsl2772_write_event_value, \ + .read_event_config = &tsl2772_read_interrupt_config, \ + .write_event_config = &tsl2772_write_interrupt_config, \ + } + +static const struct iio_info tsl2772_device_info[] = { + TSL2772_DEVICE_INFO(ALS), + TSL2772_DEVICE_INFO(PRX), + TSL2772_DEVICE_INFO(ALSPRX), + TSL2772_DEVICE_INFO(PRX2), + TSL2772_DEVICE_INFO(ALSPRX2), }; -static const struct iio_event_spec tsl2x7x_events[] = { +static const struct iio_event_spec tsl2772_events[] = { { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_RISING, @@ -1387,7 +1392,7 @@ static const struct iio_event_spec tsl2x7x_events[] = { }, }; -static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { +static const struct tsl2772_chip_info tsl2772_chip_info_tbl[] = { [ALS] = { .channel_with_events = { { @@ -1403,8 +1408,11 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, { .type = IIO_INTENSITY, .indexed = 1, @@ -1425,6 +1433,9 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), }, { .type = IIO_INTENSITY, .indexed = 1, @@ -1432,7 +1443,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { }, }, .chan_table_elements = 3, - .info = &tsl2X7X_device_info[ALS], + .info = &tsl2772_device_info[ALS], }, [PRX] = { .channel_with_events = { @@ -1441,8 +1452,8 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, }, .channel_without_events = { @@ -1454,7 +1465,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { }, }, .chan_table_elements = 1, - .info = &tsl2X7X_device_info[PRX], + .info = &tsl2772_device_info[PRX], }, [ALSPRX] = { .channel_with_events = { @@ -1471,8 +1482,11 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, { .type = IIO_INTENSITY, .indexed = 1, @@ -1483,8 +1497,8 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, }, .channel_without_events = { @@ -1501,6 +1515,9 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), }, { .type = IIO_INTENSITY, .indexed = 1, @@ -1514,7 +1531,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { }, }, .chan_table_elements = 4, - .info = &tsl2X7X_device_info[ALSPRX], + .info = &tsl2772_device_info[ALSPRX], }, [PRX2] = { .channel_with_events = { @@ -1524,8 +1541,10 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, }, .channel_without_events = { @@ -1535,10 +1554,12 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_CALIBSCALE), }, }, .chan_table_elements = 1, - .info = &tsl2X7X_device_info[PRX2], + .info = &tsl2772_device_info[PRX2], }, [ALSPRX2] = { .channel_with_events = { @@ -1555,8 +1576,11 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, { .type = IIO_INTENSITY, .indexed = 1, @@ -1568,8 +1592,10 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE), - .event_spec = tsl2x7x_events, - .num_event_specs = ARRAY_SIZE(tsl2x7x_events), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_CALIBSCALE), + .event_spec = tsl2772_events, + .num_event_specs = ARRAY_SIZE(tsl2772_events), }, }, .channel_without_events = { @@ -1586,6 +1612,9 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), }, { .type = IIO_INTENSITY, .indexed = 1, @@ -1597,18 +1626,20 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_CALIBSCALE), + .info_mask_separate_available = + BIT(IIO_CHAN_INFO_CALIBSCALE), }, }, .chan_table_elements = 4, - .info = &tsl2X7X_device_info[ALSPRX2], + .info = &tsl2772_device_info[ALSPRX2], }, }; -static int tsl2x7x_probe(struct i2c_client *clientp, +static int tsl2772_probe(struct i2c_client *clientp, const struct i2c_device_id *id) { struct iio_dev *indio_dev; - struct tsl2X7X_chip *chip; + struct tsl2772_chip *chip; int ret; indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip)); @@ -1620,18 +1651,18 @@ static int tsl2x7x_probe(struct i2c_client *clientp, i2c_set_clientdata(clientp, indio_dev); ret = i2c_smbus_read_byte_data(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CHIPID); + TSL2772_CMD_REG | TSL2772_CHIPID); if (ret < 0) return ret; - if (tsl2x7x_device_id_verif(ret, id->driver_data) <= 0) { + if (tsl2772_device_id_verif(ret, id->driver_data) <= 0) { dev_info(&chip->client->dev, "%s: i2c device found does not match expected id\n", __func__); return -EINVAL; } - ret = i2c_smbus_write_byte(clientp, TSL2X7X_CMD_REG | TSL2X7X_CNTRL); + ret = i2c_smbus_write_byte(clientp, TSL2772_CMD_REG | TSL2772_CNTRL); if (ret < 0) { dev_err(&clientp->dev, "%s: Failed to write to CMD register: %d\n", @@ -1642,11 +1673,11 @@ static int tsl2x7x_probe(struct i2c_client *clientp, mutex_init(&chip->als_mutex); mutex_init(&chip->prox_mutex); - chip->tsl2x7x_chip_status = TSL2X7X_CHIP_UNKNOWN; + chip->tsl2772_chip_status = TSL2772_CHIP_UNKNOWN; chip->pdata = dev_get_platdata(&clientp->dev); chip->id = id->driver_data; chip->chip_info = - &tsl2x7x_chip_info_tbl[device_channel_config[id->driver_data]]; + &tsl2772_chip_info_tbl[device_channel_config[id->driver_data]]; indio_dev->info = chip->chip_info->info; indio_dev->dev.parent = &clientp->dev; @@ -1659,10 +1690,10 @@ static int tsl2x7x_probe(struct i2c_client *clientp, ret = devm_request_threaded_irq(&clientp->dev, clientp->irq, NULL, - &tsl2x7x_event_handler, + &tsl2772_event_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "TSL2X7X_event", + "TSL2772_event", indio_dev); if (ret) { dev_err(&clientp->dev, @@ -1673,11 +1704,14 @@ static int tsl2x7x_probe(struct i2c_client *clientp, indio_dev->channels = chip->chip_info->channel_without_events; } - tsl2x7x_defaults(chip); - tsl2x7x_chip_on(indio_dev); + tsl2772_defaults(chip); + ret = tsl2772_chip_on(indio_dev); + if (ret < 0) + return ret; ret = iio_device_register(indio_dev); if (ret) { + tsl2772_chip_off(indio_dev); dev_err(&clientp->dev, "%s: iio registration failed\n", __func__); return ret; @@ -1686,32 +1720,32 @@ static int tsl2x7x_probe(struct i2c_client *clientp, return 0; } -static int tsl2x7x_suspend(struct device *dev) +static int tsl2772_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - return tsl2x7x_chip_off(indio_dev); + return tsl2772_chip_off(indio_dev); } -static int tsl2x7x_resume(struct device *dev) +static int tsl2772_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - return tsl2x7x_chip_on(indio_dev); + return tsl2772_chip_on(indio_dev); } -static int tsl2x7x_remove(struct i2c_client *client) +static int tsl2772_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); - tsl2x7x_chip_off(indio_dev); + tsl2772_chip_off(indio_dev); iio_device_unregister(indio_dev); return 0; } -static const struct i2c_device_id tsl2x7x_idtable[] = { +static const struct i2c_device_id tsl2772_idtable[] = { { "tsl2571", tsl2571 }, { "tsl2671", tsl2671 }, { "tmd2671", tmd2671 }, @@ -1725,9 +1759,9 @@ static const struct i2c_device_id tsl2x7x_idtable[] = { {} }; -MODULE_DEVICE_TABLE(i2c, tsl2x7x_idtable); +MODULE_DEVICE_TABLE(i2c, tsl2772_idtable); -static const struct of_device_id tsl2x7x_of_match[] = { +static const struct of_device_id tsl2772_of_match[] = { { .compatible = "amstaos,tsl2571" }, { .compatible = "amstaos,tsl2671" }, { .compatible = "amstaos,tmd2671" }, @@ -1740,27 +1774,27 @@ static const struct of_device_id tsl2x7x_of_match[] = { { .compatible = "amstaos,tmd2772" }, {} }; -MODULE_DEVICE_TABLE(of, tsl2x7x_of_match); +MODULE_DEVICE_TABLE(of, tsl2772_of_match); -static const struct dev_pm_ops tsl2x7x_pm_ops = { - .suspend = tsl2x7x_suspend, - .resume = tsl2x7x_resume, +static const struct dev_pm_ops tsl2772_pm_ops = { + .suspend = tsl2772_suspend, + .resume = tsl2772_resume, }; -static struct i2c_driver tsl2x7x_driver = { +static struct i2c_driver tsl2772_driver = { .driver = { - .name = "tsl2x7x", - .of_match_table = tsl2x7x_of_match, - .pm = &tsl2x7x_pm_ops, + .name = "tsl2772", + .of_match_table = tsl2772_of_match, + .pm = &tsl2772_pm_ops, }, - .id_table = tsl2x7x_idtable, - .probe = tsl2x7x_probe, - .remove = tsl2x7x_remove, + .id_table = tsl2772_idtable, + .probe = tsl2772_probe, + .remove = tsl2772_remove, }; -module_i2c_driver(tsl2x7x_driver); +module_i2c_driver(tsl2772_driver); MODULE_AUTHOR("J. August Brenner <Jon.Brenner@ams.com>"); MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>"); -MODULE_DESCRIPTION("TAOS tsl2x7x ambient and proximity light sensor driver"); +MODULE_DESCRIPTION("TAOS tsl2772 ambient and proximity light sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index b34ace76d31b..f063355480ba 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -26,6 +26,7 @@ #define MAG3110_OUT_Y 0x03 #define MAG3110_OUT_Z 0x05 #define MAG3110_WHO_AM_I 0x07 +#define MAG3110_SYSMOD 0x08 #define MAG3110_OFF_X 0x09 /* MSB first */ #define MAG3110_OFF_Y 0x0b #define MAG3110_OFF_Z 0x0d @@ -39,6 +40,8 @@ #define MAG3110_CTRL_DR_SHIFT 5 #define MAG3110_CTRL_DR_DEFAULT 0 +#define MAG3110_SYSMOD_MODE_MASK GENMASK(1, 0) + #define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */ #define MAG3110_CTRL_AC BIT(0) /* continuous measurements */ @@ -52,17 +55,20 @@ struct mag3110_data { struct i2c_client *client; struct mutex lock; u8 ctrl_reg1; + int sleep_val; }; static int mag3110_request(struct mag3110_data *data) { int ret, tries = 150; - /* trigger measurement */ - ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, - data->ctrl_reg1 | MAG3110_CTRL_TM); - if (ret < 0) - return ret; + if ((data->ctrl_reg1 & MAG3110_CTRL_AC) == 0) { + /* trigger measurement */ + ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, + data->ctrl_reg1 | MAG3110_CTRL_TM); + if (ret < 0) + return ret; + } while (tries-- > 0) { ret = i2c_smbus_read_byte_data(data->client, MAG3110_STATUS); @@ -71,7 +77,11 @@ static int mag3110_request(struct mag3110_data *data) /* wait for data ready */ if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY) break; - msleep(20); + + if (data->sleep_val <= 20) + usleep_range(data->sleep_val * 250, data->sleep_val * 500); + else + msleep(20); } if (tries < 0) { @@ -144,6 +154,117 @@ static int mag3110_get_samp_freq_index(struct mag3110_data *data, val2); } +static int mag3110_calculate_sleep(struct mag3110_data *data) +{ + int ret, i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT; + + if (mag3110_samp_freq[i][0] > 0) + ret = 1000 / mag3110_samp_freq[i][0]; + else + ret = 1000; + + return ret == 0 ? 1 : ret; +} + +static int mag3110_standby(struct mag3110_data *data) +{ + return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, + data->ctrl_reg1 & ~MAG3110_CTRL_AC); +} + +static int mag3110_wait_standby(struct mag3110_data *data) +{ + int ret, tries = 30; + + /* + * Takes up to 1/ODR to come out of active mode into stby + * Longest expected period is 12.5seconds. + * We'll sleep for 500ms between checks + */ + while (tries-- > 0) { + ret = i2c_smbus_read_byte_data(data->client, MAG3110_SYSMOD); + if (ret < 0) { + dev_err(&data->client->dev, "i2c error\n"); + return ret; + } + /* wait for standby */ + if ((ret & MAG3110_SYSMOD_MODE_MASK) == 0) + break; + + msleep_interruptible(500); + } + + if (tries < 0) { + dev_err(&data->client->dev, "device not entering standby mode\n"); + return -EIO; + } + + return 0; +} + +static int mag3110_active(struct mag3110_data *data) +{ + return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, + data->ctrl_reg1); +} + +/* returns >0 if active, 0 if in standby and <0 on error */ +static int mag3110_is_active(struct mag3110_data *data) +{ + int reg; + + reg = i2c_smbus_read_byte_data(data->client, MAG3110_CTRL_REG1); + if (reg < 0) + return reg; + + return reg & MAG3110_CTRL_AC; +} + +static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val) +{ + int ret; + int is_active; + + mutex_lock(&data->lock); + + is_active = mag3110_is_active(data); + if (is_active < 0) { + ret = is_active; + goto fail; + } + + /* config can only be changed when in standby */ + if (is_active > 0) { + ret = mag3110_standby(data); + if (ret < 0) + goto fail; + } + + /* + * After coming out of active we must wait for the part + * to transition to STBY. This can take up to 1 /ODR to occur + */ + ret = mag3110_wait_standby(data); + if (ret < 0) + goto fail; + + ret = i2c_smbus_write_byte_data(data->client, reg, val); + if (ret < 0) + goto fail; + + if (is_active > 0) { + ret = mag3110_active(data); + if (ret < 0) + goto fail; + } + + ret = 0; +fail: + mutex_unlock(&data->lock); + + return ret; +} + static int mag3110_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -235,11 +356,15 @@ static int mag3110_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; break; } - - data->ctrl_reg1 &= ~MAG3110_CTRL_DR_MASK; + data->ctrl_reg1 &= 0xff & ~MAG3110_CTRL_DR_MASK + & ~MAG3110_CTRL_AC; data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT; - ret = i2c_smbus_write_byte_data(data->client, - MAG3110_CTRL_REG1, data->ctrl_reg1); + data->sleep_val = mag3110_calculate_sleep(data); + if (data->sleep_val < 40) + data->ctrl_reg1 |= MAG3110_CTRL_AC; + + ret = mag3110_change_config(data, MAG3110_CTRL_REG1, + data->ctrl_reg1); break; case IIO_CHAN_INFO_CALIBBIAS: if (val < -10000 || val > 10000) { @@ -337,12 +462,6 @@ static const struct iio_info mag3110_info = { static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0}; -static int mag3110_standby(struct mag3110_data *data) -{ - return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, - data->ctrl_reg1 & ~MAG3110_CTRL_AC); -} - static int mag3110_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -374,8 +493,11 @@ static int mag3110_probe(struct i2c_client *client, indio_dev->available_scan_masks = mag3110_scan_masks; data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT << MAG3110_CTRL_DR_SHIFT; - ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG1, - data->ctrl_reg1); + data->sleep_val = mag3110_calculate_sleep(data); + if (data->sleep_val < 40) + data->ctrl_reg1 |= MAG3110_CTRL_AC; + + ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1); if (ret < 0) return ret; diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index 85714055cc74..90e895adf997 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -411,12 +411,14 @@ static int lmp91000_remove(struct i2c_client *client) static const struct of_device_id lmp91000_of_match[] = { { .compatible = "ti,lmp91000", }, + { .compatible = "ti,lmp91002", }, { }, }; MODULE_DEVICE_TABLE(of, lmp91000_of_match); static const struct i2c_device_id lmp91000_id[] = { { "lmp91000", 0 }, + { "lmp91002", 0 }, {} }; MODULE_DEVICE_TABLE(i2c, lmp91000_id); diff --git a/drivers/iio/resolver/Kconfig b/drivers/iio/resolver/Kconfig new file mode 100644 index 000000000000..2ced9f22aa70 --- /dev/null +++ b/drivers/iio/resolver/Kconfig @@ -0,0 +1,17 @@ +# +# Resolver/Synchro drivers +# +menu "Resolver to digital converters" + +config AD2S1200 + tristate "Analog Devices ad2s1200/ad2s1205 driver" + depends on SPI + depends on GPIOLIB || COMPILE_TEST + help + Say yes here to build support for Analog Devices spi resolver + to digital converters, ad2s1200 and ad2s1205, provides direct access + via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad2s1200. +endmenu diff --git a/drivers/iio/resolver/Makefile b/drivers/iio/resolver/Makefile new file mode 100644 index 000000000000..4e1dccae07e7 --- /dev/null +++ b/drivers/iio/resolver/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Resolver/Synchro drivers +# + +obj-$(CONFIG_AD2S1200) += ad2s1200.o diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/iio/resolver/ad2s1200.c index ea7336645116..28e618af9939 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/iio/resolver/ad2s1200.c @@ -2,18 +2,19 @@ * ad2s1200.c simple support for the ADI Resolver to Digital Converters: * AD2S1200/1205 * + * Copyright (c) 2018-2018 David Veenstra <davidjulianveenstra@gmail.com> * Copyright (c) 2010-2010 Analog Devices Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/spi/spi.h> @@ -25,19 +26,24 @@ #define DRV_NAME "ad2s1200" -/* input pin sample and rdvel is controlled by driver */ -#define AD2S1200_PN 2 - /* input clock on serial interface */ #define AD2S1200_HZ 8192000 /* clock period in nano second */ #define AD2S1200_TSCLK (1000000000 / AD2S1200_HZ) +/** + * struct ad2s1200_state - driver instance specific data. + * @lock: protects both the GPIO pins and the rx buffer. + * @sdev: spi device. + * @sample: GPIO pin SAMPLE. + * @rdvel: GPIO pin RDVEL. + * @rx: buffer for spi transfers. + */ struct ad2s1200_state { struct mutex lock; struct spi_device *sdev; - int sample; - int rdvel; + struct gpio_desc *sample; + struct gpio_desc *rdvel; __be16 rx ____cacheline_aligned; }; @@ -48,39 +54,62 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev, long m) { struct ad2s1200_state *st = iio_priv(indio_dev); - int ret = 0; - - mutex_lock(&st->lock); - gpio_set_value(st->sample, 0); + int ret; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL: + /* 2 * Pi / (2^12 - 1) ~= 0.001534355 */ + *val = 0; + *val2 = 1534355; + return IIO_VAL_INT_PLUS_NANO; + case IIO_ANGL_VEL: + /* 2 * Pi ~= 6.283185 */ + *val = 6; + *val2 = 283185; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + gpiod_set_value(st->sample, 0); + + /* delay (6 * AD2S1200_TSCLK + 20) nano seconds */ + udelay(1); + gpiod_set_value(st->sample, 1); + gpiod_set_value(st->rdvel, !!(chan->type == IIO_ANGL)); + + ret = spi_read(st->sdev, &st->rx, 2); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } - /* delay (6 * AD2S1200_TSCLK + 20) nano seconds */ - udelay(1); - gpio_set_value(st->sample, 1); - gpio_set_value(st->rdvel, !!(chan->type == IIO_ANGL)); + switch (chan->type) { + case IIO_ANGL: + *val = be16_to_cpup(&st->rx) >> 4; + break; + case IIO_ANGL_VEL: + *val = sign_extend32(be16_to_cpup(&st->rx) >> 4, 11); + break; + default: + mutex_unlock(&st->lock); + return -EINVAL; + } - ret = spi_read(st->sdev, &st->rx, 2); - if (ret < 0) { + /* delay (2 * AD2S1200_TSCLK + 20) ns for sample pulse */ + udelay(1); mutex_unlock(&st->lock); - return ret; - } - switch (chan->type) { - case IIO_ANGL: - *val = be16_to_cpup(&st->rx) >> 4; - break; - case IIO_ANGL_VEL: - *val = sign_extend32(be16_to_cpup(&st->rx) >> 4, 11); - break; + return IIO_VAL_INT; default: - mutex_unlock(&st->lock); - return -EINVAL; + break; } - /* delay (2 * AD2S1200_TSCLK + 20) ns for sample pulse */ - udelay(1); - mutex_unlock(&st->lock); - - return IIO_VAL_INT; + return -EINVAL; } static const struct iio_chan_spec ad2s1200_channels[] = { @@ -89,11 +118,13 @@ static const struct iio_chan_spec ad2s1200_channels[] = { .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_ANGL_VEL, .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), } }; @@ -103,20 +134,9 @@ static const struct iio_info ad2s1200_info = { static int ad2s1200_probe(struct spi_device *spi) { - unsigned short *pins = spi->dev.platform_data; struct ad2s1200_state *st; struct iio_dev *indio_dev; - int pn, ret = 0; - - for (pn = 0; pn < AD2S1200_PN; pn++) { - ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT, - DRV_NAME); - if (ret) { - dev_err(&spi->dev, "request gpio pin %d failed\n", - pins[pn]); - return ret; - } - } + int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) @@ -126,8 +146,20 @@ static int ad2s1200_probe(struct spi_device *spi) st = iio_priv(indio_dev); mutex_init(&st->lock); st->sdev = spi; - st->sample = pins[0]; - st->rdvel = pins[1]; + + st->sample = devm_gpiod_get(&spi->dev, "adi,sample", GPIOD_OUT_LOW); + if (IS_ERR(st->sample)) { + dev_err(&spi->dev, "Failed to claim SAMPLE gpio: err=%ld\n", + PTR_ERR(st->sample)); + return PTR_ERR(st->sample); + } + + st->rdvel = devm_gpiod_get(&spi->dev, "adi,rdvel", GPIOD_OUT_LOW); + if (IS_ERR(st->rdvel)) { + dev_err(&spi->dev, "Failed to claim RDVEL gpio: err=%ld\n", + PTR_ERR(st->rdvel)); + return PTR_ERR(st->rdvel); + } indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad2s1200_info; @@ -136,17 +168,25 @@ static int ad2s1200_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels); indio_dev->name = spi_get_device_id(spi)->name; - ret = devm_iio_device_register(&spi->dev, indio_dev); - if (ret) - return ret; - spi->max_speed_hz = AD2S1200_HZ; spi->mode = SPI_MODE_3; - spi_setup(spi); + ret = spi_setup(spi); + + if (ret < 0) { + dev_err(&spi->dev, "spi_setup failed!\n"); + return ret; + } - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } +static const struct of_device_id ad2s1200_of_match[] = { + { .compatible = "adi,ad2s1200", }, + { .compatible = "adi,ad2s1205", }, + { } +}; +MODULE_DEVICE_TABLE(of, ad2s1200_of_match); + static const struct spi_device_id ad2s1200_id[] = { { "ad2s1200" }, { "ad2s1205" }, @@ -157,12 +197,14 @@ MODULE_DEVICE_TABLE(spi, ad2s1200_id); static struct spi_driver ad2s1200_driver = { .driver = { .name = DRV_NAME, + .of_match_table = of_match_ptr(ad2s1200_of_match), }, .probe = ad2s1200_probe, .id_table = ad2s1200_id, }; module_spi_driver(ad2s1200_driver); +MODULE_AUTHOR("David Veenstra <davidjulianveenstra@gmail.com>"); MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>"); MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index bd9445956511..aee2335a25a1 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -11,7 +11,6 @@ source "drivers/staging/iio/cdc/Kconfig" source "drivers/staging/iio/frequency/Kconfig" source "drivers/staging/iio/gyro/Kconfig" source "drivers/staging/iio/impedance-analyzer/Kconfig" -source "drivers/staging/iio/light/Kconfig" source "drivers/staging/iio/meter/Kconfig" source "drivers/staging/iio/resolver/Kconfig" diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index e99a375c07b9..c28d657497de 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -10,6 +10,5 @@ obj-y += cdc/ obj-y += frequency/ obj-y += gyro/ obj-y += impedance-analyzer/ -obj-y += light/ obj-y += meter/ obj-y += resolver/ diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig deleted file mode 100644 index aacb0ae58c0e..000000000000 --- a/drivers/staging/iio/light/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# Light sensors -# -menu "Light sensors" - -config TSL2x7x - tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" - depends on I2C - help - Support for: tsl2571, tsl2671, tmd2671, tsl2771, tmd2771, tsl2572, tsl2672, - tmd2672, tsl2772, tmd2772 devices. - Provides iio_events and direct access via sysfs. - -endmenu diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile deleted file mode 100644 index ab8dc3a3d10b..000000000000 --- a/drivers/staging/iio/light/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for industrial I/O Light sensors -# - -obj-$(CONFIG_TSL2x7x) += tsl2x7x.o diff --git a/drivers/staging/iio/meter/Kconfig b/drivers/staging/iio/meter/Kconfig index 64cd3704ec6e..e01eb8abcdce 100644 --- a/drivers/staging/iio/meter/Kconfig +++ b/drivers/staging/iio/meter/Kconfig @@ -3,48 +3,6 @@ # menu "Active energy metering IC" -config ADE7753 - tristate "Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADE7753 Single-Phase Multifunction - Metering IC with di/dt Sensor Interface. - - To compile this driver as a module, choose M here: the - module will be called ade7753. - -config ADE7754 - tristate "Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADE7754 Polyphase - Multifunction Energy Metering IC Driver. - - To compile this driver as a module, choose M here: the - module will be called ade7754. - -config ADE7758 - tristate "Analog Devices ADE7758 Poly Phase Multifunction Energy Metering IC Driver" - depends on SPI - select IIO_TRIGGER if IIO_BUFFER - select IIO_KFIFO_BUF if IIO_BUFFER - help - Say yes here to build support for Analog Devices ADE7758 Polyphase - Multifunction Energy Metering IC with Per Phase Information Driver. - - To compile this driver as a module, choose M here: the - module will be called ade7758. - -config ADE7759 - tristate "Analog Devices ADE7759 Active Energy Metering IC Driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADE7758 Active Energy - Metering IC with di/dt Sensor Interface. - - To compile this driver as a module, choose M here: the - module will be called ade7759. - config ADE7854 tristate "Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver" depends on SPI || I2C diff --git a/drivers/staging/iio/meter/Makefile b/drivers/staging/iio/meter/Makefile index 19e7982f5563..ed4547e38f3a 100644 --- a/drivers/staging/iio/meter/Makefile +++ b/drivers/staging/iio/meter/Makefile @@ -3,14 +3,6 @@ # Makefile for metering ic drivers # -obj-$(CONFIG_ADE7753) += ade7753.o -obj-$(CONFIG_ADE7754) += ade7754.o - -ade7758-y := ade7758_core.o -ade7758-$(CONFIG_IIO_BUFFER) += ade7758_ring.o ade7758_trigger.o -obj-$(CONFIG_ADE7758) += ade7758.o - -obj-$(CONFIG_ADE7759) += ade7759.o obj-$(CONFIG_ADE7854) += ade7854.o obj-$(CONFIG_ADE7854_I2C) += ade7854-i2c.o obj-$(CONFIG_ADE7854_SPI) += ade7854-spi.o diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c deleted file mode 100644 index 275e8dfff836..000000000000 --- a/drivers/staging/iio/meter/ade7753.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * ADE7753 Single-Phase Multifunction Metering IC with di/dt Sensor Interface - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/spi/spi.h> -#include "meter.h" - -#define ADE7753_WAVEFORM 0x01 -#define ADE7753_AENERGY 0x02 -#define ADE7753_RAENERGY 0x03 -#define ADE7753_LAENERGY 0x04 -#define ADE7753_VAENERGY 0x05 -#define ADE7753_RVAENERGY 0x06 -#define ADE7753_LVAENERGY 0x07 -#define ADE7753_LVARENERGY 0x08 -#define ADE7753_MODE 0x09 -#define ADE7753_IRQEN 0x0A -#define ADE7753_STATUS 0x0B -#define ADE7753_RSTSTATUS 0x0C -#define ADE7753_CH1OS 0x0D -#define ADE7753_CH2OS 0x0E -#define ADE7753_GAIN 0x0F -#define ADE7753_PHCAL 0x10 -#define ADE7753_APOS 0x11 -#define ADE7753_WGAIN 0x12 -#define ADE7753_WDIV 0x13 -#define ADE7753_CFNUM 0x14 -#define ADE7753_CFDEN 0x15 -#define ADE7753_IRMS 0x16 -#define ADE7753_VRMS 0x17 -#define ADE7753_IRMSOS 0x18 -#define ADE7753_VRMSOS 0x19 -#define ADE7753_VAGAIN 0x1A -#define ADE7753_VADIV 0x1B -#define ADE7753_LINECYC 0x1C -#define ADE7753_ZXTOUT 0x1D -#define ADE7753_SAGCYC 0x1E -#define ADE7753_SAGLVL 0x1F -#define ADE7753_IPKLVL 0x20 -#define ADE7753_VPKLVL 0x21 -#define ADE7753_IPEAK 0x22 -#define ADE7753_RSTIPEAK 0x23 -#define ADE7753_VPEAK 0x24 -#define ADE7753_RSTVPEAK 0x25 -#define ADE7753_TEMP 0x26 -#define ADE7753_PERIOD 0x27 -#define ADE7753_TMODE 0x3D -#define ADE7753_CHKSUM 0x3E -#define ADE7753_DIEREV 0x3F - -#define ADE7753_READ_REG(a) a -#define ADE7753_WRITE_REG(a) ((a) | 0x80) - -#define ADE7753_MAX_TX 4 -#define ADE7753_MAX_RX 4 -#define ADE7753_STARTUP_DELAY 1000 - -#define ADE7753_SPI_SLOW (u32)(300 * 1000) -#define ADE7753_SPI_BURST (u32)(1000 * 1000) -#define ADE7753_SPI_FAST (u32)(2000 * 1000) - -/** - * struct ade7753_state - device instance specific data - * @us: actual spi_device - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx, rx and write frequency - **/ -struct ade7753_state { - struct spi_device *us; - struct mutex buf_lock; - u8 tx[ADE7753_MAX_TX] ____cacheline_aligned; - u8 rx[ADE7753_MAX_RX]; -}; - -static int ade7753_spi_write_reg_8(struct device *dev, - u8 reg_address, - u8 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7753_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int __ade7753_spi_write_reg_16(struct device *dev, u8 reg_address, - u16 value) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - - st->tx[0] = ADE7753_WRITE_REG(reg_address); - st->tx[1] = (value >> 8) & 0xFF; - st->tx[2] = value & 0xFF; - - return spi_write(st->us, st->tx, 3); -} - -static int ade7753_spi_write_reg_16(struct device *dev, u8 reg_address, - u16 value) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - ret = __ade7753_spi_write_reg_16(dev, reg_address, value); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7753_spi_read_reg_8(struct device *dev, - u8 reg_address, - u8 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - ssize_t ret; - - ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address)); - if (ret < 0) { - dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); - return ret; - } - *val = ret; - - return 0; -} - -static int ade7753_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - ssize_t ret; - - ret = spi_w8r16be(st->us, ADE7753_READ_REG(reg_address)); - if (ret < 0) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - reg_address); - return ret; - } - - *val = ret; - - return 0; -} - -static int ade7753_spi_read_reg_24(struct device *dev, - u8 reg_address, - u32 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 1, - }, { - .rx_buf = st->tx, - .bits_per_word = 8, - .len = 3, - } - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7753_READ_REG(reg_address); - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); - goto error_ret; - } - *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static ssize_t ade7753_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 val; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7753_spi_read_reg_8(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7753_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 val; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7753_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7753_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u32 val; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7753_spi_read_reg_24(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7753_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u8 val; - - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7753_spi_write_reg_8(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static ssize_t ade7753_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u16 val; - - ret = kstrtou16(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7753_spi_write_reg_16(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static int ade7753_reset(struct device *dev) -{ - u16 val; - int ret; - - ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); - if (ret) - return ret; - - val |= BIT(6); /* Software Chip Reset */ - - return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); -} - -static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY); -static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY); -static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY); -static IIO_DEV_ATTR_LVAENERGY(ade7753_read_24bit, ADE7753_LVAENERGY); -static IIO_DEV_ATTR_CFDEN(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_CFDEN); -static IIO_DEV_ATTR_CFNUM(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_CFNUM); -static IIO_DEV_ATTR_CHKSUM(ade7753_read_8bit, ADE7753_CHKSUM); -static IIO_DEV_ATTR_PHCAL(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_PHCAL); -static IIO_DEV_ATTR_APOS(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_APOS); -static IIO_DEV_ATTR_SAGCYC(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_SAGCYC); -static IIO_DEV_ATTR_SAGLVL(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_SAGLVL); -static IIO_DEV_ATTR_LINECYC(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_LINECYC); -static IIO_DEV_ATTR_WDIV(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_WDIV); -static IIO_DEV_ATTR_IRMS(0644, - ade7753_read_24bit, - NULL, - ADE7753_IRMS); -static IIO_DEV_ATTR_VRMS(0444, - ade7753_read_24bit, - NULL, - ADE7753_VRMS); -static IIO_DEV_ATTR_IRMSOS(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_IRMSOS); -static IIO_DEV_ATTR_VRMSOS(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_VRMSOS); -static IIO_DEV_ATTR_WGAIN(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_WGAIN); -static IIO_DEV_ATTR_VAGAIN(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_VAGAIN); -static IIO_DEV_ATTR_PGA_GAIN(0644, - ade7753_read_16bit, - ade7753_write_16bit, - ADE7753_GAIN); -static IIO_DEV_ATTR_IPKLVL(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_IPKLVL); -static IIO_DEV_ATTR_VPKLVL(0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_VPKLVL); -static IIO_DEV_ATTR_IPEAK(0444, - ade7753_read_24bit, - NULL, - ADE7753_IPEAK); -static IIO_DEV_ATTR_VPEAK(0444, - ade7753_read_24bit, - NULL, - ADE7753_VPEAK); -static IIO_DEV_ATTR_VPERIOD(0444, - ade7753_read_16bit, - NULL, - ADE7753_PERIOD); - -static IIO_DEVICE_ATTR(choff_1, 0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_CH1OS); - -static IIO_DEVICE_ATTR(choff_2, 0644, - ade7753_read_8bit, - ade7753_write_8bit, - ADE7753_CH2OS); - -static int ade7753_set_irq(struct device *dev, bool enable) -{ - int ret; - u8 irqen; - - ret = ade7753_spi_read_reg_8(dev, ADE7753_IRQEN, &irqen); - if (ret) - goto error_ret; - - if (enable) - irqen |= BIT(3); /* Enables an interrupt when a data is - * present in the waveform register - */ - else - irqen &= ~BIT(3); - - ret = ade7753_spi_write_reg_8(dev, ADE7753_IRQEN, irqen); - -error_ret: - return ret; -} - -/* Power down the device */ -static int ade7753_stop_device(struct device *dev) -{ - u16 val; - int ret; - - ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); - if (ret) - return ret; - - val |= BIT(4); /* AD converters can be turned off */ - - return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); -} - -static int ade7753_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - struct device *dev = &indio_dev->dev; - struct ade7753_state *st = iio_priv(indio_dev); - - /* use low spi speed for init */ - st->us->mode = SPI_MODE_3; - spi_setup(st->us); - - /* Disable IRQ */ - ret = ade7753_set_irq(dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - ade7753_reset(dev); - usleep_range(ADE7753_STARTUP_DELAY, ADE7753_STARTUP_DELAY + 100); - -err_ret: - return ret; -} - -static ssize_t ade7753_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 t; - int sps; - - ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &t); - if (ret) - return ret; - - t = (t >> 11) & 0x3; - sps = 27900 / (1 + t); - - return sprintf(buf, "%d\n", sps); -} - -static ssize_t ade7753_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7753_state *st = iio_priv(indio_dev); - u16 val; - int ret; - u16 reg, t; - - ret = kstrtou16(buf, 10, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - - mutex_lock(&st->buf_lock); - - t = 27900 / val; - if (t > 0) - t--; - - if (t > 1) - st->us->max_speed_hz = ADE7753_SPI_SLOW; - else - st->us->max_speed_hz = ADE7753_SPI_FAST; - - ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, ®); - if (ret) - goto out; - - reg &= ~(3 << 11); - reg |= t << 11; - - ret = __ade7753_spi_write_reg_16(dev, ADE7753_MODE, reg); - -out: - mutex_unlock(&st->buf_lock); - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit); -static IIO_CONST_ATTR(in_temp_offset, "-25 C"); -static IIO_CONST_ATTR(in_temp_scale, "0.67 C"); - -static IIO_DEV_ATTR_SAMP_FREQ(0644, - ade7753_read_frequency, - ade7753_write_frequency); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); - -static struct attribute *ade7753_attributes[] = { - &iio_dev_attr_in_temp_raw.dev_attr.attr, - &iio_const_attr_in_temp_offset.dev_attr.attr, - &iio_const_attr_in_temp_scale.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_phcal.dev_attr.attr, - &iio_dev_attr_cfden.dev_attr.attr, - &iio_dev_attr_aenergy.dev_attr.attr, - &iio_dev_attr_laenergy.dev_attr.attr, - &iio_dev_attr_vaenergy.dev_attr.attr, - &iio_dev_attr_lvaenergy.dev_attr.attr, - &iio_dev_attr_cfnum.dev_attr.attr, - &iio_dev_attr_apos.dev_attr.attr, - &iio_dev_attr_sagcyc.dev_attr.attr, - &iio_dev_attr_saglvl.dev_attr.attr, - &iio_dev_attr_linecyc.dev_attr.attr, - &iio_dev_attr_chksum.dev_attr.attr, - &iio_dev_attr_pga_gain.dev_attr.attr, - &iio_dev_attr_wgain.dev_attr.attr, - &iio_dev_attr_choff_1.dev_attr.attr, - &iio_dev_attr_choff_2.dev_attr.attr, - &iio_dev_attr_wdiv.dev_attr.attr, - &iio_dev_attr_irms.dev_attr.attr, - &iio_dev_attr_vrms.dev_attr.attr, - &iio_dev_attr_irmsos.dev_attr.attr, - &iio_dev_attr_vrmsos.dev_attr.attr, - &iio_dev_attr_vagain.dev_attr.attr, - &iio_dev_attr_ipklvl.dev_attr.attr, - &iio_dev_attr_vpklvl.dev_attr.attr, - &iio_dev_attr_ipeak.dev_attr.attr, - &iio_dev_attr_vpeak.dev_attr.attr, - &iio_dev_attr_vperiod.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ade7753_attribute_group = { - .attrs = ade7753_attributes, -}; - -static const struct iio_info ade7753_info = { - .attrs = &ade7753_attribute_group, -}; - -static int ade7753_probe(struct spi_device *spi) -{ - int ret; - struct ade7753_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - st = iio_priv(indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &ade7753_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* Get the device into a sane initial state */ - ret = ade7753_initial_setup(indio_dev); - if (ret) - return ret; - - return iio_device_register(indio_dev); -} - -static int ade7753_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - ade7753_stop_device(&indio_dev->dev); - - return 0; -} - -static struct spi_driver ade7753_driver = { - .driver = { - .name = "ade7753", - }, - .probe = ade7753_probe, - .remove = ade7753_remove, -}; -module_spi_driver(ade7753_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Meter"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ade7753"); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c deleted file mode 100644 index 9aa067736715..000000000000 --- a/drivers/staging/iio/meter/ade7754.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * ADE7754 Polyphase Multifunction Energy Metering IC Driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include "meter.h" - -#define ADE7754_AENERGY 0x01 -#define ADE7754_RAENERGY 0x02 -#define ADE7754_LAENERGY 0x03 -#define ADE7754_VAENERGY 0x04 -#define ADE7754_RVAENERGY 0x05 -#define ADE7754_LVAENERGY 0x06 -#define ADE7754_PERIOD 0x07 -#define ADE7754_TEMP 0x08 -#define ADE7754_WFORM 0x09 -#define ADE7754_OPMODE 0x0A -#define ADE7754_MMODE 0x0B -#define ADE7754_WAVMODE 0x0C -#define ADE7754_WATMODE 0x0D -#define ADE7754_VAMODE 0x0E -#define ADE7754_IRQEN 0x0F -#define ADE7754_STATUS 0x10 -#define ADE7754_RSTATUS 0x11 -#define ADE7754_ZXTOUT 0x12 -#define ADE7754_LINCYC 0x13 -#define ADE7754_SAGCYC 0x14 -#define ADE7754_SAGLVL 0x15 -#define ADE7754_VPEAK 0x16 -#define ADE7754_IPEAK 0x17 -#define ADE7754_GAIN 0x18 -#define ADE7754_AWG 0x19 -#define ADE7754_BWG 0x1A -#define ADE7754_CWG 0x1B -#define ADE7754_AVAG 0x1C -#define ADE7754_BVAG 0x1D -#define ADE7754_CVAG 0x1E -#define ADE7754_APHCAL 0x1F -#define ADE7754_BPHCAL 0x20 -#define ADE7754_CPHCAL 0x21 -#define ADE7754_AAPOS 0x22 -#define ADE7754_BAPOS 0x23 -#define ADE7754_CAPOS 0x24 -#define ADE7754_CFNUM 0x25 -#define ADE7754_CFDEN 0x26 -#define ADE7754_WDIV 0x27 -#define ADE7754_VADIV 0x28 -#define ADE7754_AIRMS 0x29 -#define ADE7754_BIRMS 0x2A -#define ADE7754_CIRMS 0x2B -#define ADE7754_AVRMS 0x2C -#define ADE7754_BVRMS 0x2D -#define ADE7754_CVRMS 0x2E -#define ADE7754_AIRMSOS 0x2F -#define ADE7754_BIRMSOS 0x30 -#define ADE7754_CIRMSOS 0x31 -#define ADE7754_AVRMSOS 0x32 -#define ADE7754_BVRMSOS 0x33 -#define ADE7754_CVRMSOS 0x34 -#define ADE7754_AAPGAIN 0x35 -#define ADE7754_BAPGAIN 0x36 -#define ADE7754_CAPGAIN 0x37 -#define ADE7754_AVGAIN 0x38 -#define ADE7754_BVGAIN 0x39 -#define ADE7754_CVGAIN 0x3A -#define ADE7754_CHKSUM 0x3E -#define ADE7754_VERSION 0x3F - -#define ADE7754_READ_REG(a) a -#define ADE7754_WRITE_REG(a) ((a) | 0x80) - -#define ADE7754_MAX_TX 4 -#define ADE7754_MAX_RX 4 -#define ADE7754_STARTUP_DELAY 1000 - -#define ADE7754_SPI_SLOW (u32)(300 * 1000) -#define ADE7754_SPI_BURST (u32)(1000 * 1000) -#define ADE7754_SPI_FAST (u32)(2000 * 1000) - -/** - * struct ade7754_state - device instance specific data - * @us: actual spi_device - * @buf_lock: mutex to protect tx, rx and write frequency - * @tx: transmit buffer - * @rx: receive buffer - **/ -struct ade7754_state { - struct spi_device *us; - struct mutex buf_lock; - u8 tx[ADE7754_MAX_TX] ____cacheline_aligned; - u8 rx[ADE7754_MAX_RX]; -}; - -/* Unlocked version of ade7754_spi_write_reg_8 function */ -static int __ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - - st->tx[0] = ADE7754_WRITE_REG(reg_address); - st->tx[1] = val; - return spi_write(st->us, st->tx, 2); -} - -static int ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - ret = __ade7754_spi_write_reg_8(dev, reg_address, val); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7754_spi_write_reg_16(struct device *dev, - u8 reg_address, u16 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7754_WRITE_REG(reg_address); - st->tx[1] = (val >> 8) & 0xFF; - st->tx[2] = val & 0xFF; - ret = spi_write(st->us, st->tx, 3); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7754_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - int ret; - - ret = spi_w8r8(st->us, ADE7754_READ_REG(reg_address)); - if (ret < 0) { - dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); - return ret; - } - *val = ret; - - return 0; -} - -static int ade7754_spi_read_reg_16(struct device *dev, - u8 reg_address, u16 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - int ret; - - ret = spi_w8r16be(st->us, ADE7754_READ_REG(reg_address)); - if (ret < 0) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - reg_address); - return ret; - } - - *val = ret; - - return 0; -} - -static int ade7754_spi_read_reg_24(struct device *dev, - u8 reg_address, u32 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 4, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7754_READ_REG(reg_address); - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); - goto error_ret; - } - *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static ssize_t ade7754_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7754_spi_read_reg_8(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7754_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7754_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7754_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u32 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7754_spi_read_reg_24(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val & 0xFFFFFF); -} - -static ssize_t ade7754_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u8 val; - - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7754_spi_write_reg_8(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static ssize_t ade7754_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u16 val; - - ret = kstrtou16(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7754_spi_write_reg_16(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static int ade7754_reset(struct device *dev) -{ - int ret; - u8 val; - - ret = ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val); - if (ret < 0) - return ret; - - val |= BIT(6); /* Software Chip Reset */ - return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val); -} - -static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY); -static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY); -static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY); -static IIO_DEV_ATTR_LVAENERGY(ade7754_read_24bit, ADE7754_LVAENERGY); -static IIO_DEV_ATTR_VPEAK(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_VPEAK); -static IIO_DEV_ATTR_IPEAK(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_VPEAK); -static IIO_DEV_ATTR_APHCAL(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_APHCAL); -static IIO_DEV_ATTR_BPHCAL(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_BPHCAL); -static IIO_DEV_ATTR_CPHCAL(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_CPHCAL); -static IIO_DEV_ATTR_AAPOS(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_AAPOS); -static IIO_DEV_ATTR_BAPOS(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_BAPOS); -static IIO_DEV_ATTR_CAPOS(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_CAPOS); -static IIO_DEV_ATTR_WDIV(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_WDIV); -static IIO_DEV_ATTR_VADIV(0644, - ade7754_read_8bit, - ade7754_write_8bit, - ADE7754_VADIV); -static IIO_DEV_ATTR_CFNUM(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_CFNUM); -static IIO_DEV_ATTR_CFDEN(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_CFDEN); -static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_AAPGAIN); -static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_BAPGAIN); -static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(0644, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_CAPGAIN); -static IIO_DEV_ATTR_AIRMS(0444, - ade7754_read_24bit, - NULL, - ADE7754_AIRMS); -static IIO_DEV_ATTR_BIRMS(0444, - ade7754_read_24bit, - NULL, - ADE7754_BIRMS); -static IIO_DEV_ATTR_CIRMS(0444, - ade7754_read_24bit, - NULL, - ADE7754_CIRMS); -static IIO_DEV_ATTR_AVRMS(0444, - ade7754_read_24bit, - NULL, - ADE7754_AVRMS); -static IIO_DEV_ATTR_BVRMS(0444, - ade7754_read_24bit, - NULL, - ADE7754_BVRMS); -static IIO_DEV_ATTR_CVRMS(0444, - ade7754_read_24bit, - NULL, - ADE7754_CVRMS); -static IIO_DEV_ATTR_AIRMSOS(0444, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_AIRMSOS); -static IIO_DEV_ATTR_BIRMSOS(0444, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_BIRMSOS); -static IIO_DEV_ATTR_CIRMSOS(0444, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_CIRMSOS); -static IIO_DEV_ATTR_AVRMSOS(0444, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_AVRMSOS); -static IIO_DEV_ATTR_BVRMSOS(0444, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_BVRMSOS); -static IIO_DEV_ATTR_CVRMSOS(0444, - ade7754_read_16bit, - ade7754_write_16bit, - ADE7754_CVRMSOS); - -static int ade7754_set_irq(struct device *dev, bool enable) -{ - int ret; - u16 irqen; - - ret = ade7754_spi_read_reg_16(dev, ADE7754_IRQEN, &irqen); - if (ret) - return ret; - - if (enable) - irqen |= BIT(14); /* Enables an interrupt when a data is - * present in the waveform register - */ - else - irqen &= ~BIT(14); - - return ade7754_spi_write_reg_16(dev, ADE7754_IRQEN, irqen); -} - -/* Power down the device */ -static int ade7754_stop_device(struct device *dev) -{ - int ret; - u8 val; - - ret = ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val); - if (ret < 0) { - dev_err(dev, "unable to power down the device, error: %d", - ret); - return ret; - } - - val |= 7 << 3; /* ADE7754 powered down */ - return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val); -} - -static int ade7754_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - struct ade7754_state *st = iio_priv(indio_dev); - struct device *dev = &indio_dev->dev; - - /* use low spi speed for init */ - st->us->mode = SPI_MODE_3; - spi_setup(st->us); - - /* Disable IRQ */ - ret = ade7754_set_irq(dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - ade7754_reset(dev); - usleep_range(ADE7754_STARTUP_DELAY, ADE7754_STARTUP_DELAY + 100); - -err_ret: - return ret; -} - -static ssize_t ade7754_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 t; - int sps; - - ret = ade7754_spi_read_reg_8(dev, ADE7754_WAVMODE, &t); - if (ret) - return ret; - - t = (t >> 3) & 0x3; - sps = 26000 / (1 + t); - - return sprintf(buf, "%d\n", sps); -} - -static ssize_t ade7754_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7754_state *st = iio_priv(indio_dev); - u16 val; - int ret; - u8 reg, t; - - ret = kstrtou16(buf, 10, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - - mutex_lock(&st->buf_lock); - - t = 26000 / val; - if (t > 0) - t--; - - if (t > 1) - st->us->max_speed_hz = ADE7754_SPI_SLOW; - else - st->us->max_speed_hz = ADE7754_SPI_FAST; - - ret = ade7754_spi_read_reg_8(dev, ADE7754_WAVMODE, ®); - if (ret) - goto out; - - reg &= ~(3 << 3); - reg |= t << 3; - - ret = __ade7754_spi_write_reg_8(dev, ADE7754_WAVMODE, reg); - -out: - mutex_unlock(&st->buf_lock); - - return ret ? ret : len; -} -static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit); -static IIO_CONST_ATTR(in_temp_offset, "129 C"); -static IIO_CONST_ATTR(in_temp_scale, "4 C"); - -static IIO_DEV_ATTR_SAMP_FREQ(0644, - ade7754_read_frequency, - ade7754_write_frequency); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000"); - -static struct attribute *ade7754_attributes[] = { - &iio_dev_attr_in_temp_raw.dev_attr.attr, - &iio_const_attr_in_temp_offset.dev_attr.attr, - &iio_const_attr_in_temp_scale.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_aenergy.dev_attr.attr, - &iio_dev_attr_laenergy.dev_attr.attr, - &iio_dev_attr_vaenergy.dev_attr.attr, - &iio_dev_attr_lvaenergy.dev_attr.attr, - &iio_dev_attr_vpeak.dev_attr.attr, - &iio_dev_attr_ipeak.dev_attr.attr, - &iio_dev_attr_aphcal.dev_attr.attr, - &iio_dev_attr_bphcal.dev_attr.attr, - &iio_dev_attr_cphcal.dev_attr.attr, - &iio_dev_attr_aapos.dev_attr.attr, - &iio_dev_attr_bapos.dev_attr.attr, - &iio_dev_attr_capos.dev_attr.attr, - &iio_dev_attr_wdiv.dev_attr.attr, - &iio_dev_attr_vadiv.dev_attr.attr, - &iio_dev_attr_cfnum.dev_attr.attr, - &iio_dev_attr_cfden.dev_attr.attr, - &iio_dev_attr_active_power_a_gain.dev_attr.attr, - &iio_dev_attr_active_power_b_gain.dev_attr.attr, - &iio_dev_attr_active_power_c_gain.dev_attr.attr, - &iio_dev_attr_airms.dev_attr.attr, - &iio_dev_attr_birms.dev_attr.attr, - &iio_dev_attr_cirms.dev_attr.attr, - &iio_dev_attr_avrms.dev_attr.attr, - &iio_dev_attr_bvrms.dev_attr.attr, - &iio_dev_attr_cvrms.dev_attr.attr, - &iio_dev_attr_airmsos.dev_attr.attr, - &iio_dev_attr_birmsos.dev_attr.attr, - &iio_dev_attr_cirmsos.dev_attr.attr, - &iio_dev_attr_avrmsos.dev_attr.attr, - &iio_dev_attr_bvrmsos.dev_attr.attr, - &iio_dev_attr_cvrmsos.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ade7754_attribute_group = { - .attrs = ade7754_attributes, -}; - -static const struct iio_info ade7754_info = { - .attrs = &ade7754_attribute_group, -}; - -static int ade7754_probe(struct spi_device *spi) -{ - int ret; - struct ade7754_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - st = iio_priv(indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &ade7754_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* Get the device into a sane initial state */ - ret = ade7754_initial_setup(indio_dev); - if (ret) - goto powerdown_on_error; - ret = iio_device_register(indio_dev); - if (ret) - goto powerdown_on_error; - return ret; - -powerdown_on_error: - ade7754_stop_device(&indio_dev->dev); - return ret; -} - -static int ade7754_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - ade7754_stop_device(&indio_dev->dev); - - return 0; -} - -static struct spi_driver ade7754_driver = { - .driver = { - .name = "ade7754", - }, - .probe = ade7754_probe, - .remove = ade7754_remove, -}; -module_spi_driver(ade7754_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad7754"); diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h deleted file mode 100644 index 2de81b53e786..000000000000 --- a/drivers/staging/iio/meter/ade7758.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * ADE7758 Poly Phase Multifunction Energy Metering IC driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef _ADE7758_H -#define _ADE7758_H - -#define ADE7758_AWATTHR 0x01 -#define ADE7758_BWATTHR 0x02 -#define ADE7758_CWATTHR 0x03 -#define ADE7758_AVARHR 0x04 -#define ADE7758_BVARHR 0x05 -#define ADE7758_CVARHR 0x06 -#define ADE7758_AVAHR 0x07 -#define ADE7758_BVAHR 0x08 -#define ADE7758_CVAHR 0x09 -#define ADE7758_AIRMS 0x0A -#define ADE7758_BIRMS 0x0B -#define ADE7758_CIRMS 0x0C -#define ADE7758_AVRMS 0x0D -#define ADE7758_BVRMS 0x0E -#define ADE7758_CVRMS 0x0F -#define ADE7758_FREQ 0x10 -#define ADE7758_TEMP 0x11 -#define ADE7758_WFORM 0x12 -#define ADE7758_OPMODE 0x13 -#define ADE7758_MMODE 0x14 -#define ADE7758_WAVMODE 0x15 -#define ADE7758_COMPMODE 0x16 -#define ADE7758_LCYCMODE 0x17 -#define ADE7758_MASK 0x18 -#define ADE7758_STATUS 0x19 -#define ADE7758_RSTATUS 0x1A -#define ADE7758_ZXTOUT 0x1B -#define ADE7758_LINECYC 0x1C -#define ADE7758_SAGCYC 0x1D -#define ADE7758_SAGLVL 0x1E -#define ADE7758_VPINTLVL 0x1F -#define ADE7758_IPINTLVL 0x20 -#define ADE7758_VPEAK 0x21 -#define ADE7758_IPEAK 0x22 -#define ADE7758_GAIN 0x23 -#define ADE7758_AVRMSGAIN 0x24 -#define ADE7758_BVRMSGAIN 0x25 -#define ADE7758_CVRMSGAIN 0x26 -#define ADE7758_AIGAIN 0x27 -#define ADE7758_BIGAIN 0x28 -#define ADE7758_CIGAIN 0x29 -#define ADE7758_AWG 0x2A -#define ADE7758_BWG 0x2B -#define ADE7758_CWG 0x2C -#define ADE7758_AVARG 0x2D -#define ADE7758_BVARG 0x2E -#define ADE7758_CVARG 0x2F -#define ADE7758_AVAG 0x30 -#define ADE7758_BVAG 0x31 -#define ADE7758_CVAG 0x32 -#define ADE7758_AVRMSOS 0x33 -#define ADE7758_BVRMSOS 0x34 -#define ADE7758_CVRMSOS 0x35 -#define ADE7758_AIRMSOS 0x36 -#define ADE7758_BIRMSOS 0x37 -#define ADE7758_CIRMSOS 0x38 -#define ADE7758_AWAITOS 0x39 -#define ADE7758_BWAITOS 0x3A -#define ADE7758_CWAITOS 0x3B -#define ADE7758_AVAROS 0x3C -#define ADE7758_BVAROS 0x3D -#define ADE7758_CVAROS 0x3E -#define ADE7758_APHCAL 0x3F -#define ADE7758_BPHCAL 0x40 -#define ADE7758_CPHCAL 0x41 -#define ADE7758_WDIV 0x42 -#define ADE7758_VADIV 0x44 -#define ADE7758_VARDIV 0x43 -#define ADE7758_APCFNUM 0x45 -#define ADE7758_APCFDEN 0x46 -#define ADE7758_VARCFNUM 0x47 -#define ADE7758_VARCFDEN 0x48 -#define ADE7758_CHKSUM 0x7E -#define ADE7758_VERSION 0x7F - -#define ADE7758_READ_REG(a) a -#define ADE7758_WRITE_REG(a) ((a) | 0x80) - -#define ADE7758_MAX_TX 8 -#define ADE7758_MAX_RX 4 -#define ADE7758_STARTUP_DELAY 1000 - -#define AD7758_NUM_WAVSEL 5 -#define AD7758_NUM_PHSEL 3 -#define AD7758_NUM_WAVESRC (AD7758_NUM_WAVSEL * AD7758_NUM_PHSEL) - -#define AD7758_PHASE_A 0 -#define AD7758_PHASE_B 1 -#define AD7758_PHASE_C 2 -#define AD7758_CURRENT 0 -#define AD7758_VOLTAGE 1 -#define AD7758_ACT_PWR 2 -#define AD7758_REACT_PWR 3 -#define AD7758_APP_PWR 4 -#define AD7758_WT(p, w) (((w) << 2) | (p)) - -/** - * struct ade7758_state - device instance specific data - * @us: actual spi_device - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: receive buffer - * @buf_lock: mutex to protect tx, rx, read and write frequency - **/ -struct ade7758_state { - struct spi_device *us; - struct iio_trigger *trig; - u8 *tx; - u8 *rx; - struct mutex buf_lock; - struct spi_transfer ring_xfer[4]; - struct spi_message ring_msg; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - unsigned char rx_buf[8] ____cacheline_aligned; - unsigned char tx_buf[8]; - -}; - -#ifdef CONFIG_IIO_BUFFER -/* At the moment triggers are only used for ring buffer - * filling. This may change! - */ - -void ade7758_remove_trigger(struct iio_dev *indio_dev); -int ade7758_probe_trigger(struct iio_dev *indio_dev); - -ssize_t ade7758_read_data_from_ring(struct device *dev, - struct device_attribute *attr, char *buf); - -int ade7758_configure_ring(struct iio_dev *indio_dev); -void ade7758_unconfigure_ring(struct iio_dev *indio_dev); - -int ade7758_set_irq(struct device *dev, bool enable); - -int ade7758_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val); -int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val); - -#else /* CONFIG_IIO_BUFFER */ - -static inline void ade7758_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int ade7758_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static int ade7758_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void ade7758_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -static inline int ade7758_initialize_ring(struct iio_ring_buffer *ring) -{ - return 0; -} - -static inline void ade7758_uninitialize_ring(struct iio_dev *indio_dev) -{ -} - -#endif /* CONFIG_IIO_BUFFER */ - -#endif diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c deleted file mode 100644 index 4e0dbf5c5705..000000000000 --- a/drivers/staging/iio/meter/ade7758_core.c +++ /dev/null @@ -1,955 +0,0 @@ -/* - * ADE7758 Poly Phase Multifunction Energy Metering IC driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/module.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> -#include "meter.h" -#include "ade7758.h" - -static int __ade7758_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - - st->tx[0] = ADE7758_WRITE_REG(reg_address); - st->tx[1] = val; - - return spi_write(st->us, st->tx, 2); -} - -int ade7758_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - ret = __ade7758_spi_write_reg_8(dev, reg_address, val); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7758_spi_write_reg_16(struct device *dev, u8 reg_address, - u16 value) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 3, - } - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7758_WRITE_REG(reg_address); - st->tx[1] = (value >> 8) & 0xFF; - st->tx[2] = value & 0xFF; - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7758_spi_write_reg_24(struct device *dev, u8 reg_address, - u32 value) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 4, - } - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7758_WRITE_REG(reg_address); - st->tx[1] = (value >> 16) & 0xFF; - st->tx[2] = (value >> 8) & 0xFF; - st->tx[3] = value & 0xFF; - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int __ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 1, - .delay_usecs = 4, - }, - { - .tx_buf = &st->tx[1], - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 1, - }, - }; - - st->tx[0] = ADE7758_READ_REG(reg_address); - st->tx[1] = 0; - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); - goto error_ret; - } - *val = st->rx[0]; - -error_ret: - return ret; -} - -int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - ret = __ade7758_spi_read_reg_8(dev, reg_address, val); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7758_spi_read_reg_16(struct device *dev, u8 reg_address, - u16 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 1, - .delay_usecs = 4, - }, - { - .tx_buf = &st->tx[1], - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7758_READ_REG(reg_address); - st->tx[1] = 0; - st->tx[2] = 0; - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - reg_address); - goto error_ret; - } - - *val = (st->rx[0] << 8) | st->rx[1]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int ade7758_spi_read_reg_24(struct device *dev, u8 reg_address, - u32 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 1, - .delay_usecs = 4, - }, - { - .tx_buf = &st->tx[1], - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 3, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7758_READ_REG(reg_address); - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); - goto error_ret; - } - *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static ssize_t ade7758_read_8bit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - u8 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7758_spi_read_reg_8(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7758_read_16bit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - u16 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7758_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7758_read_24bit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - u32 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7758_spi_read_reg_24(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val & 0xFFFFFF); -} - -static ssize_t ade7758_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u8 val; - - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7758_spi_write_reg_8(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static ssize_t ade7758_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u16 val; - - ret = kstrtou16(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7758_spi_write_reg_16(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static int ade7758_reset(struct device *dev) -{ - int ret; - u8 val; - - ret = ade7758_spi_read_reg_8(dev, ADE7758_OPMODE, &val); - if (ret < 0) { - dev_err(dev, "Failed to read opmode reg\n"); - return ret; - } - val |= BIT(6); /* Software Chip Reset */ - ret = ade7758_spi_write_reg_8(dev, ADE7758_OPMODE, val); - if (ret < 0) - dev_err(dev, "Failed to write opmode reg\n"); - return ret; -} - -static IIO_DEV_ATTR_VPEAK(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_VPEAK); -static IIO_DEV_ATTR_IPEAK(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_VPEAK); -static IIO_DEV_ATTR_APHCAL(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_APHCAL); -static IIO_DEV_ATTR_BPHCAL(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_BPHCAL); -static IIO_DEV_ATTR_CPHCAL(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_CPHCAL); -static IIO_DEV_ATTR_WDIV(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_WDIV); -static IIO_DEV_ATTR_VADIV(0644, - ade7758_read_8bit, - ade7758_write_8bit, - ADE7758_VADIV); -static IIO_DEV_ATTR_AIRMS(0444, - ade7758_read_24bit, - NULL, - ADE7758_AIRMS); -static IIO_DEV_ATTR_BIRMS(0444, - ade7758_read_24bit, - NULL, - ADE7758_BIRMS); -static IIO_DEV_ATTR_CIRMS(0444, - ade7758_read_24bit, - NULL, - ADE7758_CIRMS); -static IIO_DEV_ATTR_AVRMS(0444, - ade7758_read_24bit, - NULL, - ADE7758_AVRMS); -static IIO_DEV_ATTR_BVRMS(0444, - ade7758_read_24bit, - NULL, - ADE7758_BVRMS); -static IIO_DEV_ATTR_CVRMS(0444, - ade7758_read_24bit, - NULL, - ADE7758_CVRMS); -static IIO_DEV_ATTR_AIRMSOS(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_AIRMSOS); -static IIO_DEV_ATTR_BIRMSOS(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_BIRMSOS); -static IIO_DEV_ATTR_CIRMSOS(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_CIRMSOS); -static IIO_DEV_ATTR_AVRMSOS(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_AVRMSOS); -static IIO_DEV_ATTR_BVRMSOS(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_BVRMSOS); -static IIO_DEV_ATTR_CVRMSOS(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_CVRMSOS); -static IIO_DEV_ATTR_AIGAIN(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_AIGAIN); -static IIO_DEV_ATTR_BIGAIN(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_BIGAIN); -static IIO_DEV_ATTR_CIGAIN(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_CIGAIN); -static IIO_DEV_ATTR_AVRMSGAIN(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_AVRMSGAIN); -static IIO_DEV_ATTR_BVRMSGAIN(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_BVRMSGAIN); -static IIO_DEV_ATTR_CVRMSGAIN(0644, - ade7758_read_16bit, - ade7758_write_16bit, - ADE7758_CVRMSGAIN); - -int ade7758_set_irq(struct device *dev, bool enable) -{ - int ret; - u32 irqen; - - ret = ade7758_spi_read_reg_24(dev, ADE7758_MASK, &irqen); - if (ret) - return ret; - - if (enable) - irqen |= BIT(16); /* Enables an interrupt when a data is - * present in the waveform register - */ - else - irqen &= ~BIT(16); - - ret = ade7758_spi_write_reg_24(dev, ADE7758_MASK, irqen); - - return ret; -} - -/* Power down the device */ -static int ade7758_stop_device(struct device *dev) -{ - int ret; - u8 val; - - ret = ade7758_spi_read_reg_8(dev, ADE7758_OPMODE, &val); - if (ret < 0) { - dev_err(dev, "Failed to read opmode reg\n"); - return ret; - } - val |= 7 << 3; /* ADE7758 powered down */ - ret = ade7758_spi_write_reg_8(dev, ADE7758_OPMODE, val); - if (ret < 0) - dev_err(dev, "Failed to write opmode reg\n"); - return ret; -} - -static int ade7758_initial_setup(struct iio_dev *indio_dev) -{ - struct ade7758_state *st = iio_priv(indio_dev); - struct device *dev = &indio_dev->dev; - int ret; - - /* use low spi speed for init */ - st->us->mode = SPI_MODE_1; - spi_setup(st->us); - - /* Disable IRQ */ - ret = ade7758_set_irq(dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - ade7758_reset(dev); - usleep_range(ADE7758_STARTUP_DELAY, ADE7758_STARTUP_DELAY + 100); - -err_ret: - return ret; -} - -static int ade7758_read_samp_freq(struct device *dev, int *val) -{ - int ret; - u8 t; - - ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, &t); - if (ret) - return ret; - - t = (t >> 5) & 0x3; - *val = 26040 / (1 << t); - - return 0; -} - -static int ade7758_write_samp_freq(struct device *dev, int val) -{ - int ret; - u8 reg, t; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7758_state *st = iio_priv(indio_dev); - - switch (val) { - case 26040: - t = 0; - break; - case 13020: - t = 1; - break; - case 6510: - t = 2; - break; - case 3255: - t = 3; - break; - default: - return -EINVAL; - } - - mutex_lock(&st->buf_lock); - - ret = __ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, ®); - if (ret) - goto out; - - reg &= ~(5 << 3); - reg |= t << 5; - - ret = __ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg); - -out: - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7758_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - - ret = ade7758_read_samp_freq(&indio_dev->dev, val); - - return ret; - default: - return -EINVAL; - } - - return ret; -} - -static int ade7758_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - int ret; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - if (val2) - return -EINVAL; - - ret = ade7758_write_samp_freq(&indio_dev->dev, val); - - return ret; - default: - return -EINVAL; - } - - return ret; -} - -static IIO_DEV_ATTR_TEMP_RAW(ade7758_read_8bit); -static IIO_CONST_ATTR(in_temp_offset, "129 C"); -static IIO_CONST_ATTR(in_temp_scale, "4 C"); - -static IIO_DEV_ATTR_AWATTHR(ade7758_read_16bit, - ADE7758_AWATTHR); -static IIO_DEV_ATTR_BWATTHR(ade7758_read_16bit, - ADE7758_BWATTHR); -static IIO_DEV_ATTR_CWATTHR(ade7758_read_16bit, - ADE7758_CWATTHR); -static IIO_DEV_ATTR_AVARHR(ade7758_read_16bit, - ADE7758_AVARHR); -static IIO_DEV_ATTR_BVARHR(ade7758_read_16bit, - ADE7758_BVARHR); -static IIO_DEV_ATTR_CVARHR(ade7758_read_16bit, - ADE7758_CVARHR); -static IIO_DEV_ATTR_AVAHR(ade7758_read_16bit, - ADE7758_AVAHR); -static IIO_DEV_ATTR_BVAHR(ade7758_read_16bit, - ADE7758_BVAHR); -static IIO_DEV_ATTR_CVAHR(ade7758_read_16bit, - ADE7758_CVAHR); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26040 13020 6510 3255"); - -static struct attribute *ade7758_attributes[] = { - &iio_dev_attr_in_temp_raw.dev_attr.attr, - &iio_const_attr_in_temp_offset.dev_attr.attr, - &iio_const_attr_in_temp_scale.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_awatthr.dev_attr.attr, - &iio_dev_attr_bwatthr.dev_attr.attr, - &iio_dev_attr_cwatthr.dev_attr.attr, - &iio_dev_attr_avarhr.dev_attr.attr, - &iio_dev_attr_bvarhr.dev_attr.attr, - &iio_dev_attr_cvarhr.dev_attr.attr, - &iio_dev_attr_avahr.dev_attr.attr, - &iio_dev_attr_bvahr.dev_attr.attr, - &iio_dev_attr_cvahr.dev_attr.attr, - &iio_dev_attr_vpeak.dev_attr.attr, - &iio_dev_attr_ipeak.dev_attr.attr, - &iio_dev_attr_aphcal.dev_attr.attr, - &iio_dev_attr_bphcal.dev_attr.attr, - &iio_dev_attr_cphcal.dev_attr.attr, - &iio_dev_attr_wdiv.dev_attr.attr, - &iio_dev_attr_vadiv.dev_attr.attr, - &iio_dev_attr_airms.dev_attr.attr, - &iio_dev_attr_birms.dev_attr.attr, - &iio_dev_attr_cirms.dev_attr.attr, - &iio_dev_attr_avrms.dev_attr.attr, - &iio_dev_attr_bvrms.dev_attr.attr, - &iio_dev_attr_cvrms.dev_attr.attr, - &iio_dev_attr_aigain.dev_attr.attr, - &iio_dev_attr_bigain.dev_attr.attr, - &iio_dev_attr_cigain.dev_attr.attr, - &iio_dev_attr_avrmsgain.dev_attr.attr, - &iio_dev_attr_bvrmsgain.dev_attr.attr, - &iio_dev_attr_cvrmsgain.dev_attr.attr, - &iio_dev_attr_airmsos.dev_attr.attr, - &iio_dev_attr_birmsos.dev_attr.attr, - &iio_dev_attr_cirmsos.dev_attr.attr, - &iio_dev_attr_avrmsos.dev_attr.attr, - &iio_dev_attr_bvrmsos.dev_attr.attr, - &iio_dev_attr_cvrmsos.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ade7758_attribute_group = { - .attrs = ade7758_attributes, -}; - -static const struct iio_chan_spec ade7758_channels[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), - .scan_index = 0, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_CURRENT, - .indexed = 1, - .channel = 0, - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), - .scan_index = 1, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 0, - .extend_name = "apparent", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), - .scan_index = 2, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 0, - .extend_name = "active", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), - .scan_index = 3, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 0, - .extend_name = "reactive", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), - .scan_index = 4, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), - .scan_index = 5, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_CURRENT, - .indexed = 1, - .channel = 1, - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), - .scan_index = 6, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 1, - .extend_name = "apparent", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), - .scan_index = 7, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 1, - .extend_name = "active", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), - .scan_index = 8, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 1, - .extend_name = "reactive", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), - .scan_index = 9, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 2, - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), - .scan_index = 10, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_CURRENT, - .indexed = 1, - .channel = 2, - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), - .scan_index = 11, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 2, - .extend_name = "apparent", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), - .scan_index = 12, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 2, - .extend_name = "active", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), - .scan_index = 13, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, { - .type = IIO_POWER, - .indexed = 1, - .channel = 2, - .extend_name = "reactive", - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), - .scan_index = 14, - .scan_type = { - .sign = 's', - .realbits = 24, - .storagebits = 32, - }, - }, - IIO_CHAN_SOFT_TIMESTAMP(15), -}; - -static const struct iio_info ade7758_info = { - .attrs = &ade7758_attribute_group, - .read_raw = &ade7758_read_raw, - .write_raw = &ade7758_write_raw, -}; - -static int ade7758_probe(struct spi_device *spi) -{ - int ret; - struct ade7758_state *st; - struct iio_dev *indio_dev; - - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - /* Allocate the comms buffers */ - st->rx = kcalloc(ADE7758_MAX_RX, sizeof(*st->rx), GFP_KERNEL); - if (!st->rx) - return -ENOMEM; - st->tx = kcalloc(ADE7758_MAX_TX, sizeof(*st->tx), GFP_KERNEL); - if (!st->tx) { - ret = -ENOMEM; - goto error_free_rx; - } - st->us = spi; - mutex_init(&st->buf_lock); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &ade7758_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ade7758_channels; - indio_dev->num_channels = ARRAY_SIZE(ade7758_channels); - - ret = ade7758_configure_ring(indio_dev); - if (ret) - goto error_free_tx; - - /* Get the device into a sane initial state */ - ret = ade7758_initial_setup(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - - if (spi->irq) { - ret = ade7758_probe_trigger(indio_dev); - if (ret) - goto error_unreg_ring_funcs; - } - - ret = iio_device_register(indio_dev); - if (ret) - goto error_remove_trigger; - - return 0; - -error_remove_trigger: - if (spi->irq) - ade7758_remove_trigger(indio_dev); -error_unreg_ring_funcs: - ade7758_unconfigure_ring(indio_dev); -error_free_tx: - kfree(st->tx); -error_free_rx: - kfree(st->rx); - return ret; -} - -static int ade7758_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ade7758_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - ade7758_stop_device(&indio_dev->dev); - ade7758_remove_trigger(indio_dev); - ade7758_unconfigure_ring(indio_dev); - kfree(st->tx); - kfree(st->rx); - - return 0; -} - -static const struct spi_device_id ade7758_id[] = { - {"ade7758", 0}, - {} -}; -MODULE_DEVICE_TABLE(spi, ade7758_id); - -static struct spi_driver ade7758_driver = { - .driver = { - .name = "ade7758", - }, - .probe = ade7758_probe, - .remove = ade7758_remove, - .id_table = ade7758_id, -}; -module_spi_driver(ade7758_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADE7758 Polyphase Multifunction Energy Metering IC Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c deleted file mode 100644 index 6d7444d6e880..000000000000 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * ADE7758 Poly Phase Multifunction Energy Metering IC driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ -#include <linux/export.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <asm/unaligned.h> - -#include <linux/iio/iio.h> -#include <linux/iio/buffer.h> -#include <linux/iio/kfifo_buf.h> -#include <linux/iio/trigger_consumer.h> -#include "ade7758.h" - -/** - * ade7758_spi_read_burst() - read data registers - * @indio_dev: the IIO device - **/ -static int ade7758_spi_read_burst(struct iio_dev *indio_dev) -{ - struct ade7758_state *st = iio_priv(indio_dev); - int ret; - - ret = spi_sync(st->us, &st->ring_msg); - if (ret) - dev_err(&st->us->dev, "problem when reading WFORM value\n"); - - return ret; -} - -static int ade7758_write_waveform_type(struct device *dev, unsigned int type) -{ - int ret; - u8 reg; - - ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, ®); - if (ret) - goto out; - - reg &= ~0x1F; - reg |= type & 0x1F; - - ret = ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg); -out: - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is too device - * specific to be rolled into the core. - */ -static irqreturn_t ade7758_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ade7758_state *st = iio_priv(indio_dev); - s64 dat64[2]; - u32 *dat32 = (u32 *)dat64; - - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - if (ade7758_spi_read_burst(indio_dev) >= 0) - *dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF; - - iio_push_to_buffers_with_timestamp(indio_dev, dat64, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -/** - * ade7758_ring_preenable() setup the parameters of the ring before enabling - * - * The complex nature of the setting of the number of bytes per datum is due - * to this driver currently ensuring that the timestamp is stored at an 8 - * byte boundary. - **/ -static int ade7758_ring_preenable(struct iio_dev *indio_dev) -{ - unsigned int channel; - - if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) - return -EINVAL; - - channel = find_first_bit(indio_dev->active_scan_mask, - indio_dev->masklength); - - ade7758_write_waveform_type(&indio_dev->dev, - indio_dev->channels[channel].address); - - return 0; -} - -static const struct iio_buffer_setup_ops ade7758_ring_setup_ops = { - .preenable = &ade7758_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .validate_scan_mask = &iio_validate_scan_mask_onehot, -}; - -void ade7758_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); -} - -int ade7758_configure_ring(struct iio_dev *indio_dev) -{ - struct ade7758_state *st = iio_priv(indio_dev); - struct iio_buffer *buffer; - int ret = 0; - - buffer = iio_kfifo_allocate(); - if (!buffer) - return -ENOMEM; - - iio_device_attach_buffer(indio_dev, buffer); - - indio_dev->setup_ops = &ade7758_ring_setup_ops; - - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ade7758_trigger_handler, - 0, - indio_dev, - "ade7759_consumer%d", - indio_dev->id); - if (!indio_dev->pollfunc) { - ret = -ENOMEM; - goto error_iio_kfifo_free; - } - - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - - st->tx_buf[0] = ADE7758_READ_REG(ADE7758_RSTATUS); - st->tx_buf[1] = 0; - st->tx_buf[2] = 0; - st->tx_buf[3] = 0; - st->tx_buf[4] = ADE7758_READ_REG(ADE7758_WFORM); - st->tx_buf[5] = 0; - st->tx_buf[6] = 0; - st->tx_buf[7] = 0; - - /* build spi ring message */ - st->ring_xfer[0].tx_buf = &st->tx_buf[0]; - st->ring_xfer[0].len = 1; - st->ring_xfer[0].bits_per_word = 8; - st->ring_xfer[0].delay_usecs = 4; - st->ring_xfer[1].rx_buf = &st->rx_buf[1]; - st->ring_xfer[1].len = 3; - st->ring_xfer[1].bits_per_word = 8; - st->ring_xfer[1].cs_change = 1; - - st->ring_xfer[2].tx_buf = &st->tx_buf[4]; - st->ring_xfer[2].len = 1; - st->ring_xfer[2].bits_per_word = 8; - st->ring_xfer[2].delay_usecs = 1; - st->ring_xfer[3].rx_buf = &st->rx_buf[5]; - st->ring_xfer[3].len = 3; - st->ring_xfer[3].bits_per_word = 8; - - spi_message_init(&st->ring_msg); - spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg); - spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg); - spi_message_add_tail(&st->ring_xfer[2], &st->ring_msg); - spi_message_add_tail(&st->ring_xfer[3], &st->ring_msg); - - return 0; - -error_iio_kfifo_free: - iio_kfifo_free(indio_dev->buffer); - return ret; -} diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c deleted file mode 100644 index 4f6b338cffeb..000000000000 --- a/drivers/staging/iio/meter/ade7758_trigger.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * ADE7758 Poly Phase Multifunction Energy Metering IC driver - * - * Copyright 2010-2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/export.h> - -#include <linux/iio/iio.h> -#include <linux/iio/trigger.h> -#include "ade7758.h" - -/** - * ade7758_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private) -{ - disable_irq_nosync(irq); - iio_trigger_poll(private); - - return IRQ_HANDLED; -} - -/** - * ade7758_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); - - dev_dbg(&indio_dev->dev, "(%d)\n", state); - return ade7758_set_irq(&indio_dev->dev, state); -} - -/** - * ade7758_trig_try_reen() try renabling irq for data rdy trigger - * @trig: the datardy trigger - **/ -static int ade7758_trig_try_reen(struct iio_trigger *trig) -{ - struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); - struct ade7758_state *st = iio_priv(indio_dev); - - enable_irq(st->us->irq); - /* irq reenabled so success! */ - return 0; -} - -static const struct iio_trigger_ops ade7758_trigger_ops = { - .set_trigger_state = &ade7758_data_rdy_trigger_set_state, - .try_reenable = &ade7758_trig_try_reen, -}; - -int ade7758_probe_trigger(struct iio_dev *indio_dev) -{ - struct ade7758_state *st = iio_priv(indio_dev); - int ret; - - st->trig = iio_trigger_alloc("%s-dev%d", - spi_get_device_id(st->us)->name, - indio_dev->id); - if (!st->trig) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->us->irq, - ade7758_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, - spi_get_device_id(st->us)->name, - st->trig); - if (ret) - goto error_free_trig; - - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &ade7758_trigger_ops; - iio_trigger_set_drvdata(st->trig, indio_dev); - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = iio_trigger_get(st->trig); - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->us->irq, st->trig); -error_free_trig: - iio_trigger_free(st->trig); -error_ret: - return ret; -} - -void ade7758_remove_trigger(struct iio_dev *indio_dev) -{ - struct ade7758_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->us->irq, st->trig); - iio_trigger_free(st->trig); -} diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c deleted file mode 100644 index c078b770fa53..000000000000 --- a/drivers/staging/iio/meter/ade7759.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * ADE7759 Active Energy Metering IC with di/dt Sensor Interface Driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> -#include <linux/module.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include "meter.h" - -#define ADE7759_WAVEFORM 0x01 -#define ADE7759_AENERGY 0x02 -#define ADE7759_RSTENERGY 0x03 -#define ADE7759_STATUS 0x04 -#define ADE7759_RSTSTATUS 0x05 -#define ADE7759_MODE 0x06 -#define ADE7759_CFDEN 0x07 -#define ADE7759_CH1OS 0x08 -#define ADE7759_CH2OS 0x09 -#define ADE7759_GAIN 0x0A -#define ADE7759_APGAIN 0x0B -#define ADE7759_PHCAL 0x0C -#define ADE7759_APOS 0x0D -#define ADE7759_ZXTOUT 0x0E -#define ADE7759_SAGCYC 0x0F -#define ADE7759_IRQEN 0x10 -#define ADE7759_SAGLVL 0x11 -#define ADE7759_TEMP 0x12 -#define ADE7759_LINECYC 0x13 -#define ADE7759_LENERGY 0x14 -#define ADE7759_CFNUM 0x15 -#define ADE7759_CHKSUM 0x1E -#define ADE7759_DIEREV 0x1F - -#define ADE7759_READ_REG(a) a -#define ADE7759_WRITE_REG(a) ((a) | 0x80) - -#define ADE7759_MAX_TX 6 -#define ADE7759_MAX_RX 6 -#define ADE7759_STARTUP_DELAY 1000 - -#define ADE7759_SPI_SLOW (u32)(300 * 1000) -#define ADE7759_SPI_BURST (u32)(1000 * 1000) -#define ADE7759_SPI_FAST (u32)(2000 * 1000) - -/** - * struct ade7759_state - device instance specific data - * @us: actual spi_device - * @buf_lock: mutex to protect tx and rx and write frequency - * @tx: transmit buffer - * @rx: receive buffer - **/ -struct ade7759_state { - struct spi_device *us; - struct mutex buf_lock; - u8 tx[ADE7759_MAX_TX] ____cacheline_aligned; - u8 rx[ADE7759_MAX_RX]; -}; - -static int ade7759_spi_write_reg_8(struct device *dev, - u8 reg_address, - u8 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7759_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/*Unlocked version of ade7759_spi_write_reg_16 function */ -static int __ade7759_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 value) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - - st->tx[0] = ADE7759_WRITE_REG(reg_address); - st->tx[1] = (value >> 8) & 0xFF; - st->tx[2] = value & 0xFF; - return spi_write(st->us, st->tx, 3); -} - -static int ade7759_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 value) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - ret = __ade7759_spi_write_reg_16(dev, reg_address, value); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7759_spi_read_reg_8(struct device *dev, - u8 reg_address, - u8 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - int ret; - - ret = spi_w8r8(st->us, ADE7759_READ_REG(reg_address)); - if (ret < 0) { - dev_err(&st->us->dev, - "problem when reading 8 bit register 0x%02X", - reg_address); - return ret; - } - *val = ret; - - return 0; -} - -static int ade7759_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - int ret; - - ret = spi_w8r16be(st->us, ADE7759_READ_REG(reg_address)); - if (ret < 0) { - dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", - reg_address); - return ret; - } - - *val = ret; - - return 0; -} - -static int ade7759_spi_read_reg_40(struct device *dev, - u8 reg_address, - u64 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 6, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7759_READ_REG(reg_address); - memset(&st->tx[1], 0, 5); - - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->us->dev, - "problem when reading 40 bit register 0x%02X", - reg_address); - goto error_ret; - } - *val = ((u64)st->rx[1] << 32) | ((u64)st->rx[2] << 24) | - (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static ssize_t ade7759_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u8 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7759_spi_read_reg_8(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7759_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7759_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t ade7759_read_40bit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u64 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = ade7759_spi_read_reg_40(dev, this_attr->address, &val); - if (ret) - return ret; - - return sprintf(buf, "%llu\n", val); -} - -static ssize_t ade7759_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u8 val; - - ret = kstrtou8(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7759_spi_write_reg_8(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static ssize_t ade7759_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - u16 val; - - ret = kstrtou16(buf, 10, &val); - if (ret) - goto error_ret; - ret = ade7759_spi_write_reg_16(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static int ade7759_reset(struct device *dev) -{ - int ret; - u16 val; - - ret = ade7759_spi_read_reg_16(dev, ADE7759_MODE, &val); - if (ret < 0) - return ret; - - val |= BIT(6); /* Software Chip Reset */ - return ade7759_spi_write_reg_16(dev, - ADE7759_MODE, - val); -} - -static IIO_DEV_ATTR_AENERGY(ade7759_read_40bit, ADE7759_AENERGY); -static IIO_DEV_ATTR_CFDEN(0644, - ade7759_read_16bit, - ade7759_write_16bit, - ADE7759_CFDEN); -static IIO_DEV_ATTR_CFNUM(0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_CFNUM); -static IIO_DEV_ATTR_CHKSUM(ade7759_read_8bit, ADE7759_CHKSUM); -static IIO_DEV_ATTR_PHCAL(0644, - ade7759_read_16bit, - ade7759_write_16bit, - ADE7759_PHCAL); -static IIO_DEV_ATTR_APOS(0644, - ade7759_read_16bit, - ade7759_write_16bit, - ADE7759_APOS); -static IIO_DEV_ATTR_SAGCYC(0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_SAGCYC); -static IIO_DEV_ATTR_SAGLVL(0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_SAGLVL); -static IIO_DEV_ATTR_LINECYC(0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_LINECYC); -static IIO_DEV_ATTR_LENERGY(ade7759_read_40bit, ADE7759_LENERGY); -static IIO_DEV_ATTR_PGA_GAIN(0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_GAIN); -static IIO_DEV_ATTR_ACTIVE_POWER_GAIN(0644, - ade7759_read_16bit, - ade7759_write_16bit, - ADE7759_APGAIN); - -static IIO_DEVICE_ATTR(choff_1, 0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_CH1OS); - -static IIO_DEVICE_ATTR(choff_2, 0644, - ade7759_read_8bit, - ade7759_write_8bit, - ADE7759_CH2OS); - -static int ade7759_set_irq(struct device *dev, bool enable) -{ - int ret; - u8 irqen; - - ret = ade7759_spi_read_reg_8(dev, ADE7759_IRQEN, &irqen); - if (ret) - goto error_ret; - - if (enable) - irqen |= BIT(3); /* Enables an interrupt when a data is - * present in the waveform register - */ - else - irqen &= ~BIT(3); - - ret = ade7759_spi_write_reg_8(dev, ADE7759_IRQEN, irqen); - -error_ret: - return ret; -} - -/* Power down the device */ -static int ade7759_stop_device(struct device *dev) -{ - int ret; - u16 val; - - ret = ade7759_spi_read_reg_16(dev, ADE7759_MODE, &val); - if (ret < 0) { - dev_err(dev, "unable to power down the device, error: %d\n", - ret); - return ret; - } - - val |= BIT(4); /* AD converters can be turned off */ - - return ade7759_spi_write_reg_16(dev, ADE7759_MODE, val); -} - -static int ade7759_initial_setup(struct iio_dev *indio_dev) -{ - int ret; - struct ade7759_state *st = iio_priv(indio_dev); - struct device *dev = &indio_dev->dev; - - /* use low spi speed for init */ - st->us->mode = SPI_MODE_3; - spi_setup(st->us); - - /* Disable IRQ */ - ret = ade7759_set_irq(dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - ade7759_reset(dev); - usleep_range(ADE7759_STARTUP_DELAY, ADE7759_STARTUP_DELAY + 100); - -err_ret: - return ret; -} - -static ssize_t ade7759_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 t; - int sps; - - ret = ade7759_spi_read_reg_16(dev, ADE7759_MODE, &t); - if (ret) - return ret; - - t = (t >> 3) & 0x3; - sps = 27900 / (1 + t); - - return sprintf(buf, "%d\n", sps); -} - -static ssize_t ade7759_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7759_state *st = iio_priv(indio_dev); - u16 val; - int ret; - u16 reg, t; - - ret = kstrtou16(buf, 10, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - - mutex_lock(&st->buf_lock); - - t = 27900 / val; - if (t > 0) - t--; - - if (t > 1) - st->us->max_speed_hz = ADE7759_SPI_SLOW; - else - st->us->max_speed_hz = ADE7759_SPI_FAST; - - ret = ade7759_spi_read_reg_16(dev, ADE7759_MODE, ®); - if (ret) - goto out; - - reg &= ~(3 << 13); - reg |= t << 13; - - ret = __ade7759_spi_write_reg_16(dev, ADE7759_MODE, reg); - -out: - mutex_unlock(&st->buf_lock); - - return ret ? ret : len; -} -static IIO_DEV_ATTR_TEMP_RAW(ade7759_read_8bit); -static IIO_CONST_ATTR(in_temp_offset, "70 C"); -static IIO_CONST_ATTR(in_temp_scale, "1 C"); - -static IIO_DEV_ATTR_SAMP_FREQ(0644, - ade7759_read_frequency, - ade7759_write_frequency); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); - -static struct attribute *ade7759_attributes[] = { - &iio_dev_attr_in_temp_raw.dev_attr.attr, - &iio_const_attr_in_temp_offset.dev_attr.attr, - &iio_const_attr_in_temp_scale.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_phcal.dev_attr.attr, - &iio_dev_attr_cfden.dev_attr.attr, - &iio_dev_attr_aenergy.dev_attr.attr, - &iio_dev_attr_cfnum.dev_attr.attr, - &iio_dev_attr_apos.dev_attr.attr, - &iio_dev_attr_sagcyc.dev_attr.attr, - &iio_dev_attr_saglvl.dev_attr.attr, - &iio_dev_attr_linecyc.dev_attr.attr, - &iio_dev_attr_lenergy.dev_attr.attr, - &iio_dev_attr_chksum.dev_attr.attr, - &iio_dev_attr_pga_gain.dev_attr.attr, - &iio_dev_attr_active_power_gain.dev_attr.attr, - &iio_dev_attr_choff_1.dev_attr.attr, - &iio_dev_attr_choff_2.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ade7759_attribute_group = { - .attrs = ade7759_attributes, -}; - -static const struct iio_info ade7759_info = { - .attrs = &ade7759_attribute_group, -}; - -static int ade7759_probe(struct spi_device *spi) -{ - int ret; - struct ade7759_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - st = iio_priv(indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &ade7759_info; - indio_dev->modes = INDIO_DIRECT_MODE; - - /* Get the device into a sane initial state */ - ret = ade7759_initial_setup(indio_dev); - if (ret) - return ret; - - return iio_device_register(indio_dev); -} - -static int ade7759_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - ade7759_stop_device(&indio_dev->dev); - - return 0; -} - -static struct spi_driver ade7759_driver = { - .driver = { - .name = "ade7759", - }, - .probe = ade7759_probe, - .remove = ade7759_remove, -}; -module_spi_driver(ade7759_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADE7759 Active Energy Metering IC Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad7759"); diff --git a/drivers/staging/iio/resolver/Kconfig b/drivers/staging/iio/resolver/Kconfig index 1c7e2860d6b7..6a469ee6101f 100644 --- a/drivers/staging/iio/resolver/Kconfig +++ b/drivers/staging/iio/resolver/Kconfig @@ -13,18 +13,6 @@ config AD2S90 To compile this driver as a module, choose M here: the module will be called ad2s90. -config AD2S1200 - tristate "Analog Devices ad2s1200/ad2s1205 driver" - depends on SPI - depends on GPIOLIB || COMPILE_TEST - help - Say yes here to build support for Analog Devices spi resolver - to digital converters, ad2s1200 and ad2s1205, provides direct access - via sysfs. - - To compile this driver as a module, choose M here: the - module will be called ad2s1200. - config AD2S1210 tristate "Analog Devices ad2s1210 driver" depends on SPI diff --git a/drivers/staging/iio/resolver/Makefile b/drivers/staging/iio/resolver/Makefile index 14375e444ebf..8d901dc7500b 100644 --- a/drivers/staging/iio/resolver/Makefile +++ b/drivers/staging/iio/resolver/Makefile @@ -3,5 +3,4 @@ # obj-$(CONFIG_AD2S90) += ad2s90.o -obj-$(CONFIG_AD2S1200) += ad2s1200.o obj-$(CONFIG_AD2S1210) += ad2s1210.o diff --git a/include/linux/iio/adc/stm32-dfsdm-adc.h b/include/linux/iio/adc/stm32-dfsdm-adc.h index e7dc7a542a4e..0da298b41737 100644 --- a/include/linux/iio/adc/stm32-dfsdm-adc.h +++ b/include/linux/iio/adc/stm32-dfsdm-adc.h @@ -9,6 +9,8 @@ #ifndef STM32_DFSDM_ADC_H #define STM32_DFSDM_ADC_H +#include <linux/iio/iio.h> + int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev, int (*cb)(const void *data, size_t size, void *private), diff --git a/drivers/staging/iio/light/tsl2x7x.h b/include/linux/platform_data/tsl2772.h index 1097ee890ce2..f8ade15a35e2 100644 --- a/drivers/staging/iio/light/tsl2x7x.h +++ b/include/linux/platform_data/tsl2772.h @@ -1,51 +1,51 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* * Device driver for monitoring ambient light intensity (lux) - * and proximity (prox) within the TAOS TSL2X7X family of devices. + * and proximity (prox) within the TAOS TSL2772 family of devices. * * Copyright (c) 2012, TAOS Corporation. + * Copyright (c) 2017-2018 Brian Masney <masneyb@onstation.org> */ -#ifndef __TSL2X7X_H -#define __TSL2X7X_H +#ifndef __TSL2772_H +#define __TSL2772_H -struct tsl2x7x_lux { +struct tsl2772_lux { unsigned int ch0; unsigned int ch1; }; /* Max number of segments allowable in LUX table */ -#define TSL2X7X_MAX_LUX_TABLE_SIZE 6 +#define TSL2772_MAX_LUX_TABLE_SIZE 6 /* The default LUX tables all have 3 elements. */ -#define TSL2X7X_DEF_LUX_TABLE_SZ 3 -#define TSL2X7X_DEFAULT_TABLE_BYTES (sizeof(struct tsl2x7x_lux) * \ - TSL2X7X_DEF_LUX_TABLE_SZ) +#define TSL2772_DEF_LUX_TABLE_SZ 3 +#define TSL2772_DEFAULT_TABLE_BYTES (sizeof(struct tsl2772_lux) * \ + TSL2772_DEF_LUX_TABLE_SZ) /* Proximity diode to use */ -#define TSL2X7X_DIODE0 0x01 -#define TSL2X7X_DIODE1 0x02 -#define TSL2X7X_DIODE_BOTH 0x03 +#define TSL2772_DIODE0 0x01 +#define TSL2772_DIODE1 0x02 +#define TSL2772_DIODE_BOTH 0x03 /* LED Power */ -#define TSL2X7X_100_mA 0x00 -#define TSL2X7X_50_mA 0x01 -#define TSL2X7X_25_mA 0x02 -#define TSL2X7X_13_mA 0x03 -#define TSL2X7X_MAX_TIMER_CNT 0xFF +#define TSL2772_100_mA 0x00 +#define TSL2772_50_mA 0x01 +#define TSL2772_25_mA 0x02 +#define TSL2772_13_mA 0x03 /** - * struct tsl2x7x_settings - Settings for the tsl2x7x driver + * struct tsl2772_settings - Settings for the tsl2772 driver * @als_time: Integration time of the ALS channel ADCs in 2.73 ms * increments. Total integration time is * (256 - als_time) * 2.73. - * @als_gain: Index into the tsl2x7x_als_gain array. + * @als_gain: Index into the tsl2772_als_gain array. * @als_gain_trim: Default gain trim to account for aperture effects. * @wait_time: Time between proximity and ALS cycles in 2.73 * periods. * @prox_time: Integration time of the proximity ADC in 2.73 ms * increments. Total integration time is * (256 - prx_time) * 2.73. - * @prox_gain: Index into the tsl2x7x_prx_gain array. + * @prox_gain: Index into the tsl2772_prx_gain array. * @als_prox_config: The value of the ALS / Proximity configuration * register. * @als_cal_target: Known external ALS reading for calibration. @@ -65,7 +65,7 @@ struct tsl2x7x_lux { * LED(s) for proximity sensing. * @prox_power The amount of power to use for the external LED(s). */ -struct tsl2x7x_settings { +struct tsl2772_settings { int als_time; int als_gain; int als_gain_trim; @@ -89,14 +89,13 @@ struct tsl2x7x_settings { }; /** - * struct tsl2X7X_platform_data - Platform callback, glass and defaults + * struct tsl2772_platform_data - Platform callback, glass and defaults * @platform_lux_table: Device specific glass coefficents * @platform_default_settings: Device specific power on defaults - * */ -struct tsl2X7X_platform_data { - struct tsl2x7x_lux platform_lux_table[TSL2X7X_MAX_LUX_TABLE_SIZE]; - struct tsl2x7x_settings *platform_default_settings; +struct tsl2772_platform_data { + struct tsl2772_lux platform_lux_table[TSL2772_MAX_LUX_TABLE_SIZE]; + struct tsl2772_settings *platform_default_settings; }; -#endif /* __TSL2X7X_H */ +#endif /* __TSL2772_H */ diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c index f0c6f54a8b2f..3040830d7797 100644 --- a/tools/iio/iio_generic_buffer.c +++ b/tools/iio/iio_generic_buffer.c @@ -248,7 +248,7 @@ void print_usage(void) "Capture, convert and output data from IIO device buffer\n" " -a Auto-activate all available channels\n" " -A Force-activate ALL channels\n" - " -c <n> Do n conversions\n" + " -c <n> Do n conversions, or loop forever if n < 0\n" " -e Disable wait for event (new data)\n" " -g Use trigger-less mode\n" " -l <n> Set buffer length to n samples\n" @@ -330,11 +330,14 @@ static const struct option longopts[] = { int main(int argc, char **argv) { - unsigned long num_loops = 2; + unsigned long long num_loops = 2; unsigned long timedelay = 1000000; unsigned long buf_len = 128; - int ret, c, i, j, toread; + ssize_t i; + unsigned long long j; + unsigned long toread; + int ret, c; int fp = -1; int num_channels = 0; @@ -366,7 +369,7 @@ int main(int argc, char **argv) break; case 'c': errno = 0; - num_loops = strtoul(optarg, &dummy, 10); + num_loops = strtoll(optarg, &dummy, 10); if (errno) { ret = -errno; goto error; @@ -634,7 +637,7 @@ int main(int argc, char **argv) goto error; } - for (j = 0; j < num_loops; j++) { + for (j = 0; j < num_loops || num_loops < 0; j++) { if (!noevents) { struct pollfd pfd = { .fd = fp, |