diff options
author | 2018-10-01 18:13:42 -0700 | |
---|---|---|
committer | 2018-10-01 18:13:42 -0700 | |
commit | 1c4ccab04a214604eff40e26649cdf00a7930506 (patch) | |
tree | 836084fe8b5b5f1e2b75adf59cd3d7dcbb8cd9af /drivers/iio | |
parent | staging: vboxvideo: Use more drm_fb_helper functions (diff) | |
parent | iio: ad5064: Fix regulator handling (diff) | |
download | linux-1c4ccab04a214604eff40e26649cdf00a7930506.tar.gz linux-1c4ccab04a214604eff40e26649cdf00a7930506.tar.bz2 linux-1c4ccab04a214604eff40e26649cdf00a7930506.zip |
Merge tag 'iio-for-4.20b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
Second set of IIO new device support features and cleanup for the 4.20 cycle.
One merge commit in here to bring in the SPI_CS_WORD flag patches
that are also going via the SPI tree.
There are a few more fixes than normal for a pull targetting the
next merge window. These are all long term issues and as we are late
in the cycle, they can wait.
New device support
* ad7606
- Add support fo the ad7605-4 driver. This driver is still in staging
but is heading in the right direction to graduate, motivated partly
by the requirement for this device support.
* ST VL53L0X ToF ranging sensor
- New minimal driver. Interrupt support to follow.
New features
* SPI_CS_WORD optimization allows long transfers with the chip select
toggled every 16bits. There is a software fallback as well to let
drivers not care about whether the hardware supports it.
* bh1750
- Device tree support and bindings.
* ti-ads7950
- Use the SPI_CS_WORD optmization to save lots of cpu cycles (assuming
the hardware supports it)
Fixes and cleanups
* ad5064
- Fix some long incorrect regulator error handling that preventing
enabling the internal regulator.
* ad7606
- The ad7606 doesn't actually have a 2.5V range and the values provided
for scale have always been wrong. Fix them.
- Drop some wrong kernel-doc (things that don't exist)
- Add missing kernel-doc
* at91-adc
- Fixing missing ack of dataready on sysfs channel reads to avoid spurious
interrupts.
- Fix a wrong channel numbers in triggered_buffer_mode
* hmc5843
- Fix incorrect part number in a comment.
* imx25-gcq
- Fix a device_node leak in an error path.
* meson-saradc
- Drop an unused and pointless define.
- Use of_device_get_match_data instead of opencoding
- Tidy up how meson_sar_adc_param is accessed.
- Rework prior to adding some temperature sensor support.
* tag 'iio-for-4.20b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio:
iio: ad5064: Fix regulator handling
iio: adc: meson-saradc: use the address attribute from iio_chan_spec
iio: adc: meson-saradc: do not use meson_sar_adc_iio_channels directly
iio: adc: at91: fix wrong channel number in triggered buffer mode
iio: adc: at91: fix acking DRDY irq on simple conversions
iio: adc: meson-saradc: simplify access to meson_sar_adc_param
iio: adc: meson-saradc: use of_device_get_match_data
iio: adc: meson-saradc: remove #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT
iio: light: bh1750: Add device tree support
dt-bindings: iio: light: bh1750: Add device tree binding documentation
staging:iio:ad7606: Add support for the ad7605-4
iio: proximity: Add driver support for ST's VL53L0X ToF ranging sensor.
staging:iio:ad7606: update structs with doc annotations
iio: magnetometer: hmc5843: Fixed a comment error.
iio: adc: imx25-gcq: Fix leak of device_node in mx25_gcq_setup_cfgs()
iio: adc: ti-ads7950: use SPI_CS_WORD to reduce CPU usage
spi: add software implementation for SPI_CS_WORD
spi: add new SPI_CS_WORD flag
staging:iio:ad7606: Remove incorrect kernel doc annotations
staging:iio:ad7606: fix voltage scales
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/adc/at91_adc.c | 6 | ||||
-rw-r--r-- | drivers/iio/adc/fsl-imx25-gcq.c | 6 | ||||
-rw-r--r-- | drivers/iio/adc/meson_saradc.c | 70 | ||||
-rw-r--r-- | drivers/iio/adc/ti-ads7950.c | 53 | ||||
-rw-r--r-- | drivers/iio/dac/ad5064.c | 53 | ||||
-rw-r--r-- | drivers/iio/light/bh1750.c | 11 | ||||
-rw-r--r-- | drivers/iio/magnetometer/hmc5843.h | 2 | ||||
-rw-r--r-- | drivers/iio/proximity/Kconfig | 11 | ||||
-rw-r--r-- | drivers/iio/proximity/Makefile | 2 | ||||
-rw-r--r-- | drivers/iio/proximity/vl53l0x-i2c.c | 164 |
10 files changed, 304 insertions, 74 deletions
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 44b516863c9d..75d2f73582a3 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -248,12 +248,14 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *idev = pf->indio_dev; struct at91_adc_state *st = iio_priv(idev); + struct iio_chan_spec const *chan; int i, j = 0; for (i = 0; i < idev->masklength; i++) { if (!test_bit(i, idev->active_scan_mask)) continue; - st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i)); + chan = idev->channels + i; + st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, chan->channel)); j++; } @@ -279,6 +281,8 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) iio_trigger_poll(idev->trig); } else { st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb)); + /* Needed to ACK the DRDY interruption */ + at91_adc_readl(st, AT91_ADC_LCDR); st->done = true; wake_up_interruptible(&st->wq_data_avail); } diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index ea264fa9e567..929c617db364 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -209,12 +209,14 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, ret = of_property_read_u32(child, "reg", ®); if (ret) { dev_err(dev, "Failed to get reg property\n"); + of_node_put(child); return ret; } if (reg >= MX25_NUM_CFGS) { dev_err(dev, "reg value is greater than the number of available configuration registers\n"); + of_node_put(child); return -EINVAL; } @@ -228,6 +230,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, if (IS_ERR(priv->vref[refp])) { dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.", mx25_gcq_refp_names[refp]); + of_node_put(child); return PTR_ERR(priv->vref[refp]); } priv->channel_vref_mv[reg] = @@ -240,6 +243,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, break; default: dev_err(dev, "Invalid positive reference %d\n", refp); + of_node_put(child); return -EINVAL; } @@ -254,10 +258,12 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) { dev_err(dev, "Invalid fsl,adc-refp property value\n"); + of_node_put(child); return -EINVAL; } if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) { dev_err(dev, "Invalid fsl,adc-refn property value\n"); + of_node_put(child); return -EINVAL; } diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index da2d16dfa63e..028ccd218f82 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -148,7 +148,6 @@ #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) - #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11 #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) @@ -173,6 +172,7 @@ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = _chan, \ + .address = _chan, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ @@ -235,7 +235,7 @@ struct meson_sar_adc_data { struct meson_sar_adc_priv { struct regmap *regmap; struct regulator *vref; - const struct meson_sar_adc_data *data; + const struct meson_sar_adc_param *param; struct clk *clkin; struct clk *core_clk; struct clk *adc_sel_clk; @@ -280,7 +280,7 @@ static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) /* use val_calib = scale * val_raw + offset calibration function */ tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; - return clamp(tmp, 0, (1 << priv->data->param->resolution) - 1); + return clamp(tmp, 0, (1 << priv->param->resolution) - 1); } static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) @@ -324,15 +324,15 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); - if (fifo_chan != chan->channel) { + if (fifo_chan != chan->address) { dev_err(&indio_dev->dev, - "ADC FIFO entry belongs to channel %d instead of %d\n", - fifo_chan, chan->channel); + "ADC FIFO entry belongs to channel %d instead of %lu\n", + fifo_chan, chan->address); return -EINVAL; } fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); - fifo_val &= GENMASK(priv->data->param->resolution - 1, 0); + fifo_val &= GENMASK(priv->param->resolution - 1, 0); *val = meson_sar_adc_calib_val(indio_dev, fifo_val); return 0; @@ -344,16 +344,16 @@ static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, enum meson_sar_adc_num_samples samples) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - int val, channel = chan->channel; + int val, address = chan->address; - val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel); + val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, - MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel), + MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), val); - val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel); + val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, - MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val); + MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); } static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, @@ -373,23 +373,23 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, /* map channel index 0 to the channel which we want to read */ regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), - chan->channel); + chan->address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, - chan->channel); + chan->address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, regval); regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, - chan->channel); + chan->address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, regval); - if (chan->channel == 6) + if (chan->address == 6) regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0); } @@ -451,7 +451,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); - if (priv->data->param->has_bl30_integration) { + if (priv->param->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, @@ -479,7 +479,7 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - if (priv->data->param->has_bl30_integration) + if (priv->param->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); @@ -527,8 +527,8 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, if (ret) { dev_warn(indio_dev->dev.parent, - "failed to read sample for channel %d: %d\n", - chan->channel, ret); + "failed to read sample for channel %lu: %d\n", + chan->address, ret); return ret; } @@ -563,7 +563,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, } *val = ret / 1000; - *val2 = priv->data->param->resolution; + *val2 = priv->param->resolution; return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_CALIBBIAS: @@ -636,7 +636,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) */ meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); - if (priv->data->param->has_bl30_integration) { + if (priv->param->has_bl30_integration) { /* * leave sampling delay and the input clocks as configured by * BL30 to make sure BL30 gets the values it expects when @@ -716,7 +716,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) return ret; } - ret = clk_set_rate(priv->adc_clk, priv->data->param->clock_rate); + ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); if (ret) { dev_err(indio_dev->dev.parent, "failed to set adc clock rate\n"); @@ -729,7 +729,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - const struct meson_sar_adc_param *param = priv->data->param; + const struct meson_sar_adc_param *param = priv->param; u32 enable_mask; if (param->bandgap_reg == MESON_SAR_ADC_REG11) @@ -849,13 +849,13 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev) int ret, nominal0, nominal1, value0, value1; /* use points 25% and 75% for calibration */ - nominal0 = (1 << priv->data->param->resolution) / 4; - nominal1 = (1 << priv->data->param->resolution) * 3 / 4; + nominal0 = (1 << priv->param->resolution) / 4; + nominal1 = (1 << priv->param->resolution) * 3 / 4; meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); usleep_range(10, 20); ret = meson_sar_adc_get_sample(indio_dev, - &meson_sar_adc_iio_channels[7], + &indio_dev->channels[7], MEAN_AVERAGING, EIGHT_SAMPLES, &value0); if (ret < 0) goto out; @@ -863,7 +863,7 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev) meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); usleep_range(10, 20); ret = meson_sar_adc_get_sample(indio_dev, - &meson_sar_adc_iio_channels[7], + &indio_dev->channels[7], MEAN_AVERAGING, EIGHT_SAMPLES, &value1); if (ret < 0) goto out; @@ -979,11 +979,11 @@ MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); static int meson_sar_adc_probe(struct platform_device *pdev) { + const struct meson_sar_adc_data *match_data; struct meson_sar_adc_priv *priv; struct iio_dev *indio_dev; struct resource *res; void __iomem *base; - const struct of_device_id *match; int irq, ret; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); @@ -995,15 +995,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev) priv = iio_priv(indio_dev); init_completion(&priv->done); - match = of_match_device(meson_sar_adc_of_match, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "failed to match device\n"); + match_data = of_device_get_match_data(&pdev->dev); + if (!match_data) { + dev_err(&pdev->dev, "failed to get match data\n"); return -ENODEV; } - priv->data = match->data; + priv->param = match_data->param; - indio_dev->name = priv->data->name; + indio_dev->name = match_data->name; indio_dev->dev.parent = &pdev->dev; indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1027,7 +1027,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return ret; priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, - priv->data->param->regmap_config); + priv->param->regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index a5bd5944bc66..0ad63592cc3c 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -51,7 +51,7 @@ struct ti_ads7950_state { struct spi_device *spi; - struct spi_transfer ring_xfer[TI_ADS7950_MAX_CHAN + 2]; + struct spi_transfer ring_xfer; struct spi_transfer scan_single_xfer[3]; struct spi_message ring_msg; struct spi_message scan_single_msg; @@ -65,11 +65,11 @@ struct ti_ads7950_state { * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. */ - __be16 rx_buf[TI_ADS7950_MAX_CHAN + TI_ADS7950_TIMESTAMP_SIZE] + u16 rx_buf[TI_ADS7950_MAX_CHAN + 2 + TI_ADS7950_TIMESTAMP_SIZE] ____cacheline_aligned; - __be16 tx_buf[TI_ADS7950_MAX_CHAN]; - __be16 single_tx; - __be16 single_rx; + u16 tx_buf[TI_ADS7950_MAX_CHAN + 2]; + u16 single_tx; + u16 single_rx; }; @@ -108,7 +108,7 @@ enum ti_ads7950_id { .realbits = bits, \ .storagebits = 16, \ .shift = 12 - (bits), \ - .endianness = IIO_BE, \ + .endianness = IIO_CPU, \ }, \ } @@ -249,23 +249,14 @@ static int ti_ads7950_update_scan_mode(struct iio_dev *indio_dev, len = 0; for_each_set_bit(i, active_scan_mask, indio_dev->num_channels) { cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(i) | st->settings; - st->tx_buf[len++] = cpu_to_be16(cmd); + st->tx_buf[len++] = cmd; } /* Data for the 1st channel is not returned until the 3rd transfer */ - len += 2; - for (i = 0; i < len; i++) { - if ((i + 2) < len) - st->ring_xfer[i].tx_buf = &st->tx_buf[i]; - if (i >= 2) - st->ring_xfer[i].rx_buf = &st->rx_buf[i - 2]; - st->ring_xfer[i].len = 2; - st->ring_xfer[i].cs_change = 1; - } - /* make sure last transfer's cs_change is not set */ - st->ring_xfer[len - 1].cs_change = 0; + st->tx_buf[len++] = 0; + st->tx_buf[len++] = 0; - spi_message_init_with_transfers(&st->ring_msg, st->ring_xfer, len); + st->ring_xfer.len = len * 2; return 0; } @@ -281,7 +272,7 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p) if (ret < 0) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, + iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf[2], iio_get_time_ns(indio_dev)); out: @@ -298,13 +289,13 @@ static int ti_ads7950_scan_direct(struct iio_dev *indio_dev, unsigned int ch) mutex_lock(&indio_dev->mlock); cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(ch) | st->settings; - st->single_tx = cpu_to_be16(cmd); + st->single_tx = cmd; ret = spi_sync(st->spi, &st->scan_single_msg); if (ret) goto out; - ret = be16_to_cpu(st->single_rx); + ret = st->single_rx; out: mutex_unlock(&indio_dev->mlock); @@ -378,6 +369,14 @@ static int ti_ads7950_probe(struct spi_device *spi) const struct ti_ads7950_chip_info *info; int ret; + spi->bits_per_word = 16; + spi->mode |= SPI_CS_WORD; + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&spi->dev, "Error in spi setup\n"); + return ret; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -398,6 +397,16 @@ static int ti_ads7950_probe(struct spi_device *spi) indio_dev->num_channels = info->num_channels; indio_dev->info = &ti_ads7950_info; + /* build spi ring message */ + spi_message_init(&st->ring_msg); + + st->ring_xfer.tx_buf = &st->tx_buf[0]; + st->ring_xfer.rx_buf = &st->rx_buf[0]; + /* len will be set later */ + st->ring_xfer.cs_change = true; + + spi_message_add_tail(&st->ring_xfer, &st->ring_msg); + /* * Setup default message. The sample is read at the end of the first * transfer, then it takes one full cycle to convert the sample and one diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index bf4fc40ec84d..2f98cb2a3b96 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -808,6 +808,40 @@ static int ad5064_set_config(struct ad5064_state *st, unsigned int val) return ad5064_write(st, cmd, 0, val, 0); } +static int ad5064_request_vref(struct ad5064_state *st, struct device *dev) +{ + unsigned int i; + int ret; + + for (i = 0; i < ad5064_num_vref(st); ++i) + st->vref_reg[i].supply = ad5064_vref_name(st, i); + + if (!st->chip_info->internal_vref) + return devm_regulator_bulk_get(dev, ad5064_num_vref(st), + st->vref_reg); + + /* + * This assumes that when the regulator has an internal VREF + * there is only one external VREF connection, which is + * currently the case for all supported devices. + */ + st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref"); + if (!IS_ERR(st->vref_reg[0].consumer)) + return 0; + + ret = PTR_ERR(st->vref_reg[0].consumer); + if (ret != -ENODEV) + return ret; + + /* If no external regulator was supplied use the internal VREF */ + st->use_internal_vref = true; + ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); + if (ret) + dev_err(dev, "Failed to enable internal vref: %d\n", ret); + + return ret; +} + static int ad5064_probe(struct device *dev, enum ad5064_type type, const char *name, ad5064_write_func write) { @@ -828,22 +862,11 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, st->dev = dev; st->write = write; - for (i = 0; i < ad5064_num_vref(st); ++i) - st->vref_reg[i].supply = ad5064_vref_name(st, i); + ret = ad5064_request_vref(st, dev); + if (ret) + return ret; - ret = devm_regulator_bulk_get(dev, ad5064_num_vref(st), - st->vref_reg); - if (ret) { - if (!st->chip_info->internal_vref) - return ret; - st->use_internal_vref = true; - ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); - if (ret) { - dev_err(dev, "Failed to enable internal vref: %d\n", - ret); - return ret; - } - } else { + if (!st->use_internal_vref) { ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); if (ret) return ret; diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index c3a481452b67..28347df78cff 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -307,9 +307,20 @@ static const struct i2c_device_id bh1750_id[] = { }; MODULE_DEVICE_TABLE(i2c, bh1750_id); +static const struct of_device_id bh1750_of_match[] = { + { .compatible = "rohm,bh1710", }, + { .compatible = "rohm,bh1715", }, + { .compatible = "rohm,bh1721", }, + { .compatible = "rohm,bh1750", }, + { .compatible = "rohm,bh1751", }, + { } +}; +MODULE_DEVICE_TABLE(of, bh1750_of_match); + static struct i2c_driver bh1750_driver = { .driver = { .name = "bh1750", + .of_match_table = bh1750_of_match, .pm = &bh1750_pm_ops, }, .probe = bh1750_probe, diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h index 76a5d7484d8d..a75224cf99df 100644 --- a/drivers/iio/magnetometer/hmc5843.h +++ b/drivers/iio/magnetometer/hmc5843.h @@ -31,7 +31,7 @@ enum hmc5843_ids { }; /** - * struct hcm5843_data - device specific data + * struct hmc5843_data - device specific data * @dev: actual device * @lock: update and read regmap data * @regmap: hardware access register maps diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 388ef70c11d2..b99367a89f81 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -92,4 +92,15 @@ config SRF08 To compile this driver as a module, choose M here: the module will be called srf08. +config VL53L0X_I2C + tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)" + depends on I2C + help + Say Y here to build a driver for STMicroelectronics VL53L0X + ToF ranger sensors with i2c interface. + This driver can be used to measure the distance of objects. + + To compile this driver as a module, choose M here: the + module will be called vl53l0x-i2c. + endmenu diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index cac3d7d3325e..6d031f903c4c 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_RFD77402) += rfd77402.o obj-$(CONFIG_SRF04) += srf04.o obj-$(CONFIG_SRF08) += srf08.o obj-$(CONFIG_SX9500) += sx9500.o +obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o + diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c new file mode 100644 index 000000000000..b48216cc1858 --- /dev/null +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for ST VL53L0X FlightSense ToF Ranging Sensor on a i2c bus. + * + * Copyright (C) 2016 STMicroelectronics Imaging Division. + * Copyright (C) 2018 Song Qiang <songqiang1304521@gmail.com> + * + * Datasheet available at + * <https://www.st.com/resource/en/datasheet/vl53l0x.pdf> + * + * Default 7-bit i2c slave address 0x29. + * + * TODO: FIFO buffer, continuous mode, interrupts, range selection, + * sensor ID check. + */ + +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/module.h> + +#include <linux/iio/iio.h> + +#define VL_REG_SYSRANGE_START 0x00 + +#define VL_REG_SYSRANGE_MODE_MASK GENMASK(3, 0) +#define VL_REG_SYSRANGE_MODE_SINGLESHOT 0x00 +#define VL_REG_SYSRANGE_MODE_START_STOP BIT(0) +#define VL_REG_SYSRANGE_MODE_BACKTOBACK BIT(1) +#define VL_REG_SYSRANGE_MODE_TIMED BIT(2) +#define VL_REG_SYSRANGE_MODE_HISTOGRAM BIT(3) + +#define VL_REG_RESULT_INT_STATUS 0x13 +#define VL_REG_RESULT_RANGE_STATUS 0x14 +#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0) + +struct vl53l0x_data { + struct i2c_client *client; +}; + +static int vl53l0x_read_proximity(struct vl53l0x_data *data, + const struct iio_chan_spec *chan, + int *val) +{ + struct i2c_client *client = data->client; + u16 tries = 20; + u8 buffer[12]; + int ret; + + ret = i2c_smbus_write_byte_data(client, VL_REG_SYSRANGE_START, 1); + if (ret < 0) + return ret; + + do { + ret = i2c_smbus_read_byte_data(client, + VL_REG_RESULT_RANGE_STATUS); + if (ret < 0) + return ret; + + if (ret & VL_REG_RESULT_RANGE_STATUS_COMPLETE) + break; + + usleep_range(1000, 5000); + } while (--tries); + if (!tries) + return -ETIMEDOUT; + + ret = i2c_smbus_read_i2c_block_data(client, VL_REG_RESULT_RANGE_STATUS, + 12, buffer); + if (ret < 0) + return ret; + else if (ret != 12) + return -EREMOTEIO; + + /* Values should be between 30~1200 in millimeters. */ + *val = (buffer[10] << 8) + buffer[11]; + + return 0; +} + +static const struct iio_chan_spec vl53l0x_channels[] = { + { + .type = IIO_DISTANCE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static int vl53l0x_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct vl53l0x_data *data = iio_priv(indio_dev); + int ret; + + if (chan->type != IIO_DISTANCE) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = vl53l0x_read_proximity(data, chan, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1000; + + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static const struct iio_info vl53l0x_info = { + .read_raw = vl53l0x_read_raw, +}; + +static int vl53l0x_probe(struct i2c_client *client) +{ + struct vl53l0x_data *data; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK | + I2C_FUNC_SMBUS_BYTE_DATA)) + return -EOPNOTSUPP; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = "vl53l0x"; + indio_dev->info = &vl53l0x_info; + indio_dev->channels = vl53l0x_channels; + indio_dev->num_channels = ARRAY_SIZE(vl53l0x_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct of_device_id st_vl53l0x_dt_match[] = { + { .compatible = "st,vl53l0x", }, + { } +}; +MODULE_DEVICE_TABLE(of, st_vl53l0x_dt_match); + +static struct i2c_driver vl53l0x_driver = { + .driver = { + .name = "vl53l0x-i2c", + .of_match_table = st_vl53l0x_dt_match, + }, + .probe_new = vl53l0x_probe, +}; +module_i2c_driver(vl53l0x_driver); + +MODULE_AUTHOR("Song Qiang <songqiang1304521@gmail.com>"); +MODULE_DESCRIPTION("ST vl53l0x ToF ranging sensor driver"); +MODULE_LICENSE("GPL v2"); |