diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-29 15:53:42 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-29 15:53:42 +0200 |
commit | ca9280d1f82a7a0165a683dc09f182329ebec352 (patch) | |
tree | 201ebf8240be3cc1e423e6ed6a5001d729e0f739 /drivers/iio | |
parent | 13253d808d42dee88a53aa0fa57c5de4e6a460ed (diff) | |
parent | 7e87d11c9bda75816ced8d0895e8d24e5c52833a (diff) |
Merge tag 'iio-for-4.13a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
First set of new device support, features and cleanups for IIO in the 4.13 cycle
Two entirely new drivers in here plus the usual range of cleanups and features.
New device support
* ad5064
- add ltc2631, ltc2633 and ltc2635 support.
* bma180
- trivial support for bma250e (new id)
* hid-sensor-rotation
- add relative orientation and geometric orientation support.
* isl29028
- add isl29030 support (its effectively the same part from a driver point of
view)
* maxim_thermocouple
- add max31856 id.
* meson-saradc
- add meson8b SoC adc support.
* ti-adc084s021
- new driver and bindings.
* ti-adc108s102
- new driver and bindings.
Staging graduations
* isl29028
Features
* bma180
- ACPI enumeration for BMA250E which is used in various x86 tablets.
* hi8453
- add raw access rather than only events.
* hid-sensor-hub
- Implement batch mode in which we can set a threshold on the amount of time
between data coming from the fifos. This is the first device to do this
rather than use a watershed on the number of samples.
* hts221
- power management support
* lsm6dsx
- add system power management support.
* rpr0521
- sampling frequency read / write
* stm32-trigger
- add support for TRG02 triggers.
* tsl2583
- runtime power management support.
Cleanups
* core
- inkern: fix a double unlock in iio_read_available_channel_raw when raw
value doesn't appear to be raw (error path).
- fixup accidental sizeof pointer in iio_device_add_mask_type.
* docs
- fix an accidental duplicated line in sysfs-bus-iio-meas-spec.
* tools
- use local include/uapi headers to ensure always up to date.
- increase length of allowed trigger names.
* ad9834
- symbolic to octal permissions.
* ade7753
- symbolic to octal permissions.
- fix indentation
* ade7754
- symbolic to octal permissions.
* ade7758
- symbolic to octal permissions.
- ade7854
- symbolic to octal permissions.
* as3935
- move out of storm check to given consistent results for raw and processed
values.
* bmp280
- fix bme280 naming in Kconfig help.
* hi8435
- avoid garbage on event after enable.
- add missing in_voltage_sensing_mode_available to list possible enum options.
- handle the reset gpio with the obvious polarity rather than relying on
DT to provide it correctly.
* hid-sensors
- fix a wrong error path scrubbing of return values.
* hid-sensors-accel
- drop static on a local variable
* hid-sensors-rotation
- Add missing scale and offset property parsing support.
* ina2xx
- Fix a bad use of GENMASK and some typos and whitespace issues.
* isl29018
- only declare the ACPI table when ACPI is enabled.
* isl29028
- fix proximity sleep times.
* lsm6dsx
- replace ifdef CONFIG_PM with __maybe_unused to avoid the complexity of
dealing with the various PM config variables.
* meson-saradc
- mark meson_sar_adc_data static and const.
* rcar-gyroadc
- derive the interface clock speed from the fck clock on the basis they are
the same actual clock.
- drop the now unused if clock from the bindings.
* rpr0521
- disable sensor when marked as such rather than always enabling it.
- poweroff if probe fails and we can talk to device.
- make sure device powered off when it doesn't need to be on.
- use sizeof rather than hardcoded size on value read.
- whitespace fixup.
- reorder channel numbers ready for buffered support which didn't quite
make this pull request.
* st-accel
- fix platform data initialization to allow remove and reprobe.
* st-pressure
- fix platform data initialization to allow remove and reprobe.
* tsl2x7x
- S_IRUGO, S_IWUSR to octal values
- rename driver for consistency with more recent drivers
- drop FSF mailing address
- replace DEVICE_ATTR macros with the shorter DEVICE_ATTR_RW form and
relevant function renames.
* zpa2326
- report an error for consistency with other error paths.
Diffstat (limited to 'drivers/iio')
39 files changed, 2379 insertions, 186 deletions
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index efc67739c28f..17b7953f2502 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -14,6 +14,7 @@ * BMA250: 7-bit I2C slave address 0x18 or 0x19 */ +#include <linux/acpi.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/interrupt.h> @@ -36,6 +37,7 @@ enum chip_ids { BMA180, BMA250, + BMA250E, }; struct bma180_data; @@ -55,6 +57,7 @@ struct bma180_part_info { u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; u8 softreset_reg; + u8 chip_id; int (*chip_config)(struct bma180_data *data); void (*chip_disable)(struct bma180_data *data); @@ -112,6 +115,8 @@ struct bma180_part_info { #define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ +#define BMA250E_CHIP_ID 0xf9 + struct bma180_data { struct i2c_client *client; struct iio_trigger *trig; @@ -309,7 +314,7 @@ static int bma180_chip_init(struct bma180_data *data) if (ret < 0) return ret; - if (ret != BMA180_ID_REG_VAL) + if (ret != data->part_info->chip_id) return -ENODEV; ret = bma180_soft_reset(data); @@ -632,6 +637,7 @@ static const struct bma180_part_info bma180_part_info[] = { BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER, BMA180_CTRL_REG3, BMA180_NEW_DATA_INT, BMA180_RESET, + BMA180_CHIP_ID, bma180_chip_config, bma180_chip_disable, }, @@ -646,6 +652,22 @@ static const struct bma180_part_info bma180_part_info[] = { BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, BMA250_RESET_REG, + BMA180_CHIP_ID, + bma250_chip_config, + bma250_chip_disable, + }, + [BMA250E] = { + bma250_channels, ARRAY_SIZE(bma250_channels), + bma250_scale_table, ARRAY_SIZE(bma250_scale_table), + bma250_bw_table, ARRAY_SIZE(bma250_bw_table), + BMA250_INT_RESET_REG, BMA250_INT_RESET_MASK, + BMA250_POWER_REG, BMA250_SUSPEND_MASK, + BMA250_BW_REG, BMA250_BW_MASK, + BMA250_RANGE_REG, BMA250_RANGE_MASK, + BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, + BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, + BMA250_RESET_REG, + BMA250E_CHIP_ID, bma250_chip_config, bma250_chip_disable, }, @@ -706,6 +728,8 @@ static const struct iio_trigger_ops bma180_trigger_ops = { static int bma180_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + const struct acpi_device_id *acpi_id; struct bma180_data *data; struct iio_dev *indio_dev; enum chip_ids chip; @@ -718,10 +742,17 @@ static int bma180_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - if (client->dev.of_node) + if (dev->of_node) { chip = (enum chip_ids)of_device_get_match_data(&client->dev); - else + } else if (id) { chip = id->driver_data; + } else { + acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!acpi_id) + return -ENODEV; + + chip = acpi_id->driver_data; + } data->part_info = &bma180_part_info[chip]; ret = data->part_info->chip_config(data); @@ -842,9 +873,16 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); #define BMA180_PM_OPS NULL #endif +static const struct acpi_device_id bma180_acpi_match[] = { + { "BMA250E", BMA250E }, + { } +}; +MODULE_DEVICE_TABLE(acpi, bma180_acpi_match); + static struct i2c_device_id bma180_ids[] = { { "bma180", BMA180 }, { "bma250", BMA250 }, + { "bma250e", BMA250E }, { } }; @@ -866,6 +904,7 @@ MODULE_DEVICE_TABLE(of, bma180_of_match); static struct i2c_driver bma180_driver = { .driver = { .name = "bma180", + .acpi_match_table = ACPI_PTR(bma180_acpi_match), .pm = BMA180_PM_OPS, .of_match_table = bma180_of_match, }, diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 43a6cb078193..2238a26aba63 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -347,7 +347,7 @@ static int accel_3d_parse_report(struct platform_device *pdev, static int hid_accel_3d_probe(struct platform_device *pdev) { int ret = 0; - static const char *name; + const char *name; struct iio_dev *indio_dev; struct accel_3d_state *accel_state; const struct iio_chan_spec *channel_spec; diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 784670e2736b..07d1489cd457 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -710,6 +710,8 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); + struct st_sensors_platform_data *pdata = + (struct st_sensors_platform_data *)adata->dev->platform_data; int irq = adata->get_irq_data_ready(indio_dev); int err; @@ -736,9 +738,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev) &adata->sensor_settings->fs.fs_avl[0]; adata->odr = adata->sensor_settings->odr.odr_avl[0].hz; - if (!adata->dev->platform_data) - adata->dev->platform_data = - (struct st_sensors_platform_data *)&default_accel_pdata; + if (!pdata) + pdata = (struct st_sensors_platform_data *)&default_accel_pdata; err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); if (err < 0) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 401f47b51d83..614fa41559b1 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -679,6 +679,18 @@ config TI_ADC0832 This driver can also be built as a module. If so, the module will be called ti-adc0832. +config TI_ADC084S021 + tristate "Texas Instruments ADC084S021" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC084S021 + chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc084s021. + config TI_ADC12138 tristate "Texas Instruments ADC12130/ADC12132/ADC12138" depends on SPI @@ -691,6 +703,18 @@ config TI_ADC12138 This driver can also be built as a module. If so, the module will be called ti-adc12138. +config TI_ADC108S102 + tristate "Texas Instruments ADC108S102 and ADC128S102 driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Texas Instruments ADC108S102 and + ADC128S102 ADC. + + To compile this driver as a module, choose M here: the module will + be called ti-adc108s102. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 9339bec4babe..b546736a5541 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -62,7 +62,9 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o +obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o +obj-$(CONFIG_TI_ADC108S102) += ti-adc108s102.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 678e8c7ea763..ab59969b7c49 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -105,6 +105,26 @@ static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val) return spi_write(priv->spi, priv->reg_buffer, 3); } +static int hi8435_read_raw(struct iio_dev *idev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct hi8435_priv *priv = iio_priv(idev); + u32 tmp; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp); + if (ret < 0) + return ret; + *val = !!(tmp & BIT(chan->channel)); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + static int hi8435_read_event_config(struct iio_dev *idev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -121,10 +141,21 @@ static int hi8435_write_event_config(struct iio_dev *idev, enum iio_event_direction dir, int state) { struct hi8435_priv *priv = iio_priv(idev); + int ret; + u32 tmp; + + if (state) { + ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp); + if (ret < 0) + return ret; + if (tmp & BIT(chan->channel)) + priv->event_prev_val |= BIT(chan->channel); + else + priv->event_prev_val &= ~BIT(chan->channel); - priv->event_scan_mask &= ~BIT(chan->channel); - if (state) priv->event_scan_mask |= BIT(chan->channel); + } else + priv->event_scan_mask &= ~BIT(chan->channel); return 0; } @@ -325,6 +356,7 @@ static const struct iio_enum hi8435_sensing_mode = { static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode), + IIO_ENUM_AVAILABLE("sensing_mode", &hi8435_sensing_mode), {}, }; @@ -333,6 +365,7 @@ static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .event_spec = hi8435_events, \ .num_event_specs = ARRAY_SIZE(hi8435_events), \ .ext_info = hi8435_ext_info, \ @@ -376,6 +409,7 @@ static const struct iio_chan_spec hi8435_channels[] = { static const struct iio_info hi8435_info = { .driver_module = THIS_MODULE, + .read_raw = hi8435_read_raw, .read_event_config = &hi8435_read_event_config, .write_event_config = hi8435_write_event_config, .read_event_value = &hi8435_read_event_value, @@ -442,13 +476,15 @@ static int hi8435_probe(struct spi_device *spi) priv->spi = spi; reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW); - if (IS_ERR(reset_gpio)) { - /* chip s/w reset if h/w reset failed */ + if (!IS_ERR(reset_gpio)) { + /* need >=100ns low pulse to reset chip */ + gpiod_set_raw_value_cansleep(reset_gpio, 0); + udelay(1); + gpiod_set_raw_value_cansleep(reset_gpio, 1); + } else { + /* s/w reset chip if h/w reset is not available */ hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST); hi8435_writeb(priv, HI8435_CTRL_REG, 0); - } else { - udelay(5); - gpiod_set_value(reset_gpio, 1); } spi_set_drvdata(spi, idev); diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index db9838230257..6b588ac3130c 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -42,8 +42,8 @@ #define INA2XX_CURRENT 0x04 /* readonly */ #define INA2XX_CALIBRATION 0x05 -#define INA226_ALERT_MASK GENMASK(2, 1) -#define INA266_CVRF BIT(3) +#define INA226_MASK_ENABLE 0x06 +#define INA226_CVRF BIT(3) #define INA2XX_MAX_REGISTERS 8 @@ -417,8 +417,8 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, .address = (_address), \ .indexed = 1, \ .channel = (_index), \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ - | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .scan_index = (_index), \ @@ -481,12 +481,12 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) */ if (!chip->allow_async_readout) do { - ret = regmap_read(chip->regmap, INA226_ALERT_MASK, + ret = regmap_read(chip->regmap, INA226_MASK_ENABLE, &alert); if (ret < 0) return ret; - alert &= INA266_CVRF; + alert &= INA226_CVRF; } while (!alert); /* diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index dd4190b50df6..81cd39a57fe3 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -220,6 +220,7 @@ enum meson_sar_adc_chan7_mux_sel { }; struct meson_sar_adc_data { + bool has_bl30_integration; unsigned int resolution; const char *name; }; @@ -437,19 +438,24 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); - /* prevent BL30 from using the SAR ADC while we are using it */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY); - - /* wait until BL30 releases it's lock (so we can use the SAR ADC) */ - do { - udelay(1); - regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); - } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); - - if (timeout < 0) - return -ETIMEDOUT; + if (priv->data->has_bl30_integration) { + /* prevent BL30 from using the SAR ADC while we are using it */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY); + + /* + * wait until BL30 releases it's lock (so we can use the SAR + * ADC) + */ + do { + udelay(1); + regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); + } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); + + if (timeout < 0) + return -ETIMEDOUT; + } return 0; } @@ -458,9 +464,10 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - /* allow BL30 to use the SAR ADC again */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); + if (priv->data->has_bl30_integration) + /* allow BL30 to use the SAR ADC again */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); mutex_unlock(&indio_dev->mlock); } @@ -614,14 +621,16 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) */ meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); - /* - * leave sampling delay and the input clocks as configured by BL30 to - * make sure BL30 gets the values it expects when reading the - * temperature sensor. - */ - regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); - if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) - return 0; + if (priv->data->has_bl30_integration) { + /* + * leave sampling delay and the input clocks as configured by + * BL30 to make sure BL30 gets the values it expects when + * reading the temperature sensor. + */ + regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); + if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) + return 0; + } meson_sar_adc_stop_sample_engine(indio_dev); @@ -834,23 +843,46 @@ static const struct iio_info meson_sar_adc_iio_info = { .driver_module = THIS_MODULE, }; -struct meson_sar_adc_data meson_sar_adc_gxbb_data = { +static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { + .has_bl30_integration = false, + .resolution = 10, + .name = "meson-meson8-saradc", +}; + +static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { + .has_bl30_integration = false, + .resolution = 10, + .name = "meson-meson8b-saradc", +}; + +static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { + .has_bl30_integration = true, .resolution = 10, .name = "meson-gxbb-saradc", }; -struct meson_sar_adc_data meson_sar_adc_gxl_data = { +static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { + .has_bl30_integration = true, .resolution = 12, .name = "meson-gxl-saradc", }; -struct meson_sar_adc_data meson_sar_adc_gxm_data = { +static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { + .has_bl30_integration = true, .resolution = 12, .name = "meson-gxm-saradc", }; static const struct of_device_id meson_sar_adc_of_match[] = { { + .compatible = "amlogic,meson8-saradc", + .data = &meson_sar_adc_meson8_data, + }, + { + .compatible = "amlogic,meson8b-saradc", + .data = &meson_sar_adc_meson8b_data, + }, + { .compatible = "amlogic,meson-gxbb-saradc", .data = &meson_sar_adc_gxbb_data, }, { diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 018ed360e717..27a318164619 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -73,7 +73,7 @@ enum rcar_gyroadc_model { struct rcar_gyroadc { struct device *dev; void __iomem *regs; - struct clk *iclk; + struct clk *clk; struct regulator *vref[8]; unsigned int num_channels; enum rcar_gyroadc_model model; @@ -83,7 +83,7 @@ struct rcar_gyroadc { static void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv) { - const unsigned long clk_mhz = clk_get_rate(priv->iclk) / 1000000; + const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000; const unsigned long clk_mul = (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5; unsigned long clk_len = clk_mhz * clk_mul; @@ -510,9 +510,9 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) if (IS_ERR(priv->regs)) return PTR_ERR(priv->regs); - priv->iclk = devm_clk_get(dev, "if"); - if (IS_ERR(priv->iclk)) { - ret = PTR_ERR(priv->iclk); + priv->clk = devm_clk_get(dev, "fck"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get IF clock (ret=%i)\n", ret); return ret; @@ -536,7 +536,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) indio_dev->info = &rcar_gyroadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = clk_prepare_enable(priv->iclk); + ret = clk_prepare_enable(priv->clk); if (ret) { dev_err(dev, "Could not prepare or enable the IF clock.\n"); goto err_clk_if_enable; @@ -565,7 +565,7 @@ err_iio_device_register: pm_runtime_put_sync(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - clk_disable_unprepare(priv->iclk); + clk_disable_unprepare(priv->clk); err_clk_if_enable: rcar_gyroadc_deinit_supplies(indio_dev); @@ -584,7 +584,7 @@ static int rcar_gyroadc_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - clk_disable_unprepare(priv->iclk); + clk_disable_unprepare(priv->clk); rcar_gyroadc_deinit_supplies(indio_dev); return 0; diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c new file mode 100644 index 000000000000..a355121c11a4 --- /dev/null +++ b/drivers/iio/adc/ti-adc084s021.c @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2017 Axis Communications AB + * + * Driver for Texas Instruments' ADC084S021 ADC chip. + * Datasheets can be found here: + * http://www.ti.com/lit/ds/symlink/adc084s021.pdf + * + * 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/err.h> +#include <linux/spi/spi.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/regulator/consumer.h> + +#define ADC084S021_DRIVER_NAME "adc084s021" + +struct adc084s021 { + struct spi_device *spi; + struct spi_message message; + struct spi_transfer spi_trans; + struct regulator *reg; + struct mutex lock; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache line. + */ + u16 tx_buf[4] ____cacheline_aligned; + __be16 rx_buf[5]; /* First 16-bits are trash */ +}; + +#define ADC084S021_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .channel = (num), \ + .indexed = 1, \ + .scan_index = (num), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 8, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_BE, \ + }, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + } + +static const struct iio_chan_spec adc084s021_channels[] = { + ADC084S021_VOLTAGE_CHANNEL(0), + ADC084S021_VOLTAGE_CHANNEL(1), + ADC084S021_VOLTAGE_CHANNEL(2), + ADC084S021_VOLTAGE_CHANNEL(3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +/** + * Read an ADC channel and return its value. + * + * @adc: The ADC SPI data. + * @data: Buffer for converted data. + */ +static int adc084s021_adc_conversion(struct adc084s021 *adc, void *data) +{ + int n_words = (adc->spi_trans.len >> 1) - 1; /* Discard first word */ + int ret, i = 0; + u16 *p = data; + + /* Do the transfer */ + ret = spi_sync(adc->spi, &adc->message); + if (ret < 0) + return ret; + + for (; i < n_words; i++) + *(p + i) = adc->rx_buf[i + 1]; + + return ret; +} + +static int adc084s021_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret < 0) + return ret; + + ret = regulator_enable(adc->reg); + if (ret) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + + adc->tx_buf[0] = channel->channel << 3; + ret = adc084s021_adc_conversion(adc, val); + iio_device_release_direct_mode(ind |