diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml index a58334c3bb76..ec0450d111a9 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml @@ -222,6 +222,12 @@ patternProperties: '#io-channel-cells': const: 1 + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + interrupts: description: | IRQ Line for the ADC instance. Valid values are: @@ -256,6 +262,7 @@ patternProperties: - 20 channels, numbered from 0 to 19 (for in0..in19) on stm32h7 and stm32mp1. $ref: /schemas/types.yaml#/definitions/uint32-array + deprecated: true st,adc-diff-channels: description: | @@ -265,7 +272,9 @@ patternProperties: , ,... vinp and vinn are numbered from 0 to 19. Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is - required. Both properties can be used together. Some channels can be + required if no adc generic channel is defined. These legacy channel + properties are exclusive with adc generic channel bindings. + Both properties can be used together. Some channels can be used as single-ended and some other ones as differential (mixed). But channels can't be configured both as single-ended and differential. $ref: /schemas/types.yaml#/definitions/uint32-matrix @@ -279,6 +288,7 @@ patternProperties: "vinn" indicates negative input number minimum: 0 maximum: 19 + deprecated: true st,min-sample-time-nsecs: description: @@ -289,6 +299,50 @@ patternProperties: list, to set sample time resp. for all channels, or independently for each channel. $ref: /schemas/types.yaml#/definitions/uint32-array + deprecated: true + + nvmem-cells: + items: + - description: Phandle to the calibration vrefint data provided by otp + + nvmem-cell-names: + items: + - const: vrefint + + patternProperties: + "^channel@([0-9]|1[0-9])$": + type: object + $ref: "adc.yaml" + description: Represents the external channels which are connected to the ADC. + + properties: + reg: + items: + minimum: 0 + maximum: 19 + + label: + description: | + Unique name to identify which channel this is. + Reserved label names "vddcore", "vrefint" and "vbat" + are used to identify internal channels with matching names. + + diff-channels: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + minimum: 0 + maximum: 19 + + st,min-sample-time-ns: + description: | + Minimum sampling time in nanoseconds. Depending on hardware (board) + e.g. high/low analog input source impedance, fine tune of ADC + sampling time may be recommended. + + required: + - reg + + additionalProperties: false allOf: - if: @@ -369,12 +423,6 @@ patternProperties: additionalProperties: false - anyOf: - - required: - - st,adc-channels - - required: - - st,adc-diff-channels - required: - compatible - reg @@ -451,4 +499,50 @@ examples: // other adc child node follow... }; + - | + // Example 3: with stm32mp157c to setup ADC2 with: + // - internal channels 13, 14, 15. + #include + #include + adc122: adc@48003000 { + compatible = "st,stm32mp1-adc-core"; + reg = <0x48003000 0x400>; + interrupts = , + ; + clocks = <&rcc ADC12>, <&rcc ADC12_K>; + clock-names = "bus", "adc"; + booster-supply = <&booster>; + vdd-supply = <&vdd>; + vdda-supply = <&vdda>; + vref-supply = <&vref>; + st,syscfg = <&syscfg>; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + adc@100 { + compatible = "st,stm32mp1-adc"; + #io-channel-cells = <1>; + reg = <0x100>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + channel@13 { + reg = <13>; + label = "vrefint"; + st,min-sample-time-ns = <9000>; + }; + channel@14 { + reg = <14>; + label = "vddcore"; + st,min-sample-time-ns = <9000>; + }; + channel@15 { + reg = <15>; + label = "vbat"; + st,min-sample-time-ns = <9000>; + }; + }; + }; + ... diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,adrf6780.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,adrf6780.yaml new file mode 100644 index 000000000000..3a8ea93f4e0c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/frequency/adi,adrf6780.yaml @@ -0,0 +1,131 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/frequency/adi,adrf6780.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ADRF6780 Microwave Upconverter + +maintainers: + - Antoniu Miclaus + +description: | + Wideband, microwave upconverter optimized for point to point microwave + radio designs operating in the 5.9 GHz to 23.6 GHz frequency range. + + https://www.analog.com/en/products/adrf6780.html + +properties: + compatible: + enum: + - adi,adrf6780 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 1000000 + + clocks: + description: + Definition of the external clock. + minItems: 1 + + clock-names: + items: + - const: lo_in + + clock-output-names: + maxItems: 1 + + adi,vga-buff-en: + description: + RF Variable Gain Amplifier Buffer Enable. Gain is controlled by + the voltage on the VATT pin. + type: boolean + + adi,lo-buff-en: + description: + Local Oscillator Amplifier Enable. Disable to put the part in + a power down state. + type: boolean + + adi,if-mode-en: + description: + Intermediate Frequency Mode Enable. Either IF Mode or I/Q Mode + can be enabled at a time. + type: boolean + + adi,iq-mode-en: + description: + I/Q Mode Enable. Either IF Mode or I/Q Mode can be enabled at a + time. + type: boolean + + adi,lo-x2-en: + description: + Double the Local Oscillator output frequency from the Local + Oscillator Input Frequency. Either LOx1 or LOx2 can be enabled + at a time. + type: boolean + + adi,lo-ppf-en: + description: + Local Oscillator input frequency equal to the Local Oscillator + output frequency (LO x1). Either LOx1 or LOx2 can be enabled + at a time. + type: boolean + + adi,lo-en: + description: + Enable additional cirtuitry in the LO chain. Disable to put the + part in a power down state. + type: boolean + + adi,uc-bias-en: + description: + Enable all bias circuitry thourghout the entire part. + Disable to put the part in a power down state. + type: boolean + + adi,lo-sideband: + description: + Switch to the Lower LO Sideband. By default the Upper LO + sideband is enabled. + type: boolean + + adi,vdet-out-en: + description: + VDET Output Select Enable. Expose the RF detector output to the + VDET external pin. + type: boolean + + '#clock-cells': + const: 0 + +dependencies: + adi,lo-x2-en: [ "adi,lo-en" ] + adi,lo-ppf-en: [ "adi,lo-en" ] + +required: + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + adrf6780@0 { + compatible = "adi,adrf6780"; + reg = <0>; + spi-max-frequency = <1000000>; + clocks = <&adrf6780_lo>; + clock-names = "lo_in"; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml b/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml new file mode 100644 index 000000000000..db0407bc9209 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/liteon,ltr501.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LiteON LTR501 I2C Proximity and Light sensor + +maintainers: + - Nikita Travkin + +properties: + compatible: + enum: + - liteon,ltr501 + - liteon,ltr559 + - liteon,ltr301 + + reg: + maxItems: 1 + + vdd-supply: true + vddio-supply: true + + interrupts: + maxItems: 1 + +additionalProperties: false + +required: + - compatible + - reg + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + light-sensor@23 { + compatible = "liteon,ltr559"; + reg = <0x23>; + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + + interrupt-parent = <&msmgpio>; + interrupts = <115 IRQ_TYPE_EDGE_FALLING>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.yaml b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.yaml index 870b043406d8..611ad4444cf0 100644 --- a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.yaml +++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.yaml @@ -35,9 +35,18 @@ properties: mux-control-names: true channels: - $ref: /schemas/types.yaml#/definitions/string-array + $ref: /schemas/types.yaml#/definitions/non-unique-string-array description: - List of strings, labeling the mux controller states. + List of strings, labeling the mux controller states. An empty + string for a state means that the channel is not available. + + settle-time-us: + default: 0 + description: + Time required for analog signals to settle after muxing. + + "#io-channel-cells": + const: 1 required: - compatible diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 42b529a8e5db..be42b4b2fcd5 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -653,6 +653,8 @@ patternProperties: description: Linux-specific binding "^linx,.*": description: Linx Technologies + "^liteon,.*": + description: LITE-ON Technology Corp. "^litex,.*": description: LiteX SoC builder "^lltc,.*": 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; - } + ret = devm_add_action_or_reset(&pdev->dev, lpc18xx_clear_cr_reg, adc); + if (ret) + return ret; - 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); - - 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 #include #include +#include #include #include #include @@ -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 @@ -113,6 +139,16 @@ struct stm32_adc_regs { int shift; }; +/** + * 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 @@ -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,6 +1895,227 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) return -EINVAL; } + return num_channels; +} + +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) { + dev_err(&indio_dev->dev, "Invalid channel %d\n", val); + return -EINVAL; + } + + /* 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 misconfigured\n", val); + return -EINVAL; + } + } + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, + 0, scan_index, false); + scan_index++; + } + + for (i = 0; i < scan_index; i++) { + /* + * Using of_property_read_u32_index(), smp value will only be + * modified if valid u32 value can be decoded. This allows to + * 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); + + /* 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++; @@ -1762,50 +2124,13 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) if (!channels) return -ENOMEM; - of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) { - if (val >= adc_info->max_channels) { - dev_err(&indio_dev->dev, "Invalid channel %d\n", val); - return -EINVAL; - } - - /* 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); - return -EINVAL; - } - } - stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, - 0, scan_index, false); - 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 - * modified if valid u32 value can be decoded. This allows to - * 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); - /* Prepare sampling time settings */ - stm32_adc_smpr_init(adc, channels[i].channel, smp); - } + 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; + ret = devm_add_action_or_reset(&spi->dev, adc128_disable_regulator, + adc->reg); + if (ret) + return ret; mutex_init(&adc->lock); - ret = iio_device_register(indio_dev); - 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); - - iio_device_unregister(indio_dev); - regulator_disable(adc->reg); - - 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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 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 #include #include +#include #include #include @@ -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 = <r501_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; diff --git a/drivers/mux/core.c b/drivers/mux/core.c index 1fb22388e7e0..22f4709768d1 100644 --- a/drivers/mux/core.c +++ b/drivers/mux/core.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) "mux-core: " fmt +#include #include #include #include @@ -116,6 +117,7 @@ struct mux_chip *mux_chip_alloc(struct device *dev, sema_init(&mux->lock, 1); mux->cached_state = MUX_CACHE_UNKNOWN; mux->idle_state = MUX_IDLE_AS_IS; + mux->last_change = ktime_get(); } device_initialize(&mux_chip->dev); @@ -129,6 +131,8 @@ static int mux_control_set(struct mux_control *mux, int state) int ret = mux->chip->ops->set(mux, state); mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state; + if (ret >= 0) + mux->last_change = ktime_get(); return ret; } @@ -314,10 +318,25 @@ static int __mux_control_select(struct mux_control *mux, int state) return ret; } +static void mux_control_delay(struct mux_control *mux, unsigned int delay_us) +{ + ktime_t delayend; + s64 remaining; + + if (!delay_us) + return; + + delayend = ktime_add_us(mux->last_change, delay_us); + remaining = ktime_us_delta(delayend, ktime_get()); + if (remaining > 0) + fsleep(remaining); +} + /** - * mux_control_select() - Select the given multiplexer state. + * mux_control_select_delay() - Select the given multiplexer state. * @mux: The mux-control to request a change of state from. * @state: The new requested state. + * @delay_us: The time to delay (in microseconds) if the mux state is changed. * * On successfully selecting the mux-control state, it will be locked until * there is a call to mux_control_deselect(). If the mux-control is already @@ -331,7 +350,8 @@ static int __mux_control_select(struct mux_control *mux, int state) * Return: 0 when the mux-control state has the requested state or a negative * errno on error. */ -int mux_control_select(struct mux_control *mux, unsigned int state) +int mux_control_select_delay(struct mux_control *mux, unsigned int state, + unsigned int delay_us) { int ret; @@ -340,18 +360,21 @@ int mux_control_select(struct mux_control *mux, unsigned int state) return ret; ret = __mux_control_select(mux, state); + if (ret >= 0) + mux_control_delay(mux, delay_us); if (ret < 0) up(&mux->lock); return ret; } -EXPORT_SYMBOL_GPL(mux_control_select); +EXPORT_SYMBOL_GPL(mux_control_select_delay); /** - * mux_control_try_select() - Try to select the given multiplexer state. + * mux_control_try_select_delay() - Try to select the given multiplexer state. * @mux: The mux-control to request a change of state from. * @state: The new requested state. + * @delay_us: The time to delay (in microseconds) if the mux state is changed. * * On successfully selecting the mux-control state, it will be locked until * mux_control_deselect() called. @@ -363,7 +386,8 @@ EXPORT_SYMBOL_GPL(mux_control_select); * Return: 0 when the mux-control state has the requested state or a negative * errno on error. Specifically -EBUSY if the mux-control is contended. */ -int mux_control_try_select(struct mux_control *mux, unsigned int state) +int mux_control_try_select_delay(struct mux_control *mux, unsigned int state, + unsigned int delay_us) { int ret; @@ -371,13 +395,15 @@ int mux_control_try_select(struct mux_control *mux, unsigned int state) return -EBUSY; ret = __mux_control_select(mux, state); + if (ret >= 0) + mux_control_delay(mux, delay_us); if (ret < 0) up(&mux->lock); return ret; } -EXPORT_SYMBOL_GPL(mux_control_try_select); +EXPORT_SYMBOL_GPL(mux_control_try_select_delay); /** * mux_control_deselect() - Deselect the previously selected multiplexer state. diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h index 5fc6bb2fefad..7a09b040ac39 100644 --- a/include/linux/mux/consumer.h +++ b/include/linux/mux/consumer.h @@ -16,10 +16,25 @@ struct device; struct mux_control; unsigned int mux_control_states(struct mux_control *mux); -int __must_check mux_control_select(struct mux_control *mux, - unsigned int state); -int __must_check mux_control_try_select(struct mux_control *mux, - unsigned int state); +int __must_check mux_control_select_delay(struct mux_control *mux, + unsigned int state, + unsigned int delay_us); +int __must_check mux_control_try_select_delay(struct mux_control *mux, + unsigned int state, + unsigned int delay_us); + +static inline int __must_check mux_control_select(struct mux_control *mux, + unsigned int state) +{ + return mux_control_select_delay(mux, state, 0); +} + +static inline int __must_check mux_control_try_select(struct mux_control *mux, + unsigned int state) +{ + return mux_control_try_select_delay(mux, state, 0); +} + int mux_control_deselect(struct mux_control *mux); struct mux_control *mux_control_get(struct device *dev, const char *mux_name); diff --git a/include/linux/mux/driver.h b/include/linux/mux/driver.h index 627a2c6bc02d..18824064f8c0 100644 --- a/include/linux/mux/driver.h +++ b/include/linux/mux/driver.h @@ -12,6 +12,7 @@ #include #include +#include #include struct mux_chip; @@ -33,6 +34,7 @@ struct mux_control_ops { * @states: The number of mux controller states. * @idle_state: The mux controller state to use when inactive, or one * of MUX_IDLE_AS_IS and MUX_IDLE_DISCONNECT. + * @last_change: Timestamp of last change * * Mux drivers may only change @states and @idle_state, and may only do so * between allocation and registration of the mux controller. Specifically, @@ -47,6 +49,8 @@ struct mux_control { unsigned int states; int idle_state; + + ktime_t last_change; }; /**