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.
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmFxyHIRHGppYzIzQGtl
 cm5lbC5vcmcACgkQVIU0mcT0FojRCBAAgIbn0CdCVo5cmYZNV1cIcc1ReGBbfgHq
 HopVcs9XDO4aHfzTLSa8bRhAp+bWCLq+ld/3vQ4tWDAJCXM4wh6VW9GOOMhqtDhr
 TWYPC9jlH+/z5PWzySozCJ6CsHjU5Z96q+SbQGSfoQZr1xelCO9J51gbT0hZS3Dr
 LntwcWQWCCC3LW0WGj4ApKJnW4exqi30ty09Qwfujpa9X5nO2soawSBApfIlInR8
 rUrE0WBaE8/rx8ORwngrj+Tfz5F3WNz77KooFR6oGkXOuMOxSLIWS77nUntEQbUc
 SRfHUJTTUbL5uI+8ZWZe7IWZzL/OX6uyicsJwcrLxzhw0Z/+i714fIMVLxAEHWqD
 D+JgcKiGYO/aPgl23XDOYb8I010TF9tf0bkbNcxzOBa4xdhixBLeg5PyWOMhwUKt
 uaslEGKduoJ4S7olcebZJAt3wEHp8YXn71LSkHt6M+fC7rRtzpfSK/L35ZHTb7PI
 JxzWGYaD7ZdIHd4y3f7KOU/B2/aEv+ez6NLC+yb8+Bs15nZ/B17zLDAmcd+THvxi
 QOBpm/K12rDfqSGV663UCtIq+elScx0J7bIuZG1JwPIfZAiwzBNrOTLZG0o+b3bD
 JIYIoZX+45tCR5i3Lukk27QhJ2hJ/7VVOcSQ3aPcgoMTl6QCTV8Fo2oofAZ1JIMo
 yHjv28K4ZyA=
 =XWvW
 -----END PGP SIGNATURE-----

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()
  ...
This commit is contained in:
Greg Kroah-Hartman 2021-10-24 13:09:37 +02:00
commit b6df1fc1e3
34 changed files with 1488 additions and 271 deletions

View File

@ -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 vinn>, <vinp vinn>,... 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 <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
adc122: adc@48003000 {
compatible = "st,stm32mp1-adc-core";
reg = <0x48003000 0x400>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
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>;
};
};
};
...

View File

@ -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 <antoniu.miclaus@analog.com>
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";
};
};
...

View File

@ -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 <nikita@trvn.ru>
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 <dt-bindings/interrupt-controller/irq.h>
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>;
};
};

View File

@ -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

View File

@ -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,.*":

View File

@ -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,

View File

@ -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) {

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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");

View File

@ -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;

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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
@ -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[] = {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -67,7 +67,6 @@ struct xadc {
spinlock_t lock;
struct completion completion;
int irq;
};
enum xadc_type {

View File

@ -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 = {

View File

@ -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

View File

@ -7,3 +7,4 @@
obj-$(CONFIG_AD9523) += ad9523.o
obj-$(CONFIG_ADF4350) += adf4350.o
obj-$(CONFIG_ADF4371) += adf4371.o
obj-$(CONFIG_ADRF6780) += adrf6780.o

View File

@ -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");

View File

@ -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) {

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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),
},

View File

@ -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;

View File

@ -9,6 +9,7 @@
#define pr_fmt(fmt) "mux-core: " fmt
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
@ -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.

View File

@ -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);

View File

@ -12,6 +12,7 @@
#include <dt-bindings/mux/mux.h>
#include <linux/device.h>
#include <linux/ktime.h>
#include <linux/semaphore.h>
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;
};
/**