summaryrefslogtreecommitdiff
path: root/drivers/iio
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-10-24 13:09:37 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-10-24 13:09:37 +0200
commitb6df1fc1e3f668df475c12ec85735ae1c98fcb68 (patch)
treed7c4ded601856580d7395df8238f5d00c6792a1e /drivers/iio
parent8210a2004d446ca49a782ba824ca2fbb9667ce9e (diff)
parent77af145dc7eadcb78d38912b67d6a68050d21a9b (diff)
Merge tag 'iio-for-5.16b' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next
Jonathan writes: 2nd set of IIO new driver, cleanups and features for the 5.16 cycle New device support * adrf6780 microwave upconverter. - New driver for this interesting device including bindings. Features * lite-on ltr501 - Add dt-bindings including vendor ID and of_device_id table. - Add regulator support. * sensiron,scd4x - Add reporting of channel scale. Cleanups including fixes for things in this cycle * Tree wide: Another set of dev_err_probe() introductions to reduce noise in logs when deferred probing is needed and provide more debug info. Devices included this time: - amlogic,meson_saradc - capella,cm3605 - fsl,imx7d - maxim,max1118 - maxim,max1241 - nxp,lpc18xx - qcom,pm8xxxx-xoadc - rockchip,saradc - sharp,gp2ap002 - sterricson,ab8500 - ti,ads7950 * core - iio:buffer - Fix a path where a ret value is not intialized. * channel-mux - Add support to mux core subsystem for a settling delay and use it in the iio-channel-mux driver. - Fix a few dt binding warnings. * nxp,lpc18xx - Convert to devm_ functions for all of probe and drop remove() * st,lsm6dsx - Suppress a warning due to lack of handling of an enum *_MAX entry that is just there to get the size. * st,stm32-adc - Add generic channel binding, deprecating the old approach. - Add nvmem support to get calibration data for the vrefint channel and use it to perform such calibration. - Add a binding for sample-time to the generic channel description as it can be per channel. * ti,adc128s052 - Use devm_ managed functions and drop remove() * vti,sca3000 - Use sign_extend32() rather than opencoding. * xilinx,xadc - Drop irq field from state structure as now just used in probe. * tag 'iio-for-5.16b' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (36 commits) dt-bindings: iio: frequency: add adrf6780 doc iio: frequency: adrf6780: add support for ADRF6780 iio: chemical: scd4x: Add a scale for the co2 concentration reading dt-bindings: iio: io-channel-mux: allow duplicate channel, labels dt-bindings: iio: io-channel-mux: add optional #io-channel-cells iio: adc: adc128s052: Simplify adc128_probe() iio: multiplexer: iio-mux: Support settle-time-us property dt-bindings: iio: io-channel-mux: Add property for settle time mux: add support for delay after muxing iio: adc: stm32-adc: use generic binding for sample-time iio: adc: stm32-adc: add vrefint calibration support iio: adc: stm32-adc: add support of internal channels iio: adc: stm32-adc: add support of generic channels binding iio: adc: stm32-adc: split channel init into several routines dt-bindings: iio: stm32-adc: add nvmem support for vrefint internal channel dt-bindings: iio: stm32-adc: add generic channel binding iio: accel: sca3000: Use sign_extend32() instead of opencoding sign extension. iio: xilinx-xadc: Remove `irq` field from state struct iio: imu: st_lsm6dsx: Avoid potential array overflow in st_lsm6dsx_set_odr() iio: light: gp2ap002: Make use of the helper function dev_err_probe() ...
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/accel/sca3000.c3
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c22
-rw-r--r--drivers/iio/adc/imx7d_adc.c18
-rw-r--r--drivers/iio/adc/lpc18xx_adc.c75
-rw-r--r--drivers/iio/adc/max1118.c7
-rw-r--r--drivers/iio/adc/max1241.c17
-rw-r--r--drivers/iio/adc/meson_saradc.c39
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c9
-rw-r--r--drivers/iio/adc/rockchip_saradc.c27
-rw-r--r--drivers/iio/adc/stm32-adc-core.c1
-rw-r--r--drivers/iio/adc/stm32-adc-core.h10
-rw-r--r--drivers/iio/adc/stm32-adc.c422
-rw-r--r--drivers/iio/adc/ti-adc128s052.c33
-rw-r--r--drivers/iio/adc/ti-ads7950.c4
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c5
-rw-r--r--drivers/iio/adc/xilinx-xadc.h1
-rw-r--r--drivers/iio/chemical/scd4x.c9
-rw-r--r--drivers/iio/frequency/Kconfig12
-rw-r--r--drivers/iio/frequency/Makefile1
-rw-r--r--drivers/iio/frequency/adrf6780.c527
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c6
-rw-r--r--drivers/iio/industrialio-buffer.c2
-rw-r--r--drivers/iio/light/cm3605.c29
-rw-r--r--drivers/iio/light/gp2ap002.c24
-rw-r--r--drivers/iio/light/ltr501.c37
-rw-r--r--drivers/iio/multiplexer/iio-mux.c7
26 files changed, 1116 insertions, 231 deletions
diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index cb753a43533c..c6b75308148a 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -731,8 +731,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
return ret;
}
*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
- *val = ((*val) << (sizeof(*val) * 8 - 13)) >>
- (sizeof(*val) * 8 - 13);
+ *val = sign_extend32(*val, 12);
} else {
/* get the temperature when available */
ret = sca3000_read_data_short(st,
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 7b5212ba5501..4c46a201d4ef 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -1103,17 +1103,15 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
return ret;
gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END");
- if (gpadc->irq_sw < 0) {
- dev_err(dev, "failed to get platform sw_conv_end irq\n");
- return gpadc->irq_sw;
- }
+ if (gpadc->irq_sw < 0)
+ return dev_err_probe(dev, gpadc->irq_sw,
+ "failed to get platform sw_conv_end irq\n");
if (is_ab8500(gpadc->ab8500)) {
gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
- if (gpadc->irq_hw < 0) {
- dev_err(dev, "failed to get platform hw_conv_end irq\n");
- return gpadc->irq_hw;
- }
+ if (gpadc->irq_hw < 0)
+ return dev_err_probe(dev, gpadc->irq_hw,
+ "failed to get platform hw_conv_end irq\n");
} else {
gpadc->irq_hw = 0;
}
@@ -1146,11 +1144,9 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
/* The VTVout LDO used to power the AB8500 GPADC */
gpadc->vddadc = devm_regulator_get(dev, "vddadc");
- if (IS_ERR(gpadc->vddadc)) {
- ret = PTR_ERR(gpadc->vddadc);
- dev_err(dev, "failed to get vddadc\n");
- return ret;
- }
+ if (IS_ERR(gpadc->vddadc))
+ return dev_err_probe(dev, PTR_ERR(gpadc->vddadc),
+ "failed to get vddadc\n");
ret = regulator_enable(gpadc->vddadc);
if (ret) {
diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c
index 4969a5f941e3..092f8d296527 100644
--- a/drivers/iio/adc/imx7d_adc.c
+++ b/drivers/iio/adc/imx7d_adc.c
@@ -493,22 +493,16 @@ static int imx7d_adc_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return irq;
+ return dev_err_probe(dev, irq, "Failed getting irq\n");
info->clk = devm_clk_get(dev, "adc");
- if (IS_ERR(info->clk)) {
- ret = PTR_ERR(info->clk);
- dev_err(dev, "Failed getting clock, err = %d\n", ret);
- return ret;
- }
+ if (IS_ERR(info->clk))
+ return dev_err_probe(dev, PTR_ERR(info->clk), "Failed getting clock\n");
info->vref = devm_regulator_get(dev, "vref");
- if (IS_ERR(info->vref)) {
- ret = PTR_ERR(info->vref);
- dev_err(dev,
- "Failed getting reference voltage, err = %d\n", ret);
- return ret;
- }
+ if (IS_ERR(info->vref))
+ return dev_err_probe(dev, PTR_ERR(info->vref),
+ "Failed getting reference voltage\n");
platform_set_drvdata(pdev, indio_dev);
diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c
index 3566990ae87d..ceefa4d793cf 100644
--- a/drivers/iio/adc/lpc18xx_adc.c
+++ b/drivers/iio/adc/lpc18xx_adc.c
@@ -115,6 +115,23 @@ static const struct iio_info lpc18xx_adc_info = {
.read_raw = lpc18xx_adc_read_raw,
};
+static void lpc18xx_clear_cr_reg(void *data)
+{
+ struct lpc18xx_adc *adc = data;
+
+ writel(0, adc->base + LPC18XX_ADC_CR);
+}
+
+static void lpc18xx_clk_disable(void *clk)
+{
+ clk_disable_unprepare(clk);
+}
+
+static void lpc18xx_regulator_disable(void *vref)
+{
+ regulator_disable(vref);
+}
+
static int lpc18xx_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
@@ -127,7 +144,6 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
if (!indio_dev)
return -ENOMEM;
- platform_set_drvdata(pdev, indio_dev);
adc = iio_priv(indio_dev);
adc->dev = &pdev->dev;
mutex_init(&adc->lock);
@@ -137,19 +153,17 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
return PTR_ERR(adc->base);
adc->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(adc->clk)) {
- dev_err(&pdev->dev, "error getting clock\n");
- return PTR_ERR(adc->clk);
- }
+ if (IS_ERR(adc->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(adc->clk),
+ "error getting clock\n");
rate = clk_get_rate(adc->clk);
clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
adc->vref = devm_regulator_get(&pdev->dev, "vref");
- if (IS_ERR(adc->vref)) {
- dev_err(&pdev->dev, "error getting regulator\n");
- return PTR_ERR(adc->vref);
- }
+ if (IS_ERR(adc->vref))
+ return dev_err_probe(&pdev->dev, PTR_ERR(adc->vref),
+ "error getting regulator\n");
indio_dev->name = dev_name(&pdev->dev);
indio_dev->info = &lpc18xx_adc_info;
@@ -163,44 +177,30 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
return ret;
}
+ ret = devm_add_action_or_reset(&pdev->dev, lpc18xx_regulator_disable, adc->vref);
+ if (ret)
+ return ret;
+
ret = clk_prepare_enable(adc->clk);
if (ret) {
dev_err(&pdev->dev, "unable to enable clock\n");
- goto dis_reg;
+ return ret;
}
+ ret = devm_add_action_or_reset(&pdev->dev, lpc18xx_clk_disable,
+ adc->clk);
+ if (ret)
+ return ret;
+
adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
LPC18XX_ADC_CR_PDN;
writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(&pdev->dev, "unable to register device\n");
- goto dis_clk;
- }
-
- return 0;
-
-dis_clk:
- writel(0, adc->base + LPC18XX_ADC_CR);
- clk_disable_unprepare(adc->clk);
-dis_reg:
- regulator_disable(adc->vref);
- return ret;
-}
-
-static int lpc18xx_adc_remove(struct platform_device *pdev)
-{
- struct iio_dev *indio_dev = platform_get_drvdata(pdev);
- struct lpc18xx_adc *adc = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- writel(0, adc->base + LPC18XX_ADC_CR);
- clk_disable_unprepare(adc->clk);
- regulator_disable(adc->vref);
+ ret = devm_add_action_or_reset(&pdev->dev, lpc18xx_clear_cr_reg, adc);
+ if (ret)
+ return ret;
- return 0;
+ return devm_iio_device_register(&pdev->dev, indio_dev);
}
static const struct of_device_id lpc18xx_adc_match[] = {
@@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
static struct platform_driver lpc18xx_adc_driver = {
.probe = lpc18xx_adc_probe,
- .remove = lpc18xx_adc_remove,
.driver = {
.name = "lpc18xx-adc",
.of_match_table = lpc18xx_adc_match,
diff --git a/drivers/iio/adc/max1118.c b/drivers/iio/adc/max1118.c
index 8cec9d949083..a41bc570be21 100644
--- a/drivers/iio/adc/max1118.c
+++ b/drivers/iio/adc/max1118.c
@@ -221,10 +221,9 @@ static int max1118_probe(struct spi_device *spi)
if (id->driver_data == max1118) {
adc->reg = devm_regulator_get(&spi->dev, "vref");
- if (IS_ERR(adc->reg)) {
- dev_err(&spi->dev, "failed to get vref regulator\n");
- return PTR_ERR(adc->reg);
- }
+ if (IS_ERR(adc->reg))
+ return dev_err_probe(&spi->dev, PTR_ERR(adc->reg),
+ "failed to get vref regulator\n");
ret = regulator_enable(adc->reg);
if (ret)
return ret;
diff --git a/drivers/iio/adc/max1241.c b/drivers/iio/adc/max1241.c
index b60f8448f21a..a5afd84af58b 100644
--- a/drivers/iio/adc/max1241.c
+++ b/drivers/iio/adc/max1241.c
@@ -148,10 +148,9 @@ static int max1241_probe(struct spi_device *spi)
mutex_init(&adc->lock);
adc->vdd = devm_regulator_get(dev, "vdd");
- if (IS_ERR(adc->vdd)) {
- dev_err(dev, "failed to get vdd regulator\n");
- return PTR_ERR(adc->vdd);
- }
+ if (IS_ERR(adc->vdd))
+ return dev_err_probe(dev, PTR_ERR(adc->vdd),
+ "failed to get vdd regulator\n");
ret = regulator_enable(adc->vdd);
if (ret)
@@ -164,10 +163,9 @@ static int max1241_probe(struct spi_device *spi)
}
adc->vref = devm_regulator_get(dev, "vref");
- if (IS_ERR(adc->vref)) {
- dev_err(dev, "failed to get vref regulator\n");
- return PTR_ERR(adc->vref);
- }
+ if (IS_ERR(adc->vref))
+ return dev_err_probe(dev, PTR_ERR(adc->vref),
+ "failed to get vref regulator\n");
ret = regulator_enable(adc->vref);
if (ret)
@@ -182,7 +180,8 @@ static int max1241_probe(struct spi_device *spi)
adc->shutdown = devm_gpiod_get_optional(dev, "shutdown",
GPIOD_OUT_HIGH);
if (IS_ERR(adc->shutdown))
- return PTR_ERR(adc->shutdown);
+ return dev_err_probe(dev, PTR_ERR(adc->shutdown),
+ "cannot get shutdown gpio\n");
if (adc->shutdown)
dev_dbg(dev, "shutdown pin passed, low-power mode enabled");
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 705d5e11a54b..62cc6fb0ef85 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -1230,35 +1230,31 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
return ret;
priv->clkin = devm_clk_get(&pdev->dev, "clkin");
- if (IS_ERR(priv->clkin)) {
- dev_err(&pdev->dev, "failed to get clkin\n");
- return PTR_ERR(priv->clkin);
- }
+ if (IS_ERR(priv->clkin))
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->clkin),
+ "failed to get clkin\n");
priv->core_clk = devm_clk_get(&pdev->dev, "core");
- if (IS_ERR(priv->core_clk)) {
- dev_err(&pdev->dev, "failed to get core clk\n");
- return PTR_ERR(priv->core_clk);
- }
+ if (IS_ERR(priv->core_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->core_clk),
+ "failed to get core clk\n");
priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
if (IS_ERR(priv->adc_clk)) {
- if (PTR_ERR(priv->adc_clk) == -ENOENT) {
+ if (PTR_ERR(priv->adc_clk) == -ENOENT)
priv->adc_clk = NULL;
- } else {
- dev_err(&pdev->dev, "failed to get adc clk\n");
- return PTR_ERR(priv->adc_clk);
- }
+ else
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->adc_clk),
+ "failed to get adc clk\n");
}
priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
if (IS_ERR(priv->adc_sel_clk)) {
- if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) {
+ if (PTR_ERR(priv->adc_sel_clk) == -ENOENT)
priv->adc_sel_clk = NULL;
- } else {
- dev_err(&pdev->dev, "failed to get adc_sel clk\n");
- return PTR_ERR(priv->adc_sel_clk);
- }
+ else
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->adc_sel_clk),
+ "failed to get adc_sel clk\n");
}
/* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
@@ -1269,10 +1265,9 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
}
priv->vref = devm_regulator_get(&pdev->dev, "vref");
- if (IS_ERR(priv->vref)) {
- dev_err(&pdev->dev, "failed to get vref regulator\n");
- return PTR_ERR(priv->vref);
- }
+ if (IS_ERR(priv->vref))
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref),
+ "failed to get vref regulator\n");
priv->calibscale = MILLION;
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index 0610bf254771..21d7eff645c3 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -910,16 +910,15 @@ static int pm8xxx_xoadc_probe(struct platform_device *pdev)
map = dev_get_regmap(dev->parent, NULL);
if (!map) {
dev_err(dev, "parent regmap unavailable.\n");
- return -ENXIO;
+ return -ENODEV;
}
adc->map = map;
/* Bring up regulator */
adc->vref = devm_regulator_get(dev, "xoadc-ref");
- if (IS_ERR(adc->vref)) {
- dev_err(dev, "failed to get XOADC VREF regulator\n");
- return PTR_ERR(adc->vref);
- }
+ if (IS_ERR(adc->vref))
+ return dev_err_probe(dev, PTR_ERR(adc->vref),
+ "failed to get XOADC VREF regulator\n");
ret = regulator_enable(adc->vref);
if (ret) {
dev_err(dev, "failed to enable XOADC VREF regulator\n");
diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index a56a0d7337ca..14b8df4ca9c8 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -360,7 +360,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
if (IS_ERR(info->reset)) {
ret = PTR_ERR(info->reset);
if (ret != -ENOENT)
- return ret;
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to get saradc-apb\n");
dev_dbg(&pdev->dev, "no reset control found\n");
info->reset = NULL;
@@ -370,7 +371,7 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return irq;
+ return dev_err_probe(&pdev->dev, irq, "failed to get irq\n");
ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
0, dev_name(&pdev->dev), info);
@@ -380,23 +381,19 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
}
info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
- if (IS_ERR(info->pclk)) {
- dev_err(&pdev->dev, "failed to get pclk\n");
- return PTR_ERR(info->pclk);
- }
+ if (IS_ERR(info->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk),
+ "failed to get pclk\n");
info->clk = devm_clk_get(&pdev->dev, "saradc");
- if (IS_ERR(info->clk)) {
- dev_err(&pdev->dev, "failed to get adc clock\n");
- return PTR_ERR(info->clk);
- }
+ if (IS_ERR(info->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
+ "failed to get adc clock\n");
info->vref = devm_regulator_get(&pdev->dev, "vref");
- if (IS_ERR(info->vref)) {
- dev_err(&pdev->dev, "failed to get regulator, %ld\n",
- PTR_ERR(info->vref));
- return PTR_ERR(info->vref);
- }
+ if (IS_ERR(info->vref))
+ return dev_err_probe(&pdev->dev, PTR_ERR(info->vref),
+ "failed to get regulator\n");
if (info->reset)
rockchip_saradc_reset_controller(info->reset);
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index c088cb990193..b6e18eb101f7 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -659,6 +659,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
priv->cfg = (const struct stm32_adc_priv_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
+ spin_lock_init(&priv->common.lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->common.base = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
index 2322809bfd2f..faedf7a49555 100644
--- a/drivers/iio/adc/stm32-adc-core.h
+++ b/drivers/iio/adc/stm32-adc-core.h
@@ -102,6 +102,9 @@
#define STM32H7_ADC_CALFACT 0xC4
#define STM32H7_ADC_CALFACT2 0xC8
+/* STM32MP1 - ADC2 instance option register */
+#define STM32MP1_ADC2_OR 0xD0
+
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
@@ -168,23 +171,30 @@ enum stm32h7_adc_dmngt {
#define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */
+#define STM32H7_VBATEN BIT(24)
+#define STM32H7_VREFEN BIT(22)
#define STM32H7_PRESC_SHIFT 18
#define STM32H7_PRESC_MASK GENMASK(21, 18)
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
+/* STM32MP1_ADC2_OR - bit fields */
+#define STM32MP1_VDDCOREEN BIT(0)
+
/**
* struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr
* @phys_base: control registers base physical addr
* @rate: clock rate used for analog circuitry
* @vref_mv: vref voltage (mv)
+ * @lock: spinlock
*/
struct stm32_adc_common {
void __iomem *base;
phys_addr_t phys_base;
unsigned long rate;
int vref_mv;
+ spinlock_t lock; /* lock for common register */
};
#endif
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 5088de835bb1..6245434f8377 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
@@ -35,12 +36,13 @@
#define STM32H7_BOOST_CLKRATE 20000000UL
#define STM32_ADC_CH_MAX 20 /* max number of channels */
-#define STM32_ADC_CH_SZ 10 /* max channel name size */
+#define STM32_ADC_CH_SZ 16 /* max channel name size */
#define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */
#define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */
#define STM32_ADC_TIMEOUT_US 100000
#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
#define STM32_ADC_HW_STOP_DELAY_MS 100
+#define STM32_ADC_VREFINT_VOLTAGE 3300
#define STM32_DMA_BUFFER_SIZE PAGE_SIZE
@@ -77,6 +79,30 @@ enum stm32_adc_extsel {
STM32_EXT20,
};
+enum stm32_adc_int_ch {
+ STM32_ADC_INT_CH_NONE = -1,
+ STM32_ADC_INT_CH_VDDCORE,
+ STM32_ADC_INT_CH_VREFINT,
+ STM32_ADC_INT_CH_VBAT,
+ STM32_ADC_INT_CH_NB,
+};
+
+/**
+ * struct stm32_adc_ic - ADC internal channels
+ * @name: name of the internal channel
+ * @idx: internal channel enum index
+ */
+struct stm32_adc_ic {
+ const char *name;
+ u32 idx;
+};
+
+static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = {
+ { "vddcore", STM32_ADC_INT_CH_VDDCORE },
+ { "vrefint", STM32_ADC_INT_CH_VREFINT },
+ { "vbat", STM32_ADC_INT_CH_VBAT },
+};
+
/**
* struct stm32_adc_trig_info - ADC trigger info
* @name: name of the trigger, corresponding to its source
@@ -114,6 +140,16 @@ struct stm32_adc_regs {
};
/**
+ * struct stm32_adc_vrefint - stm32 ADC internal reference voltage data
+ * @vrefint_cal: vrefint calibration value from nvmem
+ * @vrefint_data: vrefint actual value
+ */
+struct stm32_adc_vrefint {
+ u32 vrefint_cal;
+ u32 vrefint_data;
+};
+
+/**
* struct stm32_adc_regspec - stm32 registers definition
* @dr: data register offset
* @ier_eoc: interrupt enable register & eocie bitfield
@@ -126,6 +162,9 @@ struct stm32_adc_regs {
* @res: resolution selection register & bitfield
* @smpr: smpr1 & smpr2 registers offset array
* @smp_bits: smpr1 & smpr2 index and bitfields
+ * @or_vdd: option register & vddcore bitfield
+ * @ccr_vbat: common register & vbat bitfield
+ * @ccr_vref: common register & vrefint bitfield
*/
struct stm32_adc_regspec {
const u32 dr;
@@ -139,6 +178,9 @@ struct stm32_adc_regspec {
const struct stm32_adc_regs res;
const u32 smpr[2];
const struct stm32_adc_regs *smp_bits;
+ const struct stm32_adc_regs or_vdd;
+ const struct stm32_adc_regs ccr_vbat;
+ const struct stm32_adc_regs ccr_vref;
};
struct stm32_adc;
@@ -156,6 +198,7 @@ struct stm32_adc;
* @unprepare: optional unprepare routine (disable, power-down)
* @irq_clear: routine to clear irqs
* @smp_cycles: programmable sampling time (ADC clock cycles)
+ * @ts_vrefint_ns: vrefint minimum sampling time in ns
*/
struct stm32_adc_cfg {
const struct stm32_adc_regspec *regs;
@@ -169,6 +212,7 @@ struct stm32_adc_cfg {
void (*unprepare)(struct iio_dev *);
void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
const unsigned int *smp_cycles;
+ const unsigned int ts_vrefint_ns;
};
/**
@@ -193,7 +237,10 @@ struct stm32_adc_cfg {
* @pcsel: bitmask to preselect channels on some devices
* @smpr_val: sampling time settings (e.g. smpr1 / smpr2)
* @cal: optional calibration data on some devices
+ * @vrefint: internal reference voltage data
* @chan_name: channel name array
+ * @num_diff: number of differential channels
+ * @int_ch: internal channel indexes array
*/
struct stm32_adc {
struct stm32_adc_common *common;
@@ -216,7 +263,10 @@ struct stm32_adc {
u32 pcsel;
u32 smpr_val[2];
struct stm32_adc_calib cal;
+ struct stm32_adc_vrefint vrefint;
char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ];
+ u32 num_diff;
+ int int_ch[STM32_ADC_INT_CH_NB];
};
struct stm32_adc_diff_channel {
@@ -449,6 +499,24 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = {
.smp_bits = stm32h7_smp_bits,
};
+static const struct stm32_adc_regspec stm32mp1_adc_regspec = {
+ .dr = STM32H7_ADC_DR,
+ .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
+ .ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
+ .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
+ .isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
+ .sqr = stm32h7_sq,
+ .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
+ .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
+ STM32H7_EXTSEL_SHIFT },
+ .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
+ .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
+ .smp_bits = stm32h7_smp_bits,
+ .or_vdd = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN },
+ .ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
+ .ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
+};
+
/*
* STM32 ADC registers access routines
* @adc: stm32 adc instance
@@ -487,6 +555,14 @@ static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
spin_unlock_irqrestore(&adc->lock, flags);
}
+static void stm32_adc_set_bits_common(struct stm32_adc *adc, u32 reg, u32 bits)
+{
+ spin_lock(&adc->common->lock);
+ writel_relaxed(readl_relaxed(adc->common->base + reg) | bits,
+ adc->common->base + reg);
+ spin_unlock(&adc->common->lock);
+}
+
static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
{
unsigned long flags;
@@ -496,6 +572,14 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
spin_unlock_irqrestore(&adc->lock, flags);
}
+static void stm32_adc_clr_bits_common(struct stm32_adc *adc, u32 reg, u32 bits)
+{
+ spin_lock(&adc->common->lock);
+ writel_relaxed(readl_relaxed(adc->common->base + reg) & ~bits,
+ adc->common->base + reg);
+ spin_unlock(&adc->common->lock);
+}
+
/**
* stm32_adc_conv_irq_enable() - Enable end of conversion interrupt
* @adc: stm32 adc instance
@@ -577,6 +661,60 @@ err_clk_dis:
return ret;
}
+static void stm32_adc_int_ch_enable(struct iio_dev *indio_dev)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ u32 i;
+
+ for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
+ if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE)
+ continue;
+
+ switch (i) {
+ case STM32_ADC_INT_CH_VDDCORE:
+ dev_dbg(&indio_dev->dev, "Enable VDDCore\n");
+ stm32_adc_set_bits(adc, adc->cfg->regs->or_vdd.reg,
+ adc->cfg->regs->or_vdd.mask);
+ break;
+ case STM32_ADC_INT_CH_VREFINT:
+ dev_dbg(&indio_dev->dev, "Enable VREFInt\n");
+ stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
+ adc->cfg->regs->ccr_vref.mask);
+ break;
+ case STM32_ADC_INT_CH_VBAT:
+ dev_dbg(&indio_dev->dev, "Enable VBAT\n");
+ stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vbat.reg,
+ adc->cfg->regs->ccr_vbat.mask);
+ break;
+ }
+ }
+}
+
+static void stm32_adc_int_ch_disable(struct stm32_adc *adc)
+{
+ u32 i;
+
+ for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
+ if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE)
+ continue;
+
+ switch (i) {
+ case STM32_ADC_INT_CH_VDDCORE:
+ stm32_adc_clr_bits(adc, adc->cfg->regs->or_vdd.reg,
+ adc->cfg->regs->or_vdd.mask);
+ break;
+ case STM32_ADC_INT_CH_VREFINT:
+ stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
+ adc->cfg->regs->ccr_vref.mask);
+ break;
+ case STM32_ADC_INT_CH_VBAT:
+ stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vbat.reg,
+ adc->cfg->regs->ccr_vbat.mask);
+ break;
+ }
+ }
+}
+
/**
* stm32f4_adc_start_conv() - Start conversions for regular channels.
* @indio_dev: IIO device instance
@@ -945,11 +1083,13 @@ static int stm32h7_adc_prepare(struct iio_dev *indio_dev)
goto pwr_dwn;
calib = ret;
+ stm32_adc_int_ch_enable(indio_dev);
+
stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
ret = stm32h7_adc_enable(indio_dev);
if (ret)
- goto pwr_dwn;
+ goto ch_disable;
/* Either restore or read calibration result for future reference */
if (calib)
@@ -965,6 +1105,8 @@ static int stm32h7_adc_prepare(struct iio_dev *indio_dev)
disable:
stm32h7_adc_disable(indio_dev);
+ch_disable:
+ stm32_adc_int_ch_disable(adc);
pwr_dwn:
stm32h7_adc_enter_pwr_down(adc);
@@ -976,6 +1118,7 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev)
struct stm32_adc *adc = iio_priv(indio_dev);
stm32h7_adc_disable(indio_dev);
+ stm32_adc_int_ch_disable(adc);
stm32h7_adc_enter_pwr_down(adc);
}
@@ -1212,6 +1355,7 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
@@ -1219,6 +1363,10 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
ret = stm32_adc_single_conv(indio_dev, chan, val);
else
ret = -EINVAL;
+
+ if (mask == IIO_CHAN_INFO_PROCESSED && adc->vrefint.vrefint_cal)
+ *val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;
+
iio_device_release_direct_mode(indio_dev);
return ret;
@@ -1657,6 +1805,13 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
u32 period_ns, shift = smpr->shift, mask = smpr->mask;
unsigned int smp, r = smpr->reg;
+ /*
+ * For vrefint channel, ensure that the sampling time cannot
+ * be lower than the one specified in the datasheet
+ */
+ if (channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT])
+ smp_ns = max(smp_ns, adc->cfg->ts_vrefint_ns);
+
/* Determine sampling time (ADC clock cycles) */
period_ns = NSEC_PER_SEC / adc->common->rate;
for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++)
@@ -1688,7 +1843,10 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
chan->datasheet_name = name;
chan->scan_index = scan_index;
chan->indexed = 1;
- chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ if (chan->channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT])
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
+ else
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET);
chan->scan_type.sign = 'u';
@@ -1706,17 +1864,11 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
}
}
-static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
+static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm32_adc *adc)
{
struct device_node *node = indio_dev->dev.of_node;
- struct stm32_adc *adc = iio_priv(indio_dev);
const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
- struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
- struct property *prop;
- const __be32 *cur;
- struct iio_chan_spec *channels;
- int scan_index = 0, num_channels = 0, num_diff = 0, ret, i;
- u32 val, smp = 0;
+ int num_channels = 0, ret;
ret = of_property_count_u32_elems(node, "st,adc-channels");
if (ret > adc_info->max_channels) {
@@ -1727,24 +1879,13 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
}
ret = of_property_count_elems_of_size(node, "st,adc-diff-channels",
- sizeof(*diff));
+ sizeof(struct stm32_adc_diff_channel));
if (ret > adc_info->max_channels) {
dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
return -EINVAL;
} else if (ret > 0) {
- int size = ret * sizeof(*diff) / sizeof(u32);
-
- num_diff = ret;
+ adc->num_diff = ret;
num_channels += ret;
- ret = of_property_read_u32_array(node, "st,adc-diff-channels",
- (u32 *)diff, size);
- if (ret)
- return ret;
- }
-
- if (!num_channels) {
- dev_err(&indio_dev->dev, "No channels configured\n");
- return -ENODATA;
}
/* Optional sample time is provided either for each, or all channels */
@@ -1754,13 +1895,45 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
return -EINVAL;
}
- if (timestamping)
- num_channels++;
+ return num_channels;
+}
- channels = devm_kcalloc(&indio_dev->dev, num_channels,
- sizeof(struct iio_chan_spec), GFP_KERNEL);
- if (!channels)
- return -ENOMEM;
+static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
+ struct stm32_adc *adc,
+ struct iio_chan_spec *channels)
+{
+ struct device_node *node = indio_dev->dev.of_node;
+ const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
+ struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
+ u32 num_diff = adc->num_diff;
+ int size = num_diff * sizeof(*diff) / sizeof(u32);
+ int scan_index = 0, val, ret, i;
+ struct property *prop;
+ const __be32 *cur;
+ u32 smp = 0;
+
+ if (num_diff) {
+ ret = of_property_read_u32_array(node, "st,adc-diff-channels",
+ (u32 *)diff, size);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Failed to get diff channels %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < num_diff; i++) {
+ if (diff[i].vinp >= adc_info->max_channels ||
+ diff[i].vinn >= adc_info->max_channels) {
+ dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
+ diff[i].vinp, diff[i].vinn);
+ return -EINVAL;
+ }
+
+ stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
+ diff[i].vinp, diff[i].vinn,
+ scan_index, true);
+ scan_index++;
+ }
+ }
of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
if (val >= adc_info->max_channels) {
@@ -1771,8 +1944,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
/* Channel can't be configured both as single-ended & diff */
for (i = 0; i < num_diff; i++) {
if (val == diff[i].vinp) {
- dev_err(&indio_dev->dev,
- "channel %d miss-configured\n", val);
+ dev_err(&indio_dev->dev, "channel %d misconfigured\n", val);
return -EINVAL;
}
}
@@ -1781,19 +1953,6 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
scan_index++;
}
- for (i = 0; i < num_diff; i++) {
- if (diff[i].vinp >= adc_info->max_channels ||
- diff[i].vinn >= adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
- diff[i].vinp, diff[i].vinn);
- return -EINVAL;
- }
- stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
- diff[i].vinp, diff[i].vinn, scan_index,
- true);
- scan_index++;
- }
-
for (i = 0; i < scan_index; i++) {
/*
* Using of_property_read_u32_index(), smp value will only be
@@ -1801,12 +1960,178 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
* get either no value, 1 shared value for all indexes, or one
* value per channel.
*/
- of_property_read_u32_index(node, "st,min-sample-time-nsecs",
- i, &smp);
+ of_property_read_u32_index(node, "st,min-sample-time-nsecs", i, &smp);
+
/* Prepare sampling time settings */
stm32_adc_smpr_init(adc, channels[i].channel, smp);
}
+ return scan_index;
+}
+
+static int stm32_adc_populate_int_ch(struct iio_dev *indio_dev, const char *ch_name,
+ int chan)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ u16 vrefint;
+ int i, ret;
+
+ for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
+ if (!strncmp(stm32_adc_ic[i].name, ch_name, STM32_ADC_CH_SZ)) {
+ adc->int_ch[i] = chan;
+
+ if (stm32_adc_ic[i].idx != STM32_ADC_INT_CH_VREFINT)
+ continue;
+
+ /* Get calibration data for vrefint channel */
+ ret = nvmem_cell_read_u16(&indio_dev->dev, "vrefint", &vrefint);
+ if (ret && ret != -ENOENT) {
+ return dev_err_probe(&indio_dev->dev, ret,
+ "nvmem access error\n");
+ }
+ if (ret == -ENOENT)
+ dev_dbg(&indio_dev->dev, "vrefint calibration not found\n");
+ else
+ adc->vrefint.vrefint_cal = vrefint;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
+ struct stm32_adc *adc,
+ struct iio_chan_spec *channels)
+{
+ struct device_node *node = indio_dev->dev.of_node;
+ const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
+ struct device_node *child;
+ const char *name;
+ int val, scan_index = 0, ret;
+ bool differential;
+ u32 vin[2];
+
+ for_each_available_child_of_node(node, child) {
+ ret = of_property_read_u32(child, "reg", &val);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Missing channel index %d\n", ret);
+ goto err;
+ }
+
+ ret = of_property_read_string(child, "label", &name);
+ /* label is optional */
+ if (!ret) {
+ if (strlen(name) >= STM32_ADC_CH_SZ) {
+ dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n",
+ name, STM32_ADC_CH_SZ);
+ return -EINVAL;
+ }
+ strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
+ ret = stm32_adc_populate_int_ch(indio_dev, name, val);
+ if (ret)
+ goto err;
+ } else if (ret != -EINVAL) {
+ dev_err(&indio_dev->dev, "Invalid label %d\n", ret);
+ goto err;
+ }
+
+ if (val >= adc_info->max_channels) {
+ dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ differential = false;
+ ret = of_property_read_u32_array(child, "diff-channels", vin, 2);
+ /* diff-channels is optional */
+ if (!ret) {
+ differential = true;
+ if (vin[0] != val || vin[1] >= adc_info->max_channels) {
+ dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
+ vin[0], vin[1]);
+ goto err;
+ }
+ } else if (ret != -EINVAL) {
+ dev_err(&indio_dev->dev, "Invalid diff-channels property %d\n", ret);
+ goto err;
+ }
+
+ stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
+ vin[1], scan_index, differential);
+
+ ret = of_property_read_u32(child, "st,min-sample-time-ns", &val);
+ /* st,min-sample-time-ns is optional */
+ if (!ret) {
+ stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
+ if (differential)
+ stm32_adc_smpr_init(adc, vin[1], val);
+ } else if (ret != -EINVAL) {
+ dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n",
+ ret);
+ goto err;
+ }
+
+ scan_index++;
+ }
+
+ return scan_index;
+
+err:
+ of_node_put(child);
+
+ return ret;
+}
+
+static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
+{
+ struct device_node *node = indio_dev->dev.of_node;
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
+ struct iio_chan_spec *channels;
+ int scan_index = 0, num_channels = 0, ret, i;
+ bool legacy = false;
+
+ for (i = 0; i < STM32_ADC_INT_CH_NB; i++)
+ adc->int_ch[i] = STM32_ADC_INT_CH_NONE;
+
+ num_channels = of_get_available_child_count(node);
+ /* If no channels have been found, fallback to channels legacy properties. */
+ if (!num_channels) {
+ legacy = true;
+
+ ret = stm32_adc_get_legacy_chan_count(indio_dev, adc);
+ if (!ret) {
+ dev_err(indio_dev->dev.parent, "No channel found\n");
+ return -ENODATA;
+ } else if (ret < 0) {
+ return ret;
+ }
+
+ num_channels = ret;
+ }
+
+ if (num_channels > adc_info->max_channels) {
+ dev_err(&indio_dev->dev, "Channel number [%d] exceeds %d\n",
+ num_channels, adc_info->max_channels);
+ return -EINVAL;
+ }
+
+ if (timestamping)
+ num_channels++;
+
+ channels = devm_kcalloc(&indio_dev->dev, num_channels,
+ sizeof(struct iio_chan_spec), GFP_KERNEL);
+ if (!channels)
+ return -ENOMEM;
+
+ if (legacy)
+ ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels);
+ else
+ ret = stm32_adc_generic_chan_init(indio_dev, adc, channels);
+ if (ret < 0)
+ return ret;
+ scan_index = ret;
+
if (timestamping) {
struct iio_chan_spec *timestamp = &channels[scan_index];
@@ -2099,7 +2424,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
};
static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
- .regs = &stm32h7_adc_regspec,
+ .regs = &stm32mp1_adc_regspec,
.adc_info = &stm32h7_adc_info,
.trigs = stm32h7_adc_trigs,
.has_vregready = true,
@@ -2109,6 +2434,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.unprepare = stm32h7_adc_unprepare,
.smp_cycles = stm32h7_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear,
+ .ts_vrefint_ns = 4300,
};
static const struct of_device_id stm32_adc_of_match[] = {
diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c
index 83c1ae07b3e9..8e7adec87755 100644
--- a/drivers/iio/adc/ti-adc128s052.c
+++ b/drivers/iio/adc/ti-adc128s052.c
@@ -132,6 +132,11 @@ static const struct iio_info adc128_info = {
.read_raw = adc128_read_raw,
};
+static void adc128_disable_regulator(void *reg)
+{
+ regulator_disable(reg);
+}
+
static int adc128_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
@@ -151,8 +156,6 @@ static int adc128_probe(struct spi_device *spi)
adc = iio_priv(indio_dev);
adc->spi = spi;
- spi_set_drvdata(spi, indio_dev);
-
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &adc128_info;
@@ -167,29 +170,14 @@ static int adc128_probe(struct spi_device *spi)
ret = regulator_enable(adc->reg);
if (ret < 0)
return ret;
-
- mutex_init(&adc->lock);
-
- ret = iio_device_register(indio_dev);
+ ret = devm_add_action_or_reset(&spi->dev, adc128_disable_regulator,
+ adc->reg);
if (ret)
- goto err_disable_regulator;
-
- return 0;
-
-err_disable_regulator:
- regulator_disable(adc->reg);
- return ret;
-}
-
-static int adc128_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct adc128 *adc = iio_priv(indio_dev);
+ return ret;
- iio_device_unregister(indio_dev);
- regulator_disable(adc->reg);
+ mutex_init(&adc->lock);
- return 0;
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct of_device_id adc128_of_match[] = {
@@ -231,7 +219,6 @@ static struct spi_driver adc128_driver = {
.acpi_match_table = ACPI_PTR(adc128_acpi_match),
},
.probe = adc128_probe,
- .remove = adc128_remove,
.id_table = adc128_id,
};
module_spi_driver(adc128_driver);
diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
index a2b83f0bd526..a7efa3eada2c 100644
--- a/drivers/iio/adc/ti-ads7950.c
+++ b/drivers/iio/adc/ti-ads7950.c
@@ -600,8 +600,8 @@ static int ti_ads7950_probe(struct spi_device *spi)
st->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(st->reg)) {
- dev_err(&spi->dev, "Failed to get regulator \"vref\"\n");
- ret = PTR_ERR(st->reg);
+ ret = dev_err_probe(&spi->dev, PTR_ERR(st->reg),
+ "Failed to get regulator \"vref\"\n");
goto error_destroy_mutex;
}
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 198d2916266d..83bea5ef765d 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1332,7 +1332,6 @@ static int xadc_probe(struct platform_device *pdev)
xadc = iio_priv(indio_dev);
xadc->ops = id->data;
- xadc->irq = irq;
init_completion(&xadc->completion);
mutex_init(&xadc->mutex);
spin_lock_init(&xadc->lock);
@@ -1397,7 +1396,7 @@ static int xadc_probe(struct platform_device *pdev)
}
}
- ret = devm_request_irq(dev, xadc->irq, xadc->ops->interrupt_handler, 0,
+ ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler, 0,
dev_name(dev), indio_dev);
if (ret)
return ret;
@@ -1407,7 +1406,7 @@ static int xadc_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);
+ ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret)
return ret;
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 8b80195725e9..7d78ce698967 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -67,7 +67,6 @@ struct xadc {
spinlock_t lock;
struct completion completion;
- int irq;
};
enum xadc_type {
diff --git a/drivers/iio/chemical/scd4x.c b/drivers/iio/chemical/scd4x.c
index ebebcb117ba2..267bc3c05338 100644
--- a/drivers/iio/chemical/scd4x.c
+++ b/drivers/iio/chemical/scd4x.c
@@ -353,7 +353,11 @@ static int scd4x_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_TEMP) {
+ if (chan->type == IIO_CONCENTRATION) {
+ *val = 0;
+ *val2 = 100;
+ return IIO_VAL_INT_PLUS_MICRO;
+ } else if (chan->type == IIO_TEMP) {
*val = 175000;
*val2 = 65536;
return IIO_VAL_FRACTIONAL;
@@ -503,7 +507,8 @@ static const struct iio_chan_spec scd4x_channels[] = {
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_CO2,
.modified = 1,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
.address = SCD4X_CO2,
.scan_index = SCD4X_CO2,
.scan_type = {
diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig
index 240b81502512..2c9e0559e8a4 100644
--- a/drivers/iio/frequency/Kconfig
+++ b/drivers/iio/frequency/Kconfig
@@ -49,5 +49,17 @@ config ADF4371
To compile this driver as a module, choose M here: the
module will be called adf4371.
+
+config ADRF6780
+ tristate "Analog Devices ADRF6780 Microwave Upconverter"
+ depends on SPI
+ depends on COMMON_CLK
+ help
+ Say yes here to build support for Analog Devices ADRF6780
+ 5.9 GHz to 23.6 GHz, Wideband, Microwave Upconverter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called adrf6780.
+
endmenu
endmenu
diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile
index 518b1e50caef..ae3136c79202 100644
--- a/drivers/iio/frequency/Makefile
+++ b/drivers/iio/frequency/Makefile
@@ -7,3 +7,4 @@
obj-$(CONFIG_AD9523) += ad9523.o
obj-$(CONFIG_ADF4350) += adf4350.o
obj-$(CONFIG_ADF4371) += adf4371.o
+obj-$(CONFIG_ADRF6780) += adrf6780.o
diff --git a/drivers/iio/frequency/adrf6780.c b/drivers/iio/frequency/adrf6780.c
new file mode 100644
index 000000000000..abe8b30fceca
--- /dev/null
+++ b/drivers/iio/frequency/adrf6780.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ADRF6780 driver
+ *
+ * Copyright 2021 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/spi/spi.h>
+
+#include <asm/unaligned.h>
+
+/* ADRF6780 Register Map */
+#define ADRF6780_REG_CONTROL 0x00
+#define ADRF6780_REG_ALARM_READBACK 0x01
+#define ADRF6780_REG_ALARM_MASKS 0x02
+#define ADRF6780_REG_ENABLE 0x03
+#define ADRF6780_REG_LINEARIZE 0x04
+#define ADRF6780_REG_LO_PATH 0x05
+#define ADRF6780_REG_ADC_CONTROL 0x06
+#define ADRF6780_REG_ADC_OUTPUT 0x0C
+
+/* ADRF6780_REG_CONTROL Map */
+#define ADRF6780_PARITY_EN_MSK BIT(15)
+#define ADRF6780_SOFT_RESET_MSK BIT(14)
+#define ADRF6780_CHIP_ID_MSK GENMASK(11, 4)
+#define ADRF6780_CHIP_ID 0xA
+#define ADRF6780_CHIP_REVISION_MSK GENMASK(3, 0)
+
+/* ADRF6780_REG_ALARM_READBACK Map */
+#define ADRF6780_PARITY_ERROR_MSK BIT(15)
+#define ADRF6780_TOO_FEW_ERRORS_MSK BIT(14)
+#define ADRF6780_TOO_MANY_ERRORS_MSK BIT(13)
+#define ADRF6780_ADDRESS_RANGE_ERROR_MSK BIT(12)
+
+/* ADRF6780_REG_ENABLE Map */
+#define ADRF6780_VGA_BUFFER_EN_MSK BIT(8)
+#define ADRF6780_DETECTOR_EN_MSK BIT(7)
+#define ADRF6780_LO_BUFFER_EN_MSK BIT(6)
+#define ADRF6780_IF_MODE_EN_MSK BIT(5)
+#define ADRF6780_IQ_MODE_EN_MSK BIT(4)
+#define ADRF6780_LO_X2_EN_MSK BIT(3)
+#define ADRF6780_LO_PPF_EN_MSK BIT(2)
+#define ADRF6780_LO_EN_MSK BIT(1)
+#define ADRF6780_UC_BIAS_EN_MSK BIT(0)
+
+/* ADRF6780_REG_LINEARIZE Map */
+#define ADRF6780_RDAC_LINEARIZE_MSK GENMASK(7, 0)
+
+/* ADRF6780_REG_LO_PATH Map */
+#define ADRF6780_LO_SIDEBAND_MSK BIT(10)
+#define ADRF6780_Q_PATH_PHASE_ACCURACY_MSK GENMASK(7, 4)
+#define ADRF6780_I_PATH_PHASE_ACCURACY_MSK GENMASK(3, 0)
+
+/* ADRF6780_REG_ADC_CONTROL Map */
+#define ADRF6780_VDET_OUTPUT_SELECT_MSK BIT(3)
+#define ADRF6780_ADC_START_MSK BIT(2)
+#define ADRF6780_ADC_EN_MSK BIT(1)
+#define ADRF6780_ADC_CLOCK_EN_MSK BIT(0)
+
+/* ADRF6780_REG_ADC_OUTPUT Map */
+#define ADRF6780_ADC_STATUS_MSK BIT(8)
+#define ADRF6780_ADC_VALUE_MSK GENMASK(7, 0)
+
+struct adrf6780_state {
+ struct spi_device *spi;
+ struct clk *clkin;
+ /* Protect against concurrent accesses to the device */
+ struct mutex lock;
+ bool vga_buff_en;
+ bool lo_buff_en;
+ bool if_mode_en;
+ bool iq_mode_en;
+ bool lo_x2_en;
+ bool lo_ppf_en;
+ bool lo_en;
+ bool uc_bias_en;
+ bool lo_sideband;
+ bool vdet_out_en;
+ u8 data[3] ____cacheline_aligned;
+};
+
+static int __adrf6780_spi_read(struct adrf6780_state *st, unsigned int reg,
+ unsigned int *val)
+{
+ int ret;
+ struct spi_transfer t = {0};
+
+ st->data[0] = 0x80 | (reg << 1);
+ st->data[1] = 0x0;
+ st->data[2] = 0x0;
+
+ t.rx_buf = &st->data[0];
+ t.tx_buf = &st->data[0];
+ t.len = 3;
+
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+
+ *val = (get_unaligned_be24(&st->data[0]) >> 1) & GENMASK(15, 0);
+
+ return ret;
+}
+
+static int adrf6780_spi_read(struct adrf6780_state *st, unsigned int reg,
+ unsigned int *val)
+{
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = adrf6780_spi_read(st, reg, val);
+ mutex_unlock(&st->lock);
+
+ return ret;
+}
+
+static int __adrf6780_spi_write(struct adrf6780_state *st,
+ unsigned int reg,
+ unsigned int val)
+{
+ put_unaligned_be24((val << 1) | (reg << 17), &st->data[0]);
+
+ return spi_write(st->spi, &st->data[0], 3);
+}
+
+static int adrf6780_spi_write(struct adrf6780_state *st, unsigned int reg,
+ unsigned int val)
+{
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = adrf6780_spi_write(st, reg, val);
+ mutex_unlock(&st->lock);
+
+ return ret;
+}
+
+static int __adrf6780_spi_update_bits(struct adrf6780_state *st,
+ unsigned int reg, unsigned int mask,
+ unsigned int val)
+{
+ int ret;
+ unsigned int data, temp;
+
+ ret = __adrf6780_spi_read(st, reg, &data);
+ if (ret)
+ return ret;
+
+ temp = (data & ~mask) | (val & mask);
+
+ return __adrf6780_spi_write(st, reg, temp);
+}
+
+static int adrf6780_spi_update_bits(struct adrf6780_state *st, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = __adrf6780_spi_update_bits(st, reg, mask, val);
+ mutex_unlock(&st->lock);
+
+ return ret;
+}
+
+static int adrf6780_read_adc_raw(struct adrf6780_state *st, unsigned int *read_val)
+{
+ int ret;
+
+ mutex_lock(&st->lock);
+
+ ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_ADC_CONTROL,
+ ADRF6780_ADC_EN_MSK |
+ ADRF6780_ADC_CLOCK_EN_MSK |
+ ADRF6780_ADC_START_MSK,
+ FIELD_PREP(ADRF6780_ADC_EN_MSK, 1) |
+ FIELD_PREP(ADRF6780_ADC_CLOCK_EN_MSK, 1) |
+ FIELD_PREP(ADRF6780_ADC_START_MSK, 1));
+ if (ret)
+ goto exit;
+
+ /* Recommended delay for the ADC to be ready*/
+ usleep_range(200, 250);
+
+ ret = __adrf6780_spi_read(st, ADRF6780_REG_ADC_OUTPUT, read_val);
+ if (ret)
+ goto exit;
+
+ if (!(*read_val & ADRF6780_ADC_STATUS_MSK)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_ADC_CONTROL,
+ ADRF6780_ADC_START_MSK,
+ FIELD_PREP(ADRF6780_ADC_START_MSK, 0));
+ if (ret)
+ goto exit;
+
+ ret = __adrf6780_spi_read(st, ADRF6780_REG_ADC_OUTPUT, read_val);
+
+exit:
+ mutex_unlock(&st->lock);
+ return ret;
+}
+
+static int adrf6780_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long info)
+{
+ struct adrf6780_state *dev = iio_priv(indio_dev);
+ unsigned int data;
+ int ret;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ ret = adrf6780_read_adc_raw(dev, &data);
+ if (ret)
+ return ret;
+
+ *val = data & ADRF6780_ADC_VALUE_MSK;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ ret = adrf6780_spi_read(dev, ADRF6780_REG_LINEARIZE, &data);
+ if (ret)
+ return ret;
+
+ *val = data & ADRF6780_RDAC_LINEARIZE_MSK;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_PHASE:
+ ret = adrf6780_spi_read(dev, ADRF6780_REG_LO_PATH, &data);
+ if (ret)
+ return ret;
+
+ switch (chan->channel2) {
+ case IIO_MOD_I:
+ *val = data & ADRF6780_I_PATH_PHASE_ACCURACY_MSK;
+
+ return IIO_VAL_INT;
+ case IIO_MOD_Q:
+ *val = FIELD_GET(ADRF6780_Q_PATH_PHASE_ACCURACY_MSK,
+ data);
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int adrf6780_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct adrf6780_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SCALE:
+ return adrf6780_spi_write(st, ADRF6780_REG_LINEARIZE, val);
+ case IIO_CHAN_INFO_PHASE:
+ switch (chan->channel2) {
+ case IIO_MOD_I:
+ return adrf6780_spi_update_bits(st,
+ ADRF6780_REG_LO_PATH,
+ ADRF6780_I_PATH_PHASE_ACCURACY_MSK,
+ FIELD_PREP(ADRF6780_I_PATH_PHASE_ACCURACY_MSK, val));
+ case IIO_MOD_Q:
+ return adrf6780_spi_update_bits(st,
+ ADRF6780_REG_LO_PATH,
+ ADRF6780_Q_PATH_PHASE_ACCURACY_MSK,
+ FIELD_PREP(ADRF6780_Q_PATH_PHASE_ACCURACY_MSK, val));
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int adrf6780_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int write_val,
+ unsigned int *read_val)
+{
+ struct adrf6780_state *st = iio_priv(indio_dev);
+
+ if (read_val)
+ return adrf6780_spi_read(st, reg, read_val);
+ else
+ return adrf6780_spi_write(st, reg, write_val);
+}
+
+static const struct iio_info adrf6780_info = {
+ .read_raw = adrf6780_read_raw,
+ .write_raw = adrf6780_write_raw,
+ .debugfs_reg_access = &adrf6780_reg_access,
+};
+
+#define ADRF6780_CHAN_ADC(_channel) { \
+ .type = IIO_ALTVOLTAGE, \
+ .output = 0, \
+ .indexed = 1, \
+ .channel = _channel, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \
+}
+
+#define ADRF6780_CHAN_RDAC(_channel) { \
+ .type = IIO_ALTVOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = _channel, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) \
+}
+
+#define ADRF6780_CHAN_IQ_PHASE(_channel, rf_comp) { \
+ .type = IIO_ALTVOLTAGE, \
+ .modified = 1, \
+ .output = 1, \
+ .indexed = 1, \
+ .channel2 = IIO_MOD_##rf_comp, \
+ .channel = _channel, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PHASE) \
+}
+
+static const struct iio_chan_spec adrf6780_channels[] = {
+ ADRF6780_CHAN_ADC(0),
+ ADRF6780_CHAN_RDAC(0),
+ ADRF6780_CHAN_IQ_PHASE(0, I),
+ ADRF6780_CHAN_IQ_PHASE(0, Q),
+};
+
+static int adrf6780_reset(struct adrf6780_state *st)
+{
+ int ret;
+ struct spi_device *spi = st->spi;
+
+ ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_CONTROL,
+ ADRF6780_SOFT_RESET_MSK,
+ FIELD_PREP(ADRF6780_SOFT_RESET_MSK, 1));
+ if (ret) {
+ dev_err(&spi->dev, "ADRF6780 SPI software reset failed.\n");
+ return ret;
+ }
+
+ ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_CONTROL,
+ ADRF6780_SOFT_RESET_MSK,
+ FIELD_PREP(ADRF6780_SOFT_RESET_MSK, 0));
+ if (ret) {
+ dev_err(&spi->dev, "ADRF6780 SPI software reset disable failed.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int adrf6780_init(struct adrf6780_state *st)
+{
+ int ret;
+ unsigned int chip_id, enable_reg, enable_reg_msk;
+ struct spi_device *spi = st->spi;
+
+ /* Perform a software reset */
+ ret = adrf6780_reset(st);
+ if (ret)
+ return ret;
+
+ ret = __adrf6780_spi_read(st, ADRF6780_REG_CONTROL, &chip_id);
+ if (ret)
+ return ret;
+
+ chip_id = FIELD_GET(ADRF6780_CHIP_ID_MSK, chip_id);
+ if (chip_id != ADRF6780_CHIP_ID) {
+ dev_err(&spi->dev, "ADRF6780 Invalid Chip ID.\n");
+ return -EINVAL;
+ }
+
+ enable_reg_msk = ADRF6780_VGA_BUFFER_EN_MSK |
+ ADRF6780_DETECTOR_EN_MSK |
+ ADRF6780_LO_BUFFER_EN_MSK |
+ ADRF6780_IF_MODE_EN_MSK |
+ ADRF6780_IQ_MODE_EN_MSK |
+ ADRF6780_LO_X2_EN_MSK |
+ ADRF6780_LO_PPF_EN_MSK |
+ ADRF6780_LO_EN_MSK |
+ ADRF6780_UC_BIAS_EN_MSK;
+
+ enable_reg = FIELD_PREP(ADRF6780_VGA_BUFFER_EN_MSK, st->vga_buff_en) |
+ FIELD_PREP(ADRF6780_DETECTOR_EN_MSK, 1) |
+ FIELD_PREP(ADRF6780_LO_BUFFER_EN_MSK, st->lo_buff_en) |
+ FIELD_PREP(ADRF6780_IF_MODE_EN_MSK, st->if_mode_en) |
+ FIELD_PREP(ADRF6780_IQ_MODE_EN_MSK, st->iq_mode_en) |
+ FIELD_PREP(ADRF6780_LO_X2_EN_MSK, st->lo_x2_en) |
+ FIELD_PREP(ADRF6780_LO_PPF_EN_MSK, st->lo_ppf_en) |
+ FIELD_PREP(ADRF6780_LO_EN_MSK, st->lo_en) |
+ FIELD_PREP(ADRF6780_UC_BIAS_EN_MSK, st->uc_bias_en);
+
+ ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_ENABLE,
+ enable_reg_msk, enable_reg);
+ if (ret)
+ return ret;
+
+ ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_LO_PATH,
+ ADRF6780_LO_SIDEBAND_MSK,
+ FIELD_PREP(ADRF6780_LO_SIDEBAND_MSK, st->lo_sideband));
+ if (ret)
+ return ret;
+
+ return __adrf6780_spi_update_bits(st, ADRF6780_REG_ADC_CONTROL,
+ ADRF6780_VDET_OUTPUT_SELECT_MSK,
+ FIELD_PREP(ADRF6780_VDET_OUTPUT_SELECT_MSK, st->vdet_out_en));
+}
+
+static void adrf6780_properties_parse(struct adrf6780_state *st)
+{
+ struct spi_device *spi = st->spi;
+
+ st->vga_buff_en = device_property_read_bool(&spi->dev, "adi,vga-buff-en");
+ st->lo_buff_en = device_property_read_bool(&spi->dev, "adi,lo-buff-en");
+ st->if_mode_en = device_property_read_bool(&spi->dev, "adi,if-mode-en");
+ st->iq_mode_en = device_property_read_bool(&spi->dev, "adi,iq-mode-en");
+ st->lo_x2_en = device_property_read_bool(&spi->dev, "adi,lo-x2-en");
+ st->lo_ppf_en = device_property_read_bool(&spi->dev, "adi,lo-ppf-en");
+ st->lo_en = device_property_read_bool(&spi->dev, "adi,lo-en");
+ st->uc_bias_en = device_property_read_bool(&spi->dev, "adi,uc-bias-en");
+ st->lo_sideband = device_property_read_bool(&spi->dev, "adi,lo-sideband");
+ st->vdet_out_en = device_property_read_bool(&spi->dev, "adi,vdet-out-en");
+}
+
+static void adrf6780_clk_disable(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static void adrf6780_powerdown(void *data)
+{
+ /* Disable all components in the Enable Register */
+ adrf6780_spi_write(data, ADRF6780_REG_ENABLE, 0x0);
+}
+
+static int adrf6780_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct adrf6780_state *st;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ indio_dev->info = &adrf6780_info;
+ indio_dev->name = "adrf6780";
+ indio_dev->channels = adrf6780_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adrf6780_channels);
+
+ st->spi = spi;
+
+ adrf6780_properties_parse(st);
+
+ st->clkin = devm_clk_get(&spi->dev, "lo_in");
+ if (IS_ERR(st->clkin))
+ return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
+ "failed to get the LO input clock\n");
+
+ ret = clk_prepare_enable(st->clkin);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev, adrf6780_clk_disable,
+ st->clkin);
+ if (ret)
+ return ret;
+
+ mutex_init(&st->lock);
+
+ ret = adrf6780_init(st);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev, adrf6780_powerdown, st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct spi_device_id adrf6780_id[] = {
+ { "adrf6780", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, adrf6780_id);
+
+static const struct of_device_id adrf6780_of_match[] = {
+ { .compatible = "adi,adrf6780" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, adrf6780_of_match);
+
+static struct spi_driver adrf6780_driver = {
+ .driver = {
+ .name = "adrf6780",
+ .of_match_table = adrf6780_of_match,
+ },
+ .probe = adrf6780_probe,
+ .id_table = adrf6780_id,
+};
+module_spi_driver(adrf6780_driver);
+
+MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com");
+MODULE_DESCRIPTION("Analog Devices ADRF6780");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 0f54df85134a..f2cbbc756459 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -1281,6 +1281,8 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
int err;
switch (sensor->id) {
+ case ST_LSM6DSX_ID_GYRO:
+ break;
case ST_LSM6DSX_ID_EXT0:
case ST_LSM6DSX_ID_EXT1:
case ST_LSM6DSX_ID_EXT2:
@@ -1306,8 +1308,8 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
}
break;
}
- default:
- break;
+ default: /* should never occur */
+ return -EINVAL;
}
if (req_odr > 0) {
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 7932e86cd8e9..e180728914c0 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -179,7 +179,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
struct iio_buffer *rb = ib->buffer;
struct iio_dev *indio_dev = ib->indio_dev;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
- int ret;
+ int ret = 0;
size_t written;
if (!indio_dev->info)
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index 4c83953672be..3e7fb16ab1f6 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -159,6 +159,7 @@ static int cm3605_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
enum iio_chan_type ch_type;
u32 rset;
+ int irq;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*cm3605));
@@ -195,12 +196,9 @@ static int cm3605_probe(struct platform_device *pdev)
cm3605->aout = devm_iio_channel_get(dev, "aout");
if (IS_ERR(cm3605->aout)) {
- if (PTR_ERR(cm3605->aout) == -ENODEV) {
- dev_err(dev, "no ADC, deferring...\n");
- return -EPROBE_DEFER;
- }
- dev_err(dev, "failed to get AOUT ADC channel\n");
- return PTR_ERR(cm3605->aout);
+ ret = PTR_ERR(cm3605->aout);
+ ret = (ret == -ENODEV) ? -EPROBE_DEFER : ret;
+ return dev_err_probe(dev, ret, "failed to get AOUT ADC channel\n");
}
ret = iio_get_channel_type(cm3605->aout, &ch_type);
if (ret < 0)
@@ -211,10 +209,10 @@ static int cm3605_probe(struct platform_device *pdev)
}
cm3605->vdd = devm_regulator_get(dev, "vdd");
- if (IS_ERR(cm3605->vdd)) {
- dev_err(dev, "failed to get VDD regulator\n");
- return PTR_ERR(cm3605->vdd);
- }
+ if (IS_ERR(cm3605->vdd))
+ return dev_err_probe(dev, PTR_ERR(cm3605->vdd),
+ "failed to get VDD regulator\n");
+
ret = regulator_enable(cm3605->vdd);
if (ret) {
dev_err(dev, "failed to enable VDD regulator\n");
@@ -223,13 +221,16 @@ static int cm3605_probe(struct platform_device *pdev)
cm3605->aset = devm_gpiod_get(dev, "aset", GPIOD_OUT_HIGH);
if (IS_ERR(cm3605->aset)) {
- dev_err(dev, "no ASET GPIO\n");
- ret = PTR_ERR(cm3605->aset);
+ ret = dev_err_probe(dev, PTR_ERR(cm3605->aset), "no ASET GPIO\n");
goto out_disable_vdd;
}
- ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
- cm3605_prox_irq, NULL, 0, "cm3605", indio_dev);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "failed to get irq\n");
+
+ ret = devm_request_threaded_irq(dev, irq, cm3605_prox_irq,
+ NULL, 0, "cm3605", indio_dev);
if (ret) {
dev_err(dev, "unable to request IRQ\n");
goto out_disable_aset;
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index f960be7d4001..c6d1d88d3775 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -503,12 +503,9 @@ static int gp2ap002_probe(struct i2c_client *client,
if (!gp2ap002->is_gp2ap002s00f) {
gp2ap002->alsout = devm_iio_channel_get(dev, "alsout");
if (IS_ERR(gp2ap002->alsout)) {
- if (PTR_ERR(gp2ap002->alsout) == -ENODEV) {
- dev_err(dev, "no ADC, deferring...\n");
- return -EPROBE_DEFER;
- }
- dev_err(dev, "failed to get ALSOUT ADC channel\n");
- return PTR_ERR(gp2ap002->alsout);
+ ret = PTR_ERR(gp2ap002->alsout);
+ ret = (ret == -ENODEV) ? -EPROBE_DEFER : ret;
+ return dev_err_probe(dev, ret, "failed to get ALSOUT ADC channel\n");
}
ret = iio_get_channel_type(gp2ap002->alsout, &ch_type);
if (ret < 0)
@@ -521,15 +518,14 @@ static int gp2ap002_probe(struct i2c_client *client,
}
gp2ap002->vdd = devm_regulator_get(dev, "vdd");
- if (IS_ERR(gp2ap002->vdd)) {
- dev_err(dev, "failed to get VDD regulator\n");
- return PTR_ERR(gp2ap002->vdd);
- }
+ if (IS_ERR(gp2ap002->vdd))
+ return dev_err_probe(dev, PTR_ERR(gp2ap002->vdd),
+ "failed to get VDD regulator\n");
+
gp2ap002->vio = devm_regulator_get(dev, "vio");
- if (IS_ERR(gp2ap002->vio)) {
- dev_err(dev, "failed to get VIO regulator\n");
- return PTR_ERR(gp2ap002->vio);
- }
+ if (IS_ERR(gp2ap002->vio))
+ return dev_err_probe(dev, PTR_ERR(gp2ap002->vio),
+ "failed to get VIO regulator\n");
/* Operating voltage 2.4V .. 3.6V according to datasheet */
ret = regulator_set_voltage(gp2ap002->vdd, 2400000, 3600000);
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 1830221da48d..7e51aaac0bf8 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/acpi.h>
+#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/events.h>
@@ -151,6 +152,7 @@ struct ltr501_chip_info {
struct ltr501_data {
struct i2c_client *client;
+ struct regulator_bulk_data regulators[2];
struct mutex lock_als, lock_ps;
const struct ltr501_chip_info *chip_info;
u8 als_contr, ps_contr;
@@ -1379,6 +1381,13 @@ static const struct regmap_config ltr501_regmap_config = {
.volatile_reg = ltr501_is_volatile_reg,
};
+static void ltr501_disable_regulators(void *d)
+{
+ struct ltr501_data *data = d;
+
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
+}
+
static int ltr501_powerdown(struct ltr501_data *data)
{
return ltr501_write_contr(data, data->als_contr &
@@ -1423,6 +1432,25 @@ static int ltr501_probe(struct i2c_client *client,
mutex_init(&data->lock_als);
mutex_init(&data->lock_ps);
+ data->regulators[0].supply = "vdd";
+ data->regulators[1].supply = "vddio";
+ ret = devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(data->regulators),
+ data->regulators);
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to get regulators\n");
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
+ data->regulators);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&client->dev,
+ ltr501_disable_regulators, data);
+ if (ret)
+ return ret;
+
data->reg_it = devm_regmap_field_alloc(&client->dev, regmap,
reg_field_it);
if (IS_ERR(data->reg_it)) {
@@ -1581,9 +1609,18 @@ static const struct i2c_device_id ltr501_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ltr501_id);
+static const struct of_device_id ltr501_of_match[] = {
+ { .compatible = "liteon,ltr501", },
+ { .compatible = "liteon,ltr559", },
+ { .compatible = "liteon,ltr301", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, ltr501_of_match);
+
static struct i2c_driver ltr501_driver = {
.driver = {
.name = LTR501_DRV_NAME,
+ .of_match_table = ltr501_of_match,
.pm = &ltr501_pm_ops,
.acpi_match_table = ACPI_PTR(ltr_acpi_match),
},
diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c
index d54ae5cbe51b..f422d44377df 100644
--- a/drivers/iio/multiplexer/iio-mux.c
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -33,6 +33,7 @@ struct mux {
struct iio_chan_spec *chan;
struct iio_chan_spec_ext_info *ext_info;
struct mux_child *child;
+ u32 delay_us;
};
static int iio_mux_select(struct mux *mux, int idx)
@@ -42,7 +43,8 @@ static int iio_mux_select(struct mux *mux, int idx)
int ret;
int i;
- ret = mux_control_select(mux->control, chan->channel);
+ ret = mux_control_select_delay(mux->control, chan->channel,
+ mux->delay_us);
if (ret < 0) {
mux->cached_state = -1;
return ret;
@@ -392,6 +394,9 @@ static int mux_probe(struct platform_device *pdev)
mux->parent = parent;
mux->cached_state = -1;
+ mux->delay_us = 0;
+ of_property_read_u32(np, "settle-time-us", &mux->delay_us);
+
indio_dev->name = dev_name(dev);
indio_dev->info = &mux_info;
indio_dev->modes = INDIO_DIRECT_MODE;