diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 4fc9f6bd4281..d8d6d85235b0 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -764,10 +764,13 @@ Contact: linux-iio@vger.kernel.org Description: Specifies the output powerdown mode. DAC output stage is disconnected from the amplifier and + 500ohm_to_gnd: connected to ground via a 500Ohm resistor, 1kohm_to_gnd: connected to ground via an 1kOhm resistor, 2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor, + 3.85kohm_to_gnd: connected to ground via a 3.85kOhm resistor, 6kohm_to_gnd: connected to ground via a 6kOhm resistor, 7.7kohm_to_gnd: connected to ground via a 7.7kOhm resistor, + 16kohm_to_gnd: connected to ground via a 16kOhm resistor, 20kohm_to_gnd: connected to ground via a 20kOhm resistor, 32kohm_to_gnd: connected to ground via a 32kOhm resistor, 42kohm_to_gnd: connected to ground via a 42kOhm resistor, @@ -1510,21 +1513,24 @@ Contact: linux-iio@vger.kernel.org Description: Description of the scan element data storage within the buffer and hence the form in which it is read from user-space. - Form is [be|le]:[s|u]bits/storagebits[>>shift]. - be or le specifies big or little endian. s or u specifies if - signed (2's complement) or unsigned. bits is the number of bits - of data and storagebits is the space (after padding) that it - occupies in the buffer. shift if specified, is the shift that - needs to be applied prior to masking out unused bits. Some - devices put their data in the middle of the transferred elements - with additional information on both sides. Note that some - devices will have additional information in the unused bits - so to get a clean value, the bits value must be used to mask - the buffer output value appropriately. The storagebits value - also specifies the data alignment. So s48/64>>2 will be a - signed 48 bit integer stored in a 64 bit location aligned to - a 64 bit boundary. To obtain the clean value, shift right 2 - and apply a mask to zero the top 16 bits of the result. + Form is [be|le]:[f|s|u]bits/storagebits[>>shift]. + be or le specifies big or little endian. f means floating-point + (IEEE 754 binary format), s means signed (2's complement), u means + unsigned. bits is the number of bits of data and storagebits is the + space (after padding) that it occupies in the buffer; when using a + floating-point format, bits must be one of the width values defined + in the IEEE 754 standard for binary interchange formats (e.g. 16 + indicates the binary16 format for half-precision numbers). shift, + if specified, is the shift that needs to be applied prior to + masking out unused bits. Some devices put their data in the middle + of the transferred elements with additional information on both + sides. Note that some devices will have additional information in + the unused bits, so to get a clean value the bits value must be + used to mask the buffer output value appropriately. The storagebits + value also specifies the data alignment. So s48/64>>2 will be a + signed 48 bit integer stored in a 64 bit location aligned to a 64 + bit boundary. To obtain the clean value, shift right 2 and apply a + mask to zero the top 16 bits of the result. For other storage combinations this attribute will be extended appropriately. @@ -1752,6 +1758,21 @@ Description: measurement from channel Y. Units after application of scale and offset are milliamps. +What: /sys/bus/iio/devices/iio:deviceX/in_rot_quaternionaxis_raw +KernelVersion: 7.1 +Contact: linux-iio@vger.kernel.org +Description: + Raw value of {x, y, z} components of the quaternion vector. These + components represent the axis about which a rotation occurs, and are + subject to the following constraints: + + - the quaternion vector is normalized, i.e. w^2 + x^2 + y^2 + z^2 = 1 + - the rotation angle is within the [-pi, pi] range, i.e. the w + component (which represents the amount of rotation) is non-negative + + These constraints allow the w value to be calculated from the other + components: w = sqrt(1 - (x^2 + y^2 + z^2)). + What: /sys/.../iio:deviceX/in_energy_en What: /sys/.../iio:deviceX/in_distance_en What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en @@ -1959,6 +1980,23 @@ Description: Raw (unscaled no offset etc.) resistance reading. Units after application of scale and offset are ohms. +What: /sys/bus/iio/devices/iio:deviceX/in_coverageY_raw +KernelVersion: 7.2 +Contact: linux-iio@vger.kernel.org +Description: + Raw (unscaled no offset etc.) coverage reading. Used for sensors + that report fractional coverage as a percentage, such as leak + detectors where the value represents what portion of the sensing + element is wetted. Units after application of scale and offset are + percent. + +What: /sys/bus/iio/devices/iio:deviceX/in_coverageY_scale +KernelVersion: 7.2 +Contact: linux-iio@vger.kernel.org +Description: + Scale to be applied to in_coverageY_raw to obtain coverage + in percent. + What: /sys/bus/iio/devices/iio:deviceX/heater_enable KernelVersion: 4.1.0 Contact: linux-iio@vger.kernel.org diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt index 440633642fea..f544399675fa 100644 --- a/Documentation/admin-guide/devices.txt +++ b/Documentation/admin-guide/devices.txt @@ -291,7 +291,6 @@ 154 = /dev/pmu Macintosh PowerBook power manager 155 = 156 = /dev/lcd Front panel LCD display - 157 = /dev/ac Applicom Intl Profibus card 158 = /dev/nwbutton Netwinder external button 159 = /dev/nwdebug Netwinder debug interface 160 = /dev/nwflash Netwinder flash memory diff --git a/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt b/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt deleted file mode 100644 index 52a294cf2730..000000000000 --- a/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt +++ /dev/null @@ -1,12 +0,0 @@ -Altera Arria10 Partial Reconfiguration IP - -Required properties: -- compatible : should contain "altr,a10-pr-ip" -- reg : base address and size for memory mapped io. - -Example: - - fpga_mgr: fpga-mgr@ff20c000 { - compatible = "altr,a10-pr-ip"; - reg = <0xff20c000 0x10>; - }; diff --git a/Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt deleted file mode 100644 index d52f3340414d..000000000000 --- a/Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt +++ /dev/null @@ -1,17 +0,0 @@ -Altera SOCFPGA FPGA Manager - -Required properties: -- compatible : should contain "altr,socfpga-fpga-mgr" -- reg : base address and size for memory mapped io. - - The first index is for FPGA manager register access. - - The second index is for writing FPGA configuration data. -- interrupts : interrupt for the FPGA Manager device. - -Example: - - hps_0_fpgamgr: fpgamgr@ff706000 { - compatible = "altr,socfpga-fpga-mgr"; - reg = <0xFF706000 0x1000 - 0xFFB90000 0x1000>; - interrupts = <0 175 4>; - }; diff --git a/Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml b/Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml new file mode 100644 index 000000000000..1f4df40308bd --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fpga/altr,a10-pr-ip.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Altera Arria10 Partial Reconfiguration IP + +maintainers: + - Matthew Gerlach + +description: + The Altera Arria 10 Partial Reconfiguration IP core allows the host + processor to perform partial reconfiguration of the FPGA fabric. + +properties: + compatible: + const: altr,a10-pr-ip + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + fpga-mgr@ff20c000 { + compatible = "altr,a10-pr-ip"; + reg = <0xff20c000 0x10>; + }; diff --git a/Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml b/Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml new file mode 100644 index 000000000000..9bcc1200d61d --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fpga/altr,socfpga-fpga-mgr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Altera SOCFPGA FPGA Manager + +maintainers: + - Steffen Trumtrar + +properties: + compatible: + const: altr,socfpga-fpga-mgr + + reg: + items: + - description: FPGA manager register access + - description: Writing FPGA configuration data + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + fpgamgr@ff706000 { + compatible = "altr,socfpga-fpga-mgr"; + reg = <0xff706000 0x1000>, + <0xffb90000 0x1000>; + interrupts = <0 175 4>; + }; diff --git a/Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml b/Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml new file mode 100644 index 000000000000..7c7444ff9c3a --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fpga/efinix,trion-config.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Efinix SPI FPGA Manager + +maintainers: + - Ian Dannapel + +description: | + Efinix FPGAs (Trion, Topaz, and Titanium families) support loading bitstreams + through "SPI Passive Mode". + Additional pin hogs for bus width configuration should be set + elsewhere, if necessary. + + References: + - https://www.efinixinc.com/docs/an006-configuring-trion-fpgas-v6.3.pdf + - https://www.efinixinc.com/docs/an033-configuring-titanium-fpgas-v2.8.pdf + - https://www.efinixinc.com/docs/an061-configuring-topaz-fpgas-v1.1.pdf + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + oneOf: + - items: + - enum: + - efinix,titanium-config + - efinix,topaz-config + - const: efinix,trion-config + - const: efinix,trion-config + + spi-cpha: true + + spi-cpol: true + + spi-max-frequency: + maximum: 25000000 + + reg: + maxItems: 1 + + reset-gpios: + description: + reset and re-configuration trigger pin (low active) + maxItems: 1 + + cdone-gpios: + description: + optional configuration done status pin (high active) + maxItems: 1 + +required: + - compatible + - reg + - reset-gpios + - spi-cpha + - spi-cpol + +unevaluatedProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + fpga-mgr@0 { + compatible = "efinix,trion-config"; + reg = <0>; + spi-max-frequency = <25000000>; + spi-cpha; + spi-cpol; + reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>; + cdone-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + }; + }; + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + fpga-mgr@0 { + compatible = "efinix,titanium-config", "efinix,trion-config"; + reg = <0>; + spi-max-frequency = <25000000>; + spi-cpha; + spi-cpol; + reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>; + cdone-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml b/Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml new file mode 100644 index 000000000000..c93e3a1a135b --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fpga/technologic,ts7300-fpga.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Technologic Systems TS-7300 FPGA Manager + +maintainers: + - Florian Fainelli + +description: + FPGA manager for the Altera Cyclone II FPGA on Technologic Systems + TS-7300 board. The FPGA is programmed via the memory-mapped interface + implemented in the CPLD. + +properties: + compatible: + const: technologic,ts7300-fpga + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + fpga-mgr@13c00000 { + compatible = "technologic,ts7300-fpga"; + reg = <0x13c00000 0x2>; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml index 79df2696ef24..4a3f7d3e05c3 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml @@ -18,7 +18,11 @@ description: | service a wide variety of precision, wide bandwidth data acquisition applications. + The AD4880 is a dual-channel variant with two independent ADC channels, + each with its own SPI configuration interface. + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4080.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4880.pdf $ref: /schemas/spi/spi-peripheral-props.yaml# @@ -34,9 +38,16 @@ properties: - adi,ad4086 - adi,ad4087 - adi,ad4088 + - adi,ad4880 + - adi,ad4884 reg: - maxItems: 1 + minItems: 1 + maxItems: 2 + description: + SPI chip select(s). For single-channel devices, one chip select. + For multi-channel devices like AD4880, two chip selects are required + as each channel has its own SPI configuration interface. spi-max-frequency: description: Configuration of the SPI bus. @@ -60,7 +71,10 @@ properties: vrefin-supply: true io-backends: - maxItems: 1 + minItems: 1 + items: + - description: Backend for channel A (primary) + - description: Backend for channel B (secondary) adi,lvds-cnv-enable: description: Enable the LVDS signal type on the CNV pin. Default is CMOS. @@ -81,6 +95,27 @@ required: - vdd33-supply - vrefin-supply +allOf: + - if: + properties: + compatible: + contains: + enum: + - adi,ad4880 + - adi,ad4884 + then: + properties: + reg: + minItems: 2 + io-backends: + minItems: 2 + else: + properties: + reg: + maxItems: 1 + io-backends: + maxItems: 1 + additionalProperties: false examples: @@ -101,4 +136,21 @@ examples: io-backends = <&iio_backend>; }; }; + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad4880"; + reg = <0>, <1>; + spi-max-frequency = <10000000>; + vdd33-supply = <&vdd33>; + vddldo-supply = <&vddldo>; + vrefin-supply = <&vrefin>; + clocks = <&cnv>; + clock-names = "cnv"; + io-backends = <&iio_backend_cha>, <&iio_backend_chb>; + }; + }; ... diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml index d00690a8d3fb..cc38617bb829 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml @@ -5,19 +5,30 @@ $id: http://devicetree.org/schemas/iio/adc/adi,ad4130.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Analog Devices AD4130 ADC device driver +title: Analog Devices AD4130 family ADCs maintainers: - Cosmin Tanislav description: | - Bindings for the Analog Devices AD4130 ADC. Datasheet can be found here: + Bindings for the Analog Devices AD4130 family ADCs. + Datasheets can be found here: + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4129-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4129-8.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4130-4.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD4130-8.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4131-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4131-8.pdf properties: compatible: enum: + - adi,ad4129-4 + - adi,ad4129-8 + - adi,ad4130-4 - adi,ad4130 + - adi,ad4131-4 + - adi,ad4131-8 reg: maxItems: 1 @@ -32,6 +43,10 @@ properties: interrupts: maxItems: 1 + description: | + Data Ready / FIFO interrupt. For devices with FIFO support, the + interrupt polarity specified here is inverted when the device enters + FIFO mode, and normal for data ready. interrupt-names: description: | diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4691.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4691.yaml new file mode 100644 index 000000000000..af28a0c1cfa9 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4691.yaml @@ -0,0 +1,180 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad4691.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD4691 Family Multichannel SAR ADCs + +maintainers: + - Radu Sabau + +description: | + The AD4691 family are high-speed, low-power, multichannel successive + approximation register (SAR) analog-to-digital converters (ADCs) with + an SPI-compatible serial interface. The ADC supports CNV Burst Mode, + where an external PWM drives the CNV pin, and Manual Mode, where CNV + is directly tied to the SPI chip-select. + + Datasheets: + * https://www.analog.com/en/products/ad4691.html + * https://www.analog.com/en/products/ad4692.html + * https://www.analog.com/en/products/ad4693.html + * https://www.analog.com/en/products/ad4694.html + +$ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - adi,ad4691 + - adi,ad4692 + - adi,ad4693 + - adi,ad4694 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 40000000 + + spi-cpol: true + spi-cpha: true + + avdd-supply: + description: Analog power supply (4.5V to 5.5V). + + vdd-supply: + description: + External 1.8V digital core supply. When present, the internal LDO is + disabled (LDO_EN = 0). Mutually exclusive with ldo-in-supply. + + ldo-in-supply: + description: + LDO input supply (2.4V to 5.5V). When present and vdd-supply is absent, + the internal LDO generates 1.8V VDD from this input (LDO_EN = 1). + Mutually exclusive with vdd-supply. + + vio-supply: + description: I/O voltage supply (1.71V to 1.89V or VDD). + + ref-supply: + description: External reference voltage supply (2.4V to 5.25V). + + refin-supply: + description: Internal reference buffer input supply. + + reset-gpios: + description: + GPIO line controlling the hardware reset pin (active-low). + maxItems: 1 + + pwms: + description: + PWM connected to the CNV pin. When present, selects CNV Burst Mode where + the PWM drives the conversion rate. When absent, Manual Mode is used + (CNV tied to SPI CS). + maxItems: 1 + + interrupts: + description: + Interrupt lines connected to the ADC GP pins. Each GP pin can be + physically wired to an interrupt-capable input on the SoC. + maxItems: 4 + + interrupt-names: + description: Names of the interrupt lines, matching the GP pin names. + minItems: 1 + maxItems: 4 + items: + enum: + - gp0 + - gp1 + - gp2 + - gp3 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + '#trigger-source-cells': + description: + This node can act as a trigger source. The single cell in a consumer + reference specifies the GP pin number (0-3) used as the trigger output. + const: 1 + +required: + - compatible + - reg + - avdd-supply + - vio-supply + +allOf: + # vdd-supply and ldo-in-supply are mutually exclusive, one is required: + # either an external 1.8V VDD is provided or the internal LDO is fed from + # ldo-in-supply to generate VDD. + - oneOf: + - required: + - vdd-supply + - required: + - ldo-in-supply + # ref-supply and refin-supply are mutually exclusive, one is required + - oneOf: + - required: + - ref-supply + - required: + - refin-supply + +unevaluatedProperties: false + +examples: + - | + #include + /* AD4692 in CNV Burst Mode with SPI offload */ + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad4692"; + reg = <0>; + spi-cpol; + spi-cpha; + spi-max-frequency = <40000000>; + + avdd-supply = <&avdd_supply>; + ldo-in-supply = <&avdd_supply>; + vio-supply = <&vio_supply>; + ref-supply = <&ref_5v>; + + reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + + pwms = <&pwm_gen 0 0>; + + #trigger-source-cells = <1>; + }; + }; + + - | + #include + /* AD4692 in Manual Mode (CNV tied to SPI CS) */ + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad4692"; + reg = <0>; + spi-cpol; + spi-cpha; + spi-max-frequency = <31250000>; + + avdd-supply = <&avdd_supply>; + ldo-in-supply = <&avdd_supply>; + vio-supply = <&vio_supply>; + refin-supply = <&refin_supply>; + + reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/allwinner,sun20i-d1-gpadc.yaml b/Documentation/devicetree/bindings/iio/adc/allwinner,sun20i-d1-gpadc.yaml index da605a051b94..6467800d30e2 100644 --- a/Documentation/devicetree/bindings/iio/adc/allwinner,sun20i-d1-gpadc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/allwinner,sun20i-d1-gpadc.yaml @@ -14,6 +14,7 @@ properties: oneOf: - enum: - allwinner,sun20i-d1-gpadc + - allwinner,sun55i-a523-gpadc - items: - enum: - allwinner,sun50i-h616-gpadc @@ -29,7 +30,12 @@ properties: const: 0 clocks: - maxItems: 1 + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + maxItems: 2 interrupts: maxItems: 1 @@ -40,6 +46,30 @@ properties: resets: maxItems: 1 +allOf: + - if: + properties: + compatible: + enum: + - allwinner,sun55i-a523-gpadc + then: + properties: + clocks: + items: + - description: Bus clock + - description: Module clock + clock-names: + items: + - const: bus + - const: mod + required: + - clock-names + else: + properties: + clocks: + maxItems: 1 + clock-names: false + patternProperties: "^channel@[0-9a-f]+$": $ref: adc.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml index 9c57eb13f892..1ea60dff98d5 100644 --- a/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml @@ -10,14 +10,9 @@ maintainers: - Andreas Klinger description: | - Bit-banging driver using two GPIOs: - - sck-gpio gives a clock to the sensor with 24 cycles for data retrieval - and up to 3 cycles for selection of the input channel and gain for the - next measurement - - dout-gpio is the sensor data the sensor responds to the clock - - Specifications about the driver can be found at: - http://www.aviaic.com/ENProducts.aspx + The HX711 is a 24-bit ADC with selectable gain (32/64/128) and two + differential input channels. Channel A supports gain 64 and 128; + channel B supports gain 32. properties: compatible: @@ -26,23 +21,23 @@ properties: sck-gpios: description: - Definition of the GPIO for the clock (output). In the datasheet it is - named PD_SCK + GPIO for the clock output (PD_SCK in the datasheet). maxItems: 1 dout-gpios: description: - Definition of the GPIO for the data-out sent by the sensor in - response to the clock (input). - See Documentation/devicetree/bindings/gpio/gpio.txt for information - on how to specify a consumer gpio. + GPIO for the data output from the sensor (DOUT in the datasheet). maxItems: 1 avdd-supply: description: - Definition of the regulator used as analog supply + Analog supply voltage (AVDD). clock-frequency: + description: + Controls the SCK bit-bang timing. The value is used to derive the + delay between SCK edges; keep the SCK high time below 60 us to + avoid triggering chip power-down mode. minimum: 20000 maximum: 2500000 default: 400000 diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml index c978c3a3e31a..63aac8de22ad 100644 --- a/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml @@ -78,6 +78,10 @@ patternProperties: reg: maxItems: 1 + label: + description: | + Unique name to identify which channel this is. + qcom,decimation: $ref: /schemas/types.yaml#/definitions/uint32 description: | @@ -130,36 +134,47 @@ examples: vcoin: adc-channel@0 { reg = <0x00 0x00>; + label = "vcoin"; }; vbat: adc-channel@1 { reg = <0x00 0x01>; + label = "vbat"; }; dcin: adc-channel@2 { reg = <0x00 0x02>; + label = "dcin"; }; ichg: adc-channel@3 { reg = <0x00 0x03>; + label = "ichg"; }; vph_pwr: adc-channel@4 { reg = <0x00 0x04>; + label = "vph_pwr"; }; usb_vbus: adc-channel@a { reg = <0x00 0x0a>; + label = "usb_vbus"; }; die_temp: adc-channel@b { reg = <0x00 0x0b>; + label = "die_temp"; }; ref_625mv: adc-channel@c { reg = <0x00 0x0c>; + label = "ref_625mv"; }; ref_1250mv: adc-channel@d { reg = <0x00 0x0d>; + label = "ref_1250mv"; }; ref_325mv: adc-channel@e { reg = <0x00 0x0e>; + label = "ref_325mv"; }; ref_muxoff: adc-channel@f { reg = <0x00 0x0f>; + label = "ref_muxoff"; }; }; }; diff --git a/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml b/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml index 40d87346ff4c..a5b0debe85b1 100644 --- a/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml +++ b/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Sensirion SCD30 carbon dioxide sensor maintainers: - - Tomasz Duszynski + - Maxwell Doose description: | Air quality sensor capable of measuring co2 concentration, temperature diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5706r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5706r.yaml new file mode 100644 index 000000000000..19cc744a9f0f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5706r.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/dac/adi,ad5706r.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD5706R 4-Channel Current Output DAC + +maintainers: + - Alexis Czezar Torreno + +description: | + The AD5706R is a 4-channel, 16-bit resolution, current output + digital-to-analog converter (DAC) with programmable output current + ranges (50mA, 150mA, 200mA, 300mA), an integrated 2.5V voltage + reference, and load DAC, A/B toggle, and dither functions. + + Datasheet: + https://www.analog.com/en/products/ad5706r.html + +properties: + compatible: + enum: + - adi,ad5706r + + reg: + maxItems: 1 + + avdd-supply: + description: Analog power supply (2.9V to 3.6V). + + iovdd-supply: + description: Logic power supply (1.14V to 1.89V). + + pvdd0-supply: + description: Power supply for IDAC0 channel (1.65V to AVDD). + + pvdd1-supply: + description: Power supply for IDAC1 channel (1.65V to AVDD). + + pvdd2-supply: + description: Power supply for IDAC2 channel (1.65V to AVDD). + + pvdd3-supply: + description: Power supply for IDAC3 channel (1.65V to AVDD). + + vref-supply: + description: + Optional external 2.5V voltage reference. If not provided, the + internal 2.5V reference is used. + + pwms: + maxItems: 1 + description: + Optional PWM connected to the LDAC/TGP/DCK pin for hardware + triggered DAC updates, toggle, or dither clock generation. + + reset-gpios: + maxItems: 1 + description: + GPIO connected to the active low RESET pin. If not provided, + software reset is used. + + enable-gpios: + maxItems: 1 + description: + GPIO connected to the active low OUT_EN pin. Controls whether + the current outputs are enabled or in high-Z/ground state. + +required: + - compatible + - reg + - avdd-supply + - iovdd-supply + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + dac@0 { + compatible = "adi,ad5706r"; + reg = <0>; + avdd-supply = <&avdd>; + iovdd-supply = <&iovdd>; + pvdd0-supply = <&pvdd>; + pvdd1-supply = <&pvdd>; + pvdd2-supply = <&pvdd>; + pvdd3-supply = <&pvdd>; + vref-supply = <&vref>; + spi-max-frequency = <50000000>; + pwms = <&pwm0 0 1000000 0>; + reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml index d2466aa6bda2..d131f136bd15 100644 --- a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml +++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml @@ -161,8 +161,8 @@ patternProperties: properties: reg: description: The channel number. - minItems: 1 - maxItems: 8 + minimum: 0 + maximum: 7 label: description: Unique name to identify which channel this is. @@ -280,23 +280,23 @@ examples: #address-cells = <1>; #size-cells = <0>; - dac@0 { - compatible = "microchip,mcp47feb02"; - reg = <0>; - vdd-supply = <&vdac_vdd>; - vref-supply = <&vref_reg>; + dac@60 { + compatible = "microchip,mcp47feb02"; + reg = <0x60>; + vdd-supply = <&vdac_vdd>; + vref-supply = <&vref_reg>; - #address-cells = <1>; - #size-cells = <0>; - channel@0 { - reg = <0>; - label = "Adjustable_voltage_ch0"; - }; + #address-cells = <1>; + #size-cells = <0>; + channel@0 { + reg = <0>; + label = "Adjustable_voltage_ch0"; + }; - channel@1 { - reg = <0x1>; - label = "Adjustable_voltage_ch1"; - }; - }; + channel@1 { + reg = <0x1>; + label = "Adjustable_voltage_ch1"; + }; + }; }; ... diff --git a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml index fcbd4b430e48..8e094651381c 100644 --- a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml +++ b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml @@ -26,6 +26,9 @@ properties: vdd-supply: true vddio-supply: true + mount-matrix: + description: an optional 3x3 mounting rotation matrix. + spi-max-frequency: maximum: 10000000 @@ -56,6 +59,9 @@ examples: reg = <0x69>; interrupt-parent = <&gpio6>; interrupts = <18 IRQ_TYPE_EDGE_RISING>; + mount-matrix = "0", "1", "0", + "1", "0", "0", + "0", "0", "1"; }; }; ... diff --git a/Documentation/devicetree/bindings/iio/light/brcm,apds9999.yaml b/Documentation/devicetree/bindings/iio/light/brcm,apds9999.yaml new file mode 100644 index 000000000000..9f5b3b294c2c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/brcm,apds9999.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/brcm,apds9999.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# +title: Broadcom APDS-9999 Digital Proximity and RGB Sensor + +maintainers: + - Jose A. Perez de Azpillaga + +description: | + Broadcom APDS-9999 is a digital proximity and RGB sensor with + ambient light sensing (ALS) capability. The device uses individual + R, G, B, and IR channels plus a Vertical Cavity Surface Emitting + Laser (VCSEL) for proximity detection. + + Datasheet: https://docs.broadcom.com/docs/APDS-9999-DS + +properties: + compatible: + enum: + - brcm,apds9999 + + reg: + maxItems: 1 + + vdd-supply: true + + vcsel-supply: + description: VCSEL power supply (VVCSEL pin) + + interrupts: + maxItems: 1 + +additionalProperties: false + +required: + - compatible + - reg + - vdd-supply + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + light-sensor@52 { + compatible = "brcm,apds9999"; + reg = <0x52>; + vdd-supply = <&vdd_reg>; + vcsel-supply = <&vcsel_reg>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/light/tsl2772.yaml b/Documentation/devicetree/bindings/iio/light/tsl2772.yaml index d81229857944..9921ccaa64a0 100644 --- a/Documentation/devicetree/bindings/iio/light/tsl2772.yaml +++ b/Documentation/devicetree/bindings/iio/light/tsl2772.yaml @@ -26,6 +26,8 @@ properties: - amstaos,tmd2672 - amstaos,tsl2772 - amstaos,tmd2772 + - avago,apds9900 + - avago,apds9901 - avago,apds9930 reg: diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml index 4ea69f1fdd63..0041e1db6838 100644 --- a/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml +++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/iio/light/vishay,veml6030.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: VEML3235, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS) +title: VEML3235, VEML3328, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS) maintainers: - Rishi Gupta @@ -21,6 +21,7 @@ description: | Specifications about the sensors can be found at: https://www.vishay.com/docs/80131/veml3235.pdf + https://www.vishay.com/docs/84968/veml3328.pdf https://www.vishay.com/docs/84366/veml6030.pdf https://www.vishay.com/docs/84889/veml6035.pdf https://www.vishay.com/docs/84286/veml7700.pdf @@ -29,6 +30,7 @@ properties: compatible: enum: - vishay,veml3235 + - vishay,veml3328 - vishay,veml6030 - vishay,veml6035 - vishay,veml7700 @@ -79,6 +81,7 @@ allOf: compatible: enum: - vishay,veml3235 + - vishay,veml3328 - vishay,veml7700 then: properties: diff --git a/Documentation/devicetree/bindings/iio/magnetometer/memsic,mmc5983.yaml b/Documentation/devicetree/bindings/iio/magnetometer/memsic,mmc5983.yaml new file mode 100644 index 000000000000..4a4df6bb70fe --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/memsic,mmc5983.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/magnetometer/memsic,mmc5983.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MEMSIC MMC5983MA 3-axis magnetic sensor + +maintainers: + - Vladislav Kulikov + +properties: + compatible: + const: memsic,mmc5983 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vdd-supply: + description: Regulator that provides power to the sensor + + vddio-supply: + description: Regulator that provides power to the digital interface and INT pin + +required: + - compatible + - reg + - vdd-supply + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + magnetometer@30 { + compatible = "memsic,mmc5983"; + reg = <0x30>; + vdd-supply = <&vdd_3v3_reg>; + vddio-supply = <&vdd_3v3_reg>; + }; + }; + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + magnetometer@0 { + compatible = "memsic,mmc5983"; + reg = <0>; + spi-max-frequency = <10000000>; + vdd-supply = <&vdd_3v3_reg>; + vddio-supply = <&vdd_3v3_reg>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml index a22725f7619b..13e5f29f0588 100644 --- a/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml +++ b/Documentation/devicetree/bindings/iio/temperature/adi,ltc2983.yaml @@ -4,14 +4,18 @@ $id: http://devicetree.org/schemas/iio/temperature/adi,ltc2983.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Analog Devices LTC2983, LTC2986, LTM2985 Multi-sensor Temperature system +title: Analog Devices LTC2983 and similar Multi-sensor Temperature systems maintainers: - Nuno Sá description: | - Analog Devices LTC2983, LTC2984, LTC2986, LTM2985 Multi-Sensor Digital - Temperature Measurement Systems + Analog Devices Multi-Sensor Digital Temperature Measurement Systems: + - ADT7604 + - LTC2983 + - LTC2984 + - LTC2986 + - LTM2985 https://www.analog.com/media/en/technical-documentation/data-sheets/2983fc.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/2984fb.pdf @@ -43,6 +47,7 @@ properties: compatible: oneOf: - enum: + - adi,adt7604 - adi,ltc2983 - adi,ltc2986 - adi,ltm2985 @@ -436,6 +441,121 @@ patternProperties: required: - adi,custom-temp + '^copper-trace@': + $ref: '#/$defs/sensor-node' + unevaluatedProperties: false + description: | + Copper trace resistance sensor (some parts only). Two variants exist: + sub-ohm (< 1 ohm, no custom table allowed) and standard (> 1 ohm, + required custom table). + + properties: + reg: + minimum: 2 + maximum: 20 + + adi,sensor-type: + description: Sensor type for copper trace sensors. + $ref: /schemas/types.yaml#/definitions/uint32 + const: 32 + + adi,rsense-handle: + description: Associated sense resistor sensor. + $ref: /schemas/types.yaml#/definitions/phandle + + adi,copper-trace-sub-ohm: + description: + Select the sub-ohm (< 1 ohm) copper trace variant. Custom table + and excitation current are not allowed in this mode. + type: boolean + + adi,excitation-current-microamp: + description: + Excitation current applied to the copper trace. Not used in + sub-ohm mode. The datasheet recommends 1mA for copper trace + sensors due to their typically small resistance. + enum: [5, 10, 25, 50, 100, 250, 500, 1000] + default: 1000 + + adi,custom-copper-trace: + description: + Resistance-to-temperature table for copper trace sensors with + resistance > 1 ohm. Required when adi,copper-trace-sub-ohm is not + set. See Page 36 of the datasheet. + $ref: /schemas/types.yaml#/definitions/uint64-matrix + minItems: 3 + maxItems: 64 + items: + items: + - description: Resistance point in uOhms. + - description: Temperature point in uK. + + required: + - adi,rsense-handle + + allOf: + - if: + required: + - adi,copper-trace-sub-ohm + then: + properties: + adi,custom-copper-trace: false + adi,excitation-current-microamp: false + - if: + not: + required: + - adi,copper-trace-sub-ohm + then: + required: + - adi,custom-copper-trace + + '^leak-detector@': + $ref: '#/$defs/sensor-node' + unevaluatedProperties: false + description: | + Leak detector sensor (some parts only). Outputs resistance in ohms and + a coverage percentage via IIO_COVERAGE (raw/1024 = coverage %). + + properties: + reg: + minimum: 2 + maximum: 20 + + adi,sensor-type: + description: Sensor type for leak detector sensors. + $ref: /schemas/types.yaml#/definitions/uint32 + const: 33 + + adi,rsense-handle: + description: Associated sense resistor sensor. + $ref: /schemas/types.yaml#/definitions/phandle + + adi,excitation-current-nanoamp: + description: + Excitation current applied to the leak detector. The correct value + depends on the electrical characteristics of the liquid being sensed. + For example, 10000 (10µA) is recommended for PG25 (see datasheet + Table 39). + enum: [250, 500, 1000, 5000, 10000, 25000, 50000, 100000, 250000, + 500000, 1000000] + + adi,custom-leak-detector: + description: | + Lookup table mapping resistance to coverage percentage. Entries must + be in ascending resistance order. + $ref: /schemas/types.yaml#/definitions/uint64-matrix + minItems: 3 + maxItems: 64 + items: + items: + - description: Resistance point in uOhms. + - description: Coverage data percentage (0 to 100). + + required: + - adi,rsense-handle + - adi,excitation-current-nanoamp + - adi,custom-leak-detector + '^rsense@': $ref: '#/$defs/sensor-node' unevaluatedProperties: false @@ -477,6 +597,32 @@ allOf: patternProperties: '^temp@': false + - if: + properties: + compatible: + contains: + const: adi,adt7604 + then: + patternProperties: + '^thermocouple@': false + '^diode@': false + '^adc@': false + '^temp@': false + '^rtd@': + properties: + adi,sensor-type: + not: + const: 18 + '^thermistor@': + properties: + adi,sensor-type: + not: + const: 27 + else: + patternProperties: + '^copper-trace@': false + '^leak-detector@': false + examples: - | #include @@ -556,4 +702,69 @@ examples: }; }; }; + + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + temperature-sensor@0 { + compatible = "adi,adt7604"; + reg = <0>; + interrupt-parent = <&gpio>; + interrupts = <25 IRQ_TYPE_EDGE_RISING>; + + #address-cells = <1>; + #size-cells = <0>; + vdd-supply = <&supply>; + + trace_rsense: rsense@2 { + reg = <2>; + adi,sensor-type = <29>; + adi,rsense-val-milli-ohms = <100000>; // 100 ohm + }; + + copper-trace@4 { + reg = <4>; + adi,sensor-type = <32>; + adi,rsense-handle = <&trace_rsense>; + adi,copper-trace-sub-ohm; + }; + + r_sense: rsense@12 { + reg = <12>; + adi,sensor-type = <29>; + adi,rsense-val-milli-ohms = <1000000>; // 1 kohm + }; + + leak-detector@14 { + reg = <14>; + adi,sensor-type = <33>; + adi,rsense-handle = <&r_sense>; + adi,excitation-current-nanoamp = <10000>; + adi,custom-leak-detector = + /bits/ 64 < 0 100>, + /bits/ 64 < 202020000 99>, + /bits/ 64 < 285710000 70>, + /bits/ 64 < 333330000 60>, + /bits/ 64 < 400000000 50>, + /bits/ 64 < 500000000 40>, + /bits/ 64 < 666670000 30>, + /bits/ 64 < 1000000000 20>, + /bits/ 64 < 2000000000 10>, + /bits/ 64 <1000000000000 0>; + }; + + rtd@18 { + reg = <18>; + adi,sensor-type = <12>; // PT100 + adi,rsense-handle = <&r_sense>; + adi,number-of-wires = <2>; + adi,rsense-share; + adi,excitation-current-microamp = <500>; + adi,rtd-curve = <0>; + }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/interconnect/qcom,hawi-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,hawi-rpmh.yaml new file mode 100644 index 000000000000..49a2dca5db62 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,hawi-rpmh.yaml @@ -0,0 +1,131 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,hawi-rpmh.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm RPMh Network-On-Chip Interconnect on Hawi + +maintainers: + - Vivek Aknurwar + +description: | + RPMh interconnect providers support system bandwidth requirements through + RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is + able to communicate with the BCM through the Resource State Coordinator (RSC) + associated with each execution environment. Provider nodes must point to at + least one RPMh device child node pertaining to their RSC and each provider + can map to multiple RPMh resources. + + See also: include/dt-bindings/interconnect/qcom,hawi-rpmh.h + +properties: + compatible: + enum: + - qcom,hawi-aggre1-noc + - qcom,hawi-clk-virt + - qcom,hawi-cnoc-main + - qcom,hawi-gem-noc + - qcom,hawi-llclpi-noc + - qcom,hawi-lpass-ag-noc + - qcom,hawi-lpass-lpiaon-noc + - qcom,hawi-lpass-lpicx-noc + - qcom,hawi-mc-virt + - qcom,hawi-mmss-noc + - qcom,hawi-nsp-noc + - qcom,hawi-pcie-anoc + - qcom,hawi-stdst-cfg + - qcom,hawi-stdst-main + - qcom,hawi-system-noc + + reg: + maxItems: 1 + + clocks: + minItems: 2 + maxItems: 3 + +required: + - compatible + +allOf: + - $ref: qcom,rpmh-common.yaml# + - if: + properties: + compatible: + contains: + enum: + - qcom,hawi-clk-virt + - qcom,hawi-mc-virt + then: + properties: + reg: false + else: + required: + - reg + + - if: + properties: + compatible: + contains: + enum: + - qcom,hawi-pcie-anoc + then: + properties: + clocks: + items: + - description: aggre-NOC PCIe AXI clock + - description: cfg-NOC PCIe a-NOC AHB clock + + - if: + properties: + compatible: + contains: + enum: + - qcom,hawi-aggre1-noc + then: + properties: + clocks: + items: + - description: aggre UFS PHY AXI clock + - description: aggre USB3 PRIM AXI clock + - description: RPMH CC IPA clock + + - if: + properties: + compatible: + contains: + enum: + - qcom,hawi-aggre1-noc + - qcom,hawi-pcie-anoc + then: + required: + - clocks + else: + properties: + clocks: false + +unevaluatedProperties: false + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + clk_virt: interconnect-0 { + compatible = "qcom,hawi-clk-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre_noc: interconnect@f00000 { + compatible = "qcom,hawi-aggre1-noc"; + reg = <0x0 0xf00000 0x0 0x54400>; + #interconnect-cells = <2>; + clocks = <&gcc_aggre_ufs_phy_axi_clk>, + <&gcc_aggre_usb3_prim_axi_clk>, + <&rpmhcc_ipa_clk>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml index ce79521bb1ef..ff64225e8281 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml @@ -26,6 +26,7 @@ properties: - items: - enum: - qcom,glymur-cpu-bwmon + - qcom,hawi-cpu-bwmon - qcom,kaanapali-cpu-bwmon - qcom,qcm2290-cpu-bwmon - qcom,qcs615-cpu-bwmon @@ -45,6 +46,7 @@ properties: - const: qcom,sdm845-bwmon # BWMON v4, unified register space - items: - enum: + - qcom,hawi-llcc-bwmon - qcom,qcs615-llcc-bwmon - qcom,qcs8300-llcc-bwmon - qcom,sa8775p-llcc-bwmon diff --git a/Documentation/devicetree/bindings/interconnect/qcom,nord-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,nord-rpmh.yaml new file mode 100644 index 000000000000..3650d3d5b918 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,nord-rpmh.yaml @@ -0,0 +1,131 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,nord-rpmh.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm RPMh Network-On-Chip Interconnect on Nord + +maintainers: + - Odelu Kukatla + +description: | + RPMh interconnect providers support system bandwidth requirements through + RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is + able to communicate with the BCM through the Resource State Coordinator (RSC) + associated with each execution environment. Provider nodes must point to at + least one RPMh device child node pertaining to their RSC and each provider + can map to multiple RPMh resources. + + See also: include/dt-bindings/interconnect/qcom,nord-rpmh.h + +properties: + compatible: + enum: + - qcom,nord-aggre1-noc + - qcom,nord-aggre1-noc-tile + - qcom,nord-aggre2-noc + - qcom,nord-aggre2-noc-tile + - qcom,nord-clk-virt + - qcom,nord-cnoc-cfg + - qcom,nord-cnoc-main + - qcom,nord-hpass-ag-noc + - qcom,nord-hscnoc + - qcom,nord-mc-virt + - qcom,nord-mmss-noc + - qcom,nord-nsp-data-noc-0 + - qcom,nord-nsp-data-noc-1 + - qcom,nord-nsp-data-noc-2 + - qcom,nord-nsp-data-noc-3 + - qcom,nord-pcie-cfg + - qcom,nord-pcie-data-inbound + - qcom,nord-pcie-data-outbound + - qcom,nord-system-noc + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 4 + +required: + - compatible + +allOf: + - $ref: qcom,rpmh-common.yaml# + - if: + properties: + compatible: + contains: + enum: + - qcom,nord-clk-virt + - qcom,nord-mc-virt + then: + properties: + reg: false + else: + required: + - reg + + - if: + properties: + compatible: + contains: + enum: + - qcom,nord-aggre1-noc-tile + then: + properties: + clocks: + items: + - description: aggre UFS PHY AXI clock + - description: aggre USB2 AXI clock + - description: aggre USB3 PRIM AXI clock + - description: aggre USB3 SEC AXI clock + + - if: + properties: + compatible: + contains: + enum: + - qcom,nord-aggre2-noc + then: + properties: + clocks: + items: + - description: RPMH CC IPA clock + + - if: + properties: + compatible: + contains: + enum: + - qcom,nord-aggre1-noc-tile + - qcom,nord-aggre2-noc + then: + required: + - clocks + else: + properties: + clocks: false + +unevaluatedProperties: false + +examples: + - | + clk_virt: interconnect-clk-virt { + compatible = "qcom,nord-clk-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre1_noc_tile: interconnect@1720000 { + compatible = "qcom,nord-aggre1-noc-tile"; + reg = <0x01720000 0x23400>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + clocks = <&ne_gcc_aggre_noc_ufs_phy_axi_clk>, + <&ne_gcc_aggre_noc_usb2_axi_clk>, + <&ne_gcc_aggre_noc_usb3_prim_axi_clk>, + <&ne_gcc_aggre_noc_usb3_sec_axi_clk>; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml index 8f6bc6399626..51428a2b0ce0 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sdm660.yaml @@ -79,6 +79,19 @@ allOf: - const: aggre2_usb3_axi - const: cfg_noc_usb2_axi + - if: + properties: + compatible: + enum: + - qcom,sdm660-bimc + - qcom,sdm660-cnoc + - qcom,sdm660-gnoc + - qcom,sdm660-snoc + then: + properties: + clocks: false + clock-names: false + examples: - | #include diff --git a/Documentation/devicetree/bindings/interconnect/qcom,shikra.yaml b/Documentation/devicetree/bindings/interconnect/qcom,shikra.yaml new file mode 100644 index 000000000000..a0c26de94ccf --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,shikra.yaml @@ -0,0 +1,134 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,shikra.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Shikra Network-On-Chip interconnect + +maintainers: + - Raviteja Laggyshetty + +description: + The Qualcomm Shikra interconnect providers support adjusting the + bandwidth requirements between the various NoC fabrics. + +properties: + compatible: + enum: + - qcom,shikra-config-noc + - qcom,shikra-mem-noc-core + - qcom,shikra-sys-noc + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 4 + + clock-names: + minItems: 1 + maxItems: 4 + +# Child node's properties +patternProperties: + '^interconnect-[a-z0-9]+$': + type: object + description: + The interconnect providers do not have a separate QoS register space, + but share parent's space. + + $ref: qcom,rpm-common.yaml# + + properties: + compatible: + enum: + - qcom,shikra-clk-virt + - qcom,shikra-mc-virt + - qcom,shikra-mmrt-virt + - qcom,shikra-mmnrt-virt + + required: + - compatible + + unevaluatedProperties: false + +required: + - compatible + - reg + +allOf: + - $ref: qcom,rpm-common.yaml# + - if: + properties: + compatible: + const: qcom,shikra-mem-noc-core + + then: + properties: + clocks: + items: + - description: GPU-NoC AXI clock + + clock-names: + items: + - const: gpu_axi + patternProperties: + '^interconnect-[a-z0-9]+$': false + + - if: + properties: + compatible: + const: qcom,shikra-sys-noc + + then: + properties: + clocks: + items: + - description: EMAC0-NoC AXI clock. + - description: EMAC1-NoC AXI clock. + - description: USB2-NoC AXI clock. + - description: USB3-NoC AXI clock. + + clock-names: + items: + - const: emac0_axi + - const: emac1_axi + - const: usb2_axi + - const: usb3_axi + + - if: + properties: + compatible: + const: qcom,shikra-config-noc + + then: + properties: + clocks: false + clock-names: false + patternProperties: + '^interconnect-[a-z0-9]+$': false + +unevaluatedProperties: false + +examples: + - | + interconnect@1880000 { + compatible = "qcom,shikra-sys-noc"; + reg = <0x01880000 0x6a080>; + #interconnect-cells = <2>; + clocks = <&gcc_emac0_axi_sys_noc_clk>, + <&gcc_emac1_axi_sys_noc_clk>, + <&gcc_sys_noc_usb2_prim_axi_clk>, + <&gcc_sys_noc_usb3_prim_axi_clk>; + clock-names = "emac0_axi", + "emac1_axi", + "usb2_axi", + "usb3_axi"; + + interconnect-clk { + compatible = "qcom,shikra-clk-virt"; + #interconnect-cells = <2>; + }; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sm6115.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sm6115.yaml index 14b1a0b08e73..cdae0acf3a1d 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sm6115.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sm6115.yaml @@ -62,23 +62,33 @@ allOf: - if: properties: compatible: - const: qcom,sm6115-cnoc + const: qcom,sm6115-bimc + then: + properties: + clocks: false + clock-names: false + patternProperties: + '^interconnect-[a-z0-9]+$': false + - if: + properties: + compatible: + const: qcom,sm6115-cnoc then: properties: clocks: items: - description: USB-NoC AXI clock - clock-names: items: - const: usb_axi + patternProperties: + '^interconnect-[a-z0-9]+$': false - if: properties: compatible: const: qcom,sm6115-snoc - then: properties: clocks: @@ -87,7 +97,6 @@ allOf: - description: UFS-NoC AXI clock. - description: USB-NoC AXI clock. - description: IPA clock. - clock-names: items: - const: cpu_axi @@ -95,20 +104,6 @@ allOf: - const: usb_axi - const: ipa - - if: - properties: - compatible: - enum: - - qcom,sm6115-bimc - - qcom,sm6115-clk-virt - - qcom,sm6115-mmrt-virt - - qcom,sm6115-mmnrt-virt - - then: - properties: - clocks: false - clock-names: false - unevaluatedProperties: false examples: @@ -149,4 +144,6 @@ examples: compatible = "qcom,sm6115-cnoc"; reg = <0x01900000 0x8200>; #interconnect-cells = <1>; + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>; + clock-names = "usb_axi"; }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6b9fb6a6bf0b..396044f368e7 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -491,6 +491,8 @@ patternProperties: description: Emtop Embedded Solutions "^eeti,.*": description: eGalax_eMPIA Technology Inc + "^efinix,.*": + description: Efinix, Inc. "^egnite,.*": description: egnite GmbH "^einfochips,.*": diff --git a/Documentation/driver-api/iio/buffers.rst b/Documentation/driver-api/iio/buffers.rst index 63f364e862d1..8779022e3da5 100644 --- a/Documentation/driver-api/iio/buffers.rst +++ b/Documentation/driver-api/iio/buffers.rst @@ -37,9 +37,10 @@ directory contains attributes of the following form: * :file:`index`, the scan_index of the channel. * :file:`type`, description of the scan element data storage within the buffer and hence the form in which it is read from user space. - Format is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift] . + Format is [be|le]:[f|s|u]bits/storagebits[Xrepeat][>>shift] . * *be* or *le*, specifies big or little endian. + * *f*, specifies if floating-point. * *s* or *u*, specifies if signed (2's complement) or unsigned. * *bits*, is the number of valid data bits. * *storagebits*, is the number of bits (after padding) that it occupies in the @@ -78,7 +79,7 @@ fields in iio_chan_spec definition:: /* other members */ int scan_index struct { - char sign; + char format; u8 realbits; u8 storagebits; u8 shift; @@ -98,7 +99,7 @@ following channel definition:: /* other stuff here */ .scan_index = 0, .scan_type = { - .sign = 's', + .format = IIO_SCAN_FORMAT_SIGNED_INT, .realbits = 12, .storagebits = 16, .shift = 4, diff --git a/Documentation/driver-api/iio/triggered-buffers.rst b/Documentation/driver-api/iio/triggered-buffers.rst index 417555dbbdf4..23762b06fdc6 100644 --- a/Documentation/driver-api/iio/triggered-buffers.rst +++ b/Documentation/driver-api/iio/triggered-buffers.rst @@ -29,21 +29,21 @@ A typical triggered buffer setup looks like this:: irqreturn_t sensor_trigger_handler(int irq, void *p) { - u16 buf[8]; + IIO_DECLARE_BUFFER_WITH_TS(u16, buf, 3) = { }; int i = 0; /* read data for each active channel */ - for_each_set_bit(bit, active_scan_mask, masklength) - buf[i++] = sensor_get_data(bit) + iio_for_each_active_channel(indio_dev, bit) + buf[i++] = sensor_get_data(bit); - iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp); + iio_push_to_buffers_with_ts(indio_dev, buf, sizeof(buf), timestamp); iio_trigger_notify_done(trigger); return IRQ_HANDLED; } /* setup triggered buffer, usually in probe function */ - iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc, + iio_triggered_buffer_setup(indio_dev, sensor_iio_pollfunc, sensor_trigger_handler, sensor_buffer_setup_ops); diff --git a/Documentation/iio/ad4691.rst b/Documentation/iio/ad4691.rst new file mode 100644 index 000000000000..e45733341a4b --- /dev/null +++ b/Documentation/iio/ad4691.rst @@ -0,0 +1,227 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +============= +AD4691 driver +============= + +ADC driver for Analog Devices Inc. AD4691 family of multichannel SAR ADCs. +The module name is ``ad4691``. + + +Supported devices +================= + +The following chips are supported by this driver: + +* `AD4691 `_ — 16-channel, 500 kSPS +* `AD4692 `_ — 16-channel, 1 MSPS +* `AD4693 `_ — 8-channel, 500 kSPS +* `AD4694 `_ — 8-channel, 1 MSPS + + +IIO channels +============ + +Each physical ADC input maps to one IIO voltage channel. The AD4691 and AD4692 +expose 16 channels (``voltage0`` through ``voltage15``); the AD4693 and AD4694 +expose 8 channels (``voltage0`` through ``voltage7``). + +All channels share a common scale (``in_voltage_scale``), derived from the +reference voltage. Each channel exposes: + +* ``in_voltageN_raw`` — single-shot ADC result + +The following attributes are shared across all channels: + +* ``in_voltage_sampling_frequency`` — effective output rate, defined as the + internal oscillator frequency divided by the oversampling ratio. Writing this + attribute selects the nearest achievable rate for the current OSR; the value + read back reflects the actual rate after snapping to the closest valid + oscillator entry. +* ``in_voltage_sampling_frequency_available`` — list of achievable effective + rates for the current oversampling ratio. The list updates dynamically when + the oversampling ratio changes. + +The following attributes are shared across all channels and only available in +CNV Burst Mode: + +* ``in_voltage_oversampling_ratio`` — hardware oversampling depth applied to + all channels; see `Oversampling`_ below. +* ``in_voltage_oversampling_ratio_available`` — valid ratios: 1, 2, 4, 8, 16, + 32. + + +Operating modes +=============== + +The driver supports two operating modes, selected automatically from the +device tree at probe time. + +Manual Mode +----------- + +Selected when no ``pwms`` property is present in the device tree. The CNV pin +is tied to the SPI chip-select: every CS assertion triggers a conversion and +returns the previous result. A user-defined IIO trigger (e.g. hrtimer trigger) +drives the buffer. + +Oversampling is not supported in Manual Mode. + +CNV Burst Mode +-------------- + +Selected when a ``pwms`` property is present in the device tree. A PWM drives +the CNV pin at the configured conversion rate. A GP pin wired to the SoC and +declared in the device tree signals DATA_READY at the end of each burst, +triggering a readout of all active channel results into the IIO buffer. + +The buffer output rate is controlled by the ``sampling_frequency`` attribute +on the IIO buffer. In practice the PWM rate should be set low enough to allow +the SPI readout to complete before the next conversion burst begins. + +Autonomous Mode (idle / single-shot) +------------------------------------- + +When the IIO buffer is disabled, ``in_voltageN_raw`` reads perform a single +conversion on the requested channel using the internal oscillator. The +oscillator is started and stopped around each read to save power. + + +Oversampling +============ + +In CNV Burst Mode a shared hardware accumulator averages a configurable number +of successive conversions across all active channels. The result is always a +16-bit mean, so the buffer data type (shown in ``buffer0/in_voltageN_type``) +is unaffected by the oversampling ratio. Valid ratios are 1, 2, 4, 8, 16 and +32; the default is 1 (no averaging). Oversampling is not supported in Manual +Mode. + +.. code-block:: bash + + # Set oversampling ratio to 16 (shared across all channels) + echo 16 > /sys/bus/iio/devices/iio:device0/in_voltage_oversampling_ratio + + # Read the resulting effective sampling frequency + cat /sys/bus/iio/devices/iio:device0/in_voltage_sampling_frequency + +Writing ``in_voltage_oversampling_ratio`` stores the new shared depth and snaps +the internal oscillator to the largest valid table entry that is both less than +or equal to ``old_effective_rate × new_osr`` and evenly divisible by +``new_osr``. This preserves an integer read-back of +``in_voltage_sampling_frequency`` after the change and keeps the oscillator as +close as possible to the previous effective rate. + + +Reference voltage +================= + +The driver supports two reference configurations, mutually exclusive: + +* **External reference** (``ref-supply``): a voltage between 2.4 V and 5.25 V + supplied externally. +* **Buffered internal reference** (``refin-supply``): an internal reference + buffer is enabled by the driver. + +Exactly one of ``ref-supply`` or ``refin-supply`` must be present in the +device tree. The reference voltage determines the full-scale range reported +via ``in_voltage_scale``. + + +LDO supply +========== + +The chip contains an internal LDO that powers part of the analog front-end. +The supply configuration is mutually exclusive: + +* **External VDD** (``vdd-supply``): an external 1.8 V supply is used directly; + the internal LDO is disabled. +* **Internal LDO** (``ldo-in-supply``): the internal LDO is enabled and fed + from the ``ldo-in`` regulator. Use this when no external 1.8 V VDD is present. + +Exactly one of ``vdd-supply`` or ``ldo-in-supply`` must be provided. + + +Reset +===== + +The driver supports two reset mechanisms: + +* **Hardware reset** (``reset-gpios`` in device tree): the GPIO line is + asserted then deasserted at probe; the driver waits 300 µs for the chip + to complete its internal reset sequence before accepting SPI commands. +* **Software reset** (fallback when ``reset-gpios`` is absent): written + automatically at probe. + + +GP pins and interrupts +====================== + +The chip exposes up to four general-purpose (GP) pins. In CNV Burst Mode +(non-offload), one GP pin must be wired to an interrupt-capable SoC input and +declared in the device tree using the ``interrupts`` and ``interrupt-names`` +properties. The ``interrupt-names`` value identifies which GP pin is used +(``"gp0"`` through ``"gp3"``). + +Example device tree fragment:: + + adc@0 { + compatible = "adi,ad4692"; + ... + interrupt-parent = <&gpio0>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "gp0"; + }; + + +SPI offload support +=================== + +When a SPI offload engine (e.g. the AXI SPI Engine) is present, the driver +uses DMA-backed transfers for CPU-independent, high-throughput data capture. +SPI offload is detected automatically at probe; if no offload hardware is +available the driver falls back to the software triggered-buffer path. + +Two SPI offload sub-modes exist: + +CNV Burst offload +----------------- + +Used when a ``pwms`` property is present and SPI offload is available. The PWM +drives CNV at the configured rate; on DATA_READY the offload engine reads all +active channel results and streams them directly to the IIO DMA buffer with no +CPU involvement. The GP pin used as DATA_READY trigger is supplied by the +trigger-source consumer at buffer enable time; no ``interrupt-names`` entry is +required. + +Manual offload +-------------- + +Used when no ``pwms`` property is present and SPI offload is available. A +periodic SPI offload trigger controls the conversion rate and the offload engine +streams results directly to the IIO DMA buffer. + +The ``sampling_frequency`` attribute on the IIO buffer controls the trigger +rate (in Hz). The initial rate is 100 kHz. + +Oversampling is not supported in Manual Mode. + + +Buffer data format +================== + +The sample format in the IIO buffer depends on whether SPI offload is in use. + +Software triggered-buffer path (no SPI offload) +------------------------------------------------ + +Each active channel occupies one 16-bit big-endian slot (``storagebits=16``, +``endianness=be``). Active channels are packed densely in scan-index order, +followed by a 64-bit software timestamp appended by the IIO core. + +SPI offload path +---------------- + +Each active channel occupies one 16-bit CPU-native slot (``storagebits=16``, +``endianness=cpu``). The SPI offload engine streams 16-bit words directly from +the SPI Engine into the DMA buffer; no software timestamp is appended. diff --git a/Documentation/iio/adxl313.rst b/Documentation/iio/adxl313.rst index 966e72c0109a..3641193bf647 100644 --- a/Documentation/iio/adxl313.rst +++ b/Documentation/iio/adxl313.rst @@ -11,7 +11,7 @@ This driver supports Analog Device's ADXL313 on SPI/I2C bus. * `ADXL313 `_ -The ADXL313is a low noise density, low power, 3-axis accelerometer with +The ADXL313 is a low noise density, low power, 3-axis accelerometer with selectable measurement ranges. The ADXL313 supports the ±0.5 g, ±1 g, ±2 g and ±4 g ranges. @@ -38,7 +38,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. +---------------------------------------------------+----------------------------------------------------------+ | in_accel_x_raw | Raw X-axis accelerometer channel value. | +---------------------------------------------------+----------------------------------------------------------+ -| in_accel_y_calibbias | y-axis acceleration offset correction | +| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. | +---------------------------------------------------+----------------------------------------------------------+ | in_accel_y_raw | Raw Y-axis accelerometer channel value. | +---------------------------------------------------+----------------------------------------------------------+ @@ -112,9 +112,9 @@ apply the following formula: Where _offset and _scale are device attributes. If no _offset attribute is present, simply assume its value is 0. -The ADXL313 driver offers data for a single types of channels, the table below -shows the measurement units for the processed value, which are defined by the -IIO framework: +The ADXL313 driver offers data for multiple channels of a single type. +The table below shows the measurement units for the processed value, +which are defined by the IIO framework: +-------------------------------------+---------------------------+ | Channel type | Measurement unit | diff --git a/Documentation/iio/adxl345.rst b/Documentation/iio/adxl345.rst index 978f746a8198..0aa33a852412 100644 --- a/Documentation/iio/adxl345.rst +++ b/Documentation/iio/adxl345.rst @@ -47,7 +47,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. +-------------------------------------------+----------------------------------------------------------+ | in_accel_x_raw | Raw X-axis accelerometer channel value. | +-------------------------------------------+----------------------------------------------------------+ -| in_accel_y_calibbias | Y-axis acceleration offset correction | +| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. | +-------------------------------------------+----------------------------------------------------------+ | in_accel_y_raw | Raw Y-axis accelerometer channel value. | +-------------------------------------------+----------------------------------------------------------+ diff --git a/Documentation/iio/adxl380.rst b/Documentation/iio/adxl380.rst index 61cafa2f98bf..654d4c0e84a1 100644 --- a/Documentation/iio/adxl380.rst +++ b/Documentation/iio/adxl380.rst @@ -51,7 +51,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. +---------------------------------------------------+----------------------------------------------------------+ | in_accel_x_raw | Raw X-axis accelerometer channel value. | +---------------------------------------------------+----------------------------------------------------------+ -| in_accel_y_calibbias | y-axis acceleration offset correction | +| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. | +---------------------------------------------------+----------------------------------------------------------+ | in_accel_y_raw | Raw Y-axis accelerometer channel value. | +---------------------------------------------------+----------------------------------------------------------+ diff --git a/Documentation/iio/iio_devbuf.rst b/Documentation/iio/iio_devbuf.rst index dca1f0200b0d..e91730fa3cea 100644 --- a/Documentation/iio/iio_devbuf.rst +++ b/Documentation/iio/iio_devbuf.rst @@ -83,9 +83,10 @@ and the relevant _type attributes to establish the data storage format. Read-only attribute containing the description of the scan element data storage within the buffer and hence the form in which it is read from userspace. Format -is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift], where: +is [be|le]:[f|s|u]bits/storagebits[Xrepeat][>>shift], where: - **be** or **le** specifies big or little-endian. +- **f** specifies if floating-point. - **s** or **u** specifies if signed (2's complement) or unsigned. - **bits** is the number of valid data bits. - **storagebits** is the number of bits (after padding) that it occupies in the diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst index ba3e609c6a13..007e0a1fcc5a 100644 --- a/Documentation/iio/index.rst +++ b/Documentation/iio/index.rst @@ -23,6 +23,7 @@ Industrial I/O Kernel Drivers ad4000 ad4030 ad4062 + ad4691 ad4695 ad7191 ad7380 diff --git a/Documentation/misc-devices/apds990x.rst b/Documentation/misc-devices/apds990x.rst deleted file mode 100644 index e2f75577f731..000000000000 --- a/Documentation/misc-devices/apds990x.rst +++ /dev/null @@ -1,128 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -====================== -Kernel driver apds990x -====================== - -Supported chips: -Avago APDS990X - -Data sheet: -Not freely available - -Author: -Samu Onkalo - -Description ------------ - -APDS990x is a combined ambient light and proximity sensor. ALS and proximity -functionality are highly connected. ALS measurement path must be running -while the proximity functionality is enabled. - -ALS produces raw measurement values for two channels: Clear channel -(infrared + visible light) and IR only. However, threshold comparisons happen -using clear channel only. Lux value and the threshold level on the HW -might vary quite much depending the spectrum of the light source. - -Driver makes necessary conversions to both directions so that user handles -only lux values. Lux value is calculated using information from the both -channels. HW threshold level is calculated from the given lux value to match -with current type of the lightning. Sometimes inaccuracy of the estimations -lead to false interrupt, but that doesn't harm. - -ALS contains 4 different gain steps. Driver automatically -selects suitable gain step. After each measurement, reliability of the results -is estimated and new measurement is triggered if necessary. - -Platform data can provide tuned values to the conversion formulas if -values are known. Otherwise plain sensor default values are used. - -Proximity side is little bit simpler. There is no need for complex conversions. -It produces directly usable values. - -Driver controls chip operational state using pm_runtime framework. -Voltage regulators are controlled based on chip operational state. - -SYSFS ------ - - -chip_id - RO - shows detected chip type and version - -power_state - RW - enable / disable chip. Uses counting logic - - 1 enables the chip - 0 disables the chip -lux0_input - RO - measured lux value - - sysfs_notify called when threshold interrupt occurs - -lux0_sensor_range - RO - lux0_input max value. - - Actually never reaches since sensor tends - to saturate much before that. Real max value varies depending - on the light spectrum etc. - -lux0_rate - RW - measurement rate in Hz - -lux0_rate_avail - RO - supported measurement rates - -lux0_calibscale - RW - calibration value. - - Set to neutral value by default. - Output results are multiplied with calibscale / calibscale_default - value. - -lux0_calibscale_default - RO - neutral calibration value - -lux0_thresh_above_value - RW - HI level threshold value. - - All results above the value - trigs an interrupt. 65535 (i.e. sensor_range) disables the above - interrupt. - -lux0_thresh_below_value - RW - LO level threshold value. - - All results below the value - trigs an interrupt. 0 disables the below interrupt. - -prox0_raw - RO - measured proximity value - - sysfs_notify called when threshold interrupt occurs - -prox0_sensor_range - RO - prox0_raw max value (1023) - -prox0_raw_en - RW - enable / disable proximity - uses counting logic - - - 1 enables the proximity - - 0 disables the proximity - -prox0_reporting_mode - RW - trigger / periodic. - - In "trigger" mode the driver tells two possible - values: 0 or prox0_sensor_range value. 0 means no proximity, - 1023 means proximity. This causes minimal number of interrupts. - In "periodic" mode the driver reports all values above - prox0_thresh_above. This causes more interrupts, but it can give - _rough_ estimate about the distance. - -prox0_reporting_mode_avail - RO - accepted values to prox0_reporting_mode (trigger, periodic) - -prox0_thresh_above_value - RW - threshold level which trigs proximity events. diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst index 081e79415e38..f911edaecbfa 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -13,7 +13,6 @@ fit into other categories. ad525x_dpot amd-sbi - apds990x bh1770glc c2port dw-xdata-pcie diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 6c8fdcf8db66..3f0ef1e27eb0 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -340,7 +340,6 @@ Code Seq# Include File Comments 0xA2 all uapi/linux/acrn.h ACRN hypervisor 0xA3 80-8F Port ACL in development: -0xA3 90-9F linux/dtlk.h 0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem 0xA4 00-1F uapi/asm/sgx.h 0xA5 01-05 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator diff --git a/MAINTAINERS b/MAINTAINERS index eab64f775f57..6b4560681b51 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -640,7 +640,7 @@ F: drivers/iio/accel/adxl355_i2c.c F: drivers/iio/accel/adxl355_spi.c ADXL367 THREE-AXIS DIGITAL ACCELEROMETER DRIVER -M: Cosmin Tanislav +M: Marcelo Schmitt L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers @@ -1492,7 +1492,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml F: drivers/iio/adc/ad4080.c ANALOG DEVICES INC AD4130 DRIVER -M: Cosmin Tanislav +M: Marcelo Schmitt L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers @@ -1516,6 +1516,15 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad4170-4.yaml F: drivers/iio/adc/ad4170-4.c +ANALOG DEVICES INC AD4691 DRIVER +M: Radu Sabau +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,ad4691.yaml +F: Documentation/iio/ad4691.rst +F: drivers/iio/adc/ad4691.c + ANALOG DEVICES INC AD4695 DRIVER M: Michael Hennerich M: Nuno Sá @@ -1538,6 +1547,14 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml F: drivers/iio/adc/ad4851.c +ANALOG DEVICES INC AD5706R DRIVER +M: Alexis Czezar Torreno +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/dac/adi,ad5706r.yaml +F: drivers/iio/dac/ad5706r.c + ANALOG DEVICES INC AD7091R DRIVER M: Marcelo Schmitt L: linux-iio@vger.kernel.org @@ -1580,7 +1597,7 @@ F: Documentation/devicetree/bindings/iio/dac/adi,ad7293.yaml F: drivers/iio/dac/ad7293.c ANALOG DEVICES INC AD74115 DRIVER -M: Cosmin Tanislav +M: Marcelo Schmitt L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers @@ -1588,7 +1605,7 @@ F: Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml F: drivers/iio/addac/ad74115.c ANALOG DEVICES INC AD74413R DRIVER -M: Cosmin Tanislav +M: Marcelo Schmitt L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers @@ -1884,8 +1901,9 @@ W: https://ez.analog.com/linux-software-drivers F: drivers/dma/dma-axi-dmac.c ANALOG DEVICES INC IIO DRIVERS -M: Lars-Peter Clausen +M: Nuno Sá M: Michael Hennerich +L: linux@analog.com S: Supported W: http://wiki.analog.com/ W: https://ez.analog.com/linux-software-drivers @@ -5041,6 +5059,13 @@ S: Maintained F: Documentation/devicetree/bindings/iio/light/brcm,apds9160.yaml F: drivers/iio/light/apds9160.c +BROADCOM APDS9999 AMBIENT LIGHT SENSOR DRIVER +M: Jose A. Perez de Azpillaga +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/light/brcm,apds9999.yaml +F: drivers/iio/light/apds9999.c + BROADCOM ASP 2.0 ETHERNET DRIVER M: Justin Chen M: Florian Fainelli @@ -7787,13 +7812,6 @@ T: git git://linuxtv.org/media.git F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.yaml F: drivers/media/i2c/dw9807-vcm.c -DOUBLETALK DRIVER -M: "James R. Van Zandt" -L: blinux-list@redhat.com -S: Maintained -F: drivers/char/dtlk.c -F: include/linux/dtlk.h - DPAA2 DATAPATH I/O (DPIO) DRIVER M: Roy Pledge L: linux-kernel@vger.kernel.org @@ -12582,6 +12600,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git F: Documentation/ABI/testing/configfs-iio* F: Documentation/ABI/testing/sysfs-bus-iio* F: Documentation/devicetree/bindings/iio/ +F: Documentation/driver-api/iio/ F: Documentation/iio/ F: drivers/iio/ F: drivers/staging/iio/ @@ -17333,6 +17352,13 @@ F: drivers/mtd/ F: include/linux/mtd/ F: include/uapi/mtd/ +MEMSIC MMC5983 MAGNETOMETER DRIVER +M: Vladislav Kulikov +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/magnetometer/memsic,mmc5983.yaml +F: drivers/iio/magnetometer/mmc5983.c + MEN A21 WATCHDOG DRIVER M: Johannes Thumshirn L: linux-watchdog@vger.kernel.org @@ -22835,7 +22861,7 @@ F: Documentation/devicetree/bindings/mtd/renesas-nandc.yaml F: drivers/mtd/nand/raw/renesas-nand-controller.c RENESAS R-CAR GYROADC DRIVER -M: Marek Vasut +M: Marek Vasut L: linux-iio@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml @@ -24459,7 +24485,7 @@ F: Documentation/devicetree/bindings/iio/chemical/senseair,sunrise.yaml F: drivers/iio/chemical/sunrise_co2.c SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER -M: Tomasz Duszynski +M: Maxwell Doose S: Maintained F: Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml F: drivers/iio/chemical/scd30.h @@ -28677,6 +28703,11 @@ S: Maintained F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml F: drivers/iio/light/veml3235.c +VISHAY VEML3328 RGB IR LIGHT SENSOR DRIVER +M: Joshua Crofts +S: Maintained +F: drivers/iio/light/veml3328.c + VISHAY VEML6030 AMBIENT LIGHT SENSOR DRIVER M: Javier Carrasco S: Maintained diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index 8631be100d1d..06e3cc55cb0d 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -572,7 +572,6 @@ CONFIG_PPDEV=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=m CONFIG_NVRAM=y -CONFIG_DTLK=m CONFIG_IPWIRELESS=m CONFIG_I2C_CHARDEV=m CONFIG_I2C_HYDRA=m diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 9e6194224593..ec0ab4f28530 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3080,12 +3080,10 @@ static void binder_transaction(struct binder_proc *proc, int t_debug_id = atomic_inc_return(&binder_last_id); ktime_t t_start_time = ktime_get(); struct lsm_context lsmctx = { }; - struct list_head sgc_head; - struct list_head pf_head; + LIST_HEAD(sgc_head); + LIST_HEAD(pf_head); const void __user *user_buffer = (const void __user *) (uintptr_t)tr->data.ptr.buffer; - INIT_LIST_HEAD(&sgc_head); - INIT_LIST_HEAD(&pf_head); e = binder_transaction_log_add(&binder_transaction_log); e->debug_id = t_debug_id; diff --git a/drivers/android/binder/page_range.rs b/drivers/android/binder/page_range.rs index e54a90e62402..e82a5523804f 100644 --- a/drivers/android/binder/page_range.rs +++ b/drivers/android/binder/page_range.rs @@ -705,7 +705,7 @@ fn drop(self: Pin<&mut Self>) { let page; let page_index; let mm; - let mmap_read; + let vma_read; let mm_mutex; let vma_addr; let range_ptr; @@ -728,17 +728,18 @@ fn drop(self: Pin<&mut Self>) { None => return LRU_SKIP, }; - mmap_read = match mm.mmap_read_trylock() { - Some(guard) => guard, - None => return LRU_SKIP, - }; - // We can't lock it normally here, since we hold the lru lock. let inner = match range.lock.try_lock() { Some(inner) => inner, None => return LRU_SKIP, }; + vma_addr = inner.vma_addr; + vma_read = match mm.lock_vma_under_rcu(vma_addr) { + Some(guard) => guard, + None => return LRU_SKIP, + }; + // SAFETY: The item is in this lru list, so it's okay to remove it. unsafe { bindings::list_lru_isolate(lru, item) }; @@ -751,7 +752,6 @@ fn drop(self: Pin<&mut Self>) { // `zap_page_range` before we release the mmap lock, so `use_page_slow` will not be able to // insert a new page until after our call to `zap_page_range`. page = unsafe { PageInfo::take_page(info) }; - vma_addr = inner.vma_addr; // From this point on, we don't access this PageInfo or ShrinkablePageRange again, because // they can be freed at any point after we unlock `lru_lock`. This is with the exception of @@ -761,14 +761,12 @@ fn drop(self: Pin<&mut Self>) { // SAFETY: The lru lock is locked when this method is called. unsafe { bindings::spin_unlock(&raw mut (*lru).lock) }; - if let Some(unchecked_vma) = mmap_read.vma_lookup(vma_addr) { - if let Some(vma) = check_vma(unchecked_vma, range_ptr) { - let user_page_addr = vma_addr + (page_index << PAGE_SHIFT); - vma.zap_vma_range(user_page_addr, PAGE_SIZE); - } + if let Some(vma) = check_vma(&vma_read, range_ptr) { + let user_page_addr = vma_addr + (page_index << PAGE_SHIFT); + vma.zap_vma_range(user_page_addr, PAGE_SIZE); } - drop(mmap_read); + drop(vma_read); drop(mm_mutex); drop(mm); drop(page); diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index 0277e1ab1198..9db2a2a2c913 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -232,7 +232,9 @@ static int mhi_ep_process_cmd_ring(struct mhi_ep_ring *ring, struct mhi_ring_ele ret = mhi_ep_create_device(mhi_cntrl, ch_id); if (ret) { dev_err(dev, "Error creating device for channel (%u)\n", ch_id); + mutex_lock(&mhi_cntrl->state_lock); mhi_ep_handle_syserr(mhi_cntrl); + mutex_unlock(&mhi_cntrl->state_lock); return ret; } } @@ -1087,11 +1089,12 @@ static void mhi_ep_reset_worker(struct work_struct *work) mhi_ep_power_down(mhi_cntrl); - mutex_lock(&mhi_cntrl->state_lock); - /* Reset MMIO to signal host that the MHI_RESET is completed in endpoint */ mhi_ep_mmio_reset(mhi_cntrl); + + mutex_lock(&mhi_cntrl->state_lock); cur_state = mhi_cntrl->mhi_state; + mutex_unlock(&mhi_cntrl->state_lock); /* * Only proceed further if the reset is due to SYS_ERR. The host will @@ -1100,8 +1103,6 @@ static void mhi_ep_reset_worker(struct work_struct *work) */ if (cur_state == MHI_STATE_SYS_ERR) mhi_ep_power_up(mhi_cntrl); - - mutex_unlock(&mhi_cntrl->state_lock); } /* @@ -1148,7 +1149,9 @@ int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl) for (i = 0; i < mhi_cntrl->event_rings; i++) mhi_ep_ring_init(&mhi_cntrl->mhi_event[i].ring, RING_TYPE_ER, i); + mutex_lock(&mhi_cntrl->state_lock); mhi_cntrl->mhi_state = MHI_STATE_RESET; + mutex_unlock(&mhi_cntrl->state_lock); /* Set AMSS EE before signaling ready state */ mhi_ep_mmio_set_env(mhi_cntrl, MHI_EE_AMSS); diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c index 750da3dbb4c6..0d0d9c7ffa4b 100644 --- a/drivers/bus/mhi/host/pci_generic.c +++ b/drivers/bus/mhi/host/pci_generic.c @@ -914,6 +914,16 @@ static const struct mhi_pci_dev_info mhi_telit_fe912c04_info = { .edl_trigger = true, }; +static const struct mhi_pci_dev_info mhi_telit_fe910c04_info = { + .name = "telit-fe910c04", + .config = &modem_telit_fn920c04_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .sideband_wake = false, + .mru_default = 32768, + .edl_trigger = true, +}; + static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = { .name = "netprisma-lcur57", .edl = "qcom/prog_firehose_sdx24.mbn", @@ -941,6 +951,9 @@ static const struct pci_device_id mhi_pci_id_table[] = { /* Telit FN920C04 (sdx35) */ {PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2020), .driver_data = (kernel_ulong_t) &mhi_telit_fn920c04_info }, + /* Telit FE910C04 (sdx35) */ + {PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x202a), + .driver_data = (kernel_ulong_t) &mhi_telit_fe910c04_info }, /* Telit FE912C04 (sdx35) */ { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2045), .driver_data = (kernel_ulong_t) &mhi_telit_fe912c04_info }, @@ -1189,7 +1202,8 @@ static int mhi_pci_get_irqs(struct mhi_controller *mhi_cntrl, */ mhi_cntrl->nr_irqs = 1 + mhi_cntrl_config->num_events; - nr_vectors = pci_alloc_irq_vectors(pdev, 1, mhi_cntrl->nr_irqs, PCI_IRQ_MSIX | PCI_IRQ_MSI); + nr_vectors = pci_alloc_irq_vectors(pdev, 1, roundup_pow_of_two(mhi_cntrl->nr_irqs), + PCI_IRQ_MSIX | PCI_IRQ_MSI); if (nr_vectors < 0) { dev_err(&pdev->dev, "Error allocating MSI vectors %d\n", nr_vectors); @@ -1247,7 +1261,7 @@ static void mhi_pci_recovery_work(struct work_struct *work) dev_warn(&pdev->dev, "device recovery started\n"); - if (pdev->is_physfn) + if (!pdev->is_virtfn) timer_delete(&mhi_pdev->health_check_timer); pm_runtime_forbid(&pdev->dev); @@ -1277,7 +1291,7 @@ static void mhi_pci_recovery_work(struct work_struct *work) set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status); - if (pdev->is_physfn) + if (!pdev->is_virtfn) mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD); return; @@ -1368,7 +1382,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mhi_cntrl_config = info->config; /* Initialize health check monitor only for Physical functions */ - if (pdev->is_physfn) + if (!pdev->is_virtfn) timer_setup(&mhi_pdev->health_check_timer, health_check, 0); mhi_cntrl = &mhi_pdev->mhi_cntrl; @@ -1390,7 +1404,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mhi_cntrl->mru = info->mru_default; mhi_cntrl->name = info->name; - if (pdev->is_physfn) + if (!pdev->is_virtfn) mhi_pdev->reset_on_remove = info->reset_on_remove; if (info->edl_trigger) @@ -1439,7 +1453,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status); /* start health check */ - if (pdev->is_physfn) + if (!pdev->is_virtfn) mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD); /* Allow runtime suspend only if both PME from D3Hot and M3 are supported */ @@ -1468,7 +1482,7 @@ static void mhi_pci_remove(struct pci_dev *pdev) pm_runtime_forbid(&pdev->dev); pci_disable_sriov(pdev); - if (pdev->is_physfn) + if (!pdev->is_virtfn) timer_delete_sync(&mhi_pdev->health_check_timer); cancel_work_sync(&mhi_pdev->recovery_work); @@ -1500,7 +1514,7 @@ static void mhi_pci_reset_prepare(struct pci_dev *pdev) dev_info(&pdev->dev, "reset\n"); - if (pdev->is_physfn) + if (!pdev->is_virtfn) timer_delete(&mhi_pdev->health_check_timer); /* Clean up MHI state */ @@ -1546,7 +1560,7 @@ static void mhi_pci_reset_done(struct pci_dev *pdev) } set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status); - if (pdev->is_physfn) + if (!pdev->is_virtfn) mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD); } @@ -1612,7 +1626,7 @@ static int __maybe_unused mhi_pci_runtime_suspend(struct device *dev) if (test_and_set_bit(MHI_PCI_DEV_SUSPENDED, &mhi_pdev->status)) return 0; - if (pdev->is_physfn) + if (!pdev->is_virtfn) timer_delete(&mhi_pdev->health_check_timer); cancel_work_sync(&mhi_pdev->recovery_work); @@ -1665,7 +1679,7 @@ static int __maybe_unused mhi_pci_runtime_resume(struct device *dev) } /* Resume health check */ - if (pdev->is_physfn) + if (!pdev->is_virtfn) mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD); /* It can be a remote wakeup (no mhi runtime_get), update access time */ diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 2a3a37b2cf3c..9865227af167 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -199,17 +199,6 @@ config NWFLASH source "drivers/char/hw_random/Kconfig" -config DTLK - tristate "Double Talk PC internal speech card support" - depends on ISA - help - This driver is for the DoubleTalk PC, a speech synthesizer - manufactured by RC Systems (). It is also - called the `internal DoubleTalk'. - - To compile this driver as a module, choose M here: the - module will be called dtlk. - config XILINX_HWICAP tristate "Xilinx HWICAP Support" depends on MICROBLAZE @@ -220,21 +209,6 @@ config XILINX_HWICAP If unsure, say N. -config APPLICOM - tristate "Applicom intelligent fieldbus card support" - depends on PCI - help - This driver provides the kernel-side support for the intelligent - fieldbus cards made by Applicom International. More information - about these cards can be found on the WWW at the address - , or by email from David Woodhouse - . - - To compile this driver as a module, choose M here: the - module will be called applicom. - - If unsure, say N. - config SONYPI tristate "Sony Vaio Programmable I/O Control Device support" depends on X86_32 && PCI && INPUT && HAS_IOPORT diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 47bdc882797a..a46d7bf7c4c8 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -16,8 +16,6 @@ obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_APM_EMULATION) += apm-emulation.o -obj-$(CONFIG_DTLK) += dtlk.o -obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c deleted file mode 100644 index c138c468f3a4..000000000000 --- a/drivers/char/applicom.c +++ /dev/null @@ -1,857 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Derived from Applicom driver ac.c for SCO Unix */ -/* Ported by David Woodhouse, Axiom (Cambridge) Ltd. */ -/* dwmw2@infradead.org 30/8/98 */ -/* $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $ */ -/* This module is for Linux 2.1 and 2.2 series kernels. */ -/*****************************************************************************/ -/* J PAGET 18/02/94 passage V2.4.2 ioctl avec code 2 reset to les interrupt */ -/* ceci pour reseter correctement apres une sortie sauvage */ -/* J PAGET 02/05/94 passage V2.4.3 dans le traitement de d'interruption, */ -/* LoopCount n'etait pas initialise a 0. */ -/* F LAFORSE 04/07/95 version V2.6.0 lecture bidon apres acces a une carte */ -/* pour liberer le bus */ -/* J.PAGET 19/11/95 version V2.6.1 Nombre, addresse,irq n'est plus configure */ -/* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */ -/* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */ -/* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */ -/* addresses de base des cartes, IOCTL 6 plus complet */ -/* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */ -/* de code autre que le texte V2.6.1 en V2.8.0 */ -/*****************************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "applicom.h" - - -/* NOTE: We use for loops with {write,read}b() instead of - memcpy_{from,to}io throughout this driver. This is because - the board doesn't correctly handle word accesses - only - bytes. -*/ - - -#undef DEBUG - -#define MAX_BOARD 8 /* maximum of pc board possible */ -#define MAX_ISA_BOARD 4 -#define LEN_RAM_IO 0x800 - -#ifndef PCI_VENDOR_ID_APPLICOM -#define PCI_VENDOR_ID_APPLICOM 0x1389 -#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001 -#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002 -#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 -#endif - -static DEFINE_MUTEX(ac_mutex); -static char *applicom_pci_devnames[] = { - "PCI board", - "PCI2000IBS / PCI2000CAN", - "PCI2000PFB" -}; - -static const struct pci_device_id applicom_pci_tbl[] = { - { PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCIGENERIC) }, - { PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN) }, - { PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCI2000PFB) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, applicom_pci_tbl); - -MODULE_AUTHOR("David Woodhouse & Applicom International"); -MODULE_DESCRIPTION("Driver for Applicom Profibus card"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(AC_MINOR); - -static struct applicom_board { - unsigned long PhysIO; - void __iomem *RamIO; - wait_queue_head_t FlagSleepSend; - long irq; - spinlock_t mutex; -} apbs[MAX_BOARD]; - -static unsigned int irq; /* interrupt number IRQ */ -static unsigned long mem; /* physical segment of board */ - -module_param_hw(irq, uint, irq, 0); -MODULE_PARM_DESC(irq, "IRQ of the Applicom board"); -module_param_hw(mem, ulong, iomem, 0); -MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board"); - -static unsigned int numboards; /* number of installed boards */ -static volatile unsigned char Dummy; -static DECLARE_WAIT_QUEUE_HEAD(FlagSleepRec); -static unsigned int WriteErrorCount; /* number of write error */ -static unsigned int ReadErrorCount; /* number of read error */ -static unsigned int DeviceErrorCount; /* number of device error */ - -static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *); -static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *); -static long ac_ioctl(struct file *, unsigned int, unsigned long); -static irqreturn_t ac_interrupt(int, void *); - -static const struct file_operations ac_fops = { - .owner = THIS_MODULE, - .read = ac_read, - .write = ac_write, - .unlocked_ioctl = ac_ioctl, -}; - -static struct miscdevice ac_miscdev = { - AC_MINOR, - "ac", - &ac_fops -}; - -static int dummy; /* dev_id for request_irq() */ - -static int ac_register_board(unsigned long physloc, void __iomem *loc, - unsigned char boardno) -{ - volatile unsigned char byte_reset_it; - - if((readb(loc + CONF_END_TEST) != 0x00) || - (readb(loc + CONF_END_TEST + 1) != 0x55) || - (readb(loc + CONF_END_TEST + 2) != 0xAA) || - (readb(loc + CONF_END_TEST + 3) != 0xFF)) - return 0; - - if (!boardno) - boardno = readb(loc + NUMCARD_OWNER_TO_PC); - - if (!boardno || boardno > MAX_BOARD) { - printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", - boardno, physloc, MAX_BOARD); - return 0; - } - - if (apbs[boardno - 1].RamIO) { - printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", - boardno, physloc, boardno, apbs[boardno-1].PhysIO); - return 0; - } - - boardno--; - - apbs[boardno].PhysIO = physloc; - apbs[boardno].RamIO = loc; - init_waitqueue_head(&apbs[boardno].FlagSleepSend); - spin_lock_init(&apbs[boardno].mutex); - byte_reset_it = readb(loc + RAM_IT_TO_PC); - - numboards++; - return boardno + 1; -} - -static void __exit applicom_exit(void) -{ - unsigned int i; - - misc_deregister(&ac_miscdev); - - for (i = 0; i < MAX_BOARD; i++) { - - if (!apbs[i].RamIO) - continue; - - if (apbs[i].irq) - free_irq(apbs[i].irq, &dummy); - - iounmap(apbs[i].RamIO); - } -} - -static int __init applicom_init(void) -{ - int i, numisa = 0; - struct pci_dev *dev = NULL; - void __iomem *RamIO; - int boardno, ret; - - printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n"); - - /* No mem and irq given - check for a PCI card */ - - while ( (dev = pci_get_class(PCI_CLASS_OTHERS << 16, dev))) { - - if (!pci_match_id(applicom_pci_tbl, dev)) - continue; - - if (pci_enable_device(dev)) { - pci_dev_put(dev); - return -EIO; - } - - RamIO = ioremap(pci_resource_start(dev, 0), LEN_RAM_IO); - - if (!RamIO) { - printk(KERN_INFO "ac.o: Failed to ioremap PCI memory " - "space at 0x%llx\n", - (unsigned long long)pci_resource_start(dev, 0)); - pci_disable_device(dev); - pci_dev_put(dev); - return -EIO; - } - - printk(KERN_INFO "Applicom %s found at mem 0x%llx, irq %d\n", - applicom_pci_devnames[dev->device-1], - (unsigned long long)pci_resource_start(dev, 0), - dev->irq); - - boardno = ac_register_board(pci_resource_start(dev, 0), - RamIO, 0); - if (!boardno) { - printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); - iounmap(RamIO); - pci_disable_device(dev); - continue; - } - - if (request_irq(dev->irq, &ac_interrupt, IRQF_SHARED, "Applicom PCI", &dummy)) { - printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq); - iounmap(RamIO); - pci_disable_device(dev); - apbs[boardno - 1].RamIO = NULL; - continue; - } - - /* Enable interrupts. */ - - writeb(0x40, apbs[boardno - 1].RamIO + RAM_IT_FROM_PC); - - apbs[boardno - 1].irq = dev->irq; - } - - /* Finished with PCI cards. If none registered, - * and there was no mem/irq specified, exit */ - - if (!mem || !irq) { - if (numboards) - goto fin; - else { - printk(KERN_INFO "ac.o: No PCI boards found.\n"); - printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n"); - return -ENXIO; - } - } - - /* Now try the specified ISA cards */ - - for (i = 0; i < MAX_ISA_BOARD; i++) { - RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO); - - if (!RamIO) { - printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1); - continue; - } - - if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i), - RamIO,i+1))) { - iounmap(RamIO); - continue; - } - - printk(KERN_NOTICE "Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq); - - if (!numisa) { - if (request_irq(irq, &ac_interrupt, IRQF_SHARED, "Applicom ISA", &dummy)) { - printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq); - iounmap(RamIO); - apbs[boardno - 1].RamIO = NULL; - } - else - apbs[boardno - 1].irq = irq; - } - else - apbs[boardno - 1].irq = 0; - - numisa++; - } - - if (!numisa) - printk(KERN_WARNING "ac.o: No valid ISA Applicom boards found " - "at mem 0x%lx\n", mem); - - fin: - init_waitqueue_head(&FlagSleepRec); - - WriteErrorCount = 0; - ReadErrorCount = 0; - DeviceErrorCount = 0; - - if (numboards) { - ret = misc_register(&ac_miscdev); - if (ret) { - printk(KERN_WARNING "ac.o: Unable to register misc device\n"); - goto out; - } - for (i = 0; i < MAX_BOARD; i++) { - int serial; - char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1]; - - if (!apbs[i].RamIO) - continue; - - for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) - boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); - - boardname[serial] = 0; - - - printk(KERN_INFO "Applicom board %d: %s, PROM V%d.%d", - i+1, boardname, - (int)(readb(apbs[i].RamIO + VERS) >> 4), - (int)(readb(apbs[i].RamIO + VERS) & 0xF)); - - serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) ); - - if (serial != 0) - printk(" S/N %d\n", serial); - else - printk("\n"); - } - return 0; - } - - else - return -ENXIO; - -out: - for (i = 0; i < MAX_BOARD; i++) { - if (!apbs[i].RamIO) - continue; - if (apbs[i].irq) - free_irq(apbs[i].irq, &dummy); - iounmap(apbs[i].RamIO); - } - return ret; -} - -module_init(applicom_init); -module_exit(applicom_exit); - - -static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) -{ - unsigned int NumCard; /* Board number 1 -> 8 */ - unsigned int IndexCard; /* Index board number 0 -> 7 */ - unsigned char TicCard; /* Board TIC to send */ - unsigned long flags; /* Current priority */ - struct st_ram_io st_loc; - struct mailbox tmpmailbox; -#ifdef DEBUG - int c; -#endif - DECLARE_WAITQUEUE(wait, current); - - if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - static int warncount = 5; - if (warncount) { - printk(KERN_INFO "Hmmm. write() of Applicom card, length %zd != expected %zd\n", - count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); - warncount--; - } - return -EINVAL; - } - - if(copy_from_user(&st_loc, buf, sizeof(struct st_ram_io))) - return -EFAULT; - - if(copy_from_user(&tmpmailbox, &buf[sizeof(struct st_ram_io)], - sizeof(struct mailbox))) - return -EFAULT; - - NumCard = st_loc.num_card; /* board number to send */ - TicCard = st_loc.tic_des_from_pc; /* tic number to send */ - IndexCard = NumCard - 1; - - if (IndexCard >= MAX_BOARD) - return -EINVAL; - IndexCard = array_index_nospec(IndexCard, MAX_BOARD); - - if (!apbs[IndexCard].RamIO) - return -EINVAL; - -#ifdef DEBUG - printk("Write to applicom card #%d. struct st_ram_io follows:", - IndexCard+1); - - for (c = 0; c < sizeof(struct st_ram_io);) { - - printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]); - - for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) { - printk(" %2.2X", ((unsigned char *) &st_loc)[c]); - } - } - - printk("\nstruct mailbox follows:"); - - for (c = 0; c < sizeof(struct mailbox);) { - printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]); - - for (c++; c % 8 && c < sizeof(struct mailbox); c++) { - printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]); - } - } - - printk("\n"); -#endif - - spin_lock_irqsave(&apbs[IndexCard].mutex, flags); - - /* Test octet ready correct */ - if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) { - Dummy = readb(apbs[IndexCard].RamIO + VERS); - spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags); - printk(KERN_WARNING "APPLICOM driver write error board %d, DataFromPcReady = %d\n", - IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY)); - DeviceErrorCount++; - return -EIO; - } - - /* Place ourselves on the wait queue */ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait); - - /* Check whether the card is ready for us */ - while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0) { - Dummy = readb(apbs[IndexCard].RamIO + VERS); - /* It's busy. Sleep. */ - - spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags); - schedule(); - if (signal_pending(current)) { - remove_wait_queue(&apbs[IndexCard].FlagSleepSend, - &wait); - return -EINTR; - } - spin_lock_irqsave(&apbs[IndexCard].mutex, flags); - set_current_state(TASK_INTERRUPTIBLE); - } - - /* We may not have actually slept */ - set_current_state(TASK_RUNNING); - remove_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait); - - writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - - /* Which is best - lock down the pages with rawio and then - copy directly, or use bounce buffers? For now we do the latter - because it works with 2.2 still */ - { - unsigned char *from = (unsigned char *) &tmpmailbox; - void __iomem *to = apbs[IndexCard].RamIO + RAM_FROM_PC; - int c; - - for (c = 0; c < sizeof(struct mailbox); c++) - writeb(*(from++), to++); - } - - writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC); - writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC); - writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC); - writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); - writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - Dummy = readb(apbs[IndexCard].RamIO + VERS); - spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags); - return 0; -} - -static int do_ac_read(int IndexCard, char __user *buf, - struct st_ram_io *st_loc, struct mailbox *mailbox) -{ - void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC; - unsigned char *to = (unsigned char *)mailbox; -#ifdef DEBUG - int c; -#endif - - st_loc->tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC); - st_loc->numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); - - - { - int c; - - for (c = 0; c < sizeof(struct mailbox); c++) - *(to++) = readb(from++); - } - writeb(1, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); - writeb(1, apbs[IndexCard].RamIO + TYP_ACK_FROM_PC); - writeb(IndexCard+1, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); - writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), - apbs[IndexCard].RamIO + TIC_ACK_FROM_PC); - writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); - writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY); - writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - Dummy = readb(apbs[IndexCard].RamIO + VERS); - -#ifdef DEBUG - printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard); - - for (c = 0; c < sizeof(struct st_ram_io);) { - printk("\n%5.5X: %2.2X", c, ((unsigned char *)st_loc)[c]); - - for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) { - printk(" %2.2X", ((unsigned char *)st_loc)[c]); - } - } - - printk("\nstruct mailbox follows:"); - - for (c = 0; c < sizeof(struct mailbox);) { - printk("\n%5.5X: %2.2X", c, ((unsigned char *)mailbox)[c]); - - for (c++; c % 8 && c < sizeof(struct mailbox); c++) { - printk(" %2.2X", ((unsigned char *)mailbox)[c]); - } - } - printk("\n"); -#endif - return (sizeof(struct st_ram_io) + sizeof(struct mailbox)); -} - -static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_t *ptr) -{ - unsigned long flags; - unsigned int i; - unsigned char tmp; - int ret = 0; - DECLARE_WAITQUEUE(wait, current); -#ifdef DEBUG - int loopcount=0; -#endif - /* No need to ratelimit this. Only root can trigger it anyway */ - if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - printk( KERN_WARNING "Hmmm. read() of Applicom card, length %zd != expected %zd\n", - count,sizeof(struct st_ram_io) + sizeof(struct mailbox)); - return -EINVAL; - } - - while(1) { - /* Stick ourself on the wait queue */ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&FlagSleepRec, &wait); - - /* Scan each board, looking for one which has a packet for us */ - for (i=0; i < MAX_BOARD; i++) { - if (!apbs[i].RamIO) - continue; - spin_lock_irqsave(&apbs[i].mutex, flags); - - tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY); - - if (tmp == 2) { - struct st_ram_io st_loc; - struct mailbox mailbox; - - /* Got a packet for us */ - memset(&st_loc, 0, sizeof(st_loc)); - ret = do_ac_read(i, buf, &st_loc, &mailbox); - spin_unlock_irqrestore(&apbs[i].mutex, flags); - set_current_state(TASK_RUNNING); - remove_wait_queue(&FlagSleepRec, &wait); - - if (copy_to_user(buf, &st_loc, sizeof(st_loc))) - return -EFAULT; - if (copy_to_user(buf + sizeof(st_loc), &mailbox, sizeof(mailbox))) - return -EFAULT; - return tmp; - } - - if (tmp > 2) { - /* Got an error */ - Dummy = readb(apbs[i].RamIO + VERS); - - spin_unlock_irqrestore(&apbs[i].mutex, flags); - set_current_state(TASK_RUNNING); - remove_wait_queue(&FlagSleepRec, &wait); - - printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n", - i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY)); - DeviceErrorCount++; - return -EIO; - } - - /* Nothing for us. Try the next board */ - Dummy = readb(apbs[i].RamIO + VERS); - spin_unlock_irqrestore(&apbs[i].mutex, flags); - - } /* per board */ - - /* OK - No boards had data for us. Sleep now */ - - schedule(); - remove_wait_queue(&FlagSleepRec, &wait); - - if (signal_pending(current)) - return -EINTR; - -#ifdef DEBUG - if (loopcount++ > 2) { - printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount); - } -#endif - } -} - -static irqreturn_t ac_interrupt(int vec, void *dev_instance) -{ - unsigned int i; - unsigned int FlagInt; - unsigned int LoopCount; - int handled = 0; - - // printk("Applicom interrupt on IRQ %d occurred\n", vec); - - LoopCount = 0; - - do { - FlagInt = 0; - for (i = 0; i < MAX_BOARD; i++) { - - /* Skip if this board doesn't exist */ - if (!apbs[i].RamIO) - continue; - - spin_lock(&apbs[i].mutex); - - /* Skip if this board doesn't want attention */ - if(readb(apbs[i].RamIO + RAM_IT_TO_PC) == 0) { - spin_unlock(&apbs[i].mutex); - continue; - } - - handled = 1; - FlagInt = 1; - writeb(0, apbs[i].RamIO + RAM_IT_TO_PC); - - if (readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) { - printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n", - i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY)); - DeviceErrorCount++; - } - - if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && - (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) { - - printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n", - i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY)); - DeviceErrorCount++; - } - - if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) { /* mailbox sent by the card ? */ - if (waitqueue_active(&FlagSleepRec)) { - wake_up_interruptible(&FlagSleepRec); - } - } - - if (readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) { /* ram i/o free for write by pc ? */ - if (waitqueue_active(&apbs[i].FlagSleepSend)) { /* process sleep during read ? */ - wake_up_interruptible(&apbs[i].FlagSleepSend); - } - } - Dummy = readb(apbs[i].RamIO + VERS); - - if(readb(apbs[i].RamIO + RAM_IT_TO_PC)) { - /* There's another int waiting on this card */ - spin_unlock(&apbs[i].mutex); - i--; - } else { - spin_unlock(&apbs[i].mutex); - } - } - if (FlagInt) - LoopCount = 0; - else - LoopCount++; - } while(LoopCount < 2); - return IRQ_RETVAL(handled); -} - - - -static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - -{ /* @ ADG ou ATO selon le cas */ - int i; - unsigned char IndexCard; - void __iomem *pmem; - int ret = 0; - static int warncount = 10; - volatile unsigned char byte_reset_it; - struct st_ram_io *adgl; - void __user *argp = (void __user *)arg; - - /* In general, the device is only openable by root anyway, so we're not - particularly concerned that bogus ioctls can flood the console. */ - - adgl = memdup_user(argp, sizeof(struct st_ram_io)); - if (IS_ERR(adgl)) - return PTR_ERR(adgl); - - mutex_lock(&ac_mutex); - IndexCard = adgl->num_card-1; - - if (cmd != 6 && IndexCard >= MAX_BOARD) - goto err; - IndexCard = array_index_nospec(IndexCard, MAX_BOARD); - - if (cmd != 6 && !apbs[IndexCard].RamIO) - goto err; - - switch (cmd) { - - case 0: - pmem = apbs[IndexCard].RamIO; - for (i = 0; i < sizeof(struct st_ram_io); i++) - ((unsigned char *)adgl)[i]=readb(pmem++); - if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) - ret = -EFAULT; - break; - case 1: - pmem = apbs[IndexCard].RamIO + CONF_END_TEST; - for (i = 0; i < 4; i++) - adgl->conf_end_test[i] = readb(pmem++); - for (i = 0; i < 2; i++) - adgl->error_code[i] = readb(pmem++); - for (i = 0; i < 4; i++) - adgl->parameter_error[i] = readb(pmem++); - pmem = apbs[IndexCard].RamIO + VERS; - adgl->vers = readb(pmem); - pmem = apbs[IndexCard].RamIO + TYPE_CARD; - for (i = 0; i < 20; i++) - adgl->reserv1[i] = readb(pmem++); - *(int *)&adgl->reserv1[20] = - (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + - (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + - (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) ); - - if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) - ret = -EFAULT; - break; - case 2: - pmem = apbs[IndexCard].RamIO + CONF_END_TEST; - for (i = 0; i < 10; i++) - writeb(0xff, pmem++); - writeb(adgl->data_from_pc_ready, - apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - - writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - - for (i = 0; i < MAX_BOARD; i++) { - if (apbs[i].RamIO) { - byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC); - } - } - break; - case 3: - pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC; - writeb(adgl->tic_des_from_pc, pmem); - break; - case 4: - pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC; - adgl->tic_owner_to_pc = readb(pmem++); - adgl->numcard_owner_to_pc = readb(pmem); - if (copy_to_user(argp, adgl,sizeof(struct st_ram_io))) - ret = -EFAULT; - break; - case 5: - writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); - writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); - writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); - writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - break; - case 6: - printk(KERN_INFO "APPLICOM driver release .... V2.8.0 ($Revision: 1.30 $)\n"); - printk(KERN_INFO "Number of installed boards . %d\n", (int) numboards); - printk(KERN_INFO "Segment of board ........... %X\n", (int) mem); - printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int) irq); - for (i = 0; i < MAX_BOARD; i++) { - int serial; - char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1]; - - if (!apbs[i].RamIO) - continue; - - for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) - boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); - boardname[serial] = 0; - - printk(KERN_INFO "Prom version board %d ....... V%d.%d %s", - i+1, - (int)(readb(apbs[i].RamIO + VERS) >> 4), - (int)(readb(apbs[i].RamIO + VERS) & 0xF), - boardname); - - - serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + - (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) ); - - if (serial != 0) - printk(" S/N %d\n", serial); - else - printk("\n"); - } - if (DeviceErrorCount != 0) - printk(KERN_INFO "DeviceErrorCount ........... %d\n", DeviceErrorCount); - if (ReadErrorCount != 0) - printk(KERN_INFO "ReadErrorCount ............. %d\n", ReadErrorCount); - if (WriteErrorCount != 0) - printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount); - if (waitqueue_active(&FlagSleepRec)) - printk(KERN_INFO "Process in read pending\n"); - for (i = 0; i < MAX_BOARD; i++) { - if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend)) - printk(KERN_INFO "Process in write pending board %d\n",i+1); - } - break; - default: - ret = -ENOTTY; - break; - } - - if (cmd != 6) - Dummy = readb(apbs[IndexCard].RamIO + VERS); - - kfree(adgl); - mutex_unlock(&ac_mutex); - return ret; - -err: - if (warncount) { - pr_warn("APPLICOM driver IOCTL, bad board number %d\n", - (int)IndexCard + 1); - warncount--; - } - kfree(adgl); - mutex_unlock(&ac_mutex); - return -EINVAL; - -} - diff --git a/drivers/char/applicom.h b/drivers/char/applicom.h deleted file mode 100644 index 282e08f159d5..000000000000 --- a/drivers/char/applicom.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* $Id: applicom.h,v 1.2 1999/08/28 15:09:49 dwmw2 Exp $ */ - - -#ifndef __LINUX_APPLICOM_H__ -#define __LINUX_APPLICOM_H__ - - -#define DATA_TO_PC_READY 0x00 -#define TIC_OWNER_TO_PC 0x01 -#define NUMCARD_OWNER_TO_PC 0x02 -#define TIC_DES_TO_PC 0x03 -#define NUMCARD_DES_TO_PC 0x04 -#define DATA_FROM_PC_READY 0x05 -#define TIC_OWNER_FROM_PC 0x06 -#define NUMCARD_OWNER_FROM_PC 0x07 -#define TIC_DES_FROM_PC 0x08 -#define NUMCARD_DES_FROM_PC 0x09 -#define ACK_FROM_PC_READY 0x0E -#define TIC_ACK_FROM_PC 0x0F -#define NUMCARD_ACK_FROM_PC 0x010 -#define TYP_ACK_FROM_PC 0x011 -#define CONF_END_TEST 0x012 -#define ERROR_CODE 0x016 -#define PARAMETER_ERROR 0x018 -#define VERS 0x01E -#define RAM_TO_PC 0x040 -#define RAM_FROM_PC 0x0170 -#define TYPE_CARD 0x03C0 -#define SERIAL_NUMBER 0x03DA -#define RAM_IT_FROM_PC 0x03FE -#define RAM_IT_TO_PC 0x03FF - -struct mailbox{ - u16 stjb_codef; /* offset 00 */ - s16 stjb_status; /* offset 02 */ - u16 stjb_ticuser_root; /* offset 04 */ - u8 stjb_piduser[4]; /* offset 06 */ - u16 stjb_mode; /* offset 0A */ - u16 stjb_time; /* offset 0C */ - u16 stjb_stop; /* offset 0E */ - u16 stjb_nfonc; /* offset 10 */ - u16 stjb_ncard; /* offset 12 */ - u16 stjb_nchan; /* offset 14 */ - u16 stjb_nes; /* offset 16 */ - u16 stjb_nb; /* offset 18 */ - u16 stjb_typvar; /* offset 1A */ - u32 stjb_adr; /* offset 1C */ - u16 stjb_ticuser_dispcyc; /* offset 20 */ - u16 stjb_ticuser_protocol; /* offset 22 */ - u8 stjb_filler[12]; /* offset 24 */ - u8 stjb_data[256]; /* offset 30 */ - }; - -struct st_ram_io -{ - unsigned char data_to_pc_ready; - unsigned char tic_owner_to_pc; - unsigned char numcard_owner_to_pc; - unsigned char tic_des_to_pc; - unsigned char numcard_des_to_pc; - unsigned char data_from_pc_ready; - unsigned char tic_owner_from_pc; - unsigned char numcard_owner_from_pc; - unsigned char tic_des_from_pc; - unsigned char numcard_des_from_pc; - unsigned char ack_to_pc_ready; - unsigned char tic_ack_to_pc; - unsigned char numcard_ack_to_pc; - unsigned char typ_ack_to_pc; - unsigned char ack_from_pc_ready; - unsigned char tic_ack_from_pc; - unsigned char numcard_ack_from_pc; - unsigned char typ_ack_from_pc; - unsigned char conf_end_test[4]; - unsigned char error_code[2]; - unsigned char parameter_error[4]; - unsigned char time_base; - unsigned char nul_inc; - unsigned char vers; - unsigned char num_card; - unsigned char reserv1[32]; -}; - - -#endif /* __LINUX_APPLICOM_H__ */ diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c deleted file mode 100644 index 16618079298a..000000000000 --- a/drivers/char/dtlk.c +++ /dev/null @@ -1,663 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -*- linux-c -*- - * dtlk.c - DoubleTalk PC driver for Linux - * - * Original author: Chris Pallotta - * Current maintainer: Jim Van Zandt - * - * 2000-03-18 Jim Van Zandt: Fix polling. - * Eliminate dtlk_timer_active flag and separate dtlk_stop_timer - * function. Don't restart timer in dtlk_timer_tick. Restart timer - * in dtlk_poll after every poll. dtlk_poll returns mask (duh). - * Eliminate unused function dtlk_write_byte. Misc. code cleanups. - */ - -/* This driver is for the DoubleTalk PC, a speech synthesizer - manufactured by RC Systems (http://www.rcsys.com/). It was written - based on documentation in their User's Manual file and Developer's - Tools disk. - - The DoubleTalk PC contains four voice synthesizers: text-to-speech - (TTS), linear predictive coding (LPC), PCM/ADPCM, and CVSD. It - also has a tone generator. Output data for LPC are written to the - LPC port, and output data for the other modes are written to the - TTS port. - - Two kinds of data can be read from the DoubleTalk: status - information (in response to the "\001?" interrogation command) is - read from the TTS port, and index markers (which mark the progress - of the speech) are read from the LPC port. Not all models of the - DoubleTalk PC implement index markers. Both the TTS and LPC ports - can also display status flags. - - The DoubleTalk PC generates no interrupts. - - These characteristics are mapped into the Unix stream I/O model as - follows: - - "write" sends bytes to the TTS port. It is the responsibility of - the user program to switch modes among TTS, PCM/ADPCM, and CVSD. - This driver was written for use with the text-to-speech - synthesizer. If LPC output is needed some day, other minor device - numbers can be used to select among output modes. - - "read" gets index markers from the LPC port. If the device does - not implement index markers, the read will fail with error EINVAL. - - Status information is available using the DTLK_INTERROGATE ioctl. - - */ - -#include - -#define KERNEL -#include -#include -#include -#include /* for -EBUSY */ -#include /* for request_region */ -#include /* for loops_per_jiffy */ -#include -#include -#include /* for inb_p, outb_p, inb, outb, etc. */ -#include /* for get_user, etc. */ -#include /* for wait_queue */ -#include /* for __init, module_{init,exit} */ -#include /* for EPOLLIN, etc. */ -#include /* local header file for DoubleTalk values */ - -#ifdef TRACING -#define TRACE_TEXT(str) printk(str); -#define TRACE_RET printk(")") -#else /* !TRACING */ -#define TRACE_TEXT(str) ((void) 0) -#define TRACE_RET ((void) 0) -#endif /* TRACING */ - -static DEFINE_MUTEX(dtlk_mutex); -static void dtlk_timer_tick(struct timer_list *unused); - -static int dtlk_major; -static int dtlk_port_lpc; -static int dtlk_port_tts; -static int dtlk_busy; -static int dtlk_has_indexing; -static unsigned int dtlk_portlist[] = -{0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0}; -static wait_queue_head_t dtlk_process_list; -static DEFINE_TIMER(dtlk_timer, dtlk_timer_tick); - -/* prototypes for file_operations struct */ -static ssize_t dtlk_read(struct file *, char __user *, - size_t nbytes, loff_t * ppos); -static ssize_t dtlk_write(struct file *, const char __user *, - size_t nbytes, loff_t * ppos); -static __poll_t dtlk_poll(struct file *, poll_table *); -static int dtlk_open(struct inode *, struct file *); -static int dtlk_release(struct inode *, struct file *); -static long dtlk_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); - -static const struct file_operations dtlk_fops = -{ - .owner = THIS_MODULE, - .read = dtlk_read, - .write = dtlk_write, - .poll = dtlk_poll, - .unlocked_ioctl = dtlk_ioctl, - .open = dtlk_open, - .release = dtlk_release, -}; - -/* local prototypes */ -static int dtlk_dev_probe(void); -static struct dtlk_settings *dtlk_interrogate(void); -static int dtlk_readable(void); -static char dtlk_read_lpc(void); -static char dtlk_read_tts(void); -static int dtlk_writeable(void); -static char dtlk_write_bytes(const char *buf, int n); -static char dtlk_write_tts(char); -/* - static void dtlk_handle_error(char, char, unsigned int); - */ - -static ssize_t dtlk_read(struct file *file, char __user *buf, - size_t count, loff_t * ppos) -{ - unsigned int minor = iminor(file_inode(file)); - char ch; - int i = 0, retries; - - TRACE_TEXT("(dtlk_read"); - /* printk("DoubleTalk PC - dtlk_read()\n"); */ - - if (minor != DTLK_MINOR || !dtlk_has_indexing) - return -EINVAL; - - for (retries = 0; retries < loops_per_jiffy; retries++) { - while (i < count && dtlk_readable()) { - ch = dtlk_read_lpc(); - /* printk("dtlk_read() reads 0x%02x\n", ch); */ - if (put_user(ch, buf++)) - return -EFAULT; - i++; - } - if (i) - return i; - if (file->f_flags & O_NONBLOCK) - break; - msleep_interruptible(100); - } - if (retries == loops_per_jiffy) - printk(KERN_ERR "dtlk_read times out\n"); - TRACE_RET; - return -EAGAIN; -} - -static ssize_t dtlk_write(struct file *file, const char __user *buf, - size_t count, loff_t * ppos) -{ - int i = 0, retries = 0, ch; - - TRACE_TEXT("(dtlk_write"); -#ifdef TRACING - printk(" \""); - { - int i, ch; - for (i = 0; i < count; i++) { - if (get_user(ch, buf + i)) - return -EFAULT; - if (' ' <= ch && ch <= '~') - printk("%c", ch); - else - printk("\\%03o", ch); - } - printk("\""); - } -#endif - - if (iminor(file_inode(file)) != DTLK_MINOR) - return -EINVAL; - - while (1) { - while (i < count && !get_user(ch, buf) && - (ch == DTLK_CLEAR || dtlk_writeable())) { - dtlk_write_tts(ch); - buf++; - i++; - if (i % 5 == 0) - /* We yield our time until scheduled - again. This reduces the transfer - rate to 500 bytes/sec, but that's - still enough to keep up with the - speech synthesizer. */ - msleep_interruptible(1); - else { - /* the RDY bit goes zero 2-3 usec - after writing, and goes 1 again - 180-190 usec later. Here, we wait - up to 250 usec for the RDY bit to - go nonzero. */ - for (retries = 0; - retries < loops_per_jiffy / (4000/HZ); - retries++) - if (inb_p(dtlk_port_tts) & - TTS_WRITABLE) - break; - } - retries = 0; - } - if (i == count) - return i; - if (file->f_flags & O_NONBLOCK) - break; - - msleep_interruptible(1); - - if (++retries > 10 * HZ) { /* wait no more than 10 sec - from last write */ - printk("dtlk: write timeout. " - "inb_p(dtlk_port_tts) = 0x%02x\n", - inb_p(dtlk_port_tts)); - TRACE_RET; - return -EBUSY; - } - } - TRACE_RET; - return -EAGAIN; -} - -static __poll_t dtlk_poll(struct file *file, poll_table * wait) -{ - __poll_t mask = 0; - unsigned long expires; - - TRACE_TEXT(" dtlk_poll"); - /* - static long int j; - printk("."); - printk("<%ld>", jiffies-j); - j=jiffies; - */ - poll_wait(file, &dtlk_process_list, wait); - - if (dtlk_has_indexing && dtlk_readable()) { - timer_delete(&dtlk_timer); - mask = EPOLLIN | EPOLLRDNORM; - } - if (dtlk_writeable()) { - timer_delete(&dtlk_timer); - mask |= EPOLLOUT | EPOLLWRNORM; - } - /* there are no exception conditions */ - - /* There won't be any interrupts, so we set a timer instead. */ - expires = jiffies + 3*HZ / 100; - mod_timer(&dtlk_timer, expires); - - return mask; -} - -static void dtlk_timer_tick(struct timer_list *unused) -{ - TRACE_TEXT(" dtlk_timer_tick"); - wake_up_interruptible(&dtlk_process_list); -} - -static long dtlk_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - char __user *argp = (char __user *)arg; - struct dtlk_settings *sp; - char portval; - TRACE_TEXT(" dtlk_ioctl"); - - switch (cmd) { - - case DTLK_INTERROGATE: - mutex_lock(&dtlk_mutex); - sp = dtlk_interrogate(); - mutex_unlock(&dtlk_mutex); - if (copy_to_user(argp, sp, sizeof(struct dtlk_settings))) - return -EINVAL; - return 0; - - case DTLK_STATUS: - portval = inb_p(dtlk_port_tts); - return put_user(portval, argp); - - default: - return -EINVAL; - } -} - -/* Note that nobody ever sets dtlk_busy... */ -static int dtlk_open(struct inode *inode, struct file *file) -{ - TRACE_TEXT("(dtlk_open"); - - switch (iminor(inode)) { - case DTLK_MINOR: - if (dtlk_busy) - return -EBUSY; - return stream_open(inode, file); - - default: - return -ENXIO; - } -} - -static int dtlk_release(struct inode *inode, struct file *file) -{ - TRACE_TEXT("(dtlk_release"); - - switch (iminor(inode)) { - case DTLK_MINOR: - break; - - default: - break; - } - TRACE_RET; - - timer_delete_sync(&dtlk_timer); - - return 0; -} - -static int __init dtlk_init(void) -{ - int err; - - dtlk_port_lpc = 0; - dtlk_port_tts = 0; - dtlk_busy = 0; - dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops); - if (dtlk_major < 0) { - printk(KERN_ERR "DoubleTalk PC - cannot register device\n"); - return dtlk_major; - } - err = dtlk_dev_probe(); - if (err) { - unregister_chrdev(dtlk_major, "dtlk"); - return err; - } - printk(", MAJOR %d\n", dtlk_major); - - init_waitqueue_head(&dtlk_process_list); - - return 0; -} - -static void __exit dtlk_cleanup (void) -{ - dtlk_write_bytes("goodbye", 8); - msleep_interruptible(500); /* nap 0.50 sec but - could be awakened - earlier by - signals... */ - - dtlk_write_tts(DTLK_CLEAR); - unregister_chrdev(dtlk_major, "dtlk"); - release_region(dtlk_port_lpc, DTLK_IO_EXTENT); -} - -module_init(dtlk_init); -module_exit(dtlk_cleanup); - -/* ------------------------------------------------------------------------ */ - -static int dtlk_readable(void) -{ -#ifdef TRACING - printk(" dtlk_readable=%u@%u", inb_p(dtlk_port_lpc) != 0x7f, jiffies); -#endif - return inb_p(dtlk_port_lpc) != 0x7f; -} - -static int dtlk_writeable(void) -{ - /* TRACE_TEXT(" dtlk_writeable"); */ -#ifdef TRACINGMORE - printk(" dtlk_writeable=%u", (inb_p(dtlk_port_tts) & TTS_WRITABLE)!=0); -#endif - return inb_p(dtlk_port_tts) & TTS_WRITABLE; -} - -static int __init dtlk_dev_probe(void) -{ - unsigned int testval = 0; - int i = 0; - struct dtlk_settings *sp; - - if (dtlk_port_lpc | dtlk_port_tts) - return -EBUSY; - - for (i = 0; dtlk_portlist[i]; i++) { -#if 0 - printk("DoubleTalk PC - Port %03x = %04x\n", - dtlk_portlist[i], (testval = inw_p(dtlk_portlist[i]))); -#endif - - if (!request_region(dtlk_portlist[i], DTLK_IO_EXTENT, - "dtlk")) - continue; - testval = inw_p(dtlk_portlist[i]); - if ((testval &= 0xfbff) == 0x107f) { - dtlk_port_lpc = dtlk_portlist[i]; - dtlk_port_tts = dtlk_port_lpc + 1; - - sp = dtlk_interrogate(); - printk("DoubleTalk PC at %03x-%03x, " - "ROM version %s, serial number %u", - dtlk_portlist[i], dtlk_portlist[i] + - DTLK_IO_EXTENT - 1, - sp->rom_version, sp->serial_number); - - /* put LPC port into known state, so - dtlk_readable() gives valid result */ - outb_p(0xff, dtlk_port_lpc); - - /* INIT string and index marker */ - dtlk_write_bytes("\036\1@\0\0012I\r", 8); - /* posting an index takes 18 msec. Here, we - wait up to 100 msec to see whether it - appears. */ - msleep_interruptible(100); - dtlk_has_indexing = dtlk_readable(); -#ifdef TRACING - printk(", indexing %d\n", dtlk_has_indexing); -#endif -#ifdef INSCOPE - { -/* This macro records ten samples read from the LPC port, for later display */ -#define LOOK \ -for (i = 0; i < 10; i++) \ - { \ - buffer[b++] = inb_p(dtlk_port_lpc); \ - __delay(loops_per_jiffy/(1000000/HZ)); \ - } - char buffer[1000]; - int b = 0, i, j; - - LOOK - outb_p(0xff, dtlk_port_lpc); - buffer[b++] = 0; - LOOK - dtlk_write_bytes("\0012I\r", 4); - buffer[b++] = 0; - __delay(50 * loops_per_jiffy / (1000/HZ)); - outb_p(0xff, dtlk_port_lpc); - buffer[b++] = 0; - LOOK - - printk("\n"); - for (j = 0; j < b; j++) - printk(" %02x", buffer[j]); - printk("\n"); - } -#endif /* INSCOPE */ - -#ifdef OUTSCOPE - { -/* This macro records ten samples read from the TTS port, for later display */ -#define LOOK \ -for (i = 0; i < 10; i++) \ - { \ - buffer[b++] = inb_p(dtlk_port_tts); \ - __delay(loops_per_jiffy/(1000000/HZ)); /* 1 us */ \ - } - char buffer[1000]; - int b = 0, i, j; - - mdelay(10); /* 10 ms */ - LOOK - outb_p(0x03, dtlk_port_tts); - buffer[b++] = 0; - LOOK - LOOK - - printk("\n"); - for (j = 0; j < b; j++) - printk(" %02x", buffer[j]); - printk("\n"); - } -#endif /* OUTSCOPE */ - - dtlk_write_bytes("Double Talk found", 18); - - return 0; - } - release_region(dtlk_portlist[i], DTLK_IO_EXTENT); - } - - printk(KERN_INFO "DoubleTalk PC - not found\n"); - return -ENODEV; -} - -/* - static void dtlk_handle_error(char op, char rc, unsigned int minor) - { - printk(KERN_INFO"\nDoubleTalk PC - MINOR: %d, OPCODE: %d, ERROR: %d\n", - minor, op, rc); - return; - } - */ - -/* interrogate the DoubleTalk PC and return its settings */ -static struct dtlk_settings *dtlk_interrogate(void) -{ - unsigned char *t; - static char buf[sizeof(struct dtlk_settings) + 1]; - int total, i; - static struct dtlk_settings status; - TRACE_TEXT("(dtlk_interrogate"); - dtlk_write_bytes("\030\001?", 3); - for (total = 0, i = 0; i < 50; i++) { - buf[total] = dtlk_read_tts(); - if (total > 2 && buf[total] == 0x7f) - break; - if (total < sizeof(struct dtlk_settings)) - total++; - } - /* - if (i==50) printk("interrogate() read overrun\n"); - for (i=0; i DTLK_MAX_RETRIES) - printk(KERN_ERR "dtlk_read_tts() timeout\n"); - - ch = inb_p(dtlk_port_tts); /* input from TTS port */ - ch &= 0x7f; - outb_p(ch, dtlk_port_tts); - - retries = 0; - do { - portval = inb_p(dtlk_port_tts); - } while ((portval & TTS_READABLE) != 0 && - retries++ < DTLK_MAX_RETRIES); - if (retries > DTLK_MAX_RETRIES) - printk(KERN_ERR "dtlk_read_tts() timeout\n"); - - TRACE_RET; - return ch; -} - -static char dtlk_read_lpc(void) -{ - int retries = 0; - char ch; - TRACE_TEXT("(dtlk_read_lpc"); - - /* no need to test -- this is only called when the port is readable */ - - ch = inb_p(dtlk_port_lpc); /* input from LPC port */ - - outb_p(0xff, dtlk_port_lpc); - - /* acknowledging a read takes 3-4 - usec. Here, we wait up to 20 usec - for the acknowledgement */ - retries = (loops_per_jiffy * 20) / (1000000/HZ); - while (inb_p(dtlk_port_lpc) != 0x7f && --retries > 0); - if (retries == 0) - printk(KERN_ERR "dtlk_read_lpc() timeout\n"); - - TRACE_RET; - return ch; -} - -/* write n bytes to tts port */ -static char dtlk_write_bytes(const char *buf, int n) -{ - char val = 0; - /* printk("dtlk_write_bytes(\"%-*s\", %d)\n", n, buf, n); */ - TRACE_TEXT("(dtlk_write_bytes"); - while (n-- > 0) - val = dtlk_write_tts(*buf++); - TRACE_RET; - return val; -} - -static char dtlk_write_tts(char ch) -{ - int retries = 0; -#ifdef TRACINGMORE - printk(" dtlk_write_tts("); - if (' ' <= ch && ch <= '~') - printk("'%c'", ch); - else - printk("0x%02x", ch); -#endif - if (ch != DTLK_CLEAR) /* no flow control for CLEAR command */ - while ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0 && - retries++ < DTLK_MAX_RETRIES) /* DT ready? */ - ; - if (retries > DTLK_MAX_RETRIES) - printk(KERN_ERR "dtlk_write_tts() timeout\n"); - - outb_p(ch, dtlk_port_tts); /* output to TTS port */ - /* the RDY bit goes zero 2-3 usec after writing, and goes - 1 again 180-190 usec later. Here, we wait up to 10 - usec for the RDY bit to go zero. */ - for (retries = 0; retries < loops_per_jiffy / (100000/HZ); retries++) - if ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0) - break; - -#ifdef TRACINGMORE - printk(")\n"); -#endif - return 0; -} - -MODULE_DESCRIPTION("RC Systems DoubleTalk PC speech card driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 46c84e5df00f..285c6037417a 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -976,10 +976,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) static int hpet_acpi_probe(struct platform_device *pdev) { - struct acpi_device *device = ACPI_COMPANION(&pdev->dev); + struct acpi_device *device; acpi_status result; struct hpet_data data; + device = ACPI_COMPANION(&pdev->dev); + if (!device) + return -ENODEV; + memset(&data, 0, sizeof(data)); result = diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 9eff426a9286..e89cc1f1c89e 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -53,7 +53,6 @@ #include #endif -static DEFINE_MUTEX(nvram_mutex); static DEFINE_SPINLOCK(nvram_state_lock); static int nvram_open_cnt; /* #times opened */ static int nvram_open_mode; /* special open modes */ @@ -310,11 +309,8 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, break; #ifdef CONFIG_PPC32 case IOC_NVRAM_SYNC: - if (ppc_md.nvram_sync != NULL) { - mutex_lock(&nvram_mutex); + if (ppc_md.nvram_sync) ppc_md.nvram_sync(); - mutex_unlock(&nvram_mutex); - } ret = 0; break; #endif @@ -324,11 +320,8 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (arch_nvram_ops.initialize != NULL) { - mutex_lock(&nvram_mutex); + if (arch_nvram_ops.initialize) ret = arch_nvram_ops.initialize(); - mutex_unlock(&nvram_mutex); - } break; case NVRAM_SETCKS: /* just set checksum, contents unchanged (maybe useful after @@ -336,11 +329,8 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (arch_nvram_ops.set_checksum != NULL) { - mutex_lock(&nvram_mutex); + if (arch_nvram_ops.set_checksum) ret = arch_nvram_ops.set_checksum(); - mutex_unlock(&nvram_mutex); - } break; #endif /* CONFIG_X86 || CONFIG_M68K */ } diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index ccda997a9098..24c1b26f34d6 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1117,7 +1117,11 @@ static int sonypi_disable(void) #ifdef CONFIG_ACPI static int sonypi_acpi_probe(struct platform_device *pdev) { - struct acpi_device *device = ACPI_COMPANION(&pdev->dev); + struct acpi_device *device; + + device = ACPI_COMPANION(&pdev->dev); + if (!device) + return -ENODEV; sonypi_acpi_device = device; strcpy(acpi_device_name(device), "Sony laptop hotkeys"); diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 677d230a226c..dd45fe5eb6f2 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -264,6 +264,7 @@ static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, } static const struct file_operations tlclk_fops = { + .owner = THIS_MODULE, .read = tlclk_read, .open = tlclk_open, .release = tlclk_release, @@ -837,6 +838,9 @@ static void __exit tlclk_cleanup(void) misc_deregister(&tlclk_miscdev); unregister_chrdev(tlclk_major, "telco_clock"); + got_event = 1; + wake_up_all(&wq); + release_region(TLCLK_BASE, 8); timer_delete_sync(&switchover_timer); kfree(alarm_events); diff --git a/drivers/comedi/drivers/8255_pci.c b/drivers/comedi/drivers/8255_pci.c index 8498cabe4d91..737e4cf45571 100644 --- a/drivers/comedi/drivers/8255_pci.c +++ b/drivers/comedi/drivers/8255_pci.c @@ -267,25 +267,25 @@ static int pci_8255_pci_probe(struct pci_dev *dev, static const struct pci_device_id pci_8255_pci_table[] = { #ifdef CONFIG_HAS_IOPORT - { PCI_VDEVICE(ADLINK, 0x7224), BOARD_ADLINK_PCI7224 }, - { PCI_VDEVICE(ADLINK, 0x7248), BOARD_ADLINK_PCI7248 }, - { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 }, - { PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 }, - { PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, 0x0000, 0x0000), + { PCI_VDEVICE(ADLINK, 0x7224), .driver_data = BOARD_ADLINK_PCI7224 }, + { PCI_VDEVICE(ADLINK, 0x7248), .driver_data = BOARD_ADLINK_PCI7248 }, + { PCI_VDEVICE(ADLINK, 0x7296), .driver_data = BOARD_ADLINK_PCI7296 }, + { PCI_VDEVICE(CB, 0x0028), .driver_data = BOARD_CB_PCIDIO24 }, + { PCI_VDEVICE(CB, 0x0014), .driver_data = BOARD_CB_PCIDIO24H }, + { PCI_VDEVICE_SUB(CB, 0x000b, 0x0000, 0x0000), .driver_data = BOARD_CB_PCIDIO48H_OLD }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b), + { PCI_VDEVICE_SUB(CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b), .driver_data = BOARD_CB_PCIDIO48H_NEW }, - { PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H }, + { PCI_VDEVICE(CB, 0x0017), .driver_data = BOARD_CB_PCIDIO96H }, #endif /* CONFIG_HAS_IOPORT */ - { PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 }, - { PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B }, - { PCI_VDEVICE(NI, 0x13c0), BOARD_NI_PXI6508 }, - { PCI_VDEVICE(NI, 0x0400), BOARD_NI_PCI6503 }, - { PCI_VDEVICE(NI, 0x1250), BOARD_NI_PCI6503B }, - { PCI_VDEVICE(NI, 0x17d0), BOARD_NI_PCI6503X }, - { PCI_VDEVICE(NI, 0x1800), BOARD_NI_PXI_6503 }, - { 0 } + { PCI_VDEVICE(NI, 0x0160), .driver_data = BOARD_NI_PCIDIO96 }, + { PCI_VDEVICE(NI, 0x1630), .driver_data = BOARD_NI_PCIDIO96B }, + { PCI_VDEVICE(NI, 0x13c0), .driver_data = BOARD_NI_PXI6508 }, + { PCI_VDEVICE(NI, 0x0400), .driver_data = BOARD_NI_PCI6503 }, + { PCI_VDEVICE(NI, 0x1250), .driver_data = BOARD_NI_PCI6503B }, + { PCI_VDEVICE(NI, 0x17d0), .driver_data = BOARD_NI_PCI6503X }, + { PCI_VDEVICE(NI, 0x1800), .driver_data = BOARD_NI_PXI_6503 }, + { } }; MODULE_DEVICE_TABLE(pci, pci_8255_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_1032.c b/drivers/comedi/drivers/addi_apci_1032.c index 8eec6d9402de..9ca6980705e5 100644 --- a/drivers/comedi/drivers/addi_apci_1032.c +++ b/drivers/comedi/drivers/addi_apci_1032.c @@ -378,8 +378,8 @@ static int apci1032_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci1032_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1003) }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x1003) }, + { } }; MODULE_DEVICE_TABLE(pci, apci1032_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_1500.c b/drivers/comedi/drivers/addi_apci_1500.c index c94c78588889..a203e27888e2 100644 --- a/drivers/comedi/drivers/addi_apci_1500.c +++ b/drivers/comedi/drivers/addi_apci_1500.c @@ -869,8 +869,8 @@ static int apci1500_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci1500_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80fc) }, - { 0 } + { PCI_VDEVICE(AMCC, 0x80fc) }, + { } }; MODULE_DEVICE_TABLE(pci, apci1500_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_1516.c b/drivers/comedi/drivers/addi_apci_1516.c index 3c48b72dad9d..397f06f8858a 100644 --- a/drivers/comedi/drivers/addi_apci_1516.c +++ b/drivers/comedi/drivers/addi_apci_1516.c @@ -196,10 +196,10 @@ static int apci1516_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci1516_pci_table[] = { - { PCI_VDEVICE(ADDIDATA, 0x1000), BOARD_APCI1016 }, - { PCI_VDEVICE(ADDIDATA, 0x1001), BOARD_APCI1516 }, - { PCI_VDEVICE(ADDIDATA, 0x1002), BOARD_APCI2016 }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x1000), .driver_data = BOARD_APCI1016 }, + { PCI_VDEVICE(ADDIDATA, 0x1001), .driver_data = BOARD_APCI1516 }, + { PCI_VDEVICE(ADDIDATA, 0x1002), .driver_data = BOARD_APCI2016 }, + { } }; MODULE_DEVICE_TABLE(pci, apci1516_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_1564.c b/drivers/comedi/drivers/addi_apci_1564.c index 0cd40948bee7..a54df64afc3d 100644 --- a/drivers/comedi/drivers/addi_apci_1564.c +++ b/drivers/comedi/drivers/addi_apci_1564.c @@ -802,8 +802,8 @@ static int apci1564_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci1564_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1006) }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x1006) }, + { } }; MODULE_DEVICE_TABLE(pci, apci1564_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_16xx.c b/drivers/comedi/drivers/addi_apci_16xx.c index ec2c321d2431..87d62c65a4d2 100644 --- a/drivers/comedi/drivers/addi_apci_16xx.c +++ b/drivers/comedi/drivers/addi_apci_16xx.c @@ -158,9 +158,9 @@ static int apci16xx_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci16xx_pci_table[] = { - { PCI_VDEVICE(ADDIDATA, 0x1009), BOARD_APCI1648 }, - { PCI_VDEVICE(ADDIDATA, 0x100a), BOARD_APCI1696 }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x1009), .driver_data = BOARD_APCI1648 }, + { PCI_VDEVICE(ADDIDATA, 0x100a), .driver_data = BOARD_APCI1696 }, + { } }; MODULE_DEVICE_TABLE(pci, apci16xx_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_2032.c b/drivers/comedi/drivers/addi_apci_2032.c index d0f52d5ece8f..59bc0de4d864 100644 --- a/drivers/comedi/drivers/addi_apci_2032.c +++ b/drivers/comedi/drivers/addi_apci_2032.c @@ -312,8 +312,8 @@ static int apci2032_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci2032_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1004) }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x1004) }, + { } }; MODULE_DEVICE_TABLE(pci, apci2032_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_2200.c b/drivers/comedi/drivers/addi_apci_2200.c index 00378c9dddc8..686f6ec2cbb6 100644 --- a/drivers/comedi/drivers/addi_apci_2200.c +++ b/drivers/comedi/drivers/addi_apci_2200.c @@ -125,8 +125,8 @@ static int apci2200_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci2200_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1005) }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x1005) }, + { } }; MODULE_DEVICE_TABLE(pci, apci2200_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_3120.c b/drivers/comedi/drivers/addi_apci_3120.c index 28a242e69721..049399cf5681 100644 --- a/drivers/comedi/drivers/addi_apci_3120.c +++ b/drivers/comedi/drivers/addi_apci_3120.c @@ -1098,9 +1098,9 @@ static int apci3120_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci3120_pci_table[] = { - { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 }, - { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 }, - { 0 } + { PCI_VDEVICE(AMCC, 0x818d), .driver_data = BOARD_APCI3120 }, + { PCI_VDEVICE(AMCC, 0x828d), .driver_data = BOARD_APCI3001 }, + { } }; MODULE_DEVICE_TABLE(pci, apci3120_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_3501.c b/drivers/comedi/drivers/addi_apci_3501.c index ecb5552f1785..3bcf5c067820 100644 --- a/drivers/comedi/drivers/addi_apci_3501.c +++ b/drivers/comedi/drivers/addi_apci_3501.c @@ -399,8 +399,8 @@ static int apci3501_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci3501_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x3001) }, + { } }; MODULE_DEVICE_TABLE(pci, apci3501_pci_table); diff --git a/drivers/comedi/drivers/addi_apci_3xxx.c b/drivers/comedi/drivers/addi_apci_3xxx.c index bc72273e6a29..695cce103177 100644 --- a/drivers/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/comedi/drivers/addi_apci_3xxx.c @@ -918,32 +918,32 @@ static int apci3xxx_pci_probe(struct pci_dev *dev, } static const struct pci_device_id apci3xxx_pci_table[] = { - { PCI_VDEVICE(ADDIDATA, 0x3010), BOARD_APCI3000_16 }, - { PCI_VDEVICE(ADDIDATA, 0x300f), BOARD_APCI3000_8 }, - { PCI_VDEVICE(ADDIDATA, 0x300e), BOARD_APCI3000_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3013), BOARD_APCI3006_16 }, - { PCI_VDEVICE(ADDIDATA, 0x3014), BOARD_APCI3006_8 }, - { PCI_VDEVICE(ADDIDATA, 0x3015), BOARD_APCI3006_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3016), BOARD_APCI3010_16 }, - { PCI_VDEVICE(ADDIDATA, 0x3017), BOARD_APCI3010_8 }, - { PCI_VDEVICE(ADDIDATA, 0x3018), BOARD_APCI3010_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3019), BOARD_APCI3016_16 }, - { PCI_VDEVICE(ADDIDATA, 0x301a), BOARD_APCI3016_8 }, - { PCI_VDEVICE(ADDIDATA, 0x301b), BOARD_APCI3016_4 }, - { PCI_VDEVICE(ADDIDATA, 0x301c), BOARD_APCI3100_16_4 }, - { PCI_VDEVICE(ADDIDATA, 0x301d), BOARD_APCI3100_8_4 }, - { PCI_VDEVICE(ADDIDATA, 0x301e), BOARD_APCI3106_16_4 }, - { PCI_VDEVICE(ADDIDATA, 0x301f), BOARD_APCI3106_8_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3020), BOARD_APCI3110_16_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3021), BOARD_APCI3110_8_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3022), BOARD_APCI3116_16_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3023), BOARD_APCI3116_8_4 }, - { PCI_VDEVICE(ADDIDATA, 0x300B), BOARD_APCI3003 }, - { PCI_VDEVICE(ADDIDATA, 0x3002), BOARD_APCI3002_16 }, - { PCI_VDEVICE(ADDIDATA, 0x3003), BOARD_APCI3002_8 }, - { PCI_VDEVICE(ADDIDATA, 0x3004), BOARD_APCI3002_4 }, - { PCI_VDEVICE(ADDIDATA, 0x3024), BOARD_APCI3500 }, - { 0 } + { PCI_VDEVICE(ADDIDATA, 0x3010), .driver_data = BOARD_APCI3000_16 }, + { PCI_VDEVICE(ADDIDATA, 0x300f), .driver_data = BOARD_APCI3000_8 }, + { PCI_VDEVICE(ADDIDATA, 0x300e), .driver_data = BOARD_APCI3000_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3013), .driver_data = BOARD_APCI3006_16 }, + { PCI_VDEVICE(ADDIDATA, 0x3014), .driver_data = BOARD_APCI3006_8 }, + { PCI_VDEVICE(ADDIDATA, 0x3015), .driver_data = BOARD_APCI3006_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3016), .driver_data = BOARD_APCI3010_16 }, + { PCI_VDEVICE(ADDIDATA, 0x3017), .driver_data = BOARD_APCI3010_8 }, + { PCI_VDEVICE(ADDIDATA, 0x3018), .driver_data = BOARD_APCI3010_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3019), .driver_data = BOARD_APCI3016_16 }, + { PCI_VDEVICE(ADDIDATA, 0x301a), .driver_data = BOARD_APCI3016_8 }, + { PCI_VDEVICE(ADDIDATA, 0x301b), .driver_data = BOARD_APCI3016_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301c), .driver_data = BOARD_APCI3100_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301d), .driver_data = BOARD_APCI3100_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301e), .driver_data = BOARD_APCI3106_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301f), .driver_data = BOARD_APCI3106_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3020), .driver_data = BOARD_APCI3110_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3021), .driver_data = BOARD_APCI3110_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3022), .driver_data = BOARD_APCI3116_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3023), .driver_data = BOARD_APCI3116_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x300B), .driver_data = BOARD_APCI3003 }, + { PCI_VDEVICE(ADDIDATA, 0x3002), .driver_data = BOARD_APCI3002_16 }, + { PCI_VDEVICE(ADDIDATA, 0x3003), .driver_data = BOARD_APCI3002_8 }, + { PCI_VDEVICE(ADDIDATA, 0x3004), .driver_data = BOARD_APCI3002_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3024), .driver_data = BOARD_APCI3500 }, + { } }; MODULE_DEVICE_TABLE(pci, apci3xxx_pci_table); diff --git a/drivers/comedi/drivers/adl_pci6208.c b/drivers/comedi/drivers/adl_pci6208.c index b27354a51f5c..57d1af105d41 100644 --- a/drivers/comedi/drivers/adl_pci6208.c +++ b/drivers/comedi/drivers/adl_pci6208.c @@ -180,10 +180,9 @@ static int adl_pci6208_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adl_pci6208_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - 0x9999, 0x6208) }, - { 0 } + { PCI_VDEVICE(ADLINK, 0x6208) }, + { PCI_VDEVICE_SUB(PLX, PCI_DEVICE_ID_PLX_9050, 0x9999, 0x6208) }, + { } }; MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table); diff --git a/drivers/comedi/drivers/adl_pci7250.c b/drivers/comedi/drivers/adl_pci7250.c index 78c85a402435..b2772cf17ad2 100644 --- a/drivers/comedi/drivers/adl_pci7250.c +++ b/drivers/comedi/drivers/adl_pci7250.c @@ -194,16 +194,16 @@ static int adl_pci7250_pci_probe(struct pci_dev *dev, static const struct pci_device_id adl_pci7250_pci_table[] = { #ifdef CONFIG_HAS_IOPORT - { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - 0x9999, 0x7250) }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADLINK, 0x7250, - 0x9999, 0x7250) }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADLINK, 0x7250, - PCI_VENDOR_ID_ADLINK, 0x7250) }, + { PCI_VDEVICE_SUB(PLX, PCI_DEVICE_ID_PLX_9050, + 0x9999, 0x7250) }, + { PCI_VDEVICE_SUB(ADLINK, 0x7250, + 0x9999, 0x7250) }, + { PCI_VDEVICE_SUB(ADLINK, 0x7250, + PCI_VENDOR_ID_ADLINK, 0x7250) }, #endif - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADLINK, 0x7250, - PCI_VENDOR_ID_ADLINK, 0x7000) }, /* newer LPCIe-7250 */ - { 0 } + { PCI_VDEVICE_SUB(ADLINK, 0x7250, + PCI_VENDOR_ID_ADLINK, 0x7000) }, /* newer LPCIe-7250 */ + { } }; MODULE_DEVICE_TABLE(pci, adl_pci7250_pci_table); diff --git a/drivers/comedi/drivers/adl_pci7x3x.c b/drivers/comedi/drivers/adl_pci7x3x.c index e9f22de9b6f1..3e558a9b2ad7 100644 --- a/drivers/comedi/drivers/adl_pci7x3x.c +++ b/drivers/comedi/drivers/adl_pci7x3x.c @@ -518,13 +518,13 @@ static int adl_pci7x3x_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adl_pci7x3x_pci_table[] = { - { PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 }, - { PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 }, - { PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 }, - { PCI_VDEVICE(ADLINK, 0x7432), BOARD_PCI7432 }, - { PCI_VDEVICE(ADLINK, 0x7433), BOARD_PCI7433 }, - { PCI_VDEVICE(ADLINK, 0x7434), BOARD_PCI7434 }, - { 0 } + { PCI_VDEVICE(ADLINK, 0x7230), .driver_data = BOARD_PCI7230 }, + { PCI_VDEVICE(ADLINK, 0x7233), .driver_data = BOARD_PCI7233 }, + { PCI_VDEVICE(ADLINK, 0x7234), .driver_data = BOARD_PCI7234 }, + { PCI_VDEVICE(ADLINK, 0x7432), .driver_data = BOARD_PCI7432 }, + { PCI_VDEVICE(ADLINK, 0x7433), .driver_data = BOARD_PCI7433 }, + { PCI_VDEVICE(ADLINK, 0x7434), .driver_data = BOARD_PCI7434 }, + { } }; MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table); diff --git a/drivers/comedi/drivers/adl_pci8164.c b/drivers/comedi/drivers/adl_pci8164.c index 0c513a67a264..3b56a307a900 100644 --- a/drivers/comedi/drivers/adl_pci8164.c +++ b/drivers/comedi/drivers/adl_pci8164.c @@ -135,8 +135,8 @@ static int adl_pci8164_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adl_pci8164_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x8164) }, - { 0 } + { PCI_VDEVICE(ADLINK, 0x8164) }, + { } }; MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table); diff --git a/drivers/comedi/drivers/adl_pci9111.c b/drivers/comedi/drivers/adl_pci9111.c index 086d93f40cb9..7e8e669c21d6 100644 --- a/drivers/comedi/drivers/adl_pci9111.c +++ b/drivers/comedi/drivers/adl_pci9111.c @@ -727,9 +727,9 @@ static int pci9111_pci_probe(struct pci_dev *dev, } static const struct pci_device_id pci9111_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x9111) }, - /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */ - { 0 } + { PCI_VDEVICE(ADLINK, 0x9111) }, + /* { PCI_VDEVICE(ADLINK, PCI9111_HG_DEVICE_ID) }, */ + { } }; MODULE_DEVICE_TABLE(pci, pci9111_pci_table); diff --git a/drivers/comedi/drivers/adl_pci9118.c b/drivers/comedi/drivers/adl_pci9118.c index 67c663892e48..75c487bb2f5b 100644 --- a/drivers/comedi/drivers/adl_pci9118.c +++ b/drivers/comedi/drivers/adl_pci9118.c @@ -1715,10 +1715,10 @@ static int adl_pci9118_pci_probe(struct pci_dev *dev, /* FIXME: All the supported board types have the same device ID! */ static const struct pci_device_id adl_pci9118_pci_table[] = { - { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118DG }, -/* { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HG }, */ -/* { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HR }, */ - { 0 } + { PCI_VDEVICE(AMCC, 0x80d9), .driver_data = BOARD_PCI9118DG }, +/* { PCI_VDEVICE(AMCC, 0x80d9), .driver_data = BOARD_PCI9118HG }, */ +/* { PCI_VDEVICE(AMCC, 0x80d9), .driver_data = BOARD_PCI9118HR }, */ + { } }; MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table); diff --git a/drivers/comedi/drivers/adv_pci1710.c b/drivers/comedi/drivers/adv_pci1710.c index c49b0f1f5228..fc749241da41 100644 --- a/drivers/comedi/drivers/adv_pci1710.c +++ b/drivers/comedi/drivers/adv_pci1710.c @@ -892,60 +892,66 @@ static int adv_pci1710_pci_probe(struct pci_dev *dev, static const struct pci_device_id adv_pci1710_pci_table[] = { { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0x0000), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0x0000), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xb100), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb100), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xb200), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb200), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xc100), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc100), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xc200), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc200), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd100), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, 0x1000, 0xd100), .driver_data = BOARD_PCI1710, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0x0002), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0x0002), .driver_data = BOARD_PCI1710HG, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xb102), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb102), .driver_data = BOARD_PCI1710HG, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xb202), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb202), .driver_data = BOARD_PCI1710HG, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xc102), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc102), .driver_data = BOARD_PCI1710HG, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, - PCI_VENDOR_ID_ADVANTECH, 0xc202), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc202), .driver_data = BOARD_PCI1710HG, }, { - PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd102), + PCI_VDEVICE_SUB(ADVANTECH, 0x1710, 0x1000, 0xd102), .driver_data = BOARD_PCI1710HG, + }, { + PCI_VDEVICE(ADVANTECH, 0x1711), + .driver_data = BOARD_PCI1711, + }, { + PCI_VDEVICE(ADVANTECH, 0x1713), + .driver_data = BOARD_PCI1713, + }, { + PCI_VDEVICE(ADVANTECH, 0x1731), + .driver_data = BOARD_PCI1731, }, - { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 }, - { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 }, - { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 }, - { 0 } + { } }; MODULE_DEVICE_TABLE(pci, adv_pci1710_pci_table); diff --git a/drivers/comedi/drivers/adv_pci1720.c b/drivers/comedi/drivers/adv_pci1720.c index 2619591ba301..cc21212c5d52 100644 --- a/drivers/comedi/drivers/adv_pci1720.c +++ b/drivers/comedi/drivers/adv_pci1720.c @@ -167,8 +167,8 @@ static int adv_pci1720_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adv_pci1720_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) }, - { 0 } + { PCI_VDEVICE(ADVANTECH, 0x1720) }, + { } }; MODULE_DEVICE_TABLE(pci, adv_pci1720_pci_table); diff --git a/drivers/comedi/drivers/adv_pci1723.c b/drivers/comedi/drivers/adv_pci1723.c index e2aedb152068..e7f55251500c 100644 --- a/drivers/comedi/drivers/adv_pci1723.c +++ b/drivers/comedi/drivers/adv_pci1723.c @@ -208,8 +208,8 @@ static int adv_pci1723_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adv_pci1723_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) }, - { 0 } + { PCI_VDEVICE(ADVANTECH, 0x1723) }, + { } }; MODULE_DEVICE_TABLE(pci, adv_pci1723_pci_table); diff --git a/drivers/comedi/drivers/adv_pci1724.c b/drivers/comedi/drivers/adv_pci1724.c index bb43b7deeb56..e736f2bcdb04 100644 --- a/drivers/comedi/drivers/adv_pci1724.c +++ b/drivers/comedi/drivers/adv_pci1724.c @@ -189,8 +189,8 @@ static int adv_pci1724_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adv_pci1724_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1724) }, - { 0 } + { PCI_VDEVICE(ADVANTECH, 0x1724) }, + { } }; MODULE_DEVICE_TABLE(pci, adv_pci1724_pci_table); diff --git a/drivers/comedi/drivers/adv_pci1760.c b/drivers/comedi/drivers/adv_pci1760.c index 27f3890f471d..c9b0600be7f5 100644 --- a/drivers/comedi/drivers/adv_pci1760.c +++ b/drivers/comedi/drivers/adv_pci1760.c @@ -405,8 +405,8 @@ static int pci1760_pci_probe(struct pci_dev *dev, } static const struct pci_device_id pci1760_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) }, - { 0 } + { PCI_VDEVICE(ADVANTECH, 0x1760) }, + { } }; MODULE_DEVICE_TABLE(pci, pci1760_pci_table); diff --git a/drivers/comedi/drivers/adv_pci_dio.c b/drivers/comedi/drivers/adv_pci_dio.c index ca8054504760..49e2b2efe46d 100644 --- a/drivers/comedi/drivers/adv_pci_dio.c +++ b/drivers/comedi/drivers/adv_pci_dio.c @@ -768,21 +768,21 @@ static int adv_pci_dio_pci_probe(struct pci_dev *dev, } static const struct pci_device_id adv_pci_dio_pci_table[] = { - { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 }, - { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 }, - { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 }, - { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 }, - { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 }, - { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 }, - { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 }, - { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 }, - { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 }, - { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 }, - { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 }, - { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 }, - { PCI_VDEVICE(ADVANTECH, 0x1761), TYPE_PCI1761 }, - { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 }, - { 0 } + { PCI_VDEVICE(ADVANTECH, 0x1730), .driver_data = TYPE_PCI1730 }, + { PCI_VDEVICE(ADVANTECH, 0x1733), .driver_data = TYPE_PCI1733 }, + { PCI_VDEVICE(ADVANTECH, 0x1734), .driver_data = TYPE_PCI1734 }, + { PCI_VDEVICE(ADVANTECH, 0x1735), .driver_data = TYPE_PCI1735 }, + { PCI_VDEVICE(ADVANTECH, 0x1736), .driver_data = TYPE_PCI1736 }, + { PCI_VDEVICE(ADVANTECH, 0x1739), .driver_data = TYPE_PCI1739 }, + { PCI_VDEVICE(ADVANTECH, 0x1750), .driver_data = TYPE_PCI1750 }, + { PCI_VDEVICE(ADVANTECH, 0x1751), .driver_data = TYPE_PCI1751 }, + { PCI_VDEVICE(ADVANTECH, 0x1752), .driver_data = TYPE_PCI1752 }, + { PCI_VDEVICE(ADVANTECH, 0x1753), .driver_data = TYPE_PCI1753 }, + { PCI_VDEVICE(ADVANTECH, 0x1754), .driver_data = TYPE_PCI1754 }, + { PCI_VDEVICE(ADVANTECH, 0x1756), .driver_data = TYPE_PCI1756 }, + { PCI_VDEVICE(ADVANTECH, 0x1761), .driver_data = TYPE_PCI1761 }, + { PCI_VDEVICE(ADVANTECH, 0x1762), .driver_data = TYPE_PCI1762 }, + { } }; MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table); diff --git a/drivers/comedi/drivers/amplc_dio200_pci.c b/drivers/comedi/drivers/amplc_dio200_pci.c index cb5b328a28e3..b057bbdd0063 100644 --- a/drivers/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/comedi/drivers/amplc_dio200_pci.c @@ -394,13 +394,13 @@ static struct comedi_driver dio200_pci_comedi_driver = { static const struct pci_device_id dio200_pci_table[] = { #ifdef CONFIG_HAS_IOPORT - { PCI_VDEVICE(AMPLICON, 0x000b), pci215_model }, - { PCI_VDEVICE(AMPLICON, 0x000a), pci272_model }, + { PCI_VDEVICE(AMPLICON, 0x000b), .driver_data = pci215_model }, + { PCI_VDEVICE(AMPLICON, 0x000a), .driver_data = pci272_model }, #endif /* CONFIG_HAS_IOPORT */ - { PCI_VDEVICE(AMPLICON, 0x0011), pcie236_model }, - { PCI_VDEVICE(AMPLICON, 0x0012), pcie215_model }, - { PCI_VDEVICE(AMPLICON, 0x0014), pcie296_model }, - {0} + { PCI_VDEVICE(AMPLICON, 0x0011), .driver_data = pcie236_model }, + { PCI_VDEVICE(AMPLICON, 0x0012), .driver_data = pcie215_model }, + { PCI_VDEVICE(AMPLICON, 0x0014), .driver_data = pcie296_model }, + { } }; MODULE_DEVICE_TABLE(pci, dio200_pci_table); diff --git a/drivers/comedi/drivers/amplc_pci224.c b/drivers/comedi/drivers/amplc_pci224.c index 1373637c2ca2..55292a28f28c 100644 --- a/drivers/comedi/drivers/amplc_pci224.c +++ b/drivers/comedi/drivers/amplc_pci224.c @@ -1122,9 +1122,9 @@ static int amplc_pci224_pci_probe(struct pci_dev *dev, } static const struct pci_device_id amplc_pci224_pci_table[] = { - { PCI_VDEVICE(AMPLICON, 0x0007), pci224_model }, - { PCI_VDEVICE(AMPLICON, 0x0008), pci234_model }, - { 0 } + { PCI_VDEVICE(AMPLICON, 0x0007), .driver_data = pci224_model }, + { PCI_VDEVICE(AMPLICON, 0x0008), .driver_data = pci234_model }, + { } }; MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table); diff --git a/drivers/comedi/drivers/amplc_pci230.c b/drivers/comedi/drivers/amplc_pci230.c index c74209c2e83a..aa9c502b9429 100644 --- a/drivers/comedi/drivers/amplc_pci230.c +++ b/drivers/comedi/drivers/amplc_pci230.c @@ -2554,9 +2554,9 @@ static int amplc_pci230_pci_probe(struct pci_dev *dev, } static const struct pci_device_id amplc_pci230_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) }, - { 0 } + { PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_PCI230) }, + { PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_PCI260) }, + { } }; MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table); diff --git a/drivers/comedi/drivers/amplc_pci236.c b/drivers/comedi/drivers/amplc_pci236.c index 482eb261c333..b5d8c9e8d48a 100644 --- a/drivers/comedi/drivers/amplc_pci236.c +++ b/drivers/comedi/drivers/amplc_pci236.c @@ -116,8 +116,8 @@ static struct comedi_driver amplc_pci236_driver = { }; static const struct pci_device_id pci236_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, 0x0009) }, - { 0 } + { PCI_VDEVICE(AMPLICON, 0x0009) }, + { } }; MODULE_DEVICE_TABLE(pci, pci236_pci_table); diff --git a/drivers/comedi/drivers/amplc_pci263.c b/drivers/comedi/drivers/amplc_pci263.c index 1609665c4b18..5a248bf5a7d2 100644 --- a/drivers/comedi/drivers/amplc_pci263.c +++ b/drivers/comedi/drivers/amplc_pci263.c @@ -85,8 +85,8 @@ static struct comedi_driver amplc_pci263_driver = { }; static const struct pci_device_id pci263_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, 0x000c) }, - {0} + { PCI_VDEVICE(AMPLICON, 0x000c) }, + { } }; MODULE_DEVICE_TABLE(pci, pci263_pci_table); diff --git a/drivers/comedi/drivers/cb_pcidas.c b/drivers/comedi/drivers/cb_pcidas.c index 8bb9b0623869..bb6c32f90221 100644 --- a/drivers/comedi/drivers/cb_pcidas.c +++ b/drivers/comedi/drivers/cb_pcidas.c @@ -1474,15 +1474,15 @@ static int cb_pcidas_pci_probe(struct pci_dev *dev, } static const struct pci_device_id cb_pcidas_pci_table[] = { - { PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 }, - { PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 }, - { PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 }, - { PCI_VDEVICE(CB, 0x0019), BOARD_PCIDAS1200_JR }, - { PCI_VDEVICE(CB, 0x001c), BOARD_PCIDAS1602_16_JR }, - { PCI_VDEVICE(CB, 0x004c), BOARD_PCIDAS1000 }, - { PCI_VDEVICE(CB, 0x001a), BOARD_PCIDAS1001 }, - { PCI_VDEVICE(CB, 0x001b), BOARD_PCIDAS1002 }, - { 0 } + { PCI_VDEVICE(CB, 0x0001), .driver_data = BOARD_PCIDAS1602_16 }, + { PCI_VDEVICE(CB, 0x000f), .driver_data = BOARD_PCIDAS1200 }, + { PCI_VDEVICE(CB, 0x0010), .driver_data = BOARD_PCIDAS1602_12 }, + { PCI_VDEVICE(CB, 0x0019), .driver_data = BOARD_PCIDAS1200_JR }, + { PCI_VDEVICE(CB, 0x001c), .driver_data = BOARD_PCIDAS1602_16_JR }, + { PCI_VDEVICE(CB, 0x004c), .driver_data = BOARD_PCIDAS1000 }, + { PCI_VDEVICE(CB, 0x001a), .driver_data = BOARD_PCIDAS1001 }, + { PCI_VDEVICE(CB, 0x001b), .driver_data = BOARD_PCIDAS1002 }, + { } }; MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table); diff --git a/drivers/comedi/drivers/cb_pcidas64.c b/drivers/comedi/drivers/cb_pcidas64.c index d398c6df9482..549caadc2e8d 100644 --- a/drivers/comedi/drivers/cb_pcidas64.c +++ b/drivers/comedi/drivers/cb_pcidas64.c @@ -4074,28 +4074,28 @@ static int cb_pcidas64_pci_probe(struct pci_dev *dev, } static const struct pci_device_id cb_pcidas64_pci_table[] = { - { PCI_VDEVICE(CB, 0x001d), BOARD_PCIDAS6402_16 }, - { PCI_VDEVICE(CB, 0x001e), BOARD_PCIDAS6402_12 }, - { PCI_VDEVICE(CB, 0x0035), BOARD_PCIDAS64_M1_16 }, - { PCI_VDEVICE(CB, 0x0036), BOARD_PCIDAS64_M2_16 }, - { PCI_VDEVICE(CB, 0x0037), BOARD_PCIDAS64_M3_16 }, - { PCI_VDEVICE(CB, 0x0052), BOARD_PCIDAS4020_12 }, - { PCI_VDEVICE(CB, 0x005d), BOARD_PCIDAS6023 }, - { PCI_VDEVICE(CB, 0x005e), BOARD_PCIDAS6025 }, - { PCI_VDEVICE(CB, 0x005f), BOARD_PCIDAS6030 }, - { PCI_VDEVICE(CB, 0x0060), BOARD_PCIDAS6031 }, - { PCI_VDEVICE(CB, 0x0061), BOARD_PCIDAS6032 }, - { PCI_VDEVICE(CB, 0x0062), BOARD_PCIDAS6033 }, - { PCI_VDEVICE(CB, 0x0063), BOARD_PCIDAS6034 }, - { PCI_VDEVICE(CB, 0x0064), BOARD_PCIDAS6035 }, - { PCI_VDEVICE(CB, 0x0065), BOARD_PCIDAS6040 }, - { PCI_VDEVICE(CB, 0x0066), BOARD_PCIDAS6052 }, - { PCI_VDEVICE(CB, 0x0067), BOARD_PCIDAS6070 }, - { PCI_VDEVICE(CB, 0x0068), BOARD_PCIDAS6071 }, - { PCI_VDEVICE(CB, 0x006f), BOARD_PCIDAS6036 }, - { PCI_VDEVICE(CB, 0x0078), BOARD_PCIDAS6013 }, - { PCI_VDEVICE(CB, 0x0079), BOARD_PCIDAS6014 }, - { 0 } + { PCI_VDEVICE(CB, 0x001d), .driver_data = BOARD_PCIDAS6402_16 }, + { PCI_VDEVICE(CB, 0x001e), .driver_data = BOARD_PCIDAS6402_12 }, + { PCI_VDEVICE(CB, 0x0035), .driver_data = BOARD_PCIDAS64_M1_16 }, + { PCI_VDEVICE(CB, 0x0036), .driver_data = BOARD_PCIDAS64_M2_16 }, + { PCI_VDEVICE(CB, 0x0037), .driver_data = BOARD_PCIDAS64_M3_16 }, + { PCI_VDEVICE(CB, 0x0052), .driver_data = BOARD_PCIDAS4020_12 }, + { PCI_VDEVICE(CB, 0x005d), .driver_data = BOARD_PCIDAS6023 }, + { PCI_VDEVICE(CB, 0x005e), .driver_data = BOARD_PCIDAS6025 }, + { PCI_VDEVICE(CB, 0x005f), .driver_data = BOARD_PCIDAS6030 }, + { PCI_VDEVICE(CB, 0x0060), .driver_data = BOARD_PCIDAS6031 }, + { PCI_VDEVICE(CB, 0x0061), .driver_data = BOARD_PCIDAS6032 }, + { PCI_VDEVICE(CB, 0x0062), .driver_data = BOARD_PCIDAS6033 }, + { PCI_VDEVICE(CB, 0x0063), .driver_data = BOARD_PCIDAS6034 }, + { PCI_VDEVICE(CB, 0x0064), .driver_data = BOARD_PCIDAS6035 }, + { PCI_VDEVICE(CB, 0x0065), .driver_data = BOARD_PCIDAS6040 }, + { PCI_VDEVICE(CB, 0x0066), .driver_data = BOARD_PCIDAS6052 }, + { PCI_VDEVICE(CB, 0x0067), .driver_data = BOARD_PCIDAS6070 }, + { PCI_VDEVICE(CB, 0x0068), .driver_data = BOARD_PCIDAS6071 }, + { PCI_VDEVICE(CB, 0x006f), .driver_data = BOARD_PCIDAS6036 }, + { PCI_VDEVICE(CB, 0x0078), .driver_data = BOARD_PCIDAS6013 }, + { PCI_VDEVICE(CB, 0x0079), .driver_data = BOARD_PCIDAS6014 }, + { } }; MODULE_DEVICE_TABLE(pci, cb_pcidas64_pci_table); diff --git a/drivers/comedi/drivers/cb_pcidda.c b/drivers/comedi/drivers/cb_pcidda.c index c353d0f87da9..31f368e7c9df 100644 --- a/drivers/comedi/drivers/cb_pcidda.c +++ b/drivers/comedi/drivers/cb_pcidda.c @@ -396,13 +396,13 @@ static int cb_pcidda_pci_probe(struct pci_dev *dev, } static const struct pci_device_id cb_pcidda_pci_table[] = { - { PCI_VDEVICE(CB, 0x0020), BOARD_DDA02_12 }, - { PCI_VDEVICE(CB, 0x0021), BOARD_DDA04_12 }, - { PCI_VDEVICE(CB, 0x0022), BOARD_DDA08_12 }, - { PCI_VDEVICE(CB, 0x0023), BOARD_DDA02_16 }, - { PCI_VDEVICE(CB, 0x0024), BOARD_DDA04_16 }, - { PCI_VDEVICE(CB, 0x0025), BOARD_DDA08_16 }, - { 0 } + { PCI_VDEVICE(CB, 0x0020), .driver_data = BOARD_DDA02_12 }, + { PCI_VDEVICE(CB, 0x0021), .driver_data = BOARD_DDA04_12 }, + { PCI_VDEVICE(CB, 0x0022), .driver_data = BOARD_DDA08_12 }, + { PCI_VDEVICE(CB, 0x0023), .driver_data = BOARD_DDA02_16 }, + { PCI_VDEVICE(CB, 0x0024), .driver_data = BOARD_DDA04_16 }, + { PCI_VDEVICE(CB, 0x0025), .driver_data = BOARD_DDA08_16 }, + { } }; MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table); diff --git a/drivers/comedi/drivers/cb_pcimdas.c b/drivers/comedi/drivers/cb_pcimdas.c index 641c30df392e..ae25347d8375 100644 --- a/drivers/comedi/drivers/cb_pcimdas.c +++ b/drivers/comedi/drivers/cb_pcimdas.c @@ -455,9 +455,9 @@ static int cb_pcimdas_pci_probe(struct pci_dev *dev, } static const struct pci_device_id cb_pcimdas_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0056) }, /* PCIM-DAS1602/16 */ - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0115) }, /* PCIe-DAS1602/16 */ - { 0 } + { PCI_VDEVICE(CB, 0x0056) }, /* PCIM-DAS1602/16 */ + { PCI_VDEVICE(CB, 0x0115) }, /* PCIe-DAS1602/16 */ + { } }; MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table); diff --git a/drivers/comedi/drivers/cb_pcimdda.c b/drivers/comedi/drivers/cb_pcimdda.c index 541b5742bb1b..2f270b044b38 100644 --- a/drivers/comedi/drivers/cb_pcimdda.c +++ b/drivers/comedi/drivers/cb_pcimdda.c @@ -172,8 +172,8 @@ static int cb_pcimdda_pci_probe(struct pci_dev *dev, } static const struct pci_device_id cb_pcimdda_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_ID_PCIM_DDA06_16) }, - { 0 } + { PCI_VDEVICE(CB, PCI_ID_PCIM_DDA06_16) }, + { } }; MODULE_DEVICE_TABLE(pci, cb_pcimdda_pci_table); diff --git a/drivers/comedi/drivers/contec_pci_dio.c b/drivers/comedi/drivers/contec_pci_dio.c index 41d42ff14144..56b11a280b20 100644 --- a/drivers/comedi/drivers/contec_pci_dio.c +++ b/drivers/comedi/drivers/contec_pci_dio.c @@ -98,8 +98,8 @@ static int contec_pci_dio_pci_probe(struct pci_dev *dev, } static const struct pci_device_id contec_pci_dio_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, 0x8172) }, - { 0 } + { PCI_VDEVICE(CONTEC, 0x8172) }, + { } }; MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table); diff --git a/drivers/comedi/drivers/daqboard2000.c b/drivers/comedi/drivers/daqboard2000.c index 897bf46b95ee..f05b8d3afc54 100644 --- a/drivers/comedi/drivers/daqboard2000.c +++ b/drivers/comedi/drivers/daqboard2000.c @@ -764,11 +764,11 @@ static int db2k_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) } static const struct pci_device_id db2k_pci_table[] = { - { PCI_DEVICE_SUB(PCI_VENDOR_ID_IOTECH, 0x0409, PCI_VENDOR_ID_IOTECH, - 0x0002), .driver_data = BOARD_DAQBOARD2000, }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_IOTECH, 0x0409, PCI_VENDOR_ID_IOTECH, - 0x0004), .driver_data = BOARD_DAQBOARD2001, }, - { 0 } + { PCI_VDEVICE_SUB(IOTECH, 0x0409, PCI_VENDOR_ID_IOTECH, 0x0002), + .driver_data = BOARD_DAQBOARD2000 }, + { PCI_VDEVICE_SUB(IOTECH, 0x0409, PCI_VENDOR_ID_IOTECH, 0x0004), + .driver_data = BOARD_DAQBOARD2001 }, + { } }; MODULE_DEVICE_TABLE(pci, db2k_pci_table); diff --git a/drivers/comedi/drivers/das08_pci.c b/drivers/comedi/drivers/das08_pci.c index 982f3ab0ccbd..a439e0ddbb6d 100644 --- a/drivers/comedi/drivers/das08_pci.c +++ b/drivers/comedi/drivers/das08_pci.c @@ -77,8 +77,8 @@ static int das08_pci_probe(struct pci_dev *dev, } static const struct pci_device_id das08_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0029) }, - { 0 } + { PCI_VDEVICE(CB, 0x0029) }, + { } }; MODULE_DEVICE_TABLE(pci, das08_pci_table); diff --git a/drivers/comedi/drivers/dt3000.c b/drivers/comedi/drivers/dt3000.c index fc6e9c30e522..198aaf812747 100644 --- a/drivers/comedi/drivers/dt3000.c +++ b/drivers/comedi/drivers/dt3000.c @@ -715,14 +715,14 @@ static int dt3000_pci_probe(struct pci_dev *dev, } static const struct pci_device_id dt3000_pci_table[] = { - { PCI_VDEVICE(DT, 0x0022), BOARD_DT3001 }, - { PCI_VDEVICE(DT, 0x0023), BOARD_DT3002 }, - { PCI_VDEVICE(DT, 0x0024), BOARD_DT3003 }, - { PCI_VDEVICE(DT, 0x0025), BOARD_DT3004 }, - { PCI_VDEVICE(DT, 0x0026), BOARD_DT3005 }, - { PCI_VDEVICE(DT, 0x0027), BOARD_DT3001_PGL }, - { PCI_VDEVICE(DT, 0x0028), BOARD_DT3003_PGL }, - { 0 } + { PCI_VDEVICE(DT, 0x0022), .driver_data = BOARD_DT3001 }, + { PCI_VDEVICE(DT, 0x0023), .driver_data = BOARD_DT3002 }, + { PCI_VDEVICE(DT, 0x0024), .driver_data = BOARD_DT3003 }, + { PCI_VDEVICE(DT, 0x0025), .driver_data = BOARD_DT3004 }, + { PCI_VDEVICE(DT, 0x0026), .driver_data = BOARD_DT3005 }, + { PCI_VDEVICE(DT, 0x0027), .driver_data = BOARD_DT3001_PGL }, + { PCI_VDEVICE(DT, 0x0028), .driver_data = BOARD_DT3003_PGL }, + { } }; MODULE_DEVICE_TABLE(pci, dt3000_pci_table); diff --git a/drivers/comedi/drivers/dyna_pci10xx.c b/drivers/comedi/drivers/dyna_pci10xx.c index 407a038fb3e0..3b11bbf50648 100644 --- a/drivers/comedi/drivers/dyna_pci10xx.c +++ b/drivers/comedi/drivers/dyna_pci10xx.c @@ -246,8 +246,8 @@ static int dyna_pci10xx_pci_probe(struct pci_dev *dev, } static const struct pci_device_id dyna_pci10xx_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PLX, 0x1050) }, - { 0 } + { PCI_VDEVICE(PLX, 0x1050) }, + { } }; MODULE_DEVICE_TABLE(pci, dyna_pci10xx_pci_table); diff --git a/drivers/comedi/drivers/gsc_hpdi.c b/drivers/comedi/drivers/gsc_hpdi.c index c09d135df38d..b71abefabd96 100644 --- a/drivers/comedi/drivers/gsc_hpdi.c +++ b/drivers/comedi/drivers/gsc_hpdi.c @@ -703,9 +703,9 @@ static int gsc_hpdi_pci_probe(struct pci_dev *dev, } static const struct pci_device_id gsc_hpdi_pci_table[] = { - { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, - PCI_VENDOR_ID_PLX, 0x2400) }, - { 0 } + { PCI_VDEVICE_SUB(PLX, PCI_DEVICE_ID_PLX_9080, + PCI_VENDOR_ID_PLX, 0x2400) }, + { } }; MODULE_DEVICE_TABLE(pci, gsc_hpdi_pci_table); diff --git a/drivers/comedi/drivers/icp_multi.c b/drivers/comedi/drivers/icp_multi.c index ac4b11dbd741..2abee92bfae4 100644 --- a/drivers/comedi/drivers/icp_multi.c +++ b/drivers/comedi/drivers/icp_multi.c @@ -317,8 +317,8 @@ static int icp_multi_pci_probe(struct pci_dev *dev, } static const struct pci_device_id icp_multi_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ICP, 0x8000) }, - { 0 } + { PCI_VDEVICE(ICP, 0x8000) }, + { } }; MODULE_DEVICE_TABLE(pci, icp_multi_pci_table); diff --git a/drivers/comedi/drivers/jr3_pci.c b/drivers/comedi/drivers/jr3_pci.c index 51287cbc3e48..603e57dd2f13 100644 --- a/drivers/comedi/drivers/jr3_pci.c +++ b/drivers/comedi/drivers/jr3_pci.c @@ -779,12 +779,12 @@ static int jr3_pci_pci_probe(struct pci_dev *dev, } static const struct pci_device_id jr3_pci_pci_table[] = { - { PCI_VDEVICE(JR3, 0x1111), BOARD_JR3_1 }, - { PCI_VDEVICE(JR3, 0x3111), BOARD_JR3_1 }, - { PCI_VDEVICE(JR3, 0x3112), BOARD_JR3_2 }, - { PCI_VDEVICE(JR3, 0x3113), BOARD_JR3_3 }, - { PCI_VDEVICE(JR3, 0x3114), BOARD_JR3_4 }, - { 0 } + { PCI_VDEVICE(JR3, 0x1111), .driver_data = BOARD_JR3_1 }, + { PCI_VDEVICE(JR3, 0x3111), .driver_data = BOARD_JR3_1 }, + { PCI_VDEVICE(JR3, 0x3112), .driver_data = BOARD_JR3_2 }, + { PCI_VDEVICE(JR3, 0x3113), .driver_data = BOARD_JR3_3 }, + { PCI_VDEVICE(JR3, 0x3114), .driver_data = BOARD_JR3_4 }, + { } }; MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table); diff --git a/drivers/comedi/drivers/ke_counter.c b/drivers/comedi/drivers/ke_counter.c index b825cf60e1e0..40177ffc904d 100644 --- a/drivers/comedi/drivers/ke_counter.c +++ b/drivers/comedi/drivers/ke_counter.c @@ -213,8 +213,8 @@ static int ke_counter_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ke_counter_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, 0x0014) }, - { 0 } + { PCI_VDEVICE(KOLTER, 0x0014) }, + { } }; MODULE_DEVICE_TABLE(pci, ke_counter_pci_table); diff --git a/drivers/comedi/drivers/me4000.c b/drivers/comedi/drivers/me4000.c index effe9fdbbafe..e62f6e5eca3d 100644 --- a/drivers/comedi/drivers/me4000.c +++ b/drivers/comedi/drivers/me4000.c @@ -1254,20 +1254,20 @@ static int me4000_pci_probe(struct pci_dev *dev, } static const struct pci_device_id me4000_pci_table[] = { - { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 }, - { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 }, - { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I }, - { PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S }, - { PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS }, - { PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 }, - { PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I }, - { PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S }, - { PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS }, - { PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 }, - { PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I }, - { PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S }, - { PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS }, - { 0 } + { PCI_VDEVICE(MEILHAUS, 0x4650), .driver_data = BOARD_ME4650 }, + { PCI_VDEVICE(MEILHAUS, 0x4660), .driver_data = BOARD_ME4660 }, + { PCI_VDEVICE(MEILHAUS, 0x4661), .driver_data = BOARD_ME4660I }, + { PCI_VDEVICE(MEILHAUS, 0x4662), .driver_data = BOARD_ME4660S }, + { PCI_VDEVICE(MEILHAUS, 0x4663), .driver_data = BOARD_ME4660IS }, + { PCI_VDEVICE(MEILHAUS, 0x4670), .driver_data = BOARD_ME4670 }, + { PCI_VDEVICE(MEILHAUS, 0x4671), .driver_data = BOARD_ME4670I }, + { PCI_VDEVICE(MEILHAUS, 0x4672), .driver_data = BOARD_ME4670S }, + { PCI_VDEVICE(MEILHAUS, 0x4673), .driver_data = BOARD_ME4670IS }, + { PCI_VDEVICE(MEILHAUS, 0x4680), .driver_data = BOARD_ME4680 }, + { PCI_VDEVICE(MEILHAUS, 0x4681), .driver_data = BOARD_ME4680I }, + { PCI_VDEVICE(MEILHAUS, 0x4682), .driver_data = BOARD_ME4680S }, + { PCI_VDEVICE(MEILHAUS, 0x4683), .driver_data = BOARD_ME4680IS }, + { } }; MODULE_DEVICE_TABLE(pci, me4000_pci_table); diff --git a/drivers/comedi/drivers/me_daq.c b/drivers/comedi/drivers/me_daq.c index 2f2ea029cffc..ff8699620ec2 100644 --- a/drivers/comedi/drivers/me_daq.c +++ b/drivers/comedi/drivers/me_daq.c @@ -538,9 +538,9 @@ static int me_daq_pci_probe(struct pci_dev *dev, } static const struct pci_device_id me_daq_pci_table[] = { - { PCI_VDEVICE(MEILHAUS, 0x2600), BOARD_ME2600 }, - { PCI_VDEVICE(MEILHAUS, 0x2000), BOARD_ME2000 }, - { 0 } + { PCI_VDEVICE(MEILHAUS, 0x2600), .driver_data = BOARD_ME2600 }, + { PCI_VDEVICE(MEILHAUS, 0x2000), .driver_data = BOARD_ME2000 }, + { } }; MODULE_DEVICE_TABLE(pci, me_daq_pci_table); diff --git a/drivers/comedi/drivers/mf6x4.c b/drivers/comedi/drivers/mf6x4.c index 14f1d5e9cd59..0e63c374bc3b 100644 --- a/drivers/comedi/drivers/mf6x4.c +++ b/drivers/comedi/drivers/mf6x4.c @@ -290,9 +290,14 @@ static int mf6x4_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) } static const struct pci_device_id mf6x4_pci_table[] = { - { PCI_VDEVICE(HUMUSOFT, 0x0634), BOARD_MF634 }, - { PCI_VDEVICE(HUMUSOFT, 0x0624), BOARD_MF624 }, - { 0 } + { + PCI_VDEVICE(HUMUSOFT, 0x0634), + .driver_data = BOARD_MF634, + }, { + PCI_VDEVICE(HUMUSOFT, 0x0624), + .driver_data = BOARD_MF624, + }, + { } }; MODULE_DEVICE_TABLE(pci, mf6x4_pci_table); diff --git a/drivers/comedi/drivers/ni_6527.c b/drivers/comedi/drivers/ni_6527.c index ac5820085231..8c0d27c7f8a9 100644 --- a/drivers/comedi/drivers/ni_6527.c +++ b/drivers/comedi/drivers/ni_6527.c @@ -473,9 +473,9 @@ static int ni6527_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ni6527_pci_table[] = { - { PCI_VDEVICE(NI, 0x2b10), BOARD_PXI6527 }, - { PCI_VDEVICE(NI, 0x2b20), BOARD_PCI6527 }, - { 0 } + { PCI_VDEVICE(NI, 0x2b10), .driver_data = BOARD_PXI6527 }, + { PCI_VDEVICE(NI, 0x2b20), .driver_data = BOARD_PCI6527 }, + { } }; MODULE_DEVICE_TABLE(pci, ni6527_pci_table); diff --git a/drivers/comedi/drivers/ni_65xx.c b/drivers/comedi/drivers/ni_65xx.c index 58334de3b253..6ab91f6e75c5 100644 --- a/drivers/comedi/drivers/ni_65xx.c +++ b/drivers/comedi/drivers/ni_65xx.c @@ -783,29 +783,29 @@ static int ni_65xx_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ni_65xx_pci_table[] = { - { PCI_VDEVICE(NI, 0x1710), BOARD_PXI6509 }, - { PCI_VDEVICE(NI, 0x7085), BOARD_PCI6509 }, - { PCI_VDEVICE(NI, 0x7086), BOARD_PXI6528 }, - { PCI_VDEVICE(NI, 0x7087), BOARD_PCI6515 }, - { PCI_VDEVICE(NI, 0x7088), BOARD_PCI6514 }, - { PCI_VDEVICE(NI, 0x70a9), BOARD_PCI6528 }, - { PCI_VDEVICE(NI, 0x70c3), BOARD_PCI6511 }, - { PCI_VDEVICE(NI, 0x70c8), BOARD_PCI6513 }, - { PCI_VDEVICE(NI, 0x70c9), BOARD_PXI6515 }, - { PCI_VDEVICE(NI, 0x70cc), BOARD_PCI6512 }, - { PCI_VDEVICE(NI, 0x70cd), BOARD_PXI6514 }, - { PCI_VDEVICE(NI, 0x70d1), BOARD_PXI6513 }, - { PCI_VDEVICE(NI, 0x70d2), BOARD_PXI6512 }, - { PCI_VDEVICE(NI, 0x70d3), BOARD_PXI6511 }, - { PCI_VDEVICE(NI, 0x7124), BOARD_PCI6510 }, - { PCI_VDEVICE(NI, 0x7125), BOARD_PCI6516 }, - { PCI_VDEVICE(NI, 0x7126), BOARD_PCI6517 }, - { PCI_VDEVICE(NI, 0x7127), BOARD_PCI6518 }, - { PCI_VDEVICE(NI, 0x7128), BOARD_PCI6519 }, - { PCI_VDEVICE(NI, 0x718b), BOARD_PCI6521 }, - { PCI_VDEVICE(NI, 0x718c), BOARD_PXI6521 }, - { PCI_VDEVICE(NI, 0x71c5), BOARD_PCI6520 }, - { 0 } + { PCI_VDEVICE(NI, 0x1710), .driver_data = BOARD_PXI6509 }, + { PCI_VDEVICE(NI, 0x7085), .driver_data = BOARD_PCI6509 }, + { PCI_VDEVICE(NI, 0x7086), .driver_data = BOARD_PXI6528 }, + { PCI_VDEVICE(NI, 0x7087), .driver_data = BOARD_PCI6515 }, + { PCI_VDEVICE(NI, 0x7088), .driver_data = BOARD_PCI6514 }, + { PCI_VDEVICE(NI, 0x70a9), .driver_data = BOARD_PCI6528 }, + { PCI_VDEVICE(NI, 0x70c3), .driver_data = BOARD_PCI6511 }, + { PCI_VDEVICE(NI, 0x70c8), .driver_data = BOARD_PCI6513 }, + { PCI_VDEVICE(NI, 0x70c9), .driver_data = BOARD_PXI6515 }, + { PCI_VDEVICE(NI, 0x70cc), .driver_data = BOARD_PCI6512 }, + { PCI_VDEVICE(NI, 0x70cd), .driver_data = BOARD_PXI6514 }, + { PCI_VDEVICE(NI, 0x70d1), .driver_data = BOARD_PXI6513 }, + { PCI_VDEVICE(NI, 0x70d2), .driver_data = BOARD_PXI6512 }, + { PCI_VDEVICE(NI, 0x70d3), .driver_data = BOARD_PXI6511 }, + { PCI_VDEVICE(NI, 0x7124), .driver_data = BOARD_PCI6510 }, + { PCI_VDEVICE(NI, 0x7125), .driver_data = BOARD_PCI6516 }, + { PCI_VDEVICE(NI, 0x7126), .driver_data = BOARD_PCI6517 }, + { PCI_VDEVICE(NI, 0x7127), .driver_data = BOARD_PCI6518 }, + { PCI_VDEVICE(NI, 0x7128), .driver_data = BOARD_PCI6519 }, + { PCI_VDEVICE(NI, 0x718b), .driver_data = BOARD_PCI6521 }, + { PCI_VDEVICE(NI, 0x718c), .driver_data = BOARD_PXI6521 }, + { PCI_VDEVICE(NI, 0x71c5), .driver_data = BOARD_PCI6520 }, + { } }; MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table); diff --git a/drivers/comedi/drivers/ni_660x.c b/drivers/comedi/drivers/ni_660x.c index 0679bc39e0bc..5508cdb1b0ba 100644 --- a/drivers/comedi/drivers/ni_660x.c +++ b/drivers/comedi/drivers/ni_660x.c @@ -1230,14 +1230,14 @@ static int ni_660x_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ni_660x_pci_table[] = { - { PCI_VDEVICE(NI, 0x1310), BOARD_PCI6602 }, - { PCI_VDEVICE(NI, 0x1360), BOARD_PXI6602 }, - { PCI_VDEVICE(NI, 0x2c60), BOARD_PCI6601 }, - { PCI_VDEVICE(NI, 0x2db0), BOARD_PCI6608 }, - { PCI_VDEVICE(NI, 0x2cc0), BOARD_PXI6608 }, - { PCI_VDEVICE(NI, 0x1e30), BOARD_PCI6624 }, - { PCI_VDEVICE(NI, 0x1e40), BOARD_PXI6624 }, - { 0 } + { PCI_VDEVICE(NI, 0x1310), .driver_data = BOARD_PCI6602 }, + { PCI_VDEVICE(NI, 0x1360), .driver_data = BOARD_PXI6602 }, + { PCI_VDEVICE(NI, 0x2c60), .driver_data = BOARD_PCI6601 }, + { PCI_VDEVICE(NI, 0x2db0), .driver_data = BOARD_PCI6608 }, + { PCI_VDEVICE(NI, 0x2cc0), .driver_data = BOARD_PXI6608 }, + { PCI_VDEVICE(NI, 0x1e30), .driver_data = BOARD_PCI6624 }, + { PCI_VDEVICE(NI, 0x1e40), .driver_data = BOARD_PXI6624 }, + { } }; MODULE_DEVICE_TABLE(pci, ni_660x_pci_table); diff --git a/drivers/comedi/drivers/ni_670x.c b/drivers/comedi/drivers/ni_670x.c index 9455c2abcc24..670ffe2c744b 100644 --- a/drivers/comedi/drivers/ni_670x.c +++ b/drivers/comedi/drivers/ni_670x.c @@ -259,10 +259,10 @@ static int ni_670x_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ni_670x_pci_table[] = { - { PCI_VDEVICE(NI, 0x1290), BOARD_PCI6704 }, - { PCI_VDEVICE(NI, 0x1920), BOARD_PXI6704 }, - { PCI_VDEVICE(NI, 0x2c90), BOARD_PCI6703 }, - { 0 } + { PCI_VDEVICE(NI, 0x1290), .driver_data = BOARD_PCI6704 }, + { PCI_VDEVICE(NI, 0x1920), .driver_data = BOARD_PXI6704 }, + { PCI_VDEVICE(NI, 0x2c90), .driver_data = BOARD_PCI6703 }, + { } }; MODULE_DEVICE_TABLE(pci, ni_670x_pci_table); diff --git a/drivers/comedi/drivers/ni_labpc_pci.c b/drivers/comedi/drivers/ni_labpc_pci.c index e2a44bbd9fa6..4c8cf9776924 100644 --- a/drivers/comedi/drivers/ni_labpc_pci.c +++ b/drivers/comedi/drivers/ni_labpc_pci.c @@ -106,8 +106,8 @@ static struct comedi_driver labpc_pci_comedi_driver = { }; static const struct pci_device_id labpc_pci_table[] = { - { PCI_VDEVICE(NI, 0x161), BOARD_NI_PCI1200 }, - { 0 } + { PCI_VDEVICE(NI, 0x0161), .driver_data = BOARD_NI_PCI1200 }, + { } }; MODULE_DEVICE_TABLE(pci, labpc_pci_table); diff --git a/drivers/comedi/drivers/ni_pcidio.c b/drivers/comedi/drivers/ni_pcidio.c index 2c7bb9c1ea5b..b137bf14bcfd 100644 --- a/drivers/comedi/drivers/ni_pcidio.c +++ b/drivers/comedi/drivers/ni_pcidio.c @@ -987,10 +987,10 @@ static int ni_pcidio_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ni_pcidio_pci_table[] = { - { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS }, - { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 }, - { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 }, - { 0 } + { PCI_VDEVICE(NI, 0x1150), .driver_data = BOARD_PCIDIO_32HS }, + { PCI_VDEVICE(NI, 0x12b0), .driver_data = BOARD_PCI6534 }, + { PCI_VDEVICE(NI, 0x1320), .driver_data = BOARD_PXI6533 }, + { } }; MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table); diff --git a/drivers/comedi/drivers/ni_pcimio.c b/drivers/comedi/drivers/ni_pcimio.c index f63c390314e1..4be9ca4f4828 100644 --- a/drivers/comedi/drivers/ni_pcimio.c +++ b/drivers/comedi/drivers/ni_pcimio.c @@ -1402,72 +1402,72 @@ static int ni_pcimio_pci_probe(struct pci_dev *dev, } static const struct pci_device_id ni_pcimio_pci_table[] = { - { PCI_VDEVICE(NI, 0x0162), BOARD_PCIMIO_16XE_50 }, /* 0x1620? */ - { PCI_VDEVICE(NI, 0x1170), BOARD_PCIMIO_16XE_10 }, - { PCI_VDEVICE(NI, 0x1180), BOARD_PCIMIO_16E_1 }, - { PCI_VDEVICE(NI, 0x1190), BOARD_PCIMIO_16E_4 }, - { PCI_VDEVICE(NI, 0x11b0), BOARD_PXI6070E }, - { PCI_VDEVICE(NI, 0x11c0), BOARD_PXI6040E }, - { PCI_VDEVICE(NI, 0x11d0), BOARD_PXI6030E }, - { PCI_VDEVICE(NI, 0x1270), BOARD_PCI6032E }, - { PCI_VDEVICE(NI, 0x1330), BOARD_PCI6031E }, - { PCI_VDEVICE(NI, 0x1340), BOARD_PCI6033E }, - { PCI_VDEVICE(NI, 0x1350), BOARD_PCI6071E }, - { PCI_VDEVICE(NI, 0x14e0), BOARD_PCI6110 }, - { PCI_VDEVICE(NI, 0x14f0), BOARD_PCI6111 }, - { PCI_VDEVICE(NI, 0x1580), BOARD_PXI6031E }, - { PCI_VDEVICE(NI, 0x15b0), BOARD_PXI6071E }, - { PCI_VDEVICE(NI, 0x1880), BOARD_PCI6711 }, - { PCI_VDEVICE(NI, 0x1870), BOARD_PCI6713 }, - { PCI_VDEVICE(NI, 0x18b0), BOARD_PCI6052E }, - { PCI_VDEVICE(NI, 0x18c0), BOARD_PXI6052E }, - { PCI_VDEVICE(NI, 0x2410), BOARD_PCI6733 }, - { PCI_VDEVICE(NI, 0x2420), BOARD_PXI6733 }, - { PCI_VDEVICE(NI, 0x2430), BOARD_PCI6731 }, - { PCI_VDEVICE(NI, 0x2890), BOARD_PCI6036E }, - { PCI_VDEVICE(NI, 0x28c0), BOARD_PCI6014 }, - { PCI_VDEVICE(NI, 0x2a60), BOARD_PCI6023E }, - { PCI_VDEVICE(NI, 0x2a70), BOARD_PCI6024E }, - { PCI_VDEVICE(NI, 0x2a80), BOARD_PCI6025E }, - { PCI_VDEVICE(NI, 0x2ab0), BOARD_PXI6025E }, - { PCI_VDEVICE(NI, 0x2b80), BOARD_PXI6713 }, - { PCI_VDEVICE(NI, 0x2b90), BOARD_PXI6711 }, - { PCI_VDEVICE(NI, 0x2c80), BOARD_PCI6035E }, - { PCI_VDEVICE(NI, 0x2ca0), BOARD_PCI6034E }, - { PCI_VDEVICE(NI, 0x70aa), BOARD_PCI6229 }, - { PCI_VDEVICE(NI, 0x70ab), BOARD_PCI6259 }, - { PCI_VDEVICE(NI, 0x70ac), BOARD_PCI6289 }, - { PCI_VDEVICE(NI, 0x70ad), BOARD_PXI6251 }, - { PCI_VDEVICE(NI, 0x70ae), BOARD_PXI6220 }, - { PCI_VDEVICE(NI, 0x70af), BOARD_PCI6221 }, - { PCI_VDEVICE(NI, 0x70b0), BOARD_PCI6220 }, - { PCI_VDEVICE(NI, 0x70b1), BOARD_PXI6229 }, - { PCI_VDEVICE(NI, 0x70b2), BOARD_PXI6259 }, - { PCI_VDEVICE(NI, 0x70b3), BOARD_PXI6289 }, - { PCI_VDEVICE(NI, 0x70b4), BOARD_PCI6250 }, - { PCI_VDEVICE(NI, 0x70b5), BOARD_PXI6221 }, - { PCI_VDEVICE(NI, 0x70b6), BOARD_PCI6280 }, - { PCI_VDEVICE(NI, 0x70b7), BOARD_PCI6254 }, - { PCI_VDEVICE(NI, 0x70b8), BOARD_PCI6251 }, - { PCI_VDEVICE(NI, 0x70b9), BOARD_PXI6250 }, - { PCI_VDEVICE(NI, 0x70ba), BOARD_PXI6254 }, - { PCI_VDEVICE(NI, 0x70bb), BOARD_PXI6280 }, - { PCI_VDEVICE(NI, 0x70bc), BOARD_PCI6284 }, - { PCI_VDEVICE(NI, 0x70bd), BOARD_PCI6281 }, - { PCI_VDEVICE(NI, 0x70be), BOARD_PXI6284 }, - { PCI_VDEVICE(NI, 0x70bf), BOARD_PXI6281 }, - { PCI_VDEVICE(NI, 0x70c0), BOARD_PCI6143 }, - { PCI_VDEVICE(NI, 0x70f2), BOARD_PCI6224 }, - { PCI_VDEVICE(NI, 0x70f3), BOARD_PXI6224 }, - { PCI_VDEVICE(NI, 0x710d), BOARD_PXI6143 }, - { PCI_VDEVICE(NI, 0x716c), BOARD_PCI6225 }, - { PCI_VDEVICE(NI, 0x716d), BOARD_PXI6225 }, - { PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 }, - { PCI_VDEVICE(NI, 0x717f), BOARD_PCIE6259 }, - { PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN }, - { PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 }, - { PCI_VDEVICE(NI, 0x72e9), BOARD_PXIE6259 }, - { 0 } + { PCI_VDEVICE(NI, 0x0162), .driver_data = BOARD_PCIMIO_16XE_50 }, /* 0x1620? */ + { PCI_VDEVICE(NI, 0x1170), .driver_data = BOARD_PCIMIO_16XE_10 }, + { PCI_VDEVICE(NI, 0x1180), .driver_data = BOARD_PCIMIO_16E_1 }, + { PCI_VDEVICE(NI, 0x1190), .driver_data = BOARD_PCIMIO_16E_4 }, + { PCI_VDEVICE(NI, 0x11b0), .driver_data = BOARD_PXI6070E }, + { PCI_VDEVICE(NI, 0x11c0), .driver_data = BOARD_PXI6040E }, + { PCI_VDEVICE(NI, 0x11d0), .driver_data = BOARD_PXI6030E }, + { PCI_VDEVICE(NI, 0x1270), .driver_data = BOARD_PCI6032E }, + { PCI_VDEVICE(NI, 0x1330), .driver_data = BOARD_PCI6031E }, + { PCI_VDEVICE(NI, 0x1340), .driver_data = BOARD_PCI6033E }, + { PCI_VDEVICE(NI, 0x1350), .driver_data = BOARD_PCI6071E }, + { PCI_VDEVICE(NI, 0x14e0), .driver_data = BOARD_PCI6110 }, + { PCI_VDEVICE(NI, 0x14f0), .driver_data = BOARD_PCI6111 }, + { PCI_VDEVICE(NI, 0x1580), .driver_data = BOARD_PXI6031E }, + { PCI_VDEVICE(NI, 0x15b0), .driver_data = BOARD_PXI6071E }, + { PCI_VDEVICE(NI, 0x1880), .driver_data = BOARD_PCI6711 }, + { PCI_VDEVICE(NI, 0x1870), .driver_data = BOARD_PCI6713 }, + { PCI_VDEVICE(NI, 0x18b0), .driver_data = BOARD_PCI6052E }, + { PCI_VDEVICE(NI, 0x18c0), .driver_data = BOARD_PXI6052E }, + { PCI_VDEVICE(NI, 0x2410), .driver_data = BOARD_PCI6733 }, + { PCI_VDEVICE(NI, 0x2420), .driver_data = BOARD_PXI6733 }, + { PCI_VDEVICE(NI, 0x2430), .driver_data = BOARD_PCI6731 }, + { PCI_VDEVICE(NI, 0x2890), .driver_data = BOARD_PCI6036E }, + { PCI_VDEVICE(NI, 0x28c0), .driver_data = BOARD_PCI6014 }, + { PCI_VDEVICE(NI, 0x2a60), .driver_data = BOARD_PCI6023E }, + { PCI_VDEVICE(NI, 0x2a70), .driver_data = BOARD_PCI6024E }, + { PCI_VDEVICE(NI, 0x2a80), .driver_data = BOARD_PCI6025E }, + { PCI_VDEVICE(NI, 0x2ab0), .driver_data = BOARD_PXI6025E }, + { PCI_VDEVICE(NI, 0x2b80), .driver_data = BOARD_PXI6713 }, + { PCI_VDEVICE(NI, 0x2b90), .driver_data = BOARD_PXI6711 }, + { PCI_VDEVICE(NI, 0x2c80), .driver_data = BOARD_PCI6035E }, + { PCI_VDEVICE(NI, 0x2ca0), .driver_data = BOARD_PCI6034E }, + { PCI_VDEVICE(NI, 0x70aa), .driver_data = BOARD_PCI6229 }, + { PCI_VDEVICE(NI, 0x70ab), .driver_data = BOARD_PCI6259 }, + { PCI_VDEVICE(NI, 0x70ac), .driver_data = BOARD_PCI6289 }, + { PCI_VDEVICE(NI, 0x70ad), .driver_data = BOARD_PXI6251 }, + { PCI_VDEVICE(NI, 0x70ae), .driver_data = BOARD_PXI6220 }, + { PCI_VDEVICE(NI, 0x70af), .driver_data = BOARD_PCI6221 }, + { PCI_VDEVICE(NI, 0x70b0), .driver_data = BOARD_PCI6220 }, + { PCI_VDEVICE(NI, 0x70b1), .driver_data = BOARD_PXI6229 }, + { PCI_VDEVICE(NI, 0x70b2), .driver_data = BOARD_PXI6259 }, + { PCI_VDEVICE(NI, 0x70b3), .driver_data = BOARD_PXI6289 }, + { PCI_VDEVICE(NI, 0x70b4), .driver_data = BOARD_PCI6250 }, + { PCI_VDEVICE(NI, 0x70b5), .driver_data = BOARD_PXI6221 }, + { PCI_VDEVICE(NI, 0x70b6), .driver_data = BOARD_PCI6280 }, + { PCI_VDEVICE(NI, 0x70b7), .driver_data = BOARD_PCI6254 }, + { PCI_VDEVICE(NI, 0x70b8), .driver_data = BOARD_PCI6251 }, + { PCI_VDEVICE(NI, 0x70b9), .driver_data = BOARD_PXI6250 }, + { PCI_VDEVICE(NI, 0x70ba), .driver_data = BOARD_PXI6254 }, + { PCI_VDEVICE(NI, 0x70bb), .driver_data = BOARD_PXI6280 }, + { PCI_VDEVICE(NI, 0x70bc), .driver_data = BOARD_PCI6284 }, + { PCI_VDEVICE(NI, 0x70bd), .driver_data = BOARD_PCI6281 }, + { PCI_VDEVICE(NI, 0x70be), .driver_data = BOARD_PXI6284 }, + { PCI_VDEVICE(NI, 0x70bf), .driver_data = BOARD_PXI6281 }, + { PCI_VDEVICE(NI, 0x70c0), .driver_data = BOARD_PCI6143 }, + { PCI_VDEVICE(NI, 0x70f2), .driver_data = BOARD_PCI6224 }, + { PCI_VDEVICE(NI, 0x70f3), .driver_data = BOARD_PXI6224 }, + { PCI_VDEVICE(NI, 0x710d), .driver_data = BOARD_PXI6143 }, + { PCI_VDEVICE(NI, 0x716c), .driver_data = BOARD_PCI6225 }, + { PCI_VDEVICE(NI, 0x716d), .driver_data = BOARD_PXI6225 }, + { PCI_VDEVICE(NI, 0x717d), .driver_data = BOARD_PCIE6251 }, + { PCI_VDEVICE(NI, 0x717f), .driver_data = BOARD_PCIE6259 }, + { PCI_VDEVICE(NI, 0x71bc), .driver_data = BOARD_PCI6221_37PIN }, + { PCI_VDEVICE(NI, 0x72e8), .driver_data = BOARD_PXIE6251 }, + { PCI_VDEVICE(NI, 0x72e9), .driver_data = BOARD_PXIE6259 }, + { } }; MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table); diff --git a/drivers/comedi/drivers/rtd520.c b/drivers/comedi/drivers/rtd520.c index 44bb0decd7a4..0575913abfe7 100644 --- a/drivers/comedi/drivers/rtd520.c +++ b/drivers/comedi/drivers/rtd520.c @@ -1345,9 +1345,9 @@ static int rtd520_pci_probe(struct pci_dev *dev, } static const struct pci_device_id rtd520_pci_table[] = { - { PCI_VDEVICE(RTD, 0x7520), BOARD_DM7520 }, - { PCI_VDEVICE(RTD, 0x4520), BOARD_PCI4520 }, - { 0 } + { PCI_VDEVICE(RTD, 0x7520), .driver_data = BOARD_DM7520 }, + { PCI_VDEVICE(RTD, 0x4520), .driver_data = BOARD_PCI4520 }, + { } }; MODULE_DEVICE_TABLE(pci, rtd520_pci_table); diff --git a/drivers/comedi/drivers/s626.c b/drivers/comedi/drivers/s626.c index 0e5f9a9a7fd3..ce7ae6b6d40b 100644 --- a/drivers/comedi/drivers/s626.c +++ b/drivers/comedi/drivers/s626.c @@ -2585,9 +2585,9 @@ static int s626_pci_probe(struct pci_dev *dev, * Philips SAA7146 media/dvb based cards. */ static const struct pci_device_id s626_pci_table[] = { - { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, - 0x6000, 0x0272) }, - { 0 } + { PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, + 0x6000, 0x0272) }, + { } }; MODULE_DEVICE_TABLE(pci, s626_pci_table); diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c index c47741292ae1..8455f16d62cb 100644 --- a/drivers/counter/ftm-quaddec.c +++ b/drivers/counter/ftm-quaddec.c @@ -292,7 +292,9 @@ static int ftm_quaddec_probe(struct platform_device *pdev) counter->signals = ftm_quaddec_signals; counter->num_signals = ARRAY_SIZE(ftm_quaddec_signals); - mutex_init(&ftm->ftm_quaddec_mutex); + ret = devm_mutex_init(&pdev->dev, &ftm->ftm_quaddec_mutex); + if (ret) + return ret; ftm_quaddec_init(ftm); diff --git a/drivers/counter/intel-qep.c b/drivers/counter/intel-qep.c index c49c178056f4..3181da47e9d4 100644 --- a/drivers/counter/intel-qep.c +++ b/drivers/counter/intel-qep.c @@ -188,25 +188,21 @@ static int intel_qep_ceiling_write(struct counter_device *counter, struct counter_count *count, u64 max) { struct intel_qep *qep = counter_priv(counter); - int ret = 0; /* Intel QEP ceiling configuration only supports 32-bit values */ if (max != (u32)max) return -ERANGE; - mutex_lock(&qep->lock); - if (qep->enabled) { - ret = -EBUSY; - goto out; - } + guard(mutex)(&qep->lock); + + if (qep->enabled) + return -EBUSY; pm_runtime_get_sync(qep->dev); intel_qep_writel(qep, INTEL_QEPMAX, max); pm_runtime_put(qep->dev); -out: - mutex_unlock(&qep->lock); - return ret; + return 0; } static int intel_qep_enable_read(struct counter_device *counter, @@ -226,10 +222,11 @@ static int intel_qep_enable_write(struct counter_device *counter, u32 reg; bool changed; - mutex_lock(&qep->lock); + guard(mutex)(&qep->lock); + changed = val ^ qep->enabled; if (!changed) - goto out; + return 0; pm_runtime_get_sync(qep->dev); reg = intel_qep_readl(qep, INTEL_QEPCON); @@ -246,8 +243,6 @@ static int intel_qep_enable_write(struct counter_device *counter, pm_runtime_put(qep->dev); qep->enabled = val; -out: - mutex_unlock(&qep->lock); return 0; } @@ -279,7 +274,6 @@ static int intel_qep_spike_filter_ns_write(struct counter_device *counter, struct intel_qep *qep = counter_priv(counter); u32 reg; bool enable; - int ret = 0; /* * Spike filter length is (MAX_COUNT + 2) clock periods. @@ -300,11 +294,10 @@ static int intel_qep_spike_filter_ns_write(struct counter_device *counter, if (length > INTEL_QEPFLT_MAX_COUNT(length)) return -ERANGE; - mutex_lock(&qep->lock); - if (qep->enabled) { - ret = -EBUSY; - goto out; - } + guard(mutex)(&qep->lock); + + if (qep->enabled) + return -EBUSY; pm_runtime_get_sync(qep->dev); reg = intel_qep_readl(qep, INTEL_QEPCON); @@ -316,9 +309,7 @@ static int intel_qep_spike_filter_ns_write(struct counter_device *counter, intel_qep_writel(qep, INTEL_QEPCON, reg); pm_runtime_put(qep->dev); -out: - mutex_unlock(&qep->lock); - return ret; + return 0; } static int intel_qep_preset_enable_read(struct counter_device *counter, @@ -342,13 +333,11 @@ static int intel_qep_preset_enable_write(struct counter_device *counter, { struct intel_qep *qep = counter_priv(counter); u32 reg; - int ret = 0; - mutex_lock(&qep->lock); - if (qep->enabled) { - ret = -EBUSY; - goto out; - } + guard(mutex)(&qep->lock); + + if (qep->enabled) + return -EBUSY; pm_runtime_get_sync(qep->dev); reg = intel_qep_readl(qep, INTEL_QEPCON); @@ -360,10 +349,7 @@ static int intel_qep_preset_enable_write(struct counter_device *counter, intel_qep_writel(qep, INTEL_QEPCON, reg); pm_runtime_put(qep->dev); -out: - mutex_unlock(&qep->lock); - - return ret; + return 0; } static struct counter_comp intel_qep_count_ext[] = { @@ -414,7 +400,9 @@ static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id) qep->dev = dev; qep->regs = regs; - mutex_init(&qep->lock); + ret = devm_mutex_init(dev, &qep->lock); + if (ret) + return ret; intel_qep_init(qep); pci_set_drvdata(pci, qep); diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c index e6100b5fb082..cd475382ab6a 100644 --- a/drivers/counter/interrupt-cnt.c +++ b/drivers/counter/interrupt-cnt.c @@ -233,7 +233,9 @@ static int interrupt_cnt_probe(struct platform_device *pdev) if (ret) return ret; - mutex_init(&priv->lock); + ret = devm_mutex_init(dev, &priv->lock); + if (ret) + return ret; ret = devm_counter_add(dev, counter); if (ret < 0) diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c index 2a7a0f774389..daddb5224794 100644 --- a/drivers/firmware/stratix10-rsu.c +++ b/drivers/firmware/stratix10-rsu.c @@ -244,27 +244,26 @@ static void rsu_async_get_spt_table_callback(struct device *dev, } /** - * rsu_send_msg() - send a message to Intel service layer + * __rsu_send_msg_locked() - send a message to Intel service layer * @priv: pointer to rsu private data * @command: RSU status or update command * @arg: the request argument, the bitstream address or notify status * @callback: function pointer for the callback (status or update) * - * Start an Intel service layer transaction to perform the SMC call that - * is necessary to get RSU boot log or set the address of bitstream to - * boot after reboot. + * Perform the actual SMC transaction. The caller must hold @priv->lock. * - * Returns 0 on success or -ETIMEDOUT on error. + * Returns 0 on success or a negative errno on failure. */ -static int rsu_send_msg(struct stratix10_rsu_priv *priv, - enum stratix10_svc_command_code command, - unsigned long arg, - rsu_callback callback) +static int __rsu_send_msg_locked(struct stratix10_rsu_priv *priv, + enum stratix10_svc_command_code command, + unsigned long arg, + rsu_callback callback) { struct stratix10_svc_client_msg msg; int ret; - mutex_lock(&priv->lock); + lockdep_assert_held(&priv->lock); + reinit_completion(&priv->completion); priv->client.receive_cb = callback; @@ -293,6 +292,59 @@ static int rsu_send_msg(struct stratix10_rsu_priv *priv, status_done: stratix10_svc_done(priv->chan); + return ret; +} + +/** + * rsu_send_msg() - send a message to Intel service layer + * @priv: pointer to rsu private data + * @command: RSU status or update command + * @arg: the request argument, the bitstream address or notify status + * @callback: function pointer for the callback (status or update) + * + * Start an Intel service layer transaction to perform the SMC call that + * is necessary to get RSU boot log or set the address of bitstream to + * boot after reboot. This call will block until the RSU lock can be + * acquired. + * + * Returns 0 on success or a negative errno on failure. + */ +static int rsu_send_msg(struct stratix10_rsu_priv *priv, + enum stratix10_svc_command_code command, + unsigned long arg, + rsu_callback callback) +{ + int ret; + + mutex_lock(&priv->lock); + ret = __rsu_send_msg_locked(priv, command, arg, callback); + mutex_unlock(&priv->lock); + return ret; +} + +/** + * rsu_try_send_msg() - non-blocking variant of rsu_send_msg() + * @priv: pointer to rsu private data + * @command: RSU status or update command + * @arg: the request argument, the bitstream address or notify status + * @callback: function pointer for the callback (status or update) + * + * Same as rsu_send_msg() but returns -EBUSY immediately when another + * RSU operation is already in flight, instead of waiting for the lock. + * + * Returns 0 on success, -EBUSY if the RSU is busy, or another negative + * errno on failure. + */ +static int rsu_try_send_msg(struct stratix10_rsu_priv *priv, + enum stratix10_svc_command_code command, + unsigned long arg, + rsu_callback callback) +{ + int ret; + + if (!mutex_trylock(&priv->lock)) + return -EBUSY; + ret = __rsu_send_msg_locked(priv, command, arg, callback); mutex_unlock(&priv->lock); return ret; } @@ -595,8 +647,17 @@ static ssize_t reboot_image_store(struct device *dev, if (ret) return ret; - ret = rsu_send_msg(priv, COMMAND_RSU_UPDATE, - address, rsu_command_callback); + /* + * Use the non-blocking variant so a write to this sysfs attribute + * does not stall the caller while another RSU operation is in + * flight. Userspace can retry on -EBUSY. + */ + ret = rsu_try_send_msg(priv, COMMAND_RSU_UPDATE, + address, rsu_command_callback); + if (ret == -EBUSY) { + dev_dbg(dev, "RSU busy, reboot_image write rejected\n"); + return ret; + } if (ret) { dev_err(dev, "Error, RSU update returned %i\n", ret); return ret; diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index 39eb78f5905b..c24ca5823078 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -242,37 +242,6 @@ struct stratix10_async_ctrl { DECLARE_HASHTABLE(trx_list, ASYNC_TRX_HASH_BITS); }; -/** - * struct stratix10_svc_controller - service controller - * @dev: device - * @chans: array of service channels - * @num_chans: number of channels in 'chans' array - * @num_active_client: number of active service client - * @node: list management - * @genpool: memory pool pointing to the memory region - * @complete_status: state for completion - * @invoke_fn: function to issue secure monitor call or hypervisor call - * @svc: manages the list of client svc drivers - * @sdm_lock: only allows a single command single response to SDM - * @actrl: async control structure - * - * This struct is used to create communication channels for service clients, to - * handle secure monitor or hypervisor call. - */ -struct stratix10_svc_controller { - struct device *dev; - struct stratix10_svc_chan *chans; - int num_chans; - int num_active_client; - struct list_head node; - struct gen_pool *genpool; - struct completion complete_status; - svc_invoke_fn *invoke_fn; - struct stratix10_svc *svc; - struct mutex sdm_lock; - struct stratix10_async_ctrl actrl; -}; - /** * struct stratix10_svc_chan - service communication channel * @ctrl: pointer to service controller which is the provider of this channel @@ -298,6 +267,37 @@ struct stratix10_svc_chan { struct stratix10_async_chan *async_chan; }; +/** + * struct stratix10_svc_controller - service controller + * @dev: device + * @num_chans: number of channels in 'chans' array + * @num_active_client: number of active service client + * @node: list management + * @genpool: memory pool pointing to the memory region + * @complete_status: state for completion + * @invoke_fn: function to issue secure monitor call or hypervisor call + * @svc: manages the list of client svc drivers + * @sdm_lock: only allows a single command single response to SDM + * @actrl: async control structure + * @chans: array of service channels + * + * This struct is used to create communication channels for service clients, to + * handle secure monitor or hypervisor call. + */ +struct stratix10_svc_controller { + struct device *dev; + int num_chans; + int num_active_client; + struct list_head node; + struct gen_pool *genpool; + struct completion complete_status; + svc_invoke_fn *invoke_fn; + struct stratix10_svc *svc; + struct mutex sdm_lock; + struct stratix10_async_ctrl actrl; + struct stratix10_svc_chan chans[] __counted_by(num_chans); +}; + static LIST_HEAD(svc_ctrl); static LIST_HEAD(svc_data_mem); @@ -465,6 +465,7 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data, case COMMAND_FCS_SEND_CERTIFICATE: case COMMAND_FCS_DATA_ENCRYPTION: case COMMAND_FCS_DATA_DECRYPTION: + case COMMAND_FCS_GET_PROVISION_DATA: cb_data->status = BIT(SVC_STATUS_OK); break; case COMMAND_RECONFIG_DATA_SUBMIT: @@ -487,13 +488,18 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data, cb_data->kaddr1 = &res.a1; cb_data->kaddr2 = &res.a2; break; + case COMMAND_SMC_ATF_BUILD_VER: + cb_data->status = BIT(SVC_STATUS_OK); + cb_data->kaddr1 = &res.a1; + cb_data->kaddr2 = &res.a2; + cb_data->kaddr3 = &res.a3; + break; case COMMAND_RSU_DCMF_VERSION: cb_data->status = BIT(SVC_STATUS_OK); cb_data->kaddr1 = &res.a1; cb_data->kaddr2 = &res.a2; break; case COMMAND_FCS_RANDOM_NUMBER_GEN: - case COMMAND_FCS_GET_PROVISION_DATA: case COMMAND_POLL_SERVICE_STATUS: cb_data->status = BIT(SVC_STATUS_OK); cb_data->kaddr1 = &res.a1; @@ -676,7 +682,7 @@ static int svc_normal_to_secure_thread(void *data) break; case COMMAND_FCS_GET_PROVISION_DATA: a0 = INTEL_SIP_SMC_FCS_GET_PROVISION_DATA; - a1 = (unsigned long)pdata->paddr; + a1 = 0; a2 = 0; break; /* for HWMON */ @@ -706,6 +712,12 @@ static int svc_normal_to_secure_thread(void *data) a1 = 0; a2 = 0; break; + case COMMAND_SMC_ATF_BUILD_VER: + a0 = INTEL_SIP_SMC_ATF_BUILD_VER; + a1 = 0; + a2 = 0; + a3 = 0; + break; case COMMAND_MBOX_SEND_CMD: a0 = INTEL_SIP_SMC_MBOX_SEND_CMD; a1 = pdata->arg[0]; @@ -1910,7 +1922,6 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct stratix10_svc_controller *controller; - struct stratix10_svc_chan *chans; struct gen_pool *genpool; struct stratix10_svc_sh_memory *sh_memory; struct stratix10_svc *svc = NULL; @@ -1938,23 +1949,16 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) return PTR_ERR(genpool); /* allocate service controller and supporting channel */ - controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL); + controller = devm_kzalloc(dev, struct_size(controller, chans, SVC_NUM_CHANNEL), + GFP_KERNEL); if (!controller) { ret = -ENOMEM; goto err_destroy_pool; } - chans = devm_kmalloc_array(dev, SVC_NUM_CHANNEL, - sizeof(*chans), GFP_KERNEL | __GFP_ZERO); - if (!chans) { - ret = -ENOMEM; - goto err_destroy_pool; - } - - controller->dev = dev; controller->num_chans = SVC_NUM_CHANNEL; + controller->dev = dev; controller->num_active_client = 0; - controller->chans = chans; controller->genpool = genpool; controller->invoke_fn = invoke_fn; INIT_LIST_HEAD(&controller->node); @@ -1975,16 +1979,16 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) mutex_init(&controller->sdm_lock); for (i = 0; i < SVC_NUM_CHANNEL; i++) { - chans[i].scl = NULL; - chans[i].ctrl = controller; - chans[i].name = (char *)chan_names[i]; - spin_lock_init(&chans[i].lock); - ret = kfifo_alloc(&chans[i].svc_fifo, fifo_size, GFP_KERNEL); + controller->chans[i].scl = NULL; + controller->chans[i].ctrl = controller; + controller->chans[i].name = (char *)chan_names[i]; + spin_lock_init(&controller->chans[i].lock); + ret = kfifo_alloc(&controller->chans[i].svc_fifo, fifo_size, GFP_KERNEL); if (ret) { dev_err(dev, "failed to allocate FIFO %d\n", i); goto err_free_fifos; } - spin_lock_init(&chans[i].svc_fifo_lock); + spin_lock_init(&controller->chans[i].svc_fifo_lock); } list_add_tail(&controller->node, &svc_ctrl); @@ -2028,7 +2032,7 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) list_del(&controller->node); /* free only the FIFOs that were successfully allocated */ while (i--) - kfifo_free(&chans[i].svc_fifo); + kfifo_free(&controller->chans[i].svc_fifo); stratix10_svc_async_exit(controller); err_destroy_pool: gen_pool_destroy(genpool); diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 37b35f58f0df..748fc210c135 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -288,6 +288,13 @@ config FPGA_MGR_LATTICE_SYSCONFIG_SPI FPGA manager driver support for Lattice FPGAs programming over slave SPI sysCONFIG interface. +config FPGA_MGR_EFINIX_SPI + tristate "Efinix FPGA configuration over SPI" + depends on SPI + help + FPGA manager driver support for Efinix FPGAs configuration over SPI + (passive mode only). + source "drivers/fpga/tests/Kconfig" endif # FPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index aeb89bb13517..6f5798b27e0d 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_FPGA_MGR_LATTICE_SYSCONFIG) += lattice-sysconfig.o obj-$(CONFIG_FPGA_MGR_LATTICE_SYSCONFIG_SPI) += lattice-sysconfig-spi.o obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o +obj-$(CONFIG_FPGA_MGR_EFINIX_SPI) += efinix-spi.o # FPGA Secure Update Drivers obj-$(CONFIG_FPGA_M10_BMC_SEC_UPDATE) += intel-m10-bmc-sec-update.o diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 3bf8e7338dbe..097a97eeea66 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c @@ -723,6 +723,9 @@ afu_ioctl_dma_map(struct dfl_feature_dev_data *fdata, void __user *arg) if (map.argsz < minsz || map.flags) return -EINVAL; + if (map.length >> PAGE_SHIFT > (u64)INT_MAX) + return -EINVAL; + ret = afu_dma_map_region(fdata, map.user_addr, map.length, &map.iova); if (ret) return ret; diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index 4087a36a0571..4c63c7c8579b 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -1132,6 +1132,8 @@ static int dfh_get_param_size(void __iomem *dfh_base, resource_size_t max) return -EINVAL; size += next * sizeof(u64); + if (size > max) + return -EINVAL; if (FIELD_GET(DFHv1_PARAM_HDR_NEXT_EOP, v)) return size; diff --git a/drivers/fpga/efinix-spi.c b/drivers/fpga/efinix-spi.c new file mode 100644 index 000000000000..ed9a41232a32 --- /dev/null +++ b/drivers/fpga/efinix-spi.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FPGA Manager Driver for Efinix + * + * Copyright (C) 2025 iris-GmbH infrared & intelligent sensors + * + * Ian Dannapel + * + * Load Efinix FPGA firmware over SPI using the serial configuration interface. + * + * Note: Only passive mode (host initiates transfer) is currently supported. + */ + +#include +#include +#include +#include +#include +#include + +/* + * 13 dummy bytes generate 104 SPI clock cycles (8 bits each). + * Used to meet the requirement for >100 clock cycles idle sequence. + */ +#define EFINIX_SPI_IDLE_CYCLES_BYTES 13 + +/* + * tDMIN: Minimum time between deassertion of CRESET_N to first + * valid configuration data. (32 µs) + */ +#define EFINIX_TDMIN_US_MIN 35 +#define EFINIX_TDMIN_US_MAX 40 + +/* + * tCRESET_N: Minimum CRESET_N low pulse width required to + * trigger re-configuration. (320 ns) + */ +#define EFINIX_TCRESETN_DELAY_MIN_US 1 +#define EFINIX_TCRESETN_DELAY_MAX_US 2 + +/* + * tUSER: Minimum configuration duration after CDONE goes high + * before entering user mode. (25 µs) + */ +#define EFINIX_TUSER_US_MIN 30 +#define EFINIX_TUSER_US_MAX 35 + +struct efinix_spi_conf { + struct spi_device *spi; + struct gpio_desc *cdone; + struct gpio_desc *reset; +}; + +static void efinix_spi_reset(struct efinix_spi_conf *conf) +{ + gpiod_set_value(conf->reset, 1); + usleep_range(EFINIX_TCRESETN_DELAY_MIN_US, EFINIX_TCRESETN_DELAY_MAX_US); + gpiod_set_value(conf->reset, 0); + usleep_range(EFINIX_TDMIN_US_MIN, EFINIX_TDMIN_US_MAX); +} + +static enum fpga_mgr_states efinix_spi_state(struct fpga_manager *mgr) +{ + struct efinix_spi_conf *conf = mgr->priv; + + if (conf->cdone && gpiod_get_value(conf->cdone) == 1) + return FPGA_MGR_STATE_OPERATING; + + return FPGA_MGR_STATE_UNKNOWN; +} + +static int efinix_spi_write_init(struct fpga_manager *mgr, + struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct efinix_spi_conf *conf = mgr->priv; + struct spi_transfer assert_cs = { + /* Keep CS asserted across configuration. */ + .cs_change = 1, + }; + struct spi_message message; + int ret; + + if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { + dev_err(&mgr->dev, "Partial reconfiguration not supported\n"); + return -EOPNOTSUPP; + } + + /* + * Efinix passive SPI configuration requires chip select to stay + * asserted from reset until the bitstream is fully clocked in. + * Lock the SPI bus so no other device can toggle CS between the + * reset pulse and the write/complete transfers. + */ + spi_bus_lock(conf->spi->controller); + spi_message_init_with_transfers(&message, &assert_cs, 1); + ret = spi_sync_locked(conf->spi, &message); + if (ret) { + spi_bus_unlock(conf->spi->controller); + return ret; + } + + /* Reset with CS asserted */ + efinix_spi_reset(conf); + + return 0; +} + +static int efinix_spi_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct spi_transfer write_xfer = { + .tx_buf = buf, + .len = count, + .cs_change = 1, + }; + struct efinix_spi_conf *conf = mgr->priv; + struct spi_message message; + int ret; + + spi_message_init_with_transfers(&message, &write_xfer, 1); + ret = spi_sync_locked(conf->spi, &message); + if (ret) { + dev_err(&mgr->dev, "SPI error in firmware write: %d\n", ret); + spi_bus_unlock(conf->spi->controller); + } + + return ret; +} + +static int efinix_spi_write_complete(struct fpga_manager *mgr, + struct fpga_image_info *info) +{ + unsigned long timeout = + jiffies + usecs_to_jiffies(info->config_complete_timeout_us); + struct spi_transfer clk_cycles = { + .len = EFINIX_SPI_IDLE_CYCLES_BYTES, + /* Release CS after the trailing idle clocks are sent. */ + .cs_change = 0, + }; + struct efinix_spi_conf *conf = mgr->priv; + struct spi_message message; + int done, ret; + bool expired = false; + u8 *dummy_buf; + + dummy_buf = kzalloc(EFINIX_SPI_IDLE_CYCLES_BYTES, GFP_KERNEL); + if (!dummy_buf) { + ret = -ENOMEM; + goto unlock_spi; + } + + /* + * Keep the bus locked while sending the trailing idle clocks, then + * let this final transfer deassert CS to terminate configuration. + */ + clk_cycles.tx_buf = dummy_buf; + spi_message_init_with_transfers(&message, &clk_cycles, 1); + ret = spi_sync_locked(conf->spi, &message); + if (ret) { + dev_err(&mgr->dev, "SPI error in write complete: %d\n", ret); + goto free_buf; + } + + if (conf->cdone) { + while (!expired) { + done = gpiod_get_value(conf->cdone); + if (done < 0) { + ret = done; + goto free_buf; + } + if (done) + break; + + usleep_range(10, 20); + expired = time_after(jiffies, timeout); + } + + if (expired) { + dev_err(&mgr->dev, "Timeout waiting for CDONE\n"); + ret = -ETIMEDOUT; + goto free_buf; + } + } + + usleep_range(EFINIX_TUSER_US_MIN, EFINIX_TUSER_US_MAX); + +free_buf: + kfree(dummy_buf); +unlock_spi: + spi_bus_unlock(conf->spi->controller); + + return ret; +} + +static const struct fpga_manager_ops efinix_spi_ops = { + .state = efinix_spi_state, + .write_init = efinix_spi_write_init, + .write = efinix_spi_write, + .write_complete = efinix_spi_write_complete, +}; + +static int efinix_spi_probe(struct spi_device *spi) +{ + struct efinix_spi_conf *conf; + struct fpga_manager *mgr; + + if (!(spi->mode & SPI_CPHA) || !(spi->mode & SPI_CPOL)) + return dev_err_probe(&spi->dev, -EINVAL, + "Unsupported SPI mode, set CPHA and CPOL\n"); + + conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); + if (!conf) + return -ENOMEM; + + conf->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(conf->reset)) + return dev_err_probe(&spi->dev, PTR_ERR(conf->reset), + "Failed to get RESET gpio\n"); + + conf->cdone = devm_gpiod_get_optional(&spi->dev, "cdone", GPIOD_IN); + if (IS_ERR(conf->cdone)) + return dev_err_probe(&spi->dev, PTR_ERR(conf->cdone), + "Failed to get CDONE gpio\n"); + + conf->spi = spi; + + mgr = devm_fpga_mgr_register(&spi->dev, + "Efinix FPGA Manager", + &efinix_spi_ops, conf); + + return PTR_ERR_OR_ZERO(mgr); +} + +static const struct of_device_id efinix_spi_of_match[] = { + { .compatible = "efinix,trion-config", }, + {} +}; +MODULE_DEVICE_TABLE(of, efinix_spi_of_match); + +static const struct spi_device_id efinix_ids[] = { + { "trion-config", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(spi, efinix_ids); + +static struct spi_driver efinix_spi_driver = { + .driver = { + .name = "efinix-spi", + .of_match_table = efinix_spi_of_match, + }, + .probe = efinix_spi_probe, + .id_table = efinix_ids, +}; + +module_spi_driver(efinix_spi_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ian Dannapel "); +MODULE_DESCRIPTION("Efinix FPGA SPI Programming Driver"); diff --git a/drivers/fpga/lattice-sysconfig-spi.c b/drivers/fpga/lattice-sysconfig-spi.c index 44691cfcf50a..5d195602b261 100644 --- a/drivers/fpga/lattice-sysconfig-spi.c +++ b/drivers/fpga/lattice-sysconfig-spi.c @@ -3,8 +3,14 @@ * Lattice FPGA programming over slave SPI sysCONFIG interface. */ -#include +#include +#include +#include +#include +#include +#include #include +#include #include "lattice-sysconfig.h" @@ -85,7 +91,6 @@ static int sysconfig_spi_bitstream_burst_complete(struct sysconfig_priv *priv) static int sysconfig_spi_probe(struct spi_device *spi) { - const struct spi_device_id *dev_id; struct device *dev = &spi->dev; struct sysconfig_priv *priv; const u32 *spi_max_speed; @@ -94,15 +99,7 @@ static int sysconfig_spi_probe(struct spi_device *spi) if (!priv) return -ENOMEM; - spi_max_speed = device_get_match_data(dev); - if (!spi_max_speed) { - dev_id = spi_get_device_id(spi); - if (!dev_id) - return -ENODEV; - - spi_max_speed = (const u32 *)dev_id->driver_data; - } - + spi_max_speed = spi_get_device_match_data(spi); if (!spi_max_speed) return -EINVAL; @@ -125,26 +122,26 @@ static const struct spi_device_id sysconfig_spi_ids[] = { { .name = "sysconfig-ecp5", .driver_data = (kernel_ulong_t)&ecp5_spi_max_speed_hz, - }, {}, + }, + {} }; MODULE_DEVICE_TABLE(spi, sysconfig_spi_ids); -#if IS_ENABLED(CONFIG_OF) static const struct of_device_id sysconfig_of_ids[] = { { .compatible = "lattice,sysconfig-ecp5", .data = &ecp5_spi_max_speed_hz, - }, {}, + }, + {} }; MODULE_DEVICE_TABLE(of, sysconfig_of_ids); -#endif /* IS_ENABLED(CONFIG_OF) */ static struct spi_driver lattice_sysconfig_driver = { .probe = sysconfig_spi_probe, .id_table = sysconfig_spi_ids, .driver = { .name = "lattice_sysconfig_spi_fpga_mgr", - .of_match_table = of_match_ptr(sysconfig_of_ids), + .of_match_table = sysconfig_of_ids, }, }; module_spi_driver(lattice_sysconfig_driver); diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c index 6134cea86ac8..cc8f6d7bb978 100644 --- a/drivers/fpga/microchip-spi.c +++ b/drivers/fpga/microchip-spi.c @@ -116,6 +116,9 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr, } header_size = *(buf + MPF_HEADER_SIZE_OFFSET); + if (!header_size) + return -EINVAL; + if (header_size > count) { info->header_size = header_size; return -EAGAIN; diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index caa091224dc5..9107a5b461d3 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -168,11 +168,10 @@ static int child_regions_with_firmware(struct device_node *overlay) fpga_region_of_match); } - of_node_put(child_region); - if (ret) pr_err("firmware-name not allowed in child FPGA region: %pOF", child_region); + of_node_put(child_region); return ret; } diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c index 4e1d2a4d3df4..3460e4809f86 100644 --- a/drivers/fpga/ts73xx-fpga.c +++ b/drivers/fpga/ts73xx-fpga.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -119,9 +120,17 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(mgr); } +static const struct of_device_id ts73xx_fpga_of_match[] = { + { .compatible = "technologic,ts7300-fpga" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ts73xx_fpga_of_match); + static struct platform_driver ts73xx_fpga_driver = { .driver = { .name = "ts73xx-fpga-mgr", + .of_match_table = ts73xx_fpga_of_match, }, .probe = ts73xx_fpga_probe, }; diff --git a/drivers/gpib/agilent_82357a/agilent_82357a.c b/drivers/gpib/agilent_82357a/agilent_82357a.c index 770ba6eb40d1..2468a471d175 100644 --- a/drivers/gpib/agilent_82357a/agilent_82357a.c +++ b/drivers/gpib/agilent_82357a/agilent_82357a.c @@ -1298,7 +1298,7 @@ static inline int agilent_82357a_device_match(struct usb_interface *interface, if (gpib_match_device_path(&interface->dev, config->device_path) == 0) return 0; if (config->serial_number && - strcmp(usbdev->serial, config->serial_number) != 0) + (!usbdev->serial || strcmp(usbdev->serial, config->serial_number) != 0)) return 0; return 1; diff --git a/drivers/gpib/common/gpib_os.c b/drivers/gpib/common/gpib_os.c index 5909274ddc12..69f6aa73ab9a 100644 --- a/drivers/gpib/common/gpib_os.c +++ b/drivers/gpib/common/gpib_os.c @@ -544,13 +544,6 @@ int ibopen(struct inode *inode, struct file *filep) priv = filep->private_data; init_gpib_file_private((struct gpib_file_private *)filep->private_data); - if (board->use_count == 0) { - int retval; - - retval = request_module("gpib%i", minor); - if (retval) - dev_dbg(board->gpib_dev, "request module returned %i\n", retval); - } if (board->interface) { if (!try_module_get(board->provider_module)) { dev_err(board->gpib_dev, "try_module_get() failed\n"); @@ -613,7 +606,7 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) unsigned int minor = iminor(file_inode(filep)); struct gpib_board *board; struct gpib_file_private *file_priv = filep->private_data; - long retval = -ENOTTY; + long retval = -EBADRQC; if (minor >= GPIB_MAX_NUM_BOARDS) { pr_err("gpib: invalid minor number of device file\n"); @@ -806,7 +799,6 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) mutex_unlock(&board->big_gpib_mutex); return write_ioctl(file_priv, board, arg); default: - retval = -ENOTTY; goto done; } @@ -1018,7 +1010,6 @@ static int command_ioctl(struct gpib_file_private *file_priv, userbuf += bytes_written; if (retval < 0) { atomic_set(&desc->io_in_progress, 0); - atomic_dec(&desc->descriptor_busy); wake_up_interruptible(&board->wait); break; diff --git a/drivers/gpib/ines/ines.h b/drivers/gpib/ines/ines.h index 6ad57e9a1216..22af59682870 100644 --- a/drivers/gpib/ines/ines.h +++ b/drivers/gpib/ines/ines.h @@ -21,6 +21,7 @@ enum ines_pci_chip { PCI_CHIP_AMCC5920, PCI_CHIP_QUANCOM, PCI_CHIP_QUICKLOGIC5030, + PCI_CHIP_INES_72130, }; struct ines_priv { @@ -162,4 +163,19 @@ enum ines_auxd_bits { INES_T6_50us = 0x10, }; +enum ines72130_regs { + BUS_STATUS_REG = 0xc, +}; + +enum ines_72130_bus_status_bits { + BSR_NRFD_BIT = 0x1, + BSR_NDAC_BIT = 0x2, + BSR_DAV_BIT = 0x4, + BSR_EOI_BIT = 0x8, + BSR_SRQ_BIT = 0x10, + BSR_ATN_BIT = 0x20, + BSR_REN_BIT = 0x40, + BSR_IFC_BIT = 0x80, +}; + #endif // _INES_GPIB_H diff --git a/drivers/gpib/ines/ines_gpib.c b/drivers/gpib/ines/ines_gpib.c index c000f647fbb5..3562f3184c28 100644 --- a/drivers/gpib/ines/ines_gpib.c +++ b/drivers/gpib/ines/ines_gpib.c @@ -57,6 +57,34 @@ static int ines_line_status(const struct gpib_board *board) return status; } +static int ines72130_line_status(const struct gpib_board *board) +{ + int status = VALID_ALL; + int bsr_bits; + struct ines_priv *ines_priv = board->private_data; + + bsr_bits = ines_inb(ines_priv, BUS_STATUS_REG); + + if (bsr_bits & BSR_REN_BIT) + status |= BUS_REN; + if (bsr_bits & BSR_IFC_BIT) + status |= BUS_IFC; + if (bsr_bits & BSR_SRQ_BIT) + status |= BUS_SRQ; + if (bsr_bits & BSR_EOI_BIT) + status |= BUS_EOI; + if (bsr_bits & BSR_NRFD_BIT) + status |= BUS_NRFD; + if (bsr_bits & BSR_NDAC_BIT) + status |= BUS_NDAC; + if (bsr_bits & BSR_DAV_BIT) + status |= BUS_DAV; + if (bsr_bits & BSR_ATN_BIT) + status |= BUS_ATN; + + return status; +} + static void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count) { if (count > 0xffff) { @@ -75,6 +103,9 @@ static int ines_t1_delay(struct gpib_board *board, unsigned int nano_sec) retval = nec7210_t1_delay(board, nec_priv, nano_sec); + if (ines_priv->pci_chip_type == PCI_CHIP_INES_72130) + return retval; + if (nano_sec <= 250) { write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_250ns | INES_INITIAL_T1_2000ns, AUXMR); @@ -294,6 +325,8 @@ static irqreturn_t ines_interrupt(struct gpib_board *board) spin_lock_irqsave(&board->spinlock, flags); nec7210_interrupt(board, nec_priv); + if (priv->pci_chip_type == PCI_CHIP_INES_72130) + goto out; isr3_bits = ines_inb(priv, ISR3); isr4_bits = ines_inb(priv, ISR4); if (isr3_bits & IFC_ACTIVE_BIT) { @@ -311,11 +344,13 @@ static irqreturn_t ines_interrupt(struct gpib_board *board) if (wake) wake_up_interruptible(&board->wait); +out: spin_unlock_irqrestore(&board->spinlock, flags); return IRQ_HANDLED; } static int ines_pci_attach(struct gpib_board *board, const struct gpib_board_config *config); +static int ines_pci_xl_attach(struct gpib_board *board, const struct gpib_board_config *config); static int ines_pci_accel_attach(struct gpib_board *board, const struct gpib_board_config *config); static int ines_isa_attach(struct gpib_board *board, const struct gpib_board_config *config); @@ -569,6 +604,34 @@ static struct gpib_interface ines_pci_unaccel_interface = { .return_to_local = ines_return_to_local, }; +static struct gpib_interface ines_pci_xl_interface = { + .name = "ines_pci_xl", + .attach = ines_pci_xl_attach, + .detach = ines_pci_detach, + .read = ines_read, + .write = ines_write, + .command = ines_command, + .take_control = ines_take_control, + .go_to_standby = ines_go_to_standby, + .request_system_control = ines_request_system_control, + .interface_clear = ines_interface_clear, + .remote_enable = ines_remote_enable, + .enable_eos = ines_enable_eos, + .disable_eos = ines_disable_eos, + .parallel_poll = ines_parallel_poll, + .parallel_poll_configure = ines_parallel_poll_configure, + .parallel_poll_response = ines_parallel_poll_response, + .local_parallel_poll_mode = NULL, // XXX + .line_status = ines72130_line_status, + .update_status = ines_update_status, + .primary_address = ines_primary_address, + .secondary_address = ines_secondary_address, + .serial_poll_response = ines_serial_poll_response, + .serial_poll_status = ines_serial_poll_status, + .t1_delay = ines_t1_delay, + .return_to_local = ines_return_to_local, +}; + static struct gpib_interface ines_pci_interface = { .name = "ines_pci", .attach = ines_pci_accel_attach, @@ -870,6 +933,24 @@ static int ines_pci_attach(struct gpib_board *board, const struct gpib_board_con return 0; } +static int ines_pci_xl_attach(struct gpib_board *board, const struct gpib_board_config *config) +{ + struct ines_priv *ines_priv; + struct nec7210_priv *nec_priv; + int retval; + + retval = ines_common_pci_attach(board, config); + if (retval < 0) + return retval; + + ines_priv = board->private_data; + ines_priv->pci_chip_type = PCI_CHIP_INES_72130; + nec_priv = &ines_priv->nec7210_priv; + nec7210_board_online(nec_priv, board); + + return 0; +} + static int ines_pci_accel_attach(struct gpib_board *board, const struct gpib_board_config *config) { struct ines_priv *ines_priv; @@ -1419,6 +1500,12 @@ static int __init ines_init_module(void) goto err_pci_unaccel; } + ret = gpib_register_driver(&ines_pci_xl_interface, THIS_MODULE); + if (ret) { + pr_err("gpib_register_driver failed: error = %d\n", ret); + goto err_pci_xl; + } + ret = gpib_register_driver(&ines_pci_accel_interface, THIS_MODULE); if (ret) { pr_err("gpib_register_driver failed: error = %d\n", ret); @@ -1473,6 +1560,8 @@ static int __init ines_init_module(void) gpib_unregister_driver(&ines_pci_accel_interface); err_pci_accel: gpib_unregister_driver(&ines_pci_unaccel_interface); +err_pci_xl: + gpib_unregister_driver(&ines_pci_xl_interface); err_pci_unaccel: gpib_unregister_driver(&ines_pci_interface); err_pci: @@ -1485,6 +1574,7 @@ static void __exit ines_exit_module(void) { gpib_unregister_driver(&ines_pci_interface); gpib_unregister_driver(&ines_pci_unaccel_interface); + gpib_unregister_driver(&ines_pci_xl_interface); gpib_unregister_driver(&ines_pci_accel_interface); gpib_unregister_driver(&ines_isa_interface); #ifdef CONFIG_GPIB_PCMCIA diff --git a/drivers/gpib/ni_usb/ni_usb_gpib.c b/drivers/gpib/ni_usb/ni_usb_gpib.c index 0bbc13ecebf9..28de1d543ad6 100644 --- a/drivers/gpib/ni_usb/ni_usb_gpib.c +++ b/drivers/gpib/ni_usb/ni_usb_gpib.c @@ -720,7 +720,7 @@ static int ni_usb_read(struct gpib_board *board, u8 *buffer, size_t length, break; } ni_usb_soft_update_status(board, status.ibsta, 0); - if (status.ibsta & END) + if ((status.ibsta & END) && (status.error_code == NIUSB_NO_ERROR)) *end = 1; else *end = 0; diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 0c8698c8fc5e..ad8dafea7d2f 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -514,7 +514,7 @@ static int __catu_probe(struct device *dev, struct resource *res) int ret = 0; u32 dma_mask; struct catu_drvdata *drvdata; - struct coresight_desc catu_desc; + struct coresight_desc catu_desc = { 0 }; struct coresight_platform_data *pdata = NULL; void __iomem *base; diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 94ee24afdc6d..6d65c43d574f 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,10 @@ DEFINE_MUTEX(coresight_mutex); static DEFINE_PER_CPU(struct coresight_device *, csdev_sink); +static DEFINE_RAW_SPINLOCK(coresight_dev_lock); +static DEFINE_PER_CPU(struct coresight_device *, csdev_source); +static DEFINE_PER_CPU(bool, percpu_pm_failed); + /** * struct coresight_node - elements of a path, from source to sink * @csdev: Address of an element. @@ -58,6 +63,24 @@ static LIST_HEAD(coresight_dev_idx_list); static const struct cti_assoc_op *cti_assoc_ops; +static struct coresight_node * +coresight_path_first_node(struct coresight_path *path) +{ + if (list_empty(&path->path_list)) + return NULL; + + return list_first_entry(&path->path_list, struct coresight_node, link); +} + +static struct coresight_node * +coresight_path_last_node(struct coresight_path *path) +{ + if (list_empty(&path->path_list)) + return NULL; + + return list_last_entry(&path->path_list, struct coresight_node, link); +} + void coresight_set_cti_ops(const struct cti_assoc_op *cti_op) { cti_assoc_ops = cti_op; @@ -82,14 +105,89 @@ struct coresight_device *coresight_get_percpu_sink(int cpu) } EXPORT_SYMBOL_GPL(coresight_get_percpu_sink); -static struct coresight_device *coresight_get_source(struct coresight_path *path) +static void coresight_set_percpu_source(struct coresight_device *csdev) +{ + if (!csdev || !coresight_is_percpu_source(csdev)) + return; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + + /* Expect no device to be set yet */ + WARN_ON(per_cpu(csdev_source, csdev->cpu)); + per_cpu(csdev_source, csdev->cpu) = csdev; +} + +static void coresight_clear_percpu_source(struct coresight_device *csdev) +{ + if (!csdev || !coresight_is_percpu_source(csdev)) + return; + + /* Clear percpu_pm_failed */ + per_cpu(percpu_pm_failed, csdev->cpu) = false; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + + /* The per-CPU pointer should contain the same csdev */ + WARN_ON(per_cpu(csdev_source, csdev->cpu) != csdev); + per_cpu(csdev_source, csdev->cpu) = NULL; +} + +struct coresight_device *coresight_get_percpu_source_ref(int cpu) { struct coresight_device *csdev; + if (WARN_ON(cpu < 0)) + return NULL; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + + csdev = per_cpu(csdev_source, cpu); + if (!csdev) + return NULL; + + /* + * Holding a reference to the csdev->dev ensures that the + * coresight_device is live for the caller. The path building + * logic can safely either build a path to the sink or fail + * if the device is being unregistered (if there was a race). + * The caller can skip the "source" device, if no path could + * be built. + */ + get_device(&csdev->dev); + + return csdev; +} + +void coresight_put_percpu_source_ref(struct coresight_device *csdev) +{ + if (!csdev || !coresight_is_percpu_source(csdev)) + return; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + + /* + * TODO: coresight_device_release() is invoked to release resources when + * the device's refcount reaches zero. It then calls free_percpu(), + * which acquires pcpu_lock — a sleepable lock when PREEMPT_RT is + * enabled. Since the raw spinlock coresight_dev_lock is held, this can + * lead to a potential "scheduling while atomic" issue. + */ + put_device(&csdev->dev); +} + +struct coresight_device *coresight_get_source(struct coresight_path *path) +{ + struct coresight_device *csdev; + struct coresight_node *nd; + if (!path) return NULL; - csdev = list_first_entry(&path->path_list, struct coresight_node, link)->csdev; + nd = coresight_path_first_node(path); + if (!nd) + return NULL; + + csdev = nd->csdev; if (!coresight_is_device_source(csdev)) return NULL; @@ -385,19 +483,47 @@ static void coresight_disable_helpers(struct coresight_device *csdev, } /* - * Helper function to call source_ops(csdev)->disable and also disable the - * helpers. - * - * There is an imbalance between coresight_enable_path() and - * coresight_disable_path(). Enabling also enables the source's helpers as part - * of the path, but disabling always skips the first item in the path (which is - * the source), so sources and their helpers don't get disabled as part of that - * function and we need the extra step here. + * coresight_enable_source() and coresight_disable_source() only enable and + * disable the source, but do nothing for the associated helpers, which are + * controlled as part of the path. */ +int coresight_enable_source(struct coresight_device *csdev, + struct perf_event *event, enum cs_mode mode, + struct coresight_path *path) +{ + int ret; + + if (!coresight_is_device_source(csdev)) + return -EINVAL; + + ret = source_ops(csdev)->enable(csdev, event, mode, path); + if (ret) + return ret; + + /* + * Update the path pointer until after the source is enabled to avoid + * races where multiple paths attempt to enable the same source. + * + * Do not set the path pointer here for per-CPU sources; set it locally + * on the CPU instead. Otherwise, there is a window where the path is + * enabled but the pointer is not yet set, causing CPU PM notifiers to + * miss PM operations due to reading a NULL pointer. + */ + if (!coresight_is_percpu_source(csdev)) + csdev->path = path; + + return 0; +} + void coresight_disable_source(struct coresight_device *csdev, void *data) { + if (!coresight_is_device_source(csdev)) + return; + + if (!coresight_is_percpu_source(csdev)) + csdev->path = NULL; + source_ops(csdev)->disable(csdev, data); - coresight_disable_helpers(csdev, NULL); } EXPORT_SYMBOL_GPL(coresight_disable_source); @@ -424,20 +550,42 @@ int coresight_resume_source(struct coresight_device *csdev) EXPORT_SYMBOL_GPL(coresight_resume_source); /* - * coresight_disable_path_from : Disable components in the given path beyond - * @nd in the list. If @nd is NULL, all the components, except the SOURCE are - * disabled. + * Callers must fetch nodes from the path and pass @from and @to to the path + * enable/disable functions. Walk the path from @from to locate @to. If @to + * is found, it indicates @from and @to are in order. Otherwise, they are out + * of order. */ -static void coresight_disable_path_from(struct coresight_path *path, - struct coresight_node *nd) +static bool coresight_path_nodes_in_order(struct coresight_path *path, + struct coresight_node *from, + struct coresight_node *to) +{ + struct coresight_node *nd; + + if (WARN_ON_ONCE(!from || !to)) + return false; + + nd = from; + list_for_each_entry_from(nd, &path->path_list, link) { + if (nd == to) + return true; + } + + return false; +} + +static void coresight_disable_path_from_to(struct coresight_path *path, + struct coresight_node *from, + struct coresight_node *to) { u32 type; struct coresight_device *csdev, *parent, *child; + struct coresight_node *nd; - if (!nd) - nd = list_first_entry(&path->path_list, struct coresight_node, link); + if (!coresight_path_nodes_in_order(path, from, to)) + return; - list_for_each_entry_continue(nd, &path->path_list, link) { + nd = from; + list_for_each_entry_from(nd, &path->path_list, link) { csdev = nd->csdev; type = csdev->type; @@ -457,12 +605,6 @@ static void coresight_disable_path_from(struct coresight_path *path, coresight_disable_sink(csdev); break; case CORESIGHT_DEV_TYPE_SOURCE: - /* - * We skip the first node in the path assuming that it - * is the source. So we don't expect a source device in - * the middle of a path. - */ - WARN_ON(1); break; case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; @@ -476,12 +618,18 @@ static void coresight_disable_path_from(struct coresight_path *path, /* Disable all helpers adjacent along the path last */ coresight_disable_helpers(csdev, path); + + /* Iterate up to and including @to */ + if (nd == to) + break; } } void coresight_disable_path(struct coresight_path *path) { - coresight_disable_path_from(path, NULL); + coresight_disable_path_from_to(path, + coresight_path_first_node(path), + coresight_path_last_node(path)); } EXPORT_SYMBOL_GPL(coresight_disable_path); @@ -499,22 +647,36 @@ static int coresight_enable_helpers(struct coresight_device *csdev, ret = coresight_enable_helper(helper, mode, path); if (ret) - return ret; + goto err; } return 0; + +err: + while (i--) { + helper = csdev->pdata->out_conns[i]->dest_dev; + if (helper && coresight_is_helper(helper)) + coresight_disable_helper(helper, path); + } + + return ret; } -int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) +static int coresight_enable_path_from_to(struct coresight_path *path, + enum cs_mode mode, + struct coresight_node *from, + struct coresight_node *to) { int ret = 0; u32 type; struct coresight_node *nd; struct coresight_device *csdev, *parent, *child; - struct coresight_device *source; - source = coresight_get_source(path); - list_for_each_entry_reverse(nd, &path->path_list, link) { + if (!coresight_path_nodes_in_order(path, from, to)) + return -EINVAL; + + nd = to; + list_for_each_entry_from_reverse(nd, &path->path_list, link) { csdev = nd->csdev; type = csdev->type; @@ -553,7 +715,8 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; - ret = coresight_enable_link(csdev, parent, child, source); + ret = coresight_enable_link(csdev, parent, child, + coresight_get_source(path)); if (ret) goto err_disable_helpers; break; @@ -561,6 +724,10 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) ret = -EINVAL; goto err_disable_helpers; } + + /* Iterate down to and including @from */ + if (nd == from) + break; } out: @@ -568,18 +735,36 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) err_disable_helpers: coresight_disable_helpers(csdev, path); err_disable_path: - coresight_disable_path_from(path, nd); + /* No device is actually enabled */ + if (nd == to) + goto out; + + /* Fetch the previous node, the last successfully enabled one */ + nd = list_next_entry(nd, link); + coresight_disable_path_from_to(path, nd, to); goto out; } +int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) +{ + return coresight_enable_path_from_to(path, mode, + coresight_path_first_node(path), + coresight_path_last_node(path)); +} + struct coresight_device *coresight_get_sink(struct coresight_path *path) { struct coresight_device *csdev; + struct coresight_node *nd; if (!path) return NULL; - csdev = list_last_entry(&path->path_list, struct coresight_node, link)->csdev; + nd = coresight_path_last_node(path); + if (!nd) + return NULL; + + csdev = nd->csdev; if (csdev->type != CORESIGHT_DEV_TYPE_SINK && csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) return NULL; @@ -642,15 +827,29 @@ struct coresight_device *coresight_get_sink_by_id(u32 id) */ static bool coresight_get_ref(struct coresight_device *csdev) { - struct device *dev = csdev->dev.parent; + struct device *dev = &csdev->dev; + struct device *parent = csdev->dev.parent; + struct device_driver *drv; + + /* Make sure csdev can't go away */ + get_device(dev); + + /* Make sure parent device can't go away */ + get_device(parent); /* Make sure the driver can't be removed */ - if (!try_module_get(dev->driver->owner)) - return false; - /* Make sure the device can't go away */ - get_device(dev); - pm_runtime_get_sync(dev); + drv = parent->driver; + if (!drv || !try_module_get(drv->owner)) + goto err_module; + + /* Make sure the device is powered on */ + pm_runtime_get_sync(parent); return true; + +err_module: + put_device(parent); + put_device(dev); + return false; } /** @@ -661,11 +860,15 @@ static bool coresight_get_ref(struct coresight_device *csdev) */ static void coresight_put_ref(struct coresight_device *csdev) { - struct device *dev = csdev->dev.parent; + struct device *dev = &csdev->dev; + struct device *parent = csdev->dev.parent; + struct device_driver *drv = parent->driver; - pm_runtime_put(dev); + pm_runtime_put(parent); + if (drv) + module_put(drv->owner); + put_device(parent); put_device(dev); - module_put(dev->driver->owner); } /* @@ -739,8 +942,8 @@ static int coresight_get_trace_id(struct coresight_device *csdev, * Call this after creating the path and before enabling it. This leaves * the trace ID set on the path, or it remains 0 if it couldn't be assigned. */ -void coresight_path_assign_trace_id(struct coresight_path *path, - enum cs_mode mode) +int coresight_path_assign_trace_id(struct coresight_path *path, + enum cs_mode mode) { struct coresight_device *sink = coresight_get_sink(path); struct coresight_node *nd; @@ -750,15 +953,18 @@ void coresight_path_assign_trace_id(struct coresight_path *path, /* Assign a trace ID to the path for the first device that wants to do it */ trace_id = coresight_get_trace_id(nd->csdev, mode, sink); - /* - * 0 in this context is that it didn't want to assign so keep searching. - * Non 0 is either success or fail. - */ - if (trace_id != 0) { - path->trace_id = trace_id; - return; - } + /* 0 means the device has no ID assignment, so keep searching */ + if (trace_id == 0) + continue; + + if (!IS_VALID_CS_TRACE_ID(trace_id)) + return -EINVAL; + + path->trace_id = trace_id; + return 0; } + + return -EINVAL; } /** @@ -787,7 +993,7 @@ static int _coresight_build_path(struct coresight_device *csdev, goto out; if (coresight_is_percpu_source(csdev) && coresight_is_percpu_sink(sink) && - sink == per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev))) { + sink == per_cpu(csdev_sink, csdev->cpu)) { if (_coresight_build_path(sink, source, sink, path) == 0) { found = true; goto out; @@ -1014,7 +1220,7 @@ coresight_find_default_sink(struct coresight_device *csdev) /* look for a default sink if we have not found for this device */ if (!csdev->def_sink) { if (coresight_is_percpu_source(csdev)) - csdev->def_sink = per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev)); + csdev->def_sink = per_cpu(csdev_sink, csdev->cpu); if (!csdev->def_sink) csdev->def_sink = coresight_find_sink(csdev, &depth); } @@ -1322,32 +1528,56 @@ void coresight_release_platform_data(struct device *dev, devm_kfree(dev, pdata); } -struct coresight_device *coresight_register(struct coresight_desc *desc) +static struct coresight_device * +coresight_init_device(struct coresight_desc *desc) { - int ret; struct coresight_device *csdev; - bool registered = false; csdev = kzalloc_obj(*csdev); - if (!csdev) { - ret = -ENOMEM; - goto err_out; - } + if (!csdev) + return ERR_PTR(-ENOMEM); csdev->pdata = desc->pdata; - csdev->type = desc->type; csdev->subtype = desc->subtype; csdev->ops = desc->ops; csdev->access = desc->access; csdev->orphan = true; + if (desc->flags & CORESIGHT_DESC_CPU_BOUND) { + csdev->cpu = desc->cpu; + } else { + /* A per-CPU source or sink must set CPU_BOUND flag */ + if (coresight_is_percpu_source(csdev) || + coresight_is_percpu_sink(csdev)) { + kfree(csdev); + return ERR_PTR(-EINVAL); + } + + csdev->cpu = -1; + } + csdev->dev.type = &coresight_dev_type[desc->type]; csdev->dev.groups = desc->groups; csdev->dev.parent = desc->dev; csdev->dev.release = coresight_device_release; csdev->dev.bus = &coresight_bustype; + return csdev; +} + +struct coresight_device *coresight_register(struct coresight_desc *desc) +{ + int ret; + struct coresight_device *csdev; + bool registered = false; + + csdev = coresight_init_device(desc); + if (IS_ERR(csdev)) { + ret = PTR_ERR(csdev); + goto err_out; + } + if (csdev->type == CORESIGHT_DEV_TYPE_SINK || csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { raw_spin_lock_init(&csdev->perf_sink_id_map.lock); @@ -1398,6 +1628,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) if (ret) goto out_unlock; + coresight_set_percpu_source(csdev); mutex_unlock(&coresight_mutex); if (cti_assoc_ops && cti_assoc_ops->add) @@ -1427,6 +1658,7 @@ void coresight_unregister(struct coresight_device *csdev) cti_assoc_ops->remove(csdev); mutex_lock(&coresight_mutex); + coresight_clear_percpu_source(csdev); etm_perf_del_symlink_sink(csdev); coresight_remove_conns(csdev); coresight_clear_default_sink(csdev); @@ -1615,6 +1847,211 @@ static void coresight_release_device_list(void) } } +static struct coresight_path *coresight_cpu_get_active_path(enum cs_mode mode) +{ + struct coresight_device *source; + bool is_active = false; + + source = coresight_get_percpu_source_ref(smp_processor_id()); + if (!source) + return NULL; + + if (coresight_get_mode(source) & mode) + is_active = true; + + coresight_put_percpu_source_ref(source); + + /* + * It is expected to run in atomic context or with the CPU lock held for + * sysfs mode, so it cannot be preempted to disable the path. Here + * returns the active path pointer without concern that its state may + * change. Since the build path has taken a reference on the component, + * the path can be safely used by the caller. + */ + return is_active ? source->path : NULL; +} + +/* Return: 1 if PM is required, 0 if skip, or a negative error */ +static int coresight_pm_is_needed(struct coresight_path *path) +{ + struct coresight_device *source, *sink; + + if (this_cpu_read(percpu_pm_failed)) + return -EIO; + + if (!path) + return 0; + + source = coresight_get_source(path); + sink = coresight_get_sink(path); + if (!source || !sink) + return 0; + + /* pm_save_disable() and pm_restore_enable() must be paired */ + if (coresight_ops(source)->pm_save_disable && + coresight_ops(source)->pm_restore_enable) + return 1; + + /* + * It is not permitted that the source has no callbacks while the sink + * does, as the sink cannot be disabled without disabling the source, + * which may lead to lockups. Fix this by enabling self-hosted PM + * mode for ETM (see etm4_probe()). + */ + if (coresight_ops(sink)->pm_save_disable && + coresight_ops(sink)->pm_restore_enable) { + pr_warn_once("coresight PM failed: source has no PM callbacks; " + "cannot safely control sink\n"); + return -EINVAL; + } + + return 0; +} + +static int coresight_pm_device_save(struct coresight_device *csdev) +{ + if (!csdev || !coresight_ops(csdev)->pm_save_disable) + return 0; + + return coresight_ops(csdev)->pm_save_disable(csdev); +} + +static void coresight_pm_device_restore(struct coresight_device *csdev) +{ + if (!csdev || !coresight_ops(csdev)->pm_restore_enable) + return; + + coresight_ops(csdev)->pm_restore_enable(csdev); +} + +static int coresight_pm_save(struct coresight_path *path) +{ + struct coresight_device *source = coresight_get_source(path); + struct coresight_node *from, *to; + int ret; + + ret = coresight_pm_device_save(source); + if (ret) + return ret; + + from = coresight_path_first_node(path); + /* Disable up to the node before sink */ + to = list_prev_entry(coresight_path_last_node(path), link); + coresight_disable_path_from_to(path, from, to); + + /* + * Save the sink. Most sinks do not implement a save callback to avoid + * latency from memory copying. We assume the sink's save and restore + * always succeed. + */ + coresight_pm_device_save(coresight_get_sink(path)); + return 0; +} + +static void coresight_pm_restore(struct coresight_path *path) +{ + struct coresight_device *source = coresight_get_source(path); + struct coresight_device *sink = coresight_get_sink(path); + struct coresight_node *from, *to; + int ret; + + coresight_pm_device_restore(sink); + + from = coresight_path_first_node(path); + /* Enable up to the node before sink */ + to = list_prev_entry(coresight_path_last_node(path), link); + ret = coresight_enable_path_from_to(path, coresight_get_mode(source), + from, to); + if (ret) + goto path_failed; + + coresight_pm_device_restore(source); + return; + +path_failed: + coresight_pm_device_save(sink); + + pr_err("Failed in coresight PM restore on CPU%d: %d\n", + smp_processor_id(), ret); + + /* + * Once PM fails on a CPU, set percpu_pm_failed and leave it set until + * reboot. This prevents repeated partial transitions during idle + * entry and exit. + */ + this_cpu_write(percpu_pm_failed, true); +} + +static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, + void *v) +{ + struct coresight_path *path = + coresight_cpu_get_active_path(CS_MODE_SYSFS | CS_MODE_PERF); + int ret; + + ret = coresight_pm_is_needed(path); + if (ret <= 0) + return ret ? NOTIFY_BAD : NOTIFY_DONE; + + switch (cmd) { + case CPU_PM_ENTER: + if (coresight_pm_save(path)) + return NOTIFY_BAD; + break; + case CPU_PM_EXIT: + case CPU_PM_ENTER_FAILED: + coresight_pm_restore(path); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static struct notifier_block coresight_cpu_pm_nb = { + .notifier_call = coresight_cpu_pm_notify, +}; + +static int coresight_dying_cpu(unsigned int cpu) +{ + struct coresight_path *path; + + /* + * The perf event layer will disable PMU events in the CPU + * hotplug. Here only handles SYSFS case. + */ + path = coresight_cpu_get_active_path(CS_MODE_SYSFS); + if (!path) + return 0; + + coresight_disable_sysfs(coresight_get_source(path)); + return 0; +} + +static int __init coresight_pm_setup(void) +{ + int ret; + + ret = cpu_pm_register_notifier(&coresight_cpu_pm_nb); + if (ret) + return ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_ONLINE, + "arm/coresight-core:dying", + NULL, coresight_dying_cpu); + if (ret) + cpu_pm_unregister_notifier(&coresight_cpu_pm_nb); + + return ret; +} + +static void coresight_pm_cleanup(void) +{ + cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_ONLINE); + cpu_pm_unregister_notifier(&coresight_cpu_pm_nb); +} + const struct bus_type coresight_bustype = { .name = "coresight", }; @@ -1669,9 +2106,15 @@ static int __init coresight_init(void) /* initialise the coresight syscfg API */ ret = cscfg_init(); + if (ret) + goto exit_notifier; + + ret = coresight_pm_setup(); if (!ret) return 0; + cscfg_exit(); +exit_notifier: atomic_notifier_chain_unregister(&panic_notifier_list, &coresight_notifier); exit_perf: @@ -1683,6 +2126,7 @@ static int __init coresight_init(void) static void __exit coresight_exit(void) { + coresight_pm_cleanup(); cscfg_exit(); atomic_notifier_chain_unregister(&panic_notifier_list, &coresight_notifier); @@ -1729,10 +2173,10 @@ int coresight_etm_get_trace_id(struct coresight_device *csdev, enum cs_mode mode { int cpu, trace_id; - if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE || !source_ops(csdev)->cpu_id) + if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) return -EINVAL; - cpu = source_ops(csdev)->cpu_id(csdev); + cpu = csdev->cpu; switch (mode) { case CS_MODE_SYSFS: trace_id = coresight_trace_id_get_cpu_id(cpu); diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 2f4c9362709a..b2c9a4db13b4 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -659,7 +659,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) void __iomem *base; struct device *dev = &adev->dev; struct cti_drvdata *drvdata = NULL; - struct coresight_desc cti_desc; + struct coresight_desc cti_desc = { 0 }; struct coresight_platform_data *pdata = NULL; struct resource *res = &adev->res; @@ -702,11 +702,14 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) * eCPU ID. System CTIs will have the name cti_sys where I is an * index allocated by order of discovery. */ - if (drvdata->ctidev.cpu >= 0) + if (drvdata->ctidev.cpu >= 0) { + cti_desc.cpu = drvdata->ctidev.cpu; + cti_desc.flags = CORESIGHT_DESC_CPU_BOUND; cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d", drvdata->ctidev.cpu); - else + } else { cti_desc.name = coresight_alloc_device_name("cti_sys", dev); + } if (!cti_desc.name) return -ENOMEM; diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index 4eff96f48594..d6d5388705c3 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -329,6 +329,7 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata, if (!tg) return -ENOMEM; + tg->nr_sigs = nr_filter_sigs; err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS); if (!err) drvdata->config.trig_out_filter |= tg->used_mask; diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index b952a1d47f12..a827f76b8144 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -83,7 +83,7 @@ struct etb_drvdata { struct coresight_device *csdev; struct miscdevice miscdev; raw_spinlock_t spinlock; - local_t reading; + atomic_t reading; pid_t pid; u8 *buf; u32 buffer_depth; @@ -601,7 +601,7 @@ static int etb_open(struct inode *inode, struct file *file) struct etb_drvdata *drvdata = container_of(file->private_data, struct etb_drvdata, miscdev); - if (local_cmpxchg(&drvdata->reading, 0, 1)) + if (atomic_cmpxchg(&drvdata->reading, 0, 1)) return -EBUSY; dev_dbg(&drvdata->csdev->dev, "%s: successfully opened\n", __func__); @@ -639,7 +639,7 @@ static int etb_release(struct inode *inode, struct file *file) { struct etb_drvdata *drvdata = container_of(file->private_data, struct etb_drvdata, miscdev); - local_set(&drvdata->reading, 0); + atomic_set(&drvdata->reading, 0); dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__); return 0; diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index f85dedf89a3f..09b21a711a87 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -49,7 +49,6 @@ struct etm_ctxt { }; static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt); -static DEFINE_PER_CPU(struct coresight_device *, csdev_src); GEN_PMU_FORMAT_ATTR(cycacc); GEN_PMU_FORMAT_ATTR(timestamp); @@ -315,6 +314,115 @@ static bool sinks_compatible(struct coresight_device *a, (sink_ops(a) == sink_ops(b)); } +/* + * This helper is used for fetching the path pointer via the ctxt. + * + * Perf event callbacks run on the same CPU in atomic context, but AUX pause + * and resume may run in NMI context and preempt other callbacks. Since the + * event stop callback clears ctxt->event_data before the data is released, + * AUX pause/resume will either observe a NULL pointer and stop fetching the + * path pointer, or safely access event_data and the path, as the data has + * not yet been freed. + */ +static struct coresight_path *etm_event_get_ctxt_path(struct etm_ctxt *ctxt) +{ + struct etm_event_data *event_data; + struct coresight_path *path; + + if (!ctxt) + return NULL; + + event_data = READ_ONCE(ctxt->event_data); + if (!event_data) + return NULL; + + path = etm_event_cpu_path(event_data, smp_processor_id()); + if (!path) + return NULL; + + return path; +} + +static struct coresight_path * +etm_event_build_path(struct perf_event *event, int cpu, + struct coresight_device *user_sink, + struct coresight_device *match_sink) +{ + struct coresight_path *path = NULL; + struct coresight_device *source, *sink; + int ret; + + source = coresight_get_percpu_source_ref(cpu); + + /* + * If there is no ETM associated with this CPU or ever we try to trace + * on this CPU, we handle it accordingly. + */ + if (!source) + return NULL; + + /* + * If AUX pause feature is enabled but the ETM driver does not + * support the operations, skip for this source. + */ + if (event->attr.aux_start_paused && + (!source_ops(source)->pause_perf || + !source_ops(source)->resume_perf)) { + dev_err_once(&source->dev, "AUX pause is not supported.\n"); + goto out; + } + + /* If sink has been specified by user, directly use it */ + if (user_sink) { + sink = user_sink; + } else { + /* + * No sink provided - look for a default sink for all the ETMs, + * where this event can be scheduled. + * + * We allocate the sink specific buffers only once for this + * event. If the ETMs have different default sink devices, we + * can only use a single "type" of sink as the event can carry + * only one sink specific buffer. Thus we have to make sure + * that the sinks are of the same type and driven by the same + * driver, as the one we allocate the buffer for. We don't + * trace on a CPU if the sink is not compatible. + */ + + /* Find the default sink for this ETM */ + sink = coresight_find_default_sink(source); + if (!sink) + goto out; + + /* Check if this sink compatible with the last sink */ + if (match_sink && !sinks_compatible(match_sink, sink)) + goto out; + } + + /* + * Building a path doesn't enable it, it simply builds a + * list of devices from source to sink that can be + * referenced later when the path is actually needed. + */ + path = coresight_build_path(source, sink); + if (IS_ERR(path)) + goto out; + + /* ensure we can allocate a trace ID for this CPU */ + ret = coresight_path_assign_trace_id(path, CS_MODE_PERF); + if (ret) { + coresight_release_path(path); + path = NULL; + goto out; + } + + coresight_trace_id_perf_start(&sink->perf_sink_id_map); + +out: + coresight_put_percpu_source_ref(source); + return IS_ERR_OR_NULL(path) ? NULL : path; +} + static void *etm_setup_aux(struct perf_event *event, void **pages, int nr_pages, bool overwrite) { @@ -322,7 +430,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, int cpu = event->cpu; cpumask_t *mask; struct coresight_device *sink = NULL; - struct coresight_device *user_sink = NULL, *last_sink = NULL; + struct coresight_device *user_sink = NULL; struct etm_event_data *event_data = NULL; event_data = alloc_event_data(cpu); @@ -354,80 +462,25 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, */ for_each_cpu(cpu, mask) { struct coresight_path *path; - struct coresight_device *csdev; - csdev = per_cpu(csdev_src, cpu); - /* - * If there is no ETM associated with this CPU clear it from - * the mask and continue with the rest. If ever we try to trace - * on this CPU, we handle it accordingly. - */ - if (!csdev) { + path = etm_event_build_path(event, cpu, user_sink, sink); + if (!path) { + /* + * Failed to create a path for the CPU, clear it from + * the mask and continue to next one. + */ cpumask_clear_cpu(cpu, mask); continue; } /* - * If AUX pause feature is enabled but the ETM driver does not - * support the operations, clear this CPU from the mask and - * continue to next one. + * The first found sink is saved here and passed to + * etm_event_build_path() to check whether the remaining ETMs + * have a compatible default sink. */ - if (event->attr.aux_start_paused && - (!source_ops(csdev)->pause_perf || !source_ops(csdev)->resume_perf)) { - dev_err_once(&csdev->dev, "AUX pause is not supported.\n"); - cpumask_clear_cpu(cpu, mask); - continue; - } + if (!user_sink && !sink) + sink = coresight_get_sink(path); - /* - * No sink provided - look for a default sink for all the ETMs, - * where this event can be scheduled. - * We allocate the sink specific buffers only once for this - * event. If the ETMs have different default sink devices, we - * can only use a single "type" of sink as the event can carry - * only one sink specific buffer. Thus we have to make sure - * that the sinks are of the same type and driven by the same - * driver, as the one we allocate the buffer for. As such - * we choose the first sink and check if the remaining ETMs - * have a compatible default sink. We don't trace on a CPU - * if the sink is not compatible. - */ - if (!user_sink) { - /* Find the default sink for this ETM */ - sink = coresight_find_default_sink(csdev); - if (!sink) { - cpumask_clear_cpu(cpu, mask); - continue; - } - - /* Check if this sink compatible with the last sink */ - if (last_sink && !sinks_compatible(last_sink, sink)) { - cpumask_clear_cpu(cpu, mask); - continue; - } - last_sink = sink; - } - - /* - * Building a path doesn't enable it, it simply builds a - * list of devices from source to sink that can be - * referenced later when the path is actually needed. - */ - path = coresight_build_path(csdev, sink); - if (IS_ERR(path)) { - cpumask_clear_cpu(cpu, mask); - continue; - } - - /* ensure we can allocate a trace ID for this CPU */ - coresight_path_assign_trace_id(path, CS_MODE_PERF); - if (!IS_VALID_CS_TRACE_ID(path->trace_id)) { - cpumask_clear_cpu(cpu, mask); - coresight_release_path(path); - continue; - } - - coresight_trace_id_perf_start(&sink->perf_sink_id_map); *etm_event_cpu_path_ptr(event_data, cpu) = path; } @@ -464,13 +517,23 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, goto out; } -static int etm_event_resume(struct coresight_device *csdev, - struct etm_ctxt *ctxt) +static int etm_event_resume(struct coresight_path *path) { - if (!ctxt->event_data) + struct coresight_device *source; + int ret; + + if (!path) return 0; - return coresight_resume_source(csdev); + source = coresight_get_source(path); + if (!source) + return 0; + + ret = coresight_resume_source(source); + if (ret < 0) + dev_err(&source->dev, "Failed to resume ETM event.\n"); + + return ret; } static void etm_event_start(struct perf_event *event, int flags) @@ -479,23 +542,19 @@ static void etm_event_start(struct perf_event *event, int flags) struct etm_event_data *event_data; struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt); struct perf_output_handle *handle = &ctxt->handle; - struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); + struct coresight_device *source, *sink; struct coresight_path *path; u64 hw_id; - if (!csdev) - goto fail; - if (flags & PERF_EF_RESUME) { - if (etm_event_resume(csdev, ctxt) < 0) { - dev_err(&csdev->dev, "Failed to resume ETM event.\n"); + path = etm_event_get_ctxt_path(ctxt); + if (etm_event_resume(path) < 0) goto fail; - } return; } /* Have we messed up our tracking ? */ - if (WARN_ON(ctxt->event_data)) + if (WARN_ON(READ_ONCE(ctxt->event_data))) goto fail; /* @@ -523,9 +582,10 @@ static void etm_event_start(struct perf_event *event, int flags) path = etm_event_cpu_path(event_data, cpu); path->handle = handle; - /* We need a sink, no need to continue without one */ + /* We need source and sink, no need to continue if any is not set */ + source = coresight_get_source(path); sink = coresight_get_sink(path); - if (WARN_ON_ONCE(!sink)) + if (WARN_ON_ONCE(!source || !sink)) goto fail_end_stop; /* Nothing will happen without a path */ @@ -533,7 +593,7 @@ static void etm_event_start(struct perf_event *event, int flags) goto fail_end_stop; /* Finally enable the tracer */ - if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF, path)) + if (coresight_enable_source(source, event, CS_MODE_PERF, path)) goto fail_disable_path; /* @@ -557,7 +617,7 @@ static void etm_event_start(struct perf_event *event, int flags) /* Tell the perf core the event is alive */ event->hw.state = 0; /* Save the event_data for this ETM */ - ctxt->event_data = event_data; + WRITE_ONCE(ctxt->event_data, event_data); return; fail_disable_path: @@ -577,26 +637,25 @@ static void etm_event_start(struct perf_event *event, int flags) return; } -static void etm_event_pause(struct perf_event *event, - struct coresight_device *csdev, +static void etm_event_pause(struct coresight_path *path, + struct perf_event *event, struct etm_ctxt *ctxt) { - int cpu = smp_processor_id(); - struct coresight_device *sink; struct perf_output_handle *handle = &ctxt->handle; - struct coresight_path *path; + struct coresight_device *source, *sink; + struct etm_event_data *event_data; unsigned long size; - if (!ctxt->event_data) + if (!path) + return; + + source = coresight_get_source(path); + sink = coresight_get_sink(path); + if (WARN_ON_ONCE(!source || !sink)) return; /* Stop tracer */ - coresight_pause_source(csdev); - - path = etm_event_cpu_path(ctxt->event_data, cpu); - sink = coresight_get_sink(path); - if (WARN_ON_ONCE(!sink)) - return; + coresight_pause_source(source); /* * The per CPU sink has own interrupt handling, it might have @@ -613,8 +672,9 @@ static void etm_event_pause(struct perf_event *event, if (!sink_ops(sink)->update_buffer) return; + event_data = READ_ONCE(ctxt->event_data); size = sink_ops(sink)->update_buffer(sink, handle, - ctxt->event_data->snk_config); + event_data->snk_config); if (READ_ONCE(handle->event)) { if (!size) return; @@ -630,14 +690,14 @@ static void etm_event_stop(struct perf_event *event, int mode) { int cpu = smp_processor_id(); unsigned long size; - struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); + struct coresight_device *source, *sink; struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt); struct perf_output_handle *handle = &ctxt->handle; + struct coresight_path *path = etm_event_get_ctxt_path(ctxt); struct etm_event_data *event_data; - struct coresight_path *path; if (mode & PERF_EF_PAUSE) - return etm_event_pause(event, csdev, ctxt); + return etm_event_pause(path, event, ctxt); /* * If we still have access to the event_data via handle, @@ -647,9 +707,9 @@ static void etm_event_stop(struct perf_event *event, int mode) WARN_ON(perf_get_aux(handle) != ctxt->event_data)) return; - event_data = ctxt->event_data; + event_data = READ_ONCE(ctxt->event_data); /* Clear the event_data as this ETM is stopping the trace. */ - ctxt->event_data = NULL; + WRITE_ONCE(ctxt->event_data, NULL); if (event->hw.state == PERF_HES_STOPPED) return; @@ -671,19 +731,13 @@ static void etm_event_stop(struct perf_event *event, int mode) return; } - if (!csdev) - return; - - path = etm_event_cpu_path(event_data, cpu); - if (!path) - return; - + source = coresight_get_source(path); sink = coresight_get_sink(path); - if (!sink) + if (!source || !sink) return; /* stop tracer */ - coresight_disable_source(csdev, event); + coresight_disable_source(source, event); /* tell the core */ event->hw.state = PERF_HES_STOPPED; @@ -824,7 +878,7 @@ static void etm_addr_filters_sync(struct perf_event *event) int etm_perf_symlink(struct coresight_device *csdev, bool link) { char entry[sizeof("cpu9999999")]; - int ret = 0, cpu = source_ops(csdev)->cpu_id(csdev); + int ret = 0, cpu = csdev->cpu; struct device *pmu_dev = etm_pmu.dev; struct device *cs_dev = &csdev->dev; @@ -833,17 +887,12 @@ int etm_perf_symlink(struct coresight_device *csdev, bool link) if (!etm_perf_up) return -EPROBE_DEFER; - if (link) { + if (link) ret = sysfs_create_link(&pmu_dev->kobj, &cs_dev->kobj, entry); - if (ret) - return ret; - per_cpu(csdev_src, cpu) = csdev; - } else { + else sysfs_remove_link(&pmu_dev->kobj, entry); - per_cpu(csdev_src, cpu) = NULL; - } - return 0; + return ret; } EXPORT_SYMBOL_GPL(etm_perf_symlink); diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c index a547a6d2e0bd..862ad0786699 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -441,6 +441,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) struct etm_enable_arg { struct etm_drvdata *drvdata; + struct coresight_path *path; int rc; }; @@ -462,15 +463,12 @@ static void etm_enable_sysfs_smp_call(void *info) arg->rc = etm_enable_hw(arg->drvdata); /* The tracer didn't start */ - if (arg->rc) + if (arg->rc) { coresight_set_mode(csdev, CS_MODE_DISABLED); -} + return; + } -static int etm_cpu_id(struct coresight_device *csdev) -{ - struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - - return drvdata->cpu; + csdev->path = arg->path; } void etm_release_trace_id(struct etm_drvdata *drvdata) @@ -499,10 +497,13 @@ static int etm_enable_perf(struct coresight_device *csdev, ret = etm_enable_hw(drvdata); /* Failed to start tracer; roll back to DISABLED mode */ - if (ret) + if (ret) { coresight_set_mode(csdev, CS_MODE_DISABLED); + return ret; + } - return ret; + csdev->path = path; + return 0; } static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path) @@ -521,6 +522,7 @@ static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_pat */ if (cpu_online(drvdata->cpu)) { arg.drvdata = drvdata; + arg.path = path; ret = smp_call_function_single(drvdata->cpu, etm_enable_sysfs_smp_call, &arg, 1); if (!ret) @@ -590,6 +592,7 @@ static void etm_disable_sysfs_smp_call(void *info) etm_disable_hw(drvdata); + drvdata->csdev->path = NULL; coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); } @@ -614,6 +617,7 @@ static void etm_disable_perf(struct coresight_device *csdev) CS_LOCK(drvdata->csa.base); + drvdata->csdev->path = NULL; coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); /* @@ -627,13 +631,6 @@ static void etm_disable_sysfs(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - /* - * Taking hotplug lock here protects from clocks getting disabled - * with tracing being left on (crash scenario) if user disable occurs - * after cpu online mask indicates the cpu is offline but before the - * DYING hotplug callback is serviced by the ETM driver. - */ - cpus_read_lock(); spin_lock(&drvdata->spinlock); /* @@ -644,7 +641,6 @@ static void etm_disable_sysfs(struct coresight_device *csdev) drvdata, 1); spin_unlock(&drvdata->spinlock); - cpus_read_unlock(); /* * we only release trace IDs when resetting sysfs. @@ -684,7 +680,6 @@ static void etm_disable(struct coresight_device *csdev, } static const struct coresight_ops_source etm_source_ops = { - .cpu_id = etm_cpu_id, .enable = etm_enable, .disable = etm_disable, }; @@ -704,35 +699,6 @@ static int etm_online_cpu(unsigned int cpu) return 0; } -static int etm_starting_cpu(unsigned int cpu) -{ - if (!etmdrvdata[cpu]) - return 0; - - spin_lock(&etmdrvdata[cpu]->spinlock); - if (!etmdrvdata[cpu]->os_unlock) { - etm_os_unlock(etmdrvdata[cpu]); - etmdrvdata[cpu]->os_unlock = true; - } - - if (coresight_get_mode(etmdrvdata[cpu]->csdev)) - etm_enable_hw(etmdrvdata[cpu]); - spin_unlock(&etmdrvdata[cpu]->spinlock); - return 0; -} - -static int etm_dying_cpu(unsigned int cpu) -{ - if (!etmdrvdata[cpu]) - return 0; - - spin_lock(&etmdrvdata[cpu]->spinlock); - if (coresight_get_mode(etmdrvdata[cpu]->csdev)) - etm_disable_hw(etmdrvdata[cpu]); - spin_unlock(&etmdrvdata[cpu]->spinlock); - return 0; -} - static bool etm_arch_supported(u8 arch) { switch (arch) { @@ -800,13 +766,6 @@ static int __init etm_hp_setup(void) { int ret; - ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING, - "arm/coresight:starting", - etm_starting_cpu, etm_dying_cpu); - - if (ret) - return ret; - ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "arm/coresight:online", etm_online_cpu, NULL); @@ -817,15 +776,11 @@ static int __init etm_hp_setup(void) return 0; } - /* failed dyn state - remove others */ - cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); - return ret; } static void etm_hp_clear(void) { - cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); if (hp_online) { cpuhp_remove_state_nocalls(hp_online); hp_online = 0; @@ -891,6 +846,8 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_etm_groups; + desc.cpu = drvdata->cpu; + desc.flags = CORESIGHT_DESC_CPU_BOUND; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index d565a73f0042..14bb31bd6a0b 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -56,10 +56,14 @@ MODULE_PARM_DESC(boot_enable, "Enable tracing on boot"); #define PARAM_PM_SAVE_NEVER 1 /* never save any state */ #define PARAM_PM_SAVE_SELF_HOSTED 2 /* save self-hosted state only */ +/* + * Save option for ETM4. ETE, sysreg ETM4s and ACPI boots ignore this option and + * will always save. + */ static int pm_save_enable = PARAM_PM_SAVE_FIRMWARE; module_param(pm_save_enable, int, 0444); MODULE_PARM_DESC(pm_save_enable, - "Save/restore state on power down: 1 = never, 2 = self-hosted"); + "Save/restore state on power down: 1 = never, 2 = self-hosted. MMIO and DT only."); static struct etmv4_drvdata *etmdrvdata[NR_CPUS]; static void etm4_set_default_config(struct etmv4_config *config); @@ -227,13 +231,6 @@ static void etm4_cs_unlock(struct etmv4_drvdata *drvdata, CS_UNLOCK(csa->base); } -static int etm4_cpu_id(struct coresight_device *csdev) -{ - struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - - return drvdata->cpu; -} - void etm4_release_trace_id(struct etmv4_drvdata *drvdata) { coresight_trace_id_put_cpu_id(drvdata->cpu); @@ -241,6 +238,7 @@ void etm4_release_trace_id(struct etmv4_drvdata *drvdata) struct etm4_enable_arg { struct etmv4_drvdata *drvdata; + struct coresight_path *path; int rc; }; @@ -628,8 +626,12 @@ static void etm4_enable_sysfs_smp_call(void *info) arg->rc = etm4_enable_hw(arg->drvdata); /* The tracer didn't start */ - if (arg->rc) + if (arg->rc) { coresight_set_mode(csdev, CS_MODE_DISABLED); + return; + } + + csdev->path = arg->path; } /* @@ -897,9 +899,13 @@ static int etm4_enable_perf(struct coresight_device *csdev, out: /* Failed to start tracer; roll back to DISABLED mode */ - if (ret) + if (ret) { coresight_set_mode(csdev, CS_MODE_DISABLED); - return ret; + return ret; + } + + csdev->path = path; + return 0; } static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path) @@ -929,6 +935,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa * ensures that register writes occur when cpu is powered. */ arg.drvdata = drvdata; + arg.path = path; ret = smp_call_function_single(drvdata->cpu, etm4_enable_sysfs_smp_call, &arg, 1); if (!ret) @@ -1070,6 +1077,7 @@ static void etm4_disable_sysfs_smp_call(void *info) etm4_disable_hw(drvdata); + drvdata->csdev->path = NULL; coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); } @@ -1099,6 +1107,7 @@ static int etm4_disable_perf(struct coresight_device *csdev, /* TRCVICTLR::SSSTATUS, bit[9] */ filters->ssstatus = (control & BIT(9)); + drvdata->csdev->path = NULL; coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); /* @@ -1113,13 +1122,6 @@ static void etm4_disable_sysfs(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - /* - * Taking hotplug lock here protects from clocks getting disabled - * with tracing being left on (crash scenario) if user disable occurs - * after cpu online mask indicates the cpu is offline but before the - * DYING hotplug callback is serviced by the ETM driver. - */ - cpus_read_lock(); raw_spin_lock(&drvdata->spinlock); /* @@ -1133,8 +1135,6 @@ static void etm4_disable_sysfs(struct coresight_device *csdev) cscfg_csdev_disable_active_config(csdev); - cpus_read_unlock(); - /* * we only release trace IDs when resetting sysfs. * This permits sysfs users to read the trace ID after the trace @@ -1201,18 +1201,12 @@ static void etm4_pause_perf(struct coresight_device *csdev) } static const struct coresight_ops_source etm4_source_ops = { - .cpu_id = etm4_cpu_id, .enable = etm4_enable, .disable = etm4_disable, .resume_perf = etm4_resume_perf, .pause_perf = etm4_pause_perf, }; -static const struct coresight_ops etm4_cs_ops = { - .trace_id = coresight_etm_get_trace_id, - .source_ops = &etm4_source_ops, -}; - static bool cpu_supports_sysreg_trace(void) { u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1); @@ -1839,44 +1833,19 @@ static int etm4_online_cpu(unsigned int cpu) return 0; } -static int etm4_starting_cpu(unsigned int cpu) +static inline bool etm4_pm_save_needed(struct etmv4_drvdata *drvdata) { - if (!etmdrvdata[cpu]) - return 0; - - raw_spin_lock(&etmdrvdata[cpu]->spinlock); - if (!etmdrvdata[cpu]->os_unlock) - etm4_os_unlock(etmdrvdata[cpu]); - - if (coresight_get_mode(etmdrvdata[cpu]->csdev)) - etm4_enable_hw(etmdrvdata[cpu]); - raw_spin_unlock(&etmdrvdata[cpu]->spinlock); - return 0; + return !!drvdata->save_state; } -static int etm4_dying_cpu(unsigned int cpu) -{ - if (!etmdrvdata[cpu]) - return 0; - - raw_spin_lock(&etmdrvdata[cpu]->spinlock); - if (coresight_get_mode(etmdrvdata[cpu]->csdev)) - etm4_disable_hw(etmdrvdata[cpu]); - raw_spin_unlock(&etmdrvdata[cpu]->spinlock); - return 0; -} - -static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) +static int etm4_cpu_save(struct coresight_device *csdev) { int i, ret = 0; + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etmv4_save_state *state; - struct coresight_device *csdev = drvdata->csdev; struct csdev_access *csa; struct device *etm_dev; - if (WARN_ON(!csdev)) - return -ENODEV; - etm_dev = &csdev->dev; csa = &csdev->access; @@ -1979,7 +1948,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR0); if (drvdata->numvmidc > 4) - state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR1); + state->trcvmidcctlr1 = etm4x_read32(csa, TRCVMIDCCTLR1); state->trcclaimset = etm4x_read32(csa, TRCCLAIMCLR); @@ -2008,31 +1977,13 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) return ret; } -static int etm4_cpu_save(struct etmv4_drvdata *drvdata) -{ - int ret = 0; - - if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED) - return 0; - - /* - * Save and restore the ETM Trace registers only if - * the ETM is active. - */ - if (coresight_get_mode(drvdata->csdev)) - ret = __etm4_cpu_save(drvdata); - return ret; -} - -static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata) +static void etm4_cpu_restore(struct coresight_device *csdev) { int i; + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etmv4_save_state *state = drvdata->save_state; struct csdev_access *csa = &drvdata->csdev->access; - if (WARN_ON(!drvdata->csdev)) - return; - etm4_cs_unlock(drvdata, csa); etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); @@ -2102,7 +2053,7 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata) etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0); if (drvdata->numvmidc > 4) - etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR1); + etm4x_relaxed_write32(csa, state->trcvmidcctlr1, TRCVMIDCCTLR1); etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); @@ -2125,47 +2076,16 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata) etm4_cs_lock(drvdata, csa); } -static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) -{ - if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED) - return; +static const struct coresight_ops etm4_cs_ops = { + .trace_id = coresight_etm_get_trace_id, + .source_ops = &etm4_source_ops, +}; - if (coresight_get_mode(drvdata->csdev)) - __etm4_cpu_restore(drvdata); -} - -static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, - void *v) -{ - struct etmv4_drvdata *drvdata; - unsigned int cpu = smp_processor_id(); - - if (!etmdrvdata[cpu]) - return NOTIFY_OK; - - drvdata = etmdrvdata[cpu]; - - if (WARN_ON_ONCE(drvdata->cpu != cpu)) - return NOTIFY_BAD; - - switch (cmd) { - case CPU_PM_ENTER: - if (etm4_cpu_save(drvdata)) - return NOTIFY_BAD; - break; - case CPU_PM_EXIT: - case CPU_PM_ENTER_FAILED: - etm4_cpu_restore(drvdata); - break; - default: - return NOTIFY_DONE; - } - - return NOTIFY_OK; -} - -static struct notifier_block etm4_cpu_pm_nb = { - .notifier_call = etm4_cpu_pm_notify, +static const struct coresight_ops etm4_cs_pm_ops = { + .trace_id = coresight_etm_get_trace_id, + .source_ops = &etm4_source_ops, + .pm_save_disable = etm4_cpu_save, + .pm_restore_enable = etm4_cpu_restore, }; /* Setup PM. Deals with error conditions and counts */ @@ -2173,17 +2093,6 @@ static int __init etm4_pm_setup(void) { int ret; - ret = cpu_pm_register_notifier(&etm4_cpu_pm_nb); - if (ret) - return ret; - - ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING, - "arm/coresight4:starting", - etm4_starting_cpu, etm4_dying_cpu); - - if (ret) - goto unregister_notifier; - ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "arm/coresight4:online", etm4_online_cpu, NULL); @@ -2194,24 +2103,28 @@ static int __init etm4_pm_setup(void) return 0; } - /* failed dyn state - remove others */ - cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); - -unregister_notifier: - cpu_pm_unregister_notifier(&etm4_cpu_pm_nb); return ret; } static void etm4_pm_clear(void) { - cpu_pm_unregister_notifier(&etm4_cpu_pm_nb); - cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); if (hp_online) { cpuhp_remove_state_nocalls(hp_online); hp_online = 0; } } +static bool etm4x_always_pm_save(struct device *dev, struct csdev_access *csa) +{ + /* + * Only IO mem ETM devices will benefit from skipping PM save and only + * DT has the option to control it, not ACPI. Otherwise system register + * based ETMs and ETEs will always lose context on CPU power down, so + * always save. + */ + return !csa->io_mem || is_acpi_device_node(dev_fwnode(dev)); +} + static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) { int ret; @@ -2221,6 +2134,7 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) struct coresight_desc desc = { 0 }; u8 major, minor; char *type_name; + bool pm_save; if (!drvdata) return -EINVAL; @@ -2248,6 +2162,21 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) etm4_set_default(&drvdata->config); + if (etm4x_always_pm_save(dev, init_arg->csa)) + pm_save = true; + else if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE) + pm_save = coresight_loses_context_with_cpu(dev); + else + pm_save = pm_save_enable != PARAM_PM_SAVE_NEVER; + + if (pm_save) { + drvdata->save_state = devm_kmalloc(dev, + sizeof(struct etmv4_save_state), + GFP_KERNEL); + if (!drvdata->save_state) + return -ENOMEM; + } + pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); @@ -2256,10 +2185,12 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) desc.type = CORESIGHT_DEV_TYPE_SOURCE; desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC; - desc.ops = &etm4_cs_ops; + desc.ops = etm4_pm_save_needed(drvdata) ? &etm4_cs_pm_ops : &etm4_cs_ops; desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_etmv4_groups; + desc.cpu = drvdata->cpu; + desc.flags = CORESIGHT_DESC_CPU_BOUND; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); @@ -2305,17 +2236,6 @@ static int etm4_probe(struct device *dev) if (ret) return ret; - if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE) - pm_save_enable = coresight_loses_context_with_cpu(dev) ? - PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER; - - if (pm_save_enable != PARAM_PM_SAVE_NEVER) { - drvdata->save_state = devm_kmalloc(dev, - sizeof(struct etmv4_save_state), GFP_KERNEL); - if (!drvdata->save_state) - return -ENOMEM; - } - raw_spin_lock_init(&drvdata->spinlock); drvdata->cpu = coresight_get_cpu(dev); diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index e337b6e2bf32..93c2d075cad6 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -45,9 +45,8 @@ coresight_add_out_conn(struct device *dev, } } - pdata->nr_outconns++; pdata->out_conns = - devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns, + devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns + 1, sizeof(*pdata->out_conns), GFP_KERNEL); if (!pdata->out_conns) return ERR_PTR(-ENOMEM); @@ -63,7 +62,8 @@ coresight_add_out_conn(struct device *dev, * used right away. */ *conn = *new_conn; - pdata->out_conns[pdata->nr_outconns - 1] = conn; + pdata->out_conns[pdata->nr_outconns] = conn; + pdata->nr_outconns++; return conn; } EXPORT_SYMBOL_GPL(coresight_add_out_conn); @@ -86,13 +86,13 @@ int coresight_add_in_conn(struct coresight_connection *out_conn) return 0; } - pdata->nr_inconns++; pdata->in_conns = - devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns, + devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns + 1, sizeof(*pdata->in_conns), GFP_KERNEL); if (!pdata->in_conns) return -ENOMEM; - pdata->in_conns[pdata->nr_inconns - 1] = out_conn; + pdata->in_conns[pdata->nr_inconns] = out_conn; + pdata->nr_inconns++; return 0; } EXPORT_SYMBOL_GPL(coresight_add_in_conn); diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 1ea882dffd70..dddac946659f 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -153,7 +153,7 @@ int coresight_make_links(struct coresight_device *orig, void coresight_remove_links(struct coresight_device *orig, struct coresight_connection *conn); u32 coresight_get_sink_id(struct coresight_device *csdev); -void coresight_path_assign_trace_id(struct coresight_path *path, +int coresight_path_assign_trace_id(struct coresight_path *path, enum cs_mode mode); #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X) @@ -248,6 +248,12 @@ void coresight_add_helper(struct coresight_device *csdev, void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); struct coresight_device *coresight_get_percpu_sink(int cpu); +struct coresight_device *coresight_get_source(struct coresight_path *path); +struct coresight_device *coresight_get_percpu_source_ref(int cpu); +void coresight_put_percpu_source_ref(struct coresight_device *csdev); +int coresight_enable_source(struct coresight_device *csdev, + struct perf_event *event, enum cs_mode mode, + struct coresight_path *path); void coresight_disable_source(struct coresight_device *csdev, void *data); void coresight_pause_source(struct coresight_device *csdev); int coresight_resume_source(struct coresight_device *csdev); diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index d7f5037953d6..2bfdd7b45e49 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -953,39 +953,41 @@ int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool acti unsigned long cfg_hash; int err = 0; - mutex_lock(&cscfg_mutex); + guard(mutex)(&cscfg_mutex); cfg_hash = (unsigned long)config_desc->event_ea->var; if (activate) { /* cannot be a current active value to activate this */ - if (cscfg_mgr->sysfs_active_config) { - err = -EBUSY; - goto exit_unlock; - } - err = _cscfg_activate_config(cfg_hash); - if (!err) + if (cscfg_mgr->sysfs_active_config) + return -EBUSY; + + scoped_guard(raw_spinlock_irqsave, &cscfg_mgr->sysfs_store_lock) { + err = _cscfg_activate_config(cfg_hash); + if (err) + return err; + cscfg_mgr->sysfs_active_config = cfg_hash; + } } else { - /* disable if matching current value */ - if (cscfg_mgr->sysfs_active_config == cfg_hash) { + if (cscfg_mgr->sysfs_active_config != cfg_hash) + return -EINVAL; + + scoped_guard(raw_spinlock_irqsave, &cscfg_mgr->sysfs_store_lock) { + /* disable if matching current value */ _cscfg_deactivate_config(cfg_hash); cscfg_mgr->sysfs_active_config = 0; - } else - err = -EINVAL; + } } -exit_unlock: - mutex_unlock(&cscfg_mutex); - return err; + return 0; } /* set the sysfs preset value */ void cscfg_config_sysfs_set_preset(int preset) { - mutex_lock(&cscfg_mutex); + guard(raw_spinlock_irqsave)(&cscfg_mgr->sysfs_store_lock); cscfg_mgr->sysfs_active_preset = preset; - mutex_unlock(&cscfg_mutex); } /* @@ -994,10 +996,9 @@ void cscfg_config_sysfs_set_preset(int preset) */ void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset) { - mutex_lock(&cscfg_mutex); + guard(raw_spinlock_irqsave)(&cscfg_mgr->sysfs_store_lock); *preset = cscfg_mgr->sysfs_active_preset; *cfg_hash = cscfg_mgr->sysfs_active_config; - mutex_unlock(&cscfg_mutex); } EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg); @@ -1201,6 +1202,7 @@ static int cscfg_create_device(void) INIT_LIST_HEAD(&cscfg_mgr->load_order_list); atomic_set(&cscfg_mgr->sys_active_cnt, 0); cscfg_mgr->load_state = CSCFG_NONE; + raw_spin_lock_init(&cscfg_mgr->sysfs_store_lock); /* setup the device */ dev = cscfg_device(); diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index 66e2db890d82..658e93c3705f 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -42,6 +42,7 @@ enum cscfg_load_ops { * @sysfs_active_config:Active config hash used if CoreSight controlled from sysfs. * @sysfs_active_preset:Active preset index used if CoreSight controlled from sysfs. * @load_state: A multi-stage load/unload operation is in progress. + * @sysfs_store_lock: Exclusive access sysfs stored variables. */ struct cscfg_manager { struct device dev; @@ -54,6 +55,7 @@ struct cscfg_manager { u32 sysfs_active_config; int sysfs_active_preset; enum cscfg_load_ops load_state; + raw_spinlock_t sysfs_store_lock; }; /* get reference to dev in cscfg_manager */ diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index d2a6ed8bcc74..4b010f8bc4c0 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -5,26 +5,12 @@ */ #include -#include #include #include #include "coresight-priv.h" #include "coresight-trace-id.h" -/* - * Use IDR to map the hash of the source's device name - * to the pointer of path for the source. The idr is for - * the sources which aren't associated with CPU. - */ -static DEFINE_IDR(path_idr); - -/* - * When operating Coresight drivers from the sysFS interface, only a single - * path can exist from a tracer (associated to a CPU) to a sink. - */ -static DEFINE_PER_CPU(struct coresight_path *, tracer_path); - ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute *attr, char *buf) { @@ -53,6 +39,26 @@ ssize_t coresight_simple_show32(struct device *_dev, } EXPORT_SYMBOL_GPL(coresight_simple_show32); +static void coresight_source_get_refcnt(struct coresight_device *csdev) +{ + /* + * There could be multiple applications driving the software + * source. So keep the refcount for each such user when the + * source is already enabled. + * + * No need to increment the reference counter for other source + * types, as multiple enables are the same as a single enable. + */ + if (coresight_is_software_source(csdev)) + csdev->refcnt++; +} + +static void coresight_source_put_refcnt(struct coresight_device *csdev) +{ + if (coresight_is_software_source(csdev)) + csdev->refcnt--; +} + static int coresight_enable_source_sysfs(struct coresight_device *csdev, enum cs_mode mode, struct coresight_path *path) @@ -66,19 +72,19 @@ static int coresight_enable_source_sysfs(struct coresight_device *csdev, */ lockdep_assert_held(&coresight_mutex); if (coresight_get_mode(csdev) != CS_MODE_SYSFS) { - ret = source_ops(csdev)->enable(csdev, NULL, mode, path); + ret = coresight_enable_source(csdev, NULL, mode, path); if (ret) return ret; } - csdev->refcnt++; + coresight_source_get_refcnt(csdev); return 0; } /** - * coresight_disable_source_sysfs - Drop the reference count by 1 and disable - * the device if there are no users left. + * coresight_disable_source_sysfs - Drop the reference count by 1 for software + * sources. Disable the device if there are no users left. * * @csdev: The coresight device to disable * @data: Opaque data to pass on to the disable function of the source device. @@ -93,7 +99,7 @@ static bool coresight_disable_source_sysfs(struct coresight_device *csdev, if (coresight_get_mode(csdev) != CS_MODE_SYSFS) return false; - csdev->refcnt--; + coresight_source_put_refcnt(csdev); if (csdev->refcnt == 0) { coresight_disable_source(csdev, data); return true; @@ -162,18 +168,17 @@ static int coresight_validate_source_sysfs(struct coresight_device *csdev, return -EINVAL; } + if (coresight_is_percpu_source(csdev) && !cpu_online(csdev->cpu)) + return -ENODEV; + return 0; } int coresight_enable_sysfs(struct coresight_device *csdev) { - int cpu, ret = 0; + int ret = 0; struct coresight_device *sink; struct coresight_path *path; - enum coresight_dev_subtype_source subtype; - u32 hash; - - subtype = csdev->subtype.source_subtype; mutex_lock(&coresight_mutex); @@ -188,13 +193,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev) * doesn't hold coresight_mutex. */ if (coresight_get_mode(csdev) == CS_MODE_SYSFS) { - /* - * There could be multiple applications driving the software - * source. So keep the refcount for each such user when the - * source is already enabled. - */ - if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) - csdev->refcnt++; + coresight_source_get_refcnt(csdev); goto out; } @@ -211,8 +210,8 @@ int coresight_enable_sysfs(struct coresight_device *csdev) goto out; } - coresight_path_assign_trace_id(path, CS_MODE_SYSFS); - if (!IS_VALID_CS_TRACE_ID(path->trace_id)) + ret = coresight_path_assign_trace_id(path, CS_MODE_SYSFS); + if (ret) goto err_path; ret = coresight_enable_path(path, CS_MODE_SYSFS); @@ -223,35 +222,6 @@ int coresight_enable_sysfs(struct coresight_device *csdev) if (ret) goto err_source; - switch (subtype) { - case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: - /* - * When working from sysFS it is important to keep track - * of the paths that were created so that they can be - * undone in 'coresight_disable()'. Since there can only - * be a single session per tracer (when working from sysFS) - * a per-cpu variable will do just fine. - */ - cpu = source_ops(csdev)->cpu_id(csdev); - per_cpu(tracer_path, cpu) = path; - break; - case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: - case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: - case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: - /* - * Use the hash of source's device name as ID - * and map the ID to the pointer of the path. - */ - hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); - ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL); - if (ret) - goto err_source; - break; - default: - /* We can't be here */ - break; - } - out: mutex_unlock(&coresight_mutex); return ret; @@ -267,9 +237,8 @@ EXPORT_SYMBOL_GPL(coresight_enable_sysfs); void coresight_disable_sysfs(struct coresight_device *csdev) { - int cpu, ret; - struct coresight_path *path = NULL; - u32 hash; + struct coresight_path *path; + int ret; mutex_lock(&coresight_mutex); @@ -277,32 +246,15 @@ void coresight_disable_sysfs(struct coresight_device *csdev) if (ret) goto out; + /* + * coresight_disable_source_sysfs() clears the 'csdev->path' pointer + * when disabling the source. Retrieve the path pointer here. + */ + path = csdev->path; + if (!coresight_disable_source_sysfs(csdev, NULL)) goto out; - switch (csdev->subtype.source_subtype) { - case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC: - cpu = source_ops(csdev)->cpu_id(csdev); - path = per_cpu(tracer_path, cpu); - per_cpu(tracer_path, cpu) = NULL; - break; - case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE: - case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM: - case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS: - hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev))); - /* Find the path by the hash. */ - path = idr_find(&path_idr, hash); - if (path == NULL) { - pr_err("Path is not found for %s\n", dev_name(&csdev->dev)); - goto out; - } - idr_remove(&path_idr, hash); - break; - default: - /* We can't be here */ - break; - } - coresight_disable_path(path); coresight_release_path(path); @@ -360,6 +312,13 @@ static ssize_t enable_source_store(struct device *dev, if (ret) return ret; + /* + * CoreSight hotplug callbacks in core layer control a activated path + * from its source to sink. Taking hotplug lock here protects a race + * condition with hotplug callbacks. + */ + guard(cpus_read_lock)(); + if (val) { ret = coresight_enable_sysfs(csdev); if (ret) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 4dc1defe27a5..361a433e6f0c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -154,7 +154,7 @@ tmc_pages_get_offset(struct tmc_pages *tmc_pages, dma_addr_t addr) for (i = 0; i < tmc_pages->nr_pages; i++) { page_start = tmc_pages->daddrs[i]; if (addr >= page_start && addr < (page_start + PAGE_SIZE)) - return i * PAGE_SIZE + (addr - page_start); + return (long)i * PAGE_SIZE + (addr - page_start); } return -EINVAL; @@ -1379,7 +1379,7 @@ alloc_etr_buf(struct tmc_drvdata *drvdata, struct perf_event *event, node = (event->cpu == -1) ? NUMA_NO_NODE : cpu_to_node(event->cpu); /* Use the minimum limit if the required size is smaller */ - size = nr_pages << PAGE_SHIFT; + size = (ssize_t)nr_pages << PAGE_SHIFT; size = max_t(ssize_t, size, TMC_ETR_PERF_MIN_BUF_SIZE); /* diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 1511f8eb95af..c7cbca45f2de 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -116,6 +116,20 @@ static int trbe_errata_cpucaps[] = { */ #define TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP_BYTES 256 +/* + * struct trbe_save_state: Register values representing TRBE state + * @trblimitr - Trace Buffer Limit Address Register value + * @trbbaser - Trace Buffer Base Register value + * @trbptr - Trace Buffer Write Pointer Register value + * @trbsr - Trace Buffer Status Register value + */ +struct trbe_save_state { + u64 trblimitr; + u64 trbbaser; + u64 trbptr; + u64 trbsr; +}; + /* * struct trbe_cpudata: TRBE instance specific data * @trbe_flag - TRBE dirty/access flag support @@ -134,6 +148,7 @@ struct trbe_cpudata { enum cs_mode mode; struct trbe_buf *buf; struct trbe_drvdata *drvdata; + struct trbe_save_state save_state; DECLARE_BITMAP(errata, TRBE_ERRATA_MAX); }; @@ -1189,6 +1204,46 @@ static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) return IRQ_HANDLED; } +static int arm_trbe_save(struct coresight_device *csdev) +{ + struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); + struct trbe_save_state *state = &cpudata->save_state; + + state->trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); + + /* Disable the unit, ensure the writes to memory are complete */ + if (state->trblimitr & TRBLIMITR_EL1_E) + trbe_drain_and_disable_local(cpudata); + + state->trbbaser = read_sysreg_s(SYS_TRBBASER_EL1); + state->trbptr = read_sysreg_s(SYS_TRBPTR_EL1); + state->trbsr = read_sysreg_s(SYS_TRBSR_EL1); + return 0; +} + +static void arm_trbe_restore(struct coresight_device *csdev) +{ + struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); + struct trbe_save_state *state = &cpudata->save_state; + + write_sysreg_s(state->trbbaser, SYS_TRBBASER_EL1); + write_sysreg_s(state->trbptr, SYS_TRBPTR_EL1); + write_sysreg_s(state->trbsr, SYS_TRBSR_EL1); + + if (!(state->trblimitr & TRBLIMITR_EL1_E)) { + write_sysreg_s(state->trblimitr, SYS_TRBLIMITR_EL1); + } else { + /* + * The section K5.5 Context switching, Arm ARM (ARM DDI 0487 + * L.a), S_PKLXF requires a Context synchronization event to + * guarantee the Trace Buffer Unit will observe the new values + * of the system registers. + */ + isb(); + set_trbe_enabled(cpudata, state->trblimitr); + } +} + static const struct coresight_ops_sink arm_trbe_sink_ops = { .enable = arm_trbe_enable, .disable = arm_trbe_disable, @@ -1198,7 +1253,9 @@ static const struct coresight_ops_sink arm_trbe_sink_ops = { }; static const struct coresight_ops arm_trbe_cs_ops = { - .sink_ops = &arm_trbe_sink_ops, + .pm_save_disable = arm_trbe_save, + .pm_restore_enable = arm_trbe_restore, + .sink_ops = &arm_trbe_sink_ops, }; static ssize_t align_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1289,6 +1346,8 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp desc.ops = &arm_trbe_cs_ops; desc.groups = arm_trbe_groups; desc.dev = dev; + desc.cpu = cpu; + desc.flags = CORESIGHT_DESC_CPU_BOUND; trbe_csdev = coresight_register(&desc); if (IS_ERR(trbe_csdev)) goto cpu_clear; diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c index 5776f63468fa..20a950b9dd4f 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.c +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c @@ -337,6 +337,7 @@ static void smb_sync_perf_buffer(struct smb_drv_data *drvdata, unsigned long to_copy; long pg_idx, pg_offset; + head %= (unsigned long)buf->nr_pages << PAGE_SHIFT; pg_idx = head >> PAGE_SHIFT; pg_offset = head & (PAGE_SIZE - 1); diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c index bcc11dabdf22..6dc918c4ae17 100644 --- a/drivers/iio/accel/adxl313_core.c +++ b/drivers/iio/accel/adxl313_core.c @@ -1240,7 +1240,9 @@ int adxl313_core_probe(struct device *dev, data->regmap = regmap; data->chip_info = chip_info; - mutex_init(&data->lock); + ret = devm_mutex_init(dev, &data->lock); + if (ret) + return ret; indio_dev->name = chip_info->name; indio_dev->info = &adxl313_info; @@ -1250,10 +1252,8 @@ int adxl313_core_probe(struct device *dev, indio_dev->available_scan_masks = adxl313_scan_masks; ret = adxl313_setup(dev, data, setup); - if (ret) { - dev_err(dev, "ADXL313 setup failed\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "ADXL313 setup failed\n"); int_line = adxl313_get_int_type(dev, &irq); if (int_line == ADXL313_INT_NONE) { diff --git a/drivers/iio/accel/adxl313_i2c.c b/drivers/iio/accel/adxl313_i2c.c index b67ff0b4dc54..6736b83f23bd 100644 --- a/drivers/iio/accel/adxl313_i2c.c +++ b/drivers/iio/accel/adxl313_i2c.c @@ -65,6 +65,7 @@ MODULE_DEVICE_TABLE(of, adxl313_of_match); static int adxl313_i2c_probe(struct i2c_client *client) { const struct adxl313_chip_info *chip_data; + struct device *dev = &client->dev; struct regmap *regmap; /* @@ -75,13 +76,10 @@ static int adxl313_i2c_probe(struct i2c_client *client) regmap = devm_regmap_init_i2c(client, &adxl31x_i2c_regmap_config[chip_data->type]); - if (IS_ERR(regmap)) { - dev_err(&client->dev, "Error initializing i2c regmap: %ld\n", - PTR_ERR(regmap)); - return PTR_ERR(regmap); - } + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing i2c regmap\n"); - return adxl313_core_probe(&client->dev, regmap, chip_data, NULL); + return adxl313_core_probe(dev, regmap, chip_data, NULL); } static struct i2c_driver adxl313_i2c_driver = { diff --git a/drivers/iio/accel/adxl313_spi.c b/drivers/iio/accel/adxl313_spi.c index dedb0885c277..d096ea0632ba 100644 --- a/drivers/iio/accel/adxl313_spi.c +++ b/drivers/iio/accel/adxl313_spi.c @@ -70,6 +70,7 @@ static int adxl313_spi_setup(struct device *dev, struct regmap *regmap) static int adxl313_spi_probe(struct spi_device *spi) { const struct adxl313_chip_info *chip_data; + struct device *dev = &spi->dev; struct regmap *regmap; int ret; @@ -83,14 +84,10 @@ static int adxl313_spi_probe(struct spi_device *spi) regmap = devm_regmap_init_spi(spi, &adxl31x_spi_regmap_config[chip_data->type]); - if (IS_ERR(regmap)) { - dev_err(&spi->dev, "Error initializing spi regmap: %ld\n", - PTR_ERR(regmap)); - return PTR_ERR(regmap); - } + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing spi regmap\n"); - return adxl313_core_probe(&spi->dev, regmap, - chip_data, &adxl313_spi_setup); + return adxl313_core_probe(dev, regmap, chip_data, &adxl313_spi_setup); } static const struct spi_device_id adxl313_spi_id[] = { diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c index af84c0043c6c..511fb610436c 100644 --- a/drivers/iio/accel/adxl345_i2c.c +++ b/drivers/iio/accel/adxl345_i2c.c @@ -43,8 +43,8 @@ static const struct adxl345_chip_info adxl375_i2c_info = { }; static const struct i2c_device_id adxl345_i2c_id[] = { - { "adxl345", (kernel_ulong_t)&adxl345_i2c_info }, - { "adxl375", (kernel_ulong_t)&adxl375_i2c_info }, + { .name = "adxl345", .driver_data = (kernel_ulong_t)&adxl345_i2c_info }, + { .name = "adxl375", .driver_data = (kernel_ulong_t)&adxl375_i2c_info }, { } }; MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id); diff --git a/drivers/iio/accel/adxl355_core.c b/drivers/iio/accel/adxl355_core.c index 8f90c58f4100..89ac62ff4d04 100644 --- a/drivers/iio/accel/adxl355_core.c +++ b/drivers/iio/accel/adxl355_core.c @@ -336,10 +336,8 @@ static int adxl355_setup(struct adxl355_data *data) return ret; do { - if (--retries == 0) { - dev_err(data->dev, "Shadow registers mismatch\n"); - return -EIO; - } + if (--retries == 0) + return dev_err_probe(data->dev, -EIO, "Shadow registers mismatch\n"); /* * Perform a software reset to make sure the device is in a consistent @@ -351,7 +349,7 @@ static int adxl355_setup(struct adxl355_data *data) return ret; /* Wait at least 5ms after software reset */ - usleep_range(5000, 10000); + fsleep(5 * USEC_PER_MSEC); /* Read shadow registers for comparison */ ret = regmap_bulk_read(data->regmap, @@ -775,10 +773,8 @@ static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq) irq); ret = devm_iio_trigger_register(data->dev, data->dready_trig); - if (ret) { - dev_err(data->dev, "iio trigger register failed\n"); - return ret; - } + if (ret) + return dev_err_probe(data->dev, ret, "iio trigger register failed\n"); indio_dev->trig = iio_trigger_get(data->dready_trig); @@ -802,7 +798,9 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap, data->dev = dev; data->op_mode = ADXL355_STANDBY; data->chip_info = chip_info; - mutex_init(&data->lock); + ret = devm_mutex_init(dev, &data->lock); + if (ret) + return ret; indio_dev->name = chip_info->name; indio_dev->info = &adxl355_info; @@ -812,18 +810,14 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap, indio_dev->available_scan_masks = adxl355_avail_scan_masks; ret = adxl355_setup(data); - if (ret) { - dev_err(dev, "ADXL355 setup failed\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "ADXL355 setup failed\n"); ret = devm_iio_triggered_buffer_setup(dev, indio_dev, &iio_pollfunc_store_time, &adxl355_trigger_handler, NULL); - if (ret) { - dev_err(dev, "iio triggered buffer setup failed\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "iio triggered buffer setup failed\n"); irq = fwnode_irq_get_byname(dev_fwnode(dev), "DRDY"); if (irq > 0) { diff --git a/drivers/iio/accel/adxl355_i2c.c b/drivers/iio/accel/adxl355_i2c.c index 1a512c7b792b..0b6b016bd358 100644 --- a/drivers/iio/accel/adxl355_i2c.c +++ b/drivers/iio/accel/adxl355_i2c.c @@ -23,6 +23,7 @@ static const struct regmap_config adxl355_i2c_regmap_config = { static int adxl355_i2c_probe(struct i2c_client *client) { struct regmap *regmap; + struct device *dev = &client->dev; const struct adxl355_chip_info *chip_data; chip_data = i2c_get_match_data(client); @@ -30,19 +31,15 @@ static int adxl355_i2c_probe(struct i2c_client *client) return -ENODEV; regmap = devm_regmap_init_i2c(client, &adxl355_i2c_regmap_config); - if (IS_ERR(regmap)) { - dev_err(&client->dev, "Error initializing i2c regmap: %ld\n", - PTR_ERR(regmap)); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing i2c regmap\n"); - return PTR_ERR(regmap); - } - - return adxl355_core_probe(&client->dev, regmap, chip_data); + return adxl355_core_probe(dev, regmap, chip_data); } static const struct i2c_device_id adxl355_i2c_id[] = { - { "adxl355", (kernel_ulong_t)&adxl35x_chip_info[ADXL355] }, - { "adxl359", (kernel_ulong_t)&adxl35x_chip_info[ADXL359] }, + { .name = "adxl355", .driver_data = (kernel_ulong_t)&adxl35x_chip_info[ADXL355] }, + { .name = "adxl359", .driver_data = (kernel_ulong_t)&adxl35x_chip_info[ADXL359] }, { } }; MODULE_DEVICE_TABLE(i2c, adxl355_i2c_id); diff --git a/drivers/iio/accel/adxl355_spi.c b/drivers/iio/accel/adxl355_spi.c index 869e3e57d6f7..347ed62b6582 100644 --- a/drivers/iio/accel/adxl355_spi.c +++ b/drivers/iio/accel/adxl355_spi.c @@ -26,6 +26,7 @@ static const struct regmap_config adxl355_spi_regmap_config = { static int adxl355_spi_probe(struct spi_device *spi) { const struct adxl355_chip_info *chip_data; + struct device *dev = &spi->dev; struct regmap *regmap; chip_data = spi_get_device_match_data(spi); @@ -33,14 +34,10 @@ static int adxl355_spi_probe(struct spi_device *spi) return -EINVAL; regmap = devm_regmap_init_spi(spi, &adxl355_spi_regmap_config); - if (IS_ERR(regmap)) { - dev_err(&spi->dev, "Error initializing spi regmap: %ld\n", - PTR_ERR(regmap)); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing spi regmap\n"); - return PTR_ERR(regmap); - } - - return adxl355_core_probe(&spi->dev, regmap, chip_data); + return adxl355_core_probe(dev, regmap, chip_data); } static const struct spi_device_id adxl355_spi_id[] = { diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c index 0c04b2bb7efb..63a0b182824f 100644 --- a/drivers/iio/accel/adxl367.c +++ b/drivers/iio/accel/adxl367.c @@ -1445,7 +1445,9 @@ int adxl367_probe(struct device *dev, const struct adxl367_ops *ops, st->context = context; st->ops = ops; - mutex_init(&st->lock); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; indio_dev->channels = adxl367_channels; indio_dev->num_channels = ARRAY_SIZE(adxl367_channels); diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2c.c index 1c7d2eb054a2..fb50ded68bae 100644 --- a/drivers/iio/accel/adxl367_i2c.c +++ b/drivers/iio/accel/adxl367_i2c.c @@ -61,7 +61,7 @@ static int adxl367_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adxl367_i2c_id[] = { - { "adxl367" }, + { .name = "adxl367" }, { } }; MODULE_DEVICE_TABLE(i2c, adxl367_i2c_id); diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index 545a21e5a308..e375d068a3f5 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -1299,7 +1299,9 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, st->irq = irq; st->chip_info = chip_info; - mutex_init(&st->threshold_m); + ret = devm_mutex_init(dev, &st->threshold_m); + if (ret < 0) + return ret; indio_dev->channels = adxl372_channels; indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); @@ -1314,10 +1316,8 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, } ret = adxl372_setup(st); - if (ret < 0) { - dev_err(dev, "ADXL372 setup failed\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "ADXL372 setup failed\n"); if (chip_info->fifo_supported) { ret = adxl372_buffer_setup(indio_dev); diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index ca2cabf24938..ddb125075778 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -44,8 +44,8 @@ static int adxl372_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adxl372_i2c_id[] = { - { "adxl371", (kernel_ulong_t)&adxl371_chip_info }, - { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, + { .name = "adxl371", .driver_data = (kernel_ulong_t)&adxl371_chip_info }, + { .name = "adxl372", .driver_data = (kernel_ulong_t)&adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c index e7bb32fbc475..7dca5523091f 100644 --- a/drivers/iio/accel/adxl380.c +++ b/drivers/iio/accel/adxl380.c @@ -1967,7 +1967,9 @@ int adxl380_probe(struct device *dev, struct regmap *regmap, st->chip_info = chip_info; st->odr = ADXL380_ODR_DSM; - mutex_init(&st->lock); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; indio_dev->channels = adxl380_channels; indio_dev->num_channels = ARRAY_SIZE(adxl380_channels); diff --git a/drivers/iio/accel/adxl380_i2c.c b/drivers/iio/accel/adxl380_i2c.c index bd8782d08c7d..367a29298047 100644 --- a/drivers/iio/accel/adxl380_i2c.c +++ b/drivers/iio/accel/adxl380_i2c.c @@ -33,10 +33,10 @@ static int adxl380_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adxl380_i2c_id[] = { - { "adxl318", (kernel_ulong_t)&adxl318_chip_info }, - { "adxl319", (kernel_ulong_t)&adxl319_chip_info }, - { "adxl380", (kernel_ulong_t)&adxl380_chip_info }, - { "adxl382", (kernel_ulong_t)&adxl382_chip_info }, + { .name = "adxl318", .driver_data = (kernel_ulong_t)&adxl318_chip_info }, + { .name = "adxl319", .driver_data = (kernel_ulong_t)&adxl319_chip_info }, + { .name = "adxl380", .driver_data = (kernel_ulong_t)&adxl380_chip_info }, + { .name = "adxl382", .driver_data = (kernel_ulong_t)&adxl382_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, adxl380_i2c_id); diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 7bc6761f5135..e643bc73eefe 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -1083,11 +1083,11 @@ static int bma180_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); static const struct i2c_device_id bma180_ids[] = { - { "bma023", (kernel_ulong_t)&bma180_part_info[BMA023] }, - { "bma150", (kernel_ulong_t)&bma180_part_info[BMA150] }, - { "bma180", (kernel_ulong_t)&bma180_part_info[BMA180] }, - { "bma250", (kernel_ulong_t)&bma180_part_info[BMA250] }, - { "smb380", (kernel_ulong_t)&bma180_part_info[BMA150] }, + { .name = "bma023", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA023] }, + { .name = "bma150", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA150] }, + { .name = "bma180", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA180] }, + { .name = "bma250", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA250] }, + { .name = "smb380", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA150] }, { } }; diff --git a/drivers/iio/accel/bma220_i2c.c b/drivers/iio/accel/bma220_i2c.c index 8b6f8e305c8c..b058e97bc6a6 100644 --- a/drivers/iio/accel/bma220_i2c.c +++ b/drivers/iio/accel/bma220_i2c.c @@ -47,7 +47,7 @@ static const struct of_device_id bma220_i2c_match[] = { MODULE_DEVICE_TABLE(of, bma220_i2c_match); static const struct i2c_device_id bma220_i2c_id[] = { - { "bma220" }, + { .name = "bma220" }, { } }; MODULE_DEVICE_TABLE(i2c, bma220_i2c_id); diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c index 24a390c3ae66..23d394c5a791 100644 --- a/drivers/iio/accel/bma400_i2c.c +++ b/drivers/iio/accel/bma400_i2c.c @@ -28,7 +28,7 @@ static int bma400_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bma400_i2c_ids[] = { - { "bma400" }, + { .name = "bma400" }, { } }; MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids); diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index b4604f441553..3315172742d0 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -245,16 +245,16 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); static const struct i2c_device_id bmc150_accel_id[] = { - {"bma222"}, - {"bma222e"}, - {"bma250e"}, - {"bma253"}, - {"bma254"}, - {"bma255"}, - {"bma280"}, - {"bmc150_accel"}, - {"bmc156_accel", BOSCH_BMC156}, - {"bmi055_accel"}, + { .name = "bma222", .driver_data = BOSCH_UNKNOWN }, + { .name = "bma222e", .driver_data = BOSCH_UNKNOWN }, + { .name = "bma250e", .driver_data = BOSCH_UNKNOWN }, + { .name = "bma253", .driver_data = BOSCH_UNKNOWN }, + { .name = "bma254", .driver_data = BOSCH_UNKNOWN }, + { .name = "bma255", .driver_data = BOSCH_UNKNOWN }, + { .name = "bma280", .driver_data = BOSCH_UNKNOWN }, + { .name = "bmc150_accel", .driver_data = BOSCH_UNKNOWN }, + { .name = "bmc156_accel", .driver_data = BOSCH_BMC156 }, + { .name = "bmi055_accel", .driver_data = BOSCH_UNKNOWN }, { } }; diff --git a/drivers/iio/accel/bmi088-accel-i2c.c b/drivers/iio/accel/bmi088-accel-i2c.c index 310f863029bb..d9468b1c5aee 100644 --- a/drivers/iio/accel/bmi088-accel-i2c.c +++ b/drivers/iio/accel/bmi088-accel-i2c.c @@ -45,9 +45,9 @@ static const struct of_device_id bmi088_of_match[] = { MODULE_DEVICE_TABLE(of, bmi088_of_match); static const struct i2c_device_id bmi088_accel_id[] = { - { "bmi085-accel", BOSCH_BMI085 }, - { "bmi088-accel", BOSCH_BMI088 }, - { "bmi090l-accel", BOSCH_BMI090L }, + { .name = "bmi085-accel", .driver_data = BOSCH_BMI085 }, + { .name = "bmi088-accel", .driver_data = BOSCH_BMI088 }, + { .name = "bmi090l-accel", .driver_data = BOSCH_BMI090L }, { } }; MODULE_DEVICE_TABLE(i2c, bmi088_accel_id); diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c index c2dd123b9021..15acbe1c2cbd 100644 --- a/drivers/iio/accel/da280.c +++ b/drivers/iio/accel/da280.c @@ -162,9 +162,9 @@ static const struct acpi_device_id da280_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, da280_acpi_match); static const struct i2c_device_id da280_i2c_id[] = { - { "da217", (kernel_ulong_t)&da217_match_data }, - { "da226", (kernel_ulong_t)&da226_match_data }, - { "da280", (kernel_ulong_t)&da280_match_data }, + { .name = "da217", .driver_data = (kernel_ulong_t)&da217_match_data }, + { .name = "da226", .driver_data = (kernel_ulong_t)&da226_match_data }, + { .name = "da280", .driver_data = (kernel_ulong_t)&da280_match_data }, { } }; MODULE_DEVICE_TABLE(i2c, da280_i2c_id); diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c index e1df7b009d89..dcb69c8eaf09 100644 --- a/drivers/iio/accel/da311.c +++ b/drivers/iio/accel/da311.c @@ -268,7 +268,7 @@ static int da311_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume); static const struct i2c_device_id da311_i2c_id[] = { - { "da311" }, + { .name = "da311" }, { } }; MODULE_DEVICE_TABLE(i2c, da311_i2c_id); diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c index 33f225d73e7b..2957bf55d110 100644 --- a/drivers/iio/accel/dmard06.c +++ b/drivers/iio/accel/dmard06.c @@ -199,9 +199,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard06_pm_ops, dmard06_suspend, dmard06_resume); static const struct i2c_device_id dmard06_id[] = { - { "dmard05" }, - { "dmard06" }, - { "dmard07" }, + { .name = "dmard05" }, + { .name = "dmard06" }, + { .name = "dmard07" }, { } }; MODULE_DEVICE_TABLE(i2c, dmard06_id); diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c index d9290e3b9c46..fe35a1270786 100644 --- a/drivers/iio/accel/dmard09.c +++ b/drivers/iio/accel/dmard09.c @@ -123,7 +123,7 @@ static int dmard09_probe(struct i2c_client *client) } static const struct i2c_device_id dmard09_id[] = { - { "dmard09" }, + { .name = "dmard09" }, { } }; diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c index 575e8510e1bd..8ba00fd57901 100644 --- a/drivers/iio/accel/dmard10.c +++ b/drivers/iio/accel/dmard10.c @@ -229,7 +229,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, dmard10_resume); static const struct i2c_device_id dmard10_i2c_id[] = { - { "dmard10" }, + { .name = "dmard10" }, { } }; MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id); diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c index 106198a12474..fa46f5aa34f7 100644 --- a/drivers/iio/accel/fxls8962af-i2c.c +++ b/drivers/iio/accel/fxls8962af-i2c.c @@ -28,10 +28,10 @@ static int fxls8962af_probe(struct i2c_client *client) } static const struct i2c_device_id fxls8962af_id[] = { - { "fxls8962af", fxls8962af }, - { "fxls8964af", fxls8964af }, - { "fxls8967af", fxls8967af }, - { "fxls8974cf", fxls8974cf }, + { .name = "fxls8962af", .driver_data = fxls8962af }, + { .name = "fxls8964af", .driver_data = fxls8964af }, + { .name = "fxls8967af", .driver_data = fxls8967af }, + { .name = "fxls8974cf", .driver_data = fxls8974cf }, { } }; MODULE_DEVICE_TABLE(i2c, fxls8962af_id); diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 2ff591b3458f..2bf05ab5235e 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -3,6 +3,7 @@ * HID Sensors Driver * Copyright (c) 2012, Intel Corporation. */ +#include #include #include #include @@ -119,17 +120,6 @@ static const struct iio_chan_spec gravity_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP), }; -/* Adjust channel real bits based on report descriptor */ -static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - /* Channel read_raw handler */ static int accel_3d_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -297,19 +287,20 @@ static int accel_3d_parse_report(struct platform_device *pdev, struct accel_3d_state *st) { int ret; - int i; - for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) { + for (unsigned int ch = CHANNEL_SCAN_INDEX_X; ch <= CHANNEL_SCAN_INDEX_Z; ch++) { ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, usage_id, - HID_USAGE_SENSOR_ACCEL_X_AXIS + i, - &st->accel[CHANNEL_SCAN_INDEX_X + i]); + HID_USAGE_SENSOR_ACCEL_X_AXIS + ch, + &st->accel[ch]); if (ret < 0) break; - accel_3d_adjust_channel_bit_mask(channels, - CHANNEL_SCAN_INDEX_X + i, - st->accel[CHANNEL_SCAN_INDEX_X + i].size); + channels[ch].scan_type = (struct iio_scan_type) { + .format = 's', + .realbits = BYTES_TO_BITS(st->accel[ch].size), + .storagebits = BITS_PER_TYPE(u32), + }; } dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n", st->accel[0].index, diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 2823ddde4bf2..8a082ff034dd 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1630,11 +1630,11 @@ static const struct dev_pm_ops kxcjk1013_pm_ops = { }; static const struct i2c_device_id kxcjk1013_id[] = { - { "kxcjk1013", (kernel_ulong_t)&kxcjk1013_info }, - { "kxcj91008", (kernel_ulong_t)&kxcj91008_info }, - { "kxtj21009", (kernel_ulong_t)&kxtj21009_info }, - { "kxtf9", (kernel_ulong_t)&kxtf9_info }, - { "kx023-1025", (kernel_ulong_t)&kx0231025_info }, + { .name = "kxcjk1013", .driver_data = (kernel_ulong_t)&kxcjk1013_info }, + { .name = "kxcj91008", .driver_data = (kernel_ulong_t)&kxcj91008_info }, + { .name = "kxtj21009", .driver_data = (kernel_ulong_t)&kxtj21009_info }, + { .name = "kxtf9", .driver_data = (kernel_ulong_t)&kxtf9_info }, + { .name = "kx023-1025", .driver_data = (kernel_ulong_t)&kx0231025_info }, { } }; MODULE_DEVICE_TABLE(i2c, kxcjk1013_id); diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c index 1fa88b99149e..8f3314db82d2 100644 --- a/drivers/iio/accel/kxsd9-i2c.c +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -43,7 +43,7 @@ static const struct of_device_id kxsd9_of_match[] = { MODULE_DEVICE_TABLE(of, kxsd9_of_match); static const struct i2c_device_id kxsd9_i2c_id[] = { - { "kxsd9" }, + { .name = "kxsd9" }, { } }; MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id); diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c index 3e494f9ddc56..b45897210a62 100644 --- a/drivers/iio/accel/mc3230.c +++ b/drivers/iio/accel/mc3230.c @@ -230,8 +230,8 @@ static int mc3230_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(mc3230_pm_ops, mc3230_suspend, mc3230_resume); static const struct i2c_device_id mc3230_i2c_id[] = { - { "mc3230", (kernel_ulong_t)&mc3230_chip_info }, - { "mc3510c", (kernel_ulong_t)&mc3510c_chip_info }, + { .name = "mc3230", .driver_data = (kernel_ulong_t)&mc3230_chip_info }, + { .name = "mc3510c", .driver_data = (kernel_ulong_t)&mc3510c_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, mc3230_i2c_id); diff --git a/drivers/iio/accel/mma7455_i2c.c b/drivers/iio/accel/mma7455_i2c.c index 2ff8eb1f9ce9..9588fd133b1e 100644 --- a/drivers/iio/accel/mma7455_i2c.c +++ b/drivers/iio/accel/mma7455_i2c.c @@ -32,8 +32,8 @@ static void mma7455_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id mma7455_i2c_ids[] = { - { "mma7455" }, - { "mma7456" }, + { .name = "mma7455" }, + { .name = "mma7456" }, { } }; MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids); diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index be3213600cf4..0ecf6c06dcc6 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -259,7 +259,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, mma7660_resume); static const struct i2c_device_id mma7660_i2c_id[] = { - { "mma7660" }, + { .name = "mma7660" }, { } }; MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 15172ba2972c..1403b32e2b21 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -18,21 +18,22 @@ * TODO: orientation events */ -#include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include + +#include +#include #include #include -#include #include #include #include -#include -#include -#include -#include -#include #define MMA8452_STATUS 0x00 #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) @@ -252,6 +253,8 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *)buf); + if (ret < 0) + return ret; ret = mma8452_set_runtime_pm_state(data->client, false); @@ -704,8 +707,8 @@ static int mma8452_set_hp_filter_frequency(struct mma8452_data *data, } static int __mma8452_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct mma8452_data *data = iio_priv(indio_dev); int i, j, ret; @@ -786,8 +789,9 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, } static int mma8452_get_event_regs(struct mma8452_data *data, - const struct iio_chan_spec *chan, enum iio_event_direction dir, - const struct mma8452_event_regs **ev_reg) + const struct iio_chan_spec *chan, + enum iio_event_direction dir, + const struct mma8452_event_regs **ev_reg) { if (!chan) return -EINVAL; @@ -816,11 +820,11 @@ static int mma8452_get_event_regs(struct mma8452_data *data, } static int mma8452_read_event_value(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct mma8452_data *data = iio_priv(indio_dev); int ret, us, power_mode; @@ -879,11 +883,11 @@ static int mma8452_read_event_value(struct iio_dev *indio_dev, } static int mma8452_write_event_value(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct mma8452_data *data = iio_priv(indio_dev); int ret, reg, steps; @@ -953,8 +957,7 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, case IIO_EV_DIR_FALLING: return mma8452_freefall_mode_enabled(data); case IIO_EV_DIR_RISING: - ret = i2c_smbus_read_byte_data(data->client, - ev_regs->ev_cfg); + ret = i2c_smbus_read_byte_data(data->client, ev_regs->ev_cfg); if (ret < 0) return ret; @@ -1191,7 +1194,7 @@ static const struct attribute_group mma8452_event_attribute_group = { static const struct iio_mount_matrix * mma8452_get_mount_matrix(const struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) + const struct iio_chan_spec *chan) { struct mma8452_data *data = iio_priv(indio_dev); @@ -1514,8 +1517,9 @@ static int mma8452_reset(struct i2c_client *client) * The following code will read the reset register, and check whether * this reset works. */ - i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG2, - MMA8452_CTRL_REG2_RST); + i2c_smbus_write_byte_data(client, + MMA8452_CTRL_REG2, + MMA8452_CTRL_REG2_RST); for (i = 0; i < 10; i++) { usleep_range(100, 200); @@ -1544,6 +1548,7 @@ MODULE_DEVICE_TABLE(of, mma8452_dt_ids); static int mma8452_probe(struct i2c_client *client) { + struct device *dev = &client->dev; struct mma8452_data *data; struct iio_dev *indio_dev; int ret; @@ -1576,14 +1581,12 @@ static int mma8452_probe(struct i2c_client *client) "failed to get VDDIO regulator!\n"); ret = regulator_enable(data->vdd_reg); - if (ret) { - dev_err(&client->dev, "failed to enable VDD regulator!\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to enable VDD regulator!\n"); ret = regulator_enable(data->vddio_reg); if (ret) { - dev_err(&client->dev, "failed to enable VDDIO regulator!\n"); + dev_err_probe(dev, ret, "failed to enable VDDIO regulator!\n"); goto disable_regulator_vdd; } @@ -1645,8 +1648,8 @@ static int mma8452_probe(struct i2c_client *client) dev_dbg(&client->dev, "using interrupt line INT2\n"); } else { ret = i2c_smbus_write_byte_data(client, - MMA8452_CTRL_REG5, - data->chip_info->all_events); + MMA8452_CTRL_REG5, + data->chip_info->all_events); if (ret < 0) goto disable_regulators; @@ -1654,8 +1657,8 @@ static int mma8452_probe(struct i2c_client *client) } ret = i2c_smbus_write_byte_data(client, - MMA8452_CTRL_REG4, - data->chip_info->enabled_events); + MMA8452_CTRL_REG4, + data->chip_info->enabled_events); if (ret < 0) goto disable_regulators; @@ -1680,18 +1683,16 @@ static int mma8452_probe(struct i2c_client *client) goto trigger_cleanup; if (client->irq) { - ret = devm_request_threaded_irq(&client->dev, - client->irq, - NULL, mma8452_interrupt, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - client->name, indio_dev); + ret = request_threaded_irq(client->irq, NULL, mma8452_interrupt, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + client->name, indio_dev); if (ret) goto buffer_cleanup; } ret = pm_runtime_set_active(&client->dev); if (ret < 0) - goto buffer_cleanup; + goto free_irq; pm_runtime_enable(&client->dev); pm_runtime_set_autosuspend_delay(&client->dev, @@ -1700,7 +1701,7 @@ static int mma8452_probe(struct i2c_client *client) ret = iio_device_register(indio_dev); if (ret < 0) - goto buffer_cleanup; + goto free_irq; ret = mma8452_set_freefall_mode(data, false); if (ret < 0) @@ -1711,6 +1712,10 @@ static int mma8452_probe(struct i2c_client *client) unregister_device: iio_device_unregister(indio_dev); +free_irq: + if (client->irq) + free_irq(client->irq, indio_dev); + buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); @@ -1736,6 +1741,9 @@ static void mma8452_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); + if (client->irq) + free_irq(client->irq, indio_dev); + iio_triggered_buffer_cleanup(indio_dev); mma8452_trigger_cleanup(indio_dev); mma8452_standby(iio_priv(indio_dev)); @@ -1821,12 +1829,12 @@ static const struct dev_pm_ops mma8452_pm_ops = { }; static const struct i2c_device_id mma8452_id[] = { - { "fxls8471", (kernel_ulong_t)&mma_chip_info_table[fxls8471] }, - { "mma8451", (kernel_ulong_t)&mma_chip_info_table[mma8451] }, - { "mma8452", (kernel_ulong_t)&mma_chip_info_table[mma8452] }, - { "mma8453", (kernel_ulong_t)&mma_chip_info_table[mma8453] }, - { "mma8652", (kernel_ulong_t)&mma_chip_info_table[mma8652] }, - { "mma8653", (kernel_ulong_t)&mma_chip_info_table[mma8653] }, + { .name = "fxls8471", .driver_data = (kernel_ulong_t)&mma_chip_info_table[fxls8471] }, + { .name = "mma8451", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8451] }, + { .name = "mma8452", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8452] }, + { .name = "mma8453", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8453] }, + { .name = "mma8652", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8652] }, + { .name = "mma8653", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8653] }, { } }; MODULE_DEVICE_TABLE(i2c, mma8452_id); diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 02195deada49..020370b0ec07 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -582,7 +582,7 @@ static const struct acpi_device_id mma9551_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); static const struct i2c_device_id mma9551_id[] = { - { "mma9551" }, + { .name = "mma9551" }, { } }; diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index f85384a7908f..90ce86244ee8 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -1219,7 +1219,7 @@ static const struct acpi_device_id mma9553_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match); static const struct i2c_device_id mma9553_id[] = { - { "mma9553" }, + { .name = "mma9553" }, { } }; diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index a2c3cf13d098..434971fbfb12 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -580,8 +580,8 @@ static const struct of_device_id mxc4005_of_match[] = { MODULE_DEVICE_TABLE(of, mxc4005_of_match); static const struct i2c_device_id mxc4005_id[] = { - { "mxc4005" }, - { "mxc6655" }, + { .name = "mxc4005" }, + { .name = "mxc6655" }, { } }; MODULE_DEVICE_TABLE(i2c, mxc4005_id); diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index fc3ed84d1933..901f2b9f16a2 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -171,8 +171,8 @@ static const struct acpi_device_id mxc6255_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match); static const struct i2c_device_id mxc6255_id[] = { - { "mxc6225" }, - { "mxc6255" }, + { .name = "mxc6225" }, + { .name = "mxc6255" }, { } }; MODULE_DEVICE_TABLE(i2c, mxc6255_id); diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c index 3e572af2ec03..d1687cdd33ea 100644 --- a/drivers/iio/accel/ssp_accel_sensor.c +++ b/drivers/iio/accel/ssp_accel_sensor.c @@ -76,7 +76,7 @@ static const struct iio_chan_spec ssp_acc_channels[] = { SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X), SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y), SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z), - SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), + IIO_CHAN_SOFT_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), }; static int ssp_process_accel_data(struct iio_dev *indio_dev, void *buf, diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index f24449500533..eecc7fcdb06e 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -138,32 +138,32 @@ static const struct acpi_device_id st_accel_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match); static const struct i2c_device_id st_accel_id_table[] = { - { LSM303DLH_ACCEL_DEV_NAME }, - { LSM303DLHC_ACCEL_DEV_NAME }, - { LIS3DH_ACCEL_DEV_NAME }, - { LSM330D_ACCEL_DEV_NAME }, - { LSM330DL_ACCEL_DEV_NAME }, - { LSM330DLC_ACCEL_DEV_NAME }, - { LIS331DLH_ACCEL_DEV_NAME }, - { LSM303DL_ACCEL_DEV_NAME }, - { LSM303DLM_ACCEL_DEV_NAME }, - { LSM330_ACCEL_DEV_NAME }, - { LSM303AGR_ACCEL_DEV_NAME }, - { LIS2DH12_ACCEL_DEV_NAME }, - { LIS3L02DQ_ACCEL_DEV_NAME }, - { LNG2DM_ACCEL_DEV_NAME }, - { H3LIS331DL_ACCEL_DEV_NAME }, - { LIS331DL_ACCEL_DEV_NAME }, - { LIS3LV02DL_ACCEL_DEV_NAME }, - { LIS2DW12_ACCEL_DEV_NAME }, - { LIS3DE_ACCEL_DEV_NAME }, - { LIS2DE12_ACCEL_DEV_NAME }, - { LIS2DS12_ACCEL_DEV_NAME }, - { LIS2HH12_ACCEL_DEV_NAME }, - { LIS302DL_ACCEL_DEV_NAME }, - { LSM303C_ACCEL_DEV_NAME }, - { SC7A20_ACCEL_DEV_NAME }, - { IIS328DQ_ACCEL_DEV_NAME }, + { .name = LSM303DLH_ACCEL_DEV_NAME }, + { .name = LSM303DLHC_ACCEL_DEV_NAME }, + { .name = LIS3DH_ACCEL_DEV_NAME }, + { .name = LSM330D_ACCEL_DEV_NAME }, + { .name = LSM330DL_ACCEL_DEV_NAME }, + { .name = LSM330DLC_ACCEL_DEV_NAME }, + { .name = LIS331DLH_ACCEL_DEV_NAME }, + { .name = LSM303DL_ACCEL_DEV_NAME }, + { .name = LSM303DLM_ACCEL_DEV_NAME }, + { .name = LSM330_ACCEL_DEV_NAME }, + { .name = LSM303AGR_ACCEL_DEV_NAME }, + { .name = LIS2DH12_ACCEL_DEV_NAME }, + { .name = LIS3L02DQ_ACCEL_DEV_NAME }, + { .name = LNG2DM_ACCEL_DEV_NAME }, + { .name = H3LIS331DL_ACCEL_DEV_NAME }, + { .name = LIS331DL_ACCEL_DEV_NAME }, + { .name = LIS3LV02DL_ACCEL_DEV_NAME }, + { .name = LIS2DW12_ACCEL_DEV_NAME }, + { .name = LIS3DE_ACCEL_DEV_NAME }, + { .name = LIS2DE12_ACCEL_DEV_NAME }, + { .name = LIS2DS12_ACCEL_DEV_NAME }, + { .name = LIS2HH12_ACCEL_DEV_NAME }, + { .name = LIS302DL_ACCEL_DEV_NAME }, + { .name = LSM303C_ACCEL_DEV_NAME }, + { .name = SC7A20_ACCEL_DEV_NAME }, + { .name = IIS328DQ_ACCEL_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, st_accel_id_table); diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index f31c6ab3392d..8b5a3e0489e9 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -630,8 +630,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, static const struct i2c_device_id stk8312_i2c_id[] = { /* Deprecated in favour of lowercase form */ - { "STK8312" }, - { "stk8312" }, + { .name = "STK8312" }, + { .name = "stk8312" }, { } }; MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id); diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index a9ff2a273fe1..ccea1331cafc 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -519,7 +519,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend, stk8ba50_resume); static const struct i2c_device_id stk8ba50_i2c_id[] = { - { "stk8ba50" }, + { .name = "stk8ba50" }, { } }; MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id); diff --git a/drivers/iio/adc/88pm886-gpadc.c b/drivers/iio/adc/88pm886-gpadc.c index cffe35136685..4435f3d5e2b8 100644 --- a/drivers/iio/adc/88pm886-gpadc.c +++ b/drivers/iio/adc/88pm886-gpadc.c @@ -373,7 +373,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(pm886_gpadc_pm_ops, pm886_gpadc_runtime_resume, NULL); static const struct platform_device_id pm886_gpadc_id[] = { - { "88pm886-gpadc" }, + { .name = "88pm886-gpadc" }, { } }; MODULE_DEVICE_TABLE(platform, pm886_gpadc_id); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a9dedbb8eb46..1c663c98c6c9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -78,6 +78,7 @@ config AD4030 config AD4062 tristate "Analog Devices AD4062 Driver" depends on I3C + depends on GPIOLIB select REGMAP_I3C select IIO_BUFFER select IIO_TRIGGERED_BUFFER @@ -144,6 +145,22 @@ config AD4170_4 To compile this driver as a module, choose M here: the module will be called ad4170-4. +config AD4691 + tristate "Analog Devices AD4691 Family ADC Driver" + depends on SPI + depends on REGULATOR || COMPILE_TEST + select IIO_BUFFER + select IIO_BUFFER_DMAENGINE + select IIO_TRIGGERED_BUFFER + select REGMAP + select SPI_OFFLOAD + help + Say yes here to build support for Analog Devices AD4691 Family MuxSAR + SPI analog to digital converters (ADC). + + To compile this driver as a module, choose M here: the module will be + called ad4691. + config AD4695 tristate "Analog Device AD4695 ADC Driver" depends on SPI @@ -414,6 +431,7 @@ config AD7766 config AD7768_1 tristate "Analog Devices AD7768-1 ADC driver" depends on SPI + select GPIOLIB select REGULATOR select REGMAP_SPI select RATIONAL @@ -1354,7 +1372,7 @@ config QCOM_SPMI_VADC be called qcom-spmi-vadc. config QCOM_SPMI_ADC5 - tristate "Qualcomm Technologies Inc. SPMI PMIC5 ADC" + tristate "Qualcomm SPMI PMIC5 ADC" depends on SPMI select REGMAP_SPMI select QCOM_VADC_COMMON @@ -1374,7 +1392,7 @@ config QCOM_SPMI_ADC5 be called qcom-spmi-adc5. config QCOM_SPMI_ADC5_GEN3 - tristate "Qualcomm Technologies Inc. SPMI PMIC5 GEN3 ADC" + tristate "Qualcomm SPMI PMIC5 GEN3 ADC" depends on SPMI && THERMAL select REGMAP_SPMI select QCOM_VADC_COMMON diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 097357d146ba..707dd708912f 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_AD4080) += ad4080.o obj-$(CONFIG_AD4130) += ad4130.o obj-$(CONFIG_AD4134) += ad4134.o obj-$(CONFIG_AD4170_4) += ad4170-4.o +obj-$(CONFIG_AD4691) += ad4691.o obj-$(CONFIG_AD4695) += ad4695.o obj-$(CONFIG_AD4851) += ad4851.o obj-$(CONFIG_AD7091R) += ad7091r-base.o diff --git a/drivers/iio/adc/ad4062.c b/drivers/iio/adc/ad4062.c index 222499a45b9b..8e5984055b15 100644 --- a/drivers/iio/adc/ad4062.c +++ b/drivers/iio/adc/ad4062.c @@ -436,10 +436,9 @@ static int ad4062_check_ids(struct ad4062_state *st) return ret; val = be16_to_cpu(st->buf.be16); - if (val != AD4062_I3C_VENDOR) { - dev_err(dev, "Vendor ID x%x does not match expected value\n", val); - return -ENODEV; - } + if (val != AD4062_I3C_VENDOR) + return dev_err_probe(dev, -ENODEV, + "Vendor ID x%x does not match expected value\n", val); return 0; } diff --git a/drivers/iio/adc/ad4080.c b/drivers/iio/adc/ad4080.c index 204ad198342b..8d2953341b15 100644 --- a/drivers/iio/adc/ad4080.c +++ b/drivers/iio/adc/ad4080.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,10 @@ #define AD4086_CHIP_ID 0x0056 #define AD4087_CHIP_ID 0x0057 #define AD4088_CHIP_ID 0x0058 +#define AD4880_CHIP_ID 0x0059 +#define AD4884_CHIP_ID 0x005C + +#define AD4080_MAX_CHANNELS 2 #define AD4080_LVDS_CNV_CLK_CNT_MAX 7 @@ -179,8 +184,9 @@ struct ad4080_chip_info { }; struct ad4080_state { - struct regmap *regmap; - struct iio_backend *back; + struct spi_device *spi[AD4080_MAX_CHANNELS]; + struct regmap *regmap[AD4080_MAX_CHANNELS]; + struct iio_backend *back[AD4080_MAX_CHANNELS]; const struct ad4080_chip_info *info; /* * Synchronize access to members the of driver state, and ensure @@ -189,7 +195,7 @@ struct ad4080_state { struct mutex lock; unsigned int num_lanes; unsigned long clk_rate; - enum ad4080_filter_type filter_type; + enum ad4080_filter_type filter_type[AD4080_MAX_CHANNELS]; bool lvds_cnv_en; }; @@ -206,9 +212,9 @@ static int ad4080_reg_access(struct iio_dev *indio_dev, unsigned int reg, struct ad4080_state *st = iio_priv(indio_dev); if (readval) - return regmap_read(st->regmap, reg, readval); + return regmap_read(st->regmap[0], reg, readval); - return regmap_write(st->regmap, reg, writeval); + return regmap_write(st->regmap[0], reg, writeval); } static int ad4080_get_scale(struct ad4080_state *st, int *val, int *val2) @@ -229,8 +235,9 @@ static unsigned int ad4080_get_dec_rate(struct iio_dev *dev, struct ad4080_state *st = iio_priv(dev); int ret; unsigned int data; + unsigned int ch = chan->channel; - ret = regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data); + ret = regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data); if (ret) return ret; @@ -242,13 +249,14 @@ static int ad4080_set_dec_rate(struct iio_dev *dev, unsigned int mode) { struct ad4080_state *st = iio_priv(dev); + unsigned int ch = chan->channel; guard(mutex)(&st->lock); - if ((st->filter_type >= SINC_5 && mode >= 512) || mode < 2) + if ((st->filter_type[ch] >= SINC_5 && mode >= 512) || mode < 2) return -EINVAL; - return regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG, + return regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG, AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK, FIELD_PREP(AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK, (ilog2(mode) - 1))); @@ -268,15 +276,15 @@ static int ad4080_read_raw(struct iio_dev *indio_dev, dec_rate = ad4080_get_dec_rate(indio_dev, chan); if (dec_rate < 0) return dec_rate; - if (st->filter_type == SINC_5_COMP) + if (st->filter_type[chan->channel] == SINC_5_COMP) dec_rate *= 2; - if (st->filter_type) + if (st->filter_type[chan->channel]) *val = DIV_ROUND_CLOSEST(st->clk_rate, dec_rate); else *val = st->clk_rate; return IIO_VAL_INT; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - if (st->filter_type == FILTER_NONE) { + if (st->filter_type[chan->channel] == FILTER_NONE) { *val = 1; } else { *val = ad4080_get_dec_rate(indio_dev, chan); @@ -297,7 +305,7 @@ static int ad4080_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - if (st->filter_type == FILTER_NONE && val > 1) + if (st->filter_type[chan->channel] == FILTER_NONE && val > 1) return -EINVAL; return ad4080_set_dec_rate(indio_dev, chan, val); @@ -306,23 +314,23 @@ static int ad4080_write_raw(struct iio_dev *indio_dev, } } -static int ad4080_lvds_sync_write(struct ad4080_state *st) +static int ad4080_lvds_sync_write(struct ad4080_state *st, unsigned int ch) { - struct device *dev = regmap_get_device(st->regmap); + struct device *dev = regmap_get_device(st->regmap[ch]); int ret; - ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A, + ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A, AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN); if (ret) return ret; - ret = iio_backend_interface_data_align(st->back, 10000); + ret = iio_backend_interface_data_align(st->back[ch], 10000); if (ret) return dev_err_probe(dev, ret, "Data alignment process failed\n"); dev_dbg(dev, "Success: Pattern correct and Locked!\n"); - return regmap_clear_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A, + return regmap_clear_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A, AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN); } @@ -331,9 +339,10 @@ static int ad4080_get_filter_type(struct iio_dev *dev, { struct ad4080_state *st = iio_priv(dev); unsigned int data; + unsigned int ch = chan->channel; int ret; - ret = regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data); + ret = regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data); if (ret) return ret; @@ -345,6 +354,7 @@ static int ad4080_set_filter_type(struct iio_dev *dev, unsigned int mode) { struct ad4080_state *st = iio_priv(dev); + unsigned int ch = chan->channel; int dec_rate; int ret; @@ -357,18 +367,18 @@ static int ad4080_set_filter_type(struct iio_dev *dev, if (mode >= SINC_5 && dec_rate >= 512) return -EINVAL; - ret = iio_backend_filter_type_set(st->back, mode); + ret = iio_backend_filter_type_set(st->back[ch], mode); if (ret) return ret; - ret = regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG, + ret = regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG, AD4080_FILTER_CONFIG_FILTER_SEL_MSK, FIELD_PREP(AD4080_FILTER_CONFIG_FILTER_SEL_MSK, mode)); if (ret) return ret; - st->filter_type = mode; + st->filter_type[ch] = mode; return 0; } @@ -382,14 +392,14 @@ static int ad4080_read_avail(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - switch (st->filter_type) { + switch (st->filter_type[chan->channel]) { case FILTER_NONE: *vals = ad4080_dec_rate_none; *length = ARRAY_SIZE(ad4080_dec_rate_none); break; default: *vals = ad4080_dec_rate_avail; - *length = st->filter_type >= SINC_5 ? + *length = st->filter_type[chan->channel] >= SINC_5 ? (ARRAY_SIZE(ad4080_dec_rate_avail) - 2) : ARRAY_SIZE(ad4080_dec_rate_avail); break; @@ -401,6 +411,28 @@ static int ad4080_read_avail(struct iio_dev *indio_dev, } } +static int ad4880_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct ad4080_state *st = iio_priv(indio_dev); + int ret; + + for (unsigned int ch = 0; ch < st->info->num_channels; ch++) { + /* + * Each backend has a single channel (channel 0 from the + * backend's perspective), so always use channel index 0. + */ + if (test_bit(ch, scan_mask)) + ret = iio_backend_chan_enable(st->back[ch], 0); + else + ret = iio_backend_chan_disable(st->back[ch], 0); + if (ret) + return ret; + } + + return 0; +} + static const struct iio_info ad4080_iio_info = { .debugfs_reg_access = ad4080_reg_access, .read_raw = ad4080_read_raw, @@ -408,6 +440,19 @@ static const struct iio_info ad4080_iio_info = { .read_avail = ad4080_read_avail, }; +/* + * AD4880 needs update_scan_mode to enable/disable individual backend channels. + * Single-channel devices don't need this as their backends may not implement + * chan_enable/chan_disable operations. + */ +static const struct iio_info ad4880_iio_info = { + .debugfs_reg_access = ad4080_reg_access, + .read_raw = ad4080_read_raw, + .write_raw = ad4080_write_raw, + .read_avail = ad4080_read_avail, + .update_scan_mode = ad4880_update_scan_mode, +}; + static const struct iio_enum ad4080_filter_type_enum = { .items = ad4080_filter_type_iio_enum, .num_items = ARRAY_SIZE(ad4080_filter_type_iio_enum), @@ -422,17 +467,28 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[] = { { } }; -#define AD4080_CHANNEL_DEFINE(bits, storage) { \ +/* + * AD4880 needs per-channel filter configuration since each channel has + * its own independent ADC with separate SPI interface. + */ +static struct iio_chan_spec_ext_info ad4880_ext_info[] = { + IIO_ENUM("filter_type", IIO_SEPARATE, &ad4080_filter_type_enum), + IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, + &ad4080_filter_type_enum), + { } +}; + +#define AD4080_CHANNEL_DEFINE(bits, storage, idx) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ - .channel = 0, \ + .channel = (idx), \ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .info_mask_shared_by_all_available = \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .ext_info = ad4080_ext_info, \ - .scan_index = 0, \ + .scan_index = (idx), \ .scan_type = { \ .sign = 's', \ .realbits = (bits), \ @@ -440,23 +496,56 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[] = { }, \ } -static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32); +/* + * AD4880 has per-channel attributes (filter_type, oversampling_ratio, + * sampling_frequency) since each channel has its own independent ADC + * with separate SPI configuration interface. + */ +#define AD4880_CHANNEL_DEFINE(bits, storage, idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (idx), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_separate_available = \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .ext_info = ad4880_ext_info, \ + .scan_index = (idx), \ + .scan_type = { \ + .sign = 's', \ + .realbits = (bits), \ + .storagebits = (storage), \ + }, \ +} -static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32); +static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32, 0); -static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32); +static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32, 0); -static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16); +static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32, 0); -static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16); +static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16, 0); -static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16); +static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16, 0); -static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16); +static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16, 0); -static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16); +static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16, 0); -static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16); +static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16, 0); + +static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16, 0); + +static const struct iio_chan_spec ad4880_channels[] = { + AD4880_CHANNEL_DEFINE(20, 32, 0), + AD4880_CHANNEL_DEFINE(20, 32, 1), +}; + +static const struct iio_chan_spec ad4884_channels[] = { + AD4880_CHANNEL_DEFINE(16, 16, 0), + AD4880_CHANNEL_DEFINE(16, 16, 1), +}; static const struct ad4080_chip_info ad4080_chip_info = { .name = "ad4080", @@ -548,25 +637,44 @@ static const struct ad4080_chip_info ad4088_chip_info = { .lvds_cnv_clk_cnt_max = 8, }; -static int ad4080_setup(struct iio_dev *indio_dev) +static const struct ad4080_chip_info ad4880_chip_info = { + .name = "ad4880", + .product_id = AD4880_CHIP_ID, + .scale_table = ad4080_scale_table, + .num_scales = ARRAY_SIZE(ad4080_scale_table), + .num_channels = 2, + .channels = ad4880_channels, + .lvds_cnv_clk_cnt_max = AD4080_LVDS_CNV_CLK_CNT_MAX, +}; + +static const struct ad4080_chip_info ad4884_chip_info = { + .name = "ad4884", + .product_id = AD4884_CHIP_ID, + .scale_table = ad4080_scale_table, + .num_scales = ARRAY_SIZE(ad4080_scale_table), + .num_channels = 2, + .channels = ad4884_channels, + .lvds_cnv_clk_cnt_max = 2, +}; + +static int ad4080_setup_channel(struct ad4080_state *st, unsigned int ch) { - struct ad4080_state *st = iio_priv(indio_dev); - struct device *dev = regmap_get_device(st->regmap); + struct device *dev = regmap_get_device(st->regmap[ch]); __le16 id_le; u16 id; int ret; - ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A, + ret = regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A, AD4080_INTERFACE_CONFIG_A_SW_RESET); if (ret) return ret; - ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A, + ret = regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A, AD4080_INTERFACE_CONFIG_A_SDO_ENABLE); if (ret) return ret; - ret = regmap_bulk_read(st->regmap, AD4080_REG_PRODUCT_ID_L, &id_le, + ret = regmap_bulk_read(st->regmap[ch], AD4080_REG_PRODUCT_ID_L, &id_le, sizeof(id_le)); if (ret) return ret; @@ -575,18 +683,18 @@ static int ad4080_setup(struct iio_dev *indio_dev) if (id != st->info->product_id) dev_info(dev, "Unrecognized CHIP_ID 0x%X\n", id); - ret = regmap_set_bits(st->regmap, AD4080_REG_GPIO_CONFIG_A, + ret = regmap_set_bits(st->regmap[ch], AD4080_REG_GPIO_CONFIG_A, AD4080_GPIO_CONFIG_A_GPO_1_EN); if (ret) return ret; - ret = regmap_write(st->regmap, AD4080_REG_GPIO_CONFIG_B, + ret = regmap_write(st->regmap[ch], AD4080_REG_GPIO_CONFIG_B, FIELD_PREP(AD4080_GPIO_CONFIG_B_GPIO_1_SEL_MSK, AD4080_GPIO_CONFIG_B_GPIO_FILTER_RES_RDY)); if (ret) return ret; - ret = iio_backend_num_lanes_set(st->back, st->num_lanes); + ret = iio_backend_num_lanes_set(st->back[ch], st->num_lanes); if (ret) return ret; @@ -594,7 +702,7 @@ static int ad4080_setup(struct iio_dev *indio_dev) return 0; /* Set maximum LVDS Data Transfer Latency */ - ret = regmap_update_bits(st->regmap, + ret = regmap_update_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_B, AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK, FIELD_PREP(AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK, @@ -603,24 +711,38 @@ static int ad4080_setup(struct iio_dev *indio_dev) return ret; if (st->num_lanes > 1) { - ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A, + ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A, AD4080_ADC_DATA_INTF_CONFIG_A_SPI_LVDS_LANES); if (ret) return ret; } - ret = regmap_set_bits(st->regmap, + ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_B, AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_EN); if (ret) return ret; - return ad4080_lvds_sync_write(st); + return ad4080_lvds_sync_write(st, ch); } -static int ad4080_properties_parse(struct ad4080_state *st) +static int ad4080_setup(struct iio_dev *indio_dev) +{ + struct ad4080_state *st = iio_priv(indio_dev); + int ret; + + for (unsigned int ch = 0; ch < st->info->num_channels; ch++) { + ret = ad4080_setup_channel(st, ch); + if (ret) + return ret; + } + + return 0; +} + +static int ad4080_properties_parse(struct ad4080_state *st, + struct device *dev) { - struct device *dev = regmap_get_device(st->regmap); st->lvds_cnv_en = device_property_read_bool(dev, "adi,lvds-cnv-enable"); @@ -655,14 +777,28 @@ static int ad4080_probe(struct spi_device *spi) return dev_err_probe(dev, ret, "failed to get and enable supplies\n"); - st->regmap = devm_regmap_init_spi(spi, &ad4080_regmap_config); - if (IS_ERR(st->regmap)) - return PTR_ERR(st->regmap); + /* Setup primary SPI device (channel 0) */ + st->spi[0] = spi; + st->regmap[0] = devm_regmap_init_spi(spi, &ad4080_regmap_config); + if (IS_ERR(st->regmap[0])) + return PTR_ERR(st->regmap[0]); st->info = spi_get_device_match_data(spi); if (!st->info) return -ENODEV; + /* Setup ancillary SPI devices for additional channels */ + for (unsigned int ch = 1; ch < st->info->num_channels; ch++) { + st->spi[ch] = devm_spi_new_ancillary_device(spi, spi_get_chipselect(spi, ch)); + if (IS_ERR(st->spi[ch])) + return dev_err_probe(dev, PTR_ERR(st->spi[ch]), + "failed to register ancillary device\n"); + + st->regmap[ch] = devm_regmap_init_spi(st->spi[ch], &ad4080_regmap_config); + if (IS_ERR(st->regmap[ch])) + return PTR_ERR(st->regmap[ch]); + } + ret = devm_mutex_init(dev, &st->lock); if (ret) return ret; @@ -670,9 +806,10 @@ static int ad4080_probe(struct spi_device *spi) indio_dev->name = st->info->name; indio_dev->channels = st->info->channels; indio_dev->num_channels = st->info->num_channels; - indio_dev->info = &ad4080_iio_info; + indio_dev->info = st->info->num_channels > 1 ? + &ad4880_iio_info : &ad4080_iio_info; - ret = ad4080_properties_parse(st); + ret = ad4080_properties_parse(st, dev); if (ret) return ret; @@ -682,15 +819,25 @@ static int ad4080_probe(struct spi_device *spi) st->clk_rate = clk_get_rate(clk); - st->back = devm_iio_backend_get(dev, NULL); - if (IS_ERR(st->back)) - return PTR_ERR(st->back); + /* Get backends for all channels */ + for (unsigned int ch = 0; ch < st->info->num_channels; ch++) { + st->back[ch] = devm_iio_backend_get_by_index(dev, ch); + if (IS_ERR(st->back[ch])) + return PTR_ERR(st->back[ch]); - ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev); - if (ret) - return ret; + ret = devm_iio_backend_enable(dev, st->back[ch]); + if (ret) + return ret; + } - ret = devm_iio_backend_enable(dev, st->back); + /* + * Request buffer from the first backend only. For multi-channel + * devices (e.g., AD4880), the FPGA uses two axi_ad408x IP instances + * (one per ADC channel) whose outputs are combined by a packer block + * that interleaves all channel data into a single DMA stream routed + * through the first backend's clock domain. + */ + ret = devm_iio_backend_request_buffer(dev, st->back[0], indio_dev); if (ret) return ret; @@ -711,6 +858,8 @@ static const struct spi_device_id ad4080_id[] = { { "ad4086", (kernel_ulong_t)&ad4086_chip_info }, { "ad4087", (kernel_ulong_t)&ad4087_chip_info }, { "ad4088", (kernel_ulong_t)&ad4088_chip_info }, + { "ad4880", (kernel_ulong_t)&ad4880_chip_info }, + { "ad4884", (kernel_ulong_t)&ad4884_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad4080_id); @@ -725,6 +874,8 @@ static const struct of_device_id ad4080_of_match[] = { { .compatible = "adi,ad4086", &ad4086_chip_info }, { .compatible = "adi,ad4087", &ad4087_chip_info }, { .compatible = "adi,ad4088", &ad4088_chip_info }, + { .compatible = "adi,ad4880", &ad4880_chip_info }, + { .compatible = "adi,ad4884", &ad4884_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad4080_of_match); diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c index 5567ae5dee88..7f39f3484062 100644 --- a/drivers/iio/adc/ad4130.c +++ b/drivers/iio/adc/ad4130.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include @@ -30,6 +32,9 @@ #include #include #include +#include +#include +#include #define AD4130_NAME "ad4130" @@ -40,6 +45,7 @@ #define AD4130_ADC_CONTROL_REG 0x01 #define AD4130_ADC_CONTROL_BIPOLAR_MASK BIT(14) #define AD4130_ADC_CONTROL_INT_REF_VAL_MASK BIT(13) +#define AD4130_ADC_CONTROL_CONT_READ_MASK BIT(11) #define AD4130_INT_REF_2_5V 2500000 #define AD4130_INT_REF_1_25V 1250000 #define AD4130_ADC_CONTROL_CSB_EN_MASK BIT(9) @@ -54,7 +60,9 @@ #define AD4130_IO_CONTROL_REG 0x03 #define AD4130_IO_CONTROL_INT_PIN_SEL_MASK GENMASK(9, 8) #define AD4130_IO_CONTROL_GPIO_DATA_MASK GENMASK(7, 4) +#define AD4130_4_IO_CONTROL_GPIO_DATA_MASK GENMASK(7, 6) #define AD4130_IO_CONTROL_GPIO_CTRL_MASK GENMASK(3, 0) +#define AD4130_4_IO_CONTROL_GPIO_CTRL_MASK GENMASK(3, 2) #define AD4130_VBIAS_REG 0x04 @@ -125,6 +133,28 @@ #define AD4130_INVALID_SLOT -1 +static const unsigned int ad4129_reg_size[] = { + [AD4130_STATUS_REG] = 1, + [AD4130_ADC_CONTROL_REG] = 2, + [AD4130_DATA_REG] = 2, + [AD4130_IO_CONTROL_REG] = 2, + [AD4130_VBIAS_REG] = 2, + [AD4130_ID_REG] = 1, + [AD4130_ERROR_REG] = 2, + [AD4130_ERROR_EN_REG] = 2, + [AD4130_MCLK_COUNT_REG] = 1, + [AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3, + [AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2, + [AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3, + [AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2, + [AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2, + [AD4130_MISC_REG] = 2, + [AD4130_FIFO_CONTROL_REG] = 3, + [AD4130_FIFO_STATUS_REG] = 1, + [AD4130_FIFO_THRESHOLD_REG] = 3, + [AD4130_FIFO_DATA_REG] = 2, +}; + static const unsigned int ad4130_reg_size[] = { [AD4130_STATUS_REG] = 1, [AD4130_ADC_CONTROL_REG] = 2, @@ -147,6 +177,24 @@ static const unsigned int ad4130_reg_size[] = { [AD4130_FIFO_DATA_REG] = 3, }; +static const unsigned int ad4131_reg_size[] = { + [AD4130_STATUS_REG] = 1, + [AD4130_ADC_CONTROL_REG] = 2, + [AD4130_DATA_REG] = 2, + [AD4130_IO_CONTROL_REG] = 2, + [AD4130_VBIAS_REG] = 2, + [AD4130_ID_REG] = 1, + [AD4130_ERROR_REG] = 2, + [AD4130_ERROR_EN_REG] = 2, + [AD4130_MCLK_COUNT_REG] = 1, + [AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3, + [AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2, + [AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3, + [AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2, + [AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2, + [AD4130_MISC_REG] = 2, +}; + enum ad4130_int_ref_val { AD4130_INT_REF_VAL_2_5V, AD4130_INT_REF_VAL_1_25V, @@ -224,6 +272,28 @@ enum ad4130_pin_function { AD4130_PIN_FN_VBIAS = BIT(3), }; +/* Pin mapping for AIN0..AIN7, VBIAS_0..VBIAS_7 */ +static const u8 ad4130_4_pin_map[] = { + 0x00, 0x01, 0x04, 0x05, 0x0A, 0x0B, 0x0E, 0x0F, /* 0 - 7 */ +}; + +/* Pin mapping for AIN0..AIN15, VBIAS_0..VBIAS_15 */ +static const u8 ad4130_8_pin_map[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0 - 7 */ + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 8 - 15 */ +}; + +struct ad4130_chip_info { + const char *name; + unsigned int max_analog_pins; + unsigned int num_gpios; + const struct iio_info *info; + const unsigned int *reg_size; + const unsigned int reg_size_length; + const u8 *pin_map; + bool has_fifo; +}; + /* * If you make adaptations in this struct, you most likely also have to adapt * ad4130_setup_info_eq(), too. @@ -268,6 +338,7 @@ struct ad4130_state { struct regmap *regmap; struct spi_device *spi; struct clk *mclk; + const struct ad4130_chip_info *chip_info; struct regulator_bulk_data regulators[4]; u32 irq_trigger; u32 inv_irq_trigger; @@ -294,6 +365,7 @@ struct ad4130_state { u32 mclk_sel; bool int_ref_en; bool bipolar; + bool buffer_wait_for_irq; unsigned int num_enabled_channels; unsigned int effective_watermark; @@ -301,6 +373,7 @@ struct ad4130_state { struct spi_message fifo_msg; struct spi_transfer fifo_xfer[2]; + struct iio_trigger *trig; /* * DMA (thus cache coherency maintenance) requires any transfer @@ -312,9 +385,13 @@ struct ad4130_state { u8 reg_write_tx_buf[4]; u8 reg_read_tx_buf[1]; u8 reg_read_rx_buf[3]; - u8 fifo_tx_buf[2]; - u8 fifo_rx_buf[AD4130_FIFO_SIZE * - AD4130_FIFO_MAX_SAMPLE_SIZE]; + union { + struct { + u8 fifo_tx_buf[2]; + u8 fifo_rx_buf[AD4130_FIFO_SIZE * AD4130_FIFO_MAX_SAMPLE_SIZE]; + }; + IIO_DECLARE_BUFFER_WITH_TS(u32, scan_channels, AD4130_MAX_CHANNELS); + }; }; static const char * const ad4130_int_pin_names[] = { @@ -394,10 +471,10 @@ static const char * const ad4130_filter_types_str[] = { static int ad4130_get_reg_size(struct ad4130_state *st, unsigned int reg, unsigned int *size) { - if (reg >= ARRAY_SIZE(ad4130_reg_size)) + if (reg >= st->chip_info->reg_size_length) return -EINVAL; - *size = ad4130_reg_size[reg]; + *size = st->chip_info->reg_size[reg]; return 0; } @@ -505,7 +582,8 @@ static int ad4130_gpio_init_valid_mask(struct gpio_chip *gc, /* * Output-only GPIO functionality is available on pins AIN2 through - * AIN5. If these pins are used for anything else, do not expose them. + * AIN5 for some parts and AIN2 through AIN3 for others. If these pins + * are used for anything else, do not expose them. */ for (i = 0; i < ngpios; i++) { unsigned int pin = i + AD4130_AIN2_P1; @@ -526,8 +604,14 @@ static int ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) { struct ad4130_state *st = gpiochip_get_data(gc); - unsigned int mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK, - BIT(offset)); + unsigned int mask; + + if (st->chip_info->num_gpios == AD4130_MAX_GPIOS) + mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK, + BIT(offset)); + else + mask = FIELD_PREP(AD4130_4_IO_CONTROL_GPIO_DATA_MASK, + BIT(offset)); return regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask, value ? mask : 0); @@ -588,10 +672,43 @@ static irqreturn_t ad4130_irq_handler(int irq, void *private) struct iio_dev *indio_dev = private; struct ad4130_state *st = iio_priv(indio_dev); - if (iio_buffer_enabled(indio_dev)) - ad4130_push_fifo_data(indio_dev); - else + if (iio_buffer_enabled(indio_dev)) { + if (st->chip_info->has_fifo) + ad4130_push_fifo_data(indio_dev); + else if (st->buffer_wait_for_irq) + complete(&st->completion); + else + iio_trigger_poll(st->trig); + } else { complete(&st->completion); + } + + return IRQ_HANDLED; +} + +static irqreturn_t ad4130_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad4130_state *st = iio_priv(indio_dev); + unsigned int data_reg_size = ad4130_data_reg_size(st); + struct spi_transfer xfer = { }; + unsigned int num_en_chn; + int ret; + + num_en_chn = bitmap_weight(indio_dev->active_scan_mask, + iio_get_masklength(indio_dev)); + xfer.rx_buf = st->scan_channels; + xfer.len = data_reg_size * num_en_chn; + ret = spi_sync_transfer(st->spi, &xfer, 1); + if (ret < 0) + goto err_out; + + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_channels, + iio_get_time_ns(indio_dev)); + +err_out: + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } @@ -1291,6 +1408,79 @@ static const struct iio_info ad4130_info = { .debugfs_reg_access = ad4130_reg_access, }; +static const struct iio_info ad4131_info = { + .read_raw = ad4130_read_raw, + .read_avail = ad4130_read_avail, + .write_raw_get_fmt = ad4130_write_raw_get_fmt, + .write_raw = ad4130_write_raw, + .update_scan_mode = ad4130_update_scan_mode, + .debugfs_reg_access = ad4130_reg_access, +}; + +static const struct ad4130_chip_info ad4129_4_chip_info = { + .name = "ad4129-4", + .max_analog_pins = 8, + .num_gpios = 2, + .info = &ad4130_info, + .reg_size = ad4129_reg_size, + .reg_size_length = ARRAY_SIZE(ad4129_reg_size), + .has_fifo = true, + .pin_map = ad4130_4_pin_map, +}; + +static const struct ad4130_chip_info ad4129_8_chip_info = { + .name = "ad4129-8", + .max_analog_pins = 16, + .num_gpios = 4, + .info = &ad4130_info, + .reg_size = ad4129_reg_size, + .reg_size_length = ARRAY_SIZE(ad4129_reg_size), + .has_fifo = true, + .pin_map = ad4130_8_pin_map, +}; + +static const struct ad4130_chip_info ad4130_4_chip_info = { + .name = "ad4130-4", + .max_analog_pins = 16, + .num_gpios = 2, + .info = &ad4130_info, + .reg_size = ad4130_reg_size, + .reg_size_length = ARRAY_SIZE(ad4130_reg_size), + .has_fifo = true, + .pin_map = ad4130_4_pin_map, +}; + +static const struct ad4130_chip_info ad4130_8_chip_info = { + .name = "ad4130-8", + .max_analog_pins = 16, + .num_gpios = 4, + .info = &ad4130_info, + .reg_size = ad4130_reg_size, + .reg_size_length = ARRAY_SIZE(ad4130_reg_size), + .has_fifo = true, + .pin_map = ad4130_8_pin_map, +}; + +static const struct ad4130_chip_info ad4131_4_chip_info = { + .name = "ad4131-4", + .max_analog_pins = 8, + .num_gpios = 2, + .info = &ad4131_info, + .reg_size = ad4131_reg_size, + .reg_size_length = ARRAY_SIZE(ad4131_reg_size), + .pin_map = ad4130_4_pin_map, +}; + +static const struct ad4130_chip_info ad4131_8_chip_info = { + .name = "ad4131-8", + .max_analog_pins = 16, + .num_gpios = 4, + .info = &ad4131_info, + .reg_size = ad4131_reg_size, + .reg_size_length = ARRAY_SIZE(ad4131_reg_size), + .pin_map = ad4130_8_pin_map, +}; + static int ad4130_buffer_postenable(struct iio_dev *indio_dev) { struct ad4130_state *st = iio_priv(indio_dev); @@ -1298,44 +1488,89 @@ static int ad4130_buffer_postenable(struct iio_dev *indio_dev) guard(mutex)(&st->lock); - ret = ad4130_set_watermark_interrupt_en(st, true); + if (st->chip_info->has_fifo) { + ret = ad4130_set_watermark_interrupt_en(st, true); + if (ret) + return ret; + + ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger); + if (ret) + return ret; + + ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM); + if (ret) + return ret; + } + + ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS); if (ret) return ret; - ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger); - if (ret) - return ret; + /* + * When using triggered buffer, Entering continuous read mode must + * be the last command sent. No configuration changes are allowed until + * exiting this mode. + */ + if (!st->chip_info->has_fifo) { + ret = regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG, + AD4130_ADC_CONTROL_CONT_READ_MASK, + FIELD_PREP(AD4130_ADC_CONTROL_CONT_READ_MASK, 1)); + if (ret) + return ret; + } - ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM); - if (ret) - return ret; - - return ad4130_set_mode(st, AD4130_MODE_CONTINUOUS); + return 0; } static int ad4130_buffer_predisable(struct iio_dev *indio_dev) { struct ad4130_state *st = iio_priv(indio_dev); unsigned int i; + u32 temp; int ret; guard(mutex)(&st->lock); + if (!st->chip_info->has_fifo) { + temp = 0x42; + reinit_completion(&st->completion); + + /* + * In continuous read mode, when all samples are read, the data + * ready signal returns high until the next conversion result is + * ready. To exit this mode, the command must be sent when data + * ready is low. In order to ensure that condition, wait for the + * next interrupt (when the new conversion is finished), allowing + * data ready to return low before sending the exit command. + */ + st->buffer_wait_for_irq = true; + if (!wait_for_completion_timeout(&st->completion, msecs_to_jiffies(1000))) + dev_warn(&st->spi->dev, "Conversion timed out\n"); + st->buffer_wait_for_irq = false; + + /* Perform a read data command to exit continuous read mode (0x42) */ + ret = spi_write(st->spi, &temp, 1); + if (ret) + return ret; + } + ret = ad4130_set_mode(st, AD4130_MODE_IDLE); if (ret) return ret; - ret = irq_set_irq_type(st->spi->irq, st->irq_trigger); - if (ret) - return ret; + if (st->chip_info->has_fifo) { + ret = irq_set_irq_type(st->spi->irq, st->irq_trigger); + if (ret) + return ret; - ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED); - if (ret) - return ret; + ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED); + if (ret) + return ret; - ret = ad4130_set_watermark_interrupt_en(st, false); - if (ret) - return ret; + ret = ad4130_set_watermark_interrupt_en(st, false); + if (ret) + return ret; + } /* * update_scan_mode() is not called in the disable path, disable all @@ -1410,6 +1645,34 @@ static const struct iio_dev_attr *ad4130_fifo_attributes[] = { NULL }; +static const struct iio_trigger_ops ad4130_trigger_ops = { + .validate_device = iio_trigger_validate_own_device, +}; + +static int ad4130_triggered_buffer_setup(struct iio_dev *indio_dev) +{ + struct ad4130_state *st = iio_priv(indio_dev); + int ret; + + st->trig = devm_iio_trigger_alloc(indio_dev->dev.parent, "%s-dev%d", + indio_dev->name, iio_device_id(indio_dev)); + if (!st->trig) + return -ENOMEM; + + st->trig->ops = &ad4130_trigger_ops; + iio_trigger_set_drvdata(st->trig, indio_dev); + ret = devm_iio_trigger_register(indio_dev->dev.parent, st->trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->trig); + + return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev, + &iio_pollfunc_store_time, + &ad4130_trigger_handler, + &ad4130_buffer_ops); +} + static int _ad4130_find_table_index(const unsigned int *tbl, size_t len, unsigned int val) { @@ -1496,6 +1759,17 @@ static int ad4130_parse_fw_setup(struct ad4130_state *st, return 0; } +static unsigned int ad4130_translate_pin(struct ad4130_state *st, + unsigned int logical_pin) +{ + /* For analog input pins, use the chip-specific pin mapping */ + if (logical_pin < st->chip_info->max_analog_pins) + return st->chip_info->pin_map[logical_pin]; + + /* For internal channels, pass through unchanged */ + return logical_pin; +} + static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin) { struct device *dev = &st->spi->dev; @@ -1504,7 +1778,7 @@ static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin) return dev_err_probe(dev, -EINVAL, "Invalid differential channel %u\n", pin); - if (pin >= AD4130_MAX_ANALOG_PINS) + if (pin >= st->chip_info->max_analog_pins) return 0; if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL) @@ -1536,7 +1810,7 @@ static int ad4130_validate_excitation_pin(struct ad4130_state *st, u32 pin) { struct device *dev = &st->spi->dev; - if (pin >= AD4130_MAX_ANALOG_PINS) + if (pin >= st->chip_info->max_analog_pins) return dev_err_probe(dev, -EINVAL, "Invalid excitation pin %u\n", pin); @@ -1554,7 +1828,7 @@ static int ad4130_validate_vbias_pin(struct ad4130_state *st, u32 pin) { struct device *dev = &st->spi->dev; - if (pin >= AD4130_MAX_ANALOG_PINS) + if (pin >= st->chip_info->max_analog_pins) return dev_err_probe(dev, -EINVAL, "Invalid vbias pin %u\n", pin); @@ -1730,7 +2004,7 @@ static int ad4310_parse_fw(struct iio_dev *indio_dev) ret = device_property_count_u32(dev, "adi,vbias-pins"); if (ret > 0) { - if (ret > AD4130_MAX_ANALOG_PINS) + if (ret > st->chip_info->max_analog_pins) return dev_err_probe(dev, -EINVAL, "Too many vbias pins %u\n", ret); @@ -1914,9 +2188,14 @@ static int ad4130_setup(struct iio_dev *indio_dev) * function of P2 takes priority over the GPIO out function. */ val = 0; - for (i = 0; i < AD4130_MAX_GPIOS; i++) - if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE) - val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i)); + for (i = 0; i < st->chip_info->num_gpios; i++) { + if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE) { + if (st->chip_info->num_gpios == 2) + val |= FIELD_PREP(AD4130_4_IO_CONTROL_GPIO_CTRL_MASK, BIT(i)); + else + val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i)); + } + } val |= FIELD_PREP(AD4130_IO_CONTROL_INT_PIN_SEL_MASK, st->int_pin_sel); @@ -1926,21 +2205,23 @@ static int ad4130_setup(struct iio_dev *indio_dev) val = 0; for (i = 0; i < st->num_vbias_pins; i++) - val |= BIT(st->vbias_pins[i]); + val |= BIT(ad4130_translate_pin(st, st->vbias_pins[i])); ret = regmap_write(st->regmap, AD4130_VBIAS_REG, val); if (ret) return ret; - ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG, - AD4130_FIFO_CONTROL_HEADER_MASK); - if (ret) - return ret; + if (st->chip_info->has_fifo) { + ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG, + AD4130_FIFO_CONTROL_HEADER_MASK); + if (ret) + return ret; - /* FIFO watermark interrupt starts out as enabled, disable it. */ - ret = ad4130_set_watermark_interrupt_en(st, false); - if (ret) - return ret; + /* FIFO watermark interrupt starts out as enabled, disable it. */ + ret = ad4130_set_watermark_interrupt_en(st, false); + if (ret) + return ret; + } /* Setup channels. */ for (i = 0; i < indio_dev->num_channels; i++) { @@ -1948,10 +2229,14 @@ static int ad4130_setup(struct iio_dev *indio_dev) struct iio_chan_spec *chan = &st->chans[i]; unsigned int val; - val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK, chan->channel) | - FIELD_PREP(AD4130_CHANNEL_AINM_MASK, chan->channel2) | - FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK, chan_info->iout0) | - FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK, chan_info->iout1); + val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK, + ad4130_translate_pin(st, chan->channel)) | + FIELD_PREP(AD4130_CHANNEL_AINM_MASK, + ad4130_translate_pin(st, chan->channel2)) | + FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK, + ad4130_translate_pin(st, chan_info->iout0)) | + FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK, + ad4130_translate_pin(st, chan_info->iout1)); ret = regmap_write(st->regmap, AD4130_CHANNEL_X_REG(i), val); if (ret) @@ -1994,26 +2279,30 @@ static int ad4130_probe(struct spi_device *spi) st = iio_priv(indio_dev); + st->chip_info = device_get_match_data(dev); + memset(st->reset_buf, 0xff, sizeof(st->reset_buf)); init_completion(&st->completion); mutex_init(&st->lock); st->spi = spi; - /* - * Xfer: [ XFR1 ] [ XFR2 ] - * Master: 0x7D N ...................... - * Slave: ...... DATA1 DATA2 ... DATAN - */ - st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG; - st->fifo_xfer[0].tx_buf = st->fifo_tx_buf; - st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf); - st->fifo_xfer[1].rx_buf = st->fifo_rx_buf; - spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer, - ARRAY_SIZE(st->fifo_xfer)); + if (st->chip_info->has_fifo) { + /* + * Xfer: [ XFR1 ] [ XFR2 ] + * Master: 0x7D N ...................... + * Slave: ...... DATA1 DATA2 ... DATAN + */ + st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG; + st->fifo_xfer[0].tx_buf = st->fifo_tx_buf; + st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf); + st->fifo_xfer[1].rx_buf = st->fifo_rx_buf; + spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer, + ARRAY_SIZE(st->fifo_xfer)); + } - indio_dev->name = AD4130_NAME; + indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &ad4130_info; + indio_dev->info = st->chip_info->info; st->regmap = devm_regmap_init(dev, NULL, st, &ad4130_regmap_config); if (IS_ERR(st->regmap)) @@ -2056,9 +2345,9 @@ static int ad4130_probe(struct spi_device *spi) ad4130_fill_scale_tbls(st); st->gc.owner = THIS_MODULE; - st->gc.label = AD4130_NAME; + st->gc.label = st->chip_info->name; st->gc.base = -1; - st->gc.ngpio = AD4130_MAX_GPIOS; + st->gc.ngpio = st->chip_info->num_gpios; st->gc.parent = dev; st->gc.can_sleep = true; st->gc.init_valid_mask = ad4130_gpio_init_valid_mask; @@ -2069,9 +2358,12 @@ static int ad4130_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev, - &ad4130_buffer_ops, - ad4130_fifo_attributes); + if (st->chip_info->has_fifo) + ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev, + &ad4130_buffer_ops, + ad4130_fifo_attributes); + else + ret = ad4130_triggered_buffer_setup(indio_dev); if (ret) return ret; @@ -2081,40 +2373,75 @@ static int ad4130_probe(struct spi_device *spi) if (ret) return dev_err_probe(dev, ret, "Failed to request irq\n"); - /* - * When the chip enters FIFO mode, IRQ polarity is inverted. - * When the chip exits FIFO mode, IRQ polarity returns to normal. - * See datasheet pages: 65, FIFO Watermark Interrupt section, - * and 71, Bit Descriptions for STATUS Register, RDYB. - * Cache the normal and inverted IRQ triggers to set them when - * entering and exiting FIFO mode. - */ - st->irq_trigger = irq_get_trigger_type(spi->irq); - if (st->irq_trigger & IRQF_TRIGGER_RISING) - st->inv_irq_trigger = IRQF_TRIGGER_FALLING; - else if (st->irq_trigger & IRQF_TRIGGER_FALLING) - st->inv_irq_trigger = IRQF_TRIGGER_RISING; - else - return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n", - st->irq_trigger); + if (st->chip_info->has_fifo) { + /* + * When the chip enters FIFO mode, IRQ polarity is inverted. + * When the chip exits FIFO mode, IRQ polarity returns to normal. + * See datasheet pages: 65, FIFO Watermark Interrupt section, + * and 71, Bit Descriptions for STATUS Register, RDYB. + * Cache the normal and inverted IRQ triggers to set them when + * entering and exiting FIFO mode. + */ + st->irq_trigger = irq_get_trigger_type(spi->irq); + if (st->irq_trigger & IRQF_TRIGGER_RISING) + st->inv_irq_trigger = IRQF_TRIGGER_FALLING; + else if (st->irq_trigger & IRQF_TRIGGER_FALLING) + st->inv_irq_trigger = IRQF_TRIGGER_RISING; + else + return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n", + st->irq_trigger); + } return devm_iio_device_register(dev, indio_dev); } static const struct of_device_id ad4130_of_match[] = { + { + .compatible = "adi,ad4129-4", + .data = &ad4129_4_chip_info + }, + { + .compatible = "adi,ad4129-8", + .data = &ad4129_8_chip_info + }, + { + .compatible = "adi,ad4130-4", + .data = &ad4130_4_chip_info + }, { .compatible = "adi,ad4130", + .data = &ad4130_8_chip_info + }, + { + .compatible = "adi,ad4131-4", + .data = &ad4131_4_chip_info + }, + { + .compatible = "adi,ad4131-8", + .data = &ad4131_8_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad4130_of_match); +static const struct spi_device_id ad4130_id_table[] = { + { "ad4129-4", (kernel_ulong_t)&ad4129_4_chip_info }, + { "ad4129-8", (kernel_ulong_t)&ad4129_8_chip_info }, + { "ad4130-4", (kernel_ulong_t)&ad4130_4_chip_info }, + { "ad4130", (kernel_ulong_t)&ad4130_8_chip_info }, + { "ad4131-4", (kernel_ulong_t)&ad4131_4_chip_info }, + { "ad4131-8", (kernel_ulong_t)&ad4131_8_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad4130_id_table); + static struct spi_driver ad4130_driver = { .driver = { .name = AD4130_NAME, .of_match_table = ad4130_of_match, }, .probe = ad4130_probe, + .id_table = ad4130_id_table, }; module_spi_driver(ad4130_driver); diff --git a/drivers/iio/adc/ad4170-4.c b/drivers/iio/adc/ad4170-4.c index 77af0e6b2c59..627cbf5a37b0 100644 --- a/drivers/iio/adc/ad4170-4.c +++ b/drivers/iio/adc/ad4170-4.c @@ -1699,34 +1699,29 @@ static int ad4170_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) return ret; } +static const unsigned long gpio_masks[] = { + AD4170_GPIO_MODE_GPIO0_MSK, + AD4170_GPIO_MODE_GPIO1_MSK, + AD4170_GPIO_MODE_GPIO2_MSK, + AD4170_GPIO_MODE_GPIO3_MSK, +}; + static int ad4170_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) { struct iio_dev *indio_dev = gpiochip_get_data(gc); struct ad4170_state *st = iio_priv(indio_dev); - unsigned long gpio_mask; int ret; if (!iio_device_claim_direct(indio_dev)) return -EBUSY; - switch (offset) { - case 0: - gpio_mask = AD4170_GPIO_MODE_GPIO0_MSK; - break; - case 1: - gpio_mask = AD4170_GPIO_MODE_GPIO1_MSK; - break; - case 2: - gpio_mask = AD4170_GPIO_MODE_GPIO2_MSK; - break; - case 3: - gpio_mask = AD4170_GPIO_MODE_GPIO3_MSK; - break; - default: + if (offset >= ARRAY_SIZE(gpio_masks)) { ret = -EINVAL; goto err_release; } - ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, gpio_mask, + + ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, + gpio_masks[offset], AD4170_GPIO_MODE_GPIO_INPUT << (2 * offset)); err_release: @@ -1740,7 +1735,6 @@ static int ad4170_gpio_direction_output(struct gpio_chip *gc, { struct iio_dev *indio_dev = gpiochip_get_data(gc); struct ad4170_state *st = iio_priv(indio_dev); - unsigned long gpio_mask; int ret; ret = ad4170_gpio_set(gc, offset, value); @@ -1750,24 +1744,13 @@ static int ad4170_gpio_direction_output(struct gpio_chip *gc, if (!iio_device_claim_direct(indio_dev)) return -EBUSY; - switch (offset) { - case 0: - gpio_mask = AD4170_GPIO_MODE_GPIO0_MSK; - break; - case 1: - gpio_mask = AD4170_GPIO_MODE_GPIO1_MSK; - break; - case 2: - gpio_mask = AD4170_GPIO_MODE_GPIO2_MSK; - break; - case 3: - gpio_mask = AD4170_GPIO_MODE_GPIO3_MSK; - break; - default: + if (offset >= ARRAY_SIZE(gpio_masks)) { ret = -EINVAL; goto err_release; } - ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, gpio_mask, + + ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, + gpio_masks[offset], AD4170_GPIO_MODE_GPIO_OUTPUT << (2 * offset)); err_release: diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c new file mode 100644 index 000000000000..548678adc2a4 --- /dev/null +++ b/drivers/iio/adc/ad4691.c @@ -0,0 +1,2084 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024-2026 Analog Devices, Inc. + * Author: Radu Sabau + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define AD4691_VREF_uV_MIN 2400000 +#define AD4691_VREF_uV_MAX 5250000 +#define AD4691_VREF_2P5_uV_MAX 2750000 +#define AD4691_VREF_3P0_uV_MAX 3250000 +#define AD4691_VREF_3P3_uV_MAX 3750000 +#define AD4691_VREF_4P096_uV_MAX 4500000 + +#define AD4691_CNV_DUTY_CYCLE_NS 380 +#define AD4691_CNV_HIGH_TIME_NS 430 +/* + * Conservative default for the manual offload periodic trigger. Low enough + * to work safely out of the box across all OSR and channel count combinations. + */ +#define AD4691_OFFLOAD_INITIAL_TRIGGER_HZ (100 * HZ_PER_KHZ) + +#define AD4691_SPI_CONFIG_A_REG 0x000 +#define AD4691_SW_RESET (BIT(7) | BIT(0)) + +#define AD4691_STATUS_REG 0x014 +#define AD4691_CLAMP_STATUS1_REG 0x01A +#define AD4691_CLAMP_STATUS2_REG 0x01B +#define AD4691_DEVICE_SETUP 0x020 +#define AD4691_MANUAL_MODE BIT(2) +#define AD4691_LDO_EN BIT(4) +#define AD4691_REF_CTRL 0x021 +#define AD4691_REF_CTRL_MASK GENMASK(4, 2) +#define AD4691_REFBUF_EN BIT(0) +#define AD4691_OSC_FREQ_REG 0x023 +#define AD4691_OSC_FREQ_MASK GENMASK(3, 0) +#define AD4691_STD_SEQ_CONFIG 0x025 +#define AD4691_SEQ_ALL_CHANNELS_OFF 0x00 +#define AD4691_SPARE_CONTROL 0x02A + +#define AD4691_MAX_CHANNELS 16 + +#define AD4691_NOOP 0x00 +#define AD4691_ADC_CHAN(ch) ((0x10 + (ch)) << 3) +#define AD4691_EXIT_COMMAND 0x5000 + +#define AD4691_OSC_EN_REG 0x180 +#define AD4691_STATE_RESET_REG 0x181 +#define AD4691_STATE_RESET_ALL BIT(0) +#define AD4691_ADC_SETUP 0x182 +#define AD4691_ADC_MODE_MASK GENMASK(1, 0) +#define AD4691_CNV_BURST_MODE 0x01 +#define AD4691_AUTONOMOUS_MODE 0x02 +/* + * ACC_MASK_REG covers both mask bytes via ADDR_DESCENDING SPI: writing a + * 16-bit BE value to 0x185 auto-decrements to 0x184 for the second byte. + */ +#define AD4691_ACC_MASK_REG 0x185 +#define AD4691_ACC_DEPTH_IN(n) (0x186 + (n)) +#define AD4691_GPIO_MODE1_REG 0x196 +#define AD4691_GPIO_MODE2_REG 0x197 +#define AD4691_GP_MODE_MASK GENMASK(3, 0) +#define AD4691_GP_MODE_DATA_READY 0x06 +#define AD4691_GPIO_READ 0x1A0 +#define AD4691_ACC_STATUS_FULL1_REG 0x1B0 +#define AD4691_ACC_STATUS_FULL2_REG 0x1B1 +#define AD4691_ACC_STATUS_OVERRUN1_REG 0x1B2 +#define AD4691_ACC_STATUS_OVERRUN2_REG 0x1B3 +#define AD4691_ACC_STATUS_SAT1_REG 0x1B4 +#define AD4691_ACC_STATUS_SAT2_REG 0x1BE +#define AD4691_ACC_SAT_OVR_REG(n) (0x1C0 + (n)) +#define AD4691_AVG_IN(n) (0x201 + (2 * (n))) +#define AD4691_AVG_STS_IN(n) (0x222 + (3 * (n))) +#define AD4691_ACC_IN(n) (0x252 + (3 * (n))) +#define AD4691_ACC_STS_DATA(n) (0x283 + (4 * (n))) + + +static const char * const ad4691_supplies[] = { "avdd", "vio" }; + +enum ad4691_ref_ctrl { + AD4691_VREF_2P5, + AD4691_VREF_3P0, + AD4691_VREF_3P3, + AD4691_VREF_4P096, + AD4691_VREF_5P0 +}; + +struct ad4691_channel_info { + const struct iio_chan_spec *channels __counted_by_ptr(num_channels); + const struct iio_chan_spec *manual_channels __counted_by_ptr(num_channels); + unsigned int num_channels; +}; + +struct ad4691_chip_info { + const char *name; + unsigned int max_rate; + const struct ad4691_channel_info *sw_info; + const struct ad4691_channel_info *offload_info; +}; + +/* CNV burst mode channel — exposes oversampling ratio. */ +#define AD4691_CHANNEL(ch) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_SAMP_FREQ) \ + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) \ + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .channel = ch, \ + .scan_index = ch, \ + .scan_type = { \ + .format = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +/* + * Manual mode channel — no oversampling ratio attribute. OSR is not + * supported in manual mode; ACC_DEPTH_IN is not configured during manual + * buffer enable. + */ +#define AD4691_MANUAL_CHANNEL(ch) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .channel = ch, \ + .scan_index = ch, \ + .scan_type = { \ + .format = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +/* + * Offload path (bits_per_word=16): the SPI Engine assembles received + * bits into native 16-bit words before DMA, so samples are in + * CPU-native byte order (IIO_CPU). storagebits=16 matches the 16-bit + * DMA word size. + * + * CNV burst offload configures ACC_DEPTH_IN per channel, so the + * oversampling_ratio attribute is exposed. Manual offload does not; + * use AD4691_OFFLOAD_MANUAL_CHANNEL for that path. + */ +#define AD4691_OFFLOAD_CHANNEL(ch) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_SAMP_FREQ) \ + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) \ + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .channel = ch, \ + .scan_index = ch, \ + .scan_type = { \ + .format = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + }, \ + } + +/* Manual offload — same IIO_CPU layout but no oversampling_ratio attribute. */ +#define AD4691_OFFLOAD_MANUAL_CHANNEL(ch) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .channel = ch, \ + .scan_index = ch, \ + .scan_type = { \ + .format = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + }, \ + } + +static const struct iio_chan_spec ad4691_channels[] = { + AD4691_CHANNEL(0), + AD4691_CHANNEL(1), + AD4691_CHANNEL(2), + AD4691_CHANNEL(3), + AD4691_CHANNEL(4), + AD4691_CHANNEL(5), + AD4691_CHANNEL(6), + AD4691_CHANNEL(7), + AD4691_CHANNEL(8), + AD4691_CHANNEL(9), + AD4691_CHANNEL(10), + AD4691_CHANNEL(11), + AD4691_CHANNEL(12), + AD4691_CHANNEL(13), + AD4691_CHANNEL(14), + AD4691_CHANNEL(15), + IIO_CHAN_SOFT_TIMESTAMP(16), +}; + +static const struct iio_chan_spec ad4693_channels[] = { + AD4691_CHANNEL(0), + AD4691_CHANNEL(1), + AD4691_CHANNEL(2), + AD4691_CHANNEL(3), + AD4691_CHANNEL(4), + AD4691_CHANNEL(5), + AD4691_CHANNEL(6), + AD4691_CHANNEL(7), + IIO_CHAN_SOFT_TIMESTAMP(8), +}; + +/* + * Offload channel arrays: no IIO_CHAN_SOFT_TIMESTAMP because DMA delivers + * data directly to userspace without a software timestamp. + */ +static const struct iio_chan_spec ad4691_offload_channels[] = { + AD4691_OFFLOAD_CHANNEL(0), + AD4691_OFFLOAD_CHANNEL(1), + AD4691_OFFLOAD_CHANNEL(2), + AD4691_OFFLOAD_CHANNEL(3), + AD4691_OFFLOAD_CHANNEL(4), + AD4691_OFFLOAD_CHANNEL(5), + AD4691_OFFLOAD_CHANNEL(6), + AD4691_OFFLOAD_CHANNEL(7), + AD4691_OFFLOAD_CHANNEL(8), + AD4691_OFFLOAD_CHANNEL(9), + AD4691_OFFLOAD_CHANNEL(10), + AD4691_OFFLOAD_CHANNEL(11), + AD4691_OFFLOAD_CHANNEL(12), + AD4691_OFFLOAD_CHANNEL(13), + AD4691_OFFLOAD_CHANNEL(14), + AD4691_OFFLOAD_CHANNEL(15), +}; + +static const struct iio_chan_spec ad4693_offload_channels[] = { + AD4691_OFFLOAD_CHANNEL(0), + AD4691_OFFLOAD_CHANNEL(1), + AD4691_OFFLOAD_CHANNEL(2), + AD4691_OFFLOAD_CHANNEL(3), + AD4691_OFFLOAD_CHANNEL(4), + AD4691_OFFLOAD_CHANNEL(5), + AD4691_OFFLOAD_CHANNEL(6), + AD4691_OFFLOAD_CHANNEL(7), +}; + +static const struct iio_chan_spec ad4691_manual_channels[] = { + AD4691_MANUAL_CHANNEL(0), + AD4691_MANUAL_CHANNEL(1), + AD4691_MANUAL_CHANNEL(2), + AD4691_MANUAL_CHANNEL(3), + AD4691_MANUAL_CHANNEL(4), + AD4691_MANUAL_CHANNEL(5), + AD4691_MANUAL_CHANNEL(6), + AD4691_MANUAL_CHANNEL(7), + AD4691_MANUAL_CHANNEL(8), + AD4691_MANUAL_CHANNEL(9), + AD4691_MANUAL_CHANNEL(10), + AD4691_MANUAL_CHANNEL(11), + AD4691_MANUAL_CHANNEL(12), + AD4691_MANUAL_CHANNEL(13), + AD4691_MANUAL_CHANNEL(14), + AD4691_MANUAL_CHANNEL(15), + IIO_CHAN_SOFT_TIMESTAMP(16), +}; + +static const struct iio_chan_spec ad4693_manual_channels[] = { + AD4691_MANUAL_CHANNEL(0), + AD4691_MANUAL_CHANNEL(1), + AD4691_MANUAL_CHANNEL(2), + AD4691_MANUAL_CHANNEL(3), + AD4691_MANUAL_CHANNEL(4), + AD4691_MANUAL_CHANNEL(5), + AD4691_MANUAL_CHANNEL(6), + AD4691_MANUAL_CHANNEL(7), + IIO_CHAN_SOFT_TIMESTAMP(8), +}; + +static const struct iio_chan_spec ad4691_offload_manual_channels[] = { + AD4691_OFFLOAD_MANUAL_CHANNEL(0), + AD4691_OFFLOAD_MANUAL_CHANNEL(1), + AD4691_OFFLOAD_MANUAL_CHANNEL(2), + AD4691_OFFLOAD_MANUAL_CHANNEL(3), + AD4691_OFFLOAD_MANUAL_CHANNEL(4), + AD4691_OFFLOAD_MANUAL_CHANNEL(5), + AD4691_OFFLOAD_MANUAL_CHANNEL(6), + AD4691_OFFLOAD_MANUAL_CHANNEL(7), + AD4691_OFFLOAD_MANUAL_CHANNEL(8), + AD4691_OFFLOAD_MANUAL_CHANNEL(9), + AD4691_OFFLOAD_MANUAL_CHANNEL(10), + AD4691_OFFLOAD_MANUAL_CHANNEL(11), + AD4691_OFFLOAD_MANUAL_CHANNEL(12), + AD4691_OFFLOAD_MANUAL_CHANNEL(13), + AD4691_OFFLOAD_MANUAL_CHANNEL(14), + AD4691_OFFLOAD_MANUAL_CHANNEL(15), +}; + +static const struct iio_chan_spec ad4693_offload_manual_channels[] = { + AD4691_OFFLOAD_MANUAL_CHANNEL(0), + AD4691_OFFLOAD_MANUAL_CHANNEL(1), + AD4691_OFFLOAD_MANUAL_CHANNEL(2), + AD4691_OFFLOAD_MANUAL_CHANNEL(3), + AD4691_OFFLOAD_MANUAL_CHANNEL(4), + AD4691_OFFLOAD_MANUAL_CHANNEL(5), + AD4691_OFFLOAD_MANUAL_CHANNEL(6), + AD4691_OFFLOAD_MANUAL_CHANNEL(7), +}; + +static const int ad4691_oversampling_ratios[] = { 1, 2, 4, 8, 16, 32 }; + +static const struct ad4691_channel_info ad4691_sw_info = { + .channels = ad4691_channels, + .manual_channels = ad4691_manual_channels, + .num_channels = ARRAY_SIZE(ad4691_channels), +}; + +static const struct ad4691_channel_info ad4693_sw_info = { + .channels = ad4693_channels, + .manual_channels = ad4693_manual_channels, + .num_channels = ARRAY_SIZE(ad4693_channels), +}; + +static const struct ad4691_channel_info ad4691_offload_info = { + .channels = ad4691_offload_channels, + .manual_channels = ad4691_offload_manual_channels, + .num_channels = ARRAY_SIZE(ad4691_offload_channels), +}; + +static const struct ad4691_channel_info ad4693_offload_info = { + .channels = ad4693_offload_channels, + .manual_channels = ad4693_offload_manual_channels, + .num_channels = ARRAY_SIZE(ad4693_offload_channels), +}; + +/* + * Internal oscillator frequency table. Index is the OSC_FREQ_REG[3:0] value. + * Index 0 (1 MHz) is only valid for AD4692/AD4694; AD4691/AD4693 support + * up to 500 kHz and use index 1 as their highest valid rate. + */ +static const int ad4691_osc_freqs_Hz[] = { + [0x0] = 1000000, + [0x1] = 500000, + [0x2] = 400000, + [0x3] = 250000, + [0x4] = 200000, + [0x5] = 167000, + [0x6] = 133000, + [0x7] = 125000, + [0x8] = 100000, + [0x9] = 50000, + [0xA] = 25000, + [0xB] = 12500, + [0xC] = 10000, + [0xD] = 5000, + [0xE] = 2500, + [0xF] = 1250, +}; + +static const char * const ad4691_gp_names[] = { "gp0", "gp1", "gp2", "gp3" }; + +static const struct ad4691_chip_info ad4691_chip_info = { + .name = "ad4691", + .max_rate = 500 * HZ_PER_KHZ, + .sw_info = &ad4691_sw_info, + .offload_info = &ad4691_offload_info, +}; + +static const struct ad4691_chip_info ad4692_chip_info = { + .name = "ad4692", + .max_rate = 1 * HZ_PER_MHZ, + .sw_info = &ad4691_sw_info, + .offload_info = &ad4691_offload_info, +}; + +static const struct ad4691_chip_info ad4693_chip_info = { + .name = "ad4693", + .max_rate = 500 * HZ_PER_KHZ, + .sw_info = &ad4693_sw_info, + .offload_info = &ad4693_offload_info, +}; + +static const struct ad4691_chip_info ad4694_chip_info = { + .name = "ad4694", + .max_rate = 1 * HZ_PER_MHZ, + .sw_info = &ad4693_sw_info, + .offload_info = &ad4693_offload_info, +}; + +struct ad4691_state { + const struct ad4691_chip_info *info; + struct regmap *regmap; + struct spi_device *spi; + + struct pwm_device *conv_trigger; + int irq; + int vref_uV; + u32 cnv_period_ns; + /* + * Snapped oscillator frequency (Hz) shared by all channels. Set when + * sampling_frequency or oversampling_ratio is written; written to + * OSC_FREQ_REG at buffer enable and single-shot time so both attributes + * can be set in any order. Reading in_voltage_sampling_frequency + * returns target_osc_freq_Hz / osr — the effective rate given the + * shared oversampling ratio. + */ + u32 target_osc_freq_Hz; + /* Shared oversampling ratio across all channels; always 1 in manual mode. */ + unsigned int osr; + /* + * Precomputed effective-rate lists, one row per entry in + * ad4691_oversampling_ratios[]. Populated at probe; read_avail picks + * the row for the current shared OSR. The tables are stable after + * probe so returning a pointer into them from read_avail is race-free. + */ + int samp_freq_avail[ARRAY_SIZE(ad4691_oversampling_ratios)][ARRAY_SIZE(ad4691_osc_freqs_Hz)]; + int samp_freq_avail_len[ARRAY_SIZE(ad4691_oversampling_ratios)]; + + bool manual_mode; + bool irq_enabled; + bool refbuf_en; + bool ldo_en; + /* + * Synchronize access to members of the driver state, and ensure + * atomicity of consecutive SPI operations. + */ + struct mutex lock; + /* NULL when no SPI offload hardware is present. */ + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + u64 trigger_hz; + /* + * Per-buffer-enable lifetime resources: + * Manual Mode - a pre-built SPI message that clocks out N+1 + * transfers in one go. + * CNV Burst Mode - a pre-built SPI message that clocks out 2*N + * transfers in one go. + */ + struct spi_message scan_msg; + /* + * max 16 + 1 NOOP (manual) or 2*16 + 1 state-reset (CNV burst). + */ + struct spi_transfer scan_xfers[34]; + /* + * CNV burst: 16 AVG_IN addresses = 16. Manual: 16 channel cmds + + * 1 NOOP = 17. Stored as native u16. The non-offload path fills slots + * with put_unaligned_be16() (bits_per_word=8, bytes go out in memory + * order). The offload path assigns native values directly + * (bits_per_word=bpw, SPI reads each slot as a native 16-bit word and + * shifts it out MSB-first). + */ + u16 scan_tx[17] __aligned(IIO_DMA_MINALIGN); + /* + * CNV burst state-reset: 4-byte write [addr_hi, addr_lo, + * STATE_RESET_ALL, OSC_EN=1]. CS is asserted throughout, so + * ADDR_DESCENDING writes byte[3]=1 to OSC_EN_REG (0x180) as a + * deliberate side-write, keeping the oscillator enabled. Shared + * with the offload path (mutually exclusive at probe). + */ + u8 scan_tx_reset[4] __aligned(IIO_DMA_MINALIGN); + /* + * Scan buffer: one BE16 slot per active channel, plus timestamp. + * DMA-aligned because scan_xfers point rx_buf directly into vals[]. + */ + IIO_DECLARE_DMA_BUFFER_WITH_TS(__be16, vals, 16); +}; + +/* + * Configure the given GP pin (0-3) as DATA_READY output. + * GP0/GP1 → GPIO_MODE1_REG, GP2/GP3 → GPIO_MODE2_REG. + * Even pins occupy bits [3:0], odd pins bits [7:4]. + */ +static int ad4691_gpio_setup(struct ad4691_state *st, unsigned int gp_num) +{ + unsigned int bit_off = gp_num % 2; + unsigned int reg_off = gp_num / 2; + unsigned int shift = 4 * bit_off; + + return regmap_update_bits(st->regmap, + AD4691_GPIO_MODE1_REG + reg_off, + AD4691_GP_MODE_MASK << shift, + AD4691_GP_MODE_DATA_READY << shift); +} + +static const struct spi_offload_config ad4691_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + +static bool ad4691_offload_trigger_match(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + return type == SPI_OFFLOAD_TRIGGER_DATA_READY && nargs == 1 && args[0] <= 3; +} + +static int ad4691_offload_trigger_request(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + struct ad4691_state *st = spi_offload_trigger_get_priv(trigger); + + if (nargs != 1 || args[0] > 3) + return -EINVAL; + + return ad4691_gpio_setup(st, args[0]); +} + +static int ad4691_offload_trigger_validate(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + if (config->type != SPI_OFFLOAD_TRIGGER_DATA_READY) + return -EINVAL; + + return 0; +} + +static const struct spi_offload_trigger_ops ad4691_offload_trigger_ops = { + .match = ad4691_offload_trigger_match, + .request = ad4691_offload_trigger_request, + .validate = ad4691_offload_trigger_validate, +}; + +static int ad4691_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct spi_device *spi = context; + u8 tx[2], rx[4]; + int ret; + + /* Set bit 15 to mark the operation as READ. */ + put_unaligned_be16(0x8000 | reg, tx); + + switch (reg) { + case 0 ... AD4691_OSC_FREQ_REG: + case AD4691_SPARE_CONTROL ... AD4691_ACC_MASK_REG - 1: + case AD4691_ACC_MASK_REG + 1 ... AD4691_ACC_SAT_OVR_REG(15): + ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 1); + if (ret) + return ret; + *val = rx[0]; + return 0; + case AD4691_ACC_MASK_REG: + case AD4691_STD_SEQ_CONFIG: + case AD4691_AVG_IN(0) ... AD4691_AVG_IN(15): + ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 2); + if (ret) + return ret; + *val = get_unaligned_be16(rx); + return 0; + case AD4691_AVG_STS_IN(0) ... AD4691_AVG_STS_IN(15): + case AD4691_ACC_IN(0) ... AD4691_ACC_IN(15): + ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 3); + if (ret) + return ret; + *val = get_unaligned_be24(rx); + return 0; + case AD4691_ACC_STS_DATA(0) ... AD4691_ACC_STS_DATA(15): + ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 4); + if (ret) + return ret; + *val = get_unaligned_be32(rx); + return 0; + default: + return -EINVAL; + } +} + +static int ad4691_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct spi_device *spi = context; + u8 tx[4]; + + put_unaligned_be16(reg, tx); + + switch (reg) { + case 0 ... AD4691_OSC_FREQ_REG: + case AD4691_SPARE_CONTROL ... AD4691_ACC_MASK_REG - 1: + case AD4691_ACC_MASK_REG + 1 ... AD4691_GPIO_MODE2_REG: + if (val > U8_MAX) + return -EINVAL; + tx[2] = val; + return spi_write_then_read(spi, tx, 3, NULL, 0); + case AD4691_ACC_MASK_REG: + case AD4691_STD_SEQ_CONFIG: + if (val > U16_MAX) + return -EINVAL; + put_unaligned_be16(val, &tx[2]); + return spi_write_then_read(spi, tx, 4, NULL, 0); + default: + return -EINVAL; + } +} + +static bool ad4691_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AD4691_STATUS_REG: + case AD4691_CLAMP_STATUS1_REG: + case AD4691_CLAMP_STATUS2_REG: + case AD4691_GPIO_READ: + case AD4691_ACC_STATUS_FULL1_REG ... AD4691_ACC_STATUS_SAT2_REG: + case AD4691_ACC_SAT_OVR_REG(0) ... AD4691_ACC_SAT_OVR_REG(15): + case AD4691_AVG_IN(0) ... AD4691_AVG_IN(15): + case AD4691_AVG_STS_IN(0) ... AD4691_AVG_STS_IN(15): + case AD4691_ACC_IN(0) ... AD4691_ACC_IN(15): + case AD4691_ACC_STS_DATA(0) ... AD4691_ACC_STS_DATA(15): + return true; + default: + return false; + } +} + +static bool ad4691_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0 ... AD4691_OSC_FREQ_REG: + case AD4691_SPARE_CONTROL ... AD4691_ACC_SAT_OVR_REG(15): + case AD4691_STD_SEQ_CONFIG: + return true; + default: + break; + } + + /* + * Multi-byte result registers have non-unit strides; only the base + * address of each entry is a valid single-register read. + */ + if (reg >= AD4691_AVG_IN(0) && reg <= AD4691_AVG_IN(15)) + return (reg - AD4691_AVG_IN(0)) % 2 == 0; + if (reg >= AD4691_AVG_STS_IN(0) && reg <= AD4691_AVG_STS_IN(15)) + return (reg - AD4691_AVG_STS_IN(0)) % 3 == 0; + if (reg >= AD4691_ACC_IN(0) && reg <= AD4691_ACC_IN(15)) + return (reg - AD4691_ACC_IN(0)) % 3 == 0; + if (reg >= AD4691_ACC_STS_DATA(0) && reg <= AD4691_ACC_STS_DATA(15)) + return (reg - AD4691_ACC_STS_DATA(0)) % 4 == 0; + + return false; +} + +static bool ad4691_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0 ... AD4691_OSC_FREQ_REG: + case AD4691_STD_SEQ_CONFIG: + case AD4691_SPARE_CONTROL ... AD4691_GPIO_MODE2_REG: + return true; + default: + return false; + } +} + +static const struct regmap_config ad4691_regmap_config = { + .reg_bits = 16, + .val_bits = 32, + .reg_read = ad4691_reg_read, + .reg_write = ad4691_reg_write, + .volatile_reg = ad4691_volatile_reg, + .readable_reg = ad4691_readable_reg, + .writeable_reg = ad4691_writeable_reg, + .max_register = AD4691_ACC_STS_DATA(15), + .cache_type = REGCACHE_MAPLE, +}; + +/* + * Index 0 in ad4691_osc_freqs_Hz is 1 MHz — valid only for AD4692/AD4694 + * (max_rate == 1 MHz). AD4691/AD4693 cap at 500 kHz so their valid range + * starts at index 1. + */ +static unsigned int ad4691_samp_freq_start(const struct ad4691_chip_info *info) +{ + return (info->max_rate == 1 * HZ_PER_MHZ) ? 0 : 1; +} + +/* + * Find the largest oscillator table entry that is both <= needed_osc and + * evenly divisible by osr (guaranteeing an integer effective rate on + * read-back). Returns 0 if no such entry exists in the chip's valid range. + */ +static unsigned int ad4691_find_osc_freq(struct ad4691_state *st, + unsigned int needed_osc, + unsigned int osr) +{ + unsigned int start = ad4691_samp_freq_start(st->info); + + for (unsigned int i = start; i < ARRAY_SIZE(ad4691_osc_freqs_Hz); i++) { + if ((unsigned int)ad4691_osc_freqs_Hz[i] > needed_osc) + continue; + if (ad4691_osc_freqs_Hz[i] % osr) + continue; + return ad4691_osc_freqs_Hz[i]; + } + return 0; +} + +/* Write target_osc_freq_Hz to OSC_FREQ_REG. Called at use time. */ +static int ad4691_write_osc_freq(struct ad4691_state *st) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(ad4691_osc_freqs_Hz); i++) { + if (ad4691_osc_freqs_Hz[i] == st->target_osc_freq_Hz) + return regmap_write(st->regmap, AD4691_OSC_FREQ_REG, i); + } + return -EINVAL; +} + +/* Return the index of osr in ad4691_oversampling_ratios[], defaulting to 0. */ +static unsigned int ad4691_osr_index(unsigned int osr) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(ad4691_oversampling_ratios) - 1; i++) { + if ((unsigned int)ad4691_oversampling_ratios[i] == osr) + return i; + } + return ARRAY_SIZE(ad4691_oversampling_ratios) - 1; +} + +/* + * Precompute samp_freq_avail[][]: for each OSR value, list the oscillator + * table entries that divide evenly by that OSR, expressed as effective rates + * (osc_freq / osr). Called once at probe after st->info is set. + */ +static void ad4691_precompute_samp_freq_avail(struct ad4691_state *st) +{ + unsigned int start = ad4691_samp_freq_start(st->info); + + for (unsigned int i = 0; i < ARRAY_SIZE(ad4691_oversampling_ratios); i++) { + unsigned int osr = ad4691_oversampling_ratios[i]; + int n = 0; + + for (unsigned int j = start; j < ARRAY_SIZE(ad4691_osc_freqs_Hz); j++) { + if (ad4691_osc_freqs_Hz[j] % osr) + continue; + st->samp_freq_avail[i][n++] = ad4691_osc_freqs_Hz[j] / osr; + } + st->samp_freq_avail_len[i] = n; + } +} + +static int ad4691_set_sampling_freq(struct ad4691_state *st, int freq) +{ + unsigned int osr, found; + + /* + * Read osr under st->lock: osr and target_osc_freq_Hz are modified + * together under the lock; reading after acquiring it ensures we see + * a consistent snapshot with no concurrent write racing us. + */ + guard(mutex)(&st->lock); + osr = st->osr; + + if (freq <= 0 || (unsigned int)freq > st->info->max_rate / osr) + return -EINVAL; + + found = ad4691_find_osc_freq(st, (unsigned int)freq * osr, osr); + if (!found) + return -EINVAL; + + /* + * Store the snapped oscillator frequency; OSC_FREQ_REG is written at + * buffer enable and single-shot time so that sampling_frequency and + * oversampling_ratio can be set in any order. + */ + st->target_osc_freq_Hz = found; + return 0; +} + +static int ad4691_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, + int *length, long mask) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: { + unsigned int osr_idx; + + /* + * The precomputed tables are stable after probe; only the + * current OSR needs to be read under the lock to pick the + * right row atomically. + */ + guard(mutex)(&st->lock); + osr_idx = ad4691_osr_index(st->osr); + *vals = st->samp_freq_avail[osr_idx]; + *type = IIO_VAL_INT; + *length = st->samp_freq_avail_len[osr_idx]; + return IIO_AVAIL_LIST; + } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *vals = ad4691_oversampling_ratios; + *type = IIO_VAL_INT; + *length = ARRAY_SIZE(ad4691_oversampling_ratios); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int ad4691_single_shot_read(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) +{ + struct ad4691_state *st = iio_priv(indio_dev); + unsigned int reg_val, period_us; + int ret; + + guard(mutex)(&st->lock); + + /* Use AUTONOMOUS mode for single-shot reads. */ + ret = regmap_write(st->regmap, AD4691_STATE_RESET_REG, AD4691_STATE_RESET_ALL); + if (ret) + return ret; + + ret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG, + BIT(chan->channel)); + if (ret) + return ret; + + ret = regmap_write(st->regmap, AD4691_ACC_MASK_REG, + ~BIT(chan->channel) & GENMASK(15, 0)); + if (ret) + return ret; + + ret = regmap_write(st->regmap, AD4691_ACC_DEPTH_IN(0), st->osr); + if (ret) + return ret; + + ret = ad4691_write_osc_freq(st); + if (ret) + return ret; + + ret = regmap_write(st->regmap, AD4691_OSC_EN_REG, 1); + if (ret) + return ret; + + /* + * Wait osr + 1 oscillator periods: osr for accumulation, +1 for the + * pipeline margin (one extra period ensures the final result is ready). + */ + period_us = DIV_ROUND_UP((st->osr + 1) * USEC_PER_SEC, + st->target_osc_freq_Hz); + fsleep(period_us); + + ret = regmap_write(st->regmap, AD4691_OSC_EN_REG, 0); + if (ret) + return ret; + + ret = regmap_read(st->regmap, AD4691_AVG_IN(chan->channel), ®_val); + if (ret) + return ret; + + *val = reg_val; + + ret = regmap_write(st->regmap, AD4691_STATE_RESET_REG, AD4691_STATE_RESET_ALL); + if (ret) + return ret; + + return IIO_VAL_INT; +} + +static int ad4691_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long info) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: { + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + return ad4691_single_shot_read(indio_dev, chan, val); + } + case IIO_CHAN_INFO_SAMP_FREQ: { + /* + * Read target_osc_freq_Hz and osr under st->lock to get a + * consistent snapshot: write_raw for SAMP_FREQ or OSR modifies + * both fields under the lock, so a concurrent read without the + * lock could observe a new oscillator frequency with the old OSR. + */ + guard(mutex)(&st->lock); + *val = st->target_osc_freq_Hz / st->osr; + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { + guard(mutex)(&st->lock); + *val = st->osr; + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SCALE: + *val = st->vref_uV / (MICRO / MILLI); + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static int ad4691_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return ad4691_set_sampling_freq(st, val); + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { + unsigned int old_effective, found, osr_idx; + + osr_idx = ad4691_osr_index(val); + if (ad4691_oversampling_ratios[osr_idx] != val) + return -EINVAL; + + /* + * Hold st->lock while computing the new oscillator frequency + * and updating both target_osc_freq_Hz and osr atomically: + * read_raw for SAMP_FREQ reads both fields under the lock and + * must see a consistent pair (new osc ↔ new osr). + * + * Snap target_osc_freq_Hz to the largest table entry that is + * both <= old_effective * new_osr and evenly divisible by + * new_osr, preserving an integer read-back of + * in_voltage_sampling_frequency after the OSR change. + */ + guard(mutex)(&st->lock); + old_effective = st->target_osc_freq_Hz / st->osr; + found = ad4691_find_osc_freq(st, old_effective * (unsigned int)val, val); + if (!found) + return -EINVAL; + st->target_osc_freq_Hz = found; + st->osr = val; + return 0; + } + default: + return -EINVAL; + } +} + +static int ad4691_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + guard(mutex)(&st->lock); + + if (readval) + return regmap_read(st->regmap, reg, readval); + + return regmap_write(st->regmap, reg, writeval); +} + +static int ad4691_set_pwm_freq(struct ad4691_state *st, unsigned int freq) +{ + if (!freq) + return -EINVAL; + + st->cnv_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, freq); + return 0; +} + +static int ad4691_sampling_enable(struct ad4691_state *st, bool enable) +{ + struct pwm_state conv_state = { + .period = st->cnv_period_ns, + .duty_cycle = AD4691_CNV_DUTY_CYCLE_NS, + .polarity = PWM_POLARITY_NORMAL, + .enabled = enable, + }; + + return pwm_apply_might_sleep(st->conv_trigger, &conv_state); +} + +/* + * ad4691_enter_conversion_mode - Switch the chip to its buffer conversion mode. + * + * Configures the ADC hardware registers for the mode selected at probe + * (CNV_BURST or MANUAL). Called from buffer preenable before starting + * sampling. The chip is in AUTONOMOUS mode during idle (for read_raw). + */ +static int ad4691_enter_conversion_mode(struct ad4691_state *st) +{ + int ret; + + if (st->manual_mode) + return regmap_update_bits(st->regmap, AD4691_DEVICE_SETUP, + AD4691_MANUAL_MODE, AD4691_MANUAL_MODE); + + ret = ad4691_write_osc_freq(st); + if (ret) + return ret; + + ret = regmap_update_bits(st->regmap, AD4691_ADC_SETUP, + AD4691_ADC_MODE_MASK, AD4691_CNV_BURST_MODE); + if (ret) + return ret; + + return regmap_write(st->regmap, AD4691_STATE_RESET_REG, + AD4691_STATE_RESET_ALL); +} + +static int ad4691_transfer(struct ad4691_state *st, u16 cmd) +{ + u8 buf[2]; + + put_unaligned_be16(cmd, buf); + + return spi_write_then_read(st->spi, buf, sizeof(buf), NULL, 0); +} + +/* + * ad4691_exit_conversion_mode - Return the chip to AUTONOMOUS mode. + * + * Called from buffer postdisable to restore the chip to the + * idle state used by read_raw. Clears the sequencer and resets state. + */ +static int ad4691_exit_conversion_mode(struct ad4691_state *st) +{ + if (st->manual_mode) + return ad4691_transfer(st, AD4691_EXIT_COMMAND); + + return regmap_update_bits(st->regmap, AD4691_ADC_SETUP, + AD4691_ADC_MODE_MASK, AD4691_AUTONOMOUS_MODE); +} + +static int ad4691_manual_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + unsigned int k, i; + int ret; + + memset(st->scan_xfers, 0, sizeof(st->scan_xfers)); + memset(st->scan_tx, 0, sizeof(st->scan_tx)); + + spi_message_init(&st->scan_msg); + + k = 0; + iio_for_each_active_channel(indio_dev, i) { + /* + * Channel-select command occupies the first (high) byte of the + * 16-bit DIN frame; the second byte is a don't-care zero pad. + * put_unaligned_be16() writes [cmd, 0x00] in memory so the + * SPI controller sends the command byte first on the wire. + */ + put_unaligned_be16((u16)(AD4691_ADC_CHAN(i) << 8), &st->scan_tx[k]); + st->scan_xfers[k].tx_buf = &st->scan_tx[k]; + /* + * The pipeline means xfer[0] receives the residual from the + * previous sequence, not a valid sample. Discard it (rx_buf=NULL) + * to avoid aliasing vals[0] across two concurrent DMA mappings. + * xfer[1] (or the NOOP when only one channel is active) writes + * the real ch[0] result to vals[0]. Subsequent transfers write + * into vals[k-1] so each result lands at the next dense slot. + */ + st->scan_xfers[k].rx_buf = (k == 0) ? NULL : &st->vals[k - 1]; + st->scan_xfers[k].len = sizeof(*st->scan_tx); + st->scan_xfers[k].cs_change = 1; + st->scan_xfers[k].cs_change_delay.value = AD4691_CNV_HIGH_TIME_NS; + st->scan_xfers[k].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; + spi_message_add_tail(&st->scan_xfers[k], &st->scan_msg); + k++; + } + + /* Final NOOP transfer retrieves the last channel's result. */ + st->scan_xfers[k].tx_buf = &st->scan_tx[k]; /* scan_tx[k] == 0 == NOOP */ + st->scan_xfers[k].rx_buf = &st->vals[k - 1]; + st->scan_xfers[k].len = sizeof(*st->scan_tx); + spi_message_add_tail(&st->scan_xfers[k], &st->scan_msg); + + ret = spi_optimize_message(st->spi, &st->scan_msg); + if (ret) + return ret; + + ret = ad4691_enter_conversion_mode(st); + if (ret) { + spi_unoptimize_message(&st->scan_msg); + return ret; + } + + return 0; +} + +static int ad4691_manual_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + int ret; + + ret = ad4691_exit_conversion_mode(st); + spi_unoptimize_message(&st->scan_msg); + return ret; +} + +static const struct iio_buffer_setup_ops ad4691_manual_buffer_setup_ops = { + .preenable = ad4691_manual_buffer_preenable, + .postdisable = ad4691_manual_buffer_postdisable, +}; + +static int ad4691_cnv_burst_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + unsigned int acc_mask, std_seq_config; + unsigned int k, i; + int ret; + + memset(st->scan_xfers, 0, sizeof(st->scan_xfers)); + memset(st->scan_tx, 0, sizeof(st->scan_tx)); + + spi_message_init(&st->scan_msg); + + /* + * Each AVG_IN read needs two transfers: a 2-byte address write phase + * followed by a 2-byte data read phase. CS toggles between channels + * (cs_change=1 on the read phase of all but the last channel). + */ + k = 0; + iio_for_each_active_channel(indio_dev, i) { + put_unaligned_be16(0x8000 | AD4691_AVG_IN(i), &st->scan_tx[k]); + st->scan_xfers[2 * k].tx_buf = &st->scan_tx[k]; + st->scan_xfers[2 * k].len = sizeof(*st->scan_tx); + spi_message_add_tail(&st->scan_xfers[2 * k], &st->scan_msg); + st->scan_xfers[2 * k + 1].rx_buf = &st->vals[k]; + st->scan_xfers[2 * k + 1].len = sizeof(*st->scan_tx); + st->scan_xfers[2 * k + 1].cs_change = 1; + spi_message_add_tail(&st->scan_xfers[2 * k + 1], &st->scan_msg); + k++; + } + + /* + * Append a 4-byte state-reset transfer [addr_hi, addr_lo, + * STATE_RESET_ALL, OSC_EN=1]. CS is asserted throughout, so + * ADDR_DESCENDING writes byte[3]=1 to OSC_EN_REG (0x180) as a + * deliberate side-write, keeping the oscillator enabled. + * STATE_RESET_ALL starts the next burst; the hardware does not + * accumulate new conversions until after a STATE_RESET pulse, so + * no in-progress data is lost. No cs_change here — CS must + * deassert normally at end of message to frame the next command. + */ + put_unaligned_be16(AD4691_STATE_RESET_REG, st->scan_tx_reset); + st->scan_tx_reset[2] = AD4691_STATE_RESET_ALL; + st->scan_tx_reset[3] = 1; + st->scan_xfers[2 * k].tx_buf = st->scan_tx_reset; + st->scan_xfers[2 * k].len = sizeof(st->scan_tx_reset); + spi_message_add_tail(&st->scan_xfers[2 * k], &st->scan_msg); + + ret = spi_optimize_message(st->spi, &st->scan_msg); + if (ret) + return ret; + + std_seq_config = bitmap_read(indio_dev->active_scan_mask, 0, + iio_get_masklength(indio_dev)) & GENMASK(15, 0); + ret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG, std_seq_config); + if (ret) + goto err_unoptimize; + + acc_mask = ~std_seq_config & GENMASK(15, 0); + ret = regmap_write(st->regmap, AD4691_ACC_MASK_REG, acc_mask); + if (ret) + goto err_unoptimize; + + ret = regmap_write(st->regmap, AD4691_ACC_DEPTH_IN(0), st->osr); + if (ret) + goto err_unoptimize; + + ret = ad4691_enter_conversion_mode(st); + if (ret) + goto err_unoptimize; + + return 0; + +err_unoptimize: + spi_unoptimize_message(&st->scan_msg); + return ret; +} + +static int ad4691_cnv_burst_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + int ret; + + /* + * Start the PWM and unmask the IRQ here in postenable, not in + * preenable. The IIO core attaches the trigger poll function between + * preenable and postenable; enabling sampling or unmasking the IRQ + * before that point risks a DATA_READY assertion landing before the + * poll function is registered. iio_trigger_poll() would drop the + * event, disable_irq_nosync() would fire, and enable_irq() would + * never be called, leaving the IRQ permanently masked. + */ + ret = ad4691_sampling_enable(st, true); + if (ret) + return ret; + + enable_irq(st->irq); + st->irq_enabled = true; + return 0; +} + +static int ad4691_cnv_burst_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + if (st->irq_enabled) { + disable_irq(st->irq); + st->irq_enabled = false; + } + return ad4691_sampling_enable(st, false); +} + +static int ad4691_cnv_burst_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + int ret; + + ret = ad4691_exit_conversion_mode(st); + spi_unoptimize_message(&st->scan_msg); + return ret; +} + +static const struct iio_buffer_setup_ops ad4691_cnv_burst_buffer_setup_ops = { + .preenable = ad4691_cnv_burst_buffer_preenable, + .postenable = ad4691_cnv_burst_buffer_postenable, + .predisable = ad4691_cnv_burst_buffer_predisable, + .postdisable = ad4691_cnv_burst_buffer_postdisable, +}; + +static int ad4691_manual_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->regmap); + struct spi_device *spi = to_spi_device(dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_PERIODIC, + }; + unsigned int bpw = indio_dev->channels[0].scan_type.realbits; + unsigned int bit, k; + int ret; + + ret = ad4691_enter_conversion_mode(st); + if (ret) + return ret; + + memset(st->scan_xfers, 0, sizeof(st->scan_xfers)); + memset(st->scan_tx, 0, sizeof(st->scan_tx)); + + /* + * N+1 transfers for N channels. Each CS-low period triggers + * a conversion AND returns the previous result (pipelined). + * TX: [AD4691_ADC_CHAN(n), 0x00] + * RX: [data_hi, data_lo] (storagebits=16, shift=0) + * Transfer 0 RX is garbage; transfers 1..N carry real data. + * scan_tx is reused for TX commands (mutually exclusive with the + * non-offload triggered-buffer path). + * + * bits_per_word=bpw: the SPI controller reads tx_buf as a native + * 16-bit word and shifts it out MSB-first. Store the exact 16-bit + * value we want on the wire as a plain native u16 — no endianness + * macro — so the wire bytes are correct on both LE and BE hosts. + * The channel-select command is a single byte; shift it to the MSB + * position so SPI sends it first, with a zero pad in the LSB. + */ + k = 0; + iio_for_each_active_channel(indio_dev, bit) { + st->scan_tx[k] = AD4691_ADC_CHAN(bit) << 8; + st->scan_xfers[k].tx_buf = &st->scan_tx[k]; + st->scan_xfers[k].len = sizeof(*st->scan_tx); + st->scan_xfers[k].bits_per_word = bpw; + st->scan_xfers[k].cs_change = 1; + st->scan_xfers[k].cs_change_delay.value = AD4691_CNV_HIGH_TIME_NS; + st->scan_xfers[k].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; + /* First transfer RX is garbage — skip it. */ + if (k > 0) + st->scan_xfers[k].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + k++; + } + + /* Final NOOP transfer retrieves the last channel's result. */ + st->scan_xfers[k].tx_buf = &st->scan_tx[k]; /* scan_tx[k] == 0 == NOOP */ + st->scan_xfers[k].len = sizeof(*st->scan_tx); + st->scan_xfers[k].bits_per_word = bpw; + st->scan_xfers[k].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + k++; + + spi_message_init_with_transfers(&st->scan_msg, st->scan_xfers, k); + st->scan_msg.offload = st->offload; + + ret = spi_optimize_message(spi, &st->scan_msg); + if (ret) + goto err_exit_conversion; + + config.periodic.frequency_hz = st->trigger_hz; + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, &config); + if (ret) + goto err_unoptimize; + + return 0; + +err_unoptimize: + spi_unoptimize_message(&st->scan_msg); +err_exit_conversion: + ad4691_exit_conversion_mode(st); + return ret; +} + +static int ad4691_manual_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + spi_unoptimize_message(&st->scan_msg); + + return ad4691_exit_conversion_mode(st); +} + +static const struct iio_buffer_setup_ops ad4691_manual_offload_buffer_setup_ops = { + .postenable = ad4691_manual_offload_buffer_postenable, + .predisable = ad4691_manual_offload_buffer_predisable, +}; + +static int ad4691_cnv_burst_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->regmap); + struct spi_device *spi = to_spi_device(dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_DATA_READY, + }; + unsigned int bpw = indio_dev->channels[0].scan_type.realbits; + unsigned int acc_mask, std_seq_config; + unsigned int bit, k; + int ret; + + std_seq_config = bitmap_read(indio_dev->active_scan_mask, 0, + iio_get_masklength(indio_dev)) & GENMASK(15, 0); + ret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG, std_seq_config); + if (ret) + return ret; + + acc_mask = ~std_seq_config & GENMASK(15, 0); + ret = regmap_write(st->regmap, AD4691_ACC_MASK_REG, acc_mask); + if (ret) + return ret; + + ret = regmap_write(st->regmap, AD4691_ACC_DEPTH_IN(0), st->osr); + if (ret) + return ret; + + ret = ad4691_enter_conversion_mode(st); + if (ret) + return ret; + + memset(st->scan_xfers, 0, sizeof(st->scan_xfers)); + memset(st->scan_tx, 0, sizeof(st->scan_tx)); + + /* + * Each AVG_IN register read uses two transfers: + * TX: [reg_hi | 0x80, reg_lo] (address phase, CS stays asserted) + * RX: [data_hi, data_lo] (bpw-wide data phase, storagebits=16) + * Both TX and RX use bits_per_word=bpw: the SPI controller reads tx_buf + * as a native 16-bit word and shifts it out MSB-first. Store the exact + * 16-bit wire value as a plain native u16 — no endianness macro — so the + * wire bytes are correct on both LE and BE hosts. The read-address + * (0x8000 | reg) is already the 16-bit value we want on the wire. + * scan_tx is reused for TX addresses (mutually exclusive with the + * non-offload triggered-buffer path). + */ + k = 0; + iio_for_each_active_channel(indio_dev, bit) { + st->scan_tx[k] = 0x8000 | AD4691_AVG_IN(bit); + + /* TX: address phase, CS stays asserted into data phase */ + st->scan_xfers[2 * k].tx_buf = &st->scan_tx[k]; + st->scan_xfers[2 * k].len = sizeof(*st->scan_tx); + st->scan_xfers[2 * k].bits_per_word = bpw; + + /* RX: data phase, CS toggles after to delimit the next register op */ + st->scan_xfers[2 * k + 1].len = sizeof(*st->scan_tx); + st->scan_xfers[2 * k + 1].bits_per_word = bpw; + st->scan_xfers[2 * k + 1].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + st->scan_xfers[2 * k + 1].cs_change = 1; + k++; + } + + /* + * State reset: single 4-byte write [addr_hi, addr_lo, STATE_RESET_ALL, + * OSC_EN=1]. ADDR_DESCENDING writes byte[3]=1 to OSC_EN_REG (0x180) as + * a deliberate side-write, keeping the oscillator enabled. + * scan_tx_reset is shared with the non-offload path (len=4 here vs + * len=3 there) since the two paths are mutually exclusive at probe. + */ + put_unaligned_be16(AD4691_STATE_RESET_REG, st->scan_tx_reset); + st->scan_tx_reset[2] = AD4691_STATE_RESET_ALL; + st->scan_tx_reset[3] = 1; + st->scan_xfers[2 * k].tx_buf = st->scan_tx_reset; + st->scan_xfers[2 * k].len = sizeof(st->scan_tx_reset); + /* + * 4-byte u8 buffer assembled with put_unaligned_be16(); leave + * bits_per_word at the default (8) so bytes go out in memory order. + */ + + spi_message_init_with_transfers(&st->scan_msg, st->scan_xfers, 2 * k + 1); + st->scan_msg.offload = st->offload; + + ret = spi_optimize_message(spi, &st->scan_msg); + if (ret) + goto err_exit_conversion; + + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, &config); + if (ret) + goto err_unoptimize; + + ret = ad4691_sampling_enable(st, true); + if (ret) + goto err_disable_trigger; + + return 0; + +err_disable_trigger: + spi_offload_trigger_disable(st->offload, st->offload_trigger); +err_unoptimize: + spi_unoptimize_message(&st->scan_msg); +err_exit_conversion: + ad4691_exit_conversion_mode(st); + return ret; +} + +static int ad4691_cnv_burst_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st = iio_priv(indio_dev); + + ad4691_sampling_enable(st, false); + spi_offload_trigger_disable(st->offload, st->offload_trigger); + spi_unoptimize_message(&st->scan_msg); + + return ad4691_exit_conversion_mode(st); +} + +static const struct iio_buffer_setup_ops ad4691_cnv_burst_offload_buffer_setup_ops = { + .postenable = ad4691_cnv_burst_offload_buffer_postenable, + .predisable = ad4691_cnv_burst_offload_buffer_predisable, +}; + +static ssize_t sampling_frequency_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad4691_state *st = iio_priv(indio_dev); + + if (st->manual_mode && st->offload) + return sysfs_emit(buf, "%llu\n", READ_ONCE(st->trigger_hz)); + + return sysfs_emit(buf, "%lu\n", NSEC_PER_SEC / st->cnv_period_ns); +} + +static ssize_t sampling_frequency_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad4691_state *st = iio_priv(indio_dev); + unsigned int freq; + int ret; + + ret = kstrtouint(buf, 10, &freq); + if (ret) + return ret; + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + if (st->manual_mode && st->offload) { + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_PERIODIC, + .periodic = { .frequency_hz = freq }, + }; + + ret = spi_offload_trigger_validate(st->offload_trigger, &config); + if (ret) + return ret; + + WRITE_ONCE(st->trigger_hz, config.periodic.frequency_hz); + return len; + } + + ret = ad4691_set_pwm_freq(st, freq); + if (ret) + return ret; + + return len; +} + +static IIO_DEVICE_ATTR_RW(sampling_frequency, 0); + +static const struct iio_dev_attr *ad4691_buffer_attrs[] = { + &iio_dev_attr_sampling_frequency, + NULL +}; + +static irqreturn_t ad4691_irq(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct ad4691_state *st = iio_priv(indio_dev); + + /* + * Disable the IRQ before calling iio_trigger_poll(). The IRQ is + * re-enabled via the trigger .reenable callback, which the IIO core + * calls inside iio_trigger_notify_done() once use_count reaches zero. + * Re-enabling here (before notify_done) would race: a DATA_READY + * between enable_irq() and notify_done() calls iio_trigger_poll() + * while use_count > 0, dropping the event and permanently masking + * the IRQ. + */ + disable_irq_nosync(st->irq); + iio_trigger_poll(indio_dev->trig); + + return IRQ_HANDLED; +} + +static void ad4691_trigger_reenable(struct iio_trigger *trig) +{ + struct ad4691_state *st = iio_trigger_get_drvdata(trig); + + enable_irq(st->irq); +} + +static const struct iio_trigger_ops ad4691_trigger_ops = { + .reenable = ad4691_trigger_reenable, + .validate_device = iio_trigger_validate_own_device, +}; + +static void ad4691_read_scan(struct iio_dev *indio_dev, s64 ts) +{ + struct ad4691_state *st = iio_priv(indio_dev); + int ret; + + guard(mutex)(&st->lock); + + ret = spi_sync(st->spi, &st->scan_msg); + if (ret) { + dev_err_ratelimited(regmap_get_device(st->regmap), + "SPI scan failed: %d\n", ret); + return; + } + + /* + * rx_buf pointers in scan_xfers point directly into scan.vals, so no + * copy is needed. The scan_msg already includes a STATE_RESET at the + * end (appended in preenable), so no explicit reset is needed here. + */ + iio_push_to_buffers_with_ts(indio_dev, st->vals, sizeof(st->vals), ts); +} + +static irqreturn_t ad4691_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + + ad4691_read_scan(indio_dev, pf->timestamp); + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +/* + * CNV burst mode: only allow our own trigger (driven by DATA_READY IRQ). + * Manual mode: external triggers (e.g. iio-trig-hrtimer) must be allowed + * because manual mode has no DATA_READY IRQ to fire the internal trigger. + * iio_trigger_ops.validate_device = iio_trigger_validate_own_device is + * correct in both modes — it prevents other devices from hijacking our + * internal trigger; the distinction here is only for iio_info.validate_trigger. + */ +static const struct iio_info ad4691_cnv_burst_info = { + .read_raw = ad4691_read_raw, + .write_raw = ad4691_write_raw, + .read_avail = ad4691_read_avail, + .debugfs_reg_access = ad4691_reg_access, + .validate_trigger = iio_validate_own_trigger, +}; + +static const struct iio_info ad4691_manual_info = { + .read_raw = ad4691_read_raw, + .write_raw = ad4691_write_raw, + .read_avail = ad4691_read_avail, + .debugfs_reg_access = ad4691_reg_access, +}; + +static int ad4691_pwm_setup(struct ad4691_state *st) +{ + struct device *dev = regmap_get_device(st->regmap); + + st->conv_trigger = devm_pwm_get(dev, "cnv"); + if (IS_ERR(st->conv_trigger)) + return dev_err_probe(dev, PTR_ERR(st->conv_trigger), + "Failed to get CNV PWM\n"); + + return ad4691_set_pwm_freq(st, st->info->max_rate); +} + +static int ad4691_regulator_setup(struct ad4691_state *st) +{ + struct device *dev = regmap_get_device(st->regmap); + int ret; + + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4691_supplies), + ad4691_supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to get and enable supplies\n"); + + /* + * vdd-supply and ldo-in-supply are mutually exclusive: + * vdd-supply present → external 1.8V VDD; disable internal LDO. + * vdd-supply absent → enable internal LDO fed from ldo-in-supply. + * Having both simultaneously is strongly inadvisable per the datasheet. + */ + if (device_property_present(dev, "vdd-supply")) { + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get and enable VDD\n"); + } else if (device_property_present(dev, "ldo-in-supply")) { + ret = devm_regulator_get_enable(dev, "ldo-in"); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get and enable LDO-IN\n"); + st->ldo_en = true; + } else { + return dev_err_probe(dev, -EINVAL, + "missing one of vdd-supply, ldo-in-supply\n"); + } + + if (device_property_present(dev, "ref-supply")) { + st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "ref"); + if (st->vref_uV < 0) + return dev_err_probe(dev, st->vref_uV, + "Failed to get REF supply voltage\n"); + } else if (device_property_present(dev, "refin-supply")) { + st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "refin"); + if (st->vref_uV < 0) + return dev_err_probe(dev, st->vref_uV, + "Failed to get REFIN supply voltage\n"); + st->refbuf_en = true; + } else { + return dev_err_probe(dev, -EINVAL, + "missing one of ref-supply, refin-supply\n"); + } + + if (st->vref_uV < AD4691_VREF_uV_MIN || st->vref_uV > AD4691_VREF_uV_MAX) + return dev_err_probe(dev, -EINVAL, + "vref(%d) must be in the range [%u...%u]\n", + st->vref_uV, AD4691_VREF_uV_MIN, + AD4691_VREF_uV_MAX); + + return 0; +} + +static int ad4691_reset(struct ad4691_state *st) +{ + struct device *dev = regmap_get_device(st->regmap); + struct reset_control *rst; + int ret; + + rst = devm_reset_control_get_optional_exclusive(dev, NULL); + if (IS_ERR(rst)) + return dev_err_probe(dev, PTR_ERR(rst), "Failed to get reset\n"); + + if (rst) { + /* + * Assert the reset line to guarantee a clean reset pulse on + * every probe, including driver reloads where the line may + * already be deasserted (reset_control_put() does not + * re-assert on release). tRESETL (minimum pulse width) = 10 ns + * (Table 5); kernel function-call overhead alone exceeds this, + * so no explicit delay is needed between assert and deassert. + */ + reset_control_assert(rst); + ret = reset_control_deassert(rst); + if (ret) + return ret; + } else { + /* No hardware reset available, fall back to software reset. */ + ret = regmap_write(st->regmap, AD4691_SPI_CONFIG_A_REG, + AD4691_SW_RESET); + if (ret) + return ret; + } + + /* + * Wait 300 µs (Table 5) for the device to complete its internal reset + * sequence before accepting SPI commands. + */ + fsleep(300); + return 0; +} + +static int ad4691_config(struct ad4691_state *st) +{ + struct device *dev = regmap_get_device(st->regmap); + enum ad4691_ref_ctrl ref_val; + unsigned int val; + int ret; + + /* + * Determine buffer conversion mode from DT: if a PWM is provided it + * drives the CNV pin (CNV_BURST_MODE); otherwise CNV is tied to CS + * and each SPI transfer triggers a conversion (MANUAL_MODE). + * Both modes idle in AUTONOMOUS mode so that read_raw can use the + * internal oscillator without disturbing the hardware configuration. + */ + if (device_property_present(dev, "pwms")) { + st->manual_mode = false; + ret = ad4691_pwm_setup(st); + if (ret) + return ret; + } else { + st->manual_mode = true; + } + + switch (st->vref_uV) { + case AD4691_VREF_uV_MIN ... AD4691_VREF_2P5_uV_MAX: + ref_val = AD4691_VREF_2P5; + break; + case AD4691_VREF_2P5_uV_MAX + 1 ... AD4691_VREF_3P0_uV_MAX: + ref_val = AD4691_VREF_3P0; + break; + case AD4691_VREF_3P0_uV_MAX + 1 ... AD4691_VREF_3P3_uV_MAX: + ref_val = AD4691_VREF_3P3; + break; + case AD4691_VREF_3P3_uV_MAX + 1 ... AD4691_VREF_4P096_uV_MAX: + ref_val = AD4691_VREF_4P096; + break; + case AD4691_VREF_4P096_uV_MAX + 1 ... AD4691_VREF_uV_MAX: + ref_val = AD4691_VREF_5P0; + break; + default: + return dev_err_probe(dev, -EINVAL, + "Unsupported vref voltage: %d uV\n", + st->vref_uV); + } + + val = FIELD_PREP(AD4691_REF_CTRL_MASK, ref_val); + if (st->refbuf_en) + val |= AD4691_REFBUF_EN; + + ret = regmap_write(st->regmap, AD4691_REF_CTRL, val); + if (ret) + return dev_err_probe(dev, ret, "Failed to write REF_CTRL\n"); + + ret = regmap_assign_bits(st->regmap, AD4691_DEVICE_SETUP, + AD4691_LDO_EN, st->ldo_en); + if (ret) + return dev_err_probe(dev, ret, "Failed to write DEVICE_SETUP\n"); + + /* + * Set the internal oscillator to the highest rate this chip supports. + * Index 0 (1 MHz) exceeds the 500 kHz max of AD4691/AD4693, so those + * chips start at index 1 (500 kHz). + */ + ret = regmap_write(st->regmap, AD4691_OSC_FREQ_REG, + ad4691_samp_freq_start(st->info)); + if (ret) + return dev_err_probe(dev, ret, "Failed to write OSC_FREQ\n"); + + st->target_osc_freq_Hz = ad4691_osc_freqs_Hz[ad4691_samp_freq_start(st->info)]; + + ret = regmap_update_bits(st->regmap, AD4691_ADC_SETUP, + AD4691_ADC_MODE_MASK, AD4691_AUTONOMOUS_MODE); + if (ret) + return dev_err_probe(dev, ret, "Failed to write ADC_SETUP\n"); + + ad4691_precompute_samp_freq_avail(st); + + return 0; +} + +static int ad4691_setup_triggered_buffer(struct iio_dev *indio_dev, + struct ad4691_state *st) +{ + struct device *dev = regmap_get_device(st->regmap); + struct iio_trigger *trig; + unsigned int i; + int irq, ret; + + /* + * Manual mode exposes channels without the oversampling_ratio attribute + * because ACC_DEPTH_IN is not configured in manual mode. + */ + if (st->manual_mode) + indio_dev->channels = st->info->sw_info->manual_channels; + else + indio_dev->channels = st->info->sw_info->channels; + indio_dev->num_channels = st->info->sw_info->num_channels; + indio_dev->info = st->manual_mode ? &ad4691_manual_info : &ad4691_cnv_burst_info; + + /* + * Manual mode relies on an external trigger (e.g. iio-trig-hrtimer); + * no internal trigger is needed or registered. + */ + if (st->manual_mode) + return devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ad4691_trigger_handler, + &ad4691_manual_buffer_setup_ops); + + /* + * CNV burst mode: allocate an internal trigger driven by the + * DATA_READY IRQ on the GP pin. + */ + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, + iio_device_id(indio_dev)); + if (!trig) + return -ENOMEM; + + trig->ops = &ad4691_trigger_ops; + iio_trigger_set_drvdata(trig, st); + + ret = devm_iio_trigger_register(dev, trig); + if (ret) + return dev_err_probe(dev, ret, "IIO trigger register failed\n"); + + indio_dev->trig = iio_trigger_get(trig); + + /* + * The GP pin named in interrupt-names asserts at end-of-conversion. + * The IRQ handler fires the IIO trigger so the trigger handler can + * read and push the sample to the buffer. The IRQ is kept disabled + * until the buffer is enabled. + */ + irq = -ENXIO; + for (i = 0; i < ARRAY_SIZE(ad4691_gp_names); i++) { + irq = fwnode_irq_get_byname(dev_fwnode(dev), + ad4691_gp_names[i]); + if (irq > 0 || irq == -EPROBE_DEFER) + break; + } + if (irq < 0) + return dev_err_probe(dev, irq, "failed to get GP interrupt\n"); + + st->irq = irq; + + ret = ad4691_gpio_setup(st, i); + if (ret) + return ret; + + /* + * The handler only calls disable_irq_nosync() and iio_trigger_poll(), + * both safe in hardirq context, so register as a hard IRQ handler. + * IRQF_NO_AUTOEN keeps it disabled until the buffer is enabled. + */ + ret = devm_request_irq(dev, irq, ad4691_irq, IRQF_NO_AUTOEN, + indio_dev->name, indio_dev); + if (ret) + return ret; + + return devm_iio_triggered_buffer_setup_ext(dev, indio_dev, + iio_pollfunc_store_time, + ad4691_trigger_handler, + IIO_BUFFER_DIRECTION_IN, + &ad4691_cnv_burst_buffer_setup_ops, + ad4691_buffer_attrs); +} + +static int ad4691_setup_offload(struct iio_dev *indio_dev, + struct ad4691_state *st, + struct spi_offload *spi_offload) +{ + struct device *dev = regmap_get_device(st->regmap); + struct dma_chan *rx_dma; + int ret; + + st->offload = spi_offload; + + /* + * CNV burst offload exposes oversampling_ratio (ACC_DEPTH_IN is + * configured per channel at buffer enable). Manual offload does not + * configure ACC_DEPTH_IN, so it uses a separate channel array + * without the oversampling_ratio attribute. Both paths use IIO_CPU + * (no .endianness annotation) because bits_per_word=16 causes the + * SPI Engine to produce native 16-bit DMA words. + */ + if (st->manual_mode) + indio_dev->channels = st->info->offload_info->manual_channels; + else + indio_dev->channels = st->info->offload_info->channels; + indio_dev->num_channels = st->info->offload_info->num_channels; + /* + * Offload path uses DMA directly; no IIO trigger is involved, so + * external triggers are not restricted (no validate_trigger). + */ + indio_dev->info = &ad4691_manual_info; + + if (st->manual_mode) { + st->offload_trigger = + devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_PERIODIC); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "Failed to get periodic offload trigger\n"); + + st->trigger_hz = AD4691_OFFLOAD_INITIAL_TRIGGER_HZ; + } else { + struct spi_offload_trigger_info trigger_info = { + .fwnode = dev_fwnode(dev), + .ops = &ad4691_offload_trigger_ops, + .priv = st, + }; + + ret = devm_spi_offload_trigger_register(dev, &trigger_info); + if (ret) + return dev_err_probe(dev, ret, + "Failed to register offload trigger\n"); + + st->offload_trigger = + devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_DATA_READY); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "Failed to get DATA_READY offload trigger\n"); + } + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "Failed to get offload RX DMA channel\n"); + + if (st->manual_mode) + indio_dev->setup_ops = &ad4691_manual_offload_buffer_setup_ops; + else + indio_dev->setup_ops = &ad4691_cnv_burst_offload_buffer_setup_ops; + + ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); + if (ret) + return ret; + + indio_dev->buffer->attrs = ad4691_buffer_attrs; + + return 0; +} + +static int ad4691_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct spi_offload *spi_offload; + struct iio_dev *indio_dev; + struct ad4691_state *st; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + st->info = spi_get_device_match_data(spi); + if (!st->info) + return -ENODEV; + st->osr = 1; + + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + + st->regmap = devm_regmap_init(dev, NULL, spi, &ad4691_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(dev, PTR_ERR(st->regmap), + "Failed to initialize regmap\n"); + + ret = ad4691_regulator_setup(st); + if (ret) + return ret; + + ret = ad4691_reset(st); + if (ret) + return ret; + + ret = ad4691_config(st); + if (ret) + return ret; + + spi_offload = devm_spi_offload_get(dev, spi, &ad4691_offload_config); + ret = PTR_ERR_OR_ZERO(spi_offload); + if (ret == -ENODEV) + spi_offload = NULL; + else if (ret) + return dev_err_probe(dev, ret, "Failed to get SPI offload\n"); + + indio_dev->name = st->info->name; + indio_dev->modes = INDIO_DIRECT_MODE; + + if (spi_offload) + ret = ad4691_setup_offload(indio_dev, st, spi_offload); + else + ret = ad4691_setup_triggered_buffer(indio_dev, st); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id ad4691_of_match[] = { + { .compatible = "adi,ad4691", .data = &ad4691_chip_info }, + { .compatible = "adi,ad4692", .data = &ad4692_chip_info }, + { .compatible = "adi,ad4693", .data = &ad4693_chip_info }, + { .compatible = "adi,ad4694", .data = &ad4694_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(of, ad4691_of_match); + +static const struct spi_device_id ad4691_id[] = { + { .name = "ad4691", .driver_data = (kernel_ulong_t)&ad4691_chip_info }, + { .name = "ad4692", .driver_data = (kernel_ulong_t)&ad4692_chip_info }, + { .name = "ad4693", .driver_data = (kernel_ulong_t)&ad4693_chip_info }, + { .name = "ad4694", .driver_data = (kernel_ulong_t)&ad4694_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad4691_id); + +static struct spi_driver ad4691_driver = { + .driver = { + .name = "ad4691", + .of_match_table = ad4691_of_match, + }, + .probe = ad4691_probe, + .id_table = ad4691_id, +}; +module_spi_driver(ad4691_driver); + +MODULE_AUTHOR("Radu Sabau "); +MODULE_DESCRIPTION("Analog Devices AD4691 Family ADC Driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DMA_BUFFER"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c index bd4877268689..7bf7d538abd9 100644 --- a/drivers/iio/adc/ad7091r5.c +++ b/drivers/iio/adc/ad7091r5.c @@ -101,23 +101,17 @@ static const struct ad7091r_init_info ad7091r5_init_info = { static int ad7091r5_i2c_probe(struct i2c_client *i2c) { - const struct ad7091r_init_info *init_info; - - init_info = i2c_get_match_data(i2c); - if (!init_info) - return -EINVAL; - - return ad7091r_probe(&i2c->dev, init_info, i2c->irq); + return ad7091r_probe(&i2c->dev, &ad7091r5_init_info, i2c->irq); } static const struct of_device_id ad7091r5_dt_ids[] = { - { .compatible = "adi,ad7091r5", .data = &ad7091r5_init_info }, + { .compatible = "adi,ad7091r5" }, { } }; MODULE_DEVICE_TABLE(of, ad7091r5_dt_ids); static const struct i2c_device_id ad7091r5_i2c_ids[] = { - { "ad7091r5", (kernel_ulong_t)&ad7091r5_init_info }, + { .name = "ad7091r5" }, { } }; MODULE_DEVICE_TABLE(i2c, ad7091r5_i2c_ids); diff --git a/drivers/iio/adc/ad7191.c b/drivers/iio/adc/ad7191.c index d9cd903ffdd2..51ec199fb06f 100644 --- a/drivers/iio/adc/ad7191.c +++ b/drivers/iio/adc/ad7191.c @@ -154,27 +154,18 @@ static int ad7191_config_setup(struct iio_dev *indio_dev) const u32 gain[4] = { 1, 8, 64, 128 }; static u32 scale_buffer[4][2]; int odr_value, odr_index = 0, pga_value, pga_index = 0, i, ret; + const char *propname; u64 scale_uv; st->samp_freq_index = 0; st->scale_index = 0; - ret = device_property_read_u32(dev, "adi,odr-value", &odr_value); - if (ret && ret != -EINVAL) - return dev_err_probe(dev, ret, "Failed to get odr value.\n"); + propname = "adi,odr-value"; + if (device_property_present(dev, propname)) { + ret = device_property_read_u32(dev, propname, &odr_value); + if (ret) + return dev_err_probe(dev, ret, "Failed to get %s.\n", propname); - if (ret == -EINVAL) { - st->odr_gpios = devm_gpiod_get_array(dev, "odr", GPIOD_OUT_LOW); - if (IS_ERR(st->odr_gpios)) - return dev_err_probe(dev, PTR_ERR(st->odr_gpios), - "Failed to get odr gpios.\n"); - - if (st->odr_gpios->ndescs != 2) - return dev_err_probe(dev, -EINVAL, "Expected 2 odr gpio pins.\n"); - - st->samp_freq_avail = samp_freq; - st->samp_freq_avail_size = ARRAY_SIZE(samp_freq); - } else { for (i = 0; i < ARRAY_SIZE(samp_freq); i++) { if (odr_value != samp_freq[i]) continue; @@ -186,6 +177,17 @@ static int ad7191_config_setup(struct iio_dev *indio_dev) st->samp_freq_avail_size = 1; st->odr_gpios = NULL; + } else { + st->odr_gpios = devm_gpiod_get_array(dev, "odr", GPIOD_OUT_LOW); + if (IS_ERR(st->odr_gpios)) + return dev_err_probe(dev, PTR_ERR(st->odr_gpios), + "Failed to get odr gpios.\n"); + + if (st->odr_gpios->ndescs != 2) + return dev_err_probe(dev, -EINVAL, "Expected 2 odr gpio pins.\n"); + + st->samp_freq_avail = samp_freq; + st->samp_freq_avail_size = ARRAY_SIZE(samp_freq); } mutex_lock(&st->lock); @@ -200,22 +202,12 @@ static int ad7191_config_setup(struct iio_dev *indio_dev) mutex_unlock(&st->lock); - ret = device_property_read_u32(dev, "adi,pga-value", &pga_value); - if (ret && ret != -EINVAL) - return dev_err_probe(dev, ret, "Failed to get pga value.\n"); + propname = "adi,pga-value"; + if (device_property_present(dev, propname)) { + ret = device_property_read_u32(dev, propname, &pga_value); + if (ret) + return dev_err_probe(dev, ret, "Failed to get %s.\n", propname); - if (ret == -EINVAL) { - st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW); - if (IS_ERR(st->pga_gpios)) - return dev_err_probe(dev, PTR_ERR(st->pga_gpios), - "Failed to get pga gpios.\n"); - - if (st->pga_gpios->ndescs != 2) - return dev_err_probe(dev, -EINVAL, "Expected 2 pga gpio pins.\n"); - - st->scale_avail = scale_buffer; - st->scale_avail_size = ARRAY_SIZE(scale_buffer); - } else { for (i = 0; i < ARRAY_SIZE(gain); i++) { if (pga_value != gain[i]) continue; @@ -227,6 +219,17 @@ static int ad7191_config_setup(struct iio_dev *indio_dev) st->scale_avail_size = 1; st->pga_gpios = NULL; + } else { + st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW); + if (IS_ERR(st->pga_gpios)) + return dev_err_probe(dev, PTR_ERR(st->pga_gpios), + "Failed to get pga gpios.\n"); + + if (st->pga_gpios->ndescs != 2) + return dev_err_probe(dev, -EINVAL, "Expected 2 pga gpio pins.\n"); + + st->scale_avail = scale_buffer; + st->scale_avail_size = ARRAY_SIZE(scale_buffer); } st->temp_gpio = devm_gpiod_get(dev, "temp", GPIOD_OUT_LOW); diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 8b1664f6b102..caf4473ad643 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -39,7 +39,7 @@ #define AD7192_REG_CONF 2 /* Configuration Register (RW, 24-bit) */ #define AD7192_REG_DATA 3 /* Data Register (RO, 24/32-bit) */ #define AD7192_REG_ID 4 /* ID Register (RO, 8-bit) */ -#define AD7192_REG_GPOCON 5 /* GPOCON Register (RO, 8-bit) */ +#define AD7192_REG_GPOCON 5 /* GPOCON Register (RW, 8-bit) */ #define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit */ /* (AD7792)/24-bit (AD7192)) */ #define AD7192_REG_FULLSALE 7 /* Full-Scale Register */ @@ -576,7 +576,12 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev) ret = ad_sd_reset(&st->sd); if (ret < 0) return ret; - usleep_range(500, 1000); /* Wait for at least 500us */ + + /* + * Per AD7192 datasheet (Rev. A, page 34, RESET section), allow + * 500 us after a reset before accessing on-chip registers. + */ + fsleep(500); /* write/read test for device presence */ ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id); diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c index ba12a3796e2b..01c2f55a680c 100644 --- a/drivers/iio/adc/ad7280a.c +++ b/drivers/iio/adc/ad7280a.c @@ -496,7 +496,8 @@ static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev, devaddr = chan->address >> 8; ch = chan->address & 0xFF; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + if (readin) st->cb_mask[devaddr] |= BIT(ch); else @@ -505,7 +506,6 @@ static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev, ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE_REG, 0, FIELD_PREP(AD7280A_CELL_BALANCE_CHAN_BITMAP_MSK, st->cb_mask[devaddr])); - mutex_unlock(&st->lock); return ret ? ret : len; } @@ -516,14 +516,13 @@ static ssize_t ad7280_show_balance_timer(struct iio_dev *indio_dev, char *buf) { struct ad7280_state *st = iio_priv(indio_dev); + u8 devaddr = chan->address >> 8; + u8 ch = chan->address & 0xFF; unsigned int msecs; int ret; - mutex_lock(&st->lock); - ret = ad7280_read_reg(st, chan->address >> 8, - (chan->address & 0xFF) + AD7280A_CB1_TIMER_REG); - mutex_unlock(&st->lock); - + scoped_guard(mutex, &st->lock) + ret = ad7280_read_reg(st, devaddr, ch + AD7280A_CB1_TIMER_REG); if (ret < 0) return ret; @@ -538,6 +537,8 @@ static ssize_t ad7280_store_balance_timer(struct iio_dev *indio_dev, const char *buf, size_t len) { struct ad7280_state *st = iio_priv(indio_dev); + u8 devaddr = chan->address >> 8; + u8 ch = chan->address & 0xFF; int val, val2; int ret; @@ -551,11 +552,10 @@ static ssize_t ad7280_store_balance_timer(struct iio_dev *indio_dev, if (val > 31) return -EINVAL; - mutex_lock(&st->lock); - ret = ad7280_write(st, chan->address >> 8, - (chan->address & 0xFF) + AD7280A_CB1_TIMER_REG, 0, + guard(mutex)(&st->lock); + + ret = ad7280_write(st, devaddr, ch + AD7280A_CB1_TIMER_REG, 0, FIELD_PREP(AD7280A_CB_TIMER_VAL_MSK, val)); - mutex_unlock(&st->lock); return ret ? ret : len; } @@ -737,7 +737,8 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev, if (val2 != 0) return -EINVAL; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + switch (chan->type) { case IIO_VOLTAGE: value = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ @@ -748,22 +749,20 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev, ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 1, value); if (ret) - break; + return ret; st->cell_threshhigh = value; - break; + return 0; case IIO_EV_DIR_FALLING: addr = AD7280A_CELL_UNDERVOLTAGE_REG; ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 1, value); if (ret) - break; + return ret; st->cell_threshlow = value; - break; + return 0; default: - ret = -EINVAL; - goto err_unlock; + return -EINVAL; } - break; case IIO_TEMP: value = (val * 10) / 196; /* LSB 19.6mV */ value = clamp(value, 0L, 0xFFL); @@ -773,31 +772,23 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev, ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 1, value); if (ret) - break; + return ret; st->aux_threshhigh = value; - break; + return 0; case IIO_EV_DIR_FALLING: addr = AD7280A_AUX_ADC_UNDERVOLTAGE_REG; ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 1, value); if (ret) - break; + return ret; st->aux_threshlow = value; - break; + return 0; default: - ret = -EINVAL; - goto err_unlock; + return -EINVAL; } - break; default: - ret = -EINVAL; - goto err_unlock; + return -EINVAL; } - -err_unlock: - mutex_unlock(&st->lock); - - return ret; } static irqreturn_t ad7280_event_handler(int irq, void *private) @@ -881,17 +872,18 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, long m) { struct ad7280_state *st = iio_priv(indio_dev); + u8 devaddr = chan->address >> 8; + u8 ch = chan->address & 0xFF; int ret; switch (m) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&st->lock); + case IIO_CHAN_INFO_RAW: { + guard(mutex)(&st->lock); + if (chan->address == AD7280A_ALL_CELLS) ret = ad7280_read_all_channels(st, st->scan_cnt, NULL); else - ret = ad7280_read_channel(st, chan->address >> 8, - chan->address & 0xFF); - mutex_unlock(&st->lock); + ret = ad7280_read_channel(st, devaddr, ch); if (ret < 0) return ret; @@ -899,8 +891,9 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; + } case IIO_CHAN_INFO_SCALE: - if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6_REG) + if (ch <= AD7280A_CELL_VOLTAGE_6_REG) *val = 4000; else *val = 5000; @@ -990,8 +983,8 @@ static int ad7280_probe(struct spi_device *spi) st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_1600ns; break; default: - dev_err(dev, "Firmware provided acquisition time is invalid\n"); - return -EINVAL; + return dev_err_probe(dev, -EINVAL, + "Firmware provided acquisition time is invalid\n"); } } else { st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_400ns; diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c index 60e12faa3207..6a1493e27a30 100644 --- a/drivers/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -536,7 +536,7 @@ static int ad7291_probe(struct i2c_client *client) } static const struct i2c_device_id ad7291_id[] = { - { "ad7291" }, + { .name = "ad7291" }, { } }; diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c index a398973f313d..e5ad83d2240a 100644 --- a/drivers/iio/adc/ad7292.c +++ b/drivers/iio/adc/ad7292.c @@ -253,12 +253,13 @@ static const struct iio_info ad7292_info = { static int ad7292_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct ad7292_state *st; struct iio_dev *indio_dev; bool diff_channels = false; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -266,12 +267,11 @@ static int ad7292_probe(struct spi_device *spi) st->spi = spi; ret = ad7292_spi_reg_read(st, AD7292_REG_VENDOR_ID); - if (ret != ADI_VENDOR_ID) { - dev_err(&spi->dev, "Wrong vendor id 0x%x\n", ret); - return -EINVAL; - } + if (ret != ADI_VENDOR_ID) + return dev_err_probe(dev, -EINVAL, + "Wrong vendor id 0x%x\n", ret); - ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); + ret = devm_regulator_get_enable_read_voltage(dev, "vref"); if (ret < 0 && ret != -ENODEV) return ret; @@ -281,7 +281,7 @@ static int ad7292_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7292_info; - device_for_each_child_node_scoped(&spi->dev, child) { + device_for_each_child_node_scoped(dev, child) { diff_channels = fwnode_property_read_bool(child, "diff-channels"); if (diff_channels) @@ -296,7 +296,7 @@ static int ad7292_probe(struct spi_device *spi) indio_dev->channels = ad7292_channels; } - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad7292_id_table[] = { diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index d9271894f091..cebb8ed8dcb1 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -1475,7 +1475,7 @@ static int ad7606_probe_channels(struct iio_dev *indio_dev) } if (slow_bus) - channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i); + channels[i] = IIO_CHAN_SOFT_TIMESTAMP(i); indio_dev->channels = channels; diff --git a/drivers/iio/adc/ad7625.c b/drivers/iio/adc/ad7625.c index 0466c0c7eae4..f1ee29f35fa8 100644 --- a/drivers/iio/adc/ad7625.c +++ b/drivers/iio/adc/ad7625.c @@ -175,12 +175,12 @@ enum ad7960_mode { static int ad7625_set_sampling_freq(struct ad7625_state *st, u32 freq) { - u32 target; struct pwm_waveform clk_gate_wf = { }, cnv_wf = { }; + unsigned long target; int ret; target = DIV_ROUND_UP(NSEC_PER_SEC, freq); - cnv_wf.period_length_ns = clamp(target, 100, 10 * KILO); + cnv_wf.period_length_ns = clamp(target, 100UL, 10UL * NSEC_PER_USEC); /* * Use the maximum conversion time t_CNVH from the datasheet as diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 73fb734d06b2..598936e47fd2 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -1871,10 +1871,8 @@ static int ad7768_probe(struct spi_device *spi) return ret; ret = ad7768_setup(indio_dev); - if (ret < 0) { - dev_err(&spi->dev, "AD7768 setup failed\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "AD7768 setup failed\n"); init_completion(&st->completion); ret = devm_mutex_init(&spi->dev, &st->pga_lock); diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index 24d2dcad8f4d..26382b1f8c9e 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -264,16 +264,12 @@ static const struct iio_info ad7780_info = { static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st) { - int ret; - st->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW); - if (IS_ERR(st->powerdown_gpio)) { - ret = PTR_ERR(st->powerdown_gpio); - dev_err(dev, "Failed to request powerdown GPIO: %d\n", ret); - return ret; - } + if (IS_ERR(st->powerdown_gpio)) + return dev_err_probe(dev, PTR_ERR(st->powerdown_gpio), + "Failed to request powerdown GPIO\n"); if (!st->chip_info->is_ad778x) return 0; @@ -282,20 +278,16 @@ static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st) st->gain_gpio = devm_gpiod_get_optional(dev, "adi,gain", GPIOD_OUT_HIGH); - if (IS_ERR(st->gain_gpio)) { - ret = PTR_ERR(st->gain_gpio); - dev_err(dev, "Failed to request gain GPIO: %d\n", ret); - return ret; - } + if (IS_ERR(st->gain_gpio)) + return dev_err_probe(dev, PTR_ERR(st->gain_gpio), + "Failed to request gain GPIO\n"); st->filter_gpio = devm_gpiod_get_optional(dev, "adi,filter", GPIOD_OUT_HIGH); - if (IS_ERR(st->filter_gpio)) { - ret = PTR_ERR(st->filter_gpio); - dev_err(dev, "Failed to request filter GPIO: %d\n", ret); - return ret; - } + if (IS_ERR(st->filter_gpio)) + return dev_err_probe(dev, PTR_ERR(st->filter_gpio), + "Failed to request filter GPIO\n"); return 0; } @@ -307,11 +299,12 @@ static void ad7780_reg_disable(void *reg) static int ad7780_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct ad7780_state *st; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -329,29 +322,28 @@ static int ad7780_probe(struct spi_device *spi) indio_dev->num_channels = 1; indio_dev->info = &ad7780_info; - ret = ad7780_init_gpios(&spi->dev, st); + ret = ad7780_init_gpios(dev, st); if (ret) return ret; - st->reg = devm_regulator_get(&spi->dev, "avdd"); + st->reg = devm_regulator_get(dev, "avdd"); if (IS_ERR(st->reg)) return PTR_ERR(st->reg); ret = regulator_enable(st->reg); - if (ret) { - dev_err(&spi->dev, "Failed to enable specified AVdd supply\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable specified AVdd supply\n"); - ret = devm_add_action_or_reset(&spi->dev, ad7780_reg_disable, st->reg); + ret = devm_add_action_or_reset(dev, ad7780_reg_disable, st->reg); if (ret) return ret; - ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev); if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad7780_id[] = { diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 041fc25e3209..bcdc19e799aa 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -407,23 +407,22 @@ static void ad7791_reg_disable(void *reg) static int ad7791_probe(struct spi_device *spi) { - const struct ad7791_platform_data *pdata = dev_get_platdata(&spi->dev); + struct device *dev = &spi->dev; + const struct ad7791_platform_data *pdata = dev_get_platdata(dev); struct iio_dev *indio_dev; struct ad7791_state *st; int ret; - if (!spi->irq) { - dev_err(&spi->dev, "Missing IRQ.\n"); - return -ENXIO; - } + if (!spi->irq) + return dev_err_probe(dev, -ENXIO, "Missing IRQ.\n"); - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - st->reg = devm_regulator_get(&spi->dev, "refin"); + st->reg = devm_regulator_get(dev, "refin"); if (IS_ERR(st->reg)) return PTR_ERR(st->reg); @@ -431,7 +430,7 @@ static int ad7791_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, ad7791_reg_disable, st->reg); + ret = devm_add_action_or_reset(dev, ad7791_reg_disable, st->reg); if (ret) return ret; @@ -447,7 +446,7 @@ static int ad7791_probe(struct spi_device *spi) else indio_dev->info = &ad7791_no_filter_info; - ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev); if (ret) return ret; @@ -455,7 +454,7 @@ static int ad7791_probe(struct spi_device *spi) if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad7791_spi_ids[] = { diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 8ff7b70d6632..ea1c192e2142 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -268,7 +268,12 @@ static int ad7793_setup(struct iio_dev *indio_dev, ret = ad_sd_reset(&st->sd); if (ret < 0) goto out; - usleep_range(500, 2000); /* Wait for at least 500us */ + + /* + * Per AD7792/AD7793 datasheet (Rev. B, page 25, RESET section), + * allow 500 us after a reset before accessing on-chip registers. + */ + fsleep(500); /* write/read test for device presence */ ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id); @@ -278,8 +283,8 @@ static int ad7793_setup(struct iio_dev *indio_dev, id &= AD7793_ID_MASK; if (id != st->chip_info->id) { - ret = -ENODEV; - dev_err(&st->sd.spi->dev, "device ID query failed\n"); + ret = dev_err_probe(&st->sd.spi->dev, -ENODEV, + "device ID query failed\n"); goto out; } @@ -338,8 +343,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, return 0; out: - dev_err(&st->sd.spi->dev, "setup failed\n"); - return ret; + return dev_err_probe(&st->sd.spi->dev, ret, "setup failed\n"); } static const u16 ad7793_sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, @@ -774,22 +778,19 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { static int ad7793_probe(struct spi_device *spi) { - const struct ad7793_platform_data *pdata = dev_get_platdata(&spi->dev); + struct device *dev = &spi->dev; + const struct ad7793_platform_data *pdata = dev_get_platdata(dev); struct ad7793_state *st; struct iio_dev *indio_dev; int ret, vref_mv = 0; - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -ENODEV; - } + if (!pdata) + return dev_err_probe(dev, -ENODEV, "no platform data?\n"); - if (!spi->irq) { - dev_err(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } + if (!spi->irq) + return dev_err_probe(dev, -ENODEV, "no IRQ?\n"); - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -798,7 +799,7 @@ static int ad7793_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info); if (pdata->refsel != AD7793_REFSEL_INTERNAL) { - ret = devm_regulator_get_enable_read_voltage(&spi->dev, "refin"); + ret = devm_regulator_get_enable_read_voltage(dev, "refin"); if (ret < 0) return ret; @@ -816,7 +817,7 @@ static int ad7793_probe(struct spi_device *spi) indio_dev->num_channels = st->chip_info->num_channels; indio_dev->info = st->chip_info->iio_info; - ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev); if (ret) return ret; @@ -824,7 +825,7 @@ static int ad7793_probe(struct spi_device *spi) if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad7793_id[] = { diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index b35d299a3977..ebc629bcfd4d 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -341,8 +341,8 @@ static int ad7949_spi_probe(struct spi_device *spi) } else if (spi_is_bpw_supported(spi, 8)) { spi->bits_per_word = 8; } else { - dev_err(dev, "unable to find common BPW with spi controller\n"); - return -EINVAL; + return dev_err_probe(dev, -EINVAL, + "unable to find common BPW with spi controller\n"); } /* Setup internal voltage reference */ @@ -357,8 +357,8 @@ static int ad7949_spi_probe(struct spi_device *spi) ad7949_adc->refsel = AD7949_CFG_VAL_REF_INT_4096; break; default: - dev_err(dev, "unsupported internal voltage reference\n"); - return -EINVAL; + return dev_err_probe(dev, -EINVAL, + "unsupported internal voltage reference\n"); } /* Setup external voltage reference, buffered? */ @@ -382,10 +382,9 @@ static int ad7949_spi_probe(struct spi_device *spi) if (ad7949_adc->refsel & AD7949_CFG_VAL_REF_EXTERNAL) { ret = regulator_enable(ad7949_adc->vref); - if (ret < 0) { - dev_err(dev, "fail to enable regulator\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, + "fail to enable regulator\n"); ret = devm_add_action_or_reset(dev, ad7949_disable_reg, ad7949_adc->vref); @@ -396,16 +395,10 @@ static int ad7949_spi_probe(struct spi_device *spi) mutex_init(&ad7949_adc->lock); ret = ad7949_spi_init(ad7949_adc); - if (ret) { - dev_err(dev, "fail to init this device: %d\n", ret); - return ret; - } - - ret = devm_iio_device_register(dev, indio_dev); if (ret) - dev_err(dev, "fail to register iio device: %d\n", ret); + return dev_err_probe(dev, ret, "fail to init this device\n"); - return ret; + return devm_iio_device_register(dev, indio_dev); } static const struct of_device_id ad7949_spi_of_id[] = { diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 108bb22162ef..bb076d8f5dd5 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -18,27 +18,29 @@ * ad7998 and similar chips. */ -#include +#include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include #include #include -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include #include #include #define AD799X_CHANNEL_SHIFT 4 +#define AD799X_MAX_CHANNELS 8 /* * AD7991, AD7995 and AD7999 defines @@ -133,8 +135,11 @@ struct ad799x_state { unsigned int id; u16 config; - u8 *rx_buf; unsigned int transfer_size; + + int vref_uV; + + IIO_DECLARE_BUFFER_WITH_TS(__be16, rx_buf, AD799X_MAX_CHANNELS); }; static int ad799x_write_config(struct ad799x_state *st, u16 val) @@ -217,7 +222,8 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) } b_sent = i2c_smbus_read_i2c_block_data(st->client, - cmd, st->transfer_size, st->rx_buf); + cmd, st->transfer_size, + (u8 *)st->rx_buf); if (b_sent < 0) goto out; @@ -234,11 +240,6 @@ static int ad799x_update_scan_mode(struct iio_dev *indio_dev, { struct ad799x_state *st = iio_priv(indio_dev); - kfree(st->rx_buf); - st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (!st->rx_buf) - return -ENOMEM; - st->transfer_size = bitmap_weight(scan_mask, iio_get_masklength(indio_dev)) * 2; @@ -306,14 +307,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - if (st->vref) - ret = regulator_get_voltage(st->vref); - else - ret = regulator_get_voltage(st->reg); - - if (ret < 0) - return ret; - *val = ret / 1000; + *val = st->vref_uV / (MICRO / MILLI); *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; } @@ -781,8 +775,14 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = { }, }; +static void ad799x_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int ad799x_probe(struct i2c_client *client) { + struct device *dev = &client->dev; const struct i2c_device_id *id = i2c_client_get_device_id(client); int ret; int extra_config = 0; @@ -791,7 +791,7 @@ static int ad799x_probe(struct i2c_client *client) const struct ad799x_chip_info *chip_info = &ad799x_chip_info_tbl[id->driver_data]; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -799,6 +799,10 @@ static int ad799x_probe(struct i2c_client *client) /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + st->id = id->driver_data; if (client->irq > 0 && chip_info->irq_config.info) st->chip_config = &chip_info->irq_config; @@ -807,33 +811,53 @@ static int ad799x_probe(struct i2c_client *client) /* TODO: Add pdata options for filtering and bit delay */ - st->reg = devm_regulator_get(&client->dev, "vcc"); + st->reg = devm_regulator_get(dev, "vcc"); if (IS_ERR(st->reg)) return PTR_ERR(st->reg); ret = regulator_enable(st->reg); if (ret) return ret; + ret = devm_add_action_or_reset(dev, ad799x_reg_disable, st->reg); + if (ret) + return ret; + /* check if an external reference is supplied */ if (chip_info->has_vref) { - st->vref = devm_regulator_get_optional(&client->dev, "vref"); + st->vref = devm_regulator_get_optional(dev, "vref"); ret = PTR_ERR_OR_ZERO(st->vref); - if (ret) { - if (ret != -ENODEV) - goto error_disable_reg; + if (ret == -ENODEV) { st->vref = NULL; - dev_info(&client->dev, "Using VCC reference voltage\n"); + dev_info(dev, "Using VCC reference voltage\n"); + } else if (ret) { + return ret; } if (st->vref) { - dev_info(&client->dev, "Using external reference voltage\n"); + dev_info(dev, "Using external reference voltage\n"); extra_config |= AD7991_REF_SEL; ret = regulator_enable(st->vref); if (ret) - goto error_disable_reg; + return ret; + + ret = devm_add_action_or_reset(dev, ad799x_reg_disable, st->vref); + if (ret) + return ret; + + ret = regulator_get_voltage(st->vref); + if (ret < 0) + return ret; + st->vref_uV = ret; } } + if (!st->vref) { + ret = regulator_get_voltage(st->reg); + if (ret < 0) + return ret; + st->vref_uV = ret; + } + st->client = client; indio_dev->name = id->name; @@ -845,15 +869,15 @@ static int ad799x_probe(struct i2c_client *client) ret = ad799x_update_config(st, st->chip_config->default_config | extra_config); if (ret) - goto error_disable_vref; + return ret; - ret = iio_triggered_buffer_setup(indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, &ad799x_trigger_handler, NULL); if (ret) - goto error_disable_vref; + return ret; if (client->irq > 0) { - ret = devm_request_threaded_irq(&client->dev, + ret = devm_request_threaded_irq(dev, client->irq, NULL, ad799x_event_handler, @@ -862,40 +886,10 @@ static int ad799x_probe(struct i2c_client *client) client->name, indio_dev); if (ret) - goto error_cleanup_ring; + return ret; } - mutex_init(&st->lock); - - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_ring; - - return 0; - -error_cleanup_ring: - iio_triggered_buffer_cleanup(indio_dev); -error_disable_vref: - if (st->vref) - regulator_disable(st->vref); -error_disable_reg: - regulator_disable(st->reg); - - return ret; -} - -static void ad799x_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ad799x_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - iio_triggered_buffer_cleanup(indio_dev); - if (st->vref) - regulator_disable(st->vref); - regulator_disable(st->reg); - kfree(st->rx_buf); + return devm_iio_device_register(dev, indio_dev); } static int ad799x_suspend(struct device *dev) @@ -946,14 +940,14 @@ static int ad799x_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(ad799x_pm_ops, ad799x_suspend, ad799x_resume); static const struct i2c_device_id ad799x_id[] = { - { "ad7991", ad7991 }, - { "ad7995", ad7995 }, - { "ad7999", ad7999 }, - { "ad7992", ad7992 }, - { "ad7993", ad7993 }, - { "ad7994", ad7994 }, - { "ad7997", ad7997 }, - { "ad7998", ad7998 }, + { .name = "ad7991", .driver_data = ad7991 }, + { .name = "ad7995", .driver_data = ad7995 }, + { .name = "ad7999", .driver_data = ad7999 }, + { .name = "ad7992", .driver_data = ad7992 }, + { .name = "ad7993", .driver_data = ad7993 }, + { .name = "ad7994", .driver_data = ad7994 }, + { .name = "ad7997", .driver_data = ad7997 }, + { .name = "ad7998", .driver_data = ad7998 }, { } }; @@ -965,7 +959,6 @@ static struct i2c_driver ad799x_driver = { .pm = pm_sleep_ptr(&ad799x_pm_ops), }, .probe = ad799x_probe, - .remove = ad799x_remove, .id_table = ad799x_id, }; module_i2c_driver(ad799x_driver); diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 0bf67437508f..0c377f9a7f25 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -1349,11 +1349,10 @@ static int ad9467_probe(struct spi_device *spi) return ret; id = ad9467_spi_read(st, AN877_ADC_REG_CHIP_ID); - if (id != st->info->id) { - dev_err(dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", - id, st->info->id); - return -ENODEV; - } + if (id != st->info->id) + return dev_err_probe(dev, -ENODEV, + "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", + id, st->info->id); if (st->info->num_scales > 1) indio_dev->info = &ad9467_info; diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index a955556f9ec8..1b410291da53 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -262,11 +262,25 @@ static int ad_sigma_delta_clear_pending_event(struct ad_sigma_delta *sigma_delta /* * Read R̅D̅Y̅ pin (if possible) or status register to check if there is an - * old event. + * old event. For devices with neither an RDY GPIO nor registers, + * ad_sd_read_reg() transmits no address byte and clocks raw MISO bytes, + * which is indistinguishable from reading conversion data and would + * partially consume a pending result. Skip the check for such devices. + * + * This is safe for all current registerless devices: ad7191 and ad7780 + * (with powerdown GPIO) are reset between conversions by CS deassertion, + * so there is no stale result to drain; ad7780 (without powerdown GPIO) + * and max11205 are continuously-converting and cycle ~DRDY at the output + * data rate regardless of whether the previous result was read, so the + * next falling edge fires naturally. + * + * A future registerless device that holds ~DRDY asserted until data is + * read would be broken by this early return and would need either + * num_resetclks set or a rdy-gpio. */ if (sigma_delta->rdy_gpiod) { pending_event = gpiod_get_value(sigma_delta->rdy_gpiod); - } else { + } else if (sigma_delta->info->has_registers) { unsigned int status_reg; ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_STATUS, 1, &status_reg); @@ -274,11 +288,24 @@ static int ad_sigma_delta_clear_pending_event(struct ad_sigma_delta *sigma_delta return ret; pending_event = !(status_reg & AD_SD_REG_STATUS_RDY); + } else { + return 0; } if (!pending_event) return 0; + /* + * With num_resetclks = 0, data_read_len is 0 and the drain sequence + * below would compute memset(data + 2, 0xff, 0 - 1), underflowing to + * SIZE_MAX and corrupting the heap. There is no safe way to drain the + * stale result without knowing the data register size; it will be + * consumed by the first ad_sd_read_reg() call in + * ad_sigma_delta_single_conversion(). + */ + if (!data_read_len) + return 0; + /* * In general the size of the data register is unknown. It varies from * device to device, might be one byte longer if CONTROL.DATA_STATUS is @@ -441,11 +468,10 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, out: ad_sd_disable_irq(sigma_delta); - ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); - ad_sigma_delta_disable_one(sigma_delta, chan->address); - out_unlock: sigma_delta->keep_cs_asserted = false; + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); + ad_sigma_delta_disable_one(sigma_delta, chan->address); sigma_delta->bus_locked = false; spi_bus_unlock(sigma_delta->spi->controller); out_release: @@ -578,6 +604,9 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) return 0; err_unlock: + sigma_delta->keep_cs_asserted = false; + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); + sigma_delta->bus_locked = false; spi_bus_unlock(sigma_delta->spi->controller); spi_unoptimize_message(&sigma_delta->sample_msg); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 6e1930f7c65d..f610ad729bf3 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -481,7 +481,7 @@ static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private) static int at91_adc_channel_init(struct iio_dev *idev) { struct at91_adc_state *st = iio_priv(idev); - struct iio_chan_spec *chan_array, *timestamp; + struct iio_chan_spec *chan_array; int bit, idx = 0; unsigned long rsvd_mask = 0; @@ -519,14 +519,8 @@ static int at91_adc_channel_init(struct iio_dev *idev) chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); idx++; } - timestamp = chan_array + idx; - timestamp->type = IIO_TIMESTAMP; - timestamp->channel = -1; - timestamp->scan_index = idx; - timestamp->scan_type.sign = 's'; - timestamp->scan_type.realbits = 64; - timestamp->scan_type.storagebits = 64; + chan_array[idx] = IIO_CHAN_SOFT_TIMESTAMP(idx); idev->channels = chan_array; return idev->num_channels; diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c index 2c51b90b7101..d42b747325aa 100644 --- a/drivers/iio/adc/cc10001_adc.c +++ b/drivers/iio/adc/cc10001_adc.c @@ -262,7 +262,7 @@ static const struct iio_info cc10001_adc_info = { static int cc10001_adc_channel_init(struct iio_dev *indio_dev, unsigned long channel_map) { - struct iio_chan_spec *chan_array, *timestamp; + struct iio_chan_spec *chan_array; unsigned int bit, idx = 0; indio_dev->num_channels = bitmap_weight(&channel_map, @@ -289,13 +289,7 @@ static int cc10001_adc_channel_init(struct iio_dev *indio_dev, idx++; } - timestamp = &chan_array[idx]; - timestamp->type = IIO_TIMESTAMP; - timestamp->channel = -1; - timestamp->scan_index = idx; - timestamp->scan_type.sign = 's'; - timestamp->scan_type.realbits = 64; - timestamp->scan_type.storagebits = 64; + chan_array[idx] = IIO_CHAN_SOFT_TIMESTAMP(idx); indio_dev->channels = chan_array; diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c index eb902a946efe..b01c6f5a73b1 100644 --- a/drivers/iio/adc/dln2-adc.c +++ b/drivers/iio/adc/dln2-adc.c @@ -444,16 +444,6 @@ static int dln2_update_scan_mode(struct iio_dev *indio_dev, lval.scan_type.endianness = IIO_LE; \ } -/* Assignment version of IIO_CHAN_SOFT_TIMESTAMP */ -#define IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(lval, _si) { \ - lval.type = IIO_TIMESTAMP; \ - lval.channel = -1; \ - lval.scan_index = _si; \ - lval.scan_type.sign = 's'; \ - lval.scan_type.realbits = 64; \ - lval.scan_type.storagebits = 64; \ -} - static const struct iio_info dln2_adc_info = { .read_raw = dln2_adc_read_raw, .write_raw = dln2_adc_write_raw, @@ -614,7 +604,7 @@ static int dln2_adc_probe(struct platform_device *pdev) for (i = 0; i < chans; ++i) DLN2_ADC_CHAN(dln2->iio_channels[i], i) - IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i); + dln2->iio_channels[i] = IIO_CHAN_SOFT_TIMESTAMP(i); indio_dev->name = DLN2_ADC_MOD_NAME; indio_dev->info = &dln2_adc_info; diff --git a/drivers/iio/adc/gehc-pmc-adc.c b/drivers/iio/adc/gehc-pmc-adc.c index d1167818b17d..24193e941494 100644 --- a/drivers/iio/adc/gehc-pmc-adc.c +++ b/drivers/iio/adc/gehc-pmc-adc.c @@ -207,7 +207,7 @@ static const struct of_device_id pmc_adc_of_match[] = { MODULE_DEVICE_TABLE(of, pmc_adc_of_match); static const struct i2c_device_id pmc_adc_id_table[] = { - { "pmc-adc" }, + { .name = "pmc-adc" }, { } }; MODULE_DEVICE_TABLE(i2c, pmc_adc_id_table); diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 1db8b68a8f64..86d2a70dd3de 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -28,22 +28,20 @@ struct hx711_gain_to_scale { int gain; int gain_pulse; - int scale; int channel; }; /* * .scale depends on AVDD which in turn is known as soon as the regulator - * is available - * therefore we set .scale in hx711_probe() + * is available; it is stored per device in hx711_data.gain_scale[] * * channel A in documentation is channel 0 in source code * channel B in documentation is channel 1 in source code */ -static struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = { - { 128, 1, 0, 0 }, - { 32, 2, 0, 1 }, - { 64, 3, 0, 0 } +static const struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = { + { 128, 1, 0 }, + { 32, 2, 1 }, + { 64, 3, 0 }, }; static int hx711_get_gain_to_pulse(int gain) @@ -56,22 +54,22 @@ static int hx711_get_gain_to_pulse(int gain) return 1; } -static int hx711_get_gain_to_scale(int gain) +static int hx711_get_gain_to_scale(const int *gain_scale, int gain) { int i; for (i = 0; i < HX711_GAIN_MAX; i++) if (hx711_gain_to_scale[i].gain == gain) - return hx711_gain_to_scale[i].scale; + return gain_scale[i]; return 0; } -static int hx711_get_scale_to_gain(int scale) +static int hx711_get_scale_to_gain(const int *gain_scale, int scale) { int i; for (i = 0; i < HX711_GAIN_MAX; i++) - if (hx711_gain_to_scale[i].scale == scale) + if (gain_scale[i] == scale) return hx711_gain_to_scale[i].gain; return -EINVAL; } @@ -82,6 +80,7 @@ struct hx711_data { struct gpio_desc *gpiod_dout; int gain_set; /* gain set on device */ int gain_chan_a; /* gain for channel A */ + int gain_scale[HX711_GAIN_MAX]; struct mutex lock; /* * triggered buffer @@ -290,7 +289,8 @@ static int hx711_read_raw(struct iio_dev *indio_dev, *val = 0; mutex_lock(&hx711_data->lock); - *val2 = hx711_get_gain_to_scale(hx711_data->gain_set); + *val2 = hx711_get_gain_to_scale(hx711_data->gain_scale, + hx711_data->gain_set); mutex_unlock(&hx711_data->lock); @@ -321,7 +321,7 @@ static int hx711_write_raw(struct iio_dev *indio_dev, mutex_lock(&hx711_data->lock); - gain = hx711_get_scale_to_gain(val2); + gain = hx711_get_scale_to_gain(hx711_data->gain_scale, val2); if (gain < 0) { mutex_unlock(&hx711_data->lock); return gain; @@ -386,6 +386,7 @@ static ssize_t hx711_scale_available_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct hx711_data *hx711_data = iio_priv(dev_to_iio_dev(dev)); struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr); int channel = iio_attr->address; int i, len = 0; @@ -393,7 +394,7 @@ static ssize_t hx711_scale_available_show(struct device *dev, for (i = 0; i < HX711_GAIN_MAX; i++) if (hx711_gain_to_scale[i].channel == channel) len += sprintf(buf + len, "0.%09d ", - hx711_gain_to_scale[i].scale); + hx711_data->gain_scale[i]); len += sprintf(buf + len, "\n"); @@ -511,7 +512,7 @@ static int hx711_probe(struct platform_device *pdev) ret *= 100; for (i = 0; i < HX711_GAIN_MAX; i++) - hx711_gain_to_scale[i].scale = + hx711_data->gain_scale[i] = ret / hx711_gain_to_scale[i].gain / 1678; hx711_data->gain_set = 128; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 7c04e3ec1cbc..c412f5ed46a1 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -1078,12 +1078,12 @@ static void ina2xx_remove(struct i2c_client *client) } static const struct i2c_device_id ina2xx_id[] = { - { "ina219", ina219 }, - { "ina220", ina219 }, - { "ina226", ina226 }, - { "ina230", ina226 }, - { "ina231", ina226 }, - { "ina236", ina236 }, + { .name = "ina219", .driver_data = ina219 }, + { .name = "ina220", .driver_data = ina219 }, + { .name = "ina226", .driver_data = ina226 }, + { .name = "ina230", .driver_data = ina226 }, + { .name = "ina231", .driver_data = ina226 }, + { .name = "ina236", .driver_data = ina236 }, { } }; MODULE_DEVICE_TABLE(i2c, ina2xx_id); diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c index 1e802c8779a4..414f69acab7b 100644 --- a/drivers/iio/adc/ingenic-adc.c +++ b/drivers/iio/adc/ingenic-adc.c @@ -7,6 +7,8 @@ */ #include + +#include #include #include #include @@ -115,7 +117,7 @@ static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask) { struct ingenic_adc *adc = iio_priv(iio_dev); - mutex_lock(&adc->lock); + guard(mutex)(&adc->lock); /* Init ADCMD */ readl(adc->base + JZ_ADC_REG_ADCMD); @@ -162,8 +164,6 @@ static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask) /* We're done */ writel(0, adc->base + JZ_ADC_REG_ADCMD); - - mutex_unlock(&adc->lock); } static void ingenic_adc_set_config(struct ingenic_adc *adc, @@ -172,18 +172,15 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc, { uint32_t cfg; - mutex_lock(&adc->lock); + guard(mutex)(&adc->lock); cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask; cfg |= val; writel(cfg, adc->base + JZ_ADC_REG_CFG); - - mutex_unlock(&adc->lock); } -static void ingenic_adc_enable_unlocked(struct ingenic_adc *adc, - int engine, - bool enabled) +static void __ingenic_adc_enable(struct ingenic_adc *adc, int engine, + bool enabled) { u8 val; @@ -201,9 +198,8 @@ static void ingenic_adc_enable(struct ingenic_adc *adc, int engine, bool enabled) { - mutex_lock(&adc->lock); - ingenic_adc_enable_unlocked(adc, engine, enabled); - mutex_unlock(&adc->lock); + guard(mutex)(&adc->lock); + __ingenic_adc_enable(adc, engine, enabled); } static int ingenic_adc_capture(struct ingenic_adc *adc, @@ -218,18 +214,17 @@ static int ingenic_adc_capture(struct ingenic_adc *adc, * probably due to the switch of VREF. We must keep the lock here to * avoid races with the buffer enable/disable functions. */ - mutex_lock(&adc->lock); + guard(mutex)(&adc->lock); cfg = readl(adc->base + JZ_ADC_REG_CFG); writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG); - ingenic_adc_enable_unlocked(adc, engine, true); + __ingenic_adc_enable(adc, engine, true); ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val, !(val & BIT(engine)), 250, 1000); if (ret) - ingenic_adc_enable_unlocked(adc, engine, false); + __ingenic_adc_enable(adc, engine, false); writel(cfg, adc->base + JZ_ADC_REG_CFG); - mutex_unlock(&adc->lock); return ret; } @@ -628,22 +623,12 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev, } } -static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *chan, - int *val) +static int __ingenic_adc_read_chan(struct ingenic_adc *adc, + struct iio_chan_spec const *chan, + int *val) { int cmd, ret, engine = (chan->channel == INGENIC_ADC_BATTERY); - struct ingenic_adc *adc = iio_priv(iio_dev); - ret = clk_enable(adc->clk); - if (ret) { - dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", - ret); - return ret; - } - - /* We cannot sample the aux channels in parallel. */ - mutex_lock(&adc->aux_lock); if (adc->soc_data->has_aux_md && engine == 0) { switch (chan->channel) { case INGENIC_ADC_AUX0: @@ -662,7 +647,7 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev, ret = ingenic_adc_capture(adc, engine); if (ret) - goto out; + return ret; switch (chan->channel) { case INGENIC_ADC_AUX0: @@ -675,9 +660,26 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev, break; } - ret = IIO_VAL_INT; -out: - mutex_unlock(&adc->aux_lock); + return IIO_VAL_INT; +} + +static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val) +{ + struct ingenic_adc *adc = iio_priv(iio_dev); + int ret; + + ret = clk_enable(adc->clk); + if (ret) { + dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", ret); + return ret; + } + + /* We cannot sample the aux channels in parallel. */ + scoped_guard(mutex, &adc->aux_lock) + ret = __ingenic_adc_read_chan(adc, chan, val); + clk_disable(adc->clk); return ret; diff --git a/drivers/iio/adc/ltc2309.c b/drivers/iio/adc/ltc2309.c index 316256edf150..1ad533270a39 100644 --- a/drivers/iio/adc/ltc2309.c +++ b/drivers/iio/adc/ltc2309.c @@ -9,7 +9,9 @@ * * Copyright (c) 2023, Liam Beguin */ +#include #include +#include #include #include #include @@ -34,12 +36,14 @@ * @client: I2C reference * @lock: Lock to serialize data access * @vref_mv: Internal voltage reference + * @read_delay_us: Chip-specific read delay in microseconds */ struct ltc2309 { struct device *dev; struct i2c_client *client; struct mutex lock; /* serialize data access */ int vref_mv; + unsigned int read_delay_us; }; /* Order matches expected channel address, See datasheet Table 1. */ @@ -117,20 +121,22 @@ static const struct iio_chan_spec ltc2309_channels[] = { struct ltc2309_chip_info { const char *name; - const struct iio_chan_spec *channels; + unsigned int read_delay_us; int num_channels; + const struct iio_chan_spec *channels __counted_by_ptr(num_channels); }; static const struct ltc2309_chip_info ltc2305_chip_info = { .name = "ltc2305", - .channels = ltc2305_channels, + .read_delay_us = 2, .num_channels = ARRAY_SIZE(ltc2305_channels), + .channels = ltc2305_channels, }; static const struct ltc2309_chip_info ltc2309_chip_info = { .name = "ltc2309", - .channels = ltc2309_channels, .num_channels = ARRAY_SIZE(ltc2309_channels), + .channels = ltc2309_channels, }; static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309, @@ -151,6 +157,9 @@ static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309, return ret; } + if (ltc2309->read_delay_us) + fsleep(ltc2309->read_delay_us); + ret = i2c_master_recv(ltc2309->client, (char *)&buf, 2); if (ret < 0) { dev_err(ltc2309->dev, "i2c read failed: %pe\n", ERR_PTR(ret)); @@ -206,6 +215,7 @@ static int ltc2309_probe(struct i2c_client *client) ltc2309->dev = &indio_dev->dev; ltc2309->client = client; + ltc2309->read_delay_us = chip_info->read_delay_us; indio_dev->name = chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; @@ -233,8 +243,8 @@ static const struct of_device_id ltc2309_of_match[] = { MODULE_DEVICE_TABLE(of, ltc2309_of_match); static const struct i2c_device_id ltc2309_id[] = { - { "ltc2305", (kernel_ulong_t)<c2305_chip_info }, - { "ltc2309", (kernel_ulong_t)<c2309_chip_info }, + { .name = "ltc2305", .driver_data = (kernel_ulong_t)<c2305_chip_info }, + { .name = "ltc2309", .driver_data = (kernel_ulong_t)<c2309_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, ltc2309_id); diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c index a579107fd5c9..369af700969f 100644 --- a/drivers/iio/adc/ltc2471.c +++ b/drivers/iio/adc/ltc2471.c @@ -136,8 +136,8 @@ static int ltc2471_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ltc2471_i2c_id[] = { - { "ltc2471", ltc2471 }, - { "ltc2473", ltc2473 }, + { .name = "ltc2471", .driver_data = ltc2471 }, + { .name = "ltc2473", .driver_data = ltc2473 }, { } }; MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id); diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c index 060651dd4130..8c3806e061dd 100644 --- a/drivers/iio/adc/ltc2485.c +++ b/drivers/iio/adc/ltc2485.c @@ -124,7 +124,7 @@ static int ltc2485_probe(struct i2c_client *client) } static const struct i2c_device_id ltc2485_id[] = { - { "ltc2485" }, + { .name = "ltc2485" }, { } }; MODULE_DEVICE_TABLE(i2c, ltc2485_id); diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index eb9d521e86e5..8e899d6ffcfa 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -142,8 +142,8 @@ static const struct ltc2497_chip_info ltc2497_info[] = { }; static const struct i2c_device_id ltc2497_id[] = { - { "ltc2497", (kernel_ulong_t)<c2497_info[TYPE_LTC2497] }, - { "ltc2499", (kernel_ulong_t)<c2497_info[TYPE_LTC2499] }, + { .name = "ltc2497", .driver_data = (kernel_ulong_t)<c2497_info[TYPE_LTC2497] }, + { .name = "ltc2499", .driver_data = (kernel_ulong_t)<c2497_info[TYPE_LTC2499] }, { } }; MODULE_DEVICE_TABLE(i2c, ltc2497_id); diff --git a/drivers/iio/adc/max11410.c b/drivers/iio/adc/max11410.c index 69351f4f10bb..dc1b96356592 100644 --- a/drivers/iio/adc/max11410.c +++ b/drivers/iio/adc/max11410.c @@ -804,7 +804,7 @@ static int max11410_parse_channels(struct max11410_state *st, chan_idx++; } - channels[chan_idx] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(chan_idx); + channels[chan_idx] = IIO_CHAN_SOFT_TIMESTAMP(chan_idx); indio_dev->num_channels = chan_idx + 1; indio_dev->channels = channels; diff --git a/drivers/iio/adc/max34408.c b/drivers/iio/adc/max34408.c index 4f45fd22a90c..da847eaed84e 100644 --- a/drivers/iio/adc/max34408.c +++ b/drivers/iio/adc/max34408.c @@ -256,8 +256,8 @@ static const struct of_device_id max34408_of_match[] = { MODULE_DEVICE_TABLE(of, max34408_of_match); static const struct i2c_device_id max34408_id[] = { - { "max34408", (kernel_ulong_t)&max34408_model_data }, - { "max34409", (kernel_ulong_t)&max34409_model_data }, + { .name = "max34408", .driver_data = (kernel_ulong_t)&max34408_model_data }, + { .name = "max34409", .driver_data = (kernel_ulong_t)&max34409_model_data }, { } }; MODULE_DEVICE_TABLE(i2c, max34408_id); diff --git a/drivers/iio/adc/max77541-adc.c b/drivers/iio/adc/max77541-adc.c index 0aa04d143ad4..013da014bccd 100644 --- a/drivers/iio/adc/max77541-adc.c +++ b/drivers/iio/adc/max77541-adc.c @@ -175,7 +175,7 @@ static int max77541_adc_probe(struct platform_device *pdev) } static const struct platform_device_id max77541_adc_platform_id[] = { - { "max77541-adc" }, + { .name = "max77541-adc" }, { } }; MODULE_DEVICE_TABLE(platform, max77541_adc_platform_id); diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 50834fdcf738..f49cde672958 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -13,6 +13,8 @@ * voltage unit is nV. */ +#include +#include #include #include #include @@ -24,10 +26,10 @@ #include #include -/* Masks */ -#define MCP3422_CHANNEL_MASK 0x60 -#define MCP3422_PGA_MASK 0x03 -#define MCP3422_SRATE_MASK 0x0C +#define MCP3422_CHANNEL_MASK GENMASK(6, 5) +#define MCP3422_SRATE_MASK GENMASK(3, 2) +#define MCP3422_PGA_MASK GENMASK(1, 0) + #define MCP3422_SRATE_240 0x0 #define MCP3422_SRATE_60 0x1 #define MCP3422_SRATE_15 0x2 @@ -36,15 +38,7 @@ #define MCP3422_PGA_2 1 #define MCP3422_PGA_4 2 #define MCP3422_PGA_8 3 -#define MCP3422_CONT_SAMPLING 0x10 - -#define MCP3422_CHANNEL(config) (((config) & MCP3422_CHANNEL_MASK) >> 5) -#define MCP3422_PGA(config) ((config) & MCP3422_PGA_MASK) -#define MCP3422_SAMPLE_RATE(config) (((config) & MCP3422_SRATE_MASK) >> 2) - -#define MCP3422_CHANNEL_VALUE(value) (((value) << 5) & MCP3422_CHANNEL_MASK) -#define MCP3422_PGA_VALUE(value) ((value) & MCP3422_PGA_MASK) -#define MCP3422_SAMPLE_RATE_VALUE(value) ((value << 2) & MCP3422_SRATE_MASK) +#define MCP3422_CONT_SAMPLING BIT(4) #define MCP3422_CHAN(_index) \ { \ @@ -108,7 +102,7 @@ static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig) static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config) { int ret = 0; - u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config); + u8 sample_rate = FIELD_GET(MCP3422_SRATE_MASK, adc->config); u8 buf[4] = {0, 0, 0, 0}; u32 temp; @@ -136,18 +130,18 @@ static int mcp3422_read_channel(struct mcp3422 *adc, mutex_lock(&adc->lock); - if (req_channel != MCP3422_CHANNEL(adc->config)) { + if (req_channel != FIELD_GET(MCP3422_CHANNEL_MASK, adc->config)) { config = adc->config; - config &= ~MCP3422_CHANNEL_MASK; - config |= MCP3422_CHANNEL_VALUE(req_channel); - config &= ~MCP3422_PGA_MASK; - config |= MCP3422_PGA_VALUE(adc->pga[req_channel]); + + FIELD_MODIFY(MCP3422_CHANNEL_MASK, &config, req_channel); + FIELD_MODIFY(MCP3422_PGA_MASK, &config, adc->pga[req_channel]); + ret = mcp3422_update_config(adc, config); if (ret < 0) { mutex_unlock(&adc->lock); return ret; } - msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]); + msleep(mcp3422_read_times[FIELD_GET(MCP3422_SRATE_MASK, adc->config)]); } ret = mcp3422_read(adc, value, &config); @@ -163,9 +157,8 @@ static int mcp3422_read_raw(struct iio_dev *iio, { struct mcp3422 *adc = iio_priv(iio); int err; - - u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config); - u8 pga = MCP3422_PGA(adc->config); + u8 sample_rate = FIELD_GET(MCP3422_SRATE_MASK, adc->config); + u8 pga = FIELD_GET(MCP3422_PGA_MASK, adc->config); switch (mask) { case IIO_CHAN_INFO_RAW: @@ -181,7 +174,7 @@ static int mcp3422_read_raw(struct iio_dev *iio, return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_SAMP_FREQ: - *val1 = mcp3422_sample_rates[MCP3422_SAMPLE_RATE(adc->config)]; + *val1 = mcp3422_sample_rates[FIELD_GET(MCP3422_SRATE_MASK, adc->config)]; return IIO_VAL_INT; default: @@ -199,7 +192,7 @@ static int mcp3422_write_raw(struct iio_dev *iio, u8 temp; u8 config = adc->config; u8 req_channel = channel->channel; - u8 sample_rate = MCP3422_SAMPLE_RATE(config); + u8 sample_rate = FIELD_GET(MCP3422_SRATE_MASK, config); u8 i; switch (mask) { @@ -211,10 +204,8 @@ static int mcp3422_write_raw(struct iio_dev *iio, if (val2 == mcp3422_scales[sample_rate][i]) { adc->pga[req_channel] = i; - config &= ~MCP3422_CHANNEL_MASK; - config |= MCP3422_CHANNEL_VALUE(req_channel); - config &= ~MCP3422_PGA_MASK; - config |= MCP3422_PGA_VALUE(adc->pga[req_channel]); + FIELD_MODIFY(MCP3422_CHANNEL_MASK, &config, req_channel); + FIELD_MODIFY(MCP3422_PGA_MASK, &config, adc->pga[req_channel]); return mcp3422_update_config(adc, config); } @@ -241,10 +232,8 @@ static int mcp3422_write_raw(struct iio_dev *iio, return -EINVAL; } - config &= ~MCP3422_CHANNEL_MASK; - config |= MCP3422_CHANNEL_VALUE(req_channel); - config &= ~MCP3422_SRATE_MASK; - config |= MCP3422_SAMPLE_RATE_VALUE(temp); + FIELD_MODIFY(MCP3422_CHANNEL_MASK, &config, req_channel); + FIELD_MODIFY(MCP3422_SRATE_MASK, &config, temp); return mcp3422_update_config(adc, config); @@ -283,7 +272,7 @@ static ssize_t mcp3422_show_scales(struct device *dev, struct device_attribute *attr, char *buf) { struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev)); - u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config); + u8 sample_rate = FIELD_GET(MCP3422_SRATE_MASK, adc->config); return sprintf(buf, "0.%09u 0.%09u 0.%09u 0.%09u\n", mcp3422_scales[sample_rate][0], @@ -376,10 +365,10 @@ static int mcp3422_probe(struct i2c_client *client) } /* meaningful default configuration */ - config = (MCP3422_CONT_SAMPLING - | MCP3422_CHANNEL_VALUE(0) - | MCP3422_PGA_VALUE(MCP3422_PGA_1) - | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); + config = MCP3422_CONT_SAMPLING | + FIELD_PREP(MCP3422_CHANNEL_MASK, 0) | + FIELD_PREP(MCP3422_PGA_MASK, MCP3422_PGA_1) | + FIELD_PREP(MCP3422_SRATE_MASK, MCP3422_SRATE_240); err = mcp3422_update_config(adc, config); if (err < 0) return err; @@ -394,14 +383,14 @@ static int mcp3422_probe(struct i2c_client *client) } static const struct i2c_device_id mcp3422_id[] = { - { "mcp3421", 1 }, - { "mcp3422", 2 }, - { "mcp3423", 3 }, - { "mcp3424", 4 }, - { "mcp3425", 5 }, - { "mcp3426", 6 }, - { "mcp3427", 7 }, - { "mcp3428", 8 }, + { .name = "mcp3421", .driver_data = 1 }, + { .name = "mcp3422", .driver_data = 2 }, + { .name = "mcp3423", .driver_data = 3 }, + { .name = "mcp3424", .driver_data = 4 }, + { .name = "mcp3425", .driver_data = 5 }, + { .name = "mcp3426", .driver_data = 6 }, + { .name = "mcp3427", .driver_data = 7 }, + { .name = "mcp3428", .driver_data = 8 }, { } }; MODULE_DEVICE_TABLE(i2c, mcp3422_id); diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index 970afb27b839..836c9b49c721 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -531,7 +531,7 @@ static int nau7802_probe(struct i2c_client *client) } static const struct i2c_device_id nau7802_i2c_id[] = { - { "nau7802" }, + { .name = "nau7802" }, { } }; MODULE_DEVICE_TABLE(i2c, nau7802_i2c_id); diff --git a/drivers/iio/adc/nxp-sar-adc.c b/drivers/iio/adc/nxp-sar-adc.c index 8f4ed3db94f0..15c7432808f4 100644 --- a/drivers/iio/adc/nxp-sar-adc.c +++ b/drivers/iio/adc/nxp-sar-adc.c @@ -326,11 +326,7 @@ static int nxp_sar_adc_read_data(struct nxp_sar_adc *info, unsigned int chan) ceocfr = readl(NXP_SAR_ADC_CEOCFR0(info->regs)); - /* - * FIELD_GET() can not be used here because EOC_CH is not constant. - * TODO: Switch to field_get() when it will be available. - */ - if (!(NXP_SAR_ADC_EOC_CH(chan) & ceocfr)) + if (!field_get(NXP_SAR_ADC_EOC_CH(chan), ceocfr)) return -EIO; cdr = readl(NXP_SAR_ADC_CDR(info->regs, chan)); @@ -350,6 +346,7 @@ static void nxp_sar_adc_isr_buffer(struct iio_dev *indio_dev) ret = nxp_sar_adc_read_data(info, info->buffered_chan[i]); if (ret < 0) { nxp_sar_adc_read_notify(info); + iio_trigger_notify_done(indio_dev->trig); return; } diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c index bce7185953ec..68bdd2f30bad 100644 --- a/drivers/iio/adc/pac1921.c +++ b/drivers/iio/adc/pac1921.c @@ -1310,7 +1310,7 @@ static int pac1921_probe(struct i2c_client *client) } static const struct i2c_device_id pac1921_id[] = { - { .name = "pac1921", 0 }, + { .name = "pac1921" }, { } }; MODULE_DEVICE_TABLE(i2c, pac1921_id); diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c index 31f88cf7f7f1..4a1a0cfb4699 100644 --- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c +++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c @@ -369,7 +369,7 @@ static const struct xoadc_channel pm8921_xoadc_channels[] = { /** * struct pm8xxx_chan_info - ADC channel information - * @name: name of this channel + * @label: label of this channel from device tree (defaults to datasheet name if not specified) * @hwchan: pointer to hardware channel information (muxing & scaling settings) * @calibration: whether to use absolute or ratiometric calibration * @decimation: 0,1,2,3 @@ -377,7 +377,7 @@ static const struct xoadc_channel pm8921_xoadc_channels[] = { * calibration: 0, 1, 2, 4, 5. */ struct pm8xxx_chan_info { - const char *name; + const char *label; const struct xoadc_channel *hwchan; enum vadc_calibration calibration; u8 decimation:2; @@ -446,7 +446,7 @@ static int pm8xxx_read_channel_rsv(struct pm8xxx_xoadc *adc, u8 lsb, msb; dev_dbg(adc->dev, "read channel \"%s\", amux %d, prescale/mux: %d, rsv %d\n", - ch->name, ch->hwchan->amux_channel, ch->hwchan->pre_scale_mux, rsv); + ch->label, ch->hwchan->amux_channel, ch->hwchan->pre_scale_mux, rsv); mutex_lock(&adc->lock); @@ -535,10 +535,7 @@ static int pm8xxx_read_channel_rsv(struct pm8xxx_xoadc *adc, goto unlock; /* Next the interrupt occurs */ - ret = wait_for_completion_timeout(&adc->complete, - VADC_CONV_TIME_MAX_US); - if (!ret) { - dev_err(adc->dev, "conversion timed out\n"); + if (!wait_for_completion_timeout(&adc->complete, VADC_CONV_TIME_MAX_US)) { ret = -ETIMEDOUT; goto unlock; } @@ -657,11 +654,8 @@ static int pm8xxx_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_PROCESSED: ch = pm8xxx_get_channel(adc, chan->address); - if (!ch) { - dev_err(adc->dev, "no such channel %lu\n", - chan->address); + if (!ch) return -EINVAL; - } ret = pm8xxx_read_channel(adc, ch, &adc_code); if (ret) return ret; @@ -677,11 +671,8 @@ static int pm8xxx_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_RAW: ch = pm8xxx_get_channel(adc, chan->address); - if (!ch) { - dev_err(adc->dev, "no such channel %lu\n", - chan->address); + if (!ch) return -EINVAL; - } ret = pm8xxx_read_channel(adc, ch, &adc_code); if (ret) return ret; @@ -725,8 +716,21 @@ static int pm8xxx_fwnode_xlate(struct iio_dev *indio_dev, return -EINVAL; } +static int pm8xxx_read_label(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, char *label) +{ + struct pm8xxx_xoadc *adc = iio_priv(indio_dev); + const struct pm8xxx_chan_info *ch; + + ch = pm8xxx_get_channel(adc, chan->address); + if (!ch) + return -EINVAL; + return sysfs_emit(label, "%s\n", ch->label); +} + static const struct iio_info pm8xxx_xoadc_info = { .fwnode_xlate = pm8xxx_fwnode_xlate, + .read_label = pm8xxx_read_label, .read_raw = pm8xxx_read_raw, }; @@ -770,7 +774,8 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev, pre_scale_mux, amux_channel); return -EINVAL; } - ch->name = name; + ch->label = hwchan->datasheet_name; + fwnode_property_read_string(fwnode, "label", &ch->label); ch->hwchan = hwchan; /* Everyone seems to use absolute calibration except in special cases */ ch->calibration = VADC_CALIB_ABSOLUTE; @@ -812,7 +817,7 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev, dev_dbg(dev, "channel [PRESCALE/MUX: %02x AMUX: %02x] \"%s\" ref voltage: %d, decimation %d prescale %d/%d, scale function %d\n", - hwchan->pre_scale_mux, hwchan->amux_channel, ch->name, + hwchan->pre_scale_mux, hwchan->amux_channel, ch->label, ch->amux_ip_rsv, ch->decimation, hwchan->prescale.numerator, hwchan->prescale.denominator, hwchan->scale_fn_type); diff --git a/drivers/iio/adc/qcom-spmi-iadc.c b/drivers/iio/adc/qcom-spmi-iadc.c index b64a8a407168..0ec3a0c4b1de 100644 --- a/drivers/iio/adc/qcom-spmi-iadc.c +++ b/drivers/iio/adc/qcom-spmi-iadc.c @@ -481,6 +481,11 @@ static const struct iio_chan_spec iadc_channels[] = { }, }; +static void iadc_disable_irq_wake(void *data) +{ + disable_irq_wake((unsigned long)data); +} + static int iadc_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -538,9 +543,16 @@ static int iadc_probe(struct platform_device *pdev) if (!iadc->poll_eoc) { ret = devm_request_irq(dev, irq_eoc, iadc_isr, 0, "spmi-iadc", iadc); - if (!ret) - enable_irq_wake(irq_eoc); - else + if (ret) + return ret; + + ret = enable_irq_wake(irq_eoc); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, iadc_disable_irq_wake, + (void *)(unsigned long)irq_eoc); + if (ret) return ret; } else { ret = devm_device_init_wakeup(iadc->dev); diff --git a/drivers/iio/adc/rohm-bd79124.c b/drivers/iio/adc/rohm-bd79124.c index 40d00bd0cc9d..864f3b1366b5 100644 --- a/drivers/iio/adc/rohm-bd79124.c +++ b/drivers/iio/adc/rohm-bd79124.c @@ -1104,7 +1104,7 @@ static const struct of_device_id bd79124_of_match[] = { MODULE_DEVICE_TABLE(of, bd79124_of_match); static const struct i2c_device_id bd79124_id[] = { - { "bd79124" }, + { .name = "bd79124" }, { } }; MODULE_DEVICE_TABLE(i2c, bd79124_id); diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c index 2bf3a09ac6b0..e2b1da13c0d3 100644 --- a/drivers/iio/adc/rtq6056.c +++ b/drivers/iio/adc/rtq6056.c @@ -728,7 +728,7 @@ static int rtq6056_probe(struct i2c_client *i2c) if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA)) return -EOPNOTSUPP; - devdata = device_get_match_data(dev); + devdata = i2c_get_match_data(i2c); if (!devdata) return dev_err_probe(dev, -EINVAL, "Invalid dev data\n"); @@ -871,6 +871,13 @@ static const struct richtek_dev_data rtq6059_devdata = { .set_average = rtq6059_adc_set_average, }; +static const struct i2c_device_id rtq6056_id[] = { + { "rtq6056", (kernel_ulong_t)&rtq6056_devdata }, + { "rtq6059", (kernel_ulong_t)&rtq6059_devdata }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rtq6056_id); + static const struct of_device_id rtq6056_device_match[] = { { .compatible = "richtek,rtq6056", .data = &rtq6056_devdata }, { .compatible = "richtek,rtq6059", .data = &rtq6059_devdata }, @@ -885,6 +892,7 @@ static struct i2c_driver rtq6056_driver = { .pm = pm_ptr(&rtq6056_pm_ops), }, .probe = rtq6056_probe, + .id_table = rtq6056_id, }; module_i2c_driver(rtq6056_driver); diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index 91995489bb1c..4be722406bb5 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -5,22 +5,25 @@ * Copyright 2012 Stefan Roese */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include +#include /* SPEAR registers definitions */ #define SPEAR600_ADC_SCAN_RATE_LO(x) ((x) & 0xFFFF) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 46106200bb86..5c5170b19b56 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -2443,15 +2443,7 @@ static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping) scan_index = ret; if (timestamping) { - struct iio_chan_spec *timestamp = &channels[scan_index]; - - timestamp->type = IIO_TIMESTAMP; - timestamp->channel = -1; - timestamp->scan_index = scan_index; - timestamp->scan_type.sign = 's'; - timestamp->scan_type.realbits = 64; - timestamp->scan_type.storagebits = 64; - + channels[scan_index] = IIO_CHAN_SOFT_TIMESTAMP(scan_index); scan_index++; } diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c index 861c14da75ad..81fc4610e15e 100644 --- a/drivers/iio/adc/sun20i-gpadc-iio.c +++ b/drivers/iio/adc/sun20i-gpadc-iio.c @@ -139,8 +139,23 @@ static irqreturn_t sun20i_gpadc_irq_handler(int irq, void *data) return IRQ_HANDLED; } +static int +sun20i_gpadc_fwnode_xlate(struct iio_dev *indio_dev, + const struct fwnode_reference_args *iiospec) +{ + if (iiospec->nargs != 1) + return -EINVAL; + + for (unsigned int i = 0; i < indio_dev->num_channels; i++) + if (indio_dev->channels[i].channel == iiospec->args[0]) + return i; + + return -EINVAL; +} + static const struct iio_info sun20i_gpadc_iio_info = { .read_raw = sun20i_gpadc_read_raw, + .fwnode_xlate = sun20i_gpadc_fwnode_xlate, }; static void sun20i_gpadc_reset_assert(void *data) @@ -177,10 +192,10 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev, static int sun20i_gpadc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct iio_dev *indio_dev; struct sun20i_gpadc_iio *info; + struct clk_bulk_data *clks; struct reset_control *rst; - struct clk *clk; + struct iio_dev *indio_dev; int irq; int ret; @@ -205,9 +220,11 @@ static int sun20i_gpadc_probe(struct platform_device *pdev) if (IS_ERR(info->regs)) return PTR_ERR(info->regs); - clk = devm_clk_get_enabled(dev, NULL); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), "failed to enable bus clock\n"); + ret = devm_clk_bulk_get_all_enabled(dev, &clks); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to enable clocks\n"); + if (ret == 0) + return dev_err_probe(dev, -ENODEV, "needs at least one clocks\n"); rst = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(rst)) @@ -243,6 +260,7 @@ static int sun20i_gpadc_probe(struct platform_device *pdev) static const struct of_device_id sun20i_gpadc_of_id[] = { { .compatible = "allwinner,sun20i-d1-gpadc" }, + { .compatible = "allwinner,sun55i-a523-gpadc" }, { } }; MODULE_DEVICE_TABLE(of, sun20i_gpadc_of_id); diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 479115ea50bf..203459ca9907 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -679,9 +679,9 @@ static void sun4i_gpadc_remove(struct platform_device *pdev) } static const struct platform_device_id sun4i_gpadc_id[] = { - { "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data }, - { "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data }, - { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data }, + { .name = "sun4i-a10-gpadc-iio", .driver_data = (kernel_ulong_t)&sun4i_gpadc_data }, + { .name = "sun5i-a13-gpadc-iio", .driver_data = (kernel_ulong_t)&sun5i_gpadc_data }, + { .name = "sun6i-a31-gpadc-iio", .driver_data = (kernel_ulong_t)&sun6i_gpadc_data }, { } }; MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id); diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index 8ef51c57912d..33f82bdfeb94 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -199,9 +199,9 @@ static int adc081c_probe(struct i2c_client *client) } static const struct i2c_device_id adc081c_id[] = { - { "adc081c", (kernel_ulong_t)&adc081c_model }, - { "adc101c", (kernel_ulong_t)&adc101c_model }, - { "adc121c", (kernel_ulong_t)&adc121c_model }, + { .name = "adc081c", .driver_data = (kernel_ulong_t)&adc081c_model }, + { .name = "adc101c", .driver_data = (kernel_ulong_t)&adc101c_model }, + { .name = "adc121c", .driver_data = (kernel_ulong_t)&adc121c_model }, { } }; MODULE_DEVICE_TABLE(i2c, adc081c_id); diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index c7ffe47449e2..8a272af69f7d 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -1128,9 +1128,9 @@ static const struct ads1015_chip_data tla2024_data = { }; static const struct i2c_device_id ads1015_id[] = { - { "ads1015", (kernel_ulong_t)&ads1015_data }, - { "ads1115", (kernel_ulong_t)&ads1115_data }, - { "tla2024", (kernel_ulong_t)&tla2024_data }, + { .name = "ads1015", .driver_data = (kernel_ulong_t)&ads1015_data }, + { .name = "ads1115", .driver_data = (kernel_ulong_t)&ads1115_data }, + { .name = "tla2024", .driver_data = (kernel_ulong_t)&tla2024_data }, { } }; MODULE_DEVICE_TABLE(i2c, ads1015_id); diff --git a/drivers/iio/adc/ti-ads1100.c b/drivers/iio/adc/ti-ads1100.c index aa8946063c7d..9fe8d54cce83 100644 --- a/drivers/iio/adc/ti-ads1100.c +++ b/drivers/iio/adc/ti-ads1100.c @@ -400,8 +400,8 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ads1100_pm_ops, NULL); static const struct i2c_device_id ads1100_id[] = { - { "ads1100" }, - { "ads1000" }, + { .name = "ads1100" }, + { .name = "ads1000" }, { } }; diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c index 2320be0efb50..d31f3d6eb781 100644 --- a/drivers/iio/adc/ti-ads1119.c +++ b/drivers/iio/adc/ti-ads1119.c @@ -804,7 +804,7 @@ static const struct of_device_id __maybe_unused ads1119_of_match[] = { MODULE_DEVICE_TABLE(of, ads1119_of_match); static const struct i2c_device_id ads1119_id[] = { - { "ads1119" }, + { .name = "ads1119" }, { } }; MODULE_DEVICE_TABLE(i2c, ads1119_id); diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c index ae30b47e4514..9e47ace16acd 100644 --- a/drivers/iio/adc/ti-ads1298.c +++ b/drivers/iio/adc/ti-ads1298.c @@ -66,7 +66,7 @@ #define ADS1298_MASK_CONFIG3_VREF_4V BIT(5) #define ADS1298_REG_LOFF 0x04 -#define ADS1298_REG_CHnSET(n) (0x05 + n) +#define ADS1298_REG_CHnSET(n) (0x05 + (n)) #define ADS1298_MASK_CH_PD BIT(7) #define ADS1298_MASK_CH_PGA GENMASK(6, 4) #define ADS1298_MASK_CH_MUX GENMASK(2, 0) @@ -210,9 +210,11 @@ static int ads1298_read_one(struct ads1298_private *priv, int chan_index) return ret; } - /* Cannot take longer than 40ms (250Hz) */ - ret = wait_for_completion_timeout(&priv->completion, msecs_to_jiffies(50)); - if (!ret) + /* + * One conversion takes at most 4ms at the lowest sample rate (250Hz). + * Use 50ms to allow for kernel scheduling latency. + */ + if (!wait_for_completion_timeout(&priv->completion, msecs_to_jiffies(50))) return -ETIMEDOUT; return 0; @@ -279,6 +281,7 @@ static const u8 ads1298_pga_settings[] = { 6, 1, 2, 3, 4, 8, 12 }; static int ads1298_get_scale(struct ads1298_private *priv, int channel, int *val, int *val2) { + unsigned int pga_idx; int ret; unsigned int regval; u8 gain; @@ -302,7 +305,11 @@ static int ads1298_get_scale(struct ads1298_private *priv, if (ret) return ret; - gain = ads1298_pga_settings[FIELD_GET(ADS1298_MASK_CH_PGA, regval)]; + pga_idx = FIELD_GET(ADS1298_MASK_CH_PGA, regval); + if (pga_idx >= ARRAY_SIZE(ads1298_pga_settings)) + return -EINVAL; + + gain = ads1298_pga_settings[pga_idx]; *val /= gain; /* Full scale is VREF / gain */ *val2 = ADS1298_BITS_PER_SAMPLE - 1; /* Signed, hence the -1 */ @@ -615,15 +622,6 @@ static int ads1298_init(struct iio_dev *indio_dev) if (!indio_dev->name) return -ENOMEM; - /* Enable internal test signal, double amplitude, double frequency */ - ret = regmap_write(priv->regmap, ADS1298_REG_CONFIG2, - ADS1298_MASK_CONFIG2_RESERVED | - ADS1298_MASK_CONFIG2_INT_TEST | - ADS1298_MASK_CONFIG2_TEST_AMP | - ADS1298_MASK_CONFIG2_TEST_FREQ_FAST); - if (ret) - return ret; - val = ADS1298_MASK_CONFIG3_RESERVED; /* Must write 1 always */ if (!priv->reg_vref) { /* Enable internal reference */ diff --git a/drivers/iio/adc/ti-ads7138.c b/drivers/iio/adc/ti-ads7138.c index ee5c1b8e3a8e..af87f5f19a0f 100644 --- a/drivers/iio/adc/ti-ads7138.c +++ b/drivers/iio/adc/ti-ads7138.c @@ -727,8 +727,8 @@ static const struct of_device_id ads7138_of_match[] = { MODULE_DEVICE_TABLE(of, ads7138_of_match); static const struct i2c_device_id ads7138_device_ids[] = { - { "ads7128", (kernel_ulong_t)&ads7128_data }, - { "ads7138", (kernel_ulong_t)&ads7138_data }, + { .name = "ads7128", .driver_data = (kernel_ulong_t)&ads7128_data }, + { .name = "ads7138", .driver_data = (kernel_ulong_t)&ads7138_data }, { } }; MODULE_DEVICE_TABLE(i2c, ads7138_device_ids); diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c index bbcc4fc22b6e..ff30a52d2850 100644 --- a/drivers/iio/adc/ti-ads7924.c +++ b/drivers/iio/adc/ti-ads7924.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -198,6 +199,8 @@ static int ads7924_get_adc_result(struct ads7924_data *data, if (chan->channel < 0 || chan->channel >= ADS7924_CHANNELS) return -EINVAL; + guard(mutex)(&data->lock); + if (data->conv_invalid) { int conv_time; @@ -227,9 +230,7 @@ static int ads7924_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - mutex_lock(&data->lock); ret = ads7924_get_adc_result(data, chan, val); - mutex_unlock(&data->lock); if (ret < 0) return ret; @@ -441,7 +442,7 @@ static int ads7924_probe(struct i2c_client *client) } static const struct i2c_device_id ads7924_id[] = { - { "ads7924" }, + { .name = "ads7924" }, { } }; MODULE_DEVICE_TABLE(i2c, ads7924_id); diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index 028acd42741f..39a074bce6d5 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -267,31 +267,6 @@ static const struct ti_ads7950_chip_info ti_ads7961_chip_info = { .num_channels = ARRAY_SIZE(ti_ads7961_channels), }; -/* - * ti_ads7950_update_scan_mode() setup the spi transfer buffer for the new - * scan mask - */ -static int ti_ads7950_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *active_scan_mask) -{ - struct ti_ads7950_state *st = iio_priv(indio_dev); - int i, cmd, len; - - len = 0; - for_each_set_bit(i, active_scan_mask, indio_dev->num_channels) { - cmd = TI_ADS7950_MAN_CMD(TI_ADS7950_CR_CHAN(i)); - st->tx_buf[len++] = cmd; - } - - /* Data for the 1st channel is not returned until the 3rd transfer */ - st->tx_buf[len++] = 0; - st->tx_buf[len++] = 0; - - st->ring_xfer.len = len * 2; - - return 0; -} - static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -299,18 +274,19 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p) struct ti_ads7950_state *st = iio_priv(indio_dev); int ret; - mutex_lock(&st->slock); - ret = spi_sync(st->spi, &st->ring_msg); - if (ret < 0) - goto out; + do { + guard(mutex)(&st->slock); - iio_push_to_buffers_with_ts_unaligned(indio_dev, &st->rx_buf[2], - sizeof(*st->rx_buf) * - TI_ADS7950_MAX_CHAN, - iio_get_time_ns(indio_dev)); + ret = spi_sync(st->spi, &st->ring_msg); + if (ret) + break; + + iio_push_to_buffers_with_ts_unaligned(indio_dev, &st->rx_buf[2], + sizeof(*st->rx_buf) * + TI_ADS7950_MAX_CHAN, + iio_get_time_ns(indio_dev)); + } while (0); -out: - mutex_unlock(&st->slock); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; @@ -321,35 +297,21 @@ static int ti_ads7950_scan_direct(struct iio_dev *indio_dev, unsigned int ch) struct ti_ads7950_state *st = iio_priv(indio_dev); int ret, cmd; - mutex_lock(&st->slock); + guard(mutex)(&st->slock); + cmd = TI_ADS7950_MAN_CMD(TI_ADS7950_CR_CHAN(ch)); st->single_tx = cmd; ret = spi_sync(st->spi, &st->scan_single_msg); if (ret) - goto out; + return ret; - ret = st->single_rx; - -out: - mutex_unlock(&st->slock); - - return ret; + return st->single_rx; } -static int ti_ads7950_get_range(struct ti_ads7950_state *st) +static unsigned int ti_ads7950_get_range(struct ti_ads7950_state *st) { - int vref; - - if (st->vref_mv) { - vref = st->vref_mv; - } else { - vref = regulator_get_voltage(st->reg); - if (vref < 0) - return vref; - - vref /= 1000; - } + unsigned int vref = st->vref_mv; if (st->cmd_settings_bitmask & TI_ADS7950_CR_RANGE_5V) vref *= 2; @@ -378,11 +340,7 @@ static int ti_ads7950_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = ti_ads7950_get_range(st); - if (ret < 0) - return ret; - - *val = ret; + *val = ti_ads7950_get_range(st); *val2 = (1 << chan->scan_type.realbits) - 1; return IIO_VAL_FRACTIONAL; @@ -392,17 +350,50 @@ static int ti_ads7950_read_raw(struct iio_dev *indio_dev, } static const struct iio_info ti_ads7950_info = { - .read_raw = &ti_ads7950_read_raw, - .update_scan_mode = ti_ads7950_update_scan_mode, + .read_raw = &ti_ads7950_read_raw, +}; + +static int ti_ads7950_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ti_ads7950_state *st = iio_priv(indio_dev); + u32 len = 0; + u32 i; + u16 cmd; + + for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->num_channels) { + cmd = TI_ADS7950_MAN_CMD(TI_ADS7950_CR_CHAN(i)); + st->tx_buf[len++] = cmd; + } + + /* Data for the 1st channel is not returned until the 3rd transfer */ + st->tx_buf[len++] = 0; + st->tx_buf[len++] = 0; + + st->ring_xfer.len = len * 2; + + return spi_optimize_message(st->spi, &st->ring_msg); +} + +static int ti_ads7950_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ti_ads7950_state *st = iio_priv(indio_dev); + + spi_unoptimize_message(&st->ring_msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ti_ads7950_buffer_setup_ops = { + .preenable = ti_ads7950_buffer_preenable, + .postdisable = ti_ads7950_buffer_postdisable, }; static int ti_ads7950_set(struct gpio_chip *chip, unsigned int offset, int value) { struct ti_ads7950_state *st = gpiochip_get_data(chip); - int ret; - mutex_lock(&st->slock); + guard(mutex)(&st->slock); if (value) st->cmd_settings_bitmask |= BIT(offset); @@ -410,11 +401,8 @@ static int ti_ads7950_set(struct gpio_chip *chip, unsigned int offset, st->cmd_settings_bitmask &= ~BIT(offset); st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st); - ret = spi_sync(st->spi, &st->scan_single_msg); - mutex_unlock(&st->slock); - - return ret; + return spi_sync(st->spi, &st->scan_single_msg); } static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) @@ -423,13 +411,12 @@ static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) bool state; int ret; - mutex_lock(&st->slock); + guard(mutex)(&st->slock); /* If set as output, return the output */ if (st->gpio_cmd_settings_bitmask & BIT(offset)) { state = st->cmd_settings_bitmask & BIT(offset); - ret = 0; - goto out; + return state; } /* GPIO data bit sets SDO bits 12-15 to GPIO input */ @@ -437,7 +424,7 @@ static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st); ret = spi_sync(st->spi, &st->scan_single_msg); if (ret) - goto out; + return ret; state = (st->single_rx >> 12) & BIT(offset); @@ -446,12 +433,9 @@ static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st); ret = spi_sync(st->spi, &st->scan_single_msg); if (ret) - goto out; + return ret; -out: - mutex_unlock(&st->slock); - - return ret ?: state; + return state; } static int ti_ads7950_get_direction(struct gpio_chip *chip, @@ -467,9 +451,8 @@ static int _ti_ads7950_set_direction(struct gpio_chip *chip, int offset, int input) { struct ti_ads7950_state *st = gpiochip_get_data(chip); - int ret = 0; - mutex_lock(&st->slock); + guard(mutex)(&st->slock); /* Only change direction if needed */ if (input && (st->gpio_cmd_settings_bitmask & BIT(offset))) @@ -477,15 +460,11 @@ static int _ti_ads7950_set_direction(struct gpio_chip *chip, int offset, else if (!input && !(st->gpio_cmd_settings_bitmask & BIT(offset))) st->gpio_cmd_settings_bitmask |= BIT(offset); else - goto out; + return 0; st->single_tx = TI_ADS7950_GPIO_CMD_SETTINGS(st); - ret = spi_sync(st->spi, &st->scan_single_msg); -out: - mutex_unlock(&st->slock); - - return ret; + return spi_sync(st->spi, &st->scan_single_msg); } static int ti_ads7950_direction_input(struct gpio_chip *chip, @@ -508,9 +487,9 @@ static int ti_ads7950_direction_output(struct gpio_chip *chip, static int ti_ads7950_init_hw(struct ti_ads7950_state *st) { - int ret = 0; + int ret; - mutex_lock(&st->slock); + guard(mutex)(&st->slock); /* Settings for Manual/Auto1/Auto2 commands */ /* Default to 5v ref */ @@ -518,17 +497,12 @@ static int ti_ads7950_init_hw(struct ti_ads7950_state *st) st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st); ret = spi_sync(st->spi, &st->scan_single_msg); if (ret) - goto out; + return ret; /* Settings for GPIO command */ st->gpio_cmd_settings_bitmask = 0x0; st->single_tx = TI_ADS7950_GPIO_CMD_SETTINGS(st); - ret = spi_sync(st->spi, &st->scan_single_msg); - -out: - mutex_unlock(&st->slock); - - return ret; + return spi_sync(st->spi, &st->scan_single_msg); } static int ti_ads7950_probe(struct spi_device *spi) @@ -541,10 +515,8 @@ static int ti_ads7950_probe(struct spi_device *spi) spi->bits_per_word = 16; spi->mode |= SPI_CS_WORD; ret = spi_setup(spi); - if (ret < 0) { - dev_err(&spi->dev, "Error in spi setup\n"); - return ret; - } + if (ret) + return dev_err_probe(&spi->dev, ret, "Error in spi setup\n"); indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) @@ -552,8 +524,6 @@ static int ti_ads7950_probe(struct spi_device *spi) st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - st->spi = spi; info = spi_get_device_match_data(spi); @@ -594,43 +564,38 @@ static int ti_ads7950_probe(struct spi_device *spi) spi_message_init_with_transfers(&st->scan_single_msg, st->scan_single_xfer, 3); + ret = devm_mutex_init(&spi->dev, &st->slock); + if (ret) + return ret; + /* Use hard coded value for reference voltage in ACPI case */ - if (ACPI_COMPANION(&spi->dev)) + if (ACPI_COMPANION(&spi->dev)) { st->vref_mv = TI_ADS7950_VA_MV_ACPI_DEFAULT; + } else { + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "Failed to get regulator \"vref\"\n"); - mutex_init(&st->slock); - - st->reg = devm_regulator_get(&spi->dev, "vref"); - if (IS_ERR(st->reg)) { - ret = dev_err_probe(&spi->dev, PTR_ERR(st->reg), - "Failed to get regulator \"vref\"\n"); - goto error_destroy_mutex; + st->vref_mv = ret / 1000; } - ret = regulator_enable(st->reg); - if (ret) { - dev_err(&spi->dev, "Failed to enable regulator \"vref\"\n"); - goto error_destroy_mutex; - } - - ret = iio_triggered_buffer_setup(indio_dev, NULL, - &ti_ads7950_trigger_handler, NULL); - if (ret) { - dev_err(&spi->dev, "Failed to setup triggered buffer\n"); - goto error_disable_reg; - } + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + &ti_ads7950_trigger_handler, + &ti_ads7950_buffer_setup_ops); + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to setup triggered buffer\n"); ret = ti_ads7950_init_hw(st); - if (ret) { - dev_err(&spi->dev, "Failed to init adc chip\n"); - goto error_cleanup_ring; - } + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to init adc chip\n"); - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device\n"); - goto error_cleanup_ring; - } + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to register iio device\n"); /* Add GPIO chip */ st->chip.label = dev_name(&st->spi->dev); @@ -645,36 +610,12 @@ static int ti_ads7950_probe(struct spi_device *spi) st->chip.get = ti_ads7950_get; st->chip.set = ti_ads7950_set; - ret = gpiochip_add_data(&st->chip, st); - if (ret) { - dev_err(&spi->dev, "Failed to init GPIOs\n"); - goto error_iio_device; - } + ret = devm_gpiochip_add_data(&spi->dev, &st->chip, st); + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to init GPIOs\n"); return 0; - -error_iio_device: - iio_device_unregister(indio_dev); -error_cleanup_ring: - iio_triggered_buffer_cleanup(indio_dev); -error_disable_reg: - regulator_disable(st->reg); -error_destroy_mutex: - mutex_destroy(&st->slock); - - return ret; -} - -static void ti_ads7950_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ti_ads7950_state *st = iio_priv(indio_dev); - - gpiochip_remove(&st->chip); - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - regulator_disable(st->reg); - mutex_destroy(&st->slock); } static const struct spi_device_id ti_ads7950_id[] = { @@ -717,7 +658,6 @@ static struct spi_driver ti_ads7950_driver = { .of_match_table = ads7950_of_table, }, .probe = ti_ads7950_probe, - .remove = ti_ads7950_remove, .id_table = ti_ads7950_id, }; module_spi_driver(ti_ads7950_driver); diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index b0bf46cae0b6..ebd2826a7ff6 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -17,7 +16,6 @@ #include #include #include -#include #define ADS8688_CMD_REG(x) (x << 8) #define ADS8688_CMD_REG_NOOP 0x00 @@ -66,6 +64,7 @@ struct ads8688_state { const struct ads8688_chip_info *chip_info; struct spi_device *spi; unsigned int vref_mv; + int scale_avail[3][2]; enum ads8688_range range[8]; union { __be32 d32; @@ -114,37 +113,9 @@ static const struct ads8688_ranges ads8688_range_def[5] = { } }; -static ssize_t ads8688_show_scales(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ads8688_state *st = iio_priv(dev_to_iio_dev(dev)); - - return sprintf(buf, "0.%09u 0.%09u 0.%09u\n", - ads8688_range_def[0].scale * st->vref_mv, - ads8688_range_def[1].scale * st->vref_mv, - ads8688_range_def[2].scale * st->vref_mv); -} - -static ssize_t ads8688_show_offsets(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d %d\n", ads8688_range_def[0].offset, - ads8688_range_def[3].offset); -} - -static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, - ads8688_show_scales, NULL, 0); -static IIO_DEVICE_ATTR(in_voltage_offset_available, S_IRUGO, - ads8688_show_offsets, NULL, 0); - -static struct attribute *ads8688_attributes[] = { - &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, - &iio_dev_attr_in_voltage_offset_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ads8688_attribute_group = { - .attrs = ads8688_attributes, +static const int ads8688_offset_avail[] = { + -(1 << (ADS8688_REALBITS - 1)), + 0 }; #define ADS8688_CHAN(index) \ @@ -155,6 +126,9 @@ static const struct attribute_group ads8688_attribute_group = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ | BIT(IIO_CHAN_INFO_SCALE) \ | BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_OFFSET), \ .scan_index = index, \ .scan_type = { \ .sign = 'u', \ @@ -369,11 +343,34 @@ static int ads8688_write_raw_get_fmt(struct iio_dev *indio_dev, return -EINVAL; } +static int ads8688_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct ads8688_state *st = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = (const int *)st->scale_avail; + *type = IIO_VAL_INT_PLUS_NANO; + *length = ARRAY_SIZE(st->scale_avail) * 2; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_OFFSET: + *vals = ads8688_offset_avail; + *type = IIO_VAL_INT; + *length = ARRAY_SIZE(ads8688_offset_avail); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + static const struct iio_info ads8688_info = { .read_raw = &ads8688_read_raw, + .read_avail = &ads8688_read_avail, .write_raw = &ads8688_write_raw, .write_raw_get_fmt = &ads8688_write_raw_get_fmt, - .attrs = &ads8688_attribute_group, }; static irqreturn_t ads8688_trigger_handler(int irq, void *p) @@ -426,6 +423,11 @@ static int ads8688_probe(struct spi_device *spi) st->vref_mv = ret == -ENODEV ? ADS8688_VREF_MV : ret / 1000; + for (unsigned int i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { + st->scale_avail[i][0] = 0; + st->scale_avail[i][1] = ads8688_range_def[i].scale * st->vref_mv; + } + st->chip_info = &ads8688_chip_info_tbl[spi_get_device_id(spi)->driver_data]; spi->mode = SPI_MODE_1; diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c index 124470c92529..d38c4401dfce 100644 --- a/drivers/iio/adc/xilinx-ams.c +++ b/drivers/iio/adc/xilinx-ams.c @@ -102,6 +102,7 @@ #define AMS_PS_SEQ_MASK GENMASK(21, 0) #define AMS_PL_SEQ_MASK GENMASK_ULL(59, 22) +#define AMS_ALARM_NONE 0x000 /* not a real offset */ #define AMS_ALARM_TEMP 0x140 #define AMS_ALARM_SUPPLY1 0x144 #define AMS_ALARM_SUPPLY2 0x148 @@ -720,22 +721,20 @@ static int ams_read_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&ams->lock); + case IIO_CHAN_INFO_RAW: { + guard(mutex)(&ams->lock); if (chan->scan_index >= AMS_CTRL_SEQ_BASE) { ret = ams_read_vcc_reg(ams, chan->address, val); if (ret) - goto unlock_mutex; + return ret; ams_enable_channel_sequence(indio_dev); } else if (chan->scan_index >= AMS_PS_SEQ_MAX) *val = readl(ams->pl_base + chan->address); else *val = readl(ams->ps_base + chan->address); - ret = IIO_VAL_INT; -unlock_mutex: - mutex_unlock(&ams->lock); - return ret; + return IIO_VAL_INT; + } case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: @@ -765,9 +764,49 @@ static int ams_read_raw(struct iio_dev *indio_dev, } } +struct ams_alarm_map { + enum ams_ps_pl_seq scan_index; + unsigned int base_offset; +}; + +/* + * Array index matches enum ams_alarm_bit. + * Entries with base_offset == AMS_ALARM_NONE are unused/invalid + * (e.g. RESERVED) and must be skipped. + */ +static const struct ams_alarm_map alarm_map[] = { + [AMS_ALARM_BIT_TEMP] = { AMS_SEQ_TEMP, AMS_ALARM_TEMP }, + [AMS_ALARM_BIT_SUPPLY1] = { AMS_SEQ_SUPPLY1, AMS_ALARM_SUPPLY1 }, + [AMS_ALARM_BIT_SUPPLY2] = { AMS_SEQ_SUPPLY2, AMS_ALARM_SUPPLY2 }, + [AMS_ALARM_BIT_SUPPLY3] = { AMS_SEQ_SUPPLY3, AMS_ALARM_SUPPLY3 }, + [AMS_ALARM_BIT_SUPPLY4] = { AMS_SEQ_SUPPLY4, AMS_ALARM_SUPPLY4 }, + [AMS_ALARM_BIT_SUPPLY5] = { AMS_SEQ_SUPPLY5, AMS_ALARM_SUPPLY5 }, + [AMS_ALARM_BIT_SUPPLY6] = { AMS_SEQ_SUPPLY6, AMS_ALARM_SUPPLY6 }, + [AMS_ALARM_BIT_RESERVED] = { 0, AMS_ALARM_NONE }, + [AMS_ALARM_BIT_SUPPLY7] = { AMS_SEQ_SUPPLY7, AMS_ALARM_SUPPLY7 }, + [AMS_ALARM_BIT_SUPPLY8] = { AMS_SEQ_SUPPLY8, AMS_ALARM_SUPPLY8 }, + [AMS_ALARM_BIT_SUPPLY9] = { AMS_SEQ_SUPPLY9, AMS_ALARM_SUPPLY9 }, + [AMS_ALARM_BIT_SUPPLY10] = { AMS_SEQ_SUPPLY10, AMS_ALARM_SUPPLY10 }, + [AMS_ALARM_BIT_VCCAMS] = { AMS_SEQ_VCCAMS, AMS_ALARM_VCCAMS }, + [AMS_ALARM_BIT_TEMP_REMOTE] = { AMS_SEQ_TEMP_REMOTE, AMS_ALARM_TEMP_REMOTE }, +}; + +static int ams_scan_index_to_event(int scan_index) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(alarm_map); i++) { + if (alarm_map[i].base_offset == AMS_ALARM_NONE) + continue; + + if (alarm_map[i].scan_index == scan_index) + return i; + } + + return -EINVAL; +} + static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir) { - int offset; + int offset, event; if (scan_index >= AMS_PS_SEQ_MAX) scan_index -= AMS_PS_SEQ_MAX; @@ -781,36 +820,11 @@ static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir) offset = 0; } - switch (scan_index) { - case AMS_SEQ_TEMP: - return AMS_ALARM_TEMP + offset; - case AMS_SEQ_SUPPLY1: - return AMS_ALARM_SUPPLY1 + offset; - case AMS_SEQ_SUPPLY2: - return AMS_ALARM_SUPPLY2 + offset; - case AMS_SEQ_SUPPLY3: - return AMS_ALARM_SUPPLY3 + offset; - case AMS_SEQ_SUPPLY4: - return AMS_ALARM_SUPPLY4 + offset; - case AMS_SEQ_SUPPLY5: - return AMS_ALARM_SUPPLY5 + offset; - case AMS_SEQ_SUPPLY6: - return AMS_ALARM_SUPPLY6 + offset; - case AMS_SEQ_SUPPLY7: - return AMS_ALARM_SUPPLY7 + offset; - case AMS_SEQ_SUPPLY8: - return AMS_ALARM_SUPPLY8 + offset; - case AMS_SEQ_SUPPLY9: - return AMS_ALARM_SUPPLY9 + offset; - case AMS_SEQ_SUPPLY10: - return AMS_ALARM_SUPPLY10 + offset; - case AMS_SEQ_VCCAMS: - return AMS_ALARM_VCCAMS + offset; - case AMS_SEQ_TEMP_REMOTE: - return AMS_ALARM_TEMP_REMOTE + offset; - default: + event = ams_scan_index_to_event(scan_index); + if (event < 0 || alarm_map[event].base_offset == AMS_ALARM_NONE) return 0; - } + + return alarm_map[event].base_offset + offset; } static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev, @@ -823,96 +837,38 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev, scan_index = AMS_PS_SEQ_MAX; } - switch (event) { - case AMS_ALARM_BIT_TEMP: - scan_index += AMS_SEQ_TEMP; - break; - case AMS_ALARM_BIT_SUPPLY1: - scan_index += AMS_SEQ_SUPPLY1; - break; - case AMS_ALARM_BIT_SUPPLY2: - scan_index += AMS_SEQ_SUPPLY2; - break; - case AMS_ALARM_BIT_SUPPLY3: - scan_index += AMS_SEQ_SUPPLY3; - break; - case AMS_ALARM_BIT_SUPPLY4: - scan_index += AMS_SEQ_SUPPLY4; - break; - case AMS_ALARM_BIT_SUPPLY5: - scan_index += AMS_SEQ_SUPPLY5; - break; - case AMS_ALARM_BIT_SUPPLY6: - scan_index += AMS_SEQ_SUPPLY6; - break; - case AMS_ALARM_BIT_SUPPLY7: - scan_index += AMS_SEQ_SUPPLY7; - break; - case AMS_ALARM_BIT_SUPPLY8: - scan_index += AMS_SEQ_SUPPLY8; - break; - case AMS_ALARM_BIT_SUPPLY9: - scan_index += AMS_SEQ_SUPPLY9; - break; - case AMS_ALARM_BIT_SUPPLY10: - scan_index += AMS_SEQ_SUPPLY10; - break; - case AMS_ALARM_BIT_VCCAMS: - scan_index += AMS_SEQ_VCCAMS; - break; - case AMS_ALARM_BIT_TEMP_REMOTE: - scan_index += AMS_SEQ_TEMP_REMOTE; - break; - default: - break; - } + if (event >= ARRAY_SIZE(alarm_map)) + return NULL; + + if (alarm_map[event].base_offset == AMS_ALARM_NONE) + return NULL; + + scan_index += alarm_map[event].scan_index; for (i = 0; i < dev->num_channels; i++) if (dev->channels[i].scan_index == scan_index) break; + if (i == dev->num_channels) + return NULL; + return &dev->channels[i]; } static int ams_get_alarm_mask(int scan_index) { - int bit = 0; + int bit = 0, event; if (scan_index >= AMS_PS_SEQ_MAX) { bit = AMS_PL_ALARM_START; scan_index -= AMS_PS_SEQ_MAX; } - switch (scan_index) { - case AMS_SEQ_TEMP: - return BIT(AMS_ALARM_BIT_TEMP + bit); - case AMS_SEQ_SUPPLY1: - return BIT(AMS_ALARM_BIT_SUPPLY1 + bit); - case AMS_SEQ_SUPPLY2: - return BIT(AMS_ALARM_BIT_SUPPLY2 + bit); - case AMS_SEQ_SUPPLY3: - return BIT(AMS_ALARM_BIT_SUPPLY3 + bit); - case AMS_SEQ_SUPPLY4: - return BIT(AMS_ALARM_BIT_SUPPLY4 + bit); - case AMS_SEQ_SUPPLY5: - return BIT(AMS_ALARM_BIT_SUPPLY5 + bit); - case AMS_SEQ_SUPPLY6: - return BIT(AMS_ALARM_BIT_SUPPLY6 + bit); - case AMS_SEQ_SUPPLY7: - return BIT(AMS_ALARM_BIT_SUPPLY7 + bit); - case AMS_SEQ_SUPPLY8: - return BIT(AMS_ALARM_BIT_SUPPLY8 + bit); - case AMS_SEQ_SUPPLY9: - return BIT(AMS_ALARM_BIT_SUPPLY9 + bit); - case AMS_SEQ_SUPPLY10: - return BIT(AMS_ALARM_BIT_SUPPLY10 + bit); - case AMS_SEQ_VCCAMS: - return BIT(AMS_ALARM_BIT_VCCAMS + bit); - case AMS_SEQ_TEMP_REMOTE: - return BIT(AMS_ALARM_BIT_TEMP_REMOTE + bit); - default: + event = ams_scan_index_to_event(scan_index); + if (event < 0) return 0; - } + + return BIT(event + bit); } static int ams_read_event_config(struct iio_dev *indio_dev, @@ -936,7 +892,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev, alarm = ams_get_alarm_mask(chan->scan_index); - mutex_lock(&ams->lock); + guard(mutex)(&ams->lock); if (state) ams->alarm_mask |= alarm; @@ -945,8 +901,6 @@ static int ams_write_event_config(struct iio_dev *indio_dev, ams_update_alarm(ams, ams->alarm_mask); - mutex_unlock(&ams->lock); - return 0; } @@ -959,15 +913,13 @@ static int ams_read_event_value(struct iio_dev *indio_dev, struct ams *ams = iio_priv(indio_dev); unsigned int offset = ams_get_alarm_offset(chan->scan_index, dir); - mutex_lock(&ams->lock); + guard(mutex)(&ams->lock); if (chan->scan_index >= AMS_PS_SEQ_MAX) *val = readl(ams->pl_base + offset); else *val = readl(ams->ps_base + offset); - mutex_unlock(&ams->lock); - return IIO_VAL_INT; } @@ -980,7 +932,7 @@ static int ams_write_event_value(struct iio_dev *indio_dev, struct ams *ams = iio_priv(indio_dev); unsigned int offset; - mutex_lock(&ams->lock); + guard(mutex)(&ams->lock); /* Set temperature channel threshold to direct threshold */ if (chan->type == IIO_TEMP) { @@ -1002,8 +954,6 @@ static int ams_write_event_value(struct iio_dev *indio_dev, else writel(val, ams->ps_base + offset); - mutex_unlock(&ams->lock); - return 0; } @@ -1012,6 +962,8 @@ static void ams_handle_event(struct iio_dev *indio_dev, u32 event) const struct iio_chan_spec *chan; chan = ams_event_to_channel(indio_dev, event); + if (!chan) + return; if (chan->type == IIO_TEMP) { /* diff --git a/drivers/iio/addac/ad74115.c b/drivers/iio/addac/ad74115.c index f8b04d86b01f..41e0b1d334cc 100644 --- a/drivers/iio/addac/ad74115.c +++ b/drivers/iio/addac/ad74115.c @@ -1835,7 +1835,10 @@ static int ad74115_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->spi = spi; - mutex_init(&st->lock); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + init_completion(&st->adc_data_completion); indio_dev->name = AD74115_NAME; diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c index 700528c9a0a4..10e912bbf0c5 100644 --- a/drivers/iio/buffer/industrialio-hw-consumer.c +++ b/drivers/iio/buffer/industrialio-hw-consumer.c @@ -40,6 +40,8 @@ static void iio_hw_buf_release(struct iio_buffer *buffer) { struct hw_consumer_buffer *hw_buf = iio_buffer_to_hw_consumer_buffer(buffer); + + bitmap_free(buffer->scan_mask); kfree(hw_buf); } diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c index 8106a6a83561..cb9fff3bd67f 100644 --- a/drivers/iio/cdc/ad7150.c +++ b/drivers/iio/cdc/ad7150.c @@ -628,9 +628,9 @@ static int ad7150_probe(struct i2c_client *client) } static const struct i2c_device_id ad7150_id[] = { - { "ad7150", AD7150 }, - { "ad7151", AD7151 }, - { "ad7156", AD7150 }, + { .name = "ad7150", .driver_data = AD7150 }, + { .name = "ad7151", .driver_data = AD7151 }, + { .name = "ad7156", .driver_data = AD7150 }, { } }; diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c index cb97e3c978d8..cf68b882bc49 100644 --- a/drivers/iio/cdc/ad7746.c +++ b/drivers/iio/cdc/ad7746.c @@ -789,9 +789,9 @@ static int ad7746_probe(struct i2c_client *client) } static const struct i2c_device_id ad7746_id[] = { - { "ad7745", 7745 }, - { "ad7746", 7746 }, - { "ad7747", 7747 }, + { .name = "ad7745", .driver_data = 7745 }, + { .name = "ad7746", .driver_data = 7746 }, + { .name = "ad7747", .driver_data = 7747 }, { } }; MODULE_DEVICE_TABLE(i2c, ad7746_id); diff --git a/drivers/iio/chemical/ags02ma.c b/drivers/iio/chemical/ags02ma.c index 151178d4e8f4..8b97ea4a9515 100644 --- a/drivers/iio/chemical/ags02ma.c +++ b/drivers/iio/chemical/ags02ma.c @@ -139,7 +139,7 @@ static int ags02ma_probe(struct i2c_client *client) } static const struct i2c_device_id ags02ma_id_table[] = { - { "ags02ma" }, + { .name = "ags02ma" }, { } }; MODULE_DEVICE_TABLE(i2c, ags02ma_id_table); diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c index 10156d794092..7aa7841c530e 100644 --- a/drivers/iio/chemical/ams-iaq-core.c +++ b/drivers/iio/chemical/ams-iaq-core.c @@ -163,7 +163,7 @@ static int ams_iaqcore_probe(struct i2c_client *client) } static const struct i2c_device_id ams_iaqcore_id[] = { - { "ams-iaq-core" }, + { .name = "ams-iaq-core" }, { } }; MODULE_DEVICE_TABLE(i2c, ams_iaqcore_id); diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c index 59f3a4fa9e9f..05da3b8a92ab 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -186,9 +186,9 @@ static const struct iio_info atlas_info = { }; static const struct i2c_device_id atlas_ezo_id[] = { - { "atlas-co2-ezo", (kernel_ulong_t)&atlas_ezo_devices[ATLAS_CO2_EZO] }, - { "atlas-o2-ezo", (kernel_ulong_t)&atlas_ezo_devices[ATLAS_O2_EZO] }, - { "atlas-hum-ezo", (kernel_ulong_t)&atlas_ezo_devices[ATLAS_HUM_EZO] }, + { .name = "atlas-co2-ezo", .driver_data = (kernel_ulong_t)&atlas_ezo_devices[ATLAS_CO2_EZO] }, + { .name = "atlas-o2-ezo", .driver_data = (kernel_ulong_t)&atlas_ezo_devices[ATLAS_O2_EZO] }, + { .name = "atlas-hum-ezo", .driver_data = (kernel_ulong_t)&atlas_ezo_devices[ATLAS_HUM_EZO] }, { } }; MODULE_DEVICE_TABLE(i2c, atlas_ezo_id); diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 8bbba85af699..0e2edcff63f9 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -586,11 +586,11 @@ static const struct iio_info atlas_info = { }; static const struct i2c_device_id atlas_id[] = { - { "atlas-ph-sm", (kernel_ulong_t)&atlas_devices[ATLAS_PH_SM] }, - { "atlas-ec-sm", (kernel_ulong_t)&atlas_devices[ATLAS_EC_SM] }, - { "atlas-orp-sm", (kernel_ulong_t)&atlas_devices[ATLAS_ORP_SM] }, - { "atlas-do-sm", (kernel_ulong_t)&atlas_devices[ATLAS_DO_SM] }, - { "atlas-rtd-sm", (kernel_ulong_t)&atlas_devices[ATLAS_RTD_SM] }, + { .name = "atlas-ph-sm", .driver_data = (kernel_ulong_t)&atlas_devices[ATLAS_PH_SM] }, + { .name = "atlas-ec-sm", .driver_data = (kernel_ulong_t)&atlas_devices[ATLAS_EC_SM] }, + { .name = "atlas-orp-sm", .driver_data = (kernel_ulong_t)&atlas_devices[ATLAS_ORP_SM] }, + { .name = "atlas-do-sm", .driver_data = (kernel_ulong_t)&atlas_devices[ATLAS_DO_SM] }, + { .name = "atlas-rtd-sm", .driver_data = (kernel_ulong_t)&atlas_devices[ATLAS_RTD_SM] }, { } }; MODULE_DEVICE_TABLE(i2c, atlas_id); diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c index 6aeac132394c..ac9a737481dc 100644 --- a/drivers/iio/chemical/bme680_core.c +++ b/drivers/iio/chemical/bme680_core.c @@ -128,7 +128,7 @@ struct bme680_data { u16 heater_temp; struct { - s32 chan[4]; + s32 chan[BME680_NUM_CHANNELS]; aligned_s64 ts; } scan; diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c index 5560ea708b36..4cc0e491621a 100644 --- a/drivers/iio/chemical/bme680_i2c.c +++ b/drivers/iio/chemical/bme680_i2c.c @@ -36,7 +36,7 @@ static int bme680_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bme680_i2c_id[] = { - { "bme680" }, + { .name = "bme680" }, { } }; MODULE_DEVICE_TABLE(i2c, bme680_i2c_id); diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 998c9239c4c7..ce7187ccd706 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -552,8 +552,8 @@ static void ccs811_remove(struct i2c_client *client) } static const struct i2c_device_id ccs811_id[] = { - { "ccs811" }, - { } + { .name = "ccs811" }, + { } }; MODULE_DEVICE_TABLE(i2c, ccs811_id); diff --git a/drivers/iio/chemical/ens160_i2c.c b/drivers/iio/chemical/ens160_i2c.c index aa0dfe639245..ab0e8dcce011 100644 --- a/drivers/iio/chemical/ens160_i2c.c +++ b/drivers/iio/chemical/ens160_i2c.c @@ -34,7 +34,7 @@ static int ens160_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ens160_i2c_id[] = { - { "ens160" }, + { .name = "ens160" }, { } }; MODULE_DEVICE_TABLE(i2c, ens160_i2c_id); diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c index 11d6bc1b63e6..c5425136814b 100644 --- a/drivers/iio/chemical/scd30_core.c +++ b/drivers/iio/chemical/scd30_core.c @@ -4,6 +4,8 @@ * * Copyright (c) 2020 Tomasz Duszynski */ + +#include #include #include #include @@ -43,6 +45,11 @@ #define SCD30_TEMP_OFFSET_MAX 655360 #define SCD30_EXTRA_TIMEOUT_PER_S 250 +/* Floating point arithmetic macros */ +#define SCD30_FLOAT_MANTISSA_MSK GENMASK(22, 0) +#define SCD30_FLOAT_EXP_MSK GENMASK(30, 23) +#define SCD30_FLOAT_SIGN_MSK BIT(31) + enum { SCD30_CONC, SCD30_TEMP, @@ -89,10 +96,14 @@ static int scd30_reset(struct scd30_state *state) /* simplified float to fixed point conversion with a scaling factor of 0.01 */ static int scd30_float_to_fp(int float32) { - int fraction, shift, - mantissa = float32 & GENMASK(22, 0), - sign = (float32 & BIT(31)) ? -1 : 1, - exp = (float32 & ~BIT(31)) >> 23; + int fraction, shift, sign; + int mantissa = FIELD_GET(SCD30_FLOAT_MANTISSA_MSK, float32); + int exp = FIELD_GET(SCD30_FLOAT_EXP_MSK, float32); + + if (float32 & SCD30_FLOAT_SIGN_MSK) + sign = -1; + else + sign = 1; /* special case 0 */ if (!exp && !mantissa) @@ -368,11 +379,13 @@ static ssize_t calibration_auto_enable_show(struct device *dev, struct device_at int ret; u16 val; - mutex_lock(&state->lock); - ret = scd30_command_read(state, CMD_ASC, &val); - mutex_unlock(&state->lock); + guard(mutex)(&state->lock); - return ret ?: sysfs_emit(buf, "%d\n", val); + ret = scd30_command_read(state, CMD_ASC, &val); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", val); } static ssize_t calibration_auto_enable_store(struct device *dev, struct device_attribute *attr, @@ -387,11 +400,13 @@ static ssize_t calibration_auto_enable_store(struct device *dev, struct device_a if (ret) return ret; - mutex_lock(&state->lock); - ret = scd30_command_write(state, CMD_ASC, val); - mutex_unlock(&state->lock); + guard(mutex)(&state->lock); - return ret ?: len; + ret = scd30_command_write(state, CMD_ASC, val); + if (ret) + return ret; + + return len; } static ssize_t calibration_forced_value_show(struct device *dev, struct device_attribute *attr, @@ -402,11 +417,13 @@ static ssize_t calibration_forced_value_show(struct device *dev, struct device_a int ret; u16 val; - mutex_lock(&state->lock); - ret = scd30_command_read(state, CMD_FRC, &val); - mutex_unlock(&state->lock); + guard(mutex)(&state->lock); - return ret ?: sysfs_emit(buf, "%d\n", val); + ret = scd30_command_read(state, CMD_FRC, &val); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", val); } static ssize_t calibration_forced_value_store(struct device *dev, struct device_attribute *attr, @@ -424,11 +441,13 @@ static ssize_t calibration_forced_value_store(struct device *dev, struct device_ if (val < SCD30_FRC_MIN_PPM || val > SCD30_FRC_MAX_PPM) return -EINVAL; - mutex_lock(&state->lock); - ret = scd30_command_write(state, CMD_FRC, val); - mutex_unlock(&state->lock); + guard(mutex)(&state->lock); - return ret ?: len; + ret = scd30_command_write(state, CMD_FRC, val); + if (ret) + return ret; + + return len; } static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0); @@ -579,24 +598,34 @@ static irqreturn_t scd30_irq_thread_handler(int irq, void *priv) return IRQ_HANDLED; } +static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data, + size_t scan_data_size) +{ + struct scd30_state *state = iio_priv(indio_dev); + int ret; + + guard(mutex)(&state->lock); + + if (!iio_trigger_using_own(indio_dev)) + ret = scd30_read_poll(state); + else + ret = scd30_read_meas(state); + memcpy(scan_data, state->meas, scan_data_size); + + return ret; +} + static irqreturn_t scd30_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct scd30_state *state = iio_priv(indio_dev); struct { int data[SCD30_MEAS_COUNT]; aligned_s64 ts; } scan = { }; int ret; - mutex_lock(&state->lock); - if (!iio_trigger_using_own(indio_dev)) - ret = scd30_read_poll(state); - else - ret = scd30_read_meas(state); - memcpy(scan.data, state->meas, sizeof(state->meas)); - mutex_unlock(&state->lock); + ret = scd30_trigger_handler_helper(indio_dev, scan.data, sizeof(scan.data)); if (ret) goto out; diff --git a/drivers/iio/chemical/scd30_i2c.c b/drivers/iio/chemical/scd30_i2c.c index 436df9c61a71..9e841f565149 100644 --- a/drivers/iio/chemical/scd30_i2c.c +++ b/drivers/iio/chemical/scd30_i2c.c @@ -20,7 +20,7 @@ #define SCD30_I2C_MAX_BUF_SIZE 18 #define SCD30_I2C_CRC8_POLYNOMIAL 0x31 -static u16 scd30_i2c_cmd_lookup_tbl[] = { +static const u16 scd30_i2c_cmd_lookup_tbl[] = { [CMD_START_MEAS] = 0x0010, [CMD_STOP_MEAS] = 0x0104, [CMD_MEAS_INTERVAL] = 0x4600, @@ -71,6 +71,9 @@ static int scd30_i2c_command(struct scd30_state *state, enum scd30_cmd cmd, u16 int i, ret; char crc; + if (!response && size != 0) + return -EINVAL; + put_unaligned_be16(scd30_i2c_cmd_lookup_tbl[cmd], buf); i = 2; diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index 21730d62b5c8..8b88be85602c 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -498,6 +498,7 @@ static const struct of_device_id sgp_dt_ids[] = { { .compatible = "sensirion,sgpc3", .data = &sgp_devices[SGPC3] }, { } }; +MODULE_DEVICE_TABLE(of, sgp_dt_ids); static int sgp_probe(struct i2c_client *client) { @@ -562,13 +563,11 @@ static void sgp_remove(struct i2c_client *client) } static const struct i2c_device_id sgp_id[] = { - { "sgp30", (kernel_ulong_t)&sgp_devices[SGP30] }, - { "sgpc3", (kernel_ulong_t)&sgp_devices[SGPC3] }, + { .name = "sgp30", .driver_data = (kernel_ulong_t)&sgp_devices[SGP30] }, + { .name = "sgpc3", .driver_data = (kernel_ulong_t)&sgp_devices[SGPC3] }, { } }; - MODULE_DEVICE_TABLE(i2c, sgp_id); -MODULE_DEVICE_TABLE(of, sgp_dt_ids); static struct i2c_driver sgp_driver = { .driver = { diff --git a/drivers/iio/chemical/sgp40.c b/drivers/iio/chemical/sgp40.c index 07d8ab830211..b2b5e32a9eb2 100644 --- a/drivers/iio/chemical/sgp40.c +++ b/drivers/iio/chemical/sgp40.c @@ -355,7 +355,7 @@ static int sgp40_probe(struct i2c_client *client) } static const struct i2c_device_id sgp40_id[] = { - { "sgp40" }, + { .name = "sgp40" }, { } }; diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c index a934bf0298dd..8e15baa31423 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -5,6 +5,7 @@ * Copyright (c) Tomasz Duszynski */ +#include #include #include #include @@ -69,6 +70,8 @@ static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) { int i, ret; + guard(mutex)(&state->lock); + if (state->state == RESET) { ret = state->ops->start_meas(state); if (ret) @@ -111,9 +114,7 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p) aligned_s64 ts; } scan; - mutex_lock(&state->lock); ret = sps30_do_meas(state, scan.data, ARRAY_SIZE(scan.data)); - mutex_unlock(&state->lock); if (ret) goto err; @@ -136,7 +137,6 @@ static int sps30_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_MASSCONCENTRATION: - mutex_lock(&state->lock); /* read up to the number of bytes actually needed */ switch (chan->channel2) { case IIO_MOD_PM1: @@ -152,7 +152,6 @@ static int sps30_read_raw(struct iio_dev *indio_dev, ret = sps30_do_meas(state, data, 4); break; } - mutex_unlock(&state->lock); if (ret) return ret; @@ -197,9 +196,9 @@ static ssize_t start_cleaning_store(struct device *dev, if (kstrtoint(buf, 0, &val) || val != 1) return -EINVAL; - mutex_lock(&state->lock); + guard(mutex)(&state->lock); + ret = state->ops->clean_fan(state); - mutex_unlock(&state->lock); if (ret) return ret; @@ -215,9 +214,9 @@ static ssize_t cleaning_period_show(struct device *dev, __be32 val; int ret; - mutex_lock(&state->lock); + guard(mutex)(&state->lock); + ret = state->ops->read_cleaning_period(state, &val); - mutex_unlock(&state->lock); if (ret) return ret; @@ -238,12 +237,11 @@ static ssize_t cleaning_period_store(struct device *dev, struct device_attribute (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) return -EINVAL; - mutex_lock(&state->lock); + guard(mutex)(&state->lock); + ret = state->ops->write_cleaning_period(state, cpu_to_be32(val)); - if (ret) { - mutex_unlock(&state->lock); + if (ret) return ret; - } msleep(20); @@ -256,8 +254,6 @@ static ssize_t cleaning_period_store(struct device *dev, struct device_attribute dev_warn(dev, "period changed but reads will return the old value\n"); - mutex_unlock(&state->lock); - return len; } diff --git a/drivers/iio/chemical/sps30_i2c.c b/drivers/iio/chemical/sps30_i2c.c index c92f04990c34..61781aaabd85 100644 --- a/drivers/iio/chemical/sps30_i2c.c +++ b/drivers/iio/chemical/sps30_i2c.c @@ -232,7 +232,7 @@ static int sps30_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id sps30_i2c_id[] = { - { "sps30" }, + { .name = "sps30" }, { } }; MODULE_DEVICE_TABLE(i2c, sps30_i2c_id); diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 5b358bcd311b..4deacf10b6ef 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -385,8 +385,8 @@ static int vz89x_probe(struct i2c_client *client) } static const struct i2c_device_id vz89x_id[] = { - { "vz89x", (kernel_ulong_t)&vz89x_chips[VZ89X] }, - { "vz89te", (kernel_ulong_t)&vz89x_chips[VZ89TE] }, + { .name = "vz89x", .driver_data = (kernel_ulong_t)&vz89x_chips[VZ89X] }, + { .name = "vz89te", .driver_data = (kernel_ulong_t)&vz89x_chips[VZ89TE] }, { } }; MODULE_DEVICE_TABLE(i2c, vz89x_id); diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c index 6e38d115b6fe..6762685e6876 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c @@ -279,13 +279,7 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) channel++; } - /* Timestamp */ - channel->scan_index = index; - channel->type = IIO_TIMESTAMP; - channel->channel = -1; - channel->scan_type.sign = 's'; - channel->scan_type.realbits = 64; - channel->scan_type.storagebits = 64; + *channel = IIO_CHAN_SOFT_TIMESTAMP(index); indio_dev->channels = st->channels; indio_dev->num_channels = index + 1; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index f34e2bbba2d1..651632ccfe0d 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -279,13 +279,7 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) } } - /* Timestamp */ - channel->type = IIO_TIMESTAMP; - channel->channel = -1; - channel->scan_index = CROS_EC_SENSOR_MAX_AXIS; - channel->scan_type.sign = 's'; - channel->scan_type.realbits = 64; - channel->scan_type.storagebits = 64; + *channel = IIO_CHAN_SOFT_TIMESTAMP(CROS_EC_SENSOR_MAX_AXIS); indio_dev->channels = state->channels; indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS; diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c index 5136ad9ada04..442b40ef27cf 100644 --- a/drivers/iio/common/scmi_sensors/scmi_iio.c +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c @@ -419,17 +419,6 @@ static const struct iio_chan_spec_ext_info scmi_iio_ext_info[] = { { } }; -static void scmi_iio_set_timestamp_channel(struct iio_chan_spec *iio_chan, - int scan_index) -{ - iio_chan->type = IIO_TIMESTAMP; - iio_chan->channel = -1; - iio_chan->scan_index = scan_index; - iio_chan->scan_type.sign = 'u'; - iio_chan->scan_type.realbits = 64; - iio_chan->scan_type.storagebits = 64; -} - static void scmi_iio_set_data_channel(struct iio_chan_spec *iio_chan, enum iio_chan_type type, enum iio_modifier mod, int scan_index) @@ -629,7 +618,7 @@ scmi_alloc_iiodev(struct scmi_device *sdev, "Error in registering sensor update notifier for sensor %s\n", sensor->sensor_info->name); - scmi_iio_set_timestamp_channel(&iio_channels[i], i); + iio_channels[i] = IIO_CHAN_SOFT_TIMESTAMP(i); iiodev->channels = iio_channels; return iiodev; } diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index e2538a84c812..51730dae5871 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -28,7 +28,7 @@ struct ssp_instruction { __le32 a; __le32 b; u8 c; -} __attribute__((__packed__)); +} __packed__; static const u8 ssp_magnitude_table[] = {110, 85, 171, 71, 203, 195, 0, 67, 208, 56, 175, 244, 206, 213, 0, 92, 250, 0, 55, 48, 189, 252, 171, diff --git a/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h b/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h index 4528ab55eb68..05fcad61c848 100644 --- a/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h +++ b/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h @@ -18,18 +18,6 @@ },\ } -/* It is defined here as it is a mixed timestamp */ -#define SSP_CHAN_TIMESTAMP(_si) { \ - .type = IIO_TIMESTAMP, \ - .channel = -1, \ - .scan_index = _si, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 64, \ - .storagebits = 64, \ - }, \ -} - #define SSP_MS_PER_S 1000 #define SSP_INVERTED_SCALING_FACTOR 1000000U diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c index 6c81c0385fb5..08ed92859be0 100644 --- a/drivers/iio/common/ssp_sensors/ssp_spi.c +++ b/drivers/iio/common/ssp_sensors/ssp_spi.c @@ -6,7 +6,7 @@ #include "ssp.h" #define SSP_DEV (&data->spi->dev) -#define SSP_GET_MESSAGE_TYPE(data) (data & (3 << SSP_RW)) +#define SSP_GET_MESSAGE_TYPE(data) ((data) & (3 << SSP_RW)) /* * SSP -> AP Instruction @@ -29,7 +29,7 @@ struct ssp_msg_header { __le16 length; __le16 options; __le32 data; -} __attribute__((__packed__)); +} __packed; struct ssp_msg { u16 length; @@ -119,9 +119,9 @@ static inline void ssp_get_buffer(struct ssp_msg *m, unsigned int offset, } #define SSP_GET_BUFFER_AT_INDEX(m, index) \ - (m->buffer[SSP_HEADER_SIZE_ALIGNED + index]) + ((m)->buffer[SSP_HEADER_SIZE_ALIGNED + (index)]) #define SSP_SET_BUFFER_AT_INDEX(m, index, val) \ - (m->buffer[SSP_HEADER_SIZE_ALIGNED + index] = val) + ((m)->buffer[SSP_HEADER_SIZE_ALIGNED + (index)] = val) static void ssp_clean_msg(struct ssp_msg *m) { diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index cd4870b65415..657c68e75542 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -178,6 +178,17 @@ config AD5624R_SPI Say yes here to build support for Analog Devices AD5624R, AD5644R and AD5664R converters (DAC). This driver uses the common SPI interface. +config AD5706R + tristate "Analog Devices AD5706R DAC driver" + depends on SPI + select REGMAP + help + Say yes here to build support for Analog Devices AD5706R 4-channel, + 16-bit current output DAC. + + To compile this driver as a module, choose M here: the + module will be called ad5706r. + config AD9739A tristate "Analog Devices AD9739A RF DAC spi driver" depends on SPI diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 2a80bbf4e80a..003431798498 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o obj-$(CONFIG_AD5592R) += ad5592r.o obj-$(CONFIG_AD5593R) += ad5593r.o +obj-$(CONFIG_AD5706R) += ad5706r.o obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5758) += ad5758.o obj-$(CONFIG_AD5761) += ad5761.o diff --git a/drivers/iio/dac/ad3552r-hs.c b/drivers/iio/dac/ad3552r-hs.c index a9578afa7015..6bc64f53bce9 100644 --- a/drivers/iio/dac/ad3552r-hs.c +++ b/drivers/iio/dac/ad3552r-hs.c @@ -549,7 +549,7 @@ static ssize_t ad3552r_hs_write_data_source(struct file *f, guard(mutex)(&st->lock); - if (count >= sizeof(buf)) + if (*ppos != 0 || count >= sizeof(buf)) return -ENOSPC; ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c index 93c33bc3e1be..16db94fef9d4 100644 --- a/drivers/iio/dac/ad3552r.c +++ b/drivers/iio/dac/ad3552r.c @@ -167,8 +167,7 @@ static int ad3552r_read_raw(struct iio_dev *indio_dev, mutex_unlock(&dac->lock); if (err < 0) return err; - *val = !((tmp_val & AD3552R_MASK_CH_DAC_POWERDOWN(ch)) >> - __ffs(AD3552R_MASK_CH_DAC_POWERDOWN(ch))); + *val = !field_get(AD3552R_MASK_CH_DAC_POWERDOWN(ch), tmp_val); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = dac->ch_data[ch].scale_int; @@ -629,7 +628,9 @@ static int ad3552r_probe(struct spi_device *spi) if (!dac->model_data) return -EINVAL; - mutex_init(&dac->lock); + err = devm_mutex_init(&spi->dev, &dac->lock); + if (err) + return err; err = ad3552r_init(dac); if (err) diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 84be5174babd..b5ec33f5c317 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -1001,53 +1001,53 @@ static int ad5064_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ad5064_i2c_ids[] = { - {"ad5625", ID_AD5625 }, - {"ad5625r-1v25", ID_AD5625R_1V25 }, - {"ad5625r-2v5", ID_AD5625R_2V5 }, - {"ad5627", ID_AD5627 }, - {"ad5627r-1v25", ID_AD5627R_1V25 }, - {"ad5627r-2v5", ID_AD5627R_2V5 }, - {"ad5629-1", ID_AD5629_1}, - {"ad5629-2", ID_AD5629_2}, - {"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */ - {"ad5645r-1v25", ID_AD5645R_1V25 }, - {"ad5645r-2v5", ID_AD5645R_2V5 }, - {"ad5665", ID_AD5665 }, - {"ad5665r-1v25", ID_AD5665R_1V25 }, - {"ad5665r-2v5", ID_AD5665R_2V5 }, - {"ad5667", ID_AD5667 }, - {"ad5667r-1v25", ID_AD5667R_1V25 }, - {"ad5667r-2v5", ID_AD5667R_2V5 }, - {"ad5669-1", ID_AD5669_1}, - {"ad5669-2", ID_AD5669_2}, - {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */ - {"ltc2606", ID_LTC2606}, - {"ltc2607", ID_LTC2607}, - {"ltc2609", ID_LTC2609}, - {"ltc2616", ID_LTC2616}, - {"ltc2617", ID_LTC2617}, - {"ltc2619", ID_LTC2619}, - {"ltc2626", ID_LTC2626}, - {"ltc2627", ID_LTC2627}, - {"ltc2629", ID_LTC2629}, - {"ltc2631-l12", ID_LTC2631_L12}, - {"ltc2631-h12", ID_LTC2631_H12}, - {"ltc2631-l10", ID_LTC2631_L10}, - {"ltc2631-h10", ID_LTC2631_H10}, - {"ltc2631-l8", ID_LTC2631_L8}, - {"ltc2631-h8", ID_LTC2631_H8}, - {"ltc2633-l12", ID_LTC2633_L12}, - {"ltc2633-h12", ID_LTC2633_H12}, - {"ltc2633-l10", ID_LTC2633_L10}, - {"ltc2633-h10", ID_LTC2633_H10}, - {"ltc2633-l8", ID_LTC2633_L8}, - {"ltc2633-h8", ID_LTC2633_H8}, - {"ltc2635-l12", ID_LTC2635_L12}, - {"ltc2635-h12", ID_LTC2635_H12}, - {"ltc2635-l10", ID_LTC2635_L10}, - {"ltc2635-h10", ID_LTC2635_H10}, - {"ltc2635-l8", ID_LTC2635_L8}, - {"ltc2635-h8", ID_LTC2635_H8}, + { .name = "ad5625", .driver_data = ID_AD5625 }, + { .name = "ad5625r-1v25", .driver_data = ID_AD5625R_1V25 }, + { .name = "ad5625r-2v5", .driver_data = ID_AD5625R_2V5 }, + { .name = "ad5627", .driver_data = ID_AD5627 }, + { .name = "ad5627r-1v25", .driver_data = ID_AD5627R_1V25 }, + { .name = "ad5627r-2v5", .driver_data = ID_AD5627R_2V5 }, + { .name = "ad5629-1", .driver_data = ID_AD5629_1 }, + { .name = "ad5629-2", .driver_data = ID_AD5629_2 }, + { .name = "ad5629-3", .driver_data = ID_AD5629_2 }, /* similar enough to ad5629-2 */ + { .name = "ad5645r-1v25", .driver_data = ID_AD5645R_1V25 }, + { .name = "ad5645r-2v5", .driver_data = ID_AD5645R_2V5 }, + { .name = "ad5665", .driver_data = ID_AD5665 }, + { .name = "ad5665r-1v25", .driver_data = ID_AD5665R_1V25 }, + { .name = "ad5665r-2v5", .driver_data = ID_AD5665R_2V5 }, + { .name = "ad5667", .driver_data = ID_AD5667 }, + { .name = "ad5667r-1v25", .driver_data = ID_AD5667R_1V25 }, + { .name = "ad5667r-2v5", .driver_data = ID_AD5667R_2V5 }, + { .name = "ad5669-1", .driver_data = ID_AD5669_1 }, + { .name = "ad5669-2", .driver_data = ID_AD5669_2 }, + { .name = "ad5669-3", .driver_data = ID_AD5669_2 }, /* similar enough to ad5669-2 */ + { .name = "ltc2606", .driver_data = ID_LTC2606 }, + { .name = "ltc2607", .driver_data = ID_LTC2607 }, + { .name = "ltc2609", .driver_data = ID_LTC2609 }, + { .name = "ltc2616", .driver_data = ID_LTC2616 }, + { .name = "ltc2617", .driver_data = ID_LTC2617 }, + { .name = "ltc2619", .driver_data = ID_LTC2619 }, + { .name = "ltc2626", .driver_data = ID_LTC2626 }, + { .name = "ltc2627", .driver_data = ID_LTC2627 }, + { .name = "ltc2629", .driver_data = ID_LTC2629 }, + { .name = "ltc2631-l12", .driver_data = ID_LTC2631_L12 }, + { .name = "ltc2631-h12", .driver_data = ID_LTC2631_H12 }, + { .name = "ltc2631-l10", .driver_data = ID_LTC2631_L10 }, + { .name = "ltc2631-h10", .driver_data = ID_LTC2631_H10 }, + { .name = "ltc2631-l8", .driver_data = ID_LTC2631_L8 }, + { .name = "ltc2631-h8", .driver_data = ID_LTC2631_H8 }, + { .name = "ltc2633-l12", .driver_data = ID_LTC2633_L12 }, + { .name = "ltc2633-h12", .driver_data = ID_LTC2633_H12 }, + { .name = "ltc2633-l10", .driver_data = ID_LTC2633_L10 }, + { .name = "ltc2633-h10", .driver_data = ID_LTC2633_H10 }, + { .name = "ltc2633-l8", .driver_data = ID_LTC2633_L8 }, + { .name = "ltc2633-h8", .driver_data = ID_LTC2633_H8 }, + { .name = "ltc2635-l12", .driver_data = ID_LTC2635_L12 }, + { .name = "ltc2635-h12", .driver_data = ID_LTC2635_H12 }, + { .name = "ltc2635-l10", .driver_data = ID_LTC2635_L10 }, + { .name = "ltc2635-h10", .driver_data = ID_LTC2635_H10 }, + { .name = "ltc2635-l8", .driver_data = ID_LTC2635_L8 }, + { .name = "ltc2635-h8", .driver_data = ID_LTC2635_H8 }, { } }; MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 8b813cee7625..2e587bdd3214 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -513,22 +513,22 @@ static int ad5380_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ad5380_i2c_ids[] = { - { "ad5380-3", ID_AD5380_3 }, - { "ad5380-5", ID_AD5380_5 }, - { "ad5381-3", ID_AD5381_3 }, - { "ad5381-5", ID_AD5381_5 }, - { "ad5382-3", ID_AD5382_3 }, - { "ad5382-5", ID_AD5382_5 }, - { "ad5383-3", ID_AD5383_3 }, - { "ad5383-5", ID_AD5383_5 }, - { "ad5384-3", ID_AD5380_3 }, - { "ad5384-5", ID_AD5380_5 }, - { "ad5390-3", ID_AD5390_3 }, - { "ad5390-5", ID_AD5390_5 }, - { "ad5391-3", ID_AD5391_3 }, - { "ad5391-5", ID_AD5391_5 }, - { "ad5392-3", ID_AD5392_3 }, - { "ad5392-5", ID_AD5392_5 }, + { .name = "ad5380-3", .driver_data = ID_AD5380_3 }, + { .name = "ad5380-5", .driver_data = ID_AD5380_5 }, + { .name = "ad5381-3", .driver_data = ID_AD5381_3 }, + { .name = "ad5381-5", .driver_data = ID_AD5381_5 }, + { .name = "ad5382-3", .driver_data = ID_AD5382_3 }, + { .name = "ad5382-5", .driver_data = ID_AD5382_5 }, + { .name = "ad5383-3", .driver_data = ID_AD5383_3 }, + { .name = "ad5383-5", .driver_data = ID_AD5383_5 }, + { .name = "ad5384-3", .driver_data = ID_AD5380_3 }, + { .name = "ad5384-5", .driver_data = ID_AD5380_5 }, + { .name = "ad5390-3", .driver_data = ID_AD5390_3 }, + { .name = "ad5390-5", .driver_data = ID_AD5390_5 }, + { .name = "ad5391-3", .driver_data = ID_AD5391_3 }, + { .name = "ad5391-5", .driver_data = ID_AD5391_5 }, + { .name = "ad5392-3", .driver_data = ID_AD5392_3 }, + { .name = "ad5392-5", .driver_data = ID_AD5392_5 }, { } }; MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids); diff --git a/drivers/iio/dac/ad5446-i2c.c b/drivers/iio/dac/ad5446-i2c.c index 40fe7e17fce4..2d4c8908d91e 100644 --- a/drivers/iio/dac/ad5446-i2c.c +++ b/drivers/iio/dac/ad5446-i2c.c @@ -65,12 +65,12 @@ static const struct ad5446_chip_info ad5622_chip_info = { }; static const struct i2c_device_id ad5446_i2c_ids[] = { - {"ad5301", (kernel_ulong_t)&ad5602_chip_info}, - {"ad5311", (kernel_ulong_t)&ad5612_chip_info}, - {"ad5321", (kernel_ulong_t)&ad5622_chip_info}, - {"ad5602", (kernel_ulong_t)&ad5602_chip_info}, - {"ad5612", (kernel_ulong_t)&ad5612_chip_info}, - {"ad5622", (kernel_ulong_t)&ad5622_chip_info}, + { .name = "ad5301", .driver_data = (kernel_ulong_t)&ad5602_chip_info }, + { .name = "ad5311", .driver_data = (kernel_ulong_t)&ad5612_chip_info }, + { .name = "ad5321", .driver_data = (kernel_ulong_t)&ad5622_chip_info }, + { .name = "ad5602", .driver_data = (kernel_ulong_t)&ad5602_chip_info }, + { .name = "ad5612", .driver_data = (kernel_ulong_t)&ad5612_chip_info }, + { .name = "ad5622", .driver_data = (kernel_ulong_t)&ad5622_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids); diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index 355bcb6a8ba0..5e586185d857 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -5,21 +5,21 @@ * Copyright 2011 Analog Devices Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include #define AD5504_RES_MASK GENMASK(11, 0) #define AD5504_CMD_READ BIT(15) @@ -270,25 +270,26 @@ static const struct iio_chan_spec ad5504_channels[] = { static int ad5504_probe(struct spi_device *spi) { - const struct ad5504_platform_data *pdata = dev_get_platdata(&spi->dev); + struct device *dev = &spi->dev; + const struct ad5504_platform_data *pdata = dev_get_platdata(dev); struct iio_dev *indio_dev; struct ad5504_state *st; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc"); + ret = devm_regulator_get_enable_read_voltage(dev, "vcc"); if (ret < 0 && ret != -ENODEV) return ret; if (ret == -ENODEV) { if (pdata->vref_mv) st->vref_mv = pdata->vref_mv; else - dev_warn(&spi->dev, "reference voltage unspecified\n"); + dev_warn(dev, "reference voltage unspecified\n"); } else { st->vref_mv = ret / 1000; } @@ -304,17 +305,17 @@ static int ad5504_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; if (spi->irq) { - ret = devm_request_threaded_irq(&spi->dev, spi->irq, - NULL, - &ad5504_event_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - spi_get_device_id(st->spi)->name, - indio_dev); + ret = devm_request_threaded_irq(dev, spi->irq, + NULL, + &ad5504_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + spi_get_device_id(st->spi)->name, + indio_dev); if (ret) return ret; } - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad5504_id[] = { diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index df8619e0c092..6b6ef1d7071f 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -8,11 +8,16 @@ * Copyright 2018 Analog Devices Inc. */ -#include "ad5686.h" - +#include +#include +#include #include #include +#include + +#include "ad5686.h" + static int ad5686_spi_write(struct ad5686_state *st, u8 cmd, u8 addr, u16 val) { @@ -87,38 +92,62 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr) return be32_to_cpu(st->data[2].d32); } +static const struct ad5686_bus_ops ad5686_spi_ops = { + .write = ad5686_spi_write, + .read = ad5686_spi_read, +}; + static int ad5686_spi_probe(struct spi_device *spi) { - const struct spi_device_id *id = spi_get_device_id(spi); - - return ad5686_probe(&spi->dev, id->driver_data, id->name, - ad5686_spi_write, ad5686_spi_read); + return ad5686_probe(&spi->dev, spi_get_device_match_data(spi), + spi->modalias, &ad5686_spi_ops); } static const struct spi_device_id ad5686_spi_id[] = { - {"ad5310r", ID_AD5310R}, - {"ad5672r", ID_AD5672R}, - {"ad5674r", ID_AD5674R}, - {"ad5676", ID_AD5676}, - {"ad5676r", ID_AD5676R}, - {"ad5679r", ID_AD5679R}, - {"ad5681r", ID_AD5681R}, - {"ad5682r", ID_AD5682R}, - {"ad5683", ID_AD5683}, - {"ad5683r", ID_AD5683R}, - {"ad5684", ID_AD5684}, - {"ad5684r", ID_AD5684R}, - {"ad5685", ID_AD5685R}, /* Does not exist */ - {"ad5685r", ID_AD5685R}, - {"ad5686", ID_AD5686}, - {"ad5686r", ID_AD5686R}, + { .name = "ad5310r", .driver_data = (kernel_ulong_t)&ad5310r_chip_info }, + { .name = "ad5672r", .driver_data = (kernel_ulong_t)&ad5672r_chip_info }, + { .name = "ad5674r", .driver_data = (kernel_ulong_t)&ad5674r_chip_info }, + { .name = "ad5676", .driver_data = (kernel_ulong_t)&ad5676_chip_info }, + { .name = "ad5676r", .driver_data = (kernel_ulong_t)&ad5676r_chip_info }, + { .name = "ad5679r", .driver_data = (kernel_ulong_t)&ad5679r_chip_info }, + { .name = "ad5681r", .driver_data = (kernel_ulong_t)&ad5681r_chip_info }, + { .name = "ad5682r", .driver_data = (kernel_ulong_t)&ad5682r_chip_info }, + { .name = "ad5683", .driver_data = (kernel_ulong_t)&ad5683_chip_info }, + { .name = "ad5683r", .driver_data = (kernel_ulong_t)&ad5683r_chip_info }, + { .name = "ad5684", .driver_data = (kernel_ulong_t)&ad5684_chip_info }, + { .name = "ad5684r", .driver_data = (kernel_ulong_t)&ad5684r_chip_info }, + { .name = "ad5685", .driver_data = (kernel_ulong_t)&ad5685r_chip_info }, /* nonexistent */ + { .name = "ad5685r", .driver_data = (kernel_ulong_t)&ad5685r_chip_info }, + { .name = "ad5686", .driver_data = (kernel_ulong_t)&ad5686_chip_info }, + { .name = "ad5686r", .driver_data = (kernel_ulong_t)&ad5686r_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad5686_spi_id); +static const struct of_device_id ad5686_of_match[] = { + { .compatible = "adi,ad5310r", .data = &ad5310r_chip_info }, + { .compatible = "adi,ad5672r", .data = &ad5672r_chip_info }, + { .compatible = "adi,ad5674r", .data = &ad5674r_chip_info }, + { .compatible = "adi,ad5676", .data = &ad5676_chip_info }, + { .compatible = "adi,ad5676r", .data = &ad5676r_chip_info }, + { .compatible = "adi,ad5679r", .data = &ad5679r_chip_info }, + { .compatible = "adi,ad5681r", .data = &ad5681r_chip_info }, + { .compatible = "adi,ad5682r", .data = &ad5682r_chip_info }, + { .compatible = "adi,ad5683", .data = &ad5683_chip_info }, + { .compatible = "adi,ad5683r", .data = &ad5683r_chip_info }, + { .compatible = "adi,ad5684", .data = &ad5684_chip_info }, + { .compatible = "adi,ad5684r", .data = &ad5684r_chip_info }, + { .compatible = "adi,ad5685r", .data = &ad5685r_chip_info }, + { .compatible = "adi,ad5686", .data = &ad5686_chip_info }, + { .compatible = "adi,ad5686r", .data = &ad5686r_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(of, ad5686_of_match); + static struct spi_driver ad5686_spi_driver = { .driver = { .name = "ad5686", + .of_match_table = ad5686_of_match, }, .probe = ad5686_spi_probe, .id_table = ad5686_spi_id, diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index a7213bc6b156..5840fda4b011 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -5,17 +5,18 @@ * Copyright 2011 Analog Devices Inc. */ -#include -#include -#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include #include +#include +#include #include -#include #include "ad5686.h" @@ -25,6 +26,24 @@ static const char * const ad5686_powerdown_modes[] = { "three_state" }; +static int ad5310_control_sync(struct ad5686_state *st) +{ + unsigned int pd_val = st->pwr_down_mask & st->pwr_down_mode; + + return ad5686_write(st, AD5686_CMD_CONTROL_REG, 0, + FIELD_PREP(AD5310_PD_MSK, pd_val & AD5686_PD_MSK) | + FIELD_PREP(AD5310_REF_BIT_MSK, st->use_internal_vref ? 0 : 1)); +} + +static int ad5683_control_sync(struct ad5686_state *st) +{ + unsigned int pd_val = st->pwr_down_mask & st->pwr_down_mode; + + return ad5686_write(st, AD5686_CMD_CONTROL_REG, 0, + FIELD_PREP(AD5683_PD_MSK, pd_val & AD5686_PD_MSK) | + FIELD_PREP(AD5683_REF_BIT_MSK, st->use_internal_vref ? 0 : 1)); +} + static inline unsigned int ad5686_pd_mask_shift(const struct iio_chan_spec *chan) { if (chan->channel == chan->address) @@ -34,28 +53,40 @@ static inline unsigned int ad5686_pd_mask_shift(const struct iio_chan_spec *chan return __ffs(chan->address) * 2; } +static inline void ad5686_pd_field_set(const struct iio_chan_spec *chan, + unsigned int *pd, unsigned int val) +{ + unsigned int shift = ad5686_pd_mask_shift(chan); + + *pd = (*pd & ~(AD5686_PD_MSK << shift)) | ((val & AD5686_PD_MSK) << shift); +} + +static inline unsigned int ad5686_pd_field_get(const struct iio_chan_spec *chan, + unsigned int pd) +{ + unsigned int shift = ad5686_pd_mask_shift(chan); + + return (pd >> shift) & AD5686_PD_MSK; +} + static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev, const struct iio_chan_spec *chan) { - unsigned int shift = ad5686_pd_mask_shift(chan); struct ad5686_state *st = iio_priv(indio_dev); guard(mutex)(&st->lock); - return ((st->pwr_down_mode >> shift) & 0x3U) - 1; + return ad5686_pd_field_get(chan, st->pwr_down_mode) - 1; } static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, unsigned int mode) { - unsigned int shift = ad5686_pd_mask_shift(chan); struct ad5686_state *st = iio_priv(indio_dev); guard(mutex)(&st->lock); - - st->pwr_down_mode &= ~(0x3U << shift); - st->pwr_down_mode |= (mode + 1) << shift; + ad5686_pd_field_set(chan, &st->pwr_down_mode, mode + 1); return 0; } @@ -70,12 +101,12 @@ static const struct iio_enum ad5686_powerdown_mode_enum = { static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, char *buf) { - unsigned int shift = ad5686_pd_mask_shift(chan); struct ad5686_state *st = iio_priv(indio_dev); guard(mutex)(&st->lock); - return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask & (0x3U << shift))); + return sysfs_emit(buf, "%d\n", + !!ad5686_pd_field_get(chan, st->pwr_down_mask)); } static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, @@ -87,8 +118,8 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, bool readin; int ret; struct ad5686_state *st = iio_priv(indio_dev); - unsigned int val, ref_bit_msk; - u8 shift, address = 0; + unsigned int val; + u8 address; ret = kstrtobool(buf, &readin); if (ret) @@ -97,42 +128,40 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, guard(mutex)(&st->lock); if (readin) - st->pwr_down_mask |= 0x3U << ad5686_pd_mask_shift(chan); + ad5686_pd_field_set(chan, &st->pwr_down_mask, AD5686_PD_MSK_PWR_DOWN); else - st->pwr_down_mask &= ~(0x3U << ad5686_pd_mask_shift(chan)); + ad5686_pd_field_set(chan, &st->pwr_down_mask, AD5686_PD_MSK_PWR_UP); switch (st->chip_info->regmap_type) { case AD5310_REGMAP: - shift = 9; - ref_bit_msk = AD5310_REF_BIT_MSK; + ret = ad5310_control_sync(st); + if (ret) + return ret; break; case AD5683_REGMAP: - shift = 13; - ref_bit_msk = AD5683_REF_BIT_MSK; + ret = ad5683_control_sync(st); + if (ret) + return ret; break; case AD5686_REGMAP: - shift = 0; - ref_bit_msk = 0; /* AD5674R/AD5679R have 16 channels and 2 powerdown registers */ - if (chan->channel > 0x7) + val = st->pwr_down_mask & st->pwr_down_mode; + if (chan->channel > 0x7) { address = 0x8; - break; - case AD5693_REGMAP: - shift = 13; - ref_bit_msk = AD5693_REF_BIT_MSK; + val = upper_16_bits(val); + } else { + address = 0x0; + val = lower_16_bits(val); + } + ret = ad5686_write(st, AD5686_CMD_POWERDOWN_DAC, address, val); + if (ret) + return ret; break; default: return -EINVAL; } - val = ((st->pwr_down_mask & st->pwr_down_mode) << shift); - if (!st->use_internal_vref) - val |= ref_bit_msk; - - ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, - address, val >> (address * 2)); - - return ret ? ret : len; + return len; } static int ad5686_read_raw(struct iio_dev *indio_dev, @@ -147,7 +176,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: mutex_lock(&st->lock); - ret = st->read(st, chan->address); + ret = ad5686_read(st, chan->address); mutex_unlock(&st->lock); if (ret < 0) return ret; @@ -177,10 +206,8 @@ static int ad5686_write_raw(struct iio_dev *indio_dev, return -EINVAL; mutex_lock(&st->lock); - ret = st->write(st, - AD5686_CMD_WRITE_INPUT_N_UPDATE_N, - chan->address, - val << chan->scan_type.shift); + ret = ad5686_write(st, AD5686_CMD_WRITE_INPUT_N_UPDATE_N, + chan->address, val << chan->scan_type.shift); mutex_unlock(&st->lock); break; default: @@ -224,7 +251,7 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { .ext_info = ad5686_ext_info, \ } -#define DECLARE_AD5693_CHANNELS(name, bits, _shift) \ +#define DECLARE_AD5683_CHANNELS(name, bits, _shift) \ static const struct iio_chan_spec name[] = { \ AD5868_CHANNEL(0, 0, bits, _shift), \ } @@ -275,213 +302,176 @@ static const struct iio_chan_spec name[] = { \ AD5868_CHANNEL(15, 15, bits, _shift), \ } -DECLARE_AD5693_CHANNELS(ad5310r_channels, 10, 2); -DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6); +/* single-channel */ +DECLARE_AD5683_CHANNELS(ad5310r_channels, 10, 2); +DECLARE_AD5683_CHANNELS(ad5311r_channels, 10, 6); +DECLARE_AD5683_CHANNELS(ad5681r_channels, 12, 4); +DECLARE_AD5683_CHANNELS(ad5682r_channels, 14, 2); +DECLARE_AD5683_CHANNELS(ad5683r_channels, 16, 0); + +/* dual-channel */ DECLARE_AD5338_CHANNELS(ad5337r_channels, 8, 8); DECLARE_AD5338_CHANNELS(ad5338r_channels, 10, 6); -DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4); -DECLARE_AD5679_CHANNELS(ad5674r_channels, 12, 4); -DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0); -DECLARE_AD5679_CHANNELS(ad5679r_channels, 16, 0); -DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4); -DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2); -DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0); -DECLARE_AD5693_CHANNELS(ad5693_channels, 16, 0); -DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2); -DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4); -static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { - [ID_AD5310R] = { - .channels = ad5310r_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5310_REGMAP, - }, - [ID_AD5311R] = { - .channels = ad5311r_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5693_REGMAP, - }, - [ID_AD5337R] = { - .channels = ad5337r_channels, - .int_vref_mv = 2500, - .num_channels = 2, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5338R] = { - .channels = ad5338r_channels, - .int_vref_mv = 2500, - .num_channels = 2, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5671R] = { - .channels = ad5672_channels, - .int_vref_mv = 2500, - .num_channels = 8, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5672R] = { - .channels = ad5672_channels, - .int_vref_mv = 2500, - .num_channels = 8, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5673R] = { - .channels = ad5674r_channels, - .int_vref_mv = 2500, - .num_channels = 16, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5674R] = { - .channels = ad5674r_channels, - .int_vref_mv = 2500, - .num_channels = 16, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5675R] = { - .channels = ad5676_channels, - .int_vref_mv = 2500, - .num_channels = 8, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5676] = { - .channels = ad5676_channels, - .num_channels = 8, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5676R] = { - .channels = ad5676_channels, - .int_vref_mv = 2500, - .num_channels = 8, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5677R] = { - .channels = ad5679r_channels, - .int_vref_mv = 2500, - .num_channels = 16, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5679R] = { - .channels = ad5679r_channels, - .int_vref_mv = 2500, - .num_channels = 16, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5681R] = { - .channels = ad5691r_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5683_REGMAP, - }, - [ID_AD5682R] = { - .channels = ad5692r_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5683_REGMAP, - }, - [ID_AD5683] = { - .channels = ad5693_channels, - .num_channels = 1, - .regmap_type = AD5683_REGMAP, - }, - [ID_AD5683R] = { - .channels = ad5693_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5683_REGMAP, - }, - [ID_AD5684] = { - .channels = ad5684_channels, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5684R] = { - .channels = ad5684_channels, - .int_vref_mv = 2500, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5685R] = { - .channels = ad5685r_channels, - .int_vref_mv = 2500, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5686] = { - .channels = ad5686_channels, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5686R] = { - .channels = ad5686_channels, - .int_vref_mv = 2500, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5691R] = { - .channels = ad5691r_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5693_REGMAP, - }, - [ID_AD5692R] = { - .channels = ad5692r_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5693_REGMAP, - }, - [ID_AD5693] = { - .channels = ad5693_channels, - .num_channels = 1, - .regmap_type = AD5693_REGMAP, - }, - [ID_AD5693R] = { - .channels = ad5693_channels, - .int_vref_mv = 2500, - .num_channels = 1, - .regmap_type = AD5693_REGMAP, - }, - [ID_AD5694] = { - .channels = ad5684_channels, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5694R] = { - .channels = ad5684_channels, - .int_vref_mv = 2500, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5695R] = { - .channels = ad5685r_channels, - .int_vref_mv = 2500, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5696] = { - .channels = ad5686_channels, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, - [ID_AD5696R] = { - .channels = ad5686_channels, - .int_vref_mv = 2500, - .num_channels = 4, - .regmap_type = AD5686_REGMAP, - }, +/* quad-channel */ +DECLARE_AD5686_CHANNELS(ad5684r_channels, 12, 4); +DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2); +DECLARE_AD5686_CHANNELS(ad5686r_channels, 16, 0); + +/* 8-channel */ +DECLARE_AD5676_CHANNELS(ad5672r_channels, 12, 4); +DECLARE_AD5676_CHANNELS(ad5676r_channels, 16, 0); + +/* 16-channel */ +DECLARE_AD5679_CHANNELS(ad5674r_channels, 12, 4); +DECLARE_AD5679_CHANNELS(ad5679r_channels, 16, 0); + +const struct ad5686_chip_info ad5310r_chip_info = { + .channels = ad5310r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5310_REGMAP, }; +EXPORT_SYMBOL_NS_GPL(ad5310r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5311r_chip_info = { + .channels = ad5311r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5311r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5681r_chip_info = { + .channels = ad5681r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5681r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5682r_chip_info = { + .channels = ad5682r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5682r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5683_chip_info = { + .channels = ad5683r_channels, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5683_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5683r_chip_info = { + .channels = ad5683r_channels, + .int_vref_mv = 2500, + .num_channels = 1, + .regmap_type = AD5683_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5683r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5337r_chip_info = { + .channels = ad5337r_channels, + .int_vref_mv = 2500, + .num_channels = 2, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5337r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5338r_chip_info = { + .channels = ad5338r_channels, + .int_vref_mv = 2500, + .num_channels = 2, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5338r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5684_chip_info = { + .channels = ad5684r_channels, + .num_channels = 4, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5684_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5684r_chip_info = { + .channels = ad5684r_channels, + .int_vref_mv = 2500, + .num_channels = 4, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5684r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5685r_chip_info = { + .channels = ad5685r_channels, + .int_vref_mv = 2500, + .num_channels = 4, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5685r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5686_chip_info = { + .channels = ad5686r_channels, + .num_channels = 4, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5686_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5686r_chip_info = { + .channels = ad5686r_channels, + .int_vref_mv = 2500, + .num_channels = 4, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5686r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5672r_chip_info = { + .channels = ad5672r_channels, + .int_vref_mv = 2500, + .num_channels = 8, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5672r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5676_chip_info = { + .channels = ad5676r_channels, + .num_channels = 8, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5676_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5676r_chip_info = { + .channels = ad5676r_channels, + .int_vref_mv = 2500, + .num_channels = 8, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5676r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5674r_chip_info = { + .channels = ad5674r_channels, + .int_vref_mv = 2500, + .num_channels = 16, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5674r_chip_info, "IIO_AD5686"); + +const struct ad5686_chip_info ad5679r_chip_info = { + .channels = ad5679r_channels, + .int_vref_mv = 2500, + .num_channels = 16, + .regmap_type = AD5686_REGMAP, +}; +EXPORT_SYMBOL_NS_GPL(ad5679r_chip_info, "IIO_AD5686"); int ad5686_probe(struct device *dev, - enum ad5686_supported_device_ids chip_type, - const char *name, ad5686_write_func write, - ad5686_read_func read) + const struct ad5686_chip_info *chip_info, + const char *name, const struct ad5686_bus_ops *ops) { struct ad5686_state *st; struct iio_dev *indio_dev; - unsigned int val, ref_bit_msk, shift; - bool has_external_vref; - u8 cmd; int ret, i; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -491,29 +481,26 @@ int ad5686_probe(struct device *dev, st = iio_priv(indio_dev); st->dev = dev; - st->write = write; - st->read = read; - - st->chip_info = &ad5686_chip_info_tbl[chip_type]; + st->ops = ops; + st->chip_info = chip_info; ret = devm_regulator_get_enable_read_voltage(dev, "vcc"); if (ret < 0 && ret != -ENODEV) return ret; - has_external_vref = ret != -ENODEV; - st->vref_mv = has_external_vref ? ret / 1000 : st->chip_info->int_vref_mv; + st->use_internal_vref = ret == -ENODEV; + st->vref_mv = st->use_internal_vref ? st->chip_info->int_vref_mv : ret / 1000; - /* Initialize masks to all ones provided the max shift (last channel) */ - shift = ad5686_pd_mask_shift(&st->chip_info->channels[st->chip_info->num_channels - 1]); - st->pwr_down_mask = GENMASK(shift + 1, 0); - st->pwr_down_mode = GENMASK(shift + 1, 0); + /* Initialize masks to all ones */ + st->pwr_down_mask = ~0; + st->pwr_down_mode = ~0; /* Set all the power down mode for all channels to 1K pulldown */ for (i = 0; i < st->chip_info->num_channels; i++) { - shift = ad5686_pd_mask_shift(&st->chip_info->channels[i]); - st->pwr_down_mask &= ~(0x3U << shift); /* powered up state */ - st->pwr_down_mode &= ~(0x3U << shift); - st->pwr_down_mode |= 0x01U << shift; + ad5686_pd_field_set(&st->chip_info->channels[i], + &st->pwr_down_mask, AD5686_PD_MSK_PWR_UP); + ad5686_pd_field_set(&st->chip_info->channels[i], + &st->pwr_down_mode, AD5686_PD_MODE_1K_TO_GND); } indio_dev->name = name; @@ -522,38 +509,31 @@ int ad5686_probe(struct device *dev, indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; - mutex_init(&st->lock); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; switch (st->chip_info->regmap_type) { case AD5310_REGMAP: - cmd = AD5686_CMD_CONTROL_REG; - ref_bit_msk = AD5310_REF_BIT_MSK; - st->use_internal_vref = !has_external_vref; + ret = ad5310_control_sync(st); + if (ret) + return ret; break; case AD5683_REGMAP: - cmd = AD5686_CMD_CONTROL_REG; - ref_bit_msk = AD5683_REF_BIT_MSK; - st->use_internal_vref = !has_external_vref; + ret = ad5683_control_sync(st); + if (ret) + return ret; break; case AD5686_REGMAP: - cmd = AD5686_CMD_INTERNAL_REFER_SETUP; - ref_bit_msk = AD5686_REF_BIT_MSK; - break; - case AD5693_REGMAP: - cmd = AD5686_CMD_CONTROL_REG; - ref_bit_msk = AD5693_REF_BIT_MSK; - st->use_internal_vref = !has_external_vref; + ret = ad5686_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0, + st->use_internal_vref ? 0 : AD5686_REF_BIT_MSK); + if (ret) + return ret; break; default: return -EINVAL; } - val = has_external_vref ? ref_bit_msk : 0; - - ret = st->write(st, cmd, 0, val); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } EXPORT_SYMBOL_NS_GPL(ad5686_probe, "IIO_AD5686"); diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h index 36e16c5c4581..a06fe7d89305 100644 --- a/drivers/iio/dac/ad5686.h +++ b/drivers/iio/dac/ad5686.h @@ -8,10 +8,9 @@ #ifndef __DRIVERS_IIO_DAC_AD5686_H__ #define __DRIVERS_IIO_DAC_AD5686_H__ -#include -#include +#include #include -#include +#include #include @@ -36,78 +35,50 @@ #define AD5686_CMD_DAISY_CHAIN_ENABLE 0x8 #define AD5686_CMD_READBACK_ENABLE 0x9 -#define AD5686_LDAC_PWRDN_NONE 0x0 -#define AD5686_LDAC_PWRDN_1K 0x1 -#define AD5686_LDAC_PWRDN_100K 0x2 -#define AD5686_LDAC_PWRDN_3STATE 0x3 - #define AD5686_CMD_CONTROL_REG 0x4 #define AD5686_CMD_READBACK_ENABLE_V2 0x5 #define AD5310_REF_BIT_MSK BIT(8) -#define AD5683_REF_BIT_MSK BIT(12) -#define AD5686_REF_BIT_MSK BIT(0) -#define AD5693_REF_BIT_MSK BIT(12) +#define AD5310_PD_MSK GENMASK(10, 9) -/** - * ad5686_supported_device_ids: - */ -enum ad5686_supported_device_ids { - ID_AD5310R, - ID_AD5311R, - ID_AD5337R, - ID_AD5338R, - ID_AD5671R, - ID_AD5672R, - ID_AD5673R, - ID_AD5674R, - ID_AD5675R, - ID_AD5676, - ID_AD5676R, - ID_AD5677R, - ID_AD5679R, - ID_AD5681R, - ID_AD5682R, - ID_AD5683, - ID_AD5683R, - ID_AD5684, - ID_AD5684R, - ID_AD5685R, - ID_AD5686, - ID_AD5686R, - ID_AD5691R, - ID_AD5692R, - ID_AD5693, - ID_AD5693R, - ID_AD5694, - ID_AD5694R, - ID_AD5695R, - ID_AD5696, - ID_AD5696R, -}; +#define AD5683_REF_BIT_MSK BIT(12) +#define AD5683_PD_MSK GENMASK(14, 13) + +#define AD5686_REF_BIT_MSK BIT(0) +#define AD5686_PD_MSK GENMASK(1, 0) + +#define AD5686_PD_MODE_1K_TO_GND 0x1 +#define AD5686_PD_MODE_100K_TO_GND 0x2 +#define AD5686_PD_MODE_THREE_STATE 0x3 + +#define AD5686_PD_MSK_PWR_UP 0x0 +#define AD5686_PD_MSK_PWR_DOWN 0x3 enum ad5686_regmap_type { AD5310_REGMAP, AD5683_REGMAP, AD5686_REGMAP, - AD5693_REGMAP }; struct ad5686_state; -typedef int (*ad5686_write_func)(struct ad5686_state *st, - u8 cmd, u8 addr, u16 val); - -typedef int (*ad5686_read_func)(struct ad5686_state *st, u8 addr); +/** + * struct ad5686_bus_ops - bus specific read/write operations + * @read: read a register value at the given address + * @write: write a command, address and value to the device + */ +struct ad5686_bus_ops { + int (*read)(struct ad5686_state *st, u8 addr); + int (*write)(struct ad5686_state *st, u8 cmd, u8 addr, u16 val); +}; /** * struct ad5686_chip_info - chip specific information - * @int_vref_mv: AD5620/40/60: the internal reference voltage + * @int_vref_mv: the internal reference voltage * @num_channels: number of channels * @channel: channel specification * @regmap_type: register map layout variant */ - struct ad5686_chip_info { u16 int_vref_mv; unsigned int num_channels; @@ -115,26 +86,54 @@ struct ad5686_chip_info { enum ad5686_regmap_type regmap_type; }; +/* single-channel instances */ +extern const struct ad5686_chip_info ad5310r_chip_info; +extern const struct ad5686_chip_info ad5311r_chip_info; +extern const struct ad5686_chip_info ad5681r_chip_info; +extern const struct ad5686_chip_info ad5682r_chip_info; +extern const struct ad5686_chip_info ad5683_chip_info; +extern const struct ad5686_chip_info ad5683r_chip_info; + +/* dual-channel instances */ +extern const struct ad5686_chip_info ad5337r_chip_info; +extern const struct ad5686_chip_info ad5338r_chip_info; + +/* quad-channel instances */ +extern const struct ad5686_chip_info ad5684_chip_info; +extern const struct ad5686_chip_info ad5684r_chip_info; +extern const struct ad5686_chip_info ad5685r_chip_info; +extern const struct ad5686_chip_info ad5686_chip_info; +extern const struct ad5686_chip_info ad5686r_chip_info; + +/* 8-channel instances */ +extern const struct ad5686_chip_info ad5672r_chip_info; +extern const struct ad5686_chip_info ad5676_chip_info; +extern const struct ad5686_chip_info ad5676r_chip_info; + +/* 16-channel instances */ +extern const struct ad5686_chip_info ad5674r_chip_info; +extern const struct ad5686_chip_info ad5679r_chip_info; + /** * struct ad5686_state - driver instance specific data - * @spi: spi_device + * @dev: device instance * @chip_info: chip model specific constants, available modes etc + * @ops: bus specific operations * @vref_mv: actual reference voltage used * @pwr_down_mask: power down mask * @pwr_down_mode: current power down mode * @use_internal_vref: set to true if the internal reference voltage is used - * @lock lock to protect the data buffer during regmap ops - * @data: spi transfer buffers + * @lock: lock to protect access to state fields, which includes + * the data buffer during regmap ops + * @data: transfer buffers */ - struct ad5686_state { struct device *dev; const struct ad5686_chip_info *chip_info; + const struct ad5686_bus_ops *ops; unsigned short vref_mv; unsigned int pwr_down_mask; unsigned int pwr_down_mode; - ad5686_write_func write; - ad5686_read_func read; bool use_internal_vref; struct mutex lock; @@ -152,9 +151,17 @@ struct ad5686_state { int ad5686_probe(struct device *dev, - enum ad5686_supported_device_ids chip_type, - const char *name, ad5686_write_func write, - ad5686_read_func read); + const struct ad5686_chip_info *chip_info, + const char *name, const struct ad5686_bus_ops *ops); +static inline int ad5686_write(struct ad5686_state *st, u8 cmd, u8 addr, u16 val) +{ + return st->ops->write(st, cmd, addr, val); +} + +static inline int ad5686_read(struct ad5686_state *st, u8 addr) +{ + return st->ops->read(st, addr); +} #endif /* __DRIVERS_IIO_DAC_AD5686_H__ */ diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c index d3327bca0e07..279309329b64 100644 --- a/drivers/iio/dac/ad5696-i2c.c +++ b/drivers/iio/dac/ad5696-i2c.c @@ -7,10 +7,14 @@ * Copyright 2018 Analog Devices Inc. */ -#include "ad5686.h" - -#include +#include #include +#include +#include + +#include + +#include "ad5686.h" static int ad5686_i2c_read(struct ad5686_state *st, u8 addr) { @@ -58,49 +62,53 @@ static int ad5686_i2c_write(struct ad5686_state *st, return (ret != 3) ? -EIO : 0; } +static const struct ad5686_bus_ops ad5686_i2c_ops = { + .write = ad5686_i2c_write, + .read = ad5686_i2c_read, +}; + static int ad5686_i2c_probe(struct i2c_client *i2c) { - const struct i2c_device_id *id = i2c_client_get_device_id(i2c); - return ad5686_probe(&i2c->dev, id->driver_data, id->name, - ad5686_i2c_write, ad5686_i2c_read); + return ad5686_probe(&i2c->dev, i2c_get_match_data(i2c), + i2c->name, &ad5686_i2c_ops); } static const struct i2c_device_id ad5686_i2c_id[] = { - {"ad5311r", ID_AD5311R}, - {"ad5337r", ID_AD5337R}, - {"ad5338r", ID_AD5338R}, - {"ad5671r", ID_AD5671R}, - {"ad5673r", ID_AD5673R}, - {"ad5675r", ID_AD5675R}, - {"ad5677r", ID_AD5677R}, - {"ad5691r", ID_AD5691R}, - {"ad5692r", ID_AD5692R}, - {"ad5693", ID_AD5693}, - {"ad5693r", ID_AD5693R}, - {"ad5694", ID_AD5694}, - {"ad5694r", ID_AD5694R}, - {"ad5695r", ID_AD5695R}, - {"ad5696", ID_AD5696}, - {"ad5696r", ID_AD5696R}, + { .name = "ad5311r", .driver_data = (kernel_ulong_t)&ad5311r_chip_info }, + { .name = "ad5337r", .driver_data = (kernel_ulong_t)&ad5337r_chip_info }, + { .name = "ad5338r", .driver_data = (kernel_ulong_t)&ad5338r_chip_info }, + { .name = "ad5671r", .driver_data = (kernel_ulong_t)&ad5672r_chip_info }, + { .name = "ad5673r", .driver_data = (kernel_ulong_t)&ad5674r_chip_info }, + { .name = "ad5675r", .driver_data = (kernel_ulong_t)&ad5676r_chip_info }, + { .name = "ad5677r", .driver_data = (kernel_ulong_t)&ad5679r_chip_info }, + { .name = "ad5691r", .driver_data = (kernel_ulong_t)&ad5681r_chip_info }, + { .name = "ad5692r", .driver_data = (kernel_ulong_t)&ad5682r_chip_info }, + { .name = "ad5693", .driver_data = (kernel_ulong_t)&ad5683_chip_info }, + { .name = "ad5693r", .driver_data = (kernel_ulong_t)&ad5683r_chip_info }, + { .name = "ad5694", .driver_data = (kernel_ulong_t)&ad5684_chip_info }, + { .name = "ad5694r", .driver_data = (kernel_ulong_t)&ad5684r_chip_info }, + { .name = "ad5695r", .driver_data = (kernel_ulong_t)&ad5685r_chip_info }, + { .name = "ad5696", .driver_data = (kernel_ulong_t)&ad5686_chip_info }, + { .name = "ad5696r", .driver_data = (kernel_ulong_t)&ad5686r_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, ad5686_i2c_id); static const struct of_device_id ad5686_of_match[] = { - { .compatible = "adi,ad5311r" }, - { .compatible = "adi,ad5337r" }, - { .compatible = "adi,ad5338r" }, - { .compatible = "adi,ad5671r" }, - { .compatible = "adi,ad5675r" }, - { .compatible = "adi,ad5691r" }, - { .compatible = "adi,ad5692r" }, - { .compatible = "adi,ad5693" }, - { .compatible = "adi,ad5693r" }, - { .compatible = "adi,ad5694" }, - { .compatible = "adi,ad5694r" }, - { .compatible = "adi,ad5695r" }, - { .compatible = "adi,ad5696" }, - { .compatible = "adi,ad5696r" }, + { .compatible = "adi,ad5311r", .data = &ad5311r_chip_info }, + { .compatible = "adi,ad5337r", .data = &ad5337r_chip_info }, + { .compatible = "adi,ad5338r", .data = &ad5338r_chip_info }, + { .compatible = "adi,ad5671r", .data = &ad5672r_chip_info }, + { .compatible = "adi,ad5675r", .data = &ad5676r_chip_info }, + { .compatible = "adi,ad5691r", .data = &ad5681r_chip_info }, + { .compatible = "adi,ad5692r", .data = &ad5682r_chip_info }, + { .compatible = "adi,ad5693", .data = &ad5683_chip_info }, + { .compatible = "adi,ad5693r", .data = &ad5683r_chip_info }, + { .compatible = "adi,ad5694", .data = &ad5684_chip_info }, + { .compatible = "adi,ad5694r", .data = &ad5684r_chip_info }, + { .compatible = "adi,ad5695r", .data = &ad5685r_chip_info }, + { .compatible = "adi,ad5696", .data = &ad5686_chip_info }, + { .compatible = "adi,ad5696r", .data = &ad5686r_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad5686_of_match); diff --git a/drivers/iio/dac/ad5706r.c b/drivers/iio/dac/ad5706r.c new file mode 100644 index 000000000000..f7872e92dc01 --- /dev/null +++ b/drivers/iio/dac/ad5706r.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AD5706R 16-bit Current Output Digital to Analog Converter + * + * Copyright 2026 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPI frame layout */ +#define AD5706R_RD_MASK BIT(15) +#define AD5706R_ADDR_MASK GENMASK(11, 0) + +/* Registers */ +#define AD5706R_REG_DAC_INPUT_A_CH(x) (0x60 + ((x) * 2)) +#define AD5706R_REG_DAC_DATA_READBACK_CH(x) (0x68 + ((x) * 2)) + +#define AD5706R_DAC_RESOLUTION 16 +#define AD5706R_DAC_MAX_CODE GENMASK(15, 0) +#define AD5706R_MULTIBYTE_REG_START 0x14 +#define AD5706R_MULTIBYTE_REG_END 0x71 +#define AD5706R_MAX_REG 0x77 + +struct ad5706r_state { + struct spi_device *spi; + struct regmap *regmap; + + u8 tx_buf[4] __aligned(IIO_DMA_MINALIGN); + u8 rx_buf[4]; +}; + +static int ad5706r_reg_len(unsigned int reg) +{ + if (reg >= AD5706R_MULTIBYTE_REG_START && reg <= AD5706R_MULTIBYTE_REG_END) + return 2; + + return 1; +} + +static int ad5706r_regmap_write(void *context, const void *data, size_t count) +{ + struct ad5706r_state *st = context; + unsigned int num_bytes; + u16 reg, val; + + if (count != 4) + return -EINVAL; + + reg = get_unaligned_be16(data); + val = get_unaligned_be16(data + 2); + num_bytes = ad5706r_reg_len(reg); + + struct spi_transfer xfer = { + .tx_buf = st->tx_buf, + .len = num_bytes + 2, + }; + + put_unaligned_be16(reg, &st->tx_buf[0]); + + if (num_bytes == 1) + st->tx_buf[2] = (u8)val; + else if (num_bytes == 2) + put_unaligned_be16(val, &st->tx_buf[2]); + else + return -EINVAL; + + return spi_sync_transfer(st->spi, &xfer, 1); +} + +static int ad5706r_regmap_read(void *context, const void *reg_buf, + size_t reg_size, void *val_buf, size_t val_size) +{ + struct ad5706r_state *st = context; + unsigned int num_bytes; + u16 reg, cmd, val; + int ret; + + if (reg_size != 2 || val_size != 2) + return -EINVAL; + + reg = get_unaligned_be16(reg_buf); + num_bytes = ad5706r_reg_len(reg); + + /* Full duplex, device responds immediately after command */ + struct spi_transfer xfer = { + .tx_buf = st->tx_buf, + .rx_buf = st->rx_buf, + .len = 2 + num_bytes, + }; + + cmd = AD5706R_RD_MASK | (reg & AD5706R_ADDR_MASK); + put_unaligned_be16(cmd, &st->tx_buf[0]); + put_unaligned_be16(0, &st->tx_buf[2]); + + ret = spi_sync_transfer(st->spi, &xfer, 1); + if (ret) + return ret; + + /* Extract value from response (skip 2-byte command echo) */ + if (num_bytes == 1) + val = st->rx_buf[2]; + else if (num_bytes == 2) + val = get_unaligned_be16(&st->rx_buf[2]); + else + return -EINVAL; + + put_unaligned_be16(val, val_buf); + + return 0; +} + +static int ad5706r_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ad5706r_state *st = iio_priv(indio_dev); + unsigned int reg, reg_val; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + reg = AD5706R_REG_DAC_DATA_READBACK_CH(chan->channel); + ret = regmap_read(st->regmap, reg, ®_val); + if (ret) + return ret; + + *val = reg_val; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 50; + *val2 = AD5706R_DAC_RESOLUTION; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static int ad5706r_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ad5706r_state *st = iio_priv(indio_dev); + unsigned int reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val < 0 || val > AD5706R_DAC_MAX_CODE) + return -EINVAL; + + reg = AD5706R_REG_DAC_INPUT_A_CH(chan->channel); + return regmap_write(st->regmap, reg, val); + default: + return -EINVAL; + } +} + +static const struct regmap_bus ad5706r_regmap_bus = { + .write = ad5706r_regmap_write, + .read = ad5706r_regmap_read, + .reg_format_endian_default = REGMAP_ENDIAN_BIG, + .val_format_endian_default = REGMAP_ENDIAN_BIG, +}; + +static const struct regmap_config ad5706r_regmap_config = { + .reg_bits = 16, + .val_bits = 16, + .max_register = AD5706R_MAX_REG, +}; + +static const struct iio_info ad5706r_info = { + .read_raw = ad5706r_read_raw, + .write_raw = ad5706r_write_raw, +}; + +#define AD5706R_CHAN(_channel) { \ + .type = IIO_CURRENT, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .output = 1, \ + .indexed = 1, \ + .channel = _channel, \ +} + +static const struct iio_chan_spec ad5706r_channels[] = { + AD5706R_CHAN(0), + AD5706R_CHAN(1), + AD5706R_CHAN(2), + AD5706R_CHAN(3), +}; + +static int ad5706r_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct iio_dev *indio_dev; + struct ad5706r_state *st; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + + st->regmap = devm_regmap_init(dev, &ad5706r_regmap_bus, + st, &ad5706r_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(dev, PTR_ERR(st->regmap), + "Failed to init regmap\n"); + + indio_dev->name = "ad5706r"; + indio_dev->info = &ad5706r_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad5706r_channels; + indio_dev->num_channels = ARRAY_SIZE(ad5706r_channels); + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id ad5706r_of_match[] = { + { .compatible = "adi,ad5706r" }, + { } +}; +MODULE_DEVICE_TABLE(of, ad5706r_of_match); + +static const struct spi_device_id ad5706r_id[] = { + { "ad5706r" }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad5706r_id); + +static struct spi_driver ad5706r_driver = { + .driver = { + .name = "ad5706r", + .of_match_table = ad5706r_of_match, + }, + .probe = ad5706r_probe, + .id_table = ad5706r_id, +}; +module_spi_driver(ad5706r_driver); + +MODULE_AUTHOR("Alexis Czezar Torreno "); +MODULE_DESCRIPTION("AD5706R 16-bit Current Output DAC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index d0e5f35462b1..cc6d56140d66 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -827,8 +827,9 @@ static int ad5755_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->num_channels = AD5755_NUM_CHANNELS; - mutex_init(&st->lock); - + ret = devm_mutex_init(&spi->dev, &st->lock); + if (ret) + return ret; pdata = ad5755_parse_fw(&spi->dev); if (!pdata) { diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c index 4ed4fda76ea9..8e6fb46cce4d 100644 --- a/drivers/iio/dac/ad5758.c +++ b/drivers/iio/dac/ad5758.c @@ -851,7 +851,9 @@ static int ad5758_probe(struct spi_device *spi) st->spi = spi; - mutex_init(&st->lock); + ret = devm_mutex_init(&spi->dev, &st->lock); + if (ret) + return ret; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5758_info; diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index a88cc639047d..1c2960fa9743 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -218,7 +218,9 @@ static int ad7303_probe(struct spi_device *spi) st->spi = spi; - mutex_init(&st->lock); + ret = devm_mutex_init(&spi->dev, &st->lock); + if (ret) + return ret; st->vdd_reg = devm_regulator_get(&spi->dev, "Vdd"); if (IS_ERR(st->vdd_reg)) diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c index 085f73de3f02..b6430b832cf0 100644 --- a/drivers/iio/dac/ds4424.c +++ b/drivers/iio/dac/ds4424.c @@ -401,10 +401,10 @@ static void ds4424_remove(struct i2c_client *client) } static const struct i2c_device_id ds4424_id[] = { - { "ds4402", (kernel_ulong_t)&ds4402_info }, - { "ds4404", (kernel_ulong_t)&ds4404_info }, - { "ds4422", (kernel_ulong_t)&ds4422_info }, - { "ds4424", (kernel_ulong_t)&ds4424_info }, + { .name = "ds4402", .driver_data = (kernel_ulong_t)&ds4402_info }, + { .name = "ds4404", .driver_data = (kernel_ulong_t)&ds4404_info }, + { .name = "ds4422", .driver_data = (kernel_ulong_t)&ds4422_info }, + { .name = "ds4424", .driver_data = (kernel_ulong_t)&ds4424_info }, { } }; diff --git a/drivers/iio/dac/ltc2664.c b/drivers/iio/dac/ltc2664.c index 67f14046cf77..616806615d3d 100644 --- a/drivers/iio/dac/ltc2664.c +++ b/drivers/iio/dac/ltc2664.c @@ -675,7 +675,9 @@ static int ltc2664_probe(struct spi_device *spi) st->chip_info = chip_info; - mutex_init(&st->lock); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; st->regmap = devm_regmap_init_spi(spi, <c2664_regmap_config); if (IS_ERR(st->regmap)) diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c index 3497513854d7..7e80c0eb5cc1 100644 --- a/drivers/iio/dac/m62332.c +++ b/drivers/iio/dac/m62332.c @@ -228,7 +228,7 @@ static void m62332_remove(struct i2c_client *client) } static const struct i2c_device_id m62332_id[] = { - { "m62332", }, + { .name = "m62332" }, { } }; MODULE_DEVICE_TABLE(i2c, m62332_id); diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index d334c67821ad..d2ddc72e0e50 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -187,11 +187,11 @@ static int max517_probe(struct i2c_client *client) } static const struct i2c_device_id max517_id[] = { - { "max517", ID_MAX517 }, - { "max518", ID_MAX518 }, - { "max519", ID_MAX519 }, - { "max520", ID_MAX520 }, - { "max521", ID_MAX521 }, + { .name = "max517", .driver_data = ID_MAX517 }, + { .name = "max518", .driver_data = ID_MAX518 }, + { .name = "max519", .driver_data = ID_MAX519 }, + { .name = "max520", .driver_data = ID_MAX520 }, + { .name = "max521", .driver_data = ID_MAX521 }, { } }; MODULE_DEVICE_TABLE(i2c, max517_id); diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c index dd4e35460195..45def245626b 100644 --- a/drivers/iio/dac/max5821.c +++ b/drivers/iio/dac/max5821.c @@ -26,10 +26,6 @@ #define MAX5821_EXTENDED_DAC_A 0x04 #define MAX5821_EXTENDED_DAC_B 0x08 -enum max5821_device_ids { - ID_MAX5821, -}; - struct max5821_data { struct i2c_client *client; unsigned short vref_mv; @@ -339,7 +335,7 @@ static int max5821_probe(struct i2c_client *client) } static const struct i2c_device_id max5821_id[] = { - { "max5821", ID_MAX5821 }, + { .name = "max5821" }, { } }; MODULE_DEVICE_TABLE(i2c, max5821_id); diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 23b9e3a09ec8..2d6bcfd5deaa 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -523,8 +523,8 @@ static const struct mcp4725_chip_info mcp4726 = { }; static const struct i2c_device_id mcp4725_id[] = { - { "mcp4725", (kernel_ulong_t)&mcp4725 }, - { "mcp4726", (kernel_ulong_t)&mcp4726 }, + { .name = "mcp4725", .driver_data = (kernel_ulong_t)&mcp4725 }, + { .name = "mcp4726", .driver_data = (kernel_ulong_t)&mcp4726 }, { } }; MODULE_DEVICE_TABLE(i2c, mcp4725_id); diff --git a/drivers/iio/dac/mcp4728.c b/drivers/iio/dac/mcp4728.c index 4f30b99110b7..64bd9490fc19 100644 --- a/drivers/iio/dac/mcp4728.c +++ b/drivers/iio/dac/mcp4728.c @@ -572,7 +572,7 @@ static int mcp4728_probe(struct i2c_client *client) } static const struct i2c_device_id mcp4728_id[] = { - { "mcp4728" }, + { .name = "mcp4728" }, { } }; MODULE_DEVICE_TABLE(i2c, mcp4728_id); diff --git a/drivers/iio/dac/mcp47feb02.c b/drivers/iio/dac/mcp47feb02.c index faccb804a5ed..217f78e44af1 100644 --- a/drivers/iio/dac/mcp47feb02.c +++ b/drivers/iio/dac/mcp47feb02.c @@ -1170,30 +1170,30 @@ static int mcp47feb02_probe(struct i2c_client *client) } static const struct i2c_device_id mcp47feb02_id[] = { - { "mcp47feb01", (kernel_ulong_t)&mcp47feb01_chip_features }, - { "mcp47feb02", (kernel_ulong_t)&mcp47feb02_chip_features }, - { "mcp47feb04", (kernel_ulong_t)&mcp47feb04_chip_features }, - { "mcp47feb08", (kernel_ulong_t)&mcp47feb08_chip_features }, - { "mcp47feb11", (kernel_ulong_t)&mcp47feb11_chip_features }, - { "mcp47feb12", (kernel_ulong_t)&mcp47feb12_chip_features }, - { "mcp47feb14", (kernel_ulong_t)&mcp47feb14_chip_features }, - { "mcp47feb18", (kernel_ulong_t)&mcp47feb18_chip_features }, - { "mcp47feb21", (kernel_ulong_t)&mcp47feb21_chip_features }, - { "mcp47feb22", (kernel_ulong_t)&mcp47feb22_chip_features }, - { "mcp47feb24", (kernel_ulong_t)&mcp47feb24_chip_features }, - { "mcp47feb28", (kernel_ulong_t)&mcp47feb28_chip_features }, - { "mcp47fvb01", (kernel_ulong_t)&mcp47fvb01_chip_features }, - { "mcp47fvb02", (kernel_ulong_t)&mcp47fvb02_chip_features }, - { "mcp47fvb04", (kernel_ulong_t)&mcp47fvb04_chip_features }, - { "mcp47fvb08", (kernel_ulong_t)&mcp47fvb08_chip_features }, - { "mcp47fvb11", (kernel_ulong_t)&mcp47fvb11_chip_features }, - { "mcp47fvb12", (kernel_ulong_t)&mcp47fvb12_chip_features }, - { "mcp47fvb14", (kernel_ulong_t)&mcp47fvb14_chip_features }, - { "mcp47fvb18", (kernel_ulong_t)&mcp47fvb18_chip_features }, - { "mcp47fvb21", (kernel_ulong_t)&mcp47fvb21_chip_features }, - { "mcp47fvb22", (kernel_ulong_t)&mcp47fvb22_chip_features }, - { "mcp47fvb24", (kernel_ulong_t)&mcp47fvb24_chip_features }, - { "mcp47fvb28", (kernel_ulong_t)&mcp47fvb28_chip_features }, + { .name = "mcp47feb01", .driver_data = (kernel_ulong_t)&mcp47feb01_chip_features }, + { .name = "mcp47feb02", .driver_data = (kernel_ulong_t)&mcp47feb02_chip_features }, + { .name = "mcp47feb04", .driver_data = (kernel_ulong_t)&mcp47feb04_chip_features }, + { .name = "mcp47feb08", .driver_data = (kernel_ulong_t)&mcp47feb08_chip_features }, + { .name = "mcp47feb11", .driver_data = (kernel_ulong_t)&mcp47feb11_chip_features }, + { .name = "mcp47feb12", .driver_data = (kernel_ulong_t)&mcp47feb12_chip_features }, + { .name = "mcp47feb14", .driver_data = (kernel_ulong_t)&mcp47feb14_chip_features }, + { .name = "mcp47feb18", .driver_data = (kernel_ulong_t)&mcp47feb18_chip_features }, + { .name = "mcp47feb21", .driver_data = (kernel_ulong_t)&mcp47feb21_chip_features }, + { .name = "mcp47feb22", .driver_data = (kernel_ulong_t)&mcp47feb22_chip_features }, + { .name = "mcp47feb24", .driver_data = (kernel_ulong_t)&mcp47feb24_chip_features }, + { .name = "mcp47feb28", .driver_data = (kernel_ulong_t)&mcp47feb28_chip_features }, + { .name = "mcp47fvb01", .driver_data = (kernel_ulong_t)&mcp47fvb01_chip_features }, + { .name = "mcp47fvb02", .driver_data = (kernel_ulong_t)&mcp47fvb02_chip_features }, + { .name = "mcp47fvb04", .driver_data = (kernel_ulong_t)&mcp47fvb04_chip_features }, + { .name = "mcp47fvb08", .driver_data = (kernel_ulong_t)&mcp47fvb08_chip_features }, + { .name = "mcp47fvb11", .driver_data = (kernel_ulong_t)&mcp47fvb11_chip_features }, + { .name = "mcp47fvb12", .driver_data = (kernel_ulong_t)&mcp47fvb12_chip_features }, + { .name = "mcp47fvb14", .driver_data = (kernel_ulong_t)&mcp47fvb14_chip_features }, + { .name = "mcp47fvb18", .driver_data = (kernel_ulong_t)&mcp47fvb18_chip_features }, + { .name = "mcp47fvb21", .driver_data = (kernel_ulong_t)&mcp47fvb21_chip_features }, + { .name = "mcp47fvb22", .driver_data = (kernel_ulong_t)&mcp47fvb22_chip_features }, + { .name = "mcp47fvb24", .driver_data = (kernel_ulong_t)&mcp47fvb24_chip_features }, + { .name = "mcp47fvb28", .driver_data = (kernel_ulong_t)&mcp47fvb28_chip_features }, { } }; MODULE_DEVICE_TABLE(i2c, mcp47feb02_id); diff --git a/drivers/iio/dac/mcp4821.c b/drivers/iio/dac/mcp4821.c index 748bdca9a964..18b5934fb8a2 100644 --- a/drivers/iio/dac/mcp4821.c +++ b/drivers/iio/dac/mcp4821.c @@ -12,13 +12,13 @@ * MCP48x2: https://ww1.microchip.com/downloads/en/DeviceDoc/20002249B.pdf * * TODO: - * - Configurable gain * - Regulator control */ #include #include #include +#include #include #include @@ -26,12 +26,32 @@ #include #define MCP4821_ACTIVE_MODE BIT(12) +#define MCP4821_GAIN_ENABLE BIT(13) #define MCP4802_SECOND_CHAN BIT(15) -/* DAC uses an internal Voltage reference of 4.096V at a gain of 2x */ -#define MCP4821_2X_GAIN_VREF_MV 4096 +/* DAC uses an internal Voltage reference of 2.048V */ +#define MCP4821_VREF_MV 2048 -enum mcp4821_supported_drvice_ids { +/* + * MCP48xx DAC output: + * + * Vout = (Vref * D / 2^N) * G + * + * where: + * - Vref = 2.048V (internal reference) + * - N = DAC resolution (12 bits for MCP4821) + * - G = gain selection: + * 1x when GA bit = 1 + * 2x when GA bit = 0 (default) + * + * Therefore full-scale voltage is: + * - 1x gain: 2.048V + * - 2x gain: 4.096V + * + * Scale = Vfull-scale / 2^N + */ + +enum mcp4821_supported_device_ids { ID_MCP4801, ID_MCP4802, ID_MCP4811, @@ -43,6 +63,8 @@ enum mcp4821_supported_drvice_ids { struct mcp4821_state { struct spi_device *spi; u16 dac_value[2]; + int gain; + int scale_avail[4]; }; struct mcp4821_chip_info { @@ -57,6 +79,7 @@ struct mcp4821_chip_info { .channel = (channel_id), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \ .scan_type = { \ .realbits = (resolution), \ .shift = 12 - (resolution), \ @@ -115,15 +138,15 @@ static int mcp4821_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - struct mcp4821_state *state; + struct mcp4821_state *state = iio_priv(indio_dev); switch (mask) { case IIO_CHAN_INFO_RAW: - state = iio_priv(indio_dev); *val = state->dac_value[chan->channel]; return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: - *val = MCP4821_2X_GAIN_VREF_MV; + *val = MCP4821_VREF_MV * state->gain; *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; default: @@ -131,6 +154,17 @@ static int mcp4821_read_raw(struct iio_dev *indio_dev, } } +static void mcp4821_calc_scale(int vref_mv, int resolution, + int *val, int *val2) +{ + s64 tmp; + int micro; + + tmp = (s64)vref_mv * MICRO >> resolution; + *val = div_s64_rem(tmp, MICRO, µ); + *val2 = micro; +} + static int mcp4821_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -139,35 +173,85 @@ static int mcp4821_write_raw(struct iio_dev *indio_dev, u16 write_val; __be16 write_buffer; int ret; + int v, v2; - if (val2 != 0) + switch (mask) { + case IIO_CHAN_INFO_RAW: + + if (val2 != 0) + return -EINVAL; + + if (val < 0 || val >= BIT(chan->scan_type.realbits)) + return -EINVAL; + + write_val = MCP4821_ACTIVE_MODE | val << chan->scan_type.shift; + if (chan->channel) + write_val |= MCP4802_SECOND_CHAN; + + /* GA bit = 1 -> 1x gain */ + if (state->gain == 1) + write_val |= MCP4821_GAIN_ENABLE; + + write_buffer = cpu_to_be16(write_val); + ret = spi_write(state->spi, &write_buffer, sizeof(write_buffer)); + if (ret) { + dev_err(&state->spi->dev, "Failed to write to device: %d", ret); + return ret; + } + + state->dac_value[chan->channel] = val; + return 0; + + case IIO_CHAN_INFO_SCALE: + mcp4821_calc_scale(MCP4821_VREF_MV, chan->scan_type.realbits, &v, &v2); + if (val == v && val2 == v2) { + state->gain = 1; + return 0; + } + + mcp4821_calc_scale(MCP4821_VREF_MV * 2, + chan->scan_type.realbits, &v, &v2); + if (val == v && val2 == v2) { + state->gain = 2; + return 0; + } return -EINVAL; - - if (val < 0 || val >= BIT(chan->scan_type.realbits)) + default: return -EINVAL; - - if (mask != IIO_CHAN_INFO_RAW) - return -EINVAL; - - write_val = MCP4821_ACTIVE_MODE | val << chan->scan_type.shift; - if (chan->channel) - write_val |= MCP4802_SECOND_CHAN; - - write_buffer = cpu_to_be16(write_val); - ret = spi_write(state->spi, &write_buffer, sizeof(write_buffer)); - if (ret) { - dev_err(&state->spi->dev, "Failed to write to device: %d", ret); - return ret; } +} - state->dac_value[chan->channel] = val; +static inline void mcp4821_init_avail_gain(struct mcp4821_state *state, + int resolution) +{ + state->scale_avail[0] = MCP4821_VREF_MV; + state->scale_avail[1] = resolution; + state->scale_avail[2] = MCP4821_VREF_MV * 2; + state->scale_avail[3] = resolution; +} - return 0; +static int mcp4821_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long info) +{ + struct mcp4821_state *state = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_SCALE: + *vals = state->scale_avail; + *type = IIO_VAL_FRACTIONAL_LOG2; + *length = ARRAY_SIZE(state->scale_avail); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } } static const struct iio_info mcp4821_info = { .read_raw = &mcp4821_read_raw, .write_raw = &mcp4821_write_raw, + .read_avail = &mcp4821_read_avail, }; static int mcp4821_probe(struct spi_device *spi) @@ -183,12 +267,15 @@ static int mcp4821_probe(struct spi_device *spi) state = iio_priv(indio_dev); state->spi = spi; + /* default gain is 2x */ + state->gain = 2; info = spi_get_device_match_data(spi); indio_dev->name = info->name; indio_dev->info = &mcp4821_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = info->channels; indio_dev->num_channels = info->num_channels; + mcp4821_init_avail_gain(state, info->channels[0].scan_type.realbits); return devm_iio_device_register(&spi->dev, indio_dev); } diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index 455d61fc3f13..b9efd704e996 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -402,17 +402,17 @@ static const struct of_device_id dac5571_of_id[] = { MODULE_DEVICE_TABLE(of, dac5571_of_id); static const struct i2c_device_id dac5571_id[] = { - {"dac081c081", (kernel_ulong_t)&dac5571_spec[single_8bit] }, - {"dac121c081", (kernel_ulong_t)&dac5571_spec[single_12bit] }, - {"dac5571", (kernel_ulong_t)&dac5571_spec[single_8bit] }, - {"dac6571", (kernel_ulong_t)&dac5571_spec[single_10bit] }, - {"dac7571", (kernel_ulong_t)&dac5571_spec[single_12bit] }, - {"dac5574", (kernel_ulong_t)&dac5571_spec[quad_8bit] }, - {"dac6574", (kernel_ulong_t)&dac5571_spec[quad_10bit] }, - {"dac7574", (kernel_ulong_t)&dac5571_spec[quad_12bit] }, - {"dac5573", (kernel_ulong_t)&dac5571_spec[quad_8bit] }, - {"dac6573", (kernel_ulong_t)&dac5571_spec[quad_10bit] }, - {"dac7573", (kernel_ulong_t)&dac5571_spec[quad_12bit] }, + { .name = "dac081c081", .driver_data = (kernel_ulong_t)&dac5571_spec[single_8bit] }, + { .name = "dac121c081", .driver_data = (kernel_ulong_t)&dac5571_spec[single_12bit] }, + { .name = "dac5571", .driver_data = (kernel_ulong_t)&dac5571_spec[single_8bit] }, + { .name = "dac6571", .driver_data = (kernel_ulong_t)&dac5571_spec[single_10bit] }, + { .name = "dac7571", .driver_data = (kernel_ulong_t)&dac5571_spec[single_12bit] }, + { .name = "dac5574", .driver_data = (kernel_ulong_t)&dac5571_spec[quad_8bit] }, + { .name = "dac6574", .driver_data = (kernel_ulong_t)&dac5571_spec[quad_10bit] }, + { .name = "dac7574", .driver_data = (kernel_ulong_t)&dac5571_spec[quad_12bit] }, + { .name = "dac5573", .driver_data = (kernel_ulong_t)&dac5571_spec[quad_8bit] }, + { .name = "dac6573", .driver_data = (kernel_ulong_t)&dac5571_spec[quad_10bit] }, + { .name = "dac7573", .driver_data = (kernel_ulong_t)&dac5571_spec[quad_12bit] }, { } }; MODULE_DEVICE_TABLE(i2c, dac5571_id); diff --git a/drivers/iio/frequency/adrf6780.c b/drivers/iio/frequency/adrf6780.c index 257fd31a0b0e..9911b5273b22 100644 --- a/drivers/iio/frequency/adrf6780.c +++ b/drivers/iio/frequency/adrf6780.c @@ -188,8 +188,11 @@ static int adrf6780_read_adc_raw(struct adrf6780_state *st, unsigned int *read_v if (ret) goto exit; - /* Recommended delay for the ADC to be ready*/ - usleep_range(200, 250); + /* + * Per ADRF6780 datasheet (Rev. D, page 23, ADC section), + * wait approximately 200 us for the ADC to be ready. + */ + fsleep(200); ret = __adrf6780_spi_read(st, ADRF6780_REG_ADC_OUTPUT, read_val); if (ret) diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index 3efe385ebedc..35928383d4f2 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -115,65 +116,53 @@ static const int adxrs290_hpf_3db_freq_hz_table[][2] = { static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int *val) { struct adxrs290_state *st = iio_priv(indio_dev); - int ret = 0; int temp; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + temp = spi_w8r16(st->spi, cmd); - if (temp < 0) { - ret = temp; - goto err_unlock; - } + if (temp < 0) + return temp; *val = sign_extend32(temp, 15); -err_unlock: - mutex_unlock(&st->lock); - return ret; + return 0; } static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) { const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_TEMP0); struct adxrs290_state *st = iio_priv(indio_dev); - int ret = 0; int temp; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + temp = spi_w8r16(st->spi, cmd); - if (temp < 0) { - ret = temp; - goto err_unlock; - } + if (temp < 0) + return temp; /* extract lower 12 bits temperature reading */ *val = sign_extend32(temp, 11); -err_unlock: - mutex_unlock(&st->lock); - return ret; + return 0; } static int adxrs290_get_3db_freq(struct iio_dev *indio_dev, u8 *val, u8 *val2) { const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_FILTER); struct adxrs290_state *st = iio_priv(indio_dev); - int ret = 0; short temp; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + temp = spi_w8r8(st->spi, cmd); - if (temp < 0) { - ret = temp; - goto err_unlock; - } + if (temp < 0) + return temp; *val = FIELD_GET(ADXRS290_LPF_MASK, temp); *val2 = FIELD_GET(ADXRS290_HPF_MASK, temp); -err_unlock: - mutex_unlock(&st->lock); - return ret; + return 0; } static int adxrs290_spi_write_reg(struct spi_device *spi, const u8 reg, @@ -220,11 +209,11 @@ static int adxrs290_set_mode(struct iio_dev *indio_dev, enum adxrs290_mode mode) if (st->mode == mode) return 0; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = spi_w8r8(st->spi, ADXRS290_READ_REG(ADXRS290_REG_POWER_CTL)); if (ret < 0) - goto out_unlock; + return ret; val = ret; @@ -236,21 +225,18 @@ static int adxrs290_set_mode(struct iio_dev *indio_dev, enum adxrs290_mode mode) val |= ADXRS290_MEASUREMENT; break; default: - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_POWER_CTL, val); if (ret < 0) { dev_err(&st->spi->dev, "unable to set mode: %d\n", ret); - goto out_unlock; + return ret; } /* update cached mode */ st->mode = mode; -out_unlock: - mutex_unlock(&st->lock); return ret; } @@ -506,19 +492,20 @@ static irqreturn_t adxrs290_trigger_handler(int irq, void *p) u8 tx = ADXRS290_READ_REG(ADXRS290_REG_DATAX0); int ret; - mutex_lock(&st->lock); + do { + guard(mutex)(&st->lock); - /* exercise a bulk data capture starting from reg DATAX0... */ - ret = spi_write_then_read(st->spi, &tx, sizeof(tx), st->buffer.channels, - sizeof(st->buffer.channels)); - if (ret < 0) - goto out_unlock_notify; + /* exercise a bulk data capture starting from reg DATAX0... */ + ret = spi_write_then_read(st->spi, &tx, sizeof(tx), + st->buffer.channels, + sizeof(st->buffer.channels)); + if (ret < 0) + break; - iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, - pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, + pf->timestamp); + } while (0); -out_unlock_notify: - mutex_unlock(&st->lock); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 38394b5f3275..d611341a0e2a 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -201,6 +201,9 @@ static int bmg160_get_filter(struct bmg160_data *data, int *val) break; } + if (i == ARRAY_SIZE(bmg160_samp_freq_table)) + return -EINVAL; + *val = bmg160_samp_freq_table[i].filter; return ret ? ret : IIO_VAL_INT; @@ -218,6 +221,9 @@ static int bmg160_set_filter(struct bmg160_data *data, int val) break; } + if (i == ARRAY_SIZE(bmg160_samp_freq_table)) + return -EINVAL; + ret = regmap_write(data->regmap, BMG160_REG_PMU_BW, bmg160_samp_freq_table[i].bw_bits); if (ret < 0) { @@ -258,8 +264,14 @@ static int bmg160_chip_init(struct bmg160_data *data) if (ret < 0) return ret; - /* Wait upto 500 ms to be ready after changing mode */ - usleep_range(500, 1000); + /* + * Wait for the chip to be ready after switching to normal mode. + * The BMG160 datasheet (BST-BMG160-DS000-07 Rev. 1.0, May 2013) + * specifies a start-up / wake-up time (tsu, twusm) of 30 ms; use + * BMG160_MAX_STARTUP_TIME_MS (80 ms) as a safety margin, matching + * what bmg160_runtime_resume() already does. + */ + msleep(BMG160_MAX_STARTUP_TIME_MS); /* Set Bandwidth */ ret = bmg160_set_bw(data, BMG160_DEF_BW); diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c index 1fb8a7969c25..028e5e29c6a1 100644 --- a/drivers/iio/gyro/bmg160_i2c.c +++ b/drivers/iio/gyro/bmg160_i2c.c @@ -47,9 +47,9 @@ static const struct acpi_device_id bmg160_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match); static const struct i2c_device_id bmg160_i2c_id[] = { - { "bmg160" }, - { "bmi055_gyro" }, - { "bmi088_gyro" }, + { .name = "bmg160" }, + { .name = "bmi055_gyro" }, + { .name = "bmi088_gyro" }, { } }; diff --git a/drivers/iio/gyro/fxas21002c_i2c.c b/drivers/iio/gyro/fxas21002c_i2c.c index 43c6b3079487..d537e91caaaf 100644 --- a/drivers/iio/gyro/fxas21002c_i2c.c +++ b/drivers/iio/gyro/fxas21002c_i2c.c @@ -39,7 +39,7 @@ static void fxas21002c_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id fxas21002c_i2c_id[] = { - { "fxas21002c" }, + { .name = "fxas21002c" }, { } }; MODULE_DEVICE_TABLE(i2c, fxas21002c_i2c_id); diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index c340cc899a7c..e48c25c87b6d 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -3,6 +3,7 @@ * HID Sensors Driver * Copyright (c) 2012, Intel Corporation. */ +#include #include #include #include @@ -82,17 +83,6 @@ static const struct iio_chan_spec gyro_3d_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP) }; -/* Adjust channel real bits based on report descriptor */ -static void gyro_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - /* Channel read_raw handler */ static int gyro_3d_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -248,19 +238,20 @@ static int gyro_3d_parse_report(struct platform_device *pdev, struct gyro_3d_state *st) { int ret; - int i; - for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) { + for (unsigned int ch = CHANNEL_SCAN_INDEX_X; ch <= CHANNEL_SCAN_INDEX_Z; ch++) { ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, usage_id, - HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS + i, - &st->gyro[CHANNEL_SCAN_INDEX_X + i]); + HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS + ch, + &st->gyro[ch]); if (ret < 0) break; - gyro_3d_adjust_channel_bit_mask(channels, - CHANNEL_SCAN_INDEX_X + i, - st->gyro[CHANNEL_SCAN_INDEX_X + i].size); + channels[ch].scan_type = (struct iio_scan_type) { + .format = 's', + .realbits = BYTES_TO_BITS(st->gyro[ch].size), + .storagebits = BITS_PER_TYPE(u32), + }; } dev_dbg(&pdev->dev, "gyro_3d %x:%x, %x:%x, %x:%x\n", st->gyro[0].index, diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index bfe95ec1abda..6b13d54d9b01 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -389,7 +389,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(itg3200_pm_ops, itg3200_suspend, itg3200_resume); static const struct i2c_device_id itg3200_id[] = { - { "itg3200" }, + { .name = "itg3200" }, { } }; MODULE_DEVICE_TABLE(i2c, itg3200_id); diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c index 6549b22e643d..2a5bcec7272c 100644 --- a/drivers/iio/gyro/mpu3050-i2c.c +++ b/drivers/iio/gyro/mpu3050-i2c.c @@ -92,7 +92,7 @@ static void mpu3050_i2c_remove(struct i2c_client *client) * supported by this driver */ static const struct i2c_device_id mpu3050_i2c_id[] = { - { "mpu3050" }, + { .name = "mpu3050" }, { } }; MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id); diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c index d9b41cf8d799..1acbbc1eeec3 100644 --- a/drivers/iio/gyro/ssp_gyro_sensor.c +++ b/drivers/iio/gyro/ssp_gyro_sensor.c @@ -76,7 +76,7 @@ static const struct iio_chan_spec ssp_gyro_channels[] = { SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X), SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y), SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z), - SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), + IIO_CHAN_SOFT_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), }; static int ssp_process_gyro_data(struct iio_dev *indio_dev, void *buf, diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index aef5ec8f9dee..b07cb39051b3 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -93,15 +93,15 @@ static int st_gyro_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id st_gyro_id_table[] = { - { L3G4200D_GYRO_DEV_NAME }, - { LSM330D_GYRO_DEV_NAME }, - { LSM330DL_GYRO_DEV_NAME }, - { LSM330DLC_GYRO_DEV_NAME }, - { L3GD20_GYRO_DEV_NAME }, - { L3GD20H_GYRO_DEV_NAME }, - { L3G4IS_GYRO_DEV_NAME }, - { LSM330_GYRO_DEV_NAME }, - { LSM9DS0_GYRO_DEV_NAME }, + { .name = L3G4200D_GYRO_DEV_NAME }, + { .name = LSM330D_GYRO_DEV_NAME }, + { .name = LSM330DL_GYRO_DEV_NAME }, + { .name = LSM330DLC_GYRO_DEV_NAME }, + { .name = L3GD20_GYRO_DEV_NAME }, + { .name = L3GD20H_GYRO_DEV_NAME }, + { .name = L3G4IS_GYRO_DEV_NAME }, + { .name = LSM330_GYRO_DEV_NAME }, + { .name = LSM9DS0_GYRO_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, st_gyro_id_table); diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index 032da52a96d0..2357e2dd7017 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -575,7 +575,7 @@ static int afe4404_probe(struct i2c_client *client) } static const struct i2c_device_id afe4404_ids[] = { - { "afe4404" }, + { .name = "afe4404" }, { } }; MODULE_DEVICE_TABLE(i2c, afe4404_ids); diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index 7dfdb5eb305e..97352485f5e2 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -507,7 +507,7 @@ static void max30100_remove(struct i2c_client *client) } static const struct i2c_device_id max30100_id[] = { - { "max30100" }, + { .name = "max30100" }, { } }; MODULE_DEVICE_TABLE(i2c, max30100_id); diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 47da44efd68b..c830eaf286f7 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -596,9 +596,9 @@ static void max30102_remove(struct i2c_client *client) } static const struct i2c_device_id max30102_id[] = { - { "max30101", max30105 }, - { "max30102", max30102 }, - { "max30105", max30105 }, + { .name = "max30101", .driver_data = max30105 }, + { .name = "max30102", .driver_data = max30102 }, + { .name = "max30105", .driver_data = max30105 }, { } }; MODULE_DEVICE_TABLE(i2c, max30102_id); diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 02ca23eb8991..f29baa251f9f 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -250,7 +250,7 @@ static int am2315_probe(struct i2c_client *client) } static const struct i2c_device_id am2315_i2c_id[] = { - { "am2315" }, + { .name = "am2315" }, { } }; MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); diff --git a/drivers/iio/humidity/ens210.c b/drivers/iio/humidity/ens210.c index 77418d97f30d..49543fc389bf 100644 --- a/drivers/iio/humidity/ens210.c +++ b/drivers/iio/humidity/ens210.c @@ -149,15 +149,16 @@ static int ens210_read_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case IIO_CHAN_INFO_RAW: - scoped_guard(mutex, &data->lock) { - ret = ens210_get_measurement( - indio_dev, channel->type == IIO_TEMP, val); - if (ret) - return ret; - return IIO_VAL_INT; - } - return -EINVAL; /* compiler warning workaround */ + case IIO_CHAN_INFO_RAW: { + guard(mutex)(&data->lock); + + ret = ens210_get_measurement(indio_dev, channel->type == IIO_TEMP, + val); + if (ret) + return ret; + + return IIO_VAL_INT; + } case IIO_CHAN_INFO_SCALE: if (channel->type == IIO_TEMP) { *val = 15; @@ -314,12 +315,12 @@ static const struct of_device_id ens210_of_match[] = { MODULE_DEVICE_TABLE(of, ens210_of_match); static const struct i2c_device_id ens210_id_table[] = { - { "ens210", (kernel_ulong_t)&ens210_chip_info_data }, - { "ens210a", (kernel_ulong_t)&ens210a_chip_info_data }, - { "ens211", (kernel_ulong_t)&ens211_chip_info_data }, - { "ens212", (kernel_ulong_t)&ens212_chip_info_data }, - { "ens213a", (kernel_ulong_t)&ens213a_chip_info_data }, - { "ens215", (kernel_ulong_t)&ens215_chip_info_data }, + { .name = "ens210", .driver_data = (kernel_ulong_t)&ens210_chip_info_data }, + { .name = "ens210a", .driver_data = (kernel_ulong_t)&ens210a_chip_info_data }, + { .name = "ens211", .driver_data = (kernel_ulong_t)&ens211_chip_info_data }, + { .name = "ens212", .driver_data = (kernel_ulong_t)&ens212_chip_info_data }, + { .name = "ens213a", .driver_data = (kernel_ulong_t)&ens213a_chip_info_data }, + { .name = "ens215", .driver_data = (kernel_ulong_t)&ens215_chip_info_data }, { } }; MODULE_DEVICE_TABLE(i2c, ens210_id_table); diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index c2b36e682e06..87194802cc4f 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -380,12 +380,12 @@ static int hdc100x_probe(struct i2c_client *client) } static const struct i2c_device_id hdc100x_id[] = { - { "hdc100x" }, - { "hdc1000" }, - { "hdc1008" }, - { "hdc1010" }, - { "hdc1050" }, - { "hdc1080" }, + { .name = "hdc100x" }, + { .name = "hdc1000" }, + { .name = "hdc1008" }, + { .name = "hdc1010" }, + { .name = "hdc1050" }, + { .name = "hdc1080" }, { } }; MODULE_DEVICE_TABLE(i2c, hdc100x_id); diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c index 1a0f18251381..82d68987556d 100644 --- a/drivers/iio/humidity/hdc2010.c +++ b/drivers/iio/humidity/hdc2010.c @@ -317,8 +317,8 @@ static void hdc2010_remove(struct i2c_client *client) } static const struct i2c_device_id hdc2010_id[] = { - { "hdc2010" }, - { "hdc2080" }, + { .name = "hdc2010" }, + { .name = "hdc2080" }, { } }; MODULE_DEVICE_TABLE(i2c, hdc2010_id); diff --git a/drivers/iio/humidity/hdc3020.c b/drivers/iio/humidity/hdc3020.c index 78b2c171c8da..1ae8702ada54 100644 --- a/drivers/iio/humidity/hdc3020.c +++ b/drivers/iio/humidity/hdc3020.c @@ -873,9 +873,9 @@ static int hdc3020_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(hdc3020_pm_ops, hdc3020_suspend, hdc3020_resume); static const struct i2c_device_id hdc3020_id[] = { - { "hdc3020" }, - { "hdc3021" }, - { "hdc3022" }, + { .name = "hdc3020" }, + { .name = "hdc3021" }, + { .name = "hdc3022" }, { } }; MODULE_DEVICE_TABLE(i2c, hdc3020_id); diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c index cbaa7d1af6c4..e823d37384d7 100644 --- a/drivers/iio/humidity/hts221_i2c.c +++ b/drivers/iio/humidity/hts221_i2c.c @@ -53,7 +53,7 @@ static const struct of_device_id hts221_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, hts221_i2c_of_match); static const struct i2c_device_id hts221_i2c_id_table[] = { - { HTS221_DEV_NAME }, + { .name = HTS221_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table); diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index 7f1775bd26fd..9ba7507f105e 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c @@ -230,8 +230,8 @@ static int htu21_probe(struct i2c_client *client) } static const struct i2c_device_id htu21_id[] = { - {"htu21", HTU21}, - {"ms8607-humidity", MS8607}, + { .name = "htu21", .driver_data = HTU21 }, + { .name = "ms8607-humidity", .driver_data = MS8607 }, { } }; MODULE_DEVICE_TABLE(i2c, htu21_id); diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c index 0797ece1fcba..0c11d0d3afe0 100644 --- a/drivers/iio/humidity/si7005.c +++ b/drivers/iio/humidity/si7005.c @@ -163,8 +163,8 @@ static int si7005_probe(struct i2c_client *client) } static const struct i2c_device_id si7005_id[] = { - { "si7005" }, - { "th02" }, + { .name = "si7005" }, + { .name = "th02" }, { } }; MODULE_DEVICE_TABLE(i2c, si7005_id); diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index ff2dba50c0a5..9fb1e3ede3ff 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -267,8 +267,8 @@ static int si7020_probe(struct i2c_client *client) } static const struct i2c_device_id si7020_id[] = { - { "si7020" }, - { "th06" }, + { .name = "si7020" }, + { .name = "th06" }, { } }; MODULE_DEVICE_TABLE(i2c, si7020_id); diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c index 3e2758f4e0d3..29f3c4acb123 100644 --- a/drivers/iio/imu/bmi160/bmi160_i2c.c +++ b/drivers/iio/imu/bmi160/bmi160_i2c.c @@ -38,8 +38,8 @@ static int bmi160_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bmi160_i2c_id[] = { - { "bmi120" }, - { "bmi160" }, + { .name = "bmi120" }, + { .name = "bmi160" }, { } }; MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id); diff --git a/drivers/iio/imu/bmi270/bmi270_i2c.c b/drivers/iio/imu/bmi270/bmi270_i2c.c index b92da4e0776f..1e6839f9669e 100644 --- a/drivers/iio/imu/bmi270/bmi270_i2c.c +++ b/drivers/iio/imu/bmi270/bmi270_i2c.c @@ -33,8 +33,8 @@ static int bmi270_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bmi270_i2c_id[] = { - { "bmi260", (kernel_ulong_t)&bmi260_chip_info }, - { "bmi270", (kernel_ulong_t)&bmi270_chip_info }, + { .name = "bmi260", .driver_data = (kernel_ulong_t)&bmi260_chip_info }, + { .name = "bmi270", .driver_data = (kernel_ulong_t)&bmi270_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, bmi270_i2c_id); diff --git a/drivers/iio/imu/bmi323/bmi323_i2c.c b/drivers/iio/imu/bmi323/bmi323_i2c.c index 8457fe304db8..328733ddeed7 100644 --- a/drivers/iio/imu/bmi323/bmi323_i2c.c +++ b/drivers/iio/imu/bmi323/bmi323_i2c.c @@ -114,7 +114,7 @@ static const struct acpi_device_id bmi323_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, bmi323_acpi_match); static const struct i2c_device_id bmi323_i2c_ids[] = { - { "bmi323" }, + { .name = "bmi323" }, { } }; MODULE_DEVICE_TABLE(i2c, bmi323_i2c_ids); diff --git a/drivers/iio/imu/bno055/bno055.c b/drivers/iio/imu/bno055/bno055.c index c96fec2ebb3e..d0101607a9b3 100644 --- a/drivers/iio/imu/bno055/bno055.c +++ b/drivers/iio/imu/bno055/bno055.c @@ -210,9 +210,30 @@ struct bno055_priv { u8 uid[BNO055_UID_LEN]; struct gpio_desc *reset_gpio; bool sw_reset; - struct { - __le16 chans[BNO055_SCAN_CH_COUNT]; - aligned_s64 timestamp; + union { + IIO_DECLARE_BUFFER_WITH_TS(__le16, chans, BNO055_SCAN_CH_COUNT); + /* + * This struct is not used, but it is here to ensure proper size + * and alignment of the scan buffer above (because of the extra + * requirements of the quaternion field). Technically it is not + * needed in this case, because other fields just happen to make + * things correctly aligned already. But it is better to be + * explicit about the requirements anyway. The actual contents + * of the scan buffer will vary depending on which channels are + * enabled. + */ + struct { + __le16 acc[3]; + __le16 magn[3]; + __le16 gyr[3]; + __le16 yaw; + __le16 pitch; + __le16 roll; + IIO_DECLARE_QUATERNION(__le16, quaternion); + __le16 lia[3]; + __le16 gravity[3]; + aligned_s64 timestamp; + }; } buf; struct dentry *debugfs; }; diff --git a/drivers/iio/imu/bno055/bno055_i2c.c b/drivers/iio/imu/bno055/bno055_i2c.c index f49d0905ee33..000bc9392480 100644 --- a/drivers/iio/imu/bno055/bno055_i2c.c +++ b/drivers/iio/imu/bno055/bno055_i2c.c @@ -30,7 +30,7 @@ static int bno055_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bno055_i2c_id[] = { - { "bno055" }, + { .name = "bno055" }, { } }; MODULE_DEVICE_TABLE(i2c, bno055_i2c_id); diff --git a/drivers/iio/imu/bno055/bno055_ser_core.c b/drivers/iio/imu/bno055/bno055_ser_core.c index 48669dabb37b..733f9112de06 100644 --- a/drivers/iio/imu/bno055/bno055_ser_core.c +++ b/drivers/iio/imu/bno055/bno055_ser_core.c @@ -288,7 +288,7 @@ static int bno055_ser_write_reg(void *context, const void *_data, size_t count) struct bno055_ser_priv *priv = context; if (count < 2) { - dev_err(&priv->serdev->dev, "Invalid write count %zu", count); + dev_err(&priv->serdev->dev, "Invalid write count %zu\n", count); return -EINVAL; } @@ -306,7 +306,7 @@ static int bno055_ser_read_reg(void *context, struct bno055_ser_priv *priv = context; if (val_size > 128) { - dev_err(&priv->serdev->dev, "Invalid read valsize %zu", val_size); + dev_err(&priv->serdev->dev, "Invalid read valsize %zu\n", val_size); return -EINVAL; } diff --git a/drivers/iio/imu/fxos8700_i2c.c b/drivers/iio/imu/fxos8700_i2c.c index 2cc4a27a4527..c81e48c9d8e2 100644 --- a/drivers/iio/imu/fxos8700_i2c.c +++ b/drivers/iio/imu/fxos8700_i2c.c @@ -36,7 +36,7 @@ static int fxos8700_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id fxos8700_i2c_id[] = { - { "fxos8700" }, + { .name = "fxos8700" }, { } }; MODULE_DEVICE_TABLE(i2c, fxos8700_i2c_id); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c index 7e4d3ea68721..99d37ac53bbe 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -75,13 +75,13 @@ static int inv_icm42600_probe(struct i2c_client *client) * supported by this driver */ static const struct i2c_device_id inv_icm42600_id[] = { - { "icm42600", INV_CHIP_ICM42600 }, - { "icm42602", INV_CHIP_ICM42602 }, - { "icm42605", INV_CHIP_ICM42605 }, - { "icm42686", INV_CHIP_ICM42686 }, - { "icm42622", INV_CHIP_ICM42622 }, - { "icm42688", INV_CHIP_ICM42688 }, - { "icm42631", INV_CHIP_ICM42631 }, + { .name = "icm42600", .driver_data = INV_CHIP_ICM42600 }, + { .name = "icm42602", .driver_data = INV_CHIP_ICM42602 }, + { .name = "icm42605", .driver_data = INV_CHIP_ICM42605 }, + { .name = "icm42686", .driver_data = INV_CHIP_ICM42686 }, + { .name = "icm42622", .driver_data = INV_CHIP_ICM42622 }, + { .name = "icm42688", .driver_data = INV_CHIP_ICM42688 }, + { .name = "icm42631", .driver_data = INV_CHIP_ICM42631 }, { } }; MODULE_DEVICE_TABLE(i2c, inv_icm42600_id); diff --git a/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c b/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c index 5ebc18121a11..26fba538a3cf 100644 --- a/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c +++ b/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c @@ -39,14 +39,14 @@ static int inv_icm45600_probe(struct i2c_client *client) * supported by this driver. */ static const struct i2c_device_id inv_icm45600_id[] = { - { "icm45605", (kernel_ulong_t)&inv_icm45605_chip_info }, - { "icm45606", (kernel_ulong_t)&inv_icm45606_chip_info }, - { "icm45608", (kernel_ulong_t)&inv_icm45608_chip_info }, - { "icm45634", (kernel_ulong_t)&inv_icm45634_chip_info }, - { "icm45686", (kernel_ulong_t)&inv_icm45686_chip_info }, - { "icm45687", (kernel_ulong_t)&inv_icm45687_chip_info }, - { "icm45688p", (kernel_ulong_t)&inv_icm45688p_chip_info }, - { "icm45689", (kernel_ulong_t)&inv_icm45689_chip_info }, + { .name = "icm45605", .driver_data = (kernel_ulong_t)&inv_icm45605_chip_info }, + { .name = "icm45606", .driver_data = (kernel_ulong_t)&inv_icm45606_chip_info }, + { .name = "icm45608", .driver_data = (kernel_ulong_t)&inv_icm45608_chip_info }, + { .name = "icm45634", .driver_data = (kernel_ulong_t)&inv_icm45634_chip_info }, + { .name = "icm45686", .driver_data = (kernel_ulong_t)&inv_icm45686_chip_info }, + { .name = "icm45687", .driver_data = (kernel_ulong_t)&inv_icm45687_chip_info }, + { .name = "icm45688p", .driver_data = (kernel_ulong_t)&inv_icm45688p_chip_info }, + { .name = "icm45689", .driver_data = (kernel_ulong_t)&inv_icm45689_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, inv_icm45600_id); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 8dc61812a8fc..4868e1576cee 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -174,24 +174,24 @@ static void inv_mpu_remove(struct i2c_client *client) * supported by this driver */ static const struct i2c_device_id inv_mpu_id[] = { - {"mpu6050", INV_MPU6050}, - {"mpu6500", INV_MPU6500}, - {"mpu6515", INV_MPU6515}, - {"mpu6880", INV_MPU6880}, - {"mpu9150", INV_MPU9150}, - {"mpu9250", INV_MPU9250}, - {"mpu9255", INV_MPU9255}, - {"icm20608", INV_ICM20608}, - {"icm20608d", INV_ICM20608D}, - {"icm20609", INV_ICM20609}, - {"icm20689", INV_ICM20689}, - {"icm20600", INV_ICM20600}, - {"icm20602", INV_ICM20602}, - {"icm20690", INV_ICM20690}, - {"iam20380", INV_IAM20380}, - {"iam20680", INV_IAM20680}, - {"iam20680hp", INV_IAM20680HP}, - {"iam20680ht", INV_IAM20680HT}, + { .name = "mpu6050", .driver_data = INV_MPU6050 }, + { .name = "mpu6500", .driver_data = INV_MPU6500 }, + { .name = "mpu6515", .driver_data = INV_MPU6515 }, + { .name = "mpu6880", .driver_data = INV_MPU6880 }, + { .name = "mpu9150", .driver_data = INV_MPU9150 }, + { .name = "mpu9250", .driver_data = INV_MPU9250 }, + { .name = "mpu9255", .driver_data = INV_MPU9255 }, + { .name = "icm20608", .driver_data = INV_ICM20608 }, + { .name = "icm20608d", .driver_data = INV_ICM20608D }, + { .name = "icm20609", .driver_data = INV_ICM20609 }, + { .name = "icm20689", .driver_data = INV_ICM20689 }, + { .name = "icm20600", .driver_data = INV_ICM20600 }, + { .name = "icm20602", .driver_data = INV_ICM20602 }, + { .name = "icm20690", .driver_data = INV_ICM20690 }, + { .name = "iam20380", .driver_data = INV_IAM20380 }, + { .name = "iam20680", .driver_data = INV_IAM20680 }, + { .name = "iam20680hp", .driver_data = INV_IAM20680HP }, + { .name = "iam20680ht", .driver_data = INV_IAM20680HT }, { } }; diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 3cd91d8a89ee..b8a8297b39af 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -7,6 +7,7 @@ * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). */ +#include #include #include #include @@ -783,7 +784,7 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, struct kmx61_data *data = kmx61_get_data(indio_dev); switch (mask) { - case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_RAW: { switch (chan->type) { case IIO_ACCEL: base_reg = KMX61_ACC_XOUT_L; @@ -794,28 +795,24 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - mutex_lock(&data->lock); + guard(mutex)(&data->lock); ret = kmx61_set_power_state(data, true, chan->address); - if (ret) { - mutex_unlock(&data->lock); + if (ret) return ret; - } ret = kmx61_read_measurement(data, base_reg, chan->scan_index); if (ret < 0) { kmx61_set_power_state(data, false, chan->address); - mutex_unlock(&data->lock); return ret; } *val = sign_extend32(ret >> chan->scan_type.shift, chan->scan_type.realbits - 1); ret = kmx61_set_power_state(data, false, chan->address); - - mutex_unlock(&data->lock); if (ret) return ret; return IIO_VAL_INT; + } case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ACCEL: @@ -830,45 +827,46 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case IIO_CHAN_INFO_SAMP_FREQ: + case IIO_CHAN_INFO_SAMP_FREQ: { if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) return -EINVAL; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + ret = kmx61_get_odr(data, val, val2, chan->address); - mutex_unlock(&data->lock); if (ret) return -EINVAL; return IIO_VAL_INT_PLUS_MICRO; } - return -EINVAL; + default: + return -EINVAL; + } } static int kmx61_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { - int ret; struct kmx61_data *data = kmx61_get_data(indio_dev); switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: + case IIO_CHAN_INFO_SAMP_FREQ: { if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) return -EINVAL; - mutex_lock(&data->lock); - ret = kmx61_set_odr(data, val, val2, chan->address); - mutex_unlock(&data->lock); - return ret; + guard(mutex)(&data->lock); + + return kmx61_set_odr(data, val, val2, chan->address); + } case IIO_CHAN_INFO_SCALE: switch (chan->type) { - case IIO_ACCEL: + case IIO_ACCEL: { if (val != 0) return -EINVAL; - mutex_lock(&data->lock); - ret = kmx61_set_scale(data, val2); - mutex_unlock(&data->lock); - return ret; + guard(mutex)(&data->lock); + + return kmx61_set_scale(data, val2); + } default: return -EINVAL; } @@ -945,29 +943,26 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, if (state && data->ev_enable_state) return 0; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); if (!state && data->motion_trig_on) { data->ev_enable_state = false; - goto err_unlock; + return ret; } ret = kmx61_set_power_state(data, state, KMX61_ACC); if (ret < 0) - goto err_unlock; + return ret; ret = kmx61_setup_any_motion_interrupt(data, state); if (ret < 0) { kmx61_set_power_state(data, false, KMX61_ACC); - goto err_unlock; + return ret; } data->ev_enable_state = state; -err_unlock: - mutex_unlock(&data->lock); - - return ret; + return 0; } static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, @@ -1020,11 +1015,11 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct kmx61_data *data = kmx61_get_data(indio_dev); - mutex_lock(&data->lock); + guard(mutex)(&data->lock); if (!state && data->ev_enable_state && data->motion_trig_on) { data->motion_trig_on = false; - goto err_unlock; + return ret; } if (data->acc_dready_trig == trig || data->motion_trig == trig) @@ -1034,7 +1029,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, ret = kmx61_set_power_state(data, state, device); if (ret < 0) - goto err_unlock; + return ret; if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) ret = kmx61_setup_new_data_interrupt(data, state, device); @@ -1042,7 +1037,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, ret = kmx61_setup_any_motion_interrupt(data, state); if (ret < 0) { kmx61_set_power_state(data, false, device); - goto err_unlock; + return ret; } if (data->acc_dready_trig == trig) @@ -1051,10 +1046,8 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, data->mag_dready_trig_on = state; else data->motion_trig_on = state; -err_unlock: - mutex_unlock(&data->lock); - return ret; + return 0; } static void kmx61_trig_reenable(struct iio_trigger *trig) @@ -1181,30 +1174,49 @@ static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) return IRQ_HANDLED; } -static irqreturn_t kmx61_trigger_handler(int irq, void *p) +/** + * kmx61_read_for_each_active_channel() - Read each active channel into a buffer + * + * @indio_dev: IIO Device struct to read from + * @buffer: Destination buffer to write to, the array must be of at least size 8 + * + * Return: + * 0 on success, negative errno on failure. + */ +static int kmx61_read_for_each_active_channel(struct iio_dev *indio_dev, s16 *buffer) { - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; struct kmx61_data *data = kmx61_get_data(indio_dev); - int bit, ret, i = 0; u8 base; - s16 buffer[8] = { }; + int ret, bit; + int i = 0; if (indio_dev == data->acc_indio_dev) base = KMX61_ACC_XOUT_L; else base = KMX61_MAG_XOUT_L; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + iio_for_each_active_channel(indio_dev, bit) { ret = kmx61_read_measurement(data, base, bit); - if (ret < 0) { - mutex_unlock(&data->lock); - goto err; - } + if (ret < 0) + return ret; buffer[i++] = ret; } - mutex_unlock(&data->lock); + + return 0; +} + +static irqreturn_t kmx61_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + int ret; + s16 buffer[8] = { }; + + ret = kmx61_read_for_each_active_channel(indio_dev, buffer); + if (ret < 0) + goto err; iio_push_to_buffers(indio_dev, buffer); err: @@ -1419,22 +1431,18 @@ static void kmx61_remove(struct i2c_client *client) iio_trigger_unregister(data->motion_trig); } - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - mutex_unlock(&data->lock); } static int kmx61_suspend(struct device *dev) { - int ret; struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, - false); - mutex_unlock(&data->lock); + guard(mutex)(&data->lock); - return ret; + return kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, false); } static int kmx61_resume(struct device *dev) @@ -1453,13 +1461,10 @@ static int kmx61_resume(struct device *dev) static int kmx61_runtime_suspend(struct device *dev) { struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); - int ret; - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - mutex_unlock(&data->lock); + guard(mutex)(&data->lock); - return ret; + return kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); } static int kmx61_runtime_resume(struct device *dev) @@ -1481,7 +1486,7 @@ static const struct dev_pm_ops kmx61_pm_ops = { }; static const struct i2c_device_id kmx61_id[] = { - { "kmx611021" }, + { .name = "kmx611021" }, { } }; diff --git a/drivers/iio/imu/st_lsm6dsx/Makefile b/drivers/iio/imu/st_lsm6dsx/Makefile index 57cbcd67d64f..19a488254de3 100644 --- a/drivers/iio/imu/st_lsm6dsx/Makefile +++ b/drivers/iio/imu/st_lsm6dsx/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only st_lsm6dsx-y := st_lsm6dsx_core.o st_lsm6dsx_buffer.o \ - st_lsm6dsx_shub.o + st_lsm6dsx_shub.o st_lsm6dsx_fusion.o obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 07b1773c87bd..767aadfe7061 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -294,6 +294,7 @@ enum st_lsm6dsx_sensor_id { ST_LSM6DSX_ID_EXT0, ST_LSM6DSX_ID_EXT1, ST_LSM6DSX_ID_EXT2, + ST_LSM6DSX_ID_FUSION, ST_LSM6DSX_ID_MAX }; @@ -301,6 +302,17 @@ enum st_lsm6dsx_ext_sensor_id { ST_LSM6DSX_ID_MAGN, }; +struct st_lsm6dsx_fusion_settings { + const struct iio_chan_spec *chan; + int chan_len; + struct st_lsm6dsx_reg odr_reg; + int odr_hz[ST_LSM6DSX_ODR_LIST_SIZE]; + int odr_len; + struct st_lsm6dsx_reg fifo_enable; + struct st_lsm6dsx_reg page_mux; + struct st_lsm6dsx_reg enable; +}; + /** * struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings * @i2c_addr: I2c slave address list. @@ -388,6 +400,7 @@ struct st_lsm6dsx_settings { struct st_lsm6dsx_hw_ts_settings ts_settings; struct st_lsm6dsx_shub_settings shub_settings; struct st_lsm6dsx_event_settings event_settings; + struct st_lsm6dsx_fusion_settings fusion_settings; }; enum st_lsm6dsx_fifo_mode { @@ -510,6 +523,9 @@ int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val); int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name); int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len); +int st_lsm6dsx_fusion_probe(struct st_lsm6dsx_hw *hw, const char *name); +int st_lsm6dsx_fusion_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable); +int st_lsm6dsx_fusion_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable); static inline int @@ -564,12 +580,14 @@ st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, static inline int st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) { - if (sensor->id == ST_LSM6DSX_ID_EXT0 || - sensor->id == ST_LSM6DSX_ID_EXT1 || - sensor->id == ST_LSM6DSX_ID_EXT2) + switch (sensor->id) { + case ST_LSM6DSX_ID_EXT0 ... ST_LSM6DSX_ID_EXT2: return st_lsm6dsx_shub_set_enable(sensor, enable); - - return st_lsm6dsx_sensor_set_enable(sensor, enable); + case ST_LSM6DSX_ID_FUSION: + return st_lsm6dsx_fusion_set_enable(sensor, enable); + default: + return st_lsm6dsx_sensor_set_enable(sensor, enable); + } } static const diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 48291203d1cd..777d479f10c0 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -88,6 +88,7 @@ enum st_lsm6dsx_fifo_tag { ST_LSM6DSX_EXT0_TAG = 0x0f, ST_LSM6DSX_EXT1_TAG = 0x10, ST_LSM6DSX_EXT2_TAG = 0x11, + ST_LSM6DSX_ROT_TAG = 0x13, }; static const @@ -226,8 +227,11 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor, u8 data; /* Only internal sensors have a FIFO ODR configuration register. */ - if (sensor->id >= ARRAY_SIZE(hw->settings->batch)) + if (sensor->id >= ARRAY_SIZE(hw->settings->batch)) { + if (sensor->id == ST_LSM6DSX_ID_FUSION) + return st_lsm6dsx_fusion_set_odr(sensor, enable); return 0; + } batch_reg = &hw->settings->batch[sensor->id]; if (batch_reg->addr) { @@ -365,8 +369,6 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr, return 0; } -#define ST_LSM6DSX_IIO_BUFF_SIZE (ALIGN(ST_LSM6DSX_SAMPLE_SIZE, \ - sizeof(s64)) + sizeof(s64)) /** * st_lsm6dsx_read_fifo() - hw FIFO read routine * @hw: Pointer to instance of struct st_lsm6dsx_hw. @@ -537,16 +539,23 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) } #define ST_LSM6DSX_INVALID_SAMPLE 0x7ffd -static int -st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag, - u8 *data, s64 ts) +static bool st_lsm6dsx_check_data(u8 tag, __le16 *data) +{ + if ((tag == ST_LSM6DSX_GYRO_TAG || tag == ST_LSM6DSX_ACC_TAG) && + (s16)le16_to_cpup(data) >= ST_LSM6DSX_INVALID_SAMPLE) + return false; + + return true; +} + +static int st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag, + __le16 *data, s64 ts) { - s16 val = le16_to_cpu(*(__le16 *)data); struct st_lsm6dsx_sensor *sensor; struct iio_dev *iio_dev; /* invalid sample during bootstrap phase */ - if (val >= ST_LSM6DSX_INVALID_SAMPLE) + if (!st_lsm6dsx_check_data(tag, data)) return -EINVAL; /* @@ -580,6 +589,9 @@ st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag, case ST_LSM6DSX_EXT2_TAG: iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT2]; break; + case ST_LSM6DSX_ROT_TAG: + iio_dev = hw->iio_devs[ST_LSM6DSX_ID_FUSION]; + break; default: return -EINVAL; } @@ -609,7 +621,13 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw) * must be passed a buffer that is aligned to 8 bytes so * as to allow insertion of a naturally aligned timestamp. */ - u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE] __aligned(8) = { }; + struct { + union { + __le16 data[3]; + __le32 fifo_ts; + }; + aligned_s64 timestamp; + } iio_buff = { }; u8 tag; bool reset_ts = false; int i, err, read_len; @@ -648,7 +666,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw) for (i = 0; i < pattern_len; i += ST_LSM6DSX_TAGGED_SAMPLE_SIZE) { - memcpy(iio_buff, &hw->buff[i + ST_LSM6DSX_TAG_SIZE], + memcpy(&iio_buff, &hw->buff[i + ST_LSM6DSX_TAG_SIZE], ST_LSM6DSX_SAMPLE_SIZE); tag = hw->buff[i] >> 3; @@ -659,7 +677,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw) * B0 = ts[7:0], B1 = ts[15:8], B2 = ts[23:16], * B3 = ts[31:24] */ - ts = le32_to_cpu(*((__le32 *)iio_buff)); + ts = le32_to_cpu(iio_buff.fifo_ts); /* * check if hw timestamp engine is going to * reset (the sensor generates an interrupt @@ -670,7 +688,8 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw) reset_ts = true; ts *= hw->ts_gain; } else { - st_lsm6dsx_push_tagged_data(hw, tag, iio_buff, + st_lsm6dsx_push_tagged_data(hw, tag, + iio_buff.data, ts); } } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 450cb5b47346..630e2cae6f19 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -94,6 +94,26 @@ #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f +/* Raw values from the IMU are 16-bit half-precision floating-point numbers. */ +#define ST_LSM6DSX_CHANNEL_ROT \ +{ \ + .type = IIO_ROT, \ + .modified = 1, \ + .channel2 = IIO_MOD_QUATERNION_AXIS, \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = 0, \ + .scan_type = { \ + .format = IIO_SCAN_FORMAT_FLOAT, \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + .repeat = 3, \ + }, \ + .ext_info = st_lsm6dsx_ext_info, \ +} + static const struct iio_event_spec st_lsm6dsx_ev_motion[] = { { .type = IIO_EV_TYPE_THRESH, @@ -153,6 +173,11 @@ static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3), }; +static const struct iio_chan_spec st_lsm6dsx_fusion_channels[] = { + ST_LSM6DSX_CHANNEL_ROT, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { .reset = { @@ -1492,6 +1517,33 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, }, + .fusion_settings = { + .chan = st_lsm6dsx_fusion_channels, + .chan_len = ARRAY_SIZE(st_lsm6dsx_fusion_channels), + .odr_reg = { + .addr = 0x5e, + .mask = GENMASK(5, 3), + }, + .odr_hz[0] = 15, + .odr_hz[1] = 30, + .odr_hz[2] = 60, + .odr_hz[3] = 120, + .odr_hz[4] = 240, + .odr_hz[5] = 480, + .odr_len = 6, + .fifo_enable = { + .addr = 0x44, + .mask = BIT(1), + }, + .page_mux = { + .addr = 0x01, + .mask = BIT(7), + }, + .enable = { + .addr = 0x04, + .mask = BIT(1), + }, + }, }, { .reset = { @@ -2899,6 +2951,12 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } + if (hw->settings->fusion_settings.chan) { + err = st_lsm6dsx_fusion_probe(hw, name); + if (err) + return err; + } + if (hw->irq > 0) { err = st_lsm6dsx_irq_setup(hw); if (err < 0) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c new file mode 100644 index 000000000000..2e72c7ba94dd --- /dev/null +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * STMicroelectronics st_lsm6dsx IMU sensor fusion + * + * Copyright 2026 BayLibre, SAS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st_lsm6dsx.h" + +static int +st_lsm6dsx_fusion_get_odr_val(const struct st_lsm6dsx_fusion_settings *settings, + u32 odr_mHz, u8 *val) +{ + int odr_hz = odr_mHz / MILLI; + int i; + + for (i = 0; i < settings->odr_len; i++) { + if (settings->odr_hz[i] == odr_hz) + break; + } + if (i == settings->odr_len) + return -EINVAL; + + *val = i; + return 0; +} + +/** + * st_lsm6dsx_fusion_page_enable - Enable access to sensor fusion configuration + * registers. + * @hw: Sensor hardware instance. + * + * Return: 0 on success, negative value on error. + */ +static int st_lsm6dsx_fusion_page_enable(struct st_lsm6dsx_hw *hw) +{ + const struct st_lsm6dsx_reg *mux; + + mux = &hw->settings->fusion_settings.page_mux; + + return regmap_set_bits(hw->regmap, mux->addr, mux->mask); +} + +/** + * st_lsm6dsx_fusion_page_disable - Disable access to sensor fusion + * configuration registers. + * @hw: Sensor hardware instance. + * + * Return: 0 on success, negative value on error. + */ +static int st_lsm6dsx_fusion_page_disable(struct st_lsm6dsx_hw *hw) +{ + const struct st_lsm6dsx_reg *mux; + + mux = &hw->settings->fusion_settings.page_mux; + + return regmap_clear_bits(hw->regmap, mux->addr, mux->mask); +} + +static int st_lsm6dsx_fusion_set_odr_locked(struct st_lsm6dsx_sensor *sensor, + bool enable) +{ + const struct st_lsm6dsx_fusion_settings *settings; + struct st_lsm6dsx_hw *hw = sensor->hw; + int err; + + settings = &hw->settings->fusion_settings; + if (enable) { + const struct st_lsm6dsx_reg *reg = &settings->odr_reg; + u8 odr_val; + u8 data; + + st_lsm6dsx_fusion_get_odr_val(settings, sensor->hwfifo_odr_mHz, + &odr_val); + data = ST_LSM6DSX_SHIFT_VAL(odr_val, reg->mask); + err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, + data); + if (err) + return err; + } + + return regmap_assign_bits(hw->regmap, settings->fifo_enable.addr, + settings->fifo_enable.mask, enable); +} + +int st_lsm6dsx_fusion_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) +{ + struct st_lsm6dsx_hw *hw = sensor->hw; + const struct st_lsm6dsx_reg *en_reg; + int err; + + guard(mutex)(&hw->page_lock); + + en_reg = &hw->settings->fusion_settings.enable; + err = st_lsm6dsx_fusion_page_enable(hw); + if (err) + return err; + + err = regmap_assign_bits(hw->regmap, en_reg->addr, en_reg->mask, enable); + if (err) { + st_lsm6dsx_fusion_page_disable(hw); + return err; + } + + return st_lsm6dsx_fusion_page_disable(hw); +} + +int st_lsm6dsx_fusion_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable) +{ + struct st_lsm6dsx_hw *hw = sensor->hw; + int err; + + guard(mutex)(&hw->page_lock); + + err = st_lsm6dsx_fusion_page_enable(hw); + if (err) + return err; + + err = st_lsm6dsx_fusion_set_odr_locked(sensor, enable); + if (err) { + st_lsm6dsx_fusion_page_disable(hw); + return err; + } + + return st_lsm6dsx_fusion_page_disable(hw); +} + +static int st_lsm6dsx_fusion_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *ch, + int *val, int *val2, long mask) +{ + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *val = sensor->hwfifo_odr_mHz / MILLI; + *val2 = (sensor->hwfifo_odr_mHz % MILLI) * (MICRO / MILLI); + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int st_lsm6dsx_fusion_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + const struct st_lsm6dsx_fusion_settings *settings; + int err; + + settings = &sensor->hw->settings->fusion_settings; + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: { + u32 odr_mHz = val * MILLI + val2 * (MILLI / MICRO); + u8 odr_val; + + /* check that the requested frequency is supported */ + err = st_lsm6dsx_fusion_get_odr_val(settings, odr_mHz, &odr_val); + if (err) + return err; + + sensor->hwfifo_odr_mHz = odr_mHz; + return 0; + } + default: + return -EINVAL; + } +} + +static int st_lsm6dsx_fusion_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, + int *length, long mask) +{ + struct st_lsm6dsx_sensor *sensor = iio_priv(indio_dev); + const struct st_lsm6dsx_fusion_settings *settings; + + settings = &sensor->hw->settings->fusion_settings; + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = settings->odr_hz; + *type = IIO_VAL_INT; + *length = settings->odr_len; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static const struct iio_info st_lsm6dsx_fusion_info = { + .read_raw = st_lsm6dsx_fusion_read_raw, + .read_avail = st_lsm6dsx_fusion_read_avail, + .write_raw = st_lsm6dsx_fusion_write_raw, + .hwfifo_set_watermark = st_lsm6dsx_set_watermark, +}; + +int st_lsm6dsx_fusion_probe(struct st_lsm6dsx_hw *hw, const char *name) +{ + const struct st_lsm6dsx_fusion_settings *settings; + struct st_lsm6dsx_sensor *sensor; + struct iio_dev *iio_dev; + int ret; + + iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); + if (!iio_dev) + return -ENOMEM; + + settings = &hw->settings->fusion_settings; + sensor = iio_priv(iio_dev); + sensor->id = ST_LSM6DSX_ID_FUSION; + sensor->hw = hw; + sensor->hwfifo_odr_mHz = settings->odr_hz[0] * MILLI; + sensor->watermark = 1; + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->info = &st_lsm6dsx_fusion_info; + iio_dev->channels = settings->chan; + iio_dev->num_channels = settings->chan_len; + ret = snprintf(sensor->name, sizeof(sensor->name), "%s_fusion", name); + if (ret >= sizeof(sensor->name)) + return -E2BIG; + iio_dev->name = sensor->name; + + /* + * Put the IIO device pointer in the iio_devs array so that the caller + * can set up a buffer and register this IIO device. + */ + hw->iio_devs[ST_LSM6DSX_ID_FUSION] = iio_dev; + + return 0; +} diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index b2a7c2eaf50d..edec898cb11f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -150,30 +150,30 @@ static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, st_lsm6dsx_i2c_acpi_match); static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { - { ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID }, - { ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID }, - { ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID }, - { ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID }, - { ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID }, - { ST_LSM6DSO_DEV_NAME, ST_LSM6DSO_ID }, - { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, - { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, - { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, - { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, - { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, - { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, - { ST_LSM6DS0_DEV_NAME, ST_LSM6DS0_ID }, - { ST_LSM6DSRX_DEV_NAME, ST_LSM6DSRX_ID }, - { ST_LSM6DST_DEV_NAME, ST_LSM6DST_ID }, - { ST_LSM6DSOP_DEV_NAME, ST_LSM6DSOP_ID }, - { ST_ASM330LHHX_DEV_NAME, ST_ASM330LHHX_ID }, - { ST_LSM6DSTX_DEV_NAME, ST_LSM6DSTX_ID }, - { ST_LSM6DSV_DEV_NAME, ST_LSM6DSV_ID }, - { ST_LSM6DSV16X_DEV_NAME, ST_LSM6DSV16X_ID }, - { ST_LSM6DSO16IS_DEV_NAME, ST_LSM6DSO16IS_ID }, - { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID }, - { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID }, - { ST_ASM330LHHXG1_DEV_NAME, ST_ASM330LHHXG1_ID }, + { .name = ST_LSM6DS3_DEV_NAME, .driver_data = ST_LSM6DS3_ID }, + { .name = ST_LSM6DS3H_DEV_NAME, .driver_data = ST_LSM6DS3H_ID }, + { .name = ST_LSM6DSL_DEV_NAME, .driver_data = ST_LSM6DSL_ID }, + { .name = ST_LSM6DSM_DEV_NAME, .driver_data = ST_LSM6DSM_ID }, + { .name = ST_ISM330DLC_DEV_NAME, .driver_data = ST_ISM330DLC_ID }, + { .name = ST_LSM6DSO_DEV_NAME, .driver_data = ST_LSM6DSO_ID }, + { .name = ST_ASM330LHH_DEV_NAME, .driver_data = ST_ASM330LHH_ID }, + { .name = ST_LSM6DSOX_DEV_NAME, .driver_data = ST_LSM6DSOX_ID }, + { .name = ST_LSM6DSR_DEV_NAME, .driver_data = ST_LSM6DSR_ID }, + { .name = ST_LSM6DS3TRC_DEV_NAME, .driver_data = ST_LSM6DS3TRC_ID }, + { .name = ST_ISM330DHCX_DEV_NAME, .driver_data = ST_ISM330DHCX_ID }, + { .name = ST_LSM9DS1_DEV_NAME, .driver_data = ST_LSM9DS1_ID }, + { .name = ST_LSM6DS0_DEV_NAME, .driver_data = ST_LSM6DS0_ID }, + { .name = ST_LSM6DSRX_DEV_NAME, .driver_data = ST_LSM6DSRX_ID }, + { .name = ST_LSM6DST_DEV_NAME, .driver_data = ST_LSM6DST_ID }, + { .name = ST_LSM6DSOP_DEV_NAME, .driver_data = ST_LSM6DSOP_ID }, + { .name = ST_ASM330LHHX_DEV_NAME, .driver_data = ST_ASM330LHHX_ID }, + { .name = ST_LSM6DSTX_DEV_NAME, .driver_data = ST_LSM6DSTX_ID }, + { .name = ST_LSM6DSV_DEV_NAME, .driver_data = ST_LSM6DSV_ID }, + { .name = ST_LSM6DSV16X_DEV_NAME, .driver_data = ST_LSM6DSV16X_ID }, + { .name = ST_LSM6DSO16IS_DEV_NAME, .driver_data = ST_LSM6DSO16IS_ID }, + { .name = ST_ISM330IS_DEV_NAME, .driver_data = ST_ISM330IS_ID }, + { .name = ST_ASM330LHB_DEV_NAME, .driver_data = ST_ASM330LHB_ID }, + { .name = ST_ASM330LHHXG1_DEV_NAME, .driver_data = ST_ASM330LHHXG1_ID }, { } }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c index 4232a9d800fc..f71ae7a59a22 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c @@ -33,8 +33,8 @@ static const struct of_device_id st_lsm9ds0_of_match[] = { MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); static const struct i2c_device_id st_lsm9ds0_id_table[] = { - { LSM303D_IMU_DEV_NAME }, - { LSM9DS0_IMU_DEV_NAME }, + { .name = LSM303D_IMU_DEV_NAME }, + { .name = LSM9DS0_IMU_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table); diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c index 10e689f49441..4763e224ebc6 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -156,7 +156,7 @@ static ssize_t iio_backend_debugfs_write_reg(struct file *file, ssize_t rc; int ret; - if (count >= sizeof(buf)) + if (*ppos != 0 || count >= sizeof(buf)) return -ENOSPC; rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count); @@ -964,23 +964,13 @@ int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address) } EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, "IIO_BACKEND"); -static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name, - struct fwnode_handle *fwnode) +static struct iio_backend *__devm_iio_backend_fwnode_get_by_index(struct device *dev, + struct fwnode_handle *fwnode, + unsigned int index) { struct iio_backend *back; - unsigned int index; int ret; - if (name) { - ret = device_property_match_string(dev, "io-backend-names", - name); - if (ret < 0) - return ERR_PTR(ret); - index = ret; - } else { - index = 0; - } - struct fwnode_handle *fwnode_back __free(fwnode_handle) = fwnode_find_reference(fwnode, "io-backends", index); if (IS_ERR(fwnode_back)) @@ -996,8 +986,7 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con if (ret) return ERR_PTR(ret); - if (name) - back->idx = index; + back->idx = index; return back; } @@ -1005,6 +994,24 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con return ERR_PTR(-EPROBE_DEFER); } +static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name, + struct fwnode_handle *fwnode) +{ + unsigned int index; + int ret; + + if (name) { + ret = device_property_match_string(dev, "io-backend-names", name); + if (ret < 0) + return ERR_PTR(ret); + index = ret; + } else { + index = 0; + } + + return __devm_iio_backend_fwnode_get_by_index(dev, fwnode, index); +} + /** * devm_iio_backend_get - Device managed backend device get * @dev: Consumer device for the backend @@ -1021,6 +1028,22 @@ struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name) } EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, "IIO_BACKEND"); +/** + * devm_iio_backend_get_by_index - Device managed backend device get by index + * @dev: Consumer device for the backend + * @index: Index of the backend in the io-backends property + * + * Gets the backend at @index associated with @dev. + * + * RETURNS: + * A backend pointer, negative error pointer otherwise. + */ +struct iio_backend *devm_iio_backend_get_by_index(struct device *dev, unsigned int index) +{ + return __devm_iio_backend_fwnode_get_by_index(dev, dev_fwnode(dev), index); +} +EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get_by_index, "IIO_BACKEND"); + /** * devm_iio_backend_fwnode_get - Device managed backend firmware node get * @dev: Consumer device for the backend diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 5c3df993bea2..531fc4ccc15d 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -750,7 +750,7 @@ static int iio_storage_bytes_for_si(struct iio_dev *indio_dev, bytes = scan_type->storagebits / 8; if (scan_type->repeat > 1) - bytes *= scan_type->repeat; + bytes *= roundup_pow_of_two(scan_type->repeat); return bytes; } @@ -764,7 +764,9 @@ static int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) } static int iio_compute_scan_bytes(struct iio_dev *indio_dev, - const unsigned long *mask, bool timestamp) + const unsigned long *mask, bool timestamp, + unsigned int *scan_bytes, + unsigned int *timestamp_offset) { unsigned int bytes = 0; int length, i, largest = 0; @@ -786,12 +788,17 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, return length; bytes = ALIGN(bytes, length); + + if (timestamp_offset) + *timestamp_offset = bytes; + bytes += length; largest = max(largest, length); } - bytes = ALIGN(bytes, largest); - return bytes; + *scan_bytes = ALIGN(bytes, largest); + + return 0; } static void iio_buffer_activate(struct iio_dev *indio_dev, @@ -836,18 +843,23 @@ static int iio_buffer_disable(struct iio_buffer *buffer, return buffer->access->disable(buffer, indio_dev); } -static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, - struct iio_buffer *buffer) +static int iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, + struct iio_buffer *buffer) { unsigned int bytes; + int ret; if (!buffer->access->set_bytes_per_datum) - return; + return 0; - bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask, - buffer->scan_timestamp); + ret = iio_compute_scan_bytes(indio_dev, buffer->scan_mask, + buffer->scan_timestamp, &bytes, NULL); + if (ret) + return ret; buffer->access->set_bytes_per_datum(buffer, bytes); + + return 0; } static int iio_buffer_request_update(struct iio_dev *indio_dev, @@ -855,7 +867,10 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev, { int ret; - iio_buffer_update_bytes_per_datum(indio_dev, buffer); + ret = iio_buffer_update_bytes_per_datum(indio_dev, buffer); + if (ret) + return ret; + if (buffer->access->request_update) { ret = buffer->access->request_update(buffer); if (ret) { @@ -882,6 +897,7 @@ struct iio_device_config { unsigned int watermark; const unsigned long *scan_mask; unsigned int scan_bytes; + unsigned int scan_timestamp_offset; bool scan_timestamp; }; @@ -898,6 +914,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, struct iio_buffer *buffer; bool scan_timestamp; unsigned int modes; + int ret; if (insert_buffer && bitmap_empty(insert_buffer->scan_mask, masklength)) { @@ -985,8 +1002,12 @@ static int iio_verify_update(struct iio_dev *indio_dev, scan_mask = compound_mask; } - config->scan_bytes = iio_compute_scan_bytes(indio_dev, - scan_mask, scan_timestamp); + ret = iio_compute_scan_bytes(indio_dev, scan_mask, scan_timestamp, + &config->scan_bytes, + &config->scan_timestamp_offset); + if (ret) + return ret; + config->scan_mask = scan_mask; config->scan_timestamp = scan_timestamp; @@ -1141,6 +1162,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, indio_dev->active_scan_mask = config->scan_mask; ACCESS_PRIVATE(indio_dev, scan_timestamp) = config->scan_timestamp; indio_dev->scan_bytes = config->scan_bytes; + ACCESS_PRIVATE(indio_dev, scan_timestamp_offset) = config->scan_timestamp_offset; iio_dev_opaque->currentmode = config->mode; iio_update_demux(indio_dev); @@ -2423,7 +2445,7 @@ EXPORT_SYMBOL_GPL(iio_push_to_buffers); int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev, const void *data, size_t data_sz, - int64_t timestamp) + s64 timestamp) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 22eefd048ba9..7e3d3872e2e6 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -98,6 +98,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CHROMATICITY] = "chromaticity", [IIO_ATTENTION] = "attention", [IIO_ALTCURRENT] = "altcurrent", + [IIO_COVERAGE] = "coverage", }; static const char * const iio_modifier_names[] = { @@ -157,6 +158,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_ACTIVE] = "active", [IIO_MOD_REACTIVE] = "reactive", [IIO_MOD_APPARENT] = "apparent", + [IIO_MOD_QUATERNION_AXIS] = "quaternionaxis", }; /* relies on pairs of these shared then separate */ @@ -418,7 +420,7 @@ static ssize_t iio_debugfs_write_reg(struct file *file, char buf[80]; int ret; - if (count >= sizeof(buf)) + if (*ppos != 0 || count >= sizeof(buf)) return -EINVAL; ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index eff33e456c70..ef36824f312f 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -119,6 +119,20 @@ config APDS9960 To compile this driver as a module, choose M here: the module will be called apds9960 +config APDS9999 + tristate "Broadcom APDS9999 ALS, RGB and proximity sensor" + depends on I2C + help + Say Y here if you want to build support for the Broadcom APDS9999 + ALS, RGB and proximity sensor with I2C interface. + + This driver provides ambient light sensing (ALS/Lux), raw + intensity data for red, green, blue and IR channels, plus + proximity detection support. + + To compile this driver as a module, choose M here: the + module will be called apds9999. + config AS73211 tristate "AMS AS73211 XYZ color sensor and AMS AS7331 UV sensor" depends on I2C @@ -699,6 +713,17 @@ config VEML3235 To compile this driver as a module, choose M here: the module will be called veml3235. +config VEML3328 + tristate "VEML3328 RGBCIR light sensor" + select REGMAP_I2C + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML3328 + RGB IR light sensor. + + To compile this driver as a module, choose M here: the + module will be called veml3328 + config VEML6030 tristate "VEML6030 and VEML6035 ambient light sensors" select REGMAP_I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index c0048e0d5ca8..64e354c49ed8 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_APDS9160) += apds9160.o obj-$(CONFIG_APDS9300) += apds9300.o obj-$(CONFIG_APDS9306) += apds9306.o obj-$(CONFIG_APDS9960) += apds9960.o +obj-$(CONFIG_APDS9999) += apds9999.o obj-$(CONFIG_AS73211) += as73211.o obj-$(CONFIG_BH1745) += bh1745.o obj-$(CONFIG_BH1750) += bh1750.o @@ -65,6 +66,7 @@ obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_VCNL4000) += vcnl4000.o obj-$(CONFIG_VCNL4035) += vcnl4035.o obj-$(CONFIG_VEML3235) += veml3235.o +obj-$(CONFIG_VEML3328) += veml3328.o obj-$(CONFIG_VEML6030) += veml6030.o obj-$(CONFIG_VEML6040) += veml6040.o obj-$(CONFIG_VEML6046X00) += veml6046x00.o diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c index ab229318dce9..1983a7f17aa9 100644 --- a/drivers/iio/light/acpi-als.c +++ b/drivers/iio/light/acpi-als.c @@ -179,11 +179,15 @@ static irqreturn_t acpi_als_trigger_handler(int irq, void *p) static int acpi_als_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acpi_device *device = ACPI_COMPANION(dev); + struct acpi_device *device; struct iio_dev *indio_dev; struct acpi_als *als; int ret; + device = ACPI_COMPANION(dev); + if (!device) + return -ENODEV; + indio_dev = devm_iio_device_alloc(dev, sizeof(*als)); if (!indio_dev) return -ENOMEM; diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index edb3d9dc8bed..088b9431d10a 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -260,7 +260,7 @@ static int adjd_s311_probe(struct i2c_client *client) } static const struct i2c_device_id adjd_s311_id[] = { - { "adjd_s311" }, + { .name = "adjd_s311" }, { } }; MODULE_DEVICE_TABLE(i2c, adjd_s311_id); diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c index 66ff9c5fb66a..633a105fd7f0 100644 --- a/drivers/iio/light/adux1020.c +++ b/drivers/iio/light/adux1020.c @@ -818,7 +818,7 @@ static int adux1020_probe(struct i2c_client *client) } static const struct i2c_device_id adux1020_id[] = { - { "adux1020" }, + { .name = "adux1020" }, { } }; MODULE_DEVICE_TABLE(i2c, adux1020_id); diff --git a/drivers/iio/light/al3000a.c b/drivers/iio/light/al3000a.c index 9871096cbab3..d4e6fedf3d9e 100644 --- a/drivers/iio/light/al3000a.c +++ b/drivers/iio/light/al3000a.c @@ -183,7 +183,7 @@ static int al3000a_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(al3000a_pm_ops, al3000a_suspend, al3000a_resume); static const struct i2c_device_id al3000a_id[] = { - { "al3000a" }, + { .name = "al3000a" }, { } }; MODULE_DEVICE_TABLE(i2c, al3000a_id); diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c index 0932fa2b49fa..d603b4a6b8e8 100644 --- a/drivers/iio/light/al3010.c +++ b/drivers/iio/light/al3010.c @@ -111,7 +111,8 @@ static int al3010_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { struct al3010_data *data = iio_priv(indio_dev); - int ret, gain, raw; + int ret, gain; + __le16 raw; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -120,11 +121,12 @@ static int al3010_read_raw(struct iio_dev *indio_dev, * - low byte of output is stored at AL3010_REG_DATA_LOW * - high byte of output is stored at AL3010_REG_DATA_LOW + 1 */ - ret = regmap_read(data->regmap, AL3010_REG_DATA_LOW, &raw); + ret = regmap_bulk_read(data->regmap, AL3010_REG_DATA_LOW, + &raw, sizeof(raw)); if (ret) return ret; - *val = raw; + *val = le16_to_cpu(raw); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -218,7 +220,7 @@ static int al3010_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(al3010_pm_ops, al3010_suspend, al3010_resume); static const struct i2c_device_id al3010_id[] = { - {"al3010", }, + { .name = "al3010" }, { } }; MODULE_DEVICE_TABLE(i2c, al3010_id); diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c index 63f5a85912fc..4ba0ecf355d5 100644 --- a/drivers/iio/light/al3320a.c +++ b/drivers/iio/light/al3320a.c @@ -135,7 +135,8 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { struct al3320a_data *data = iio_priv(indio_dev); - int ret, gain, raw; + int ret, gain; + __le16 raw; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -144,11 +145,12 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, * - low byte of output is stored at AL3320A_REG_DATA_LOW * - high byte of output is stored at AL3320A_REG_DATA_LOW + 1 */ - ret = regmap_read(data->regmap, AL3320A_REG_DATA_LOW, &raw); + ret = regmap_bulk_read(data->regmap, AL3320A_REG_DATA_LOW, + &raw, sizeof(raw)); if (ret) return ret; - *val = raw; + *val = le16_to_cpu(raw); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -246,7 +248,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend, al3320a_resume); static const struct i2c_device_id al3320a_id[] = { - { "al3320a" }, + { .name = "al3320a" }, { } }; MODULE_DEVICE_TABLE(i2c, al3320a_id); diff --git a/drivers/iio/light/apds9160.c b/drivers/iio/light/apds9160.c index 3da0bdac04cf..8dacb1730429 100644 --- a/drivers/iio/light/apds9160.c +++ b/drivers/iio/light/apds9160.c @@ -1572,7 +1572,7 @@ static const struct of_device_id apds9160_of_match[] = { MODULE_DEVICE_TABLE(of, apds9160_of_match); static const struct i2c_device_id apds9160_id[] = { - { "apds9160", 0 }, + { .name = "apds9160" }, { } }; MODULE_DEVICE_TABLE(i2c, apds9160_id); diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c index 05ba21675063..d60ade1209f3 100644 --- a/drivers/iio/light/apds9300.c +++ b/drivers/iio/light/apds9300.c @@ -492,7 +492,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume); static const struct i2c_device_id apds9300_id[] = { - { APDS9300_DRV_NAME }, + { .name = APDS9300_DRV_NAME }, { } }; diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index 785c5dbe2d08..2686c3b0c03b 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1154,7 +1154,7 @@ static const struct dev_pm_ops apds9960_pm_ops = { }; static const struct i2c_device_id apds9960_id[] = { - { "apds9960" }, + { .name = "apds9960" }, { } }; MODULE_DEVICE_TABLE(i2c, apds9960_id); diff --git a/drivers/iio/light/apds9999.c b/drivers/iio/light/apds9999.c new file mode 100644 index 000000000000..7a0df5252078 --- /dev/null +++ b/drivers/iio/light/apds9999.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * IIO driver for Broadcom APDS9999 Lux Light Sensor + * + * Copyright (C) 2026 + * Author: Jose A. Perez de Azpillaga + * + * TODO: proximity sensor + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APDS9999_REG_MAIN_CTRL 0x00 +#define APDS9999_MAIN_CTRL_LS_EN BIT(1) +#define APDS9999_REG_LS_MEAS_RATE 0x04 +#define APDS9999_LS_RES_MASK GENMASK(6, 4) +#define APDS9999_LS_RATE_MASK GENMASK(2, 0) +#define APDS9999_REG_LS_GAIN 0x05 +#define APDS9999_REG_PART_ID 0x06 +#define APDS9999_REG_MAIN_STATUS 0x07 +#define APDS9999_MAIN_STATUS_LS_DATA BIT(3) +#define APDS9999_REG_LS_DATA_IR_0 0x0A +#define APDS9999_REG_LS_DATA_GREEN_0 0x0D +#define APDS9999_REG_LS_DATA_BLUE_0 0x10 +#define APDS9999_REG_LS_DATA_RED_0 0x13 + +#define APDS9999_PART_ID 0xC2 + +#define APDS9999_GAIN_1X 0 +#define APDS9999_GAIN_3X 1 +#define APDS9999_GAIN_6X 2 +#define APDS9999_GAIN_9X 3 +#define APDS9999_GAIN_18X 4 + +static const int apds9999_gains[] = { + [APDS9999_GAIN_1X] = 1, + [APDS9999_GAIN_3X] = 3, + [APDS9999_GAIN_6X] = 6, + [APDS9999_GAIN_9X] = 9, + [APDS9999_GAIN_18X] = 18, +}; + +#define APDS9999_RES_20BIT 0 +#define APDS9999_RES_19BIT 1 +#define APDS9999_RES_18BIT 2 +#define APDS9999_RES_17BIT 3 +#define APDS9999_RES_16BIT 4 +#define APDS9999_RES_13BIT 5 + +static const int apds9999_itimes_us[] = { + [APDS9999_RES_20BIT] = 400 * USEC_PER_MSEC, + [APDS9999_RES_19BIT] = 200 * USEC_PER_MSEC, + [APDS9999_RES_18BIT] = 100 * USEC_PER_MSEC, + [APDS9999_RES_17BIT] = 50 * USEC_PER_MSEC, + [APDS9999_RES_16BIT] = 25 * USEC_PER_MSEC, + [APDS9999_RES_13BIT] = 3125, +}; + +#define APDS9999_RATE_25_MS 0 +#define APDS9999_RATE_50_MS 1 +#define APDS9999_RATE_100_MS 2 +#define APDS9999_RATE_200_MS 3 +#define APDS9999_RATE_500_MS 4 +#define APDS9999_RATE_1000_MS 5 +#define APDS9999_RATE_2000_MS 6 + +struct apds9999_data { + struct i2c_client *client; + /* lock: serializes access to device registers and cached values */ + struct mutex lock; + int als_gain_idx; + int als_res; + int als_rate; +}; + +static void apds9999_standby(void *client) +{ + i2c_smbus_write_byte_data(client, APDS9999_REG_MAIN_CTRL, 0); +} + +/* + * Apply power-on defaults: 18-bit / 100 ms resolution and rate, + * 3x gain. These match the datasheet reset values. + */ +static int apds9999_init(struct apds9999_data *data) +{ + struct device *dev = &data->client->dev; + struct i2c_client *client = data->client; + u8 regval; + int ret; + + ret = devm_add_action_or_reset(dev, apds9999_standby, client); + if (ret) + return ret; + + guard(mutex)(&data->lock); + + regval = FIELD_PREP(APDS9999_LS_RES_MASK, APDS9999_RES_18BIT) | + FIELD_PREP(APDS9999_LS_RATE_MASK, APDS9999_RATE_100_MS); + ret = i2c_smbus_write_byte_data(client, APDS9999_REG_LS_MEAS_RATE, + regval); + if (ret) + return ret; + data->als_res = APDS9999_RES_18BIT; + data->als_rate = APDS9999_RATE_100_MS; + + ret = i2c_smbus_write_byte_data(client, APDS9999_REG_LS_GAIN, + APDS9999_GAIN_3X); + if (ret) + return ret; + data->als_gain_idx = APDS9999_GAIN_3X; + + return i2c_smbus_write_byte_data(client, APDS9999_REG_MAIN_CTRL, + APDS9999_MAIN_CTRL_LS_EN); +} + +static int apds9999_read_channel(struct apds9999_data *data, u8 reg, + u32 *counts) +{ + struct i2c_client *client = data->client; + u8 buf[3]; + int ret, tries; + + guard(mutex)(&data->lock); + + /* + * Poll MAIN_STATUS for new data. Timeout: ~2 integration periods + * plus margin. Each try sleeps 20 ms. + */ + tries = max(2, (apds9999_itimes_us[data->als_res] * 2) / 20000); + + while (tries--) { + ret = i2c_smbus_read_byte_data(client, + APDS9999_REG_MAIN_STATUS); + if (ret < 0) + return ret; + if (ret & APDS9999_MAIN_STATUS_LS_DATA) + break; + fsleep(20000); + } + + if (tries < 0) + return -ETIMEDOUT; + + ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf); + if (ret < 0) + return ret; + if (ret != sizeof(buf)) + return -EIO; + + *counts = get_unaligned_le24(buf) & GENMASK(19, 0); + return 0; +} + +static int apds9999_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct apds9999_data *data = iio_priv(indio_dev); + int gain, itime_us; + u64 scale_nano; + u32 counts; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = apds9999_read_channel(data, chan->address, &counts); + if (ret) + return ret; + *val = (int)counts; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: { + u32 remainder; + + /* + * Scale (lux per count) = 54 / (gain * integration_time_ms) + * + * The constant 54 is derived from the datasheet table: + * at gain = 3x, itime = 100 ms -> 0.180 lux/count + * -> C = 0.180 * 3 * 100 = 54 + * + * Expressed as IIO_VAL_INT_PLUS_NANO. + */ + gain = apds9999_gains[data->als_gain_idx]; + itime_us = apds9999_itimes_us[data->als_res]; + + /* scale_nano = 54 * 1e12 / (gain * itime_us) nano-lux/count */ + scale_nano = div_u64(54ULL * NSEC_PER_SEC * USEC_PER_MSEC, (u32)(gain * itime_us)); + *val = (int)div_u64_rem(scale_nano, NSEC_PER_SEC, &remainder); + *val2 = (int)remainder; + return IIO_VAL_INT_PLUS_NANO; + } + case IIO_CHAN_INFO_INT_TIME: + *val = 0; + *val2 = apds9999_itimes_us[data->als_res]; + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +static const struct iio_info apds9999_info = { + .read_raw = apds9999_read_raw, +}; + +/* + * The green channel uses optical coating to approximate the human eye + * spectral response. IIO_INTENSITY channels provide raw ADC data for + * red, green, blue, and IR so userspace can compute weighted lux. + */ +static const struct iio_chan_spec apds9999_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .address = APDS9999_REG_LS_DATA_GREEN_0, + }, + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_RED, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .address = APDS9999_REG_LS_DATA_RED_0, + }, + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_GREEN, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .address = APDS9999_REG_LS_DATA_GREEN_0, + }, + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_BLUE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .address = APDS9999_REG_LS_DATA_BLUE_0, + }, + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_IR, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .address = APDS9999_REG_LS_DATA_IR_0, + }, +}; + +static int apds9999_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct apds9999_data *data; + struct iio_dev *indio_dev; + int ret, part_id; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + + ret = devm_mutex_init(dev, &data->lock); + if (ret) + return ret; + + part_id = i2c_smbus_read_byte_data(client, APDS9999_REG_PART_ID); + if (part_id < 0) + return dev_err_probe(dev, part_id, "failed to read PART_ID\n"); + if (part_id != APDS9999_PART_ID) + dev_info(dev, "unexpected PART_ID 0x%02x (expected 0x%02x)\n", + part_id, APDS9999_PART_ID); + + ret = apds9999_init(data); + if (ret) + return dev_err_probe(dev, ret, "failed to initialize device\n"); + + indio_dev->name = "apds9999"; + indio_dev->info = &apds9999_info; + indio_dev->channels = apds9999_channels; + indio_dev->num_channels = ARRAY_SIZE(apds9999_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, "failed to register IIO device\n"); + + return 0; +} + +static const struct i2c_device_id apds9999_id[] = { + { .name = "apds9999" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, apds9999_id); + +static const struct of_device_id apds9999_of_match[] = { + { .compatible = "brcm,apds9999" }, + { } +}; +MODULE_DEVICE_TABLE(of, apds9999_of_match); + +static struct i2c_driver apds9999_driver = { + .driver = { + .name = "apds9999", + .of_match_table = apds9999_of_match, + }, + .probe = apds9999_probe, + .id_table = apds9999_id, +}; +module_i2c_driver(apds9999_driver); + +MODULE_AUTHOR("Jose A. Perez de Azpillaga "); +MODULE_DESCRIPTION("APDS-9999 Lux Light Sensor IIO Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c index 9fe830dac679..67f33bbe1c13 100644 --- a/drivers/iio/light/as73211.c +++ b/drivers/iio/light/as73211.c @@ -875,8 +875,8 @@ static const struct of_device_id as73211_of_match[] = { MODULE_DEVICE_TABLE(of, as73211_of_match); static const struct i2c_device_id as73211_id[] = { - { "as73211", (kernel_ulong_t)&as73211_spec }, - { "as7331", (kernel_ulong_t)&as7331_spec }, + { .name = "as73211", .driver_data = (kernel_ulong_t)&as73211_spec }, + { .name = "as7331", .driver_data = (kernel_ulong_t)&as7331_spec }, { } }; MODULE_DEVICE_TABLE(i2c, as73211_id); diff --git a/drivers/iio/light/bh1745.c b/drivers/iio/light/bh1745.c index 10b00344bbed..0aa8e5cc6c56 100644 --- a/drivers/iio/light/bh1745.c +++ b/drivers/iio/light/bh1745.c @@ -874,7 +874,7 @@ static int bh1745_probe(struct i2c_client *client) } static const struct i2c_device_id bh1745_idtable[] = { - { "bh1745" }, + { .name = "bh1745" }, { } }; MODULE_DEVICE_TABLE(i2c, bh1745_idtable); diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index 764f88826fcb..a51ac98c83c8 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -319,11 +319,11 @@ static int bh1750_suspend(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(bh1750_pm_ops, bh1750_suspend, NULL); static const struct i2c_device_id bh1750_id[] = { - { "bh1710", BH1710 }, - { "bh1715", BH1750 }, - { "bh1721", BH1721 }, - { "bh1750", BH1750 }, - { "bh1751", BH1750 }, + { .name = "bh1710", .driver_data = BH1710 }, + { .name = "bh1715", .driver_data = BH1750 }, + { .name = "bh1721", .driver_data = BH1721 }, + { .name = "bh1750", .driver_data = BH1750 }, + { .name = "bh1751", .driver_data = BH1750 }, { } }; MODULE_DEVICE_TABLE(i2c, bh1750_id); diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c index a740d1f992a8..ead98fb82af9 100644 --- a/drivers/iio/light/bh1780.c +++ b/drivers/iio/light/bh1780.c @@ -255,7 +255,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(bh1780_dev_pm_ops, bh1780_runtime_suspend, bh1780_runtime_resume, NULL); static const struct i2c_device_id bh1780_id[] = { - { "bh1780" }, + { .name = "bh1780" }, { } }; diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c index 3a3ad6b4c468..fec233d06602 100644 --- a/drivers/iio/light/cm3232.c +++ b/drivers/iio/light/cm3232.c @@ -366,9 +366,10 @@ static void cm3232_remove(struct i2c_client *client) } static const struct i2c_device_id cm3232_id[] = { - { "cm3232" }, + { .name = "cm3232" }, { } }; +MODULE_DEVICE_TABLE(i2c, cm3232_id); static int cm3232_suspend(struct device *dev) { @@ -400,8 +401,6 @@ static int cm3232_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(cm3232_pm_ops, cm3232_suspend, cm3232_resume); -MODULE_DEVICE_TABLE(i2c, cm3232_id); - static const struct of_device_id cm3232_of_match[] = { {.compatible = "capella,cm3232"}, { } diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 0fe61b8a7029..fbb9e0a13733 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -249,7 +249,7 @@ static int cm3323_probe(struct i2c_client *client) } static const struct i2c_device_id cm3323_id[] = { - { "cm3323" }, + { .name = "cm3323" }, { } }; MODULE_DEVICE_TABLE(i2c, cm3323_id); diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 446dd54d5037..6ebd8ce4ca12 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -713,7 +713,7 @@ static void cm36651_remove(struct i2c_client *client) } static const struct i2c_device_id cm36651_id[] = { - { "cm36651" }, + { .name = "cm36651" }, { } }; diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 815806ceb5c8..d09dea9c0782 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -223,14 +223,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) return -EINVAL; } - /* Timestamp */ channel++; - channel->type = IIO_TIMESTAMP; - channel->channel = -1; - channel->scan_index = 1; - channel->scan_type.sign = 's'; - channel->scan_type.realbits = 64; - channel->scan_type.storagebits = 64; + *channel = IIO_CHAN_SOFT_TIMESTAMP(1); indio_dev->channels = state->channels; diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index a0d8a58f2704..c83f67ff2464 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -690,7 +690,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(gp2ap002_dev_pm_ops, gp2ap002_runtime_suspend, gp2ap002_runtime_resume, NULL); static const struct i2c_device_id gp2ap002_id_table[] = { - { "gp2ap002" }, + { .name = "gp2ap002" }, { } }; MODULE_DEVICE_TABLE(i2c, gp2ap002_id_table); diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 7e388319ee2e..c218bb3519df 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -1525,7 +1525,7 @@ static void gp2ap020a00f_remove(struct i2c_client *client) } static const struct i2c_device_id gp2ap020a00f_id[] = { - { "gp2ap020a00f" }, + { .name = "gp2ap020a00f" }, { } }; MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id); diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 384572844162..d72e260b8266 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -3,6 +3,7 @@ * HID Sensors Driver * Copyright (c) 2012, Intel Corporation. */ +#include #include #include #include @@ -117,17 +118,6 @@ static const struct iio_chan_spec als_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP) }; -/* Adjust channel real bits based on report descriptor */ -static void als_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - /* Channel read_raw handler */ static int als_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -335,7 +325,11 @@ static int als_parse_report(struct platform_device *pdev, channels[index] = als_channels[i]; st->als_scan_mask[0] |= BIT(i); - als_adjust_channel_bit_mask(channels, index, st->als[i].size); + channels[index].scan_type = (struct iio_scan_type) { + .format = 's', + .realbits = BYTES_TO_BITS(st->als[i].size), + .storagebits = BITS_PER_TYPE(u32), + }; ++index; dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index, diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index efa904a70d0e..edc9274a2c07 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -3,6 +3,7 @@ * HID Sensors Driver * Copyright (c) 2014, Intel Corporation. */ +#include #include #include #include @@ -67,17 +68,6 @@ static const struct iio_chan_spec prox_channels[] = { PROX_CHANNEL(false, 0), }; -/* Adjust channel real bits based on report descriptor */ -static void prox_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - /* Channel read_raw handler */ static int prox_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -250,8 +240,11 @@ static int prox_parse_report(struct platform_device *pdev, st->scan_mask[0] |= BIT(index); channels[index] = prox_channels[i]; channels[index].scan_index = index; - prox_adjust_channel_bit_mask(channels, index, - st->prox_attr[index].size); + channels[index].scan_type = (struct iio_scan_type) { + .format = 's', + .realbits = BYTES_TO_BITS(st->prox_attr[index].size), + .storagebits = BITS_PER_TYPE(u32), + }; dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index, st->prox_attr[index].report_id); st->scale_precision[index] = diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c index b9f230210f07..cd5843e3e2c3 100644 --- a/drivers/iio/light/iqs621-als.c +++ b/drivers/iio/light/iqs621-als.c @@ -5,6 +5,7 @@ * Copyright (C) 2019 Jeff LaBundy */ +#include #include #include #include @@ -107,26 +108,20 @@ static int iqs621_als_notifier(struct notifier_block *notifier, indio_dev = iqs621_als->indio_dev; timestamp = iio_get_time_ns(indio_dev); - mutex_lock(&iqs621_als->lock); + guard(mutex)(&iqs621_als->lock); if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) { ret = iqs621_als_init(iqs621_als); if (ret) { dev_err(indio_dev->dev.parent, "Failed to re-initialize device: %d\n", ret); - ret = NOTIFY_BAD; - } else { - ret = NOTIFY_OK; + return NOTIFY_BAD; } - - goto err_mutex; + return NOTIFY_OK; } - if (!iqs621_als->light_en && !iqs621_als->range_en && - !iqs621_als->prox_en) { - ret = NOTIFY_DONE; - goto err_mutex; - } + if (!iqs621_als->light_en && !iqs621_als->range_en && !iqs621_als->prox_en) + return NOTIFY_DONE; /* IQS621 only */ light_new = event_data->als_flags & IQS621_ALS_FLAGS_LIGHT; @@ -181,12 +176,7 @@ static int iqs621_als_notifier(struct notifier_block *notifier, iqs621_als->als_flags = event_data->als_flags; iqs621_als->ir_flags = event_data->ir_flags; - ret = NOTIFY_OK; - -err_mutex: - mutex_unlock(&iqs621_als->lock); - - return ret; + return NOTIFY_OK; } static void iqs621_als_notifier_unregister(void *context) @@ -241,30 +231,22 @@ static int iqs621_als_read_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); - int ret; - mutex_lock(&iqs621_als->lock); + guard(mutex)(&iqs621_als->lock); switch (chan->type) { case IIO_LIGHT: - ret = iqs621_als->light_en; - break; + return iqs621_als->light_en; case IIO_INTENSITY: - ret = iqs621_als->range_en; - break; + return iqs621_als->range_en; case IIO_PROXIMITY: - ret = iqs621_als->prox_en; - break; + return iqs621_als->prox_en; default: - ret = -EINVAL; + return -EINVAL; } - - mutex_unlock(&iqs621_als->lock); - - return ret; } static int iqs621_als_write_event_config(struct iio_dev *indio_dev, @@ -278,11 +260,11 @@ static int iqs621_als_write_event_config(struct iio_dev *indio_dev, unsigned int val; int ret; - mutex_lock(&iqs621_als->lock); + guard(mutex)(&iqs621_als->lock); ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->als_flags, &val); if (ret) - goto err_mutex; + return ret; iqs621_als->als_flags = val; switch (chan->type) { @@ -291,40 +273,41 @@ static int iqs621_als_write_event_config(struct iio_dev *indio_dev, iqs62x->dev_desc->als_mask, iqs621_als->range_en || state ? 0 : 0xFF); - if (!ret) - iqs621_als->light_en = state; - break; + if (ret) + return ret; + iqs621_als->light_en = state; + + return 0; case IIO_INTENSITY: ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, iqs62x->dev_desc->als_mask, iqs621_als->light_en || state ? 0 : 0xFF); - if (!ret) - iqs621_als->range_en = state; - break; + if (ret) + return ret; + iqs621_als->range_en = state; + + return 0; case IIO_PROXIMITY: ret = regmap_read(iqs62x->regmap, IQS622_IR_FLAGS, &val); if (ret) - goto err_mutex; + return ret; iqs621_als->ir_flags = val; ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, iqs62x->dev_desc->ir_mask, state ? 0 : 0xFF); - if (!ret) - iqs621_als->prox_en = state; - break; + if (ret) + return ret; + iqs621_als->prox_en = state; + + return 0; default: - ret = -EINVAL; + return -EINVAL; } - -err_mutex: - mutex_unlock(&iqs621_als->lock); - - return ret; } static int iqs621_als_read_event_value(struct iio_dev *indio_dev, @@ -335,33 +318,28 @@ static int iqs621_als_read_event_value(struct iio_dev *indio_dev, int *val, int *val2) { struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); - int ret = IIO_VAL_INT; - mutex_lock(&iqs621_als->lock); + guard(mutex)(&iqs621_als->lock); switch (dir) { case IIO_EV_DIR_RISING: *val = iqs621_als->thresh_light * 16; - break; + return IIO_VAL_INT; case IIO_EV_DIR_FALLING: *val = iqs621_als->thresh_dark * 4; - break; + return IIO_VAL_INT; case IIO_EV_DIR_EITHER: if (iqs621_als->ir_flags_mask == IQS622_IR_FLAGS_TOUCH) *val = iqs621_als->thresh_prox * 4; else *val = iqs621_als->thresh_prox; - break; + return IIO_VAL_INT; default: - ret = -EINVAL; + return -EINVAL; } - - mutex_unlock(&iqs621_als->lock); - - return ret; } static int iqs621_als_write_event_value(struct iio_dev *indio_dev, @@ -375,9 +353,9 @@ static int iqs621_als_write_event_value(struct iio_dev *indio_dev, struct iqs62x_core *iqs62x = iqs621_als->iqs62x; unsigned int thresh_reg, thresh_val; u8 ir_flags_mask, *thresh_cache; - int ret = -EINVAL; + int ret; - mutex_lock(&iqs621_als->lock); + guard(mutex)(&iqs621_als->lock); switch (dir) { case IIO_EV_DIR_RISING: @@ -426,30 +404,27 @@ static int iqs621_als_write_event_value(struct iio_dev *indio_dev, break; default: - goto err_mutex; + return -EINVAL; } thresh_cache = &iqs621_als->thresh_prox; break; default: - goto err_mutex; + return -EINVAL; } if (thresh_val > 0xFF) - goto err_mutex; + return -EINVAL; ret = regmap_write(iqs62x->regmap, thresh_reg, thresh_val); if (ret) - goto err_mutex; + return ret; *thresh_cache = thresh_val; iqs621_als->ir_flags_mask = ir_flags_mask; -err_mutex: - mutex_unlock(&iqs621_als->lock); - - return ret; + return 0; } static const struct iio_info iqs621_als_info = { diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index b6ab726d1dae..8a39afaa2a37 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -829,9 +829,9 @@ static const struct acpi_device_id isl29018_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); static const struct i2c_device_id isl29018_id[] = { - {"isl29018", isl29018}, - {"isl29023", isl29023}, - {"isl29035", isl29035}, + { .name = "isl29018", .driver_data = isl29018 }, + { .name = "isl29023", .driver_data = isl29023 }, + { .name = "isl29035", .driver_data = isl29035 }, { } }; MODULE_DEVICE_TABLE(i2c, isl29018_id); diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index 374bccad9119..b88e7c4eae3e 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -673,8 +673,8 @@ static DEFINE_RUNTIME_DEV_PM_OPS(isl29028_pm_ops, isl29028_suspend, isl29028_resume, NULL); static const struct i2c_device_id isl29028_id[] = { - { "isl29028" }, - { "isl29030" }, + { .name = "isl29028" }, + { .name = "isl29030" }, { } }; MODULE_DEVICE_TABLE(i2c, isl29028_id); diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index 3acb8a4f1d12..9e0b7e6a3ecf 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -325,7 +325,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume); static const struct i2c_device_id isl29125_id[] = { - { "isl29125" }, + { .name = "isl29125" }, { } }; MODULE_DEVICE_TABLE(i2c, isl29125_id); diff --git a/drivers/iio/light/isl76682.c b/drivers/iio/light/isl76682.c index b6f2fc9978f6..9b9052d08e41 100644 --- a/drivers/iio/light/isl76682.c +++ b/drivers/iio/light/isl76682.c @@ -319,7 +319,7 @@ static int isl76682_probe(struct i2c_client *client) } static const struct i2c_device_id isl76682_id[] = { - { "isl76682" }, + { .name = "isl76682" }, { } }; MODULE_DEVICE_TABLE(i2c, isl76682_id); diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c index 6978d02a4df5..cc0a7c4a33dd 100644 --- a/drivers/iio/light/jsa1212.c +++ b/drivers/iio/light/jsa1212.c @@ -428,7 +428,7 @@ static const struct acpi_device_id jsa1212_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); static const struct i2c_device_id jsa1212_id[] = { - { JSA1212_DRIVER_NAME }, + { .name = JSA1212_DRIVER_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, jsa1212_id); diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c index f1702aca582d..bdc74b8226c8 100644 --- a/drivers/iio/light/ltr390.c +++ b/drivers/iio/light/ltr390.c @@ -889,7 +889,7 @@ static const struct dev_pm_ops ltr390_pm_ops = { }; static const struct i2c_device_id ltr390_id[] = { - { "ltr390" }, + { .name = "ltr390" }, { } }; MODULE_DEVICE_TABLE(i2c, ltr390_id); diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 4d99ae336f61..15dd82ecf745 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1601,10 +1601,10 @@ static const struct acpi_device_id ltr_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); static const struct i2c_device_id ltr501_id[] = { - { "ltr501", ltr501 }, - { "ltr559", ltr559 }, - { "ltr301", ltr301 }, - { "ltr303", ltr303 }, + { .name = "ltr501", .driver_data = ltr501 }, + { .name = "ltr559", .driver_data = ltr559 }, + { .name = "ltr301", .driver_data = ltr301 }, + { .name = "ltr303", .driver_data = ltr303 }, { } }; MODULE_DEVICE_TABLE(i2c, ltr501_id); diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c index 5f27f754fe1c..aad96fc91565 100644 --- a/drivers/iio/light/ltrf216a.c +++ b/drivers/iio/light/ltrf216a.c @@ -551,8 +551,8 @@ static const struct ltr_chip_info ltrf216a_chip_info = { }; static const struct i2c_device_id ltrf216a_id[] = { - { "ltr308", .driver_data = (kernel_ulong_t)<r308_chip_info }, - { "ltrf216a", .driver_data = (kernel_ulong_t)<rf216a_chip_info }, + { .name = "ltr308", .driver_data = (kernel_ulong_t)<r308_chip_info }, + { .name = "ltrf216a", .driver_data = (kernel_ulong_t)<rf216a_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, ltrf216a_id); diff --git a/drivers/iio/light/lv0104cs.c b/drivers/iio/light/lv0104cs.c index 916109ec3217..eba82c334d70 100644 --- a/drivers/iio/light/lv0104cs.c +++ b/drivers/iio/light/lv0104cs.c @@ -510,7 +510,7 @@ static int lv0104cs_probe(struct i2c_client *client) } static const struct i2c_device_id lv0104cs_id[] = { - { "lv0104cs" }, + { .name = "lv0104cs" }, { } }; MODULE_DEVICE_TABLE(i2c, lv0104cs_id); diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 039d45af3a7f..6594054c40c7 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -598,7 +598,7 @@ static int max44000_probe(struct i2c_client *client) } static const struct i2c_device_id max44000_id[] = { - { "max44000" }, + { .name = "max44000" }, { } }; MODULE_DEVICE_TABLE(i2c, max44000_id); diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c index 8cd7f5664e5b..82b8a806c5fa 100644 --- a/drivers/iio/light/max44009.c +++ b/drivers/iio/light/max44009.c @@ -534,7 +534,7 @@ static const struct of_device_id max44009_of_match[] = { MODULE_DEVICE_TABLE(of, max44009_of_match); static const struct i2c_device_id max44009_id[] = { - { "max44009" }, + { .name = "max44009" }, { } }; MODULE_DEVICE_TABLE(i2c, max44009_id); diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c index 25f63da70297..6731f1d9ec1c 100644 --- a/drivers/iio/light/noa1305.c +++ b/drivers/iio/light/noa1305.c @@ -315,7 +315,7 @@ static const struct of_device_id noa1305_of_match[] = { MODULE_DEVICE_TABLE(of, noa1305_of_match); static const struct i2c_device_id noa1305_ids[] = { - { "noa1305" }, + { .name = "noa1305" }, { } }; MODULE_DEVICE_TABLE(i2c, noa1305_ids); diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 53bc455b7bad..0743e16f2a8f 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -8,18 +8,19 @@ * Based on previous work from: Felipe Balbi */ -#include +#include +#include #include -#include +#include +#include #include #include -#include -#include -#include +#include #include +#include #include -#include #include +#include #include #include @@ -32,17 +33,16 @@ #define OPT3001_MANUFACTURER_ID 0x7e #define OPT3001_DEVICE_ID 0x7f -#define OPT3001_CONFIGURATION_RN_MASK (0xf << 12) +#define OPT3001_CONFIGURATION_RN_MASK GENMASK(15, 12) #define OPT3001_CONFIGURATION_RN_AUTO (0xc << 12) #define OPT3001_CONFIGURATION_CT BIT(11) -#define OPT3001_CONFIGURATION_M_MASK (3 << 9) +#define OPT3001_CONFIGURATION_M_MASK GENMASK(10, 9) #define OPT3001_CONFIGURATION_M_SHUTDOWN (0 << 9) #define OPT3001_CONFIGURATION_M_SINGLE (1 << 9) #define OPT3001_CONFIGURATION_M_CONTINUOUS (2 << 9) /* also 3 << 9 */ -#define OPT3001_CONFIGURATION_OVF BIT(8) #define OPT3001_CONFIGURATION_CRF BIT(7) #define OPT3001_CONFIGURATION_FH BIT(6) #define OPT3001_CONFIGURATION_FL BIT(5) @@ -50,7 +50,7 @@ #define OPT3001_CONFIGURATION_POL BIT(3) #define OPT3001_CONFIGURATION_ME BIT(2) -#define OPT3001_CONFIGURATION_FC_MASK (3 << 0) +#define OPT3001_CONFIGURATION_FC_MASK GENMASK(1, 0) /* The end-of-conversion enable is located in the low-limit register */ #define OPT3001_LOW_LIMIT_EOC_ENABLE 0xc000 @@ -366,8 +366,10 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2) ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready, msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); - if (ret == 0) - return -ETIMEDOUT; + if (ret == 0) { + ret = -ETIMEDOUT; + goto err; + } } else { /* Sleep for result ready time */ timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? @@ -948,8 +950,8 @@ static const struct opt3001_chip_info opt3002_chip_information = { }; static const struct i2c_device_id opt3001_id[] = { - { "opt3001", (kernel_ulong_t)&opt3001_chip_information }, - { "opt3002", (kernel_ulong_t)&opt3002_chip_information }, + { .name = "opt3001", .driver_data = (kernel_ulong_t)&opt3001_chip_information }, + { .name = "opt3002", .driver_data = (kernel_ulong_t)&opt3002_chip_information }, { } /* Terminating Entry */ }; MODULE_DEVICE_TABLE(i2c, opt3001_id); diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c index 95167273bb90..dd152d921b48 100644 --- a/drivers/iio/light/opt4001.c +++ b/drivers/iio/light/opt4001.c @@ -438,8 +438,8 @@ static int opt4001_probe(struct i2c_client *client) * opt4001 packaging */ static const struct i2c_device_id opt4001_id[] = { - { "opt4001-sot-5x3", (kernel_ulong_t)&opt4001_sot_5x3_info }, - { "opt4001-picostar", (kernel_ulong_t)&opt4001_picostar_info }, + { .name = "opt4001-sot-5x3", .driver_data = (kernel_ulong_t)&opt4001_sot_5x3_info }, + { .name = "opt4001-picostar", .driver_data = (kernel_ulong_t)&opt4001_picostar_info }, { } }; MODULE_DEVICE_TABLE(i2c, opt4001_id); diff --git a/drivers/iio/light/opt4060.c b/drivers/iio/light/opt4060.c index d6e915ab355d..c391ad3271c6 100644 --- a/drivers/iio/light/opt4060.c +++ b/drivers/iio/light/opt4060.c @@ -1297,7 +1297,7 @@ static int opt4060_probe(struct i2c_client *client) } static const struct i2c_device_id opt4060_id[] = { - { "opt4060", }, + { .name = "opt4060" }, { } }; MODULE_DEVICE_TABLE(i2c, opt4060_id); diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c index 98a1f1624c75..c0f4db8d95f7 100644 --- a/drivers/iio/light/pa12203001.c +++ b/drivers/iio/light/pa12203001.c @@ -457,7 +457,7 @@ static const struct acpi_device_id pa12203001_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match); static const struct i2c_device_id pa12203001_id[] = { - { "txcpa122" }, + { .name = "txcpa122" }, { } }; diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 9341c1d58cbe..2ac06dad6d19 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -1102,7 +1102,7 @@ static const struct acpi_device_id rpr0521_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match); static const struct i2c_device_id rpr0521_id[] = { - { "rpr0521" }, + { .name = "rpr0521" }, { } }; diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c index 44fa152dbd24..2812a2be99dd 100644 --- a/drivers/iio/light/si1133.c +++ b/drivers/iio/light/si1133.c @@ -6,19 +6,28 @@ * Copyright 2018 Maxime Roussin-Belanger */ +#include +#include +#include +#include #include +#include +#include #include #include +#include +#include +#include #include +#include #include +#include +#include +#include #include #include -#include - -#include - #define SI1133_REG_PART_ID 0x00 #define SI1133_REG_REV_ID 0x01 #define SI1133_REG_MFR_ID 0x02 @@ -50,23 +59,23 @@ #define SI1133_MAX_CMD_CTR 0xF #define SI1133_PARAM_REG_CHAN_LIST 0x01 -#define SI1133_PARAM_REG_ADCCONFIG(x) ((x) * 4) + 2 -#define SI1133_PARAM_REG_ADCSENS(x) ((x) * 4) + 3 -#define SI1133_PARAM_REG_ADCPOST(x) ((x) * 4) + 4 +#define SI1133_PARAM_REG_ADCCONFIG(x) (((x) * 4) + 2) +#define SI1133_PARAM_REG_ADCSENS(x) (((x) * 4) + 3) +#define SI1133_PARAM_REG_ADCPOST(x) (((x) * 4) + 4) #define SI1133_ADCMUX_MASK 0x1F -#define SI1133_ADCCONFIG_DECIM_RATE(x) (x) << 5 +#define SI1133_ADCCONFIG_DECIM_RATE(x) ((x) << 5) #define SI1133_ADCSENS_SCALE_MASK 0x70 #define SI1133_ADCSENS_SCALE_SHIFT 4 #define SI1133_ADCSENS_HSIG_MASK BIT(7) #define SI1133_ADCSENS_HSIG_SHIFT 7 #define SI1133_ADCSENS_HW_GAIN_MASK 0xF -#define SI1133_ADCSENS_NB_MEAS(x) fls(x) << SI1133_ADCSENS_SCALE_SHIFT +#define SI1133_ADCSENS_NB_MEAS(x) (fls(x) << SI1133_ADCSENS_SCALE_SHIFT) #define SI1133_ADCPOST_24BIT_EN BIT(6) -#define SI1133_ADCPOST_POSTSHIFT_BITQTY(x) (x & GENMASK(2, 0)) << 3 +#define SI1133_ADCPOST_POSTSHIFT_BITQTY(x) (((x) & GENMASK(2, 0)) << 3) #define SI1133_PARAM_ADCMUX_SMALL_IR 0x0 #define SI1133_PARAM_ADCMUX_MED_IR 0x1 @@ -86,16 +95,12 @@ #define SI1133_CMD_MINSLEEP_US_LOW 5000 #define SI1133_CMD_MINSLEEP_US_HIGH 7500 #define SI1133_CMD_TIMEOUT_MS 25 -#define SI1133_CMD_LUX_TIMEOUT_MS 5000 -#define SI1133_CMD_TIMEOUT_US SI1133_CMD_TIMEOUT_MS * 1000 -#define SI1133_REG_HOSTOUT(x) (x) + 0x13 - -#define SI1133_MEASUREMENT_FREQUENCY 1250 +#define SI1133_REG_HOSTOUT(x) ((x) + 0x13) #define SI1133_X_ORDER_MASK 0x0070 #define SI1133_Y_ORDER_MASK 0x0007 -#define si1133_get_x_order(m) ((m) & SI1133_X_ORDER_MASK) >> 4 +#define si1133_get_x_order(m) (((m) & SI1133_X_ORDER_MASK) >> 4) #define si1133_get_y_order(m) ((m) & SI1133_Y_ORDER_MASK) #define SI1133_LUX_ADC_MASK 0xE @@ -386,35 +391,42 @@ static int si1133_cmd_reset_counter(struct si1133_data *data) static int si1133_command(struct si1133_data *data, u8 cmd) { + unsigned long timeout; struct device *dev = &data->client->dev; u32 resp; int err; int expected_seq; - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); expected_seq = (data->rsp_seq + 1) & SI1133_MAX_CMD_CTR; - if (cmd == SI1133_CMD_FORCE) + if (cmd == SI1133_CMD_FORCE) { + /* Flush pending IRQs from a previous timeout. */ + regmap_read(data->regmap, SI1133_REG_IRQ_STATUS, &resp); + regmap_write(data->regmap, SI1133_REG_IRQ_ENABLE, + SI1133_IRQ_CHANNEL_ENABLE); + reinit_completion(&data->completion); + } err = regmap_write(data->regmap, SI1133_REG_COMMAND, cmd); if (err) { dev_warn(dev, "Failed to write command 0x%02x, ret=%d\n", cmd, err); - goto out; + return err; } if (cmd == SI1133_CMD_FORCE) { /* wait for irq */ - if (!wait_for_completion_timeout(&data->completion, - msecs_to_jiffies(SI1133_COMPLETION_TIMEOUT_MS))) { - err = -ETIMEDOUT; - goto out; + timeout = msecs_to_jiffies(SI1133_COMPLETION_TIMEOUT_MS); + if (!wait_for_completion_timeout(&data->completion, timeout)) { + regmap_write(data->regmap, SI1133_REG_IRQ_ENABLE, 0); + return -ETIMEDOUT; } err = regmap_read(data->regmap, SI1133_REG_RESPONSE0, &resp); if (err) - goto out; + return err; } else { err = regmap_read_poll_timeout(data->regmap, SI1133_REG_RESPONSE0, resp, @@ -427,7 +439,12 @@ static int si1133_command(struct si1133_data *data, u8 cmd) dev_warn(dev, "Failed to read command 0x%02x, ret=%d\n", cmd, err); - goto out; + /* + * Reset counter on err to prevent software and hardware + * counters being out of sync. + */ + si1133_cmd_reset_counter(data); + return err; } } @@ -438,9 +455,6 @@ static int si1133_command(struct si1133_data *data, u8 cmd) data->rsp_seq = expected_seq; } -out: - mutex_unlock(&data->mutex); - return err; } @@ -1055,7 +1069,7 @@ static int si1133_probe(struct i2c_client *client) } static const struct i2c_device_id si1133_ids[] = { - { "si1133" }, + { .name = "si1133" }, { } }; MODULE_DEVICE_TABLE(i2c, si1133_ids); diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index ef0abc4499b7..4601ae5d2009 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1334,13 +1334,13 @@ static int si1145_probe(struct i2c_client *client) } static const struct i2c_device_id si1145_ids[] = { - { "si1132", SI1132 }, - { "si1141", SI1141 }, - { "si1142", SI1142 }, - { "si1143", SI1143 }, - { "si1145", SI1145 }, - { "si1146", SI1146 }, - { "si1147", SI1147 }, + { .name = "si1132", .driver_data = SI1132 }, + { .name = "si1141", .driver_data = SI1141 }, + { .name = "si1142", .driver_data = SI1142 }, + { .name = "si1143", .driver_data = SI1143 }, + { .name = "si1145", .driver_data = SI1145 }, + { .name = "si1146", .driver_data = SI1146 }, + { .name = "si1147", .driver_data = SI1147 }, { } }; MODULE_DEVICE_TABLE(i2c, si1145_ids); diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c index 5d9bb4d9be63..ed8cac5b8766 100644 --- a/drivers/iio/light/st_uvis25_i2c.c +++ b/drivers/iio/light/st_uvis25_i2c.c @@ -46,7 +46,7 @@ static const struct of_device_id st_uvis25_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, st_uvis25_i2c_of_match); static const struct i2c_device_id st_uvis25_i2c_id_table[] = { - { ST_UVIS25_DEV_NAME }, + { .name = ST_UVIS25_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, st_uvis25_i2c_id_table); diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index a75a83594a7e..8380df7ffa98 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -7,15 +7,28 @@ * IIO driver for STK3310/STK3311. 7-bit I2C address: 0x48. */ +#include +#include +#include +#include #include #include -#include -#include #include +#include +#include +#include +#include #include +#include +#include +#include + #include #include #include +#include + +#include #define STK3310_REG_STATE 0x00 #define STK3310_REG_PSCTRL 0x01 @@ -115,9 +128,6 @@ static const int stk3310_it_table[][2] = { struct stk3310_data { struct i2c_client *client; struct mutex lock; - bool als_enabled; - bool ps_enabled; - uint32_t ps_near_level; u64 timestamp; struct regmap *regmap; struct regmap_field *reg_state; @@ -128,6 +138,12 @@ struct stk3310_data { struct regmap_field *reg_int_ps; struct regmap_field *reg_flag_psint; struct regmap_field *reg_flag_nf; + u32 ps_thdl; + u32 ps_thdh; + u32 ps_near_level; + bool als_enabled; + bool ps_enabled; + bool ps_int_enabled; }; static const struct iio_event_spec stk3310_events[] = { @@ -255,7 +271,7 @@ static int stk3310_read_event(struct iio_dev *indio_dev, return -EINVAL; mutex_lock(&data->lock); - ret = regmap_bulk_read(data->regmap, reg, &buf, 2); + ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf)); mutex_unlock(&data->lock); if (ret < 0) { dev_err(&data->client->dev, "register read failed\n"); @@ -295,11 +311,18 @@ static int stk3310_write_event(struct iio_dev *indio_dev, return -EINVAL; buf = cpu_to_be16(val); - ret = regmap_bulk_write(data->regmap, reg, &buf, 2); - if (ret < 0) + ret = regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf)); + if (ret < 0) { dev_err(&client->dev, "failed to set PS threshold!\n"); + return ret; + } - return ret; + if (reg == STK3310_REG_THDH_PS) + data->ps_thdh = val; + else + data->ps_thdl = val; + + return 0; } static int stk3310_read_event_config(struct iio_dev *indio_dev, @@ -331,11 +354,17 @@ static int stk3310_write_event_config(struct iio_dev *indio_dev, /* Set INT_PS value */ mutex_lock(&data->lock); ret = regmap_field_write(data->reg_int_ps, state); - if (ret < 0) + if (ret < 0) { dev_err(&client->dev, "failed to set interrupt mode\n"); + mutex_unlock(&data->lock); + return ret; + } + + data->ps_int_enabled = state; + mutex_unlock(&data->lock); - return ret; + return 0; } static int stk3310_read_raw(struct iio_dev *indio_dev, @@ -360,7 +389,7 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, reg = STK3310_REG_PS_DATA_MSB; mutex_lock(&data->lock); - ret = regmap_bulk_read(data->regmap, reg, &buf, 2); + ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf)); if (ret < 0) { dev_err(&client->dev, "register read failed\n"); mutex_unlock(&data->lock); @@ -504,10 +533,15 @@ static int stk3310_init(struct iio_dev *indio_dev) /* Enable PS interrupts */ ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN); - if (ret < 0) + if (ret < 0) { dev_err(&client->dev, "failed to enable interrupts!\n"); + return ret; + } - return ret; + data->ps_int_enabled = true; + data->ps_thdh = STK3310_PS_MAX_VAL; + + return 0; } static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg) @@ -671,9 +705,18 @@ static void stk3310_remove(struct i2c_client *client) static int stk3310_suspend(struct device *dev) { struct stk3310_data *data; + int ret; data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + if (data->ps_int_enabled) { + ret = regmap_field_write(data->reg_int_ps, 0x0); + if (ret < 0) { + dev_err(dev, "failed to disable ps int at suspend.\n"); + return ret; + } + } + return stk3310_set_state(data, STK3310_STATE_STANDBY); } @@ -681,6 +724,8 @@ static int stk3310_resume(struct device *dev) { u8 state = 0; struct stk3310_data *data; + __be16 buf; + int ret; data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); if (data->ps_enabled) @@ -688,17 +733,47 @@ static int stk3310_resume(struct device *dev) if (data->als_enabled) state |= STK3310_STATE_EN_ALS; - return stk3310_set_state(data, state); + ret = stk3310_set_state(data, state); + if (ret < 0) + return ret; + + if (data->ps_thdl != 0x0) { + buf = cpu_to_be16(data->ps_thdl); + ret = regmap_bulk_write(data->regmap, STK3310_REG_THDL_PS, &buf, sizeof(buf)); + if (ret < 0) { + dev_err(dev, "failed to set reg THDL_PS at resume.\n"); + return ret; + } + } + + if (data->ps_thdh != STK3310_PS_MAX_VAL) { + buf = cpu_to_be16(data->ps_thdh); + ret = regmap_bulk_write(data->regmap, STK3310_REG_THDH_PS, &buf, sizeof(buf)); + if (ret < 0) { + dev_err(dev, "failed to set reg THDH_PS at resume.\n"); + return ret; + } + } + + if (data->ps_int_enabled) { + ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN); + if (ret < 0) { + dev_err(dev, "failed to enable ps int at resume.\n"); + return ret; + } + } + + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend, stk3310_resume); static const struct i2c_device_id stk3310_i2c_id[] = { - { "STK3013" }, - { "STK3310" }, - { "STK3311" }, - { "STK3335" }, + { .name = "STK3013" }, + { .name = "STK3310" }, + { .name = "STK3311" }, + { .name = "STK3335" }, { } }; MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id); diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 5be461e6dbdb..458178fb629f 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -362,7 +362,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tcs3414_pm_ops, tcs3414_suspend, tcs3414_resume); static const struct i2c_device_id tcs3414_id[] = { - { "tcs3414" }, + { .name = "tcs3414" }, { } }; MODULE_DEVICE_TABLE(i2c, tcs3414_id); diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 12429a3261b3..b61442c5c1be 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -13,16 +13,18 @@ * TODO: wait time */ -#include -#include +#include #include +#include +#include +#include #include +#include +#include #include #include -#include #include -#include #include #define TCS3472_DRV_NAME "tcs3472" @@ -164,8 +166,9 @@ static int tcs3472_read_raw(struct iio_dev *indio_dev, *val = 0; *val2 = (256 - data->atime) * 2400; return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; } - return -EINVAL; } static int tcs3472_write_raw(struct iio_dev *indio_dev, @@ -202,8 +205,9 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev, } return -EINVAL; + default: + return -EINVAL; } - return -EINVAL; } /* @@ -220,32 +224,24 @@ static int tcs3472_read_event(struct iio_dev *indio_dev, int *val2) { struct tcs3472_data *data = iio_priv(indio_dev); - int ret; unsigned int period; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (info) { case IIO_EV_INFO_VALUE: *val = (dir == IIO_EV_DIR_RISING) ? data->high_thresh : data->low_thresh; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: period = (256 - data->atime) * 2400 * tcs3472_intr_pers[data->apers]; *val = period / USEC_PER_SEC; *val2 = period % USEC_PER_SEC; - ret = IIO_VAL_INT_PLUS_MICRO; - break; + return IIO_VAL_INT_PLUS_MICRO; default: - ret = -EINVAL; - break; + return -EINVAL; } - - mutex_unlock(&data->lock); - - return ret; } static int tcs3472_write_event(struct iio_dev *indio_dev, @@ -259,7 +255,8 @@ static int tcs3472_write_event(struct iio_dev *indio_dev, int period; int i; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + switch (info) { case IIO_EV_INFO_VALUE: switch (dir) { @@ -270,18 +267,18 @@ static int tcs3472_write_event(struct iio_dev *indio_dev, command = TCS3472_AILT; break; default: - ret = -EINVAL; - goto error; + return -EINVAL; } ret = i2c_smbus_write_word_data(data->client, command, val); if (ret) - goto error; + return ret; if (dir == IIO_EV_DIR_RISING) data->high_thresh = val; else data->low_thresh = val; - break; + + return 0; case IIO_EV_INFO_PERIOD: period = val * USEC_PER_SEC + val2; for (i = 1; i < ARRAY_SIZE(tcs3472_intr_pers) - 1; i++) { @@ -291,18 +288,14 @@ static int tcs3472_write_event(struct iio_dev *indio_dev, } ret = i2c_smbus_write_byte_data(data->client, TCS3472_PERS, i); if (ret) - goto error; + return ret; data->apers = i; - break; - default: - ret = -EINVAL; - break; - } -error: - mutex_unlock(&data->lock); - return ret; + return 0; + default: + return -EINVAL; + } } static int tcs3472_read_event_config(struct iio_dev *indio_dev, @@ -310,13 +303,10 @@ static int tcs3472_read_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct tcs3472_data *data = iio_priv(indio_dev); - int ret; - mutex_lock(&data->lock); - ret = !!(data->enable & TCS3472_ENABLE_AIEN); - mutex_unlock(&data->lock); + guard(mutex)(&data->lock); - return ret; + return (data->enable & TCS3472_ENABLE_AIEN) ? 1 : 0; } static int tcs3472_write_event_config(struct iio_dev *indio_dev, @@ -327,7 +317,7 @@ static int tcs3472_write_event_config(struct iio_dev *indio_dev, int ret = 0; u8 enable_old; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); enable_old = data->enable; @@ -339,12 +329,13 @@ static int tcs3472_write_event_config(struct iio_dev *indio_dev, if (enable_old != data->enable) { ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, data->enable); - if (ret) + if (ret) { data->enable = enable_old; + return ret; + } } - mutex_unlock(&data->lock); - return ret; + return 0; } static irqreturn_t tcs3472_event_handler(int irq, void *priv) @@ -440,20 +431,45 @@ static const struct iio_info tcs3472_info = { .attrs = &tcs3472_attribute_group, }; +static int tcs3472_powerdown(struct tcs3472_data *data) +{ + int ret; + u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; + + guard(mutex)(&data->lock); + + ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, + data->enable & ~enable_mask); + if (ret) + return ret; + + data->enable &= ~enable_mask; + + return 0; +} + +static void tcs3472_powerdown_action(void *data) +{ + tcs3472_powerdown(data); +} + static int tcs3472_probe(struct i2c_client *client) { + struct device *dev = &client->dev; struct tcs3472_data *data; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); - if (indio_dev == NULL) + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - mutex_init(&data->lock); + ret = devm_mutex_init(dev, &data->lock); + if (ret) + return ret; indio_dev->info = &tcs3472_info; indio_dev->name = TCS3472_DRV_NAME; @@ -466,9 +482,9 @@ static int tcs3472_probe(struct i2c_client *client) return ret; if (ret == 0x44) - dev_info(&client->dev, "TCS34721/34725 found\n"); + dev_info(dev, "TCS34721/34725 found\n"); else if (ret == 0x4d) - dev_info(&client->dev, "TCS34723/34727 found\n"); + dev_info(dev, "TCS34723/34727 found\n"); else return -ENODEV; @@ -510,61 +526,27 @@ static int tcs3472_probe(struct i2c_client *client) if (ret < 0) return ret; - ret = iio_triggered_buffer_setup(indio_dev, NULL, - tcs3472_trigger_handler, NULL); + ret = devm_add_action_or_reset(dev, tcs3472_powerdown_action, data); + if (ret) + return ret; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + tcs3472_trigger_handler, NULL); if (ret < 0) return ret; if (client->irq) { - ret = request_threaded_irq(client->irq, NULL, - tcs3472_event_handler, - IRQF_TRIGGER_FALLING | IRQF_SHARED | - IRQF_ONESHOT, - client->name, indio_dev); + ret = devm_request_threaded_irq(dev, client->irq, NULL, + tcs3472_event_handler, + IRQF_TRIGGER_FALLING | + IRQF_SHARED | + IRQF_ONESHOT, + client->name, indio_dev); if (ret) - goto buffer_cleanup; + return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) - goto free_irq; - - return 0; - -free_irq: - if (client->irq) - free_irq(client->irq, indio_dev); -buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} - -static int tcs3472_powerdown(struct tcs3472_data *data) -{ - int ret; - u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; - - mutex_lock(&data->lock); - - ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, - data->enable & ~enable_mask); - if (!ret) - data->enable &= ~enable_mask; - - mutex_unlock(&data->lock); - - return ret; -} - -static void tcs3472_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - if (client->irq) - free_irq(client->irq, indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - tcs3472_powerdown(iio_priv(indio_dev)); + return devm_iio_device_register(dev, indio_dev); } static int tcs3472_suspend(struct device *dev) @@ -581,23 +563,23 @@ static int tcs3472_resume(struct device *dev) int ret; u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, data->enable | enable_mask); - if (!ret) - data->enable |= enable_mask; + if (ret) + return ret; - mutex_unlock(&data->lock); + data->enable |= enable_mask; - return ret; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(tcs3472_pm_ops, tcs3472_suspend, tcs3472_resume); static const struct i2c_device_id tcs3472_id[] = { - { "tcs3472" }, + { .name = "tcs3472" }, { } }; MODULE_DEVICE_TABLE(i2c, tcs3472_id); @@ -608,7 +590,6 @@ static struct i2c_driver tcs3472_driver = { .pm = pm_sleep_ptr(&tcs3472_pm_ops), }, .probe = tcs3472_probe, - .remove = tcs3472_remove, .id_table = tcs3472_id, }; module_i2c_driver(tcs3472_driver); diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index f2af1cd7c2d1..7e277bc6a8b1 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -839,10 +839,10 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tsl2563_pm_ops, tsl2563_suspend, tsl2563_resume); static const struct i2c_device_id tsl2563_id[] = { - { "tsl2560", 0 }, - { "tsl2561", 1 }, - { "tsl2562", 2 }, - { "tsl2563", 3 }, + { .name = "tsl2560" }, + { .name = "tsl2561" }, + { .name = "tsl2562" }, + { .name = "tsl2563" }, { } }; MODULE_DEVICE_TABLE(i2c, tsl2563_id); diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index 8801a491de77..a0dd122af2cf 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -913,9 +913,9 @@ static DEFINE_RUNTIME_DEV_PM_OPS(tsl2583_pm_ops, tsl2583_suspend, tsl2583_resume, NULL); static const struct i2c_device_id tsl2583_idtable[] = { - { "tsl2580", 0 }, - { "tsl2581", 1 }, - { "tsl2583", 2 }, + { .name = "tsl2580" }, + { .name = "tsl2581" }, + { .name = "tsl2583" }, { } }; MODULE_DEVICE_TABLE(i2c, tsl2583_idtable); diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c index c5557867ea43..f3ffa9721ad5 100644 --- a/drivers/iio/light/tsl2591.c +++ b/drivers/iio/light/tsl2591.c @@ -192,6 +192,24 @@ static const int tsl2591_calibscale_available[] = { 1, 25, 428, 9876, }; +static const u8 tsl2591_persist_table[] = { + [TSL2591_PRST_ALS_INT_CYCLE_ANY] = 1, + [TSL2591_PRST_ALS_INT_CYCLE_2] = 2, + [TSL2591_PRST_ALS_INT_CYCLE_3] = 3, + [TSL2591_PRST_ALS_INT_CYCLE_5] = 5, + [TSL2591_PRST_ALS_INT_CYCLE_10] = 10, + [TSL2591_PRST_ALS_INT_CYCLE_15] = 15, + [TSL2591_PRST_ALS_INT_CYCLE_20] = 20, + [TSL2591_PRST_ALS_INT_CYCLE_25] = 25, + [TSL2591_PRST_ALS_INT_CYCLE_30] = 30, + [TSL2591_PRST_ALS_INT_CYCLE_35] = 35, + [TSL2591_PRST_ALS_INT_CYCLE_40] = 40, + [TSL2591_PRST_ALS_INT_CYCLE_45] = 45, + [TSL2591_PRST_ALS_INT_CYCLE_50] = 50, + [TSL2591_PRST_ALS_INT_CYCLE_55] = 55, + [TSL2591_PRST_ALS_INT_CYCLE_60] = 60, +}; + static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip, u16 als_lower_threshold); static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip, @@ -231,78 +249,22 @@ static int tsl2591_multiplier_to_gain(const u32 multiplier) static int tsl2591_persist_cycle_to_lit(const u8 als_persist) { - switch (als_persist) { - case TSL2591_PRST_ALS_INT_CYCLE_ANY: - return 1; - case TSL2591_PRST_ALS_INT_CYCLE_2: - return 2; - case TSL2591_PRST_ALS_INT_CYCLE_3: - return 3; - case TSL2591_PRST_ALS_INT_CYCLE_5: - return 5; - case TSL2591_PRST_ALS_INT_CYCLE_10: - return 10; - case TSL2591_PRST_ALS_INT_CYCLE_15: - return 15; - case TSL2591_PRST_ALS_INT_CYCLE_20: - return 20; - case TSL2591_PRST_ALS_INT_CYCLE_25: - return 25; - case TSL2591_PRST_ALS_INT_CYCLE_30: - return 30; - case TSL2591_PRST_ALS_INT_CYCLE_35: - return 35; - case TSL2591_PRST_ALS_INT_CYCLE_40: - return 40; - case TSL2591_PRST_ALS_INT_CYCLE_45: - return 45; - case TSL2591_PRST_ALS_INT_CYCLE_50: - return 50; - case TSL2591_PRST_ALS_INT_CYCLE_55: - return 55; - case TSL2591_PRST_ALS_INT_CYCLE_60: - return 60; - default: + if (als_persist >= ARRAY_SIZE(tsl2591_persist_table) || + !tsl2591_persist_table[als_persist]) return -EINVAL; - } + + return tsl2591_persist_table[als_persist]; } static int tsl2591_persist_lit_to_cycle(const u8 als_persist) { - switch (als_persist) { - case 1: - return TSL2591_PRST_ALS_INT_CYCLE_ANY; - case 2: - return TSL2591_PRST_ALS_INT_CYCLE_2; - case 3: - return TSL2591_PRST_ALS_INT_CYCLE_3; - case 5: - return TSL2591_PRST_ALS_INT_CYCLE_5; - case 10: - return TSL2591_PRST_ALS_INT_CYCLE_10; - case 15: - return TSL2591_PRST_ALS_INT_CYCLE_15; - case 20: - return TSL2591_PRST_ALS_INT_CYCLE_20; - case 25: - return TSL2591_PRST_ALS_INT_CYCLE_25; - case 30: - return TSL2591_PRST_ALS_INT_CYCLE_30; - case 35: - return TSL2591_PRST_ALS_INT_CYCLE_35; - case 40: - return TSL2591_PRST_ALS_INT_CYCLE_40; - case 45: - return TSL2591_PRST_ALS_INT_CYCLE_45; - case 50: - return TSL2591_PRST_ALS_INT_CYCLE_50; - case 55: - return TSL2591_PRST_ALS_INT_CYCLE_55; - case 60: - return TSL2591_PRST_ALS_INT_CYCLE_60; - default: - return -EINVAL; + for (unsigned int i = TSL2591_PRST_ALS_INT_CYCLE_ANY; + i < ARRAY_SIZE(tsl2591_persist_table); i++) { + if (als_persist == tsl2591_persist_table[i]) + return i; } + + return -EINVAL; } static int tsl2591_compatible_int_time(struct tsl2591_chip *chip, @@ -346,31 +308,6 @@ static int tsl2591_compatible_gain(struct tsl2591_chip *chip, const u8 als_gain) } } -static int tsl2591_compatible_als_persist_cycle(struct tsl2591_chip *chip, - const u32 als_persist) -{ - switch (als_persist) { - case TSL2591_PRST_ALS_INT_CYCLE_ANY: - case TSL2591_PRST_ALS_INT_CYCLE_2: - case TSL2591_PRST_ALS_INT_CYCLE_3: - case TSL2591_PRST_ALS_INT_CYCLE_5: - case TSL2591_PRST_ALS_INT_CYCLE_10: - case TSL2591_PRST_ALS_INT_CYCLE_15: - case TSL2591_PRST_ALS_INT_CYCLE_20: - case TSL2591_PRST_ALS_INT_CYCLE_25: - case TSL2591_PRST_ALS_INT_CYCLE_30: - case TSL2591_PRST_ALS_INT_CYCLE_35: - case TSL2591_PRST_ALS_INT_CYCLE_40: - case TSL2591_PRST_ALS_INT_CYCLE_45: - case TSL2591_PRST_ALS_INT_CYCLE_50: - case TSL2591_PRST_ALS_INT_CYCLE_55: - case TSL2591_PRST_ALS_INT_CYCLE_60: - return 0; - default: - return -EINVAL; - } -} - static int tsl2591_check_als_valid(struct i2c_client *client) { int ret; @@ -952,10 +889,6 @@ static int tsl2591_write_event_value(struct iio_dev *indio_dev, goto err_unlock; } - ret = tsl2591_compatible_als_persist_cycle(chip, als_persist); - if (ret < 0) - goto err_unlock; - ret = tsl2591_set_als_persist_cycle(chip, als_persist); if (ret < 0) goto err_unlock; diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index c8f15ba95267..244f44379c36 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -127,6 +127,7 @@ enum { tmd2672, tsl2772, tmd2772, + apds9900, apds9930, }; @@ -221,6 +222,12 @@ static const struct tsl2772_lux tmd2x72_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { { 0, 0 }, }; +static const struct tsl2772_lux apds9900_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { + { 52000, 115960 }, + { 36400, 73840 }, + { 0, 0 }, +}; + static const struct tsl2772_lux apds9930_lux_table[TSL2772_DEF_LUX_TABLE_SZ] = { { 52000, 96824 }, { 38792, 67132 }, @@ -238,6 +245,7 @@ static const struct tsl2772_lux *tsl2772_default_lux_table_group[] = { [tmd2672] = tmd2x72_lux_table, [tsl2772] = tsl2x72_lux_table, [tmd2772] = tmd2x72_lux_table, + [apds9900] = apds9900_lux_table, [apds9930] = apds9930_lux_table, }; @@ -289,6 +297,7 @@ static const int tsl2772_int_time_avail[][6] = { [tmd2672] = { 0, 2730, 0, 2730, 0, 699000 }, [tsl2772] = { 0, 2730, 0, 2730, 0, 699000 }, [tmd2772] = { 0, 2730, 0, 2730, 0, 699000 }, + [apds9900] = { 0, 2720, 0, 2720, 0, 696000 }, [apds9930] = { 0, 2730, 0, 2730, 0, 699000 }, }; @@ -316,6 +325,7 @@ static const u8 device_channel_config[] = { [tmd2672] = PRX2, [tsl2772] = ALSPRX2, [tmd2772] = ALSPRX2, + [apds9900] = ALSPRX, [apds9930] = ALSPRX2, }; @@ -530,6 +540,7 @@ static int tsl2772_get_prox(struct iio_dev *indio_dev) case tmd2672: case tsl2772: case tmd2772: + case apds9900: case apds9930: if (!(ret & TSL2772_STA_PRX_VALID)) { ret = -EINVAL; @@ -1367,6 +1378,7 @@ static int tsl2772_device_id_verif(int id, int target) return (id & 0xf0) == TRITON_ID; case tmd2671: case tmd2771: + case apds9900: return (id & 0xf0) == HALIBUT_ID; case tsl2572: case tsl2672: @@ -1888,17 +1900,19 @@ static int tsl2772_resume(struct device *dev) } static const struct i2c_device_id tsl2772_idtable[] = { - { "tsl2571", tsl2571 }, - { "tsl2671", tsl2671 }, - { "tmd2671", tmd2671 }, - { "tsl2771", tsl2771 }, - { "tmd2771", tmd2771 }, - { "tsl2572", tsl2572 }, - { "tsl2672", tsl2672 }, - { "tmd2672", tmd2672 }, - { "tsl2772", tsl2772 }, - { "tmd2772", tmd2772 }, - { "apds9930", apds9930 }, + { .name = "tsl2571", .driver_data = tsl2571 }, + { .name = "tsl2671", .driver_data = tsl2671 }, + { .name = "tmd2671", .driver_data = tmd2671 }, + { .name = "tsl2771", .driver_data = tsl2771 }, + { .name = "tmd2771", .driver_data = tmd2771 }, + { .name = "tsl2572", .driver_data = tsl2572 }, + { .name = "tsl2672", .driver_data = tsl2672 }, + { .name = "tmd2672", .driver_data = tmd2672 }, + { .name = "tsl2772", .driver_data = tsl2772 }, + { .name = "tmd2772", .driver_data = tmd2772 }, + { .name = "apds9900", .driver_data = apds9900 }, + { .name = "apds9901", .driver_data = apds9900 }, + { .name = "apds9930", .driver_data = apds9930 }, { } }; @@ -1915,6 +1929,8 @@ static const struct of_device_id tsl2772_of_match[] = { { .compatible = "amstaos,tmd2672" }, { .compatible = "amstaos,tsl2772" }, { .compatible = "amstaos,tmd2772" }, + { .compatible = "avago,apds9900" }, + { .compatible = "avago,apds9901" }, { .compatible = "avago,apds9930" }, { } }; diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c index a5788c09ad02..2f91ed8a9876 100644 --- a/drivers/iio/light/tsl4531.c +++ b/drivers/iio/light/tsl4531.c @@ -227,7 +227,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, tsl4531_resume); static const struct i2c_device_id tsl4531_id[] = { - { "tsl4531" }, + { .name = "tsl4531" }, { } }; MODULE_DEVICE_TABLE(i2c, tsl4531_id); diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index d2f5a44892a8..d335e5e551f1 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -949,7 +949,7 @@ static const struct acpi_device_id us5182d_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); static const struct i2c_device_id us5182d_id[] = { - { "usd5182" }, + { .name = "usd5182" }, { } }; diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 9650dbc41f2b..128ae3f94074 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -185,14 +186,6 @@ static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8}; #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ -enum vcnl4000_device_ids { - CM36672P, - VCNL4000, - VCNL4010, - VCNL4040, - VCNL4200, -}; - struct vcnl4200_channel { u8 reg; ktime_t last_measurement; @@ -202,7 +195,6 @@ struct vcnl4200_channel { struct vcnl4000_data { struct i2c_client *client; - enum vcnl4000_device_ids id; int rev; int al_scale; int ps_scale; @@ -234,20 +226,9 @@ struct vcnl4000_chip_spec { const int(*als_it_times)[][2]; const int num_als_it_times; const unsigned int ulux_step; + const int prod_id; }; -static const struct i2c_device_id vcnl4000_id[] = { - { "cm36672p", CM36672P }, - { "cm36686", VCNL4040 }, - { "vcnl4000", VCNL4000 }, - { "vcnl4010", VCNL4010 }, - { "vcnl4020", VCNL4010 }, - { "vcnl4040", VCNL4040 }, - { "vcnl4200", VCNL4200 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, vcnl4000_id); - static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on) { /* no suspend op */ @@ -265,12 +246,12 @@ static int vcnl4000_init(struct vcnl4000_data *data) prod_id = ret >> 4; switch (prod_id) { case VCNL4000_PROD_ID: - if (data->id != VCNL4000) + if (data->chip_spec->prod_id != VCNL4000_PROD_ID) dev_warn(&data->client->dev, "wrong device id, use vcnl4000"); break; case VCNL4010_PROD_ID: - if (data->id != VCNL4010) + if (data->chip_spec->prod_id != VCNL4010_PROD_ID) dev_warn(&data->client->dev, "wrong device id, use vcnl4010/4020"); break; @@ -288,46 +269,36 @@ static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en) { int ret; - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); if (ret < 0) - goto out; + return ret; if (en) ret &= ~VCNL4040_ALS_CONF_ALS_SHUTDOWN; else ret |= VCNL4040_ALS_CONF_ALS_SHUTDOWN; - ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, ret); - -out: - mutex_unlock(&data->vcnl4000_lock); - - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, ret); } static ssize_t vcnl4000_write_ps_enable(struct vcnl4000_data *data, bool en) { int ret; - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); if (ret < 0) - goto out; + return ret; if (en) ret &= ~VCNL4040_PS_CONF1_PS_SHUTDOWN; else ret |= VCNL4040_PS_CONF1_PS_SHUTDOWN; - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, ret); - -out: - mutex_unlock(&data->vcnl4000_lock); - - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, ret); } static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on) @@ -462,18 +433,18 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, int tries = 20; int ret; - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, req_mask); if (ret < 0) - goto fail; + return ret; /* wait for data to become ready */ while (tries--) { ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); if (ret < 0) - goto fail; + return ret; if (ret & rdy_mask) break; msleep(20); /* measurement takes up to 100 ms */ @@ -482,21 +453,10 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, if (tries < 0) { dev_err(&data->client->dev, "vcnl4000_measure() failed, data not ready\n"); - ret = -EIO; - goto fail; + return -EIO; } - ret = vcnl4000_read_data(data, data_reg, val); - if (ret < 0) - goto fail; - - mutex_unlock(&data->vcnl4000_lock); - - return 0; - -fail: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return vcnl4000_read_data(data, data_reg, val); } static int vcnl4200_measure(struct vcnl4000_data *data, @@ -506,16 +466,14 @@ static int vcnl4200_measure(struct vcnl4000_data *data, s64 delta; ktime_t next_measurement; - mutex_lock(&chan->lock); - - next_measurement = ktime_add(chan->last_measurement, - chan->sampling_rate); - delta = ktime_us_delta(next_measurement, ktime_get()); - if (delta > 0) - usleep_range(delta, delta + 500); - chan->last_measurement = ktime_get(); - - mutex_unlock(&chan->lock); + scoped_guard(mutex, &chan->lock) { + next_measurement = ktime_add(chan->last_measurement, + chan->sampling_rate); + delta = ktime_us_delta(next_measurement, ktime_get()); + if (delta > 0) + usleep_range(delta, delta + 500); + chan->last_measurement = ktime_get(); + } ret = i2c_smbus_read_word_data(data->client, chan->reg); if (ret < 0) @@ -626,21 +584,15 @@ static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val) (*data->chip_spec->als_it_times)[0][1]), val); - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); if (ret < 0) - goto out_unlock; + return ret; regval = FIELD_PREP(VCNL4040_ALS_CONF_IT, i); regval |= (ret & ~VCNL4040_ALS_CONF_IT); - ret = i2c_smbus_write_word_data(data->client, - VCNL4200_AL_CONF, - regval); - -out_unlock: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, regval); } static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2) @@ -680,20 +632,15 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val) data->vcnl4200_ps.sampling_rate = ktime_set(0, val * 60 * NSEC_PER_USEC); - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); if (ret < 0) - goto out; + return ret; regval = (ret & ~VCNL4040_PS_CONF2_PS_IT) | FIELD_PREP(VCNL4040_PS_CONF2_PS_IT, index); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, - regval); - -out: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, regval); } static ssize_t vcnl4040_read_als_period(struct vcnl4000_data *data, int *val, int *val2) @@ -741,20 +688,15 @@ static ssize_t vcnl4040_write_als_period(struct vcnl4000_data *data, int val, in break; } - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); if (ret < 0) - goto out_unlock; + return ret; regval = FIELD_PREP(VCNL4040_ALS_CONF_PERS, i); regval |= (ret & ~VCNL4040_ALS_CONF_PERS); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, - regval); - -out_unlock: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, regval); } static ssize_t vcnl4040_read_ps_period(struct vcnl4000_data *data, int *val, int *val2) @@ -803,20 +745,15 @@ static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, int } } - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); if (ret < 0) - goto out_unlock; + return ret; regval = FIELD_PREP(VCNL4040_CONF1_PS_PERS, i); regval |= (ret & ~VCNL4040_CONF1_PS_PERS); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, - regval); - -out_unlock: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, regval); } static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val) @@ -850,20 +787,15 @@ static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, if (i >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio)) return -EINVAL; - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3); if (ret < 0) - goto out_unlock; + return ret; regval = FIELD_PREP(VCNL4040_PS_CONF3_MPS, i); regval |= (ret & ~VCNL4040_PS_CONF3_MPS); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, - regval); - -out_unlock: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, regval); } static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2) @@ -898,20 +830,15 @@ static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val) if (i >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua)) return -EINVAL; - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3); if (ret < 0) - goto out_unlock; + return ret; regval = (ret & ~VCNL4040_PS_MS_LED_I); regval |= FIELD_PREP(VCNL4040_PS_MS_LED_I, i); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, - regval); - -out_unlock: - mutex_unlock(&data->vcnl4000_lock); - return ret; + return i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, regval); } static int vcnl4000_read_raw(struct iio_dev *indio_dev, @@ -1496,17 +1423,17 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir, bool state) { - int ret = -EINVAL; + int ret; u16 val, mask; struct vcnl4000_data *data = iio_priv(indio_dev); - mutex_lock(&data->vcnl4000_lock); + guard(mutex)(&data->vcnl4000_lock); switch (chan->type) { case IIO_LIGHT: ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); if (ret < 0) - goto out; + return ret; mask = VCNL4040_ALS_CONF_INT_EN; if (state) @@ -1515,13 +1442,11 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev, val = (ret & ~mask); data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, - val); - break; + return i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val); case IIO_PROXIMITY: ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); if (ret < 0) - goto out; + return ret; if (dir == IIO_EV_DIR_RISING) mask = VCNL4040_PS_IF_AWAY; @@ -1531,17 +1456,10 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev, val = state ? (ret | mask) : (ret & ~mask); data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val); - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, - val); - break; + return i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val); default: - break; + return -EINVAL; } - -out: - mutex_unlock(&data->vcnl4000_lock); - - return ret; } static irqreturn_t vcnl4040_irq_thread(int irq, void *p) @@ -1888,77 +1806,84 @@ static const struct iio_info vcnl4040_info = { .read_avail = vcnl4040_read_avail, }; -static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { - [CM36672P] = { - .prod = "CM36672P", - .init = vcnl4200_init, - .measure_proximity = vcnl4200_measure_proximity, - .set_power_state = vcnl4200_set_power_state, - .channels = cm36672p_channels, - .num_channels = ARRAY_SIZE(cm36672p_channels), - .info = &vcnl4040_info, - .irq_thread = vcnl4040_irq_thread, - .int_reg = VCNL4040_INT_FLAGS, - .ps_it_times = &vcnl4040_ps_it_times, - .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), - }, - [VCNL4000] = { - .prod = "VCNL4000", - .init = vcnl4000_init, - .measure_light = vcnl4000_measure_light, - .measure_proximity = vcnl4000_measure_proximity, - .set_power_state = vcnl4000_set_power_state, - .channels = vcnl4000_channels, - .num_channels = ARRAY_SIZE(vcnl4000_channels), - .info = &vcnl4000_info, - }, - [VCNL4010] = { - .prod = "VCNL4010/4020", - .init = vcnl4000_init, - .measure_light = vcnl4000_measure_light, - .measure_proximity = vcnl4000_measure_proximity, - .set_power_state = vcnl4000_set_power_state, - .channels = vcnl4010_channels, - .num_channels = ARRAY_SIZE(vcnl4010_channels), - .info = &vcnl4010_info, - .irq_thread = vcnl4010_irq_thread, - .trig_buffer_func = vcnl4010_trigger_handler, - .buffer_setup_ops = &vcnl4010_buffer_ops, - }, - [VCNL4040] = { - .prod = "VCNL4040", - .init = vcnl4200_init, - .measure_light = vcnl4200_measure_light, - .measure_proximity = vcnl4200_measure_proximity, - .set_power_state = vcnl4200_set_power_state, - .channels = vcnl4040_channels, - .num_channels = ARRAY_SIZE(vcnl4040_channels), - .info = &vcnl4040_info, - .irq_thread = vcnl4040_irq_thread, - .int_reg = VCNL4040_INT_FLAGS, - .ps_it_times = &vcnl4040_ps_it_times, - .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), - .als_it_times = &vcnl4040_als_it_times, - .num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times), - .ulux_step = 100000, - }, - [VCNL4200] = { - .prod = "VCNL4200", - .init = vcnl4200_init, - .measure_light = vcnl4200_measure_light, - .measure_proximity = vcnl4200_measure_proximity, - .set_power_state = vcnl4200_set_power_state, - .channels = vcnl4040_channels, - .num_channels = ARRAY_SIZE(vcnl4000_channels), - .info = &vcnl4040_info, - .irq_thread = vcnl4040_irq_thread, - .int_reg = VCNL4200_INT_FLAGS, - .ps_it_times = &vcnl4200_ps_it_times, - .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times), - .als_it_times = &vcnl4200_als_it_times, - .num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times), - .ulux_step = 24000, - }, +static const struct vcnl4000_chip_spec cm36672p_spec = { + .prod = "CM36672P", + .init = vcnl4200_init, + .measure_proximity = vcnl4200_measure_proximity, + .set_power_state = vcnl4200_set_power_state, + .channels = cm36672p_channels, + .num_channels = ARRAY_SIZE(cm36672p_channels), + .info = &vcnl4040_info, + .irq_thread = vcnl4040_irq_thread, + .int_reg = VCNL4040_INT_FLAGS, + .ps_it_times = &vcnl4040_ps_it_times, + .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), + .prod_id = VCNL4040_PROD_ID, +}; + +static const struct vcnl4000_chip_spec vcnl4000_spec = { + .prod = "VCNL4000", + .init = vcnl4000_init, + .measure_light = vcnl4000_measure_light, + .measure_proximity = vcnl4000_measure_proximity, + .set_power_state = vcnl4000_set_power_state, + .channels = vcnl4000_channels, + .num_channels = ARRAY_SIZE(vcnl4000_channels), + .info = &vcnl4000_info, + .prod_id = VCNL4000_PROD_ID, +}; + +static const struct vcnl4000_chip_spec vcnl4010_spec = { + .prod = "VCNL4010/4020", + .init = vcnl4000_init, + .measure_light = vcnl4000_measure_light, + .measure_proximity = vcnl4000_measure_proximity, + .set_power_state = vcnl4000_set_power_state, + .channels = vcnl4010_channels, + .num_channels = ARRAY_SIZE(vcnl4010_channels), + .info = &vcnl4010_info, + .irq_thread = vcnl4010_irq_thread, + .trig_buffer_func = vcnl4010_trigger_handler, + .buffer_setup_ops = &vcnl4010_buffer_ops, + .prod_id = VCNL4010_PROD_ID, +}; + +static const struct vcnl4000_chip_spec vcnl4040_spec = { + .prod = "VCNL4040", + .init = vcnl4200_init, + .measure_light = vcnl4200_measure_light, + .measure_proximity = vcnl4200_measure_proximity, + .set_power_state = vcnl4200_set_power_state, + .channels = vcnl4040_channels, + .num_channels = ARRAY_SIZE(vcnl4040_channels), + .info = &vcnl4040_info, + .irq_thread = vcnl4040_irq_thread, + .int_reg = VCNL4040_INT_FLAGS, + .ps_it_times = &vcnl4040_ps_it_times, + .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), + .als_it_times = &vcnl4040_als_it_times, + .num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times), + .ulux_step = 100000, + .prod_id = VCNL4040_PROD_ID, +}; + +static const struct vcnl4000_chip_spec vcnl4200_spec = { + .prod = "VCNL4200", + .init = vcnl4200_init, + .measure_light = vcnl4200_measure_light, + .measure_proximity = vcnl4200_measure_proximity, + .set_power_state = vcnl4200_set_power_state, + .channels = vcnl4040_channels, + .num_channels = ARRAY_SIZE(vcnl4000_channels), + .info = &vcnl4040_info, + .irq_thread = vcnl4040_irq_thread, + .int_reg = VCNL4200_INT_FLAGS, + .ps_it_times = &vcnl4200_ps_it_times, + .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times), + .als_it_times = &vcnl4200_als_it_times, + .num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times), + .ulux_step = 24000, + .prod_id = VCNL4200_PROD_ID, }; static const struct iio_trigger_ops vcnl4010_trigger_ops = { @@ -1983,9 +1908,20 @@ static int vcnl4010_probe_trigger(struct iio_dev *indio_dev) return devm_iio_trigger_register(&client->dev, trigger); } +static void vcnl4000_cleanup(void *data) +{ + struct iio_dev *indio_dev = data; + struct vcnl4000_data *chip = iio_priv(indio_dev); + struct device *dev = &chip->client->dev; + int ret; + + ret = chip->chip_spec->set_power_state(chip, false); + if (ret) + dev_warn(dev, "Failed to power down (%pe)", ERR_PTR(ret)); +} + static int vcnl4000_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); const char * const regulator_names[] = { "vdd", "vio", "vled" }; struct device *dev = &client->dev; struct vcnl4000_data *data; @@ -1999,8 +1935,7 @@ static int vcnl4000_probe(struct i2c_client *client) data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - data->id = id->driver_data; - data->chip_spec = &vcnl4000_chip_spec_cfg[data->id]; + data->chip_spec = i2c_get_match_data(client); ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names), regulator_names); @@ -2019,6 +1954,10 @@ static int vcnl4000_probe(struct i2c_client *client) if (ret) return ret; + ret = devm_add_action_or_reset(dev, vcnl4000_cleanup, indio_dev); + if (ret) + return ret; + dev_dbg(dev, "%s Ambient light/proximity sensor, Rev: %02x\n", data->chip_spec->prod, data->rev); @@ -2054,75 +1993,33 @@ static int vcnl4000_probe(struct i2c_client *client) return ret; } - ret = pm_runtime_set_active(dev); - if (ret < 0) - goto fail_poweroff; + ret = devm_pm_runtime_set_active_enabled(dev); + if (ret) + return ret; - ret = iio_device_register(indio_dev); - if (ret < 0) - goto fail_poweroff; + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ret; - pm_runtime_enable(dev); pm_runtime_set_autosuspend_delay(dev, VCNL4000_SLEEP_DELAY_MS); pm_runtime_use_autosuspend(dev); return 0; -fail_poweroff: - data->chip_spec->set_power_state(data, false); - return ret; } static const struct of_device_id vcnl_4000_of_match[] = { - { - .compatible = "capella,cm36672p", - .data = (void *)CM36672P, - }, + { .compatible = "capella,cm36672p", .data = &cm36672p_spec }, /* Capella CM36686 is fully compatible with Vishay VCNL4040 */ - { - .compatible = "capella,cm36686", - .data = (void *)VCNL4040, - }, - { - .compatible = "vishay,vcnl4000", - .data = (void *)VCNL4000, - }, - { - .compatible = "vishay,vcnl4010", - .data = (void *)VCNL4010, - }, - { - .compatible = "vishay,vcnl4020", - .data = (void *)VCNL4010, - }, - { - .compatible = "vishay,vcnl4040", - .data = (void *)VCNL4040, - }, - { - .compatible = "vishay,vcnl4200", - .data = (void *)VCNL4200, - }, + { .compatible = "capella,cm36686", .data = &vcnl4040_spec }, + { .compatible = "vishay,vcnl4000", .data = &vcnl4000_spec }, + { .compatible = "vishay,vcnl4010", .data = &vcnl4010_spec }, + { .compatible = "vishay,vcnl4020", .data = &vcnl4010_spec }, + { .compatible = "vishay,vcnl4040", .data = &vcnl4040_spec }, + { .compatible = "vishay,vcnl4200", .data = &vcnl4200_spec }, { } }; MODULE_DEVICE_TABLE(of, vcnl_4000_of_match); -static void vcnl4000_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct vcnl4000_data *data = iio_priv(indio_dev); - int ret; - - pm_runtime_dont_use_autosuspend(&client->dev); - pm_runtime_disable(&client->dev); - iio_device_unregister(indio_dev); - pm_runtime_set_suspended(&client->dev); - - ret = data->chip_spec->set_power_state(data, false); - if (ret) - dev_warn(&client->dev, "Failed to power down (%pe)\n", - ERR_PTR(ret)); -} - static int vcnl4000_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); @@ -2142,6 +2039,18 @@ static int vcnl4000_runtime_resume(struct device *dev) static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend, vcnl4000_runtime_resume, NULL); +static const struct i2c_device_id vcnl4000_id[] = { + { .name = "cm36672p", .driver_data = (kernel_ulong_t)&cm36672p_spec }, + { .name = "cm36686", .driver_data = (kernel_ulong_t)&vcnl4040_spec }, + { .name = "vcnl4000", .driver_data = (kernel_ulong_t)&vcnl4000_spec }, + { .name = "vcnl4010", .driver_data = (kernel_ulong_t)&vcnl4010_spec }, + { .name = "vcnl4020", .driver_data = (kernel_ulong_t)&vcnl4010_spec }, + { .name = "vcnl4040", .driver_data = (kernel_ulong_t)&vcnl4040_spec }, + { .name = "vcnl4200", .driver_data = (kernel_ulong_t)&vcnl4200_spec }, + { } +}; +MODULE_DEVICE_TABLE(i2c, vcnl4000_id); + static struct i2c_driver vcnl4000_driver = { .driver = { .name = VCNL4000_DRV_NAME, @@ -2150,7 +2059,6 @@ static struct i2c_driver vcnl4000_driver = { }, .probe = vcnl4000_probe, .id_table = vcnl4000_id, - .remove = vcnl4000_remove, }; module_i2c_driver(vcnl4000_driver); diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 16aeb17067bc..bf3a49b4351d 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -662,7 +662,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4035_pm_ops, vcnl4035_runtime_suspend, vcnl4035_runtime_resume, NULL); static const struct i2c_device_id vcnl4035_id[] = { - { "vcnl4035" }, + { .name = "vcnl4035" }, { } }; MODULE_DEVICE_TABLE(i2c, vcnl4035_id); diff --git a/drivers/iio/light/veml3235.c b/drivers/iio/light/veml3235.c index 9309ad83ca9e..d8a39223009b 100644 --- a/drivers/iio/light/veml3235.c +++ b/drivers/iio/light/veml3235.c @@ -525,7 +525,7 @@ static const struct of_device_id veml3235_of_match[] = { MODULE_DEVICE_TABLE(of, veml3235_of_match); static const struct i2c_device_id veml3235_id[] = { - { "veml3235" }, + { .name = "veml3235" }, { } }; MODULE_DEVICE_TABLE(i2c, veml3235_id); diff --git a/drivers/iio/light/veml3328.c b/drivers/iio/light/veml3328.c new file mode 100644 index 000000000000..9309deb5bf19 --- /dev/null +++ b/drivers/iio/light/veml3328.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Vishay VEML3328 RGBCIR light sensor driver + * + * Copyright (c) 2026 Joshua Crofts + * + * Datasheet: https://www.vishay.com/docs/84968/veml3328.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define VEML3328_REG_CONF 0x00 +#define VEML3328_REG_ID 0x0c +#define VEML3328_REG_DATA_C 0x04 +#define VEML3328_REG_DATA_R 0x05 +#define VEML3328_REG_DATA_G 0x06 +#define VEML3328_REG_DATA_B 0x07 +#define VEML3328_REG_DATA_IR 0x08 + +#define VEML3328_CONF_IT_MASK GENMASK(5, 4) +#define VEML3328_CONF_GAIN_MASK GENMASK(11, 10) + +#define VEML3328_MAX_IT_TIME (400 * USEC_PER_MSEC) + +#define VEML3328_ID_VAL 0x28 + +#define VEML3328_SHUTDOWN (BIT(0) | BIT(15)) + +struct veml3328_data { + struct regmap *regmap; + /* Ensure read-modify-write sequences are not interrupted. */ + struct mutex lock; +}; + +static const struct regmap_config veml3328_regmap_config = { + .name = "veml3328", + .reg_bits = 8, + .val_bits = 16, + .max_register = VEML3328_REG_ID, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +#define VEML3328_CHAN_SPEC(_color, _addr) { \ + .type = IIO_INTENSITY, \ + .modified = 1, \ + .channel2 = IIO_MOD_LIGHT_##_color, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), \ + .address = _addr, \ +} + +static const struct iio_chan_spec veml3328_channels[] = { + { + .type = IIO_LIGHT, + + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), + .address = VEML3328_REG_DATA_G, + }, + VEML3328_CHAN_SPEC(CLEAR, VEML3328_REG_DATA_C), + VEML3328_CHAN_SPEC(RED, VEML3328_REG_DATA_R), + VEML3328_CHAN_SPEC(GREEN, VEML3328_REG_DATA_G), + VEML3328_CHAN_SPEC(BLUE, VEML3328_REG_DATA_B), + VEML3328_CHAN_SPEC(IR, VEML3328_REG_DATA_IR), +}; + +/* + * Precomputed scale values (micro units). + * Formula for calculation: 0.384 * (50000 / IT_us) * (1 / Gain) + * Gain indexes: 0 (x0.5), 1 (x1), 2 (x2), 3 (x4) + * IT indexes: 0 (50ms), 1 (100ms), 2 (200ms), 3 (400ms) + */ +static const int veml3328_scale_vals[4][8] = { + { 0, 768000, 0, 384000, 0, 192000, 0, 96000 }, + { 0, 384000, 0, 192000, 0, 96000, 0, 48000 }, + { 0, 192000, 0, 96000, 0, 48000, 0, 24000 }, + { 0, 96000, 0, 48000, 0, 24000, 0, 12000 }, +}; + +/* integration times in microseconds */ +static const int veml3328_it_times[][2] = { + { 0, 50 * USEC_PER_MSEC }, + { 0, 100 * USEC_PER_MSEC }, + { 0, 200 * USEC_PER_MSEC }, + { 0, 400 * USEC_PER_MSEC }, +}; + +static int veml3328_power_down(struct veml3328_data *data) +{ + return regmap_set_bits(data->regmap, VEML3328_REG_CONF, + VEML3328_SHUTDOWN); +} + +static int veml3328_power_up(struct veml3328_data *data) +{ + int ret; + + ret = regmap_clear_bits(data->regmap, VEML3328_REG_CONF, + VEML3328_SHUTDOWN); + if (ret) + return ret; + + /* + * Sleep for maximum integration time to ensure sensor is powered on + * correctly. + */ + fsleep(VEML3328_MAX_IT_TIME); + + return 0; +} + +static void veml3328_power_down_action(void *data) +{ + veml3328_power_down(data); +} + +static int veml3328_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct veml3328_data *data = iio_priv(indio_dev); + struct regmap *regmap = data->regmap; + struct device *dev = regmap_get_device(regmap); + unsigned int reg_val; + int it_inx, gain_inx; + int ret; + + PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(regmap, chan->address, ®_val); + if (ret) + return ret; + + *val = reg_val; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_INT_TIME: + ret = regmap_read(regmap, VEML3328_REG_CONF, ®_val); + if (ret) + return ret; + + it_inx = FIELD_GET(VEML3328_CONF_IT_MASK, reg_val); + if (it_inx >= ARRAY_SIZE(veml3328_it_times)) + return -EINVAL; + + *val = veml3328_it_times[it_inx][0]; + *val2 = veml3328_it_times[it_inx][1]; + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CHAN_INFO_SCALE: + ret = regmap_read(regmap, VEML3328_REG_CONF, ®_val); + if (ret) + return ret; + + it_inx = FIELD_GET(VEML3328_CONF_IT_MASK, reg_val); + gain_inx = FIELD_GET(VEML3328_CONF_GAIN_MASK, reg_val); + + if (it_inx >= ARRAY_SIZE(veml3328_it_times) || gain_inx >= 4) + return -EINVAL; + + /* Stride by 2 through the flattened array to match (val, val2) */ + *val = veml3328_scale_vals[it_inx][gain_inx * 2]; + *val2 = veml3328_scale_vals[it_inx][gain_inx * 2 + 1]; + + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +static int veml3328_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct veml3328_data *data = iio_priv(indio_dev); + struct regmap *regmap = data->regmap; + struct device *dev = regmap_get_device(data->regmap); + unsigned int reg_val; + int ret, it_inx; + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(veml3328_it_times) * 2; + *vals = (const int *)veml3328_it_times; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + + case IIO_CHAN_INFO_SCALE: { + PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret) + return ret; + + ret = regmap_read(regmap, VEML3328_REG_CONF, ®_val); + if (ret) + return ret; + + it_inx = FIELD_GET(VEML3328_CONF_IT_MASK, reg_val); + if (it_inx >= ARRAY_SIZE(veml3328_it_times)) + return -EINVAL; + + *length = 8; + *vals = (const int *)veml3328_scale_vals[it_inx]; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + } + default: + return -EINVAL; + } +} + +static int veml3328_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct veml3328_data *data = iio_priv(indio_dev); + struct regmap *regmap = data->regmap; + struct device *dev = regmap_get_device(regmap); + unsigned int reg_val; + int i, it_inx; + int ret; + + PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret) + return ret; + + guard(mutex)(&data->lock); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + if (val != 0) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(veml3328_it_times); i++) { + if (veml3328_it_times[i][1] == val2) + break; + } + + if (i == ARRAY_SIZE(veml3328_it_times)) + return -EINVAL; + + return regmap_update_bits(regmap, VEML3328_REG_CONF, + VEML3328_CONF_IT_MASK, + FIELD_PREP(VEML3328_CONF_IT_MASK, i)); + + case IIO_CHAN_INFO_SCALE: + ret = regmap_read(regmap, VEML3328_REG_CONF, ®_val); + if (ret) + return ret; + + it_inx = FIELD_GET(VEML3328_CONF_IT_MASK, reg_val); + if (it_inx >= ARRAY_SIZE(veml3328_it_times)) + return -EINVAL; + + for (i = 0; i < 4; i++) { + if (val == veml3328_scale_vals[it_inx][i * 2] && + val2 == veml3328_scale_vals[it_inx][i * 2 + 1]) + break; + } + + if (i == 4) + return -EINVAL; + + return regmap_update_bits(regmap, VEML3328_REG_CONF, + VEML3328_CONF_GAIN_MASK, + FIELD_PREP(VEML3328_CONF_GAIN_MASK, i)); + + default: + return -EINVAL; + } +} + +static const struct iio_info veml3328_info = { + .read_raw = veml3328_read_raw, + .write_raw = veml3328_write_raw, + .read_avail = veml3328_read_avail, +}; + +static int veml3328_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct veml3328_data *data; + struct iio_dev *indio_dev; + unsigned int reg_val; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + + data->regmap = devm_regmap_init_i2c(client, &veml3328_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), + "Failed to initialize regmap\n"); + + ret = devm_mutex_init(dev, &data->lock); + if (ret) + return ret; + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulator\n"); + + ret = regmap_read(data->regmap, VEML3328_REG_ID, ®_val); + if (ret) + return dev_err_probe(dev, ret, "Failed to read ID register\n"); + + if ((reg_val & 0xff) != VEML3328_ID_VAL) + dev_warn(dev, "Unknown device ID: 0x%02x\n", reg_val & 0xff); + + ret = veml3328_power_up(data); + if (ret) + return dev_err_probe(dev, ret, "Failed to power on sensor\n"); + + ret = devm_add_action_or_reset(dev, veml3328_power_down_action, data); + if (ret) + return dev_err_probe(dev, ret, "Failed to register teardown\n"); + + indio_dev->name = "veml3328"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &veml3328_info; + indio_dev->channels = veml3328_channels; + indio_dev->num_channels = ARRAY_SIZE(veml3328_channels); + + pm_runtime_set_active(dev); + pm_runtime_set_autosuspend_delay(dev, 2000); + pm_runtime_use_autosuspend(dev); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); + + return devm_iio_device_register(dev, indio_dev); +} + +static int veml3328_runtime_suspend(struct device *dev) +{ + struct veml3328_data *data = iio_priv(dev_get_drvdata(dev)); + int ret; + + ret = veml3328_power_down(data); + if (ret) + dev_err(dev, "Failed to suspend: %d\n", ret); + + return ret; +} + +static int veml3328_runtime_resume(struct device *dev) +{ + struct veml3328_data *data = iio_priv(dev_get_drvdata(dev)); + int ret; + + ret = veml3328_power_up(data); + if (ret) + dev_err(dev, "Failed to resume: %d\n", ret); + + return ret; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(veml3328_pm_ops, + veml3328_runtime_suspend, + veml3328_runtime_resume, + NULL); + +static const struct of_device_id veml3328_of_match[] = { + { .compatible = "vishay,veml3328" }, + { } +}; +MODULE_DEVICE_TABLE(of, veml3328_of_match); + +static const struct i2c_device_id veml3328_id[] = { + { .name = "veml3328" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, veml3328_id); + +static struct i2c_driver veml3328_driver = { + .driver = { + .name = "veml3328", + .of_match_table = veml3328_of_match, + .pm = pm_ptr(&veml3328_pm_ops), + }, + .probe = veml3328_probe, + .id_table = veml3328_id, +}; +module_i2c_driver(veml3328_driver); + +MODULE_AUTHOR("Joshua Crofts "); +MODULE_DESCRIPTION("VEML3328 RGBCIR Light Sensor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index 6bcacae3863c..7c837d60dad8 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -521,13 +521,9 @@ static int veml6030_write_persistence(struct iio_dev *indio_dev, static int veml6030_set_scale(struct iio_dev *indio_dev, int val, int val2) { - int ret, gain_sel, it_idx, it_sel; + int ret, gain_sel, it_sel; struct veml6030_data *data = iio_priv(indio_dev); - ret = regmap_field_read(data->rf.it, &it_idx); - if (ret) - return ret; - ret = iio_gts_find_gain_time_sel_for_scale(&data->gts, val, val2, &gain_sel, &it_sel); if (ret) @@ -875,9 +871,11 @@ static irqreturn_t veml6030_event_handler(int irq, void *private) else evtdir = IIO_EV_DIR_FALLING; - iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, - 0, IIO_EV_TYPE_THRESH, evtdir), - iio_get_time_ns(indio_dev)); + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + 0, + IIO_EV_TYPE_THRESH, + evtdir), + iio_get_time_ns(indio_dev)); return IRQ_HANDLED; } @@ -1218,9 +1216,9 @@ static const struct of_device_id veml6030_of_match[] = { MODULE_DEVICE_TABLE(of, veml6030_of_match); static const struct i2c_device_id veml6030_id[] = { - { "veml6030", (kernel_ulong_t)&veml6030_chip}, - { "veml6035", (kernel_ulong_t)&veml6035_chip}, - { "veml7700", (kernel_ulong_t)&veml7700_chip}, + { .name = "veml6030", .driver_data = (kernel_ulong_t)&veml6030_chip }, + { .name = "veml6035", .driver_data = (kernel_ulong_t)&veml6035_chip }, + { .name = "veml7700", .driver_data = (kernel_ulong_t)&veml7700_chip }, { } }; MODULE_DEVICE_TABLE(i2c, veml6030_id); diff --git a/drivers/iio/light/veml6040.c b/drivers/iio/light/veml6040.c index f563f9f0ee67..0960784b8866 100644 --- a/drivers/iio/light/veml6040.c +++ b/drivers/iio/light/veml6040.c @@ -254,7 +254,7 @@ static int veml6040_probe(struct i2c_client *client) } static const struct i2c_device_id veml6040_id_table[] = { - {"veml6040"}, + { .name = "veml6040" }, { } }; MODULE_DEVICE_TABLE(i2c, veml6040_id_table); diff --git a/drivers/iio/light/veml6046x00.c b/drivers/iio/light/veml6046x00.c index e60f24d46e7b..f23d63291f73 100644 --- a/drivers/iio/light/veml6046x00.c +++ b/drivers/iio/light/veml6046x00.c @@ -1009,7 +1009,7 @@ static const struct of_device_id veml6046x00_of_match[] = { MODULE_DEVICE_TABLE(of, veml6046x00_of_match); static const struct i2c_device_id veml6046x00_id[] = { - { "veml6046x00" }, + { .name = "veml6046x00" }, { } }; MODULE_DEVICE_TABLE(i2c, veml6046x00_id); diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index 4bbd86d0cb46..c99336bd919f 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -290,7 +290,7 @@ static int veml6070_probe(struct i2c_client *client) } static const struct i2c_device_id veml6070_id[] = { - { "veml6070" }, + { .name = "veml6070" }, { } }; MODULE_DEVICE_TABLE(i2c, veml6070_id); diff --git a/drivers/iio/light/veml6075.c b/drivers/iio/light/veml6075.c index edbb43407054..59187244aba0 100644 --- a/drivers/iio/light/veml6075.c +++ b/drivers/iio/light/veml6075.c @@ -100,7 +100,7 @@ static const struct iio_chan_spec veml6075_channels[] = { static int veml6075_request_measurement(struct veml6075_data *data) { - int ret, conf, int_time; + int ret, conf, int_time, int_index; ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); if (ret < 0) @@ -117,7 +117,11 @@ static int veml6075_request_measurement(struct veml6075_data *data) * time for all possible configurations. Using a 1.50 factor simplifies * operations and ensures reliability under all circumstances. */ - int_time = veml6075_it_ms[FIELD_GET(VEML6075_CONF_IT, conf)]; + int_index = FIELD_GET(VEML6075_CONF_IT, conf); + if (int_index >= ARRAY_SIZE(veml6075_it_ms)) + return -EINVAL; + + int_time = veml6075_it_ms[int_index]; msleep(int_time + (int_time / 2)); /* shutdown again, data registers are still accessible */ @@ -451,7 +455,7 @@ static int veml6075_probe(struct i2c_client *client) } static const struct i2c_device_id veml6075_id[] = { - { "veml6075" }, + { .name = "veml6075" }, { } }; MODULE_DEVICE_TABLE(i2c, veml6075_id); diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c index c1314b144367..6cb965418dba 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -750,7 +750,7 @@ static const struct of_device_id vl6180_of_match[] = { MODULE_DEVICE_TABLE(of, vl6180_of_match); static const struct i2c_device_id vl6180_id[] = { - { "vl6180" }, + { .name = "vl6180" }, { } }; MODULE_DEVICE_TABLE(i2c, vl6180_id); diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index 0990e4d266eb..b53be5f7354e 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -516,7 +516,7 @@ static int zopt2201_probe(struct i2c_client *client) } static const struct i2c_device_id zopt2201_id[] = { - { "zopt2201" }, + { .name = "zopt2201" }, { } }; MODULE_DEVICE_TABLE(i2c, zopt2201_id); diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index fb313e591e85..ea2697fb5ab6 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -151,6 +151,17 @@ config MMC5633 To compile this driver as a module, choose M here: the module will be called mmc5633 +config MMC5983 + tristate "MEMSIC MMC5983 3-axis magnetic sensor" + depends on I2C + select REGMAP_I2C + help + Say yes here to build support for the MEMSIC MMC5983 3-axis + magnetic sensor. + + To compile this driver as a module, choose M here: the module + will be called mmc5983 + config IIO_ST_MAGN_3AXIS tristate "STMicroelectronics magnetometers 3-Axis Driver" depends on (I2C || SPI_MASTER) && SYSFS diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 5bd227f8c120..7fd9b3fd914e 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o obj-$(CONFIG_MMC35240) += mmc35240.o obj-$(CONFIG_MMC5633) += mmc5633.o +obj-$(CONFIG_MMC5983) += mmc5983.o obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o st_magn-y := st_magn_core.o diff --git a/drivers/iio/magnetometer/af8133j.c b/drivers/iio/magnetometer/af8133j.c index b1768c3aa8f3..352f53edad9a 100644 --- a/drivers/iio/magnetometer/af8133j.c +++ b/drivers/iio/magnetometer/af8133j.c @@ -504,7 +504,7 @@ static const struct of_device_id af8133j_of_match[] = { MODULE_DEVICE_TABLE(of, af8133j_of_match); static const struct i2c_device_id af8133j_id[] = { - { "af8133j" }, + { .name = "af8133j" }, { } }; MODULE_DEVICE_TABLE(i2c, af8133j_id); diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 817b18257608..18dc36945a97 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -1017,10 +1017,10 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ak8974_dev_pm_ops, ak8974_runtime_suspend, ak8974_runtime_resume, NULL); static const struct i2c_device_id ak8974_id[] = { - { "ami305" }, - { "ami306" }, - { "ak8974" }, - { "hscdtd008a" }, + { .name = "ami305" }, + { .name = "ami306" }, + { .name = "ak8974" }, + { .name = "hscdtd008a" }, { } }; MODULE_DEVICE_TABLE(i2c, ak8974_id); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index b648b0afa573..d045ea091205 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -7,24 +7,31 @@ * Copyright (c) 2010, NVIDIA Corporation. */ -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include + +#include -#include -#include #include -#include +#include #include #include @@ -127,13 +134,6 @@ #define AK09912_MAX_REGS AK09912_REG_ASAZ -/* - * Miscellaneous values. - */ -#define AK8975_MAX_CONVERSION_TIMEOUT 500 -#define AK8975_CONVERSION_DONE_POLL_TIME 10 -#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) - /* * Precalculate scale factor (in Gauss units) for each axis and * store in the device data. @@ -456,7 +456,8 @@ static int ak8975_power_on(const struct ak8975_data *data) * and the minimum wait time before mode setting is 100us, in * total 300us. Add some margin and say minimum 500us here. */ - usleep_range(500, 1000); + fsleep(500); + return 0; } @@ -473,9 +474,10 @@ static void ak8975_power_off(const struct ak8975_data *data) * Return 0 if the i2c device is the one we expect. * return a negative error number otherwise */ -static int ak8975_who_i_am(struct i2c_client *client, +static int ak8975_who_i_am(const struct ak8975_data *data, enum asahi_compass_chipset type) { + struct i2c_client *client = data->client; u8 wia_val[2]; int ret; @@ -489,12 +491,18 @@ static int ak8975_who_i_am(struct i2c_client *client, * AK8975 | DEVICE_ID | NA * AK8963 | DEVICE_ID | NA */ - ret = i2c_smbus_read_i2c_block_data_or_emulated( - client, AK09912_REG_WIA1, 2, wia_val); + ret = i2c_smbus_read_i2c_block_data_or_emulated(client, + AK09912_REG_WIA1, + sizeof(wia_val), + wia_val); if (ret < 0) { dev_err(&client->dev, "Error reading WIA\n"); return ret; } + if (ret != sizeof(wia_val)) { + dev_err(&client->dev, "Error reading WIA\n"); + return -EIO; + } if (wia_val[0] != AK8975_DEVICE_ID) return -ENODEV; @@ -541,12 +549,12 @@ static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode) data->def->ctrl_modes[mode]; ret = i2c_smbus_write_byte_data(data->client, data->def->ctrl_regs[CNTL], regval); - if (ret < 0) { + if (ret < 0) return ret; - } + data->cntl_cache = regval; /* After mode change wait at least 100us */ - usleep_range(100, 500); + fsleep(100); return 0; } @@ -570,8 +578,8 @@ static irqreturn_t ak8975_irq_handler(int irq, void *data) static int ak8975_setup_irq(struct ak8975_data *data) { struct i2c_client *client = data->client; - int rc; int irq; + int ret; init_waitqueue_head(&data->data_ready_queue); clear_bit(0, &data->flags); @@ -580,28 +588,24 @@ static int ak8975_setup_irq(struct ak8975_data *data) else irq = gpiod_to_irq(data->eoc_gpiod); - rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler, - IRQF_TRIGGER_RISING, - dev_name(&client->dev), data); - if (rc < 0) { - dev_err(&client->dev, "irq %d request failed: %d\n", irq, rc); - return rc; - } + ret = devm_request_irq(&client->dev, irq, ak8975_irq_handler, + IRQF_TRIGGER_RISING, + dev_name(&client->dev), data); + if (ret) + return ret; data->eoc_irq = irq; - return rc; + return 0; } - /* * Perform some start-of-day setup, including reading the asa calibration * values and caching them. */ -static int ak8975_setup(struct i2c_client *client) +static int ak8975_setup(struct ak8975_data *data) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak8975_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; int ret; /* Write the fused rom access mode. */ @@ -612,13 +616,18 @@ static int ak8975_setup(struct i2c_client *client) } /* Get asa data and store in the device data. */ - ret = i2c_smbus_read_i2c_block_data_or_emulated( - client, data->def->ctrl_regs[ASA_BASE], - 3, data->asa); + ret = i2c_smbus_read_i2c_block_data_or_emulated(client, + data->def->ctrl_regs[ASA_BASE], + sizeof(data->asa), + data->asa); if (ret < 0) { dev_err(&client->dev, "Not able to read asa data\n"); return ret; } + if (ret != sizeof(data->asa)) { + dev_err(&client->dev, "Error reading asa data\n"); + return -EIO; + } /* After reading fuse ROM data set power-down mode */ ret = ak8975_set_mode(data, POWER_DOWN); @@ -643,22 +652,23 @@ static int ak8975_setup(struct i2c_client *client) return 0; } -static int wait_conversion_complete_gpio(struct ak8975_data *data) +static int wait_conversion_complete_gpio(struct ak8975_data *data, + unsigned int poll_ms, + unsigned int timeout_ms) { struct i2c_client *client = data->client; - u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT; int ret; + int val; /* Wait for the conversion to complete. */ - while (timeout_ms) { - msleep(AK8975_CONVERSION_DONE_POLL_TIME); - if (gpiod_get_value(data->eoc_gpiod)) - break; - timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; - } - if (!timeout_ms) { - dev_err(&client->dev, "Conversion timeout happened\n"); - return -EINVAL; + ret = readx_poll_timeout(gpiod_get_value, data->eoc_gpiod, val, val != 0, + poll_ms * USEC_PER_MSEC, + timeout_ms * USEC_PER_MSEC); + if (ret) + return ret; + if (val < 0) { + dev_err(&client->dev, "Error in reading GPIOD\n"); + return val; } ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST1]); @@ -668,54 +678,49 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data) return ret; } -static int wait_conversion_complete_polled(struct ak8975_data *data) +static int wait_conversion_complete_polled(struct ak8975_data *data, + unsigned int poll_ms, + unsigned int timeout_ms) { struct i2c_client *client = data->client; - u8 read_status; - u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT; int ret; + int val; /* Wait for the conversion to complete. */ - while (timeout_ms) { - msleep(AK8975_CONVERSION_DONE_POLL_TIME); - ret = i2c_smbus_read_byte_data(client, - data->def->ctrl_regs[ST1]); - if (ret < 0) { - dev_err(&client->dev, "Error in reading ST1\n"); - return ret; - } - read_status = ret; - if (read_status) - break; - timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; - } - if (!timeout_ms) { - dev_err(&client->dev, "Conversion timeout happened\n"); - return -EINVAL; - } + ret = read_poll_timeout(i2c_smbus_read_byte_data, val, val != 0, + poll_ms * USEC_PER_MSEC, + timeout_ms * USEC_PER_MSEC, + true, + client, data->def->ctrl_regs[ST1]); + if (ret) + return ret; + if (val < 0) + dev_err(&client->dev, "Error in reading ST1\n"); - return read_status; + return val; } -/* Returns 0 if the end of conversion interrupt occurred or -ETIME otherwise */ -static int wait_conversion_complete_interrupt(struct ak8975_data *data) +/* Returns 0 if the end of conversion interrupt occurred or -ETIMEDOUT otherwise */ +static int wait_conversion_complete_interrupt(struct ak8975_data *data, + unsigned int timeout_ms) { int ret; ret = wait_event_timeout(data->data_ready_queue, test_bit(0, &data->flags), - AK8975_DATA_READY_TIMEOUT); + msecs_to_jiffies(timeout_ms)); clear_bit(0, &data->flags); - return ret > 0 ? 0 : -ETIME; + return ret > 0 ? 0 : -ETIMEDOUT; } -static int ak8975_start_read_axis(struct ak8975_data *data, - const struct i2c_client *client) +static int ak8975_start_read_axis(struct ak8975_data *data) { - /* Set up the device for taking a sample. */ - int ret = ak8975_set_mode(data, MODE_ONCE); + struct i2c_client *client = data->client; + int ret; + /* Set up the device for taking a sample. */ + ret = ak8975_set_mode(data, MODE_ONCE); if (ret < 0) { dev_err(&client->dev, "Error in setting operating mode\n"); return ret; @@ -723,11 +728,11 @@ static int ak8975_start_read_axis(struct ak8975_data *data, /* Wait for the conversion to complete. */ if (data->eoc_irq) - ret = wait_conversion_complete_interrupt(data); + ret = wait_conversion_complete_interrupt(data, 100); else if (data->eoc_gpiod) - ret = wait_conversion_complete_gpio(data); + ret = wait_conversion_complete_gpio(data, 10, 500); else - ret = wait_conversion_complete_polled(data); + ret = wait_conversion_complete_polled(data, 10, 500); if (ret < 0) return ret; @@ -742,22 +747,26 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) const struct i2c_client *client = data->client; const struct ak_def *def = data->def; __le16 rval; - u16 buff; int ret; pm_runtime_get_sync(&data->client->dev); mutex_lock(&data->lock); - ret = ak8975_start_read_axis(data, client); + ret = ak8975_start_read_axis(data); if (ret) goto exit; - ret = i2c_smbus_read_i2c_block_data_or_emulated( - client, def->data_regs[index], - sizeof(rval), (u8*)&rval); + ret = i2c_smbus_read_i2c_block_data_or_emulated(client, + def->data_regs[index], + sizeof(rval), + (u8 *)&rval); if (ret < 0) goto exit; + if (ret != sizeof(rval)) { + ret = -EIO; + goto exit; + } /* Read out ST2 for release lock on measurement data. */ ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST2]); @@ -778,12 +787,13 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) pm_runtime_put_autosuspend(&data->client->dev); /* Swap bytes and convert to valid range. */ - buff = le16_to_cpu(rval); - *val = clamp_t(s16, buff, -def->range, def->range); + *val = clamp_t(s16, le16_to_cpu(rval), -def->range, def->range); + return IIO_VAL_INT; exit: mutex_unlock(&data->lock); + pm_runtime_put_autosuspend(&data->client->dev); dev_err(&client->dev, "Error in reading axis\n"); return ret; } @@ -859,7 +869,7 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev) mutex_lock(&data->lock); - ret = ak8975_start_read_axis(data, client); + ret = ak8975_start_read_axis(data); if (ret) goto unlock; @@ -869,10 +879,12 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev) */ ret = i2c_smbus_read_i2c_block_data_or_emulated(client, def->data_regs[0], - 3 * sizeof(fval[0]), + sizeof(fval), (u8 *)fval); if (ret < 0) goto unlock; + if (ret != sizeof(fval)) + goto unlock; mutex_unlock(&data->lock); @@ -901,6 +913,28 @@ static irqreturn_t ak8975_handle_trigger(int irq, void *p) return IRQ_HANDLED; } +static int ak8975_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ak8975_data *data = iio_priv(indio_dev); + struct device *dev = &data->client->dev; + + return pm_runtime_resume_and_get(dev); +} + +static int ak8975_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ak8975_data *data = iio_priv(indio_dev); + struct device *dev = &data->client->dev; + + pm_runtime_put_autosuspend(dev); + + return 0; +} + +static const struct iio_buffer_setup_ops ak8975_buffer_setup_ops = { + .preenable = ak8975_buffer_preenable, + .postdisable = ak8975_buffer_postdisable, +}; static int ak8975_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); @@ -908,8 +942,8 @@ static int ak8975_probe(struct i2c_client *client) struct iio_dev *indio_dev; struct gpio_desc *eoc_gpiod; struct gpio_desc *reset_gpiod; - int err; const char *name = NULL; + int ret; /* * Grab and set up the supplied GPIO. @@ -919,8 +953,7 @@ static int ak8975_probe(struct i2c_client *client) eoc_gpiod = devm_gpiod_get_optional(&client->dev, NULL, GPIOD_IN); if (IS_ERR(eoc_gpiod)) return PTR_ERR(eoc_gpiod); - if (eoc_gpiod) - gpiod_set_consumer_name(eoc_gpiod, "ak_8975"); + gpiod_set_consumer_name(eoc_gpiod, "ak_8975"); /* * According to AK09911 datasheet, if reset GPIO is provided then @@ -945,9 +978,9 @@ static int ak8975_probe(struct i2c_client *client) data->reset_gpiod = reset_gpiod; data->eoc_irq = 0; - err = iio_read_mount_matrix(&client->dev, &data->orientation); - if (err) - return err; + ret = iio_read_mount_matrix(&client->dev, &data->orientation); + if (ret) + return ret; /* id will be NULL when enumerated via ACPI */ data->def = i2c_get_match_data(client); @@ -968,20 +1001,20 @@ static int ak8975_probe(struct i2c_client *client) if (IS_ERR(data->vid)) return PTR_ERR(data->vid); - err = ak8975_power_on(data); - if (err) - return err; + ret = ak8975_power_on(data); + if (ret) + return ret; - err = ak8975_who_i_am(client, data->def->type); - if (err < 0) { + ret = ak8975_who_i_am(data, data->def->type); + if (ret) { dev_err(&client->dev, "Unexpected device\n"); goto power_off; } dev_dbg(&client->dev, "Asahi compass chip %s\n", name); /* Perform some basic start-of-day setup of the device. */ - err = ak8975_setup(client); - if (err < 0) { + ret = ak8975_setup(data); + if (ret) { dev_err(&client->dev, "%s initialization fails\n", name); goto power_off; } @@ -994,15 +1027,15 @@ static int ak8975_probe(struct i2c_client *client) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = name; - err = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger, - NULL); - if (err) { + ret = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger, + &ak8975_buffer_setup_ops); + if (ret) { dev_err(&client->dev, "triggered buffer setup failed\n"); goto power_off; } - err = iio_device_register(indio_dev); - if (err) { + ret = iio_device_register(indio_dev); + if (ret) { dev_err(&client->dev, "device register failed\n"); goto cleanup_buffer; } @@ -1025,7 +1058,7 @@ static int ak8975_probe(struct i2c_client *client) iio_triggered_buffer_cleanup(indio_dev); power_off: ak8975_power_off(data); - return err; + return ret; } static void ak8975_remove(struct i2c_client *client) @@ -1099,13 +1132,13 @@ static const struct acpi_device_id ak_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, ak_acpi_match); static const struct i2c_device_id ak8975_id[] = { - {"AK8963", (kernel_ulong_t)&ak_def_array[AK8963] }, - {"ak8963", (kernel_ulong_t)&ak_def_array[AK8963] }, - {"ak8975", (kernel_ulong_t)&ak_def_array[AK8975] }, - {"ak09911", (kernel_ulong_t)&ak_def_array[AK09911] }, - {"ak09912", (kernel_ulong_t)&ak_def_array[AK09912] }, - {"ak09916", (kernel_ulong_t)&ak_def_array[AK09916] }, - {"ak09918", (kernel_ulong_t)&ak_def_array[AK09918] }, + { .name = "AK8963", .driver_data = (kernel_ulong_t)&ak_def_array[AK8963] }, + { .name = "ak8963", .driver_data = (kernel_ulong_t)&ak_def_array[AK8963] }, + { .name = "ak8975", .driver_data = (kernel_ulong_t)&ak_def_array[AK8975] }, + { .name = "ak09911", .driver_data = (kernel_ulong_t)&ak_def_array[AK09911] }, + { .name = "ak09912", .driver_data = (kernel_ulong_t)&ak_def_array[AK09912] }, + { .name = "ak09916", .driver_data = (kernel_ulong_t)&ak_def_array[AK09916] }, + { .name = "ak09918", .driver_data = (kernel_ulong_t)&ak_def_array[AK09918] }, { } }; MODULE_DEVICE_TABLE(i2c, ak8975_id); diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c index b110791f688a..7d3cca8cedbe 100644 --- a/drivers/iio/magnetometer/bmc150_magn_i2c.c +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c @@ -39,9 +39,9 @@ static void bmc150_magn_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id bmc150_magn_i2c_id[] = { - { "bmc150_magn" }, - { "bmc156_magn" }, - { "bmm150_magn" }, + { .name = "bmc150_magn" }, + { .name = "bmc156_magn" }, + { .name = "bmm150_magn" }, { } }; MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index c673f9323e47..23884825eb00 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -3,6 +3,7 @@ * HID Sensors Driver * Copyright (c) 2012, Intel Corporation. */ +#include #include #include #include @@ -132,17 +133,6 @@ static const struct iio_chan_spec magn_3d_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(7) }; -/* Adjust channel real bits based on report descriptor */ -static void magn_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - /* Channel read_raw handler */ static int magn_3d_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -280,7 +270,7 @@ static const struct iio_info magn_3d_info = { /* Callback handler to send event after all samples are received and captured */ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, + u32 usage_id, void *priv) { struct iio_dev *indio_dev = platform_get_drvdata(priv); @@ -302,7 +292,7 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, /* Capture samples in local storage */ static int magn_3d_capture_sample(struct hid_sensor_hub_device *hsdev, - unsigned usage_id, + u32 usage_id, size_t raw_len, char *raw_data, void *priv) { @@ -350,7 +340,7 @@ static int magn_3d_parse_report(struct platform_device *pdev, struct hid_sensor_hub_device *hsdev, struct iio_chan_spec **channels, int *chan_count, - unsigned usage_id, + u32 usage_id, struct magn_3d_state *st) { int i; @@ -418,9 +408,11 @@ static int magn_3d_parse_report(struct platform_device *pdev, if (i != CHANNEL_SCAN_INDEX_TIMESTAMP) { /* Set magn_val_addr to iio value address */ st->magn_val_addr[i] = &st->iio_vals[*chan_count]; - magn_3d_adjust_channel_bit_mask(_channels, - *chan_count, - st->magn[i].size); + _channels[*chan_count].scan_type = (struct iio_scan_type) { + .format = 's', + .realbits = BYTES_TO_BITS(st->magn[i].size), + .storagebits = BITS_PER_TYPE(u32), + }; } (*chan_count)++; } diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c index b41709959e2b..4c454b0057b1 100644 --- a/drivers/iio/magnetometer/hmc5843_i2c.c +++ b/drivers/iio/magnetometer/hmc5843_i2c.c @@ -71,10 +71,10 @@ static void hmc5843_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id hmc5843_id[] = { - { "hmc5843", HMC5843_ID }, - { "hmc5883", HMC5883_ID }, - { "hmc5883l", HMC5883L_ID }, - { "hmc5983", HMC5983_ID }, + { .name = "hmc5843", .driver_data = HMC5843_ID }, + { .name = "hmc5883", .driver_data = HMC5883_ID }, + { .name = "hmc5883l", .driver_data = HMC5883L_ID }, + { .name = "hmc5983", .driver_data = HMC5983_ID }, { } }; MODULE_DEVICE_TABLE(i2c, hmc5843_id); diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index ff09250a06e7..479a12ece8f6 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -619,7 +619,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume); static const struct i2c_device_id mag3110_id[] = { - { "mag3110" }, + { .name = "mag3110" }, { } }; MODULE_DEVICE_TABLE(i2c, mag3110_id); diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index f3d48d03f7c3..bad36c8dd598 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -560,7 +560,7 @@ static const struct acpi_device_id mmc35240_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); static const struct i2c_device_id mmc35240_id[] = { - { "mmc35240" }, + { .name = "mmc35240" }, { } }; MODULE_DEVICE_TABLE(i2c, mmc35240_id); diff --git a/drivers/iio/magnetometer/mmc5633.c b/drivers/iio/magnetometer/mmc5633.c index 9d8e27486963..f82cb68f9c57 100644 --- a/drivers/iio/magnetometer/mmc5633.c +++ b/drivers/iio/magnetometer/mmc5633.c @@ -532,8 +532,8 @@ static const struct of_device_id mmc5633_of_match[] = { MODULE_DEVICE_TABLE(of, mmc5633_of_match); static const struct i2c_device_id mmc5633_i2c_id[] = { - { "mmc5603" }, - { "mmc5633" }, + { .name = "mmc5603" }, + { .name = "mmc5633" }, { } }; MODULE_DEVICE_TABLE(i2c, mmc5633_i2c_id); diff --git a/drivers/iio/magnetometer/mmc5983.c b/drivers/iio/magnetometer/mmc5983.c new file mode 100644 index 000000000000..a67b13393b6b --- /dev/null +++ b/drivers/iio/magnetometer/mmc5983.c @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MMC5983 - MEMSIC 3-axis Magnetic Sensor + * + * Copyright (c) 2026, Vlad Kulikov + * + * IIO driver for MMC5983 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MMC5983_REG_XOUT0 0x00 +#define MMC5983_REG_XOUT1 0x01 +#define MMC5983_REG_YOUT0 0x02 +#define MMC5983_REG_YOUT1 0x03 +#define MMC5983_REG_ZOUT0 0x04 +#define MMC5983_REG_ZOUT1 0x05 +#define MMC5983_REG_XYZOUT2 0x06 + +#define MMC5983_REG_STATUS 0x08 + +#define MMC5983_REG_CTRL0 0x09 +#define MMC5983_REG_CTRL1 0x0A +#define MMC5983_REG_CTRL2 0x0B +#define MMC5983_REG_CTRL3 0x0C + +#define MMC5983_REG_ID 0x2F + +#define MMC5983_PRODUCT_ID 0x30 + +#define MMC5983_STATUS_MEAS_M_DONE_BIT BIT(0) +#define MMC5983_STATUS_OTP_RD_DONE_BIT BIT(4) + +#define MMC5983_CTRL0_TM_M_BIT BIT(0) +#define MMC5983_CTRL0_SET_BIT BIT(3) +#define MMC5983_CTRL0_RESET_BIT BIT(4) +#define MMC5983_CTRL0_OTP_RD_BIT BIT(6) + +#define MMC5983_CTRL1_SW_RST_BIT BIT(7) + +enum mmc5983_axis { + MMC5983_AXIS_X, + MMC5983_AXIS_Y, + MMC5983_AXIS_Z, +}; + +struct mmc5983_data { + struct regmap *regmap; + /* Protects chip access during SET/RESET measurement sequence */ + struct mutex mutex; +}; + +#define MMC5983_CHANNEL(_axis) { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + .address = MMC5983_AXIS_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec mmc5983_channels[] = { + MMC5983_CHANNEL(X), + MMC5983_CHANNEL(Y), + MMC5983_CHANNEL(Z), +}; + +static int mmc5983_pulse_coil(struct mmc5983_data *data, unsigned int coil_bit) +{ + int ret; + + ret = regmap_write(data->regmap, MMC5983_REG_CTRL0, coil_bit); + if (ret) + return ret; + + /* + * Datasheet page 15: SET/RESET coil pulse is 500 ns. + * Vendor sample code waits 500 us before the next operation. + */ + fsleep(500); + + return 0; +} + +static int mmc5983_take_measurement(struct mmc5983_data *data, int m[3]) +{ + unsigned int status; + u8 buf[7]; + int ret; + + ret = regmap_write(data->regmap, MMC5983_REG_CTRL0, + MMC5983_CTRL0_TM_M_BIT); + if (ret) + return ret; + + /* + * Datasheet page 15: measurement time is 8 ms at BW=00 (default, + * slowest setting). Use a 50 ms timeout for margin. + */ + ret = regmap_read_poll_timeout(data->regmap, MMC5983_REG_STATUS, + status, + status & MMC5983_STATUS_MEAS_M_DONE_BIT, + 10 * USEC_PER_MSEC, + 50 * USEC_PER_MSEC); + if (ret) + return ret; + + ret = regmap_bulk_read(data->regmap, MMC5983_REG_XOUT0, buf, + sizeof(buf)); + if (ret) + return ret; + + m[0] = (buf[0] << 10) | (buf[1] << 2) | ((buf[6] >> 6) & 0x3); + m[1] = (buf[2] << 10) | (buf[3] << 2) | ((buf[6] >> 4) & 0x3); + m[2] = (buf[4] << 10) | (buf[5] << 2) | ((buf[6] >> 2) & 0x3); + + return 0; +} + +static int mmc5983_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, + int *val2, long mask) +{ + struct mmc5983_data *data = iio_priv(indio_dev); + int m1[3], m2[3]; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: { + guard(mutex)(&data->mutex); + + /* SET: magnetize sensor elements in forward direction */ + ret = mmc5983_pulse_coil(data, MMC5983_CTRL0_SET_BIT); + if (ret) + return ret; + + ret = mmc5983_take_measurement(data, m1); + if (ret) + return ret; + + /* RESET: magnetize sensor elements in reverse direction */ + ret = mmc5983_pulse_coil(data, MMC5983_CTRL0_RESET_BIT); + if (ret) + return ret; + + ret = mmc5983_take_measurement(data, m2); + if (ret) + return ret; + + *val = (m1[chan->address] - m2[chan->address]) / 2; + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 61035; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info mmc5983_info = { + .read_raw = mmc5983_read_raw, +}; + +static bool mmc5983_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MMC5983_REG_CTRL0: + case MMC5983_REG_CTRL1: + case MMC5983_REG_CTRL2: + case MMC5983_REG_CTRL3: + return true; + default: + return false; + } +} + +static bool mmc5983_is_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MMC5983_REG_XOUT0: + case MMC5983_REG_XOUT1: + case MMC5983_REG_YOUT0: + case MMC5983_REG_YOUT1: + case MMC5983_REG_ZOUT0: + case MMC5983_REG_ZOUT1: + case MMC5983_REG_XYZOUT2: + case MMC5983_REG_STATUS: + case MMC5983_REG_CTRL0: + case MMC5983_REG_CTRL1: + case MMC5983_REG_CTRL2: + case MMC5983_REG_CTRL3: + case MMC5983_REG_ID: + return true; + default: + return false; + } +} + +static bool mmc5983_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MMC5983_REG_XOUT0: + case MMC5983_REG_XOUT1: + case MMC5983_REG_YOUT0: + case MMC5983_REG_YOUT1: + case MMC5983_REG_ZOUT0: + case MMC5983_REG_ZOUT1: + case MMC5983_REG_XYZOUT2: + case MMC5983_REG_STATUS: + case MMC5983_REG_CTRL0: + case MMC5983_REG_CTRL1: + return true; + default: + return false; + } +} + +static const struct regmap_config mmc5983_regmap_config = { + .name = "mmc5983_regmap", + .reg_bits = 8, + .val_bits = 8, + .max_register = MMC5983_REG_ID, + .writeable_reg = mmc5983_is_writeable_reg, + .readable_reg = mmc5983_is_readable_reg, + .volatile_reg = mmc5983_is_volatile_reg, +}; + +static int mmc5983_init(struct mmc5983_data *data) +{ + struct regmap *regmap = data->regmap; + struct device *dev = regmap_get_device(regmap); + unsigned int reg_id, status; + int ret; + + ret = regmap_read(regmap, MMC5983_REG_ID, ®_id); + if (ret) + return dev_err_probe(dev, ret, "Error reading product id\n"); + + if (reg_id != MMC5983_PRODUCT_ID) + dev_info(dev, "unexpected product id 0x%02x\n", reg_id); + + ret = regmap_write(regmap, MMC5983_REG_CTRL1, MMC5983_CTRL1_SW_RST_BIT); + if (ret) + return ret; + + /* Datasheet page 15: power-on time after SW_RST is 10 ms */ + fsleep(10 * USEC_PER_MSEC); + + ret = regmap_write(regmap, MMC5983_REG_CTRL0, MMC5983_CTRL0_OTP_RD_BIT); + if (ret) + return ret; + + /* + * Datasheet page 15: OTP read completes and self-clears. No separate + * OTP refresh timeout is specified, so use the 10 ms power-on time as + * a conservative upper bound. + */ + ret = regmap_read_poll_timeout(regmap, MMC5983_REG_STATUS, status, + status & MMC5983_STATUS_OTP_RD_DONE_BIT, + USEC_PER_MSEC, + 10 * USEC_PER_MSEC); + if (ret) + return ret; + + /* SET: magnetize sensor elements in forward direction */ + ret = mmc5983_pulse_coil(data, MMC5983_CTRL0_SET_BIT); + if (ret) + return ret; + + /* RESET: magnetize sensor elements in reverse direction */ + return mmc5983_pulse_coil(data, MMC5983_CTRL0_RESET_BIT); +} + +static int mmc5983_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct mmc5983_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + + ret = devm_mutex_init(dev, &data->mutex); + if (ret) + return ret; + + data->regmap = devm_regmap_init_i2c(i2c, &mmc5983_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), + "failed to allocate register map\n"); + + indio_dev->info = &mmc5983_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = "mmc5983"; + indio_dev->channels = mmc5983_channels; + indio_dev->num_channels = ARRAY_SIZE(mmc5983_channels); + + ret = mmc5983_init(data); + if (ret) + return dev_err_probe(dev, ret, "mmc5983 chip init failed\n"); + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id mmc5983_of_match[] = { + { .compatible = "memsic,mmc5983" }, + { } +}; +MODULE_DEVICE_TABLE(of, mmc5983_of_match); + +static const struct i2c_device_id mmc5983_id[] = { + { "mmc5983" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mmc5983_id); + +static struct i2c_driver mmc5983_driver = { + .driver = { + .name = "mmc5983", + .of_match_table = mmc5983_of_match, + }, + .probe = mmc5983_probe, + .id_table = mmc5983_id, +}; +module_i2c_driver(mmc5983_driver); + +MODULE_AUTHOR("Vladislav Kulikov "); +MODULE_DESCRIPTION("MEMSIC MMC5983 magnetic sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c index 2b2884425746..ac3f9f7fc808 100644 --- a/drivers/iio/magnetometer/rm3100-core.c +++ b/drivers/iio/magnetometer/rm3100-core.c @@ -204,27 +204,23 @@ static int rm3100_read_mag(struct rm3100_data *data, int idx, int *val) u8 buffer[3]; int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + ret = regmap_write(regmap, RM3100_REG_POLL, BIT(4 + idx)); if (ret < 0) - goto unlock_return; + return ret; ret = rm3100_wait_measurement(data); if (ret < 0) - goto unlock_return; + return ret; ret = regmap_bulk_read(regmap, RM3100_REG_MX2 + 3 * idx, buffer, 3); if (ret < 0) - goto unlock_return; - mutex_unlock(&data->lock); + return ret; *val = sign_extend32(get_unaligned_be24(&buffer[0]), 23); return IIO_VAL_INT; - -unlock_return: - mutex_unlock(&data->lock); - return ret; } #define RM3100_CHANNEL(axis, idx) \ @@ -284,11 +280,12 @@ static int rm3100_get_samp_freq(struct rm3100_data *data, int *val, int *val2) unsigned int tmp; int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + ret = regmap_read(data->regmap, RM3100_REG_TMRC, &tmp); - mutex_unlock(&data->lock); if (ret < 0) return ret; + *val = rm3100_samp_rates[tmp - RM3100_TMRC_OFFSET][0]; *val2 = rm3100_samp_rates[tmp - RM3100_TMRC_OFFSET][1]; @@ -338,56 +335,50 @@ static int rm3100_set_samp_freq(struct iio_dev *indio_dev, int val, int val2) int ret; int i; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + /* All cycle count registers use the same value. */ ret = regmap_read(regmap, RM3100_REG_CC_X, &cycle_count); if (ret < 0) - goto unlock_return; + return ret; for (i = 0; i < RM3100_SAMP_NUM; i++) { if (val == rm3100_samp_rates[i][0] && val2 == rm3100_samp_rates[i][1]) break; } - if (i == RM3100_SAMP_NUM) { - ret = -EINVAL; - goto unlock_return; - } + if (i == RM3100_SAMP_NUM) + return -EINVAL; ret = regmap_write(regmap, RM3100_REG_TMRC, i + RM3100_TMRC_OFFSET); if (ret < 0) - goto unlock_return; + return ret; /* Checking if cycle count registers need changing. */ if (val == 600 && cycle_count == 200) { ret = rm3100_set_cycle_count(data, 100); if (ret < 0) - goto unlock_return; + return ret; } else if (val != 600 && cycle_count == 100) { ret = rm3100_set_cycle_count(data, 200); if (ret < 0) - goto unlock_return; + return ret; } if (iio_buffer_enabled(indio_dev)) { /* Writing TMRC registers requires CMM reset. */ ret = regmap_write(regmap, RM3100_REG_CMM, 0); if (ret < 0) - goto unlock_return; + return ret; ret = regmap_write(data->regmap, RM3100_REG_CMM, (*indio_dev->active_scan_mask & 0x7) << RM3100_CMM_AXIS_SHIFT | RM3100_CMM_START); if (ret < 0) - goto unlock_return; + return ret; } - mutex_unlock(&data->lock); data->conversion_time = rm3100_samp_rates[i][2] * 2; return 0; - -unlock_return: - mutex_unlock(&data->lock); - return ret; } static int rm3100_read_raw(struct iio_dev *indio_dev, @@ -458,6 +449,27 @@ static const struct iio_buffer_setup_ops rm3100_buffer_ops = { .postdisable = rm3100_buffer_postdisable, }; +/** + * rm3100_regmap_bulk_read_locked() - Wrapper around regmap_bulk_read() with a mutex + * + * @data: Data structure containing regmap and mutex + * @reg: First register to be read from, passed to regmap_bulk_read() + * @val: Pointer to store read value, in native register size for device, + * passed to regmap_bulk_read() + * @val_count: Number of registers to read, passed to regmap_bulk_read() + * + * Intended for use only in rm3100_trigger_handler(). + * + * Return: + * A value of zero on success, a negative errno in error cases. + */ +static int rm3100_regmap_bulk_read_locked(struct rm3100_data *data, unsigned int reg, + void *val, size_t val_count) +{ + guard(mutex)(&data->lock); + return regmap_bulk_read(data->regmap, reg, val, val_count); +} + static irqreturn_t rm3100_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -465,14 +477,12 @@ static irqreturn_t rm3100_trigger_handler(int irq, void *p) unsigned long scan_mask = *indio_dev->active_scan_mask; unsigned int mask_len = iio_get_masklength(indio_dev); struct rm3100_data *data = iio_priv(indio_dev); - struct regmap *regmap = data->regmap; int ret, i, bit; - mutex_lock(&data->lock); switch (scan_mask) { case BIT(0) | BIT(1) | BIT(2): - ret = regmap_bulk_read(regmap, RM3100_REG_MX2, data->buffer, 9); - mutex_unlock(&data->lock); + ret = rm3100_regmap_bulk_read_locked(data, RM3100_REG_MX2, + data->buffer, 9); if (ret < 0) goto done; /* Convert XXXYYYZZZxxx to XXXxYYYxZZZx. x for paddings. */ @@ -480,36 +490,34 @@ static irqreturn_t rm3100_trigger_handler(int irq, void *p) memmove(data->buffer + i * 4, data->buffer + i * 3, 3); break; case BIT(0) | BIT(1): - ret = regmap_bulk_read(regmap, RM3100_REG_MX2, data->buffer, 6); - mutex_unlock(&data->lock); + ret = rm3100_regmap_bulk_read_locked(data, RM3100_REG_MX2, + data->buffer, 6); if (ret < 0) goto done; memmove(data->buffer + 4, data->buffer + 3, 3); break; case BIT(1) | BIT(2): - ret = regmap_bulk_read(regmap, RM3100_REG_MY2, data->buffer, 6); - mutex_unlock(&data->lock); + ret = rm3100_regmap_bulk_read_locked(data, RM3100_REG_MY2, + data->buffer, 6); if (ret < 0) goto done; memmove(data->buffer + 4, data->buffer + 3, 3); break; case BIT(0) | BIT(2): - ret = regmap_bulk_read(regmap, RM3100_REG_MX2, data->buffer, 9); - mutex_unlock(&data->lock); + ret = rm3100_regmap_bulk_read_locked(data, RM3100_REG_MX2, + data->buffer, 9); if (ret < 0) goto done; memmove(data->buffer + 4, data->buffer + 6, 3); break; default: for_each_set_bit(bit, &scan_mask, mask_len) { - ret = regmap_bulk_read(regmap, RM3100_REG_MX2 + 3 * bit, - data->buffer, 3); - if (ret < 0) { - mutex_unlock(&data->lock); + ret = rm3100_regmap_bulk_read_locked(data, + RM3100_REG_MX2 + 3 * bit, + data->buffer, 3); + if (ret < 0) goto done; - } } - mutex_unlock(&data->lock); } /* * Always using the same buffer so that we wouldn't need to set the diff --git a/drivers/iio/magnetometer/si7210.c b/drivers/iio/magnetometer/si7210.c index 2a36abd1c99d..5b3fc3030703 100644 --- a/drivers/iio/magnetometer/si7210.c +++ b/drivers/iio/magnetometer/si7210.c @@ -413,7 +413,7 @@ static int si7210_probe(struct i2c_client *client) } static const struct i2c_device_id si7210_id[] = { - { "si7210" }, + { .name = "si7210" }, { } }; MODULE_DEVICE_TABLE(i2c, si7210_id); diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index ed70e782af5e..26d1edd1e779 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -93,15 +93,15 @@ static int st_magn_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id st_magn_id_table[] = { - { LSM303DLH_MAGN_DEV_NAME }, - { LSM303DLHC_MAGN_DEV_NAME }, - { LSM303DLM_MAGN_DEV_NAME }, - { LIS3MDL_MAGN_DEV_NAME }, - { LSM303AGR_MAGN_DEV_NAME }, - { LIS2MDL_MAGN_DEV_NAME }, - { LSM9DS1_MAGN_DEV_NAME }, - { IIS2MDC_MAGN_DEV_NAME }, - { LSM303C_MAGN_DEV_NAME }, + { .name = LSM303DLH_MAGN_DEV_NAME }, + { .name = LSM303DLHC_MAGN_DEV_NAME }, + { .name = LSM303DLM_MAGN_DEV_NAME }, + { .name = LIS3MDL_MAGN_DEV_NAME }, + { .name = LSM303AGR_MAGN_DEV_NAME }, + { .name = LIS2MDL_MAGN_DEV_NAME }, + { .name = LSM9DS1_MAGN_DEV_NAME }, + { .name = IIS2MDC_MAGN_DEV_NAME }, + { .name = LSM303C_MAGN_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, st_magn_id_table); diff --git a/drivers/iio/magnetometer/tlv493d.c b/drivers/iio/magnetometer/tlv493d.c index e5e050af2b74..c8eb136cea6f 100644 --- a/drivers/iio/magnetometer/tlv493d.c +++ b/drivers/iio/magnetometer/tlv493d.c @@ -499,7 +499,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(tlv493d_pm_ops, tlv493d_runtime_suspend, tlv493d_runtime_resume, NULL); static const struct i2c_device_id tlv493d_id[] = { - { "tlv493d" }, + { .name = "tlv493d" }, { } }; MODULE_DEVICE_TABLE(i2c, tlv493d_id); diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c index 2adc3c036ab4..155294b66924 100644 --- a/drivers/iio/magnetometer/tmag5273.c +++ b/drivers/iio/magnetometer/tmag5273.c @@ -708,7 +708,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(tmag5273_pm_ops, NULL); static const struct i2c_device_id tmag5273_id[] = { - { "tmag5273" }, + { .name = "tmag5273" }, { } }; MODULE_DEVICE_TABLE(i2c, tmag5273_id); diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index c8a04f185dbb..a89e9672530c 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -168,6 +168,7 @@ struct yas5xx; /** * struct yas5xx_chip_info - device-specific data and function pointers * @devid: device ID number + * @product_label: product label used in Linux * @product_name: product name of the YAS variant * @version_names: version letters or namings * @volatile_reg: device-specific volatile registers @@ -189,6 +190,7 @@ struct yas5xx; */ struct yas5xx_chip_info { unsigned int devid; + const char *product_label; const char *product_name; const char *version_names[2]; const int *volatile_reg; @@ -1315,7 +1317,7 @@ static int yas537_power_on(struct yas5xx *yas5xx) return ret; /* Wait until the coil has ramped up */ - usleep_range(YAS537_MAG_RCOIL_TIME_US, YAS537_MAG_RCOIL_TIME_US + 100); + fsleep(YAS537_MAG_RCOIL_TIME_US); return 0; } @@ -1323,6 +1325,7 @@ static int yas537_power_on(struct yas5xx *yas5xx) static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { [yas530] = { .devid = YAS530_DEVICE_ID, + .product_label = "yas530", .product_name = "YAS530 MS-3E", .version_names = { "A", "B" }, .volatile_reg = yas530_volatile_reg, @@ -1338,6 +1341,7 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { }, [yas532] = { .devid = YAS532_DEVICE_ID, + .product_label = "yas532", .product_name = "YAS532 MS-3R", .version_names = { "AB", "AC" }, .volatile_reg = yas530_volatile_reg, @@ -1353,6 +1357,7 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { }, [yas533] = { .devid = YAS532_DEVICE_ID, + .product_label = "yas533", .product_name = "YAS533 MS-3F", .version_names = { "AB", "AC" }, .volatile_reg = yas530_volatile_reg, @@ -1368,6 +1373,7 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { }, [yas537] = { .devid = YAS537_DEVICE_ID, + .product_label = "yas537", .product_name = "YAS537 MS-3T", .version_names = { "v0", "v1" }, /* version naming unknown */ .volatile_reg = yas537_volatile_reg, @@ -1385,7 +1391,6 @@ static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { static int yas5xx_probe(struct i2c_client *i2c) { - const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct iio_dev *indio_dev; struct device *dev = &i2c->dev; struct yas5xx *yas5xx; @@ -1400,7 +1405,10 @@ static int yas5xx_probe(struct i2c_client *i2c) yas5xx = iio_priv(indio_dev); i2c_set_clientdata(i2c, indio_dev); yas5xx->dev = dev; - mutex_init(&yas5xx->lock); + + ret = devm_mutex_init(dev, &yas5xx->lock); + if (ret) + return ret; ret = iio_read_mount_matrix(dev, &yas5xx->orientation); if (ret) @@ -1418,7 +1426,7 @@ static int yas5xx_probe(struct i2c_client *i2c) return dev_err_probe(dev, ret, "cannot enable regulators\n"); /* See comment in runtime resume callback */ - usleep_range(31000, 40000); + fsleep(31 * USEC_PER_MSEC); /* This will take the device out of reset if need be */ yas5xx->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); @@ -1443,7 +1451,7 @@ static int yas5xx_probe(struct i2c_client *i2c) if (id_check != ci->devid) { ret = dev_err_probe(dev, -ENODEV, "device ID %02x doesn't match %s\n", - id_check, id->name); + id_check, ci->product_label); goto assert_reset; } @@ -1469,7 +1477,7 @@ static int yas5xx_probe(struct i2c_client *i2c) indio_dev->info = &yas5xx_info; indio_dev->available_scan_masks = yas5xx_scan_masks; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = id->name; + indio_dev->name = ci->product_label; indio_dev->channels = yas5xx_channels; indio_dev->num_channels = ARRAY_SIZE(yas5xx_channels); @@ -1557,7 +1565,7 @@ static int yas5xx_runtime_resume(struct device *dev) * for all voltages to settle. The YAS532 is 10ms then 4ms for the * I2C to come online. Let's keep it safe and put this at 31ms. */ - usleep_range(31000, 40000); + fsleep(31 * USEC_PER_MSEC); gpiod_set_value_cansleep(yas5xx->reset, 0); ret = ci->power_on(yas5xx); @@ -1579,10 +1587,10 @@ static DEFINE_RUNTIME_DEV_PM_OPS(yas5xx_dev_pm_ops, yas5xx_runtime_suspend, yas5xx_runtime_resume, NULL); static const struct i2c_device_id yas5xx_id[] = { - {"yas530", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas530] }, - {"yas532", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas532] }, - {"yas533", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas533] }, - {"yas537", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas537] }, + { .name = "yas530", .driver_data = (kernel_ulong_t)&yas5xx_chip_info_tbl[yas530] }, + { .name = "yas532", .driver_data = (kernel_ulong_t)&yas5xx_chip_info_tbl[yas532] }, + { .name = "yas533", .driver_data = (kernel_ulong_t)&yas5xx_chip_info_tbl[yas533] }, + { .name = "yas537", .driver_data = (kernel_ulong_t)&yas5xx_chip_info_tbl[yas537] }, { } }; MODULE_DEVICE_TABLE(i2c, yas5xx_id); diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index 5a5e6e4fbe34..4a11e4555099 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -39,6 +39,27 @@ static const u32 rotation_sensitivity_addresses[] = { HID_USAGE_SENSOR_ORIENT_QUATERNION, }; +enum { + DEV_ROT_SCAN_TYPE_16BIT, + DEV_ROT_SCAN_TYPE_32BIT, +}; + +static const struct iio_scan_type dev_rot_scan_types[] = { + [DEV_ROT_SCAN_TYPE_16BIT] = { + .sign = 's', + .realbits = 16, + /* Storage bits has to stay 32 to not break userspace. */ + .storagebits = 32, + .repeat = 4, + }, + [DEV_ROT_SCAN_TYPE_32BIT] = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .repeat = 4, + }, +}; + /* Channel definitions */ static const struct iio_chan_spec dev_rot_channels[] = { { @@ -50,23 +71,14 @@ static const struct iio_chan_spec dev_rot_channels[] = { BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_HYSTERESIS), - .scan_index = 0 + .scan_index = 0, + .has_ext_scan_type = 1, + .ext_scan_type = dev_rot_scan_types, + .num_ext_scan_type = ARRAY_SIZE(dev_rot_scan_types), }, IIO_CHAN_SOFT_TIMESTAMP(1) }; -/* Adjust channel real bits based on report descriptor */ -static void dev_rot_adjust_channel_bit_mask(struct iio_chan_spec *chan, - int size) -{ - chan->scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - chan->scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - chan->scan_type.storagebits = sizeof(u32) * 8; - chan->scan_type.repeat = 4; -} - /* Channel read_raw handler */ static int dev_rot_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -141,9 +153,25 @@ static int dev_rot_write_raw(struct iio_dev *indio_dev, return ret; } +static int dev_rot_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct dev_rot_state *rot_state = iio_priv(indio_dev); + + switch (rot_state->quaternion.size / 4) { + case sizeof(s16): + return DEV_ROT_SCAN_TYPE_16BIT; + case sizeof(s32): + return DEV_ROT_SCAN_TYPE_32BIT; + default: + return -EINVAL; + } +} + static const struct iio_info dev_rot_info = { .read_raw_multi = &dev_rot_read_raw, .write_raw = &dev_rot_write_raw, + .get_current_scan_type = &dev_rot_get_current_scan_type, }; /* Callback handler to send event after all samples are received and captured */ @@ -212,7 +240,6 @@ static int dev_rot_capture_sample(struct hid_sensor_hub_device *hsdev, /* Parse report which is specific to an usage id*/ static int dev_rot_parse_report(struct platform_device *pdev, struct hid_sensor_hub_device *hsdev, - struct iio_chan_spec *channels, unsigned usage_id, struct dev_rot_state *st) { @@ -226,9 +253,6 @@ static int dev_rot_parse_report(struct platform_device *pdev, if (ret) return ret; - dev_rot_adjust_channel_bit_mask(&channels[0], - st->quaternion.size / 4); - dev_dbg(&pdev->dev, "dev_rot %x:%x\n", st->quaternion.index, st->quaternion.report_id); @@ -287,22 +311,13 @@ static int hid_dev_rot_probe(struct platform_device *pdev) return ret; } - indio_dev->channels = devm_kmemdup(&pdev->dev, dev_rot_channels, - sizeof(dev_rot_channels), - GFP_KERNEL); - if (!indio_dev->channels) { - dev_err(&pdev->dev, "failed to duplicate channels\n"); - return -ENOMEM; - } - - ret = dev_rot_parse_report(pdev, hsdev, - (struct iio_chan_spec *)indio_dev->channels, - hsdev->usage, rot_state); + ret = dev_rot_parse_report(pdev, hsdev, hsdev->usage, rot_state); if (ret) { dev_err(&pdev->dev, "failed to setup attributes\n"); return ret; } + indio_dev->channels = dev_rot_channels; indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); indio_dev->info = &dev_rot_info; indio_dev->name = name; diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c index 672b1ca3a920..ac342127d59e 100644 --- a/drivers/iio/potentiometer/ad5272.c +++ b/drivers/iio/potentiometer/ad5272.c @@ -204,11 +204,11 @@ static const struct of_device_id ad5272_dt_ids[] = { MODULE_DEVICE_TABLE(of, ad5272_dt_ids); static const struct i2c_device_id ad5272_id[] = { - { "ad5272-020", AD5272_020 }, - { "ad5272-050", AD5272_050 }, - { "ad5272-100", AD5272_100 }, - { "ad5274-020", AD5274_020 }, - { "ad5274-100", AD5274_100 }, + { .name = "ad5272-020", .driver_data = AD5272_020 }, + { .name = "ad5272-050", .driver_data = AD5272_050 }, + { .name = "ad5272-100", .driver_data = AD5272_100 }, + { .name = "ad5274-020", .driver_data = AD5274_020 }, + { .name = "ad5274-100", .driver_data = AD5274_100 }, { } }; MODULE_DEVICE_TABLE(i2c, ad5272_id); diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c index 8a64d93f7e7b..42394343b5a9 100644 --- a/drivers/iio/potentiometer/ds1803.c +++ b/drivers/iio/potentiometer/ds1803.c @@ -235,10 +235,10 @@ static const struct of_device_id ds1803_dt_ids[] = { MODULE_DEVICE_TABLE(of, ds1803_dt_ids); static const struct i2c_device_id ds1803_id[] = { - { "ds1803-010", (kernel_ulong_t)&ds1803_cfg[DS1803_010] }, - { "ds1803-050", (kernel_ulong_t)&ds1803_cfg[DS1803_050] }, - { "ds1803-100", (kernel_ulong_t)&ds1803_cfg[DS1803_100] }, - { "ds3502", (kernel_ulong_t)&ds1803_cfg[DS3502] }, + { .name = "ds1803-010", .driver_data = (kernel_ulong_t)&ds1803_cfg[DS1803_010] }, + { .name = "ds1803-050", .driver_data = (kernel_ulong_t)&ds1803_cfg[DS1803_050] }, + { .name = "ds1803-100", .driver_data = (kernel_ulong_t)&ds1803_cfg[DS1803_100] }, + { .name = "ds3502", .driver_data = (kernel_ulong_t)&ds1803_cfg[DS3502] }, { } }; MODULE_DEVICE_TABLE(i2c, ds1803_id); diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c index a42b57733363..77149908e1bf 100644 --- a/drivers/iio/potentiometer/tpl0102.c +++ b/drivers/iio/potentiometer/tpl0102.c @@ -149,10 +149,10 @@ static int tpl0102_probe(struct i2c_client *client) } static const struct i2c_device_id tpl0102_id[] = { - { "cat5140-503", CAT5140_503 }, - { "cat5140-104", CAT5140_104 }, - { "tpl0102-104", TPL0102_104 }, - { "tpl0401-103", TPL0401_103 }, + { .name = "cat5140-503", .driver_data = CAT5140_503 }, + { .name = "cat5140-104", .driver_data = CAT5140_104 }, + { .name = "tpl0102-104", .driver_data = TPL0102_104 }, + { .name = "tpl0401-103", .driver_data = TPL0401_103 }, { } }; MODULE_DEVICE_TABLE(i2c, tpl0102_id); diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index eccc2a34358f..359dffa47091 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -403,8 +403,8 @@ static const struct of_device_id lmp91000_of_match[] = { MODULE_DEVICE_TABLE(of, lmp91000_of_match); static const struct i2c_device_id lmp91000_id[] = { - { "lmp91000" }, - { "lmp91002" }, + { .name = "lmp91000" }, + { .name = "lmp91002" }, { } }; MODULE_DEVICE_TABLE(i2c, lmp91000_id); diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c index 699b0fd64985..fd48bed35088 100644 --- a/drivers/iio/pressure/abp060mg.c +++ b/drivers/iio/pressure/abp060mg.c @@ -209,44 +209,66 @@ static int abp060mg_probe(struct i2c_client *client) static const struct i2c_device_id abp060mg_id_table[] = { /* mbar & kPa variants (abp060m [60 mbar] == abp006k [6 kPa]) */ /* gage: */ - { "abp060mg", ABP006KG }, { "abp006kg", ABP006KG }, - { "abp100mg", ABP010KG }, { "abp010kg", ABP010KG }, - { "abp160mg", ABP016KG }, { "abp016kg", ABP016KG }, - { "abp250mg", ABP025KG }, { "abp025kg", ABP025KG }, - { "abp400mg", ABP040KG }, { "abp040kg", ABP040KG }, - { "abp600mg", ABP060KG }, { "abp060kg", ABP060KG }, - { "abp001bg", ABP100KG }, { "abp100kg", ABP100KG }, - { "abp1_6bg", ABP160KG }, { "abp160kg", ABP160KG }, - { "abp2_5bg", ABP250KG }, { "abp250kg", ABP250KG }, - { "abp004bg", ABP400KG }, { "abp400kg", ABP400KG }, - { "abp006bg", ABP600KG }, { "abp600kg", ABP600KG }, - { "abp010bg", ABP001GG }, { "abp001gg", ABP001GG }, + { .name = "abp060mg", .driver_data = ABP006KG }, + { .name = "abp006kg", .driver_data = ABP006KG }, + { .name = "abp100mg", .driver_data = ABP010KG }, + { .name = "abp010kg", .driver_data = ABP010KG }, + { .name = "abp160mg", .driver_data = ABP016KG }, + { .name = "abp016kg", .driver_data = ABP016KG }, + { .name = "abp250mg", .driver_data = ABP025KG }, + { .name = "abp025kg", .driver_data = ABP025KG }, + { .name = "abp400mg", .driver_data = ABP040KG }, + { .name = "abp040kg", .driver_data = ABP040KG }, + { .name = "abp600mg", .driver_data = ABP060KG }, + { .name = "abp060kg", .driver_data = ABP060KG }, + { .name = "abp001bg", .driver_data = ABP100KG }, + { .name = "abp100kg", .driver_data = ABP100KG }, + { .name = "abp1_6bg", .driver_data = ABP160KG }, + { .name = "abp160kg", .driver_data = ABP160KG }, + { .name = "abp2_5bg", .driver_data = ABP250KG }, + { .name = "abp250kg", .driver_data = ABP250KG }, + { .name = "abp004bg", .driver_data = ABP400KG }, + { .name = "abp400kg", .driver_data = ABP400KG }, + { .name = "abp006bg", .driver_data = ABP600KG }, + { .name = "abp600kg", .driver_data = ABP600KG }, + { .name = "abp010bg", .driver_data = ABP001GG }, + { .name = "abp001gg", .driver_data = ABP001GG }, /* differential: */ - { "abp060md", ABP006KD }, { "abp006kd", ABP006KD }, - { "abp100md", ABP010KD }, { "abp010kd", ABP010KD }, - { "abp160md", ABP016KD }, { "abp016kd", ABP016KD }, - { "abp250md", ABP025KD }, { "abp025kd", ABP025KD }, - { "abp400md", ABP040KD }, { "abp040kd", ABP040KD }, - { "abp600md", ABP060KD }, { "abp060kd", ABP060KD }, - { "abp001bd", ABP100KD }, { "abp100kd", ABP100KD }, - { "abp1_6bd", ABP160KD }, { "abp160kd", ABP160KD }, - { "abp2_5bd", ABP250KD }, { "abp250kd", ABP250KD }, - { "abp004bd", ABP400KD }, { "abp400kd", ABP400KD }, + { .name = "abp060md", .driver_data = ABP006KD }, + { .name = "abp006kd", .driver_data = ABP006KD }, + { .name = "abp100md", .driver_data = ABP010KD }, + { .name = "abp010kd", .driver_data = ABP010KD }, + { .name = "abp160md", .driver_data = ABP016KD }, + { .name = "abp016kd", .driver_data = ABP016KD }, + { .name = "abp250md", .driver_data = ABP025KD }, + { .name = "abp025kd", .driver_data = ABP025KD }, + { .name = "abp400md", .driver_data = ABP040KD }, + { .name = "abp040kd", .driver_data = ABP040KD }, + { .name = "abp600md", .driver_data = ABP060KD }, + { .name = "abp060kd", .driver_data = ABP060KD }, + { .name = "abp001bd", .driver_data = ABP100KD }, + { .name = "abp100kd", .driver_data = ABP100KD }, + { .name = "abp1_6bd", .driver_data = ABP160KD }, + { .name = "abp160kd", .driver_data = ABP160KD }, + { .name = "abp2_5bd", .driver_data = ABP250KD }, + { .name = "abp250kd", .driver_data = ABP250KD }, + { .name = "abp004bd", .driver_data = ABP400KD }, + { .name = "abp400kd", .driver_data = ABP400KD }, /* psi variants */ /* gage: */ - { "abp001pg", ABP001PG }, - { "abp005pg", ABP005PG }, - { "abp015pg", ABP015PG }, - { "abp030pg", ABP030PG }, - { "abp060pg", ABP060PG }, - { "abp100pg", ABP100PG }, - { "abp150pg", ABP150PG }, + { .name = "abp001pg", .driver_data = ABP001PG }, + { .name = "abp005pg", .driver_data = ABP005PG }, + { .name = "abp015pg", .driver_data = ABP015PG }, + { .name = "abp030pg", .driver_data = ABP030PG }, + { .name = "abp060pg", .driver_data = ABP060PG }, + { .name = "abp100pg", .driver_data = ABP100PG }, + { .name = "abp150pg", .driver_data = ABP150PG }, /* differential: */ - { "abp001pd", ABP001PD }, - { "abp005pd", ABP005PD }, - { "abp015pd", ABP015PD }, - { "abp030pd", ABP030PD }, - { "abp060pd", ABP060PD }, + { .name = "abp001pd", .driver_data = ABP001PD }, + { .name = "abp005pd", .driver_data = ABP005PD }, + { .name = "abp015pd", .driver_data = ABP015PD }, + { .name = "abp030pd", .driver_data = ABP030PD }, + { .name = "abp060pd", .driver_data = ABP060PD }, { } }; MODULE_DEVICE_TABLE(i2c, abp060mg_id_table); diff --git a/drivers/iio/pressure/abp2030pa_i2c.c b/drivers/iio/pressure/abp2030pa_i2c.c index 9f1c1c8a9afb..e71dc8e8e957 100644 --- a/drivers/iio/pressure/abp2030pa_i2c.c +++ b/drivers/iio/pressure/abp2030pa_i2c.c @@ -69,7 +69,7 @@ static const struct of_device_id abp2_i2c_match[] = { MODULE_DEVICE_TABLE(of, abp2_i2c_match); static const struct i2c_device_id abp2_i2c_id[] = { - { "abp2030pa" }, + { .name = "abp2030pa" }, { } }; MODULE_DEVICE_TABLE(i2c, abp2_i2c_id); diff --git a/drivers/iio/pressure/adp810.c b/drivers/iio/pressure/adp810.c index 5282612d1309..47c5ad564c7f 100644 --- a/drivers/iio/pressure/adp810.c +++ b/drivers/iio/pressure/adp810.c @@ -199,7 +199,7 @@ static int adp810_probe(struct i2c_client *client) } static const struct i2c_device_id adp810_id_table[] = { - { "adp810" }, + { .name = "adp810" }, { } }; MODULE_DEVICE_TABLE(i2c, adp810_id_table); diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 2f2771096ed7..990340a9b10c 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -1910,7 +1910,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p) u32 comp_press; s32 comp_temp; aligned_s64 timestamp; - } buffer; + } buffer = { }; int ret; guard(mutex)(&data->lock); diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 8e459b6c97ff..3f6e0723a9d7 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -38,12 +38,12 @@ static const struct of_device_id bmp280_of_i2c_match[] = { MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); static const struct i2c_device_id bmp280_i2c_id[] = { - {"bmp085", (kernel_ulong_t)&bmp085_chip_info }, - {"bmp180", (kernel_ulong_t)&bmp180_chip_info }, - {"bmp280", (kernel_ulong_t)&bmp280_chip_info }, - {"bme280", (kernel_ulong_t)&bme280_chip_info }, - {"bmp380", (kernel_ulong_t)&bmp380_chip_info }, - {"bmp580", (kernel_ulong_t)&bmp580_chip_info }, + { .name = "bmp085", .driver_data = (kernel_ulong_t)&bmp085_chip_info }, + { .name = "bmp180", .driver_data = (kernel_ulong_t)&bmp180_chip_info }, + { .name = "bmp280", .driver_data = (kernel_ulong_t)&bmp280_chip_info }, + { .name = "bme280", .driver_data = (kernel_ulong_t)&bme280_chip_info }, + { .name = "bmp380", .driver_data = (kernel_ulong_t)&bmp380_chip_info }, + { .name = "bmp580", .driver_data = (kernel_ulong_t)&bmp580_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index c6b950c596c1..6cbde48d5be3 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -170,14 +170,8 @@ static int cros_ec_baro_probe(struct platform_device *pdev) return -EINVAL; } - /* Timestamp */ channel++; - channel->type = IIO_TIMESTAMP; - channel->channel = -1; - channel->scan_index = 1; - channel->scan_type.sign = 's'; - channel->scan_type.realbits = 64; - channel->scan_type.storagebits = 64; + *channel = IIO_CHAN_SOFT_TIMESTAMP(1); indio_dev->channels = state->channels; indio_dev->num_channels = CROS_EC_BARO_MAX_CHANNELS; diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c index 46feb27fe632..01a873165923 100644 --- a/drivers/iio/pressure/dlhl60d.c +++ b/drivers/iio/pressure/dlhl60d.c @@ -340,8 +340,8 @@ static const struct of_device_id dlh_of_match[] = { MODULE_DEVICE_TABLE(of, dlh_of_match); static const struct i2c_device_id dlh_id[] = { - { "dlhl60d", (kernel_ulong_t)&dlhl60d_info }, - { "dlhl60g", (kernel_ulong_t)&dlhl60g_info }, + { .name = "dlhl60d", .driver_data = (kernel_ulong_t)&dlhl60d_info }, + { .name = "dlhl60g", .driver_data = (kernel_ulong_t)&dlhl60g_info }, { } }; MODULE_DEVICE_TABLE(i2c, dlh_id); diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c index 8edaa4d10a70..f45af72a0554 100644 --- a/drivers/iio/pressure/dps310.c +++ b/drivers/iio/pressure/dps310.c @@ -887,7 +887,7 @@ static int dps310_probe(struct i2c_client *client) } static const struct i2c_device_id dps310_id[] = { - { DPS310_DEV_NAME }, + { .name = DPS310_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, dps310_id); diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index 5f1d6abda3e4..a039b99d9851 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -3,6 +3,7 @@ * HID Sensors Driver * Copyright (c) 2014, Intel Corporation. */ +#include #include #include #include @@ -53,17 +54,6 @@ static const struct iio_chan_spec press_channels[] = { }; -/* Adjust channel real bits based on report descriptor */ -static void press_adjust_channel_bit_mask(struct iio_chan_spec *channels, - int channel, int size) -{ - channels[channel].scan_type.sign = 's'; - /* Real storage bits will change based on the report desc. */ - channels[channel].scan_type.realbits = size * 8; - /* Maximum size of a sample to capture is u32 */ - channels[channel].scan_type.storagebits = sizeof(u32) * 8; -} - /* Channel read_raw handler */ static int press_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, @@ -225,8 +215,11 @@ static int press_parse_report(struct platform_device *pdev, &st->press_attr); if (ret < 0) return ret; - press_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESSURE, - st->press_attr.size); + channels[CHANNEL_SCAN_INDEX_PRESSURE].scan_type = (struct iio_scan_type) { + .format = 's', + .realbits = BYTES_TO_BITS(st->press_attr.size), + .storagebits = BITS_PER_TYPE(u32), + }; dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index, st->press_attr.report_id); diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index cbb4aaf45e2c..424523345060 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -266,7 +266,7 @@ static int hp03_probe(struct i2c_client *client) } static const struct i2c_device_id hp03_id[] = { - { "hp03" }, + { .name = "hp03" }, { } }; MODULE_DEVICE_TABLE(i2c, hp03_id); diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c index abe10ccb6770..be14202855cf 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c @@ -395,7 +395,7 @@ static int hp206c_probe(struct i2c_client *client) } static const struct i2c_device_id hp206c_id[] = { - {"hp206c"}, + { .name = "hp206c" }, { } }; MODULE_DEVICE_TABLE(i2c, hp206c_id); diff --git a/drivers/iio/pressure/hsc030pa_i2c.c b/drivers/iio/pressure/hsc030pa_i2c.c index 3500bda03d75..f4ea30b2980d 100644 --- a/drivers/iio/pressure/hsc030pa_i2c.c +++ b/drivers/iio/pressure/hsc030pa_i2c.c @@ -58,7 +58,7 @@ static const struct of_device_id hsc_i2c_match[] = { MODULE_DEVICE_TABLE(of, hsc_i2c_match); static const struct i2c_device_id hsc_i2c_id[] = { - { "hsc030pa" }, + { .name = "hsc030pa" }, { } }; MODULE_DEVICE_TABLE(i2c, hsc_i2c_id); diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 3d83d0098a57..02b363c5c45b 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -633,7 +633,7 @@ static const struct of_device_id icp10100_of_match[] = { MODULE_DEVICE_TABLE(of, icp10100_of_match); static const struct i2c_device_id icp10100_id[] = { - { "icp10100" }, + { .name = "icp10100" }, { } }; MODULE_DEVICE_TABLE(i2c, icp10100_id); diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c index 3db9ef4e2770..4a43eba078a8 100644 --- a/drivers/iio/pressure/mpl115_i2c.c +++ b/drivers/iio/pressure/mpl115_i2c.c @@ -45,7 +45,7 @@ static int mpl115_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id mpl115_i2c_id[] = { - { "mpl115" }, + { .name = "mpl115" }, { } }; MODULE_DEVICE_TABLE(i2c, mpl115_i2c_id); diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index aeac1586f12e..f20fa6ad16fe 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -783,7 +783,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend, mpl3115_resume); static const struct i2c_device_id mpl3115_id[] = { - { "mpl3115" }, + { .name = "mpl3115" }, { } }; MODULE_DEVICE_TABLE(i2c, mpl3115_id); diff --git a/drivers/iio/pressure/mprls0025pa_i2c.c b/drivers/iio/pressure/mprls0025pa_i2c.c index 0fe8cfe0d7e7..92edaf3005eb 100644 --- a/drivers/iio/pressure/mprls0025pa_i2c.c +++ b/drivers/iio/pressure/mprls0025pa_i2c.c @@ -69,7 +69,7 @@ static const struct of_device_id mpr_i2c_match[] = { MODULE_DEVICE_TABLE(of, mpr_i2c_match); static const struct i2c_device_id mpr_i2c_id[] = { - { "mprls0025pa" }, + { .name = "mprls0025pa" }, { } }; MODULE_DEVICE_TABLE(i2c, mpr_i2c_id); diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index 1c041b9085fb..b5be6a6daf02 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -113,8 +113,8 @@ static const struct of_device_id ms5611_i2c_matches[] = { MODULE_DEVICE_TABLE(of, ms5611_i2c_matches); static const struct i2c_device_id ms5611_id[] = { - { "ms5611", MS5611 }, - { "ms5607", MS5607 }, + { .name = "ms5611", .driver_data = MS5611 }, + { .name = "ms5607", .driver_data = MS5607 }, { } }; MODULE_DEVICE_TABLE(i2c, ms5611_id); diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index 59705a666979..03945a4fc718 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -215,10 +215,10 @@ static const struct ms_tp_data ms8607_data = { }; static const struct i2c_device_id ms5637_id[] = { - {"ms5637", (kernel_ulong_t)&ms5637_data }, - {"ms5805", (kernel_ulong_t)&ms5805_data }, - {"ms5837", (kernel_ulong_t)&ms5837_data }, - {"ms8607-temppressure", (kernel_ulong_t)&ms8607_data }, + { .name = "ms5637", .driver_data = (kernel_ulong_t)&ms5637_data }, + { .name = "ms5805", .driver_data = (kernel_ulong_t)&ms5805_data }, + { .name = "ms5837", .driver_data = (kernel_ulong_t)&ms5837_data }, + { .name = "ms8607-temppressure", .driver_data = (kernel_ulong_t)&ms8607_data }, { } }; MODULE_DEVICE_TABLE(i2c, ms5637_id); diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c index 08146ca0f91d..b3be9de03678 100644 --- a/drivers/iio/pressure/rohm-bm1390.c +++ b/drivers/iio/pressure/rohm-bm1390.c @@ -888,7 +888,7 @@ static const struct of_device_id bm1390_of_match[] = { MODULE_DEVICE_TABLE(of, bm1390_of_match); static const struct i2c_device_id bm1390_id[] = { - { "bm1390glv-z", }, + { .name = "bm1390glv-z" }, { } }; MODULE_DEVICE_TABLE(i2c, bm1390_id); diff --git a/drivers/iio/pressure/sdp500.c b/drivers/iio/pressure/sdp500.c index 9828c73c4855..ba80dc21faad 100644 --- a/drivers/iio/pressure/sdp500.c +++ b/drivers/iio/pressure/sdp500.c @@ -130,7 +130,7 @@ static int sdp500_probe(struct i2c_client *client) } static const struct i2c_device_id sdp500_id[] = { - { "sdp500" }, + { .name = "sdp500" }, { } }; MODULE_DEVICE_TABLE(i2c, sdp500_id); diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 0f50bac1fb4d..816bfcfd62ae 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -61,14 +61,14 @@ static const struct acpi_device_id st_press_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, st_press_acpi_match); static const struct i2c_device_id st_press_id_table[] = { - { LPS001WP_PRESS_DEV_NAME, LPS001WP }, - { LPS25H_PRESS_DEV_NAME, LPS25H }, - { LPS331AP_PRESS_DEV_NAME, LPS331AP }, - { LPS22HB_PRESS_DEV_NAME, LPS22HB }, - { LPS33HW_PRESS_DEV_NAME, LPS33HW }, - { LPS35HW_PRESS_DEV_NAME, LPS35HW }, - { LPS22HH_PRESS_DEV_NAME, LPS22HH }, - { LPS22DF_PRESS_DEV_NAME, LPS22DF }, + { .name = LPS001WP_PRESS_DEV_NAME, .driver_data = LPS001WP }, + { .name = LPS25H_PRESS_DEV_NAME, .driver_data = LPS25H }, + { .name = LPS331AP_PRESS_DEV_NAME, .driver_data = LPS331AP }, + { .name = LPS22HB_PRESS_DEV_NAME, .driver_data = LPS22HB }, + { .name = LPS33HW_PRESS_DEV_NAME, .driver_data = LPS33HW }, + { .name = LPS35HW_PRESS_DEV_NAME, .driver_data = LPS35HW }, + { .name = LPS22HH_PRESS_DEV_NAME, .driver_data = LPS22HH }, + { .name = LPS22DF_PRESS_DEV_NAME, .driver_data = LPS22DF }, { } }; MODULE_DEVICE_TABLE(i2c, st_press_id_table); diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c index c7cb0fd816d3..ab30f6745181 100644 --- a/drivers/iio/pressure/t5403.c +++ b/drivers/iio/pressure/t5403.c @@ -251,7 +251,7 @@ static int t5403_probe(struct i2c_client *client) } static const struct i2c_device_id t5403_id[] = { - { "t5403" }, + { .name = "t5403" }, { } }; MODULE_DEVICE_TABLE(i2c, t5403_id); diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c index a6034bf05d97..2d8af33f6a29 100644 --- a/drivers/iio/pressure/zpa2326_i2c.c +++ b/drivers/iio/pressure/zpa2326_i2c.c @@ -58,7 +58,7 @@ static void zpa2326_remove_i2c(struct i2c_client *client) } static const struct i2c_device_id zpa2326_i2c_ids[] = { - { "zpa2326" }, + { .name = "zpa2326" }, { } }; MODULE_DEVICE_TABLE(i2c, zpa2326_i2c_ids); diff --git a/drivers/iio/proximity/aw96103.c b/drivers/iio/proximity/aw96103.c index 3472a2c36e44..8fbb755dcae0 100644 --- a/drivers/iio/proximity/aw96103.c +++ b/drivers/iio/proximity/aw96103.c @@ -825,8 +825,8 @@ static const struct of_device_id aw96103_dt_match[] = { MODULE_DEVICE_TABLE(of, aw96103_dt_match); static const struct i2c_device_id aw96103_i2c_id[] = { - { "aw96103", (kernel_ulong_t)&aw_chip_info_tbl[AW96103_VAL] }, - { "aw96105", (kernel_ulong_t)&aw_chip_info_tbl[AW96105_VAL] }, + { .name = "aw96103", .driver_data = (kernel_ulong_t)&aw_chip_info_tbl[AW96103_VAL] }, + { .name = "aw96105", .driver_data = (kernel_ulong_t)&aw_chip_info_tbl[AW96105_VAL] }, { } }; MODULE_DEVICE_TABLE(i2c, aw96103_i2c_id); diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c index 9efaa5b6b5bd..c3a93c0e2b64 100644 --- a/drivers/iio/proximity/hx9023s.c +++ b/drivers/iio/proximity/hx9023s.c @@ -1199,7 +1199,7 @@ static const struct of_device_id hx9023s_of_match[] = { MODULE_DEVICE_TABLE(of, hx9023s_of_match); static const struct i2c_device_id hx9023s_id[] = { - { "hx9023s" }, + { .name = "hx9023s" }, { } }; MODULE_DEVICE_TABLE(i2c, hx9023s_id); diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index f69db6f2f380..016626f21218 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -995,7 +995,7 @@ static int isl29501_probe(struct i2c_client *client) } static const struct i2c_device_id isl29501_id[] = { - { "isl29501" }, + { .name = "isl29501" }, { } }; diff --git a/drivers/iio/proximity/mb1232.c b/drivers/iio/proximity/mb1232.c index 34b49c54e68b..1e8ecb9e9c56 100644 --- a/drivers/iio/proximity/mb1232.c +++ b/drivers/iio/proximity/mb1232.c @@ -244,13 +244,13 @@ static const struct of_device_id of_mb1232_match[] = { MODULE_DEVICE_TABLE(of, of_mb1232_match); static const struct i2c_device_id mb1232_id[] = { - { "maxbotix-mb1202", }, - { "maxbotix-mb1212", }, - { "maxbotix-mb1222", }, - { "maxbotix-mb1232", }, - { "maxbotix-mb1242", }, - { "maxbotix-mb7040", }, - { "maxbotix-mb7137", }, + { .name = "maxbotix-mb1202" }, + { .name = "maxbotix-mb1212" }, + { .name = "maxbotix-mb1222" }, + { .name = "maxbotix-mb1232" }, + { .name = "maxbotix-mb1242" }, + { .name = "maxbotix-mb7040" }, + { .name = "maxbotix-mb7137" }, { } }; MODULE_DEVICE_TABLE(i2c, mb1232_id); diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 21336b8f122a..5e9e04540393 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -319,8 +319,8 @@ static void lidar_remove(struct i2c_client *client) } static const struct i2c_device_id lidar_id[] = { - { "lidar-lite-v2" }, - { "lidar-lite-v3" }, + { .name = "lidar-lite-v2" }, + { .name = "lidar-lite-v3" }, { } }; MODULE_DEVICE_TABLE(i2c, lidar_id); diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c index 81b8daf17a54..db1e94fc5658 100644 --- a/drivers/iio/proximity/rfd77402.c +++ b/drivers/iio/proximity/rfd77402.c @@ -433,7 +433,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(rfd77402_pm_ops, rfd77402_suspend, rfd77402_resume); static const struct i2c_device_id rfd77402_id[] = { - { "rfd77402" }, + { .name = "rfd77402" }, { } }; MODULE_DEVICE_TABLE(i2c, rfd77402_id); diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c index d7e4cc48cfbf..35eb3fd7e700 100644 --- a/drivers/iio/proximity/srf08.c +++ b/drivers/iio/proximity/srf08.c @@ -226,7 +226,7 @@ static int srf08_read_raw(struct iio_dev *indio_dev, static ssize_t srf08_show_range_mm_available(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "[0.043 0.043 11.008]\n"); + return sysfs_emit(buf, "[0.043 0.043 11.008]\n"); } static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO, @@ -238,8 +238,8 @@ static ssize_t srf08_show_range_mm(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct srf08_data *data = iio_priv(indio_dev); - return sprintf(buf, "%d.%03d\n", data->range_mm / 1000, - data->range_mm % 1000); + return sysfs_emit(buf, "%d.%03d\n", + data->range_mm / 1000, data->range_mm % 1000); } /* @@ -316,10 +316,10 @@ static ssize_t srf08_show_sensitivity_available(struct device *dev, for (i = 0; i < data->chip_info->num_sensitivity_avail; i++) if (data->chip_info->sensitivity_avail[i]) - len += sprintf(buf + len, "%d ", - data->chip_info->sensitivity_avail[i]); + len += sysfs_emit_at(buf, len, "%d ", + data->chip_info->sensitivity_avail[i]); - len += sprintf(buf + len, "\n"); + len += sysfs_emit_at(buf, len, "\n"); return len; } @@ -332,11 +332,8 @@ static ssize_t srf08_show_sensitivity(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct srf08_data *data = iio_priv(indio_dev); - int len; - len = sprintf(buf, "%d\n", data->sensitivity); - - return len; + return sysfs_emit(buf, "%d\n", data->sensitivity); } static ssize_t srf08_write_sensitivity(struct srf08_data *data, @@ -533,9 +530,9 @@ static const struct of_device_id of_srf08_match[] = { MODULE_DEVICE_TABLE(of, of_srf08_match); static const struct i2c_device_id srf08_id[] = { - { "srf02", SRF02 }, - { "srf08", SRF08 }, - { "srf10", SRF10 }, + { .name = "srf02", .driver_data = SRF02 }, + { .name = "srf08", .driver_data = SRF08 }, + { .name = "srf10", .driver_data = SRF10 }, { } }; MODULE_DEVICE_TABLE(i2c, srf08_id); diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index fb02eac78ed4..602f7b95c83e 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -1007,8 +1007,8 @@ static const struct of_device_id sx9310_of_match[] = { MODULE_DEVICE_TABLE(of, sx9310_of_match); static const struct i2c_device_id sx9310_id[] = { - { "sx9310", (kernel_ulong_t)&sx9310_info }, - { "sx9311", (kernel_ulong_t)&sx9311_info }, + { .name = "sx9310", .driver_data = (kernel_ulong_t)&sx9310_info }, + { .name = "sx9311", .driver_data = (kernel_ulong_t)&sx9311_info }, { } }; MODULE_DEVICE_TABLE(i2c, sx9310_id); diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c index f61eff39751d..36c45d101336 100644 --- a/drivers/iio/proximity/sx9324.c +++ b/drivers/iio/proximity/sx9324.c @@ -1123,19 +1123,19 @@ static int sx9324_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(sx9324_pm_ops, sx9324_suspend, sx9324_resume); static const struct acpi_device_id sx9324_acpi_match[] = { - { "STH9324", SX9324_WHOAMI_VALUE }, + { .id = "STH9324" }, { } }; MODULE_DEVICE_TABLE(acpi, sx9324_acpi_match); static const struct of_device_id sx9324_of_match[] = { - { .compatible = "semtech,sx9324", (void *)SX9324_WHOAMI_VALUE }, + { .compatible = "semtech,sx9324" }, { } }; MODULE_DEVICE_TABLE(of, sx9324_of_match); static const struct i2c_device_id sx9324_id[] = { - { "sx9324", SX9324_WHOAMI_VALUE }, + { .name = "sx9324" }, { } }; MODULE_DEVICE_TABLE(i2c, sx9324_id); diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c index 4448988d4e7e..4b9498022b22 100644 --- a/drivers/iio/proximity/sx9360.c +++ b/drivers/iio/proximity/sx9360.c @@ -832,20 +832,20 @@ static int sx9360_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(sx9360_pm_ops, sx9360_suspend, sx9360_resume); static const struct acpi_device_id sx9360_acpi_match[] = { - { "STH9360", SX9360_WHOAMI_VALUE }, - { "SAMM0208", SX9360_WHOAMI_VALUE }, + { .id = "STH9360" }, + { .id = "SAMM0208" }, { } }; MODULE_DEVICE_TABLE(acpi, sx9360_acpi_match); static const struct of_device_id sx9360_of_match[] = { - { .compatible = "semtech,sx9360", (void *)SX9360_WHOAMI_VALUE }, + { .compatible = "semtech,sx9360" }, { } }; MODULE_DEVICE_TABLE(of, sx9360_of_match); static const struct i2c_device_id sx9360_id[] = { - {"sx9360", SX9360_WHOAMI_VALUE }, + { .name = "sx9360" }, { } }; MODULE_DEVICE_TABLE(i2c, sx9360_id); diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 6c67bae7488c..dadce9b44227 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -1025,7 +1025,7 @@ static const struct of_device_id sx9500_of_match[] = { MODULE_DEVICE_TABLE(of, sx9500_of_match); static const struct i2c_device_id sx9500_id[] = { - { "sx9500" }, + { .name = "sx9500" }, { } }; MODULE_DEVICE_TABLE(i2c, sx9500_id); diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c index ad3e46d47fa8..b7127c3c52d2 100644 --- a/drivers/iio/proximity/vl53l0x-i2c.c +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -87,15 +87,14 @@ static irqreturn_t vl53l0x_trigger_handler(int irq, void *priv) ret = i2c_smbus_read_i2c_block_data(data->client, VL_REG_RESULT_RANGE_STATUS, sizeof(buffer), buffer); - if (ret < 0) - return ret; - else if (ret != 12) - return -EREMOTEIO; + if (ret != 12) + goto done; scan.chan = get_unaligned_be16(&buffer[10]); iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), iio_get_time_ns(indio_dev)); +done: iio_trigger_notify_done(indio_dev->trig); vl53l0x_clear_irq(data); @@ -393,7 +392,7 @@ static int vl53l0x_probe(struct i2c_client *client) } static const struct i2c_device_id vl53l0x_id[] = { - { "vl53l0x" }, + { .name = "vl53l0x" }, { } }; MODULE_DEVICE_TABLE(i2c, vl53l0x_id); diff --git a/drivers/iio/proximity/vl53l1x-i2c.c b/drivers/iio/proximity/vl53l1x-i2c.c index 4d9cb3983dba..ff56bfcf8bd2 100644 --- a/drivers/iio/proximity/vl53l1x-i2c.c +++ b/drivers/iio/proximity/vl53l1x-i2c.c @@ -730,7 +730,7 @@ static int vl53l1x_probe(struct i2c_client *client) } static const struct i2c_device_id vl53l1x_id[] = { - { "vl53l1x" }, + { .name = "vl53l1x" }, { } }; MODULE_DEVICE_TABLE(i2c, vl53l1x_id); diff --git a/drivers/iio/resolver/ad2s1210.c b/drivers/iio/resolver/ad2s1210.c index 774728c804c0..1be19fe8aa3f 100644 --- a/drivers/iio/resolver/ad2s1210.c +++ b/drivers/iio/resolver/ad2s1210.c @@ -1334,7 +1334,7 @@ static irqreturn_t ad2s1210_trigger_handler(int irq, void *p) ret = regmap_read(st->regmap, AD2S1210_REG_FAULT, ®_val); if (ret < 0) - return ret; + goto error_ret; st->sample.fault = reg_val; } diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index 38e6f8dfd3b8..fc65d8352d12 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -28,6 +28,8 @@ #define LTC2983_STATUS_REG 0x0000 #define LTC2983_TEMP_RES_START_REG 0x0010 #define LTC2983_TEMP_RES_END_REG 0x005F +#define ADT7604_RES_RES_START_REG 0x0060 +#define ADT7604_RES_RES_END_REG 0x00AF #define LTC2983_EEPROM_KEY_REG 0x00B0 #define LTC2983_EEPROM_READ_STATUS_REG 0x00D0 #define LTC2983_GLOBAL_CONFIG_REG 0x00F0 @@ -56,10 +58,10 @@ #define LTC2983_EEPROM_WRITE_TIME_MS 2600 #define LTC2983_EEPROM_READ_TIME_MS 20 -#define LTC2983_CHAN_START_ADDR(chan) \ - (((chan - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG) -#define LTC2983_CHAN_RES_ADDR(chan) \ - (((chan - 1) * 4) + LTC2983_TEMP_RES_START_REG) +#define LTC2983_CHAN_ASSIGN_ADDR(chan) \ + ((((chan) - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG) +#define LTC2983_RESULT_ADDR(chan, base) \ + ((((chan) - 1) * 4) + (base)) #define LTC2983_THERMOCOUPLE_DIFF_MASK BIT(3) #define LTC2983_THERMOCOUPLE_SGL(x) \ FIELD_PREP(LTC2983_THERMOCOUPLE_DIFF_MASK, x) @@ -186,17 +188,44 @@ enum { LTC2983_SENSOR_SENSE_RESISTOR = 29, LTC2983_SENSOR_DIRECT_ADC = 30, LTC2983_SENSOR_ACTIVE_TEMP = 31, + /* Sensor types for some parts only; map to RTD_CUSTOM/THERMISTOR_CUSTOM in HW */ + LTC2983_SENSOR_COPPER_TRACE = 32, + LTC2983_SENSOR_LEAK_DETECTOR = 33, + LTC2983_SENSOR_NUM }; +/* Bitmask of sensor types supported by LTC2983/LTC2984 and derivatives */ +#define LTC2983_COMMON_SENSORS \ + (GENMASK_ULL(LTC2983_SENSOR_THERMOCOUPLE_CUSTOM, LTC2983_SENSOR_THERMOCOUPLE) | \ + GENMASK_ULL(LTC2983_SENSOR_RTD_CUSTOM, LTC2983_SENSOR_RTD) | \ + GENMASK_ULL(LTC2983_SENSOR_THERMISTOR_CUSTOM, LTC2983_SENSOR_THERMISTOR) | \ + BIT_ULL(LTC2983_SENSOR_DIODE) | \ + BIT_ULL(LTC2983_SENSOR_SENSE_RESISTOR) | \ + BIT_ULL(LTC2983_SENSOR_DIRECT_ADC)) + +/* Bitmask of sensor types supported by ADT7604 */ +#define ADT7604_SENSORS \ + (GENMASK_ULL(LTC2983_SENSOR_RTD_CUSTOM - 1, LTC2983_SENSOR_RTD) | \ + GENMASK_ULL(LTC2983_SENSOR_THERMISTOR_CUSTOM - 1, LTC2983_SENSOR_THERMISTOR) | \ + BIT_ULL(LTC2983_SENSOR_SENSE_RESISTOR) | \ + BIT_ULL(LTC2983_SENSOR_COPPER_TRACE) | \ + BIT_ULL(LTC2983_SENSOR_LEAK_DETECTOR)) + #define to_thermocouple(_sensor) \ container_of(_sensor, struct ltc2983_thermocouple, sensor) #define to_rtd(_sensor) \ container_of(_sensor, struct ltc2983_rtd, sensor) +#define to_copper_trace(_sensor) \ + container_of(_sensor, struct ltc2983_copper_trace, sensor) + #define to_thermistor(_sensor) \ container_of(_sensor, struct ltc2983_thermistor, sensor) +#define to_leak_detector(_sensor) \ + container_of(_sensor, struct ltc2983_leak_detector, sensor) + #define to_diode(_sensor) \ container_of(_sensor, struct ltc2983_diode, sensor) @@ -212,7 +241,7 @@ enum { struct ltc2983_chip_info { const char *name; unsigned int max_channels_nr; - bool has_temp; + u64 supported_sensors; bool has_eeprom; }; @@ -247,6 +276,8 @@ struct ltc2983_sensor { u32 chan; /* sensor type */ u32 type; + /* number of IIO channels this sensor produces */ + u8 n_iio_chan; }; struct ltc2983_custom_sensor { @@ -274,6 +305,25 @@ struct ltc2983_rtd { u32 rtd_curve; }; +struct ltc2983_copper_trace { + struct ltc2983_sensor sensor; + struct ltc2983_custom_sensor *custom; + u32 r_sense_chan; + u32 excitation_current; + /* selects the <1Ω variant: bits 17:0 of the channel word are zeroed, + * disabling excitation current and custom table fields (ADT7604 + * datasheet Table 26) + */ + bool is_sub_ohm; +}; + +struct ltc2983_leak_detector { + struct ltc2983_sensor sensor; + struct ltc2983_custom_sensor *custom; + u32 r_sense_chan; + u32 excitation_current; +}; + struct ltc2983_thermistor { struct ltc2983_sensor sensor; struct ltc2983_custom_sensor *custom; @@ -351,11 +401,17 @@ static int __ltc2983_chan_assign_common(struct ltc2983_data *st, const struct ltc2983_sensor *sensor, u32 chan_val) { - u32 reg = LTC2983_CHAN_START_ADDR(sensor->chan); + struct device *dev = &st->spi->dev; + u32 reg = LTC2983_CHAN_ASSIGN_ADDR(sensor->chan); + u32 hw_type = sensor->type; - chan_val |= LTC2983_CHAN_TYPE(sensor->type); - dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg, - chan_val); + if (hw_type == LTC2983_SENSOR_COPPER_TRACE) + hw_type = LTC2983_SENSOR_RTD_CUSTOM; + else if (hw_type == LTC2983_SENSOR_LEAK_DETECTOR) + hw_type = LTC2983_SENSOR_THERMISTOR_CUSTOM; + + chan_val |= LTC2983_CHAN_TYPE(hw_type); + dev_dbg(dev, "Assign reg:0x%04X, val:0x%08X\n", reg, chan_val); st->chan_val = cpu_to_be32(chan_val); return regmap_bulk_write(st->regmap, reg, &st->chan_val, sizeof(st->chan_val)); @@ -485,6 +541,14 @@ __ltc2983_custom_sensor_new(struct ltc2983_data *st, const struct fwnode_handle for (index = 0; index < n_entries; index++) { u64 temp = ((u64 *)new_custom->table)[index]; + /* + * Users specify plain coverage percentage (0-100). Convert + * to µK so __convert_to_raw() produces the correct hardware + * encoding: P + 273.15 K. + */ + if ((index % 2) != 0 && !strcmp(propname, "adi,custom-leak-detector")) + temp = temp * 1000000 + 273150000; + if ((index % 2) != 0) temp = __convert_to_raw(temp, 1024); else if (has_signed && (s64)temp < 0) @@ -578,6 +642,31 @@ static int ltc2983_rtd_assign_chan(struct ltc2983_data *st, return __ltc2983_chan_assign_common(st, sensor, chan_val); } +static int ltc2983_copper_trace_assign_chan(struct ltc2983_data *st, + const struct ltc2983_sensor *sensor) +{ + struct ltc2983_copper_trace *ct = to_copper_trace(sensor); + u32 chan_val; + + chan_val = LTC2983_CHAN_ASSIGN(ct->r_sense_chan); + /* Sensor config bits 21:18 must be 0b1001 (ADT7604 datasheet Table 26) */ + chan_val |= LTC2983_RTD_CFG(0x9); + + if (ct->is_sub_ohm) { + chan_val &= ~GENMASK(17, 0); + } else { + int ret; + + chan_val |= LTC2983_RTD_EXC_CURRENT(ct->excitation_current); + ret = __ltc2983_chan_custom_sensor_assign(st, ct->custom, + &chan_val); + if (ret) + return ret; + } + + return __ltc2983_chan_assign_common(st, sensor, chan_val); +} + static int ltc2983_thermistor_assign_chan(struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { @@ -601,6 +690,25 @@ static int ltc2983_thermistor_assign_chan(struct ltc2983_data *st, return __ltc2983_chan_assign_common(st, sensor, chan_val); } +static int ltc2983_leak_detector_assign_chan(struct ltc2983_data *st, + const struct ltc2983_sensor *sensor) +{ + struct ltc2983_leak_detector *ld = to_leak_detector(sensor); + u32 chan_val; + int ret; + + chan_val = LTC2983_CHAN_ASSIGN(ld->r_sense_chan); + /* bits 21:19 must be 0b001 (ADT7604 datasheet Table 38) */ + chan_val |= LTC2983_THERMISTOR_CFG(1); + chan_val |= LTC2983_THERMISTOR_EXC_CURRENT(ld->excitation_current); + + ret = __ltc2983_chan_custom_sensor_assign(st, ld->custom, &chan_val); + if (ret) + return ret; + + return __ltc2983_chan_assign_common(st, sensor, chan_val); +} + static int ltc2983_diode_assign_chan(struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { @@ -656,19 +764,26 @@ static struct ltc2983_sensor * ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { + struct device *dev = &st->spi->dev; struct ltc2983_thermocouple *thermo; u32 oc_current; int ret; - thermo = devm_kzalloc(&st->spi->dev, sizeof(*thermo), GFP_KERNEL); + thermo = devm_kzalloc(dev, sizeof(*thermo), GFP_KERNEL); if (!thermo) return ERR_PTR(-ENOMEM); if (fwnode_property_read_bool(child, "adi,single-ended")) thermo->sensor_config = LTC2983_THERMOCOUPLE_SGL(1); - ret = fwnode_property_read_u32(child, "adi,sensor-oc-current-microamp", &oc_current); - if (!ret) { + if (fwnode_property_present(child, "adi,sensor-oc-current-microamp")) { + ret = fwnode_property_read_u32(child, + "adi,sensor-oc-current-microamp", + &oc_current); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,sensor-oc-current-microamp\n"); + switch (oc_current) { case 10: thermo->sensor_config |= @@ -687,7 +802,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data LTC2983_THERMOCOUPLE_OC_CURR(3); break; default: - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + return dev_err_ptr_probe(dev, -EINVAL, "Invalid open circuit current:%u\n", oc_current); } @@ -697,8 +812,8 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data /* validate channel index */ if (!(thermo->sensor_config & LTC2983_THERMOCOUPLE_DIFF_MASK) && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chann:%d for differential thermocouple\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for differential thermocouple\n", sensor->chan); struct fwnode_handle *ref __free(fwnode_handle) = @@ -712,7 +827,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data * This would be caught later but we can just return * the error right away. */ - return dev_err_ptr_probe(&st->spi->dev, ret, + return dev_err_ptr_probe(dev, ret, "Property reg must be given\n"); } @@ -741,7 +856,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, struct ltc2983_rtd *rtd; int ret = 0; struct device *dev = &st->spi->dev; - u32 excitation_current = 0, n_wires = 0; + u32 excitation_current = 0, n_wires = 2; rtd = devm_kzalloc(dev, sizeof(*rtd), GFP_KERNEL); if (!rtd) @@ -758,8 +873,12 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, return dev_err_ptr_probe(dev, ret, "Property reg must be given\n"); - ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires); - if (!ret) { + if (fwnode_property_present(child, "adi,number-of-wires")) { + ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,number-of-wires\n"); + switch (n_wires) { case 2: rtd->sensor_config = LTC2983_RTD_N_WIRES(0); @@ -796,7 +915,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, /* * rtd channel indexes are a bit more complicated to validate. * For 4wire RTD with rotation, the channel selection cannot be - * >=19 since the chann + 1 is used in this configuration. + * >=19 since the channel + 1 is used in this configuration. * For 4wire RTDs with kelvin rsense, the rsense channel cannot be * <=1 since channel - 1 and channel - 2 are used. */ @@ -813,18 +932,18 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, (rtd->r_sense_chan <= min)) /* kelvin rsense*/ return dev_err_ptr_probe(dev, -EINVAL, - "Invalid rsense chann:%d to use in kelvin rsense\n", + "Invalid channel %d for kelvin rsense\n", rtd->r_sense_chan); if (sensor->chan < min || sensor->chan > max) return dev_err_ptr_probe(dev, -EINVAL, - "Invalid chann:%d for the rtd config\n", + "Invalid channel %d for RTD config\n", sensor->chan); } else { /* same as differential case */ if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chann:%d for RTD\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for RTD\n", sensor->chan); } @@ -841,12 +960,13 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, rtd->sensor.fault_handler = ltc2983_common_fault_handler; rtd->sensor.assign_chan = ltc2983_rtd_assign_chan; - ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp", - &excitation_current); - if (ret) { - /* default to 5uA */ - rtd->excitation_current = 1; - } else { + if (fwnode_property_present(child, "adi,excitation-current-microamp")) { + ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp", + &excitation_current); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,excitation-current-microamp\n"); + switch (excitation_current) { case 5: rtd->excitation_current = 0x01; @@ -873,13 +993,21 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, rtd->excitation_current = 0x08; break; default: - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + return dev_err_ptr_probe(dev, -EINVAL, "Invalid value for excitation current(%u)\n", excitation_current); } + } else { + /* default to 5uA */ + rtd->excitation_current = 1; } - fwnode_property_read_u32(child, "adi,rtd-curve", &rtd->rtd_curve); + if (fwnode_property_present(child, "adi,rtd-curve")) { + ret = fwnode_property_read_u32(child, "adi,rtd-curve", &rtd->rtd_curve); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,rtd-curve\n"); + } return &rtd->sensor; } @@ -922,8 +1050,8 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s /* validate channel index */ if (!(thermistor->sensor_config & LTC2983_THERMISTOR_DIFF_MASK) && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chann:%d for differential thermistor\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for differential thermistor\n", sensor->chan); /* check custom sensor */ @@ -949,22 +1077,18 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s thermistor->sensor.fault_handler = ltc2983_common_fault_handler; thermistor->sensor.assign_chan = ltc2983_thermistor_assign_chan; - ret = fwnode_property_read_u32(child, "adi,excitation-current-nanoamp", - &excitation_current); - if (ret) { - /* Auto range is not allowed for custom sensors */ - if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) - /* default to 1uA */ - thermistor->excitation_current = 0x03; - else - /* default to auto-range */ - thermistor->excitation_current = 0x0c; - } else { + if (fwnode_property_present(child, "adi,excitation-current-nanoamp")) { + ret = fwnode_property_read_u32(child, "adi,excitation-current-nanoamp", + &excitation_current); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,excitation-current-nanoamp\n"); + switch (excitation_current) { case 0: /* auto range */ if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + return dev_err_ptr_probe(dev, -EINVAL, "Auto Range not allowed for custom sensors\n"); thermistor->excitation_current = 0x0c; @@ -1003,24 +1127,222 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s thermistor->excitation_current = 0x0b; break; default: - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + return dev_err_ptr_probe(dev, -EINVAL, "Invalid value for excitation current(%u)\n", excitation_current); } + } else { + /* Auto range is not allowed for custom sensors */ + if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) + /* default to 1uA */ + thermistor->excitation_current = 0x03; + else + /* default to auto-range */ + thermistor->excitation_current = 0x0c; } return &thermistor->sensor; } +static struct ltc2983_sensor * +ltc2983_copper_trace_new(const struct fwnode_handle *child, struct ltc2983_data *st, + const struct ltc2983_sensor *sensor) +{ + struct device *dev = &st->spi->dev; + struct ltc2983_copper_trace *ct; + int ret; + + if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for copper trace\n", + sensor->chan); + + ct = devm_kzalloc(dev, sizeof(*ct), GFP_KERNEL); + if (!ct) + return ERR_PTR(-ENOMEM); + + struct fwnode_handle *ref __free(fwnode_handle) = + fwnode_find_reference(child, "adi,rsense-handle", 0); + if (IS_ERR(ref)) + return dev_err_cast_probe(dev, ref, + "Property adi,rsense-handle missing or invalid\n"); + + ret = fwnode_property_read_u32(ref, "reg", &ct->r_sense_chan); + if (ret) + return dev_err_ptr_probe(dev, ret, "Property reg must be given\n"); + + ct->is_sub_ohm = fwnode_property_read_bool(child, "adi,copper-trace-sub-ohm"); + + if (ct->is_sub_ohm && fwnode_property_present(child, "adi,custom-copper-trace")) + return dev_err_ptr_probe(dev, -EINVAL, + "sub-ohm copper trace cannot have a custom table\n"); + + if (!ct->is_sub_ohm) { + u32 excitation_current = 0; + + if (!fwnode_property_present(child, "adi,custom-copper-trace")) + return dev_err_ptr_probe(dev, -EINVAL, + "adi,custom-copper-trace is required for >1 ohm copper trace\n"); + + ct->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-copper-trace", + false, 2048, false); + if (IS_ERR(ct->custom)) + return ERR_CAST(ct->custom); + + if (fwnode_property_present(child, "adi,excitation-current-microamp")) { + ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp", + &excitation_current); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,excitation-current-microamp\n"); + + switch (excitation_current) { + case 5: + ct->excitation_current = 0x01; + break; + case 10: + ct->excitation_current = 0x02; + break; + case 25: + ct->excitation_current = 0x03; + break; + case 50: + ct->excitation_current = 0x04; + break; + case 100: + ct->excitation_current = 0x05; + break; + case 250: + ct->excitation_current = 0x06; + break; + case 500: + ct->excitation_current = 0x07; + break; + case 1000: + ct->excitation_current = 0x08; + break; + default: + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid value for excitation current(%u)\n", + excitation_current); + } + } else { + /* default to 1mA per datasheet recommendation for copper trace */ + ct->excitation_current = 0x08; + } + } + + ct->sensor.fault_handler = ltc2983_common_fault_handler; + ct->sensor.assign_chan = ltc2983_copper_trace_assign_chan; + if (ct->is_sub_ohm) + ct->sensor.n_iio_chan = 1; + else + ct->sensor.n_iio_chan = 2; + + return &ct->sensor; +} + +static struct ltc2983_sensor * +ltc2983_leak_detector_new(const struct fwnode_handle *child, struct ltc2983_data *st, + const struct ltc2983_sensor *sensor) +{ + struct device *dev = &st->spi->dev; + struct ltc2983_leak_detector *ld; + int ret; + u32 excitation_current = 0; + + if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for leak detector\n", + sensor->chan); + + ld = devm_kzalloc(dev, sizeof(*ld), GFP_KERNEL); + if (!ld) + return ERR_PTR(-ENOMEM); + + struct fwnode_handle *ref __free(fwnode_handle) = + fwnode_find_reference(child, "adi,rsense-handle", 0); + if (IS_ERR(ref)) + return dev_err_cast_probe(dev, ref, + "Property adi,rsense-handle missing or invalid\n"); + + ret = fwnode_property_read_u32(ref, "reg", &ld->r_sense_chan); + if (ret) + return dev_err_ptr_probe(dev, ret, + "rsense channel must be configured\n"); + + if (!fwnode_property_present(child, "adi,custom-leak-detector")) + return dev_err_ptr_probe(dev, -EINVAL, + "adi,custom-leak-detector is required for leak detectors\n"); + + ld->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-leak-detector", + false, 16, false); + if (IS_ERR(ld->custom)) + return ERR_CAST(ld->custom); + + ret = fwnode_property_read_u32(child, "adi,excitation-current-nanoamp", + &excitation_current); + if (ret) + return dev_err_ptr_probe(dev, ret, + "adi,excitation-current-nanoamp is required for leak detectors\n"); + + switch (excitation_current) { + case 250: + ld->excitation_current = 0x01; + break; + case 500: + ld->excitation_current = 0x02; + break; + case 1000: + ld->excitation_current = 0x03; + break; + case 5000: + ld->excitation_current = 0x04; + break; + case 10000: + ld->excitation_current = 0x05; + break; + case 25000: + ld->excitation_current = 0x06; + break; + case 50000: + ld->excitation_current = 0x07; + break; + case 100000: + ld->excitation_current = 0x08; + break; + case 250000: + ld->excitation_current = 0x09; + break; + case 500000: + ld->excitation_current = 0x0a; + break; + case 1000000: + ld->excitation_current = 0x0b; + break; + default: + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid value for excitation current(%u)\n", + excitation_current); + } + + ld->sensor.fault_handler = ltc2983_common_fault_handler; + ld->sensor.assign_chan = ltc2983_leak_detector_assign_chan; + ld->sensor.n_iio_chan = 2; + + return &ld->sensor; +} + static struct ltc2983_sensor * ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { + struct device *dev = &st->spi->dev; struct ltc2983_diode *diode; u32 temp = 0, excitation_current = 0; int ret; - diode = devm_kzalloc(&st->spi->dev, sizeof(*diode), GFP_KERNEL); + diode = devm_kzalloc(dev, sizeof(*diode), GFP_KERNEL); if (!diode) return ERR_PTR(-ENOMEM); @@ -1036,17 +1358,21 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data * /* validate channel index */ if (!(diode->sensor_config & LTC2983_DIODE_DIFF_MASK) && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chann:%d for differential thermistor\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for differential diode\n", sensor->chan); /* set common parameters */ diode->sensor.fault_handler = ltc2983_common_fault_handler; diode->sensor.assign_chan = ltc2983_diode_assign_chan; - ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp", - &excitation_current); - if (!ret) { + if (fwnode_property_present(child, "adi,excitation-current-microamp")) { + ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp", + &excitation_current); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,excitation-current-microamp\n"); + switch (excitation_current) { case 10: diode->excitation_current = 0x00; @@ -1061,13 +1387,18 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data * diode->excitation_current = 0x03; break; default: - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + return dev_err_ptr_probe(dev, -EINVAL, "Invalid value for excitation current(%u)\n", excitation_current); } } - fwnode_property_read_u32(child, "adi,ideal-factor-value", &temp); + if (fwnode_property_present(child, "adi,ideal-factor-value")) { + ret = fwnode_property_read_u32(child, "adi,ideal-factor-value", &temp); + if (ret) + return dev_err_ptr_probe(dev, ret, + "Failed to read adi,ideal-factor-value\n"); + } /* 2^20 resolution */ diode->ideal_factor_value = __convert_to_raw(temp, 1048576); @@ -1079,23 +1410,24 @@ static struct ltc2983_sensor *ltc2983_r_sense_new(struct fwnode_handle *child, struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { + struct device *dev = &st->spi->dev; struct ltc2983_rsense *rsense; int ret; u32 temp; - rsense = devm_kzalloc(&st->spi->dev, sizeof(*rsense), GFP_KERNEL); + rsense = devm_kzalloc(dev, sizeof(*rsense), GFP_KERNEL); if (!rsense) return ERR_PTR(-ENOMEM); /* validate channel index */ if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chann:%d for r_sense\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for r_sense\n", sensor->chan); ret = fwnode_property_read_u32(child, "adi,rsense-val-milli-ohms", &temp); if (ret) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + return dev_err_ptr_probe(dev, -EINVAL, "Property adi,rsense-val-milli-ohms missing\n"); /* * Times 1000 because we have milli-ohms and __convert_to_raw @@ -1115,9 +1447,10 @@ static struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child, struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { + struct device *dev = &st->spi->dev; struct ltc2983_adc *adc; - adc = devm_kzalloc(&st->spi->dev, sizeof(*adc), GFP_KERNEL); + adc = devm_kzalloc(dev, sizeof(*adc), GFP_KERNEL); if (!adc) return ERR_PTR(-ENOMEM); @@ -1125,8 +1458,8 @@ static struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child, adc->single_ended = true; if (!adc->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chan:%d for differential adc\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for differential ADC\n", sensor->chan); /* set common parameters */ @@ -1140,9 +1473,10 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child, struct ltc2983_data *st, const struct ltc2983_sensor *sensor) { + struct device *dev = &st->spi->dev; struct ltc2983_temp *temp; - temp = devm_kzalloc(&st->spi->dev, sizeof(*temp), GFP_KERNEL); + temp = devm_kzalloc(dev, sizeof(*temp), GFP_KERNEL); if (!temp) return ERR_PTR(-ENOMEM); @@ -1150,8 +1484,8 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child, temp->single_ended = true; if (!temp->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) - return dev_err_ptr_probe(&st->spi->dev, -EINVAL, - "Invalid chan:%d for differential temp\n", + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid channel %d for differential temp\n", sensor->chan); temp->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-temp", @@ -1167,22 +1501,23 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child, } static int ltc2983_chan_read(struct ltc2983_data *st, - const struct ltc2983_sensor *sensor, int *val) + const struct ltc2983_sensor *sensor, + u32 base_reg, int *val) { + struct device *dev = &st->spi->dev; u32 start_conversion = 0; int ret; unsigned long time; start_conversion = LTC2983_STATUS_START(true); start_conversion |= LTC2983_STATUS_CHAN_SEL(sensor->chan); - dev_dbg(&st->spi->dev, "Start conversion on chan:%d, status:%02X\n", + dev_dbg(dev, "Start conversion on channel:%d, status:%02X\n", sensor->chan, start_conversion); + reinit_completion(&st->completion); /* start conversion */ ret = regmap_write(st->regmap, LTC2983_STATUS_REG, start_conversion); if (ret) return ret; - - reinit_completion(&st->completion); /* * wait for conversion to complete. * 300 ms should be more than enough to complete the conversion. @@ -1192,20 +1527,30 @@ static int ltc2983_chan_read(struct ltc2983_data *st, time = wait_for_completion_timeout(&st->completion, msecs_to_jiffies(300)); if (!time) { - dev_warn(&st->spi->dev, "Conversion timed out\n"); + dev_warn(dev, "Conversion timed out\n"); return -ETIMEDOUT; } /* read the converted data */ - ret = regmap_bulk_read(st->regmap, LTC2983_CHAN_RES_ADDR(sensor->chan), + ret = regmap_bulk_read(st->regmap, LTC2983_RESULT_ADDR(sensor->chan, base_reg), &st->temp, sizeof(st->temp)); if (ret) return ret; *val = __be32_to_cpu(st->temp); + if (base_reg == ADT7604_RES_RES_START_REG) { + /* + * Resistance result register gives a plain unsigned value, + * D31 is always 0, no valid bit, no fault bits. Read bits[30:0] + * directly — the temperature result format does not apply here. + */ + *val &= GENMASK(30, 0); + return 0; + } + if (!(LTC2983_RES_VALID_MASK & *val)) { - dev_err(&st->spi->dev, "Invalid conversion detected\n"); + dev_err(dev, "Invalid conversion detected\n"); return -EIO; } @@ -1222,19 +1567,28 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct ltc2983_data *st = iio_priv(indio_dev); + struct device *dev = &st->spi->dev; int ret; /* sanity check */ if (chan->address >= st->num_channels) { - dev_err(&st->spi->dev, "Invalid chan address:%ld", - chan->address); + dev_err(dev, "Invalid channel address: %ld\n", chan->address); return -EINVAL; } switch (mask) { case IIO_CHAN_INFO_RAW: mutex_lock(&st->lock); - ret = ltc2983_chan_read(st, st->sensors[chan->address], val); + switch (chan->type) { + case IIO_RESISTANCE: + ret = ltc2983_chan_read(st, st->sensors[chan->address], + ADT7604_RES_RES_START_REG, val); + break; + default: + ret = ltc2983_chan_read(st, st->sensors[chan->address], + LTC2983_TEMP_RES_START_REG, val); + break; + } mutex_unlock(&st->lock); return ret ?: IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -1251,6 +1605,13 @@ static int ltc2983_read_raw(struct iio_dev *indio_dev, /* 2^21 */ *val2 = 2097152; return IIO_VAL_FRACTIONAL; + case IIO_RESISTANCE: + case IIO_COVERAGE: + /* value in ohm/percent */ + *val = 1; + /* 2^10 */ + *val2 = 1024; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } @@ -1303,7 +1664,7 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) st->num_channels = device_get_child_node_count(dev); if (!st->num_channels) - return dev_err_probe(&st->spi->dev, -EINVAL, + return dev_err_probe(dev, -EINVAL, "At least one channel must be given!\n"); st->sensors = devm_kcalloc(dev, st->num_channels, sizeof(*st->sensors), @@ -1311,7 +1672,7 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) if (!st->sensors) return -ENOMEM; - st->iio_channels = st->num_channels; + st->iio_channels = 0; device_for_each_child_node_scoped(dev, child) { struct ltc2983_sensor sensor; @@ -1324,14 +1685,14 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) if (sensor.chan < LTC2983_MIN_CHANNELS_NR || sensor.chan > st->info->max_channels_nr) return dev_err_probe(dev, -EINVAL, - "chan:%d must be from %u to %u\n", + "channel:%d must be from %u to %u\n", sensor.chan, LTC2983_MIN_CHANNELS_NR, st->info->max_channels_nr); if (channel_avail_mask & BIT(sensor.chan)) return dev_err_probe(dev, -EINVAL, - "chan:%d already in use\n", + "channel:%d already in use\n", sensor.chan); ret = fwnode_property_read_u32(child, "adi,sensor-type", &sensor.type); @@ -1339,7 +1700,13 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) return dev_err_probe(dev, ret, "adi,sensor-type property must given for child nodes\n"); - dev_dbg(dev, "Create new sensor, type %u, chann %u", + if (sensor.type >= LTC2983_SENSOR_NUM || + !(st->info->supported_sensors & BIT_ULL(sensor.type))) + return dev_err_probe(dev, -EINVAL, + "sensor type %d not supported on %s\n", + sensor.type, st->info->name); + + dev_dbg(dev, "Create new sensor, type %u, channel %u", sensor.type, sensor.chan); if (sensor.type >= LTC2983_SENSOR_THERMOCOUPLE && @@ -1359,13 +1726,14 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) } else if (sensor.type == LTC2983_SENSOR_SENSE_RESISTOR) { st->sensors[chan] = ltc2983_r_sense_new(child, st, &sensor); - /* don't add rsense to iio */ - st->iio_channels--; } else if (sensor.type == LTC2983_SENSOR_DIRECT_ADC) { st->sensors[chan] = ltc2983_adc_new(child, st, &sensor); - } else if (st->info->has_temp && - sensor.type == LTC2983_SENSOR_ACTIVE_TEMP) { + } else if (sensor.type == LTC2983_SENSOR_ACTIVE_TEMP) { st->sensors[chan] = ltc2983_temp_new(child, st, &sensor); + } else if (sensor.type == LTC2983_SENSOR_COPPER_TRACE) { + st->sensors[chan] = ltc2983_copper_trace_new(child, st, &sensor); + } else if (sensor.type == LTC2983_SENSOR_LEAK_DETECTOR) { + st->sensors[chan] = ltc2983_leak_detector_new(child, st, &sensor); } else { return dev_err_probe(dev, -EINVAL, "Unknown sensor type %d\n", @@ -1380,6 +1748,16 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) st->sensors[chan]->chan = sensor.chan; st->sensors[chan]->type = sensor.type; + /* + * Dedicated functions set n_iio_chan themselves; for all other + * sensor types rsense produces 0 channels, everything else 1. + */ + if (!st->sensors[chan]->n_iio_chan) { + if (sensor.type != LTC2983_SENSOR_SENSE_RESISTOR) + st->sensors[chan]->n_iio_chan = 1; + } + st->iio_channels += st->sensors[chan]->n_iio_chan; + channel_avail_mask |= BIT(sensor.chan); chan++; } @@ -1391,6 +1769,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd, unsigned int wait_time, unsigned int status_reg, unsigned long status_fail_mask) { + struct device *dev = &st->spi->dev; unsigned long time; unsigned int val; int ret; @@ -1410,7 +1789,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd, time = wait_for_completion_timeout(&st->completion, msecs_to_jiffies(wait_time)); if (!time) - return dev_err_probe(&st->spi->dev, -ETIMEDOUT, + return dev_err_probe(dev, -ETIMEDOUT, "EEPROM command timed out\n"); ret = regmap_read(st->regmap, status_reg, &val); @@ -1418,7 +1797,7 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd, return ret; if (val & status_fail_mask) - return dev_err_probe(&st->spi->dev, -EINVAL, + return dev_err_probe(dev, -EINVAL, "EEPROM command failed: 0x%02X\n", val); return 0; @@ -1426,7 +1805,9 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd, static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) { - u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0, status; + struct device *dev = &st->spi->dev; + u32 iio_chan_t = 0, iio_chan_v = 0, iio_chan_r = 0, iio_chan_c = 0; + u32 chan, iio_idx = 0, status; int ret; /* make sure the device is up: start bit (7) is 0 and done bit (6) is 1 */ @@ -1434,8 +1815,7 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) LTC2983_STATUS_UP(status) == 1, 25000, 25000 * 10); if (ret) - return dev_err_probe(&st->spi->dev, ret, - "Device startup timed out\n"); + return dev_err_probe(dev, ret, "Device startup timed out\n"); ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG, LTC2983_NOTCH_FREQ_MASK, @@ -1474,12 +1854,33 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) continue; /* assign iio channel */ - if (st->sensors[chan]->type != LTC2983_SENSOR_DIRECT_ADC) { - chan_type = IIO_TEMP; - iio_chan = &iio_chan_t; - } else { + switch (st->sensors[chan]->type) { + case LTC2983_SENSOR_COPPER_TRACE: + if (st->sensors[chan]->n_iio_chan == 1) { + /* sub-ohm copper traces produce only a resistance result */ + st->iio_chan[iio_idx++] = + LTC2983_CHAN(IIO_RESISTANCE, iio_chan_r++, chan); + } else { + st->iio_chan[iio_idx++] = + LTC2983_CHAN(IIO_TEMP, iio_chan_t++, chan); + st->iio_chan[iio_idx++] = + LTC2983_CHAN(IIO_RESISTANCE, iio_chan_r++, chan); + } + continue; + case LTC2983_SENSOR_LEAK_DETECTOR: + st->iio_chan[iio_idx++] = + LTC2983_CHAN(IIO_COVERAGE, iio_chan_c++, chan); + st->iio_chan[iio_idx++] = + LTC2983_CHAN(IIO_RESISTANCE, iio_chan_r++, chan); + continue; + case LTC2983_SENSOR_DIRECT_ADC: chan_type = IIO_VOLTAGE; iio_chan = &iio_chan_v; + break; + default: + chan_type = IIO_TEMP; + iio_chan = &iio_chan_t; + break; } /* @@ -1496,6 +1897,7 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) static const struct regmap_range ltc2983_reg_ranges[] = { regmap_reg_range(LTC2983_STATUS_REG, LTC2983_STATUS_REG), regmap_reg_range(LTC2983_TEMP_RES_START_REG, LTC2983_TEMP_RES_END_REG), + regmap_reg_range(ADT7604_RES_RES_START_REG, ADT7604_RES_RES_END_REG), regmap_reg_range(LTC2983_EEPROM_KEY_REG, LTC2983_EEPROM_KEY_REG), regmap_reg_range(LTC2983_EEPROM_READ_STATUS_REG, LTC2983_EEPROM_READ_STATUS_REG), @@ -1535,12 +1937,13 @@ static const struct iio_info ltc2983_iio_info = { static int ltc2983_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct ltc2983_data *st; struct iio_dev *indio_dev; struct gpio_desc *gpio; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -1552,7 +1955,7 @@ static int ltc2983_probe(struct spi_device *spi) st->regmap = devm_regmap_init_spi(spi, <c2983_regmap_config); if (IS_ERR(st->regmap)) - return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), + return dev_err_probe(dev, PTR_ERR(st->regmap), "Failed to initialize regmap\n"); mutex_init(&st->lock); @@ -1565,11 +1968,11 @@ static int ltc2983_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_regulator_get_enable(&spi->dev, "vdd"); + ret = devm_regulator_get_enable(dev, "vdd"); if (ret) return ret; - gpio = devm_gpiod_get_optional(&st->spi->dev, "reset", GPIOD_OUT_HIGH); + gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(gpio)) return PTR_ERR(gpio); @@ -1579,7 +1982,7 @@ static int ltc2983_probe(struct spi_device *spi) gpiod_set_value_cansleep(gpio, 0); } - st->iio_chan = devm_kzalloc(&spi->dev, + st->iio_chan = devm_kzalloc(dev, st->iio_channels * sizeof(*st->iio_chan), GFP_KERNEL); if (!st->iio_chan) @@ -1589,11 +1992,10 @@ static int ltc2983_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler, + ret = devm_request_irq(dev, spi->irq, ltc2983_irq_handler, IRQF_TRIGGER_RISING, st->info->name, st); if (ret) - return dev_err_probe(&spi->dev, ret, - "failed to request an irq\n"); + return dev_err_probe(dev, ret, "failed to request an irq\n"); if (st->info->has_eeprom) { ret = ltc2983_eeprom_cmd(st, LTC2983_EEPROM_WRITE_CMD, @@ -1610,7 +2012,7 @@ static int ltc2983_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = <c2983_iio_info; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static int ltc2983_resume(struct device *dev) @@ -1634,32 +2036,42 @@ static int ltc2983_suspend(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(ltc2983_pm_ops, ltc2983_suspend, ltc2983_resume); +static const struct ltc2983_chip_info adt7604_chip_info_data = { + .name = "adt7604", + .max_channels_nr = 20, + .has_eeprom = true, + .supported_sensors = ADT7604_SENSORS, +}; + static const struct ltc2983_chip_info ltc2983_chip_info_data = { .name = "ltc2983", .max_channels_nr = 20, + .supported_sensors = LTC2983_COMMON_SENSORS, }; static const struct ltc2983_chip_info ltc2984_chip_info_data = { .name = "ltc2984", .max_channels_nr = 20, .has_eeprom = true, + .supported_sensors = LTC2983_COMMON_SENSORS, }; static const struct ltc2983_chip_info ltc2986_chip_info_data = { .name = "ltc2986", .max_channels_nr = 10, - .has_temp = true, .has_eeprom = true, + .supported_sensors = LTC2983_COMMON_SENSORS | BIT_ULL(LTC2983_SENSOR_ACTIVE_TEMP), }; static const struct ltc2983_chip_info ltm2985_chip_info_data = { .name = "ltm2985", .max_channels_nr = 10, - .has_temp = true, .has_eeprom = true, + .supported_sensors = LTC2983_COMMON_SENSORS | BIT_ULL(LTC2983_SENSOR_ACTIVE_TEMP), }; static const struct spi_device_id ltc2983_id_table[] = { + { "adt7604", (kernel_ulong_t)&adt7604_chip_info_data }, { "ltc2983", (kernel_ulong_t)<c2983_chip_info_data }, { "ltc2984", (kernel_ulong_t)<c2984_chip_info_data }, { "ltc2986", (kernel_ulong_t)<c2986_chip_info_data }, @@ -1669,6 +2081,7 @@ static const struct spi_device_id ltc2983_id_table[] = { MODULE_DEVICE_TABLE(spi, ltc2983_id_table); static const struct of_device_id ltc2983_of_match[] = { + { .compatible = "adi,adt7604", .data = &adt7604_chip_info_data }, { .compatible = "adi,ltc2983", .data = <c2983_chip_info_data }, { .compatible = "adi,ltc2984", .data = <c2984_chip_info_data }, { .compatible = "adi,ltc2986", .data = <c2986_chip_info_data }, diff --git a/drivers/iio/temperature/max30208.c b/drivers/iio/temperature/max30208.c index 720469f9dc36..6172abc6d533 100644 --- a/drivers/iio/temperature/max30208.c +++ b/drivers/iio/temperature/max30208.c @@ -218,7 +218,7 @@ static int max30208_probe(struct i2c_client *i2c) } static const struct i2c_device_id max30208_id_table[] = { - { "max30208" }, + { .name = "max30208" }, { } }; MODULE_DEVICE_TABLE(i2c, max30208_id_table); diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index 205939680fd4..e898f56d1196 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -277,8 +277,8 @@ static const struct spi_device_id maxim_thermocouple_id[] = { MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); static const struct of_device_id maxim_thermocouple_of_match[] = { - { .compatible = "maxim,max6675" }, - { .compatible = "maxim,max31855" }, + { .compatible = "maxim,max6675" }, + { .compatible = "maxim,max31855" }, { .compatible = "maxim,max31855k" }, { .compatible = "maxim,max31855j" }, { .compatible = "maxim,max31855n" }, @@ -286,7 +286,7 @@ static const struct of_device_id maxim_thermocouple_of_match[] = { { .compatible = "maxim,max31855t" }, { .compatible = "maxim,max31855e" }, { .compatible = "maxim,max31855r" }, - { }, + { }, }; MODULE_DEVICE_TABLE(of, maxim_thermocouple_of_match); diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c index 69baf654c9c0..5c1c959277b8 100644 --- a/drivers/iio/temperature/mcp9600.c +++ b/drivers/iio/temperature/mcp9600.c @@ -551,8 +551,8 @@ static const struct mcp_chip_info mcp9601_chip_info = { }; static const struct i2c_device_id mcp9600_id[] = { - { "mcp9600", .driver_data = (kernel_ulong_t)&mcp9600_chip_info }, - { "mcp9601", .driver_data = (kernel_ulong_t)&mcp9601_chip_info }, + { .name = "mcp9600", .driver_data = (kernel_ulong_t)&mcp9600_chip_info }, + { .name = "mcp9601", .driver_data = (kernel_ulong_t)&mcp9601_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, mcp9600_id); diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index 1ad21b73e1b4..342f2e4f80d1 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -699,8 +699,8 @@ static const struct mlx_chip_info mlx90615_chip_info = { }; static const struct i2c_device_id mlx90614_id[] = { - { "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info }, - { "mlx90615", .driver_data = (kernel_ulong_t)&mlx90615_chip_info }, + { .name = "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info }, + { .name = "mlx90615", .driver_data = (kernel_ulong_t)&mlx90615_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, mlx90614_id); diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index b44f7036c2cc..3ab7687c4146 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -1276,7 +1276,7 @@ static int mlx90632_probe(struct i2c_client *client) } static const struct i2c_device_id mlx90632_id[] = { - { "mlx90632" }, + { .name = "mlx90632" }, { } }; MODULE_DEVICE_TABLE(i2c, mlx90632_id); diff --git a/drivers/iio/temperature/mlx90635.c b/drivers/iio/temperature/mlx90635.c index 1c8948ca54df..8c8bdab106dd 100644 --- a/drivers/iio/temperature/mlx90635.c +++ b/drivers/iio/temperature/mlx90635.c @@ -1026,7 +1026,7 @@ static int mlx90635_probe(struct i2c_client *client) } static const struct i2c_device_id mlx90635_id[] = { - { "mlx90635" }, + { .name = "mlx90635" }, { } }; MODULE_DEVICE_TABLE(i2c, mlx90635_id); diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index d8d8c8936d17..43400666fce2 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -350,7 +350,7 @@ static int tmp006_probe(struct i2c_client *client) data->drdy_trig->ops = &tmp006_trigger_ops; iio_trigger_set_drvdata(data->drdy_trig, indio_dev); - ret = iio_trigger_register(data->drdy_trig); + ret = devm_iio_trigger_register(&client->dev, data->drdy_trig); if (ret) return ret; @@ -391,7 +391,7 @@ static const struct of_device_id tmp006_of_match[] = { MODULE_DEVICE_TABLE(of, tmp006_of_match); static const struct i2c_device_id tmp006_id[] = { - { "tmp006" }, + { .name = "tmp006" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp006_id); diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index 043283b02c4d..d9eea06ff540 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -563,7 +563,7 @@ static const struct of_device_id tmp007_of_match[] = { MODULE_DEVICE_TABLE(of, tmp007_of_match); static const struct i2c_device_id tmp007_id[] = { - { "tmp007" }, + { .name = "tmp007" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp007_id); diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c index 8972083d903a..6bc18616ad15 100644 --- a/drivers/iio/temperature/tmp117.c +++ b/drivers/iio/temperature/tmp117.c @@ -209,8 +209,8 @@ static const struct of_device_id tmp117_of_match[] = { MODULE_DEVICE_TABLE(of, tmp117_of_match); static const struct i2c_device_id tmp117_id[] = { - { "tmp116", (kernel_ulong_t)&tmp116_channels_info }, - { "tmp117", (kernel_ulong_t)&tmp117_channels_info }, + { .name = "tmp116", .driver_data = (kernel_ulong_t)&tmp116_channels_info }, + { .name = "tmp117", .driver_data = (kernel_ulong_t)&tmp117_channels_info }, { } }; MODULE_DEVICE_TABLE(i2c, tmp117_id); diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index 104dd45598b0..31ba2c941486 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -206,7 +206,7 @@ static int tsys01_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tsys01_id[] = { - { "tsys01" }, + { .name = "tsys01" }, { } }; MODULE_DEVICE_TABLE(i2c, tsys01_id); diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c index 0cad27205667..3ef72347456e 100644 --- a/drivers/iio/temperature/tsys02d.c +++ b/drivers/iio/temperature/tsys02d.c @@ -168,7 +168,7 @@ static int tsys02d_probe(struct i2c_client *client) } static const struct i2c_device_id tsys02d_id[] = { - { "tsys02d" }, + { .name = "tsys02d" }, { } }; MODULE_DEVICE_TABLE(i2c, tsys02d_id); diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig index 7ecb69725b1d..52899c22d57c 100644 --- a/drivers/iio/trigger/Kconfig +++ b/drivers/iio/trigger/Kconfig @@ -16,15 +16,6 @@ config IIO_HRTIMER_TRIGGER To compile this driver as a module, choose M here: the module will be called iio-trig-hrtimer. -config IIO_INTERRUPT_TRIGGER - tristate "Generic interrupt trigger" - help - Provides support for using an interrupt of any type as an IIO - trigger. This may be provided by a gpio driver for example. - - To compile this driver as a module, choose M here: the - module will be called iio-trig-interrupt. - config IIO_STM32_LPTIMER_TRIGGER tristate "STM32 Low-Power Timer Trigger" depends on MFD_STM32_LPTIMER || COMPILE_TEST diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile index f3d11acb8a0b..fc1fd5661c94 100644 --- a/drivers/iio/trigger/Makefile +++ b/drivers/iio/trigger/Makefile @@ -6,7 +6,6 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o -obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o obj-$(CONFIG_IIO_STM32_LPTIMER_TRIGGER) += stm32-lptimer-trigger.o obj-$(CONFIG_IIO_STM32_TIMER_TRIGGER) += stm32-timer-trigger.o obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c deleted file mode 100644 index a100c2e3a0d9..000000000000 --- a/drivers/iio/trigger/iio-trig-interrupt.c +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Industrial I/O - generic interrupt based trigger support - * - * Copyright (c) 2008-2013 Jonathan Cameron - */ - -#include -#include -#include -#include -#include - -#include -#include - - -struct iio_interrupt_trigger_info { - unsigned int irq; -}; - -static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private) -{ - iio_trigger_poll(private); - return IRQ_HANDLED; -} - -static int iio_interrupt_trigger_probe(struct platform_device *pdev) -{ - struct iio_interrupt_trigger_info *trig_info; - struct iio_trigger *trig; - unsigned long irqflags; - struct resource *irq_res; - int irq, ret = 0; - - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - - if (irq_res == NULL) - return -ENODEV; - - irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED; - - irq = irq_res->start; - - trig = iio_trigger_alloc(NULL, "irqtrig%d", irq); - if (!trig) { - ret = -ENOMEM; - goto error_ret; - } - - trig_info = kzalloc_obj(*trig_info); - if (!trig_info) { - ret = -ENOMEM; - goto error_free_trigger; - } - iio_trigger_set_drvdata(trig, trig_info); - trig_info->irq = irq; - ret = request_irq(irq, iio_interrupt_trigger_poll, - irqflags, trig->name, trig); - if (ret) { - dev_err(&pdev->dev, - "request IRQ-%d failed", irq); - goto error_free_trig_info; - } - - ret = iio_trigger_register(trig); - if (ret) - goto error_release_irq; - platform_set_drvdata(pdev, trig); - - return 0; - -/* First clean up the partly allocated trigger */ -error_release_irq: - free_irq(irq, trig); -error_free_trig_info: - kfree(trig_info); -error_free_trigger: - iio_trigger_free(trig); -error_ret: - return ret; -} - -static void iio_interrupt_trigger_remove(struct platform_device *pdev) -{ - struct iio_trigger *trig; - struct iio_interrupt_trigger_info *trig_info; - - trig = platform_get_drvdata(pdev); - trig_info = iio_trigger_get_drvdata(trig); - iio_trigger_unregister(trig); - free_irq(trig_info->irq, trig); - kfree(trig_info); - iio_trigger_free(trig); -} - -static struct platform_driver iio_interrupt_trigger_driver = { - .probe = iio_interrupt_trigger_probe, - .remove = iio_interrupt_trigger_remove, - .driver = { - .name = "iio_interrupt_trigger", - }, -}; - -module_platform_driver(iio_interrupt_trigger_driver); - -MODULE_AUTHOR("Jonathan Cameron "); -MODULE_DESCRIPTION("Interrupt trigger for the iio subsystem"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 8569b78a1851..ce572c62f58f 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -432,7 +432,7 @@ struct icc_path *devm_of_icc_get(struct device *dev, const char *name) return ERR_PTR(-ENOMEM); path = of_icc_get(dev, name); - if (!IS_ERR(path)) { + if (!IS_ERR_OR_NULL(path)) { *ptr = path; devres_add(dev, ptr); } else { diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 786b4eda44b4..5b8a094ca4ed 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -9,26 +9,38 @@ config INTERCONNECT_QCOM_BCM_VOTER tristate config INTERCONNECT_QCOM_ELIZA - tristate "Qualcomm Eliza interconnect driver" - depends on INTERCONNECT_QCOM_RPMH_POSSIBLE - select INTERCONNECT_QCOM_RPMH - select INTERCONNECT_QCOM_BCM_VOTER - help - This is a driver for the Qualcomm Network-on-Chip on Eliza-based - platforms. + tristate "Qualcomm Eliza interconnect driver" + depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER + help + This is a driver for the Qualcomm Network-on-Chip on Eliza-based + platforms. config INTERCONNECT_QCOM_GLYMUR - tristate "Qualcomm Glymur interconnect driver" - depends on INTERCONNECT_QCOM_RPMH_POSSIBLE - select INTERCONNECT_QCOM_RPMH - select INTERCONNECT_QCOM_BCM_VOTER - help - This is a driver for the Qualcomm Network-on-Chip on glymur-based - platforms. + tristate "Qualcomm Glymur interconnect driver" + depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER + help + This is a driver for the Qualcomm Network-on-Chip on glymur-based + platforms. + +config INTERCONNECT_QCOM_HAWI + tristate "Qualcomm HAWI interconnect driver" + depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER + help + This is a driver for the Qualcomm Network-on-Chip on hawi-based + platforms. config INTERCONNECT_QCOM_KAANAPALI tristate "Qualcomm Kaanapali interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -39,6 +51,7 @@ config INTERCONNECT_QCOM_MSM8909 tristate "Qualcomm MSM8909 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on msm8909-based @@ -75,6 +88,7 @@ config INTERCONNECT_QCOM_MSM8953 tristate "Qualcomm MSM8953 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on msm8953-based @@ -84,6 +98,7 @@ config INTERCONNECT_QCOM_MSM8974 tristate "Qualcomm MSM8974 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on msm8974-based @@ -93,6 +108,7 @@ config INTERCONNECT_QCOM_MSM8976 tristate "Qualcomm MSM8976 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on msm8976-based @@ -102,14 +118,27 @@ config INTERCONNECT_QCOM_MSM8996 tristate "Qualcomm MSM8996 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on msm8996-based platforms. +config INTERCONNECT_QCOM_NORD + tristate "Qualcomm Nord interconnect driver" + depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER + help + This is a driver for the Qualcomm Network-on-Chip on Nord-based + platforms. The topology consists of several NoCs controlled by + the RPMh hardware and communicates via Bus Clock Manager (BCM) + through the Resource State Coordinator (RSC). + config INTERCONNECT_QCOM_OSM_L3 tristate "Qualcomm OSM L3 interconnect driver" depends on INTERCONNECT_QCOM || COMPILE_TEST + depends on ARM64 || COMPILE_TEST help Say y here to support the Operating State Manager (OSM) interconnect driver which controls the scaling of L3 caches on Qualcomm SoCs. @@ -118,6 +147,7 @@ config INTERCONNECT_QCOM_QCM2290 tristate "Qualcomm QCM2290 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on qcm2290-based @@ -127,6 +157,7 @@ config INTERCONNECT_QCOM_QCS404 tristate "Qualcomm QCS404 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on qcs404-based @@ -135,6 +166,7 @@ config INTERCONNECT_QCOM_QCS404 config INTERCONNECT_QCOM_QCS615 tristate "Qualcomm QCS615 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -144,6 +176,7 @@ config INTERCONNECT_QCOM_QCS615 config INTERCONNECT_QCOM_QCS8300 tristate "Qualcomm QCS8300 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -155,6 +188,7 @@ config INTERCONNECT_QCOM_QCS8300 config INTERCONNECT_QCOM_QDU1000 tristate "Qualcomm QDU1000/QRU1000 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -178,6 +212,7 @@ config INTERCONNECT_QCOM_RPMH config INTERCONNECT_QCOM_SA8775P tristate "Qualcomm SA8775P interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -187,6 +222,7 @@ config INTERCONNECT_QCOM_SA8775P config INTERCONNECT_QCOM_SAR2130P tristate "Qualcomm SAR2130P interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -196,6 +232,7 @@ config INTERCONNECT_QCOM_SAR2130P config INTERCONNECT_QCOM_SC7180 tristate "Qualcomm SC7180 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -205,6 +242,7 @@ config INTERCONNECT_QCOM_SC7180 config INTERCONNECT_QCOM_SC7280 tristate "Qualcomm SC7280 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -214,6 +252,7 @@ config INTERCONNECT_QCOM_SC7280 config INTERCONNECT_QCOM_SC8180X tristate "Qualcomm SC8180X interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -223,6 +262,7 @@ config INTERCONNECT_QCOM_SC8180X config INTERCONNECT_QCOM_SC8280XP tristate "Qualcomm SC8280XP interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -232,6 +272,7 @@ config INTERCONNECT_QCOM_SC8280XP config INTERCONNECT_QCOM_SDM660 tristate "Qualcomm SDM660 interconnect driver" depends on INTERCONNECT_QCOM + depends on ARM64 || COMPILE_TEST depends on QCOM_SMD_RPM select INTERCONNECT_QCOM_SMD_RPM help @@ -241,6 +282,7 @@ config INTERCONNECT_QCOM_SDM660 config INTERCONNECT_QCOM_SDM670 tristate "Qualcomm SDM670 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -250,6 +292,7 @@ config INTERCONNECT_QCOM_SDM670 config INTERCONNECT_QCOM_SDM845 tristate "Qualcomm SDM845 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -259,6 +302,7 @@ config INTERCONNECT_QCOM_SDM845 config INTERCONNECT_QCOM_SDX55 tristate "Qualcomm SDX55 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -268,6 +312,7 @@ config INTERCONNECT_QCOM_SDX55 config INTERCONNECT_QCOM_SDX65 tristate "Qualcomm SDX65 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -277,16 +322,27 @@ config INTERCONNECT_QCOM_SDX65 config INTERCONNECT_QCOM_SDX75 tristate "Qualcomm SDX75 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help This is a driver for the Qualcomm Network-on-Chip on sdx75-based platforms. +config INTERCONNECT_QCOM_SHIKRA + tristate "Qualcomm SHIKRA interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + select INTERCONNECT_QCOM_SMD_RPM + help + This is a driver for the Qualcomm Network-on-Chip on shikra-based + platforms. + config INTERCONNECT_QCOM_SM6115 tristate "Qualcomm SM6115 interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on sm6115-based @@ -295,6 +351,7 @@ config INTERCONNECT_QCOM_SM6115 config INTERCONNECT_QCOM_SM6350 tristate "Qualcomm SM6350 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -304,6 +361,7 @@ config INTERCONNECT_QCOM_SM6350 config INTERCONNECT_QCOM_SM7150 tristate "Qualcomm SM7150 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -313,6 +371,7 @@ config INTERCONNECT_QCOM_SM7150 config INTERCONNECT_QCOM_MILOS tristate "Qualcomm Milos interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -322,6 +381,7 @@ config INTERCONNECT_QCOM_MILOS config INTERCONNECT_QCOM_SM8150 tristate "Qualcomm SM8150 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -331,6 +391,7 @@ config INTERCONNECT_QCOM_SM8150 config INTERCONNECT_QCOM_SM8250 tristate "Qualcomm SM8250 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -340,6 +401,7 @@ config INTERCONNECT_QCOM_SM8250 config INTERCONNECT_QCOM_SM8350 tristate "Qualcomm SM8350 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -349,6 +411,7 @@ config INTERCONNECT_QCOM_SM8350 config INTERCONNECT_QCOM_SM8450 tristate "Qualcomm SM8450 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -358,6 +421,7 @@ config INTERCONNECT_QCOM_SM8450 config INTERCONNECT_QCOM_SM8550 tristate "Qualcomm SM8550 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -367,6 +431,7 @@ config INTERCONNECT_QCOM_SM8550 config INTERCONNECT_QCOM_SM8650 tristate "Qualcomm SM8650 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -376,6 +441,7 @@ config INTERCONNECT_QCOM_SM8650 config INTERCONNECT_QCOM_SM8750 tristate "Qualcomm SM8750 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help @@ -385,6 +451,7 @@ config INTERCONNECT_QCOM_SM8750 config INTERCONNECT_QCOM_X1E80100 tristate "Qualcomm X1E80100 interconnect driver" depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + depends on ARM64 || COMPILE_TEST select INTERCONNECT_QCOM_RPMH select INTERCONNECT_QCOM_BCM_VOTER help diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index cdf2c6c9fbf3..1c7d410b40cc 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -6,6 +6,7 @@ interconnect_qcom-y := icc-common.o icc-bcm-voter-objs := bcm-voter.o qnoc-eliza-objs := eliza.o qnoc-glymur-objs := glymur.o +qnoc-hawi-objs := hawi.o qnoc-kaanapali-objs := kaanapali.o qnoc-milos-objs := milos.o qnoc-msm8909-objs := msm8909.o @@ -16,6 +17,7 @@ qnoc-msm8953-objs := msm8953.o qnoc-msm8974-objs := msm8974.o qnoc-msm8976-objs := msm8976.o qnoc-msm8996-objs := msm8996.o +qnoc-nord-objs := nord.o icc-osm-l3-objs := osm-l3.o qnoc-qcm2290-objs := qcm2290.o qnoc-qcs404-objs := qcs404.o @@ -35,6 +37,7 @@ qnoc-sdm845-objs := sdm845.o qnoc-sdx55-objs := sdx55.o qnoc-sdx65-objs := sdx65.o qnoc-sdx75-objs := sdx75.o +qnoc-shikra-objs := shikra.o qnoc-sm6115-objs := sm6115.o qnoc-sm6350-objs := sm6350.o qnoc-sm7150-objs := sm7150.o @@ -51,6 +54,7 @@ icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o obj-$(CONFIG_INTERCONNECT_QCOM_ELIZA) += qnoc-eliza.o obj-$(CONFIG_INTERCONNECT_QCOM_GLYMUR) += qnoc-glymur.o +obj-$(CONFIG_INTERCONNECT_QCOM_HAWI) += qnoc-hawi.o obj-$(CONFIG_INTERCONNECT_QCOM_KAANAPALI) += qnoc-kaanapali.o obj-$(CONFIG_INTERCONNECT_QCOM_MILOS) += qnoc-milos.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8909) += qnoc-msm8909.o @@ -61,6 +65,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8953) += qnoc-msm8953.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8976) += qnoc-msm8976.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o +obj-$(CONFIG_INTERCONNECT_QCOM_NORD) += qnoc-nord.o obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o @@ -80,6 +85,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o obj-$(CONFIG_INTERCONNECT_QCOM_SDX55) += qnoc-sdx55.o obj-$(CONFIG_INTERCONNECT_QCOM_SDX65) += qnoc-sdx65.o obj-$(CONFIG_INTERCONNECT_QCOM_SDX75) += qnoc-sdx75.o +obj-$(CONFIG_INTERCONNECT_QCOM_SHIKRA) += qnoc-shikra.o obj-$(CONFIG_INTERCONNECT_QCOM_SM6115) += qnoc-sm6115.o obj-$(CONFIG_INTERCONNECT_QCOM_SM6350) += qnoc-sm6350.o obj-$(CONFIG_INTERCONNECT_QCOM_SM7150) += qnoc-sm7150.o diff --git a/drivers/interconnect/qcom/eliza.c b/drivers/interconnect/qcom/eliza.c index a4f7903f0524..891e4e6e8ba8 100644 --- a/drivers/interconnect/qcom/eliza.c +++ b/drivers/interconnect/qcom/eliza.c @@ -127,6 +127,12 @@ static struct qcom_icc_node qhs_qup2 = { .buswidth = 4, }; +static struct qcom_icc_node qhs_sdc1 = { + .name = "qhs_sdc1", + .channels = 1, + .buswidth = 4, +}; + static struct qcom_icc_node qhs_sdc2 = { .name = "qhs_sdc2", .channels = 1, @@ -383,7 +389,7 @@ static struct qcom_icc_node qsm_cfg = { .name = "qsm_cfg", .channels = 1, .buswidth = 4, - .num_links = 29, + .num_links = 30, .link_nodes = { &qhs_ahb2phy0, &qhs_ahb2phy1, &qhs_camera_cfg, &qhs_clk_ctl, &qhs_crypto0_cfg, &qhs_display_cfg, @@ -392,7 +398,7 @@ static struct qcom_icc_node qsm_cfg = { &qhs_mss_cfg, &qhs_pcie_0_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qspi, &qhs_qup1, - &qhs_qup2, &qhs_sdc2, + &qhs_qup2, &qhs_sdc1, &qhs_sdc2, &qhs_tcsr, &qhs_tlmm, &qhs_ufs_mem_cfg, &qhs_usb3_0, &qhs_venus_cfg, &qhs_vsense_ctrl_cfg, @@ -1111,7 +1117,7 @@ static struct qcom_icc_bcm bcm_cn0 = { .name = "CN0", .enable_mask = BIT(0), .keepalive = true, - .num_nodes = 43, + .num_nodes = 44, .nodes = { &qsm_cfg, &qhs_ahb2phy0, &qhs_ahb2phy1, &qhs_camera_cfg, &qhs_clk_ctl, &qhs_crypto0_cfg, @@ -1119,7 +1125,7 @@ static struct qcom_icc_bcm bcm_cn0 = { &qhs_i3c_ibi1_cfg, &qhs_imem_cfg, &qhs_mss_cfg, &qhs_pcie_0_cfg, &qhs_prng, &qhs_qdss_cfg, - &qhs_qspi, &qhs_sdc2, + &qhs_qspi, &qhs_sdc1, &qhs_sdc2, &qhs_tcsr, &qhs_tlmm, &qhs_ufs_mem_cfg, &qhs_usb3_0, &qhs_venus_cfg, &qhs_vsense_ctrl_cfg, @@ -1321,6 +1327,7 @@ static struct qcom_icc_node * const cnoc_cfg_nodes[] = { [SLAVE_QSPI_0] = &qhs_qspi, [SLAVE_QUP_1] = &qhs_qup1, [SLAVE_QUP_2] = &qhs_qup2, + [SLAVE_SDCC_1] = &qhs_sdc1, [SLAVE_SDCC_2] = &qhs_sdc2, [SLAVE_TCSR] = &qhs_tcsr, [SLAVE_TLMM] = &qhs_tlmm, diff --git a/drivers/interconnect/qcom/hawi.c b/drivers/interconnect/qcom/hawi.c new file mode 100644 index 000000000000..6ece9828c62d --- /dev/null +++ b/drivers/interconnect/qcom/hawi.c @@ -0,0 +1,2028 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "bcm-voter.h" +#include "icc-rpmh.h" + +static struct qcom_icc_node ddr_eff_veto_slave = { + .name = "ddr_eff_veto_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup0_core_slave = { + .name = "qup0_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup1_core_slave = { + .name = "qup1_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup2_core_slave = { + .name = "qup2_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup3_core_slave = { + .name = "qup3_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup4_core_slave = { + .name = "qup4_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_aoss = { + .name = "qhs_aoss", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ipa = { + .name = "qhs_ipa", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ipc_router_fence = { + .name = "qhs_ipc_router_fence", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_soccp = { + .name = "qhs_soccp", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_tme_cfg = { + .name = "qhs_tme_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_ddrss_cfg = { + .name = "qss_ddrss_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qxs_imem = { + .name = "qxs_imem", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node xs_pcie = { + .name = "xs_pcie", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node xs_pcie_g4x1 = { + .name = "xs_pcie_g4x1", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qhs_lpi_cc = { + .name = "qhs_lpi_cc", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qns_lb = { + .name = "qns_lb", + .channels = 4, + .buswidth = 32, +}; + +static struct qcom_icc_node srvc_llclpi_noc = { + .name = "srvc_llclpi_noc", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node srvc_llclpi_noc_chipcx = { + .name = "srvc_llclpi_noc_chipcx", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node ebi = { + .name = "ebi", + .channels = 4, + .buswidth = 4, +}; + +static struct qcom_icc_node ddr_rt_slave = { + .name = "ddr_rt_slave", + .channels = 4, + .buswidth = 4, +}; + +static struct qcom_icc_node srvc_pcie_aggre_noc = { + .name = "srvc_pcie_aggre_noc", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy0 = { + .name = "qhs_ahb2phy0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_boot_rom = { + .name = "qhs_boot_rom", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_camera_cfg = { + .name = "qhs_camera_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_clk_ctl = { + .name = "qhs_clk_ctl", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_crypto_cfg = { + .name = "qhs_crypto_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_display_cfg = { + .name = "qhs_display_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_eva_cfg = { + .name = "qhs_eva_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_gpuss_cfg = { + .name = "qhs_gpuss_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qhs_i2c = { + .name = "qhs_i2c", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_imem_cfg = { + .name = "qhs_imem_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ipc_router = { + .name = "qhs_ipc_router", + .channels = 4, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_iris_cfg = { + .name = "qhs_iris_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_mss_cfg = { + .name = "qhs_mss_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_cfg = { + .name = "qhs_pcie_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_g4x1_cfg = { + .name = "qhs_pcie_g4x1_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_prng = { + .name = "qhs_prng", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qspi = { + .name = "qhs_qspi", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup1 = { + .name = "qhs_qup1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup2 = { + .name = "qhs_qup2", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup3 = { + .name = "qhs_qup3", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup4 = { + .name = "qhs_qup4", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_sdc2 = { + .name = "qhs_sdc2", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_sdc4 = { + .name = "qhs_sdc4", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_tlmm = { + .name = "qhs_tlmm", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ufs_mem_cfg = { + .name = "qhs_ufs_mem_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_usb3 = { + .name = "qhs_usb3", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_vsense_ctrl_cfg = { + .name = "qhs_vsense_ctrl_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_qdss_cfg = { + .name = "qss_qdss_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_qdss_stm = { + .name = "qss_qdss_stm", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_tcsr = { + .name = "qss_tcsr", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node xs_sys_tcu_cfg = { + .name = "xs_sys_tcu_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node ddr_eff_veto_master = { + .name = "ddr_eff_veto_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &ddr_eff_veto_slave }, +}; + +static struct qcom_icc_node qup0_core_master = { + .name = "qup0_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup0_core_slave }, +}; + +static struct qcom_icc_node qup1_core_master = { + .name = "qup1_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup1_core_slave }, +}; + +static struct qcom_icc_node qup2_core_master = { + .name = "qup2_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup2_core_slave }, +}; + +static struct qcom_icc_node qup3_core_master = { + .name = "qup3_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup3_core_slave }, +}; + +static struct qcom_icc_node qup4_core_master = { + .name = "qup4_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup4_core_slave }, +}; + +static struct qcom_icc_node qnm_gemnoc_pcie = { + .name = "qnm_gemnoc_pcie", + .channels = 1, + .buswidth = 8, + .num_links = 2, + .link_nodes = { &xs_pcie, &xs_pcie_g4x1 }, +}; + +static struct qcom_icc_node qnm_lpiaon_noc_llclpi_noc = { + .name = "qnm_lpiaon_noc_llclpi_noc", + .channels = 1, + .buswidth = 16, + .num_links = 4, + .link_nodes = { &qhs_lpi_cc, &qns_lb, + &srvc_llclpi_noc, &srvc_llclpi_noc_chipcx }, +}; + +static struct qcom_icc_node llcc_mc = { + .name = "llcc_mc", + .channels = 4, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &ebi }, +}; + +static struct qcom_icc_node ddr_rt_mc = { + .name = "ddr_rt_mc", + .channels = 4, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &ddr_rt_slave }, +}; + +static struct qcom_icc_node qsm_pcie_anoc_cfg = { + .name = "qsm_pcie_anoc_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &srvc_pcie_aggre_noc }, +}; + +static struct qcom_icc_node qsm_cfg_east = { + .name = "qsm_cfg_east", + .channels = 1, + .buswidth = 4, + .num_links = 4, + .link_nodes = { &qhs_crypto_cfg, &qhs_gpuss_cfg, + &qhs_qup2, &qhs_vsense_ctrl_cfg }, +}; + +static struct qcom_icc_node qsm_cfg_mm = { + .name = "qsm_cfg_mm", + .channels = 1, + .buswidth = 4, + .num_links = 5, + .link_nodes = { &qhs_boot_rom, &qhs_camera_cfg, + &qhs_display_cfg, &qhs_eva_cfg, + &qhs_iris_cfg }, +}; + +static struct qcom_icc_node qsm_cfg_north = { + .name = "qsm_cfg_north", + .channels = 1, + .buswidth = 4, + .num_links = 5, + .link_nodes = { &qhs_pcie_cfg, &qhs_pcie_g4x1_cfg, + &qhs_qup3, &qhs_qup4, + &qhs_sdc2 }, +}; + +static struct qcom_icc_node qsm_cfg_south = { + .name = "qsm_cfg_south", + .channels = 1, + .buswidth = 4, + .num_links = 6, + .link_nodes = { &qhs_ahb2phy0, &qhs_qspi, + &qhs_qup1, &qhs_sdc4, + &qhs_ufs_mem_cfg, &qhs_usb3 }, +}; + +static struct qcom_icc_node qsm_cfg_southwest = { + .name = "qsm_cfg_southwest", + .channels = 1, + .buswidth = 4, + .num_links = 2, + .link_nodes = { &qhs_ipc_router, &qhs_mss_cfg }, +}; + +static struct qcom_icc_node qns_llcc = { + .name = "qns_llcc", + .channels = 4, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &llcc_mc }, +}; + +static struct qcom_icc_node qns_pcie = { + .name = "qns_pcie", + .channels = 1, + .buswidth = 8, + .num_links = 1, + .link_nodes = { &qnm_gemnoc_pcie }, +}; + +static struct qcom_icc_node qns_llc_lpinoc = { + .name = "qns_llc_lpinoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_lpiaon_noc_llclpi_noc }, +}; + +static struct qcom_icc_node qss_pcie_anoc_cfg = { + .name = "qss_pcie_anoc_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_pcie_anoc_cfg }, +}; + +static struct qcom_icc_node qss_stdst_east_cfg = { + .name = "qss_stdst_east_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg_east }, +}; + +static struct qcom_icc_node qss_stdst_mm_cfg = { + .name = "qss_stdst_mm_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg_mm }, +}; + +static struct qcom_icc_node qss_stdst_north_cfg = { + .name = "qss_stdst_north_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg_north }, +}; + +static struct qcom_icc_node qss_stdst_south_cfg = { + .name = "qss_stdst_south_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg_south }, +}; + +static struct qcom_icc_node qss_stdst_southwest_cfg = { + .name = "qss_stdst_southwest_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg_southwest }, +}; + +static struct qcom_icc_node alm_gic = { + .name = "alm_gic", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x14d000 }, + .prio = 4, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_llcc }, +}; + +static struct qcom_icc_node qnm_qpace = { + .name = "qnm_qpace", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x153000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_llcc }, +}; + +static struct qcom_icc_node qsm_cfg_center = { + .name = "qsm_cfg_center", + .channels = 1, + .buswidth = 4, + .num_links = 10, + .link_nodes = { &qhs_clk_ctl, &qhs_i2c, + &qhs_imem_cfg, &qhs_prng, + &qhs_tlmm, &qss_pcie_anoc_cfg, + &qss_qdss_cfg, &qss_qdss_stm, + &qss_tcsr, &xs_sys_tcu_cfg }, +}; + +static struct qcom_icc_node qss_stdst_center_cfg = { + .name = "qss_stdst_center_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg_center }, +}; + +static struct qcom_icc_node qsm_cnoc_main = { + .name = "qsm_cnoc_main", + .channels = 1, + .buswidth = 4, + .num_links = 6, + .link_nodes = { &qss_stdst_center_cfg, &qss_stdst_east_cfg, + &qss_stdst_mm_cfg, &qss_stdst_north_cfg, + &qss_stdst_south_cfg, &qss_stdst_southwest_cfg }, +}; + +static struct qcom_icc_node qss_cfg = { + .name = "qss_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cnoc_main }, +}; + +static struct qcom_icc_node qnm_gemnoc_cnoc = { + .name = "qnm_gemnoc_cnoc", + .channels = 1, + .buswidth = 16, + .num_links = 8, + .link_nodes = { &qhs_aoss, &qhs_ipa, + &qhs_ipc_router_fence, &qhs_soccp, + &qhs_tme_cfg, &qss_cfg, + &qss_ddrss_cfg, &qxs_imem }, +}; + +static struct qcom_icc_node qns_gem_noc_cnoc = { + .name = "qns_gem_noc_cnoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_gemnoc_cnoc }, +}; + +static struct qcom_icc_node alm_gpu_tcu = { + .name = "alm_gpu_tcu", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x145000 }, + .prio = 1, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node alm_sys_tcu = { + .name = "alm_sys_tcu", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x147000 }, + .prio = 6, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node chm_apps = { + .name = "chm_apps", + .channels = 4, + .buswidth = 32, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_gpu = { + .name = "qnm_gpu", + .channels = 4, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 4, + .port_offsets = { 0x51000, 0x53000, 0xd1000, 0xd3000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_lpass_gemnoc = { + .name = "qnm_lpass_gemnoc", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x149000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_mdsp = { + .name = "qnm_mdsp", + .channels = 1, + .buswidth = 16, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_mnoc_hf = { + .name = "qnm_mnoc_hf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x55000, 0xd5000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_mnoc_sf = { + .name = "qnm_mnoc_sf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x57000, 0xd7000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_nsp_gemnoc = { + .name = "qnm_nsp_gemnoc", + .channels = 4, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 4, + .port_offsets = { 0x59000, 0x5b000, 0xd9000, 0xdb000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_pcie = { + .name = "qnm_pcie", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x14b000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 2, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node qnm_snoc_sf = { + .name = "qnm_snoc_sf", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x14f000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_wlan_q6 = { + .name = "qnm_wlan_q6", + .channels = 1, + .buswidth = 8, + .num_links = 3, + .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qns_lpass_ag_noc_gemnoc = { + .name = "qns_lpass_ag_noc_gemnoc", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_lpass_gemnoc }, +}; + +static struct qcom_icc_node qns_mem_noc_hf = { + .name = "qns_mem_noc_hf", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_mnoc_hf }, +}; + +static struct qcom_icc_node qns_mem_noc_sf = { + .name = "qns_mem_noc_sf", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_mnoc_sf }, +}; + +static struct qcom_icc_node qns_nsp_gemnoc = { + .name = "qns_nsp_gemnoc", + .channels = 4, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_nsp_gemnoc }, +}; + +static struct qcom_icc_node qns_pcie_gemnoc = { + .name = "qns_pcie_gemnoc", + .channels = 1, + .buswidth = 8, + .num_links = 1, + .link_nodes = { &qnm_pcie }, +}; + +static struct qcom_icc_node qns_gemnoc_sf = { + .name = "qns_gemnoc_sf", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_snoc_sf }, +}; + +static struct qcom_icc_node qnm_lpiaon_noc = { + .name = "qnm_lpiaon_noc", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_lpass_ag_noc_gemnoc }, +}; + +static struct qcom_icc_node qnm_camnoc_hf = { + .name = "qnm_camnoc_hf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x2a000, 0x2b000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_camnoc_nrt_icp_sf = { + .name = "qnm_camnoc_nrt_icp_sf", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x2c000 }, + .prio = 4, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_camnoc_rt_cdm_sf = { + .name = "qnm_camnoc_rt_cdm_sf", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x38000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_camnoc_sf = { + .name = "qnm_camnoc_sf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x2d000, 0x2e000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_mdp = { + .name = "qnm_mdp", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x2f000, 0x30000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_mdss_dcp = { + .name = "qnm_mdss_dcp", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x39000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_vapss_hcp = { + .name = "qnm_vapss_hcp", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_cv_cpu = { + .name = "qnm_video_cv_cpu", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x34000 }, + .prio = 4, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_eva = { + .name = "qnm_video_eva", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x35000, 0x36000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_mvp = { + .name = "qnm_video_mvp", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x32000, 0x33000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_v_cpu = { + .name = "qnm_video_v_cpu", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x37000 }, + .prio = 4, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_nsp = { + .name = "qnm_nsp", + .channels = 4, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_nsp_gemnoc }, +}; + +static struct qcom_icc_node xm_pcie = { + .name = "xm_pcie", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xc000 }, + .prio = 3, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_pcie_gemnoc }, +}; + +static struct qcom_icc_node xm_pcie_g4x1 = { + .name = "xm_pcie_g4x1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xd000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_pcie_gemnoc }, +}; + +static struct qcom_icc_node qnm_aggre_noc = { + .name = "qnm_aggre_noc", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x20000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_gemnoc_sf }, +}; + +static struct qcom_icc_node qnm_apss_noc = { + .name = "qnm_apss_noc", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1e000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_gemnoc_sf }, +}; + +static struct qcom_icc_node qnm_cnoc_data = { + .name = "qnm_cnoc_data", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1f000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_gemnoc_sf }, +}; + +static struct qcom_icc_node qns_a1noc_snoc = { + .name = "qns_a1noc_snoc", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_aggre_noc }, +}; + +static struct qcom_icc_node qns_lpass_aggnoc = { + .name = "qns_lpass_aggnoc", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_lpiaon_noc }, +}; + +static struct qcom_icc_node qhm_qspi = { + .name = "qhm_qspi", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x49000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qhm_qup2 = { + .name = "qhm_qup2", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x48000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qhm_qup3 = { + .name = "qhm_qup3", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x46000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qhm_qup4 = { + .name = "qhm_qup4", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x47000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qxm_crypto = { + .name = "qxm_crypto", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x40000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qxm_ipa = { + .name = "qxm_ipa", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x41000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qxm_qup1 = { + .name = "qxm_qup1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x4d000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qxm_soccp = { + .name = "qxm_soccp", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x45000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node xm_qdss_etr_0 = { + .name = "xm_qdss_etr_0", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x42000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node xm_qdss_etr_1 = { + .name = "xm_qdss_etr_1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x43000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node xm_sdc2 = { + .name = "xm_sdc2", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x44000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node xm_sdc4 = { + .name = "xm_sdc4", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x4a000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node xm_ufs_mem = { + .name = "xm_ufs_mem", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x4b000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node xm_usb3 = { + .name = "xm_usb3", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x4c000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qnm_lpass_lpinoc = { + .name = "qnm_lpass_lpinoc", + .channels = 1, + .buswidth = 32, + .num_links = 2, + .link_nodes = { &qns_llc_lpinoc, &qns_lpass_aggnoc }, +}; + +static struct qcom_icc_node qns_lpi_aon_noc = { + .name = "qns_lpi_aon_noc", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_lpass_lpinoc }, +}; + +static struct qcom_icc_node qnm_lpinoc_dsp_qns4m = { + .name = "qnm_lpinoc_dsp_qns4m", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_lpi_aon_noc }, +}; + +static struct qcom_icc_bcm bcm_acv = { + .name = "ACV", + .enable_mask = BIT(3), + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_ce0 = { + .name = "CE0", + .num_nodes = 1, + .nodes = { &qxm_crypto }, +}; + +static struct qcom_icc_bcm bcm_cn0 = { + .name = "CN0", + .enable_mask = BIT(0), + .keepalive = true, + .num_nodes = 24, + .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie, + &qhs_aoss, &qhs_ipa, + &qhs_ipc_router_fence, &qhs_soccp, + &qhs_tme_cfg, &qss_cfg, + &qss_ddrss_cfg, &qxs_imem, + &xs_pcie, &xs_pcie_g4x1, + &qsm_cfg_center, &qsm_cfg_east, + &qsm_cfg_mm, &qsm_cfg_north, + &qsm_cfg_south, &qsm_cfg_southwest, + &qhs_ahb2phy0, &qhs_boot_rom, + &qhs_camera_cfg, &qhs_clk_ctl, + &qhs_crypto_cfg, &qhs_eva_cfg }, +}; + +static struct qcom_icc_bcm bcm_cn1 = { + .name = "CN1", + .num_nodes = 1, + .nodes = { &qhs_display_cfg }, +}; + +static struct qcom_icc_bcm bcm_co0 = { + .name = "CO0", + .enable_mask = BIT(0), + .num_nodes = 2, + .nodes = { &qnm_nsp, &qns_nsp_gemnoc }, +}; + +static struct qcom_icc_bcm bcm_de0 = { + .name = "DE0", + .enable_mask = BIT(0), + .num_nodes = 1, + .nodes = { &ddr_eff_veto_slave }, +}; + +static struct qcom_icc_bcm bcm_lp0 = { + .name = "LP0", + .num_nodes = 5, + .nodes = { &qnm_lpiaon_noc_llclpi_noc, &qns_lb, + &qnm_lpass_lpinoc, &qns_llc_lpinoc, + &qns_lpass_aggnoc }, +}; + +static struct qcom_icc_bcm bcm_mc0 = { + .name = "MC0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_mc5 = { + .name = "MC5", + .num_nodes = 1, + .nodes = { &ddr_rt_slave }, +}; + +static struct qcom_icc_bcm bcm_mm0 = { + .name = "MM0", + .num_nodes = 1, + .nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_bcm bcm_mm1 = { + .name = "MM1", + .enable_mask = BIT(0), + .num_nodes = 9, + .nodes = { &qnm_camnoc_hf, &qnm_camnoc_nrt_icp_sf, + &qnm_camnoc_rt_cdm_sf, &qnm_camnoc_sf, + &qnm_vapss_hcp, &qnm_video_cv_cpu, + &qnm_video_mvp, &qnm_video_v_cpu, + &qns_mem_noc_sf }, +}; + +static struct qcom_icc_bcm bcm_qpc0 = { + .name = "QPC0", + .num_nodes = 1, + .nodes = { &qnm_qpace }, +}; + +static struct qcom_icc_bcm bcm_qup0 = { + .name = "QUP0", + .keepalive = true, + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup0_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup1 = { + .name = "QUP1", + .keepalive = true, + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup1_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup2 = { + .name = "QUP2", + .keepalive = true, + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup2_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup3 = { + .name = "QUP3", + .keepalive = true, + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup3_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup4 = { + .name = "QUP4", + .keepalive = true, + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup4_core_slave }, +}; + +static struct qcom_icc_bcm bcm_sh0 = { + .name = "SH0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_llcc }, +}; + +static struct qcom_icc_bcm bcm_sh1 = { + .name = "SH1", + .enable_mask = BIT(0), + .num_nodes = 15, + .nodes = { &alm_gic, &alm_gpu_tcu, + &alm_sys_tcu, &chm_apps, + &qnm_gpu, &qnm_lpass_gemnoc, + &qnm_mdsp, &qnm_mnoc_hf, + &qnm_mnoc_sf, &qnm_nsp_gemnoc, + &qnm_pcie, &qnm_snoc_sf, + &qnm_wlan_q6, &qns_gem_noc_cnoc, + &qns_pcie }, +}; + +static struct qcom_icc_bcm bcm_sn0 = { + .name = "SN0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_gemnoc_sf }, +}; + +static struct qcom_icc_bcm bcm_sn2 = { + .name = "SN2", + .num_nodes = 1, + .nodes = { &qnm_aggre_noc }, +}; + +static struct qcom_icc_bcm bcm_sn3 = { + .name = "SN3", + .num_nodes = 1, + .nodes = { &qns_pcie_gemnoc }, +}; + +static struct qcom_icc_bcm * const aggre1_noc_bcms[] = { + &bcm_ce0, +}; + +static struct qcom_icc_node * const aggre1_noc_nodes[] = { + [MASTER_QSPI_0] = &qhm_qspi, + [MASTER_QUP_2] = &qhm_qup2, + [MASTER_QUP_3] = &qhm_qup3, + [MASTER_QUP_4] = &qhm_qup4, + [MASTER_CRYPTO] = &qxm_crypto, + [MASTER_IPA] = &qxm_ipa, + [MASTER_QUP_1] = &qxm_qup1, + [MASTER_SOCCP_PROC] = &qxm_soccp, + [MASTER_QDSS_ETR] = &xm_qdss_etr_0, + [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1, + [MASTER_SDCC_2] = &xm_sdc2, + [MASTER_SDCC_4] = &xm_sdc4, + [MASTER_UFS_MEM] = &xm_ufs_mem, + [MASTER_USB3] = &xm_usb3, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, +}; + +static const struct regmap_config hawi_aggre1_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x54400, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_aggre1_noc = { + .config = &hawi_aggre1_noc_regmap_config, + .nodes = aggre1_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), + .bcms = aggre1_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), + .qos_requires_clocks = true, +}; + +static struct qcom_icc_bcm * const clk_virt_bcms[] = { + &bcm_de0, + &bcm_qup0, + &bcm_qup1, + &bcm_qup2, + &bcm_qup3, + &bcm_qup4, +}; + +static struct qcom_icc_node * const clk_virt_nodes[] = { + [MASTER_DDR_EFF_VETO] = &ddr_eff_veto_master, + [MASTER_QUP_CORE_0] = &qup0_core_master, + [MASTER_QUP_CORE_1] = &qup1_core_master, + [MASTER_QUP_CORE_2] = &qup2_core_master, + [MASTER_QUP_CORE_3] = &qup3_core_master, + [MASTER_QUP_CORE_4] = &qup4_core_master, + [SLAVE_DDR_EFF_VETO] = &ddr_eff_veto_slave, + [SLAVE_QUP_CORE_0] = &qup0_core_slave, + [SLAVE_QUP_CORE_1] = &qup1_core_slave, + [SLAVE_QUP_CORE_2] = &qup2_core_slave, + [SLAVE_QUP_CORE_3] = &qup3_core_slave, + [SLAVE_QUP_CORE_4] = &qup4_core_slave, +}; + +static const struct qcom_icc_desc hawi_clk_virt = { + .nodes = clk_virt_nodes, + .num_nodes = ARRAY_SIZE(clk_virt_nodes), + .bcms = clk_virt_bcms, + .num_bcms = ARRAY_SIZE(clk_virt_bcms), +}; + +static struct qcom_icc_bcm * const cnoc_main_bcms[] = { + &bcm_cn0, +}; + +static struct qcom_icc_node * const cnoc_main_nodes[] = { + [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc, + [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie, + [SLAVE_AOSS] = &qhs_aoss, + [SLAVE_IPA_CFG] = &qhs_ipa, + [SLAVE_IPC_ROUTER_FENCE] = &qhs_ipc_router_fence, + [SLAVE_SOCCP] = &qhs_soccp, + [SLAVE_TME_CFG] = &qhs_tme_cfg, + [SLAVE_CNOC_CFG] = &qss_cfg, + [SLAVE_DDRSS_CFG] = &qss_ddrss_cfg, + [SLAVE_IMEM] = &qxs_imem, + [SLAVE_PCIE_0] = &xs_pcie, + [SLAVE_PCIE_1] = &xs_pcie_g4x1, +}; + +static const struct regmap_config hawi_cnoc_main_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x20000, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_cnoc_main = { + .config = &hawi_cnoc_main_regmap_config, + .nodes = cnoc_main_nodes, + .num_nodes = ARRAY_SIZE(cnoc_main_nodes), + .bcms = cnoc_main_bcms, + .num_bcms = ARRAY_SIZE(cnoc_main_bcms), +}; + +static struct qcom_icc_bcm * const gem_noc_bcms[] = { + &bcm_qpc0, + &bcm_sh0, + &bcm_sh1, +}; + +static struct qcom_icc_node * const gem_noc_nodes[] = { + [MASTER_GIC] = &alm_gic, + [MASTER_GPU_TCU] = &alm_gpu_tcu, + [MASTER_SYS_TCU] = &alm_sys_tcu, + [MASTER_APPSS_PROC] = &chm_apps, + [MASTER_GFX3D] = &qnm_gpu, + [MASTER_LPASS_GEM_NOC] = &qnm_lpass_gemnoc, + [MASTER_MSS_PROC] = &qnm_mdsp, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_COMPUTE_NOC] = &qnm_nsp_gemnoc, + [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie, + [MASTER_QPACE] = &qnm_qpace, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_WLAN_Q6] = &qnm_wlan_q6, + [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie, +}; + +static const struct regmap_config hawi_gem_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x160200, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_gem_noc = { + .config = &hawi_gem_noc_regmap_config, + .nodes = gem_noc_nodes, + .num_nodes = ARRAY_SIZE(gem_noc_nodes), + .bcms = gem_noc_bcms, + .num_bcms = ARRAY_SIZE(gem_noc_bcms), +}; + +static struct qcom_icc_bcm * const llclpi_noc_bcms[] = { + &bcm_lp0, +}; + +static struct qcom_icc_node * const llclpi_noc_nodes[] = { + [MASTER_LPIAON_NOC_LLCLPI_NOC] = &qnm_lpiaon_noc_llclpi_noc, + [SLAVE_LPASS_LPI_CC] = &qhs_lpi_cc, + [SLAVE_LLCC_ISLAND] = &qns_lb, + [SLAVE_SERVICE_LLCLPI_NOC] = &srvc_llclpi_noc, + [SLAVE_SERVICE_LLCLPI_NOC_CHIPCX] = &srvc_llclpi_noc_chipcx, +}; + +static const struct regmap_config hawi_llclpi_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x17200, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_llclpi_noc = { + .config = &hawi_llclpi_noc_regmap_config, + .nodes = llclpi_noc_nodes, + .num_nodes = ARRAY_SIZE(llclpi_noc_nodes), + .bcms = llclpi_noc_bcms, + .num_bcms = ARRAY_SIZE(llclpi_noc_bcms), +}; + +static struct qcom_icc_node * const lpass_ag_noc_nodes[] = { + [MASTER_LPIAON_NOC] = &qnm_lpiaon_noc, + [SLAVE_LPASS_GEM_NOC] = &qns_lpass_ag_noc_gemnoc, +}; + +static const struct regmap_config hawi_lpass_ag_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xc080, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_lpass_ag_noc = { + .config = &hawi_lpass_ag_noc_regmap_config, + .nodes = lpass_ag_noc_nodes, + .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes), +}; + +static struct qcom_icc_bcm * const lpass_lpiaon_noc_bcms[] = { + &bcm_lp0, +}; + +static struct qcom_icc_node * const lpass_lpiaon_noc_nodes[] = { + [MASTER_LPASS_LPINOC] = &qnm_lpass_lpinoc, + [SLAVE_LPIAON_NOC_LLCLPI_NOC] = &qns_llc_lpinoc, + [SLAVE_LPIAON_NOC_LPASS_AG_NOC] = &qns_lpass_aggnoc, +}; + +static const struct regmap_config hawi_lpass_lpiaon_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x19080, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_lpass_lpiaon_noc = { + .config = &hawi_lpass_lpiaon_noc_regmap_config, + .nodes = lpass_lpiaon_noc_nodes, + .num_nodes = ARRAY_SIZE(lpass_lpiaon_noc_nodes), + .bcms = lpass_lpiaon_noc_bcms, + .num_bcms = ARRAY_SIZE(lpass_lpiaon_noc_bcms), +}; + +static struct qcom_icc_node * const lpass_lpicx_noc_nodes[] = { + [MASTER_LPASS_PROC] = &qnm_lpinoc_dsp_qns4m, + [SLAVE_LPICX_NOC_LPIAON_NOC] = &qns_lpi_aon_noc, +}; + +static const struct regmap_config hawi_lpass_lpicx_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x46080, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_lpass_lpicx_noc = { + .config = &hawi_lpass_lpicx_noc_regmap_config, + .nodes = lpass_lpicx_noc_nodes, + .num_nodes = ARRAY_SIZE(lpass_lpicx_noc_nodes), +}; + +static struct qcom_icc_bcm * const mc_virt_bcms[] = { + &bcm_acv, + &bcm_mc0, + &bcm_mc5, +}; + +static struct qcom_icc_node * const mc_virt_nodes[] = { + [MASTER_LLCC] = &llcc_mc, + [MASTER_DDR_RT] = &ddr_rt_mc, + [SLAVE_EBI1] = &ebi, + [SLAVE_DDR_RT] = &ddr_rt_slave, +}; + +static const struct qcom_icc_desc hawi_mc_virt = { + .nodes = mc_virt_nodes, + .num_nodes = ARRAY_SIZE(mc_virt_nodes), + .bcms = mc_virt_bcms, + .num_bcms = ARRAY_SIZE(mc_virt_bcms), +}; + +static struct qcom_icc_bcm * const mmss_noc_bcms[] = { + &bcm_mm0, + &bcm_mm1, +}; + +static struct qcom_icc_node * const mmss_noc_nodes[] = { + [MASTER_CAMNOC_HF] = &qnm_camnoc_hf, + [MASTER_CAMNOC_NRT_ICP_SF] = &qnm_camnoc_nrt_icp_sf, + [MASTER_CAMNOC_RT_CDM_SF] = &qnm_camnoc_rt_cdm_sf, + [MASTER_CAMNOC_SF] = &qnm_camnoc_sf, + [MASTER_MDP] = &qnm_mdp, + [MASTER_MDSS_DCP] = &qnm_mdss_dcp, + [MASTER_CDSP_HCP] = &qnm_vapss_hcp, + [MASTER_VIDEO_CV_PROC] = &qnm_video_cv_cpu, + [MASTER_VIDEO_EVA] = &qnm_video_eva, + [MASTER_VIDEO_MVP] = &qnm_video_mvp, + [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf, +}; + +static const struct regmap_config hawi_mmss_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x5f800, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_mmss_noc = { + .config = &hawi_mmss_noc_regmap_config, + .nodes = mmss_noc_nodes, + .num_nodes = ARRAY_SIZE(mmss_noc_nodes), + .bcms = mmss_noc_bcms, + .num_bcms = ARRAY_SIZE(mmss_noc_bcms), +}; + +static struct qcom_icc_bcm * const nsp_noc_bcms[] = { + &bcm_co0, +}; + +static struct qcom_icc_node * const nsp_noc_nodes[] = { + [MASTER_CDSP_PROC] = &qnm_nsp, + [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc, +}; + +static const struct regmap_config hawi_nsp_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x21280, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_nsp_noc = { + .config = &hawi_nsp_noc_regmap_config, + .nodes = nsp_noc_nodes, + .num_nodes = ARRAY_SIZE(nsp_noc_nodes), + .bcms = nsp_noc_bcms, + .num_bcms = ARRAY_SIZE(nsp_noc_bcms), +}; + +static struct qcom_icc_bcm * const pcie_anoc_bcms[] = { + &bcm_sn3, +}; + +static struct qcom_icc_node * const pcie_anoc_nodes[] = { + [MASTER_PCIE_ANOC_CFG] = &qsm_pcie_anoc_cfg, + [MASTER_PCIE_0] = &xm_pcie, + [MASTER_PCIE_1] = &xm_pcie_g4x1, + [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_gemnoc, + [SLAVE_SERVICE_PCIE_ANOC] = &srvc_pcie_aggre_noc, +}; + +static const struct regmap_config hawi_pcie_anoc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x12400, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_pcie_anoc = { + .config = &hawi_pcie_anoc_regmap_config, + .nodes = pcie_anoc_nodes, + .num_nodes = ARRAY_SIZE(pcie_anoc_nodes), + .bcms = pcie_anoc_bcms, + .num_bcms = ARRAY_SIZE(pcie_anoc_bcms), + .qos_requires_clocks = true, +}; + +static struct qcom_icc_bcm * const stdst_cfg_bcms[] = { + &bcm_cn0, + &bcm_cn1, +}; + +static struct qcom_icc_node * const stdst_cfg_nodes[] = { + [MASTER_CFG_CENTER] = &qsm_cfg_center, + [MASTER_CFG_EAST] = &qsm_cfg_east, + [MASTER_CFG_MM] = &qsm_cfg_mm, + [MASTER_CFG_NORTH] = &qsm_cfg_north, + [MASTER_CFG_SOUTH] = &qsm_cfg_south, + [MASTER_CFG_SOUTHWEST] = &qsm_cfg_southwest, + [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0, + [SLAVE_BOOT_ROM] = &qhs_boot_rom, + [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_CRYPTO_CFG] = &qhs_crypto_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_display_cfg, + [SLAVE_EVA_CFG] = &qhs_eva_cfg, + [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg, + [SLAVE_I2C] = &qhs_i2c, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router, + [SLAVE_IRIS_CFG] = &qhs_iris_cfg, + [SLAVE_CNOC_MSS] = &qhs_mss_cfg, + [SLAVE_PCIE_0_CFG] = &qhs_pcie_cfg, + [SLAVE_PCIE_1_CFG] = &qhs_pcie_g4x1_cfg, + [SLAVE_PRNG] = &qhs_prng, + [SLAVE_QSPI_0] = &qhs_qspi, + [SLAVE_QUP_1] = &qhs_qup1, + [SLAVE_QUP_2] = &qhs_qup2, + [SLAVE_QUP_3] = &qhs_qup3, + [SLAVE_QUP_4] = &qhs_qup4, + [SLAVE_SDCC_2] = &qhs_sdc2, + [SLAVE_SDCC_4] = &qhs_sdc4, + [SLAVE_TLMM] = &qhs_tlmm, + [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg, + [SLAVE_USB3] = &qhs_usb3, + [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, + [SLAVE_PCIE_ANOC_CFG] = &qss_pcie_anoc_cfg, + [SLAVE_QDSS_CFG] = &qss_qdss_cfg, + [SLAVE_QDSS_STM] = &qss_qdss_stm, + [SLAVE_TCSR] = &qss_tcsr, + [SLAVE_TCU] = &xs_sys_tcu_cfg, +}; + +static const struct regmap_config hawi_stdst_cfg_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xb1000, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_stdst_cfg = { + .config = &hawi_stdst_cfg_regmap_config, + .nodes = stdst_cfg_nodes, + .num_nodes = ARRAY_SIZE(stdst_cfg_nodes), + .bcms = stdst_cfg_bcms, + .num_bcms = ARRAY_SIZE(stdst_cfg_bcms), +}; + +static struct qcom_icc_node * const stdst_main_nodes[] = { + [MASTER_CNOC_STARDUST] = &qsm_cnoc_main, + [SLAVE_STARDUST_CENTER_CFG] = &qss_stdst_center_cfg, + [SLAVE_STARDUST_EAST_CFG] = &qss_stdst_east_cfg, + [SLAVE_STARDUST_MM_CFG] = &qss_stdst_mm_cfg, + [SLAVE_STARDUST_NORTH_CFG] = &qss_stdst_north_cfg, + [SLAVE_STARDUST_SOUTH_CFG] = &qss_stdst_south_cfg, + [SLAVE_STARDUST_SOUTHWEST_CFG] = &qss_stdst_southwest_cfg, +}; + +static const struct regmap_config hawi_stdst_main_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x10000, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_stdst_main = { + .config = &hawi_stdst_main_regmap_config, + .nodes = stdst_main_nodes, + .num_nodes = ARRAY_SIZE(stdst_main_nodes), +}; + +static struct qcom_icc_bcm * const system_noc_bcms[] = { + &bcm_sn0, + &bcm_sn2, +}; + +static struct qcom_icc_node * const system_noc_nodes[] = { + [MASTER_A1NOC_SNOC] = &qnm_aggre_noc, + [MASTER_APSS_NOC] = &qnm_apss_noc, + [MASTER_CNOC_SNOC] = &qnm_cnoc_data, + [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf, +}; + +static const struct regmap_config hawi_system_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x20080, + .fast_io = true, +}; + +static const struct qcom_icc_desc hawi_system_noc = { + .config = &hawi_system_noc_regmap_config, + .nodes = system_noc_nodes, + .num_nodes = ARRAY_SIZE(system_noc_nodes), + .bcms = system_noc_bcms, + .num_bcms = ARRAY_SIZE(system_noc_bcms), +}; + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,hawi-aggre1-noc", .data = &hawi_aggre1_noc }, + { .compatible = "qcom,hawi-clk-virt", .data = &hawi_clk_virt }, + { .compatible = "qcom,hawi-cnoc-main", .data = &hawi_cnoc_main }, + { .compatible = "qcom,hawi-gem-noc", .data = &hawi_gem_noc }, + { .compatible = "qcom,hawi-llclpi-noc", .data = &hawi_llclpi_noc }, + { .compatible = "qcom,hawi-lpass-ag-noc", .data = &hawi_lpass_ag_noc }, + { .compatible = "qcom,hawi-lpass-lpiaon-noc", .data = &hawi_lpass_lpiaon_noc }, + { .compatible = "qcom,hawi-lpass-lpicx-noc", .data = &hawi_lpass_lpicx_noc }, + { .compatible = "qcom,hawi-mc-virt", .data = &hawi_mc_virt }, + { .compatible = "qcom,hawi-mmss-noc", .data = &hawi_mmss_noc }, + { .compatible = "qcom,hawi-nsp-noc", .data = &hawi_nsp_noc }, + { .compatible = "qcom,hawi-pcie-anoc", .data = &hawi_pcie_anoc }, + { .compatible = "qcom,hawi-stdst-cfg", .data = &hawi_stdst_cfg }, + { .compatible = "qcom,hawi-stdst-main", .data = &hawi_stdst_main }, + { .compatible = "qcom,hawi-system-noc", .data = &hawi_system_noc }, + { } +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qcom_icc_rpmh_probe, + .remove = qcom_icc_rpmh_remove, + .driver = { + .name = "qnoc-hawi", + .of_match_table = qnoc_of_match, + .sync_state = icc_sync_state, + }, +}; + +static int __init qnoc_driver_init(void) +{ + return platform_driver_register(&qnoc_driver); +} +core_initcall(qnoc_driver_init); + +static void __exit qnoc_driver_exit(void) +{ + platform_driver_unregister(&qnoc_driver); +} +module_exit(qnoc_driver_exit); + +MODULE_DESCRIPTION("Qualcomm Hawi NoC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/qcom/msm8953.c b/drivers/interconnect/qcom/msm8953.c index be2b1a606612..94a9773d2970 100644 --- a/drivers/interconnect/qcom/msm8953.c +++ b/drivers/interconnect/qcom/msm8953.c @@ -1307,6 +1307,7 @@ static const struct of_device_id msm8953_noc_of_match[] = { { .compatible = "qcom,msm8953-snoc-mm", .data = &msm8953_snoc_mm }, { } }; +MODULE_DEVICE_TABLE(of, msm8953_noc_of_match); static struct platform_driver msm8953_noc_driver = { .probe = qnoc_probe, @@ -1318,6 +1319,5 @@ static struct platform_driver msm8953_noc_driver = { }; module_platform_driver(msm8953_noc_driver); -MODULE_DEVICE_TABLE(of, msm8953_noc_of_match); MODULE_DESCRIPTION("Qualcomm MSM8953 NoC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/qcom/nord.c b/drivers/interconnect/qcom/nord.c new file mode 100644 index 000000000000..b3ca5675e7c8 --- /dev/null +++ b/drivers/interconnect/qcom/nord.c @@ -0,0 +1,2682 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "bcm-voter.h" +#include "icc-rpmh.h" + +static struct qcom_icc_node qup0_core_slave = { + .name = "qup0_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup1_core_slave = { + .name = "qup1_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup2_core_slave = { + .name = "qup2_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qup3_core_slave = { + .name = "qup3_core_slave", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node ps_eth_0 = { + .name = "ps_eth_0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node ps_eth_1 = { + .name = "ps_eth_1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node ps_shs_server = { + .name = "ps_shs_server", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy0 = { + .name = "qhs_ahb2phy0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy1 = { + .name = "qhs_ahb2phy1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy2 = { + .name = "qhs_ahb2phy2", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy3 = { + .name = "qhs_ahb2phy3", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy_eth_0 = { + .name = "qhs_ahb2phy_eth_0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ahb2phy_eth_1 = { + .name = "qhs_ahb2phy_eth_1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_camera_cfg = { + .name = "qhs_camera_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_clk_ctl = { + .name = "qhs_clk_ctl", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_crypto0_cfg = { + .name = "qhs_crypto0_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_crypto1_cfg = { + .name = "qhs_crypto1_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_crypto2_cfg = { + .name = "qhs_crypto2_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_display_1_cfg = { + .name = "qhs_display_1_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_display_cfg = { + .name = "qhs_display_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_dprx0 = { + .name = "qhs_dprx0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_dprx1 = { + .name = "qhs_dprx1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_eva_cfg = { + .name = "qhs_eva_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_gpuss_0_cfg = { + .name = "qhs_gpuss_0_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qhs_gpuss_1_cfg = { + .name = "qhs_gpuss_1_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qhs_i2c = { + .name = "qhs_i2c", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_imem_cfg = { + .name = "qhs_imem_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_mcw_pcie = { + .name = "qhs_mcw_pcie", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_mm_rscc = { + .name = "qhs_mm_rscc", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ne_clk_ctl = { + .name = "qhs_ne_clk_ctl", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_nspss0_cfg = { + .name = "qhs_nspss0_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_nspss1_cfg = { + .name = "qhs_nspss1_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_nspss2_cfg = { + .name = "qhs_nspss2_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_nspss3_cfg = { + .name = "qhs_nspss3_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_nw_clk_ctl = { + .name = "qhs_nw_clk_ctl", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_prng = { + .name = "qhs_prng", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qdss_cfg = { + .name = "qhs_qdss_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qspi = { + .name = "qhs_qspi", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup0 = { + .name = "qhs_qup0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup3 = { + .name = "qhs_qup3", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup1 = { + .name = "qhs_qup1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_qup2 = { + .name = "qhs_qup2", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_safedma_cfg = { + .name = "qhs_safedma_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_sdc4 = { + .name = "qhs_sdc4", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_se_clk_ctl = { + .name = "qhs_se_clk_ctl", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_tcsr = { + .name = "qhs_tcsr", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_tlmm = { + .name = "qhs_tlmm", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_tsc_cfg = { + .name = "qhs_tsc_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ufs_mem_cfg = { + .name = "qhs_ufs_mem_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_usb2 = { + .name = "qhs_usb2", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_usb3_0 = { + .name = "qhs_usb3_0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_usb3_1 = { + .name = "qhs_usb3_1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_venus_cfg = { + .name = "qhs_venus_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_computenoc_cfg = { + .name = "qss_computenoc_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_qtc_cfg = { + .name = "qss_qtc_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node xs_qdss_stm = { + .name = "xs_qdss_stm", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node xs_sys_tcu0_cfg = { + .name = "xs_sys_tcu0_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node xs_sys_tcu1_cfg = { + .name = "xs_sys_tcu1_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node xs_sys_tcu2_cfg = { + .name = "xs_sys_tcu2_cfg", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qhs_aoss = { + .name = "qhs_aoss", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_hbcu = { + .name = "qhs_hbcu", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ipa = { + .name = "qhs_ipa", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_ipc_router = { + .name = "qhs_ipc_router", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_soccp = { + .name = "qhs_soccp", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_tme_cfg = { + .name = "qhs_tme_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qss_ddrss_cfg = { + .name = "qss_ddrss_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qxs_imem = { + .name = "qxs_imem", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node ebi = { + .name = "ebi", + .channels = 16, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_ahb2phy_cfg = { + .name = "qhs_pcie_ahb2phy_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_cfg_0 = { + .name = "qhs_pcie_cfg_0", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_cfg_1 = { + .name = "qhs_pcie_cfg_1", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_cfg_2 = { + .name = "qhs_pcie_cfg_2", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_cfg_3 = { + .name = "qhs_pcie_cfg_3", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_dma_0_cfg = { + .name = "qhs_pcie_dma_0_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_dma_1_cfg = { + .name = "qhs_pcie_dma_1_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qhs_pcie_dma_2_cfg = { + .name = "qhs_pcie_dma_2_cfg", + .channels = 1, + .buswidth = 4, +}; + +static struct qcom_icc_node qxs_pcie_dma_0 = { + .name = "qxs_pcie_dma_0", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qxs_pcie_dma_1 = { + .name = "qxs_pcie_dma_1", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qxs_pcie_dma_2 = { + .name = "qxs_pcie_dma_2", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node xs_pcie_0 = { + .name = "xs_pcie_0", + .channels = 1, + .buswidth = 32, +}; + +static struct qcom_icc_node xs_pcie_1 = { + .name = "xs_pcie_1", + .channels = 1, + .buswidth = 32, +}; + +static struct qcom_icc_node xs_pcie_2 = { + .name = "xs_pcie_2", + .channels = 1, + .buswidth = 16, +}; + +static struct qcom_icc_node xs_pcie_3 = { + .name = "xs_pcie_3", + .channels = 1, + .buswidth = 8, +}; + +static struct qcom_icc_node qup0_core_master = { + .name = "qup0_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup0_core_slave }, +}; + +static struct qcom_icc_node qup1_core_master = { + .name = "qup1_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup1_core_slave }, +}; + +static struct qcom_icc_node qup2_core_master = { + .name = "qup2_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup2_core_slave }, +}; + +static struct qcom_icc_node qup3_core_master = { + .name = "qup3_core_master", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qup3_core_slave }, +}; + +static struct qcom_icc_node llcc_mc = { + .name = "llcc_mc", + .channels = 16, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &ebi }, +}; + +static struct qcom_icc_node qsm_pcie_noc_cfg = { + .name = "qsm_pcie_noc_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 8, + .link_nodes = { &qhs_pcie_ahb2phy_cfg, &qhs_pcie_cfg_0, + &qhs_pcie_cfg_1, &qhs_pcie_cfg_2, + &qhs_pcie_cfg_3, &qhs_pcie_dma_0_cfg, + &qhs_pcie_dma_1_cfg, &qhs_pcie_dma_2_cfg }, +}; + +static struct qcom_icc_node qnm_cnoc_pcie_dma = { + .name = "qnm_cnoc_pcie_dma", + .channels = 1, + .buswidth = 16, + .num_links = 3, + .link_nodes = { &qxs_pcie_dma_0, &qxs_pcie_dma_1, + &qxs_pcie_dma_2 }, +}; + +static struct qcom_icc_node qnm_hscnoc_pcie = { + .name = "qnm_hscnoc_pcie", + .channels = 1, + .buswidth = 32, + .num_links = 4, + .link_nodes = { &xs_pcie_0, &xs_pcie_1, + &xs_pcie_2, &xs_pcie_3 }, +}; + +static struct qcom_icc_node qnm_pcie_ibnoc_dma = { + .name = "qnm_pcie_ibnoc_dma", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &xs_pcie_0 }, +}; + +static struct qcom_icc_node qss_pcie_noc_cfg = { + .name = "qss_pcie_noc_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_pcie_noc_cfg }, +}; + +static struct qcom_icc_node qns_pcie_dma = { + .name = "qns_pcie_dma", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_cnoc_pcie_dma }, +}; + +static struct qcom_icc_node qns_llcc = { + .name = "qns_llcc", + .channels = 16, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &llcc_mc }, +}; + +static struct qcom_icc_node qns_pcie = { + .name = "qns_pcie", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_hscnoc_pcie }, +}; + +static struct qcom_icc_node qns_pcie_obnoc_dma = { + .name = "qns_pcie_obnoc_dma", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_pcie_ibnoc_dma }, +}; + +static struct qcom_icc_node qsm_cfg = { + .name = "qsm_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 56, + .link_nodes = { &ps_eth_0, &ps_eth_1, + &ps_shs_server, &qhs_ahb2phy0, + &qhs_ahb2phy1, &qhs_ahb2phy2, + &qhs_ahb2phy3, &qhs_ahb2phy_eth_0, + &qhs_ahb2phy_eth_1, &qhs_camera_cfg, + &qhs_clk_ctl, &qhs_crypto0_cfg, + &qhs_crypto1_cfg, &qhs_crypto2_cfg, + &qhs_display_1_cfg, &qhs_display_cfg, + &qhs_dprx0, &qhs_dprx1, + &qhs_eva_cfg, &qhs_gpuss_0_cfg, + &qhs_gpuss_1_cfg, &qhs_i2c, + &qhs_imem_cfg, &qhs_mcw_pcie, + &qhs_mm_rscc, &qhs_ne_clk_ctl, + &qhs_nspss0_cfg, &qhs_nspss1_cfg, + &qhs_nspss2_cfg, &qhs_nspss3_cfg, + &qhs_nw_clk_ctl, &qhs_prng, + &qhs_qdss_cfg, &qhs_qspi, + &qhs_qup0, &qhs_qup3, + &qhs_qup1, &qhs_qup2, + &qhs_safedma_cfg, &qhs_sdc4, + &qhs_se_clk_ctl, &qhs_tcsr, + &qhs_tlmm, &qhs_tsc_cfg, + &qhs_ufs_mem_cfg, &qhs_usb2, + &qhs_usb3_0, &qhs_usb3_1, + &qhs_venus_cfg, &qss_computenoc_cfg, + &qss_pcie_noc_cfg, &qss_qtc_cfg, + &xs_qdss_stm, &xs_sys_tcu0_cfg, + &xs_sys_tcu1_cfg, &xs_sys_tcu2_cfg }, +}; + +static struct qcom_icc_node xm_gic = { + .name = "xm_gic", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xa44000 }, + .prio = 4, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_llcc }, +}; + +static struct qcom_icc_node qss_cfg = { + .name = "qss_cfg", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qsm_cfg }, +}; + +static struct qcom_icc_node qhm_mm_rscc = { + .name = "qhm_mm_rscc", + .channels = 1, + .buswidth = 4, + .num_links = 1, + .link_nodes = { &qss_cfg }, +}; + +static struct qcom_icc_node qnm_hscnoc = { + .name = "qnm_hscnoc", + .channels = 1, + .buswidth = 16, + .num_links = 10, + .link_nodes = { &qhs_aoss, &qhs_hbcu, + &qhs_ipa, &qhs_ipc_router, + &qhs_soccp, &qhs_tme_cfg, + &qns_pcie_dma, &qss_cfg, + &qss_ddrss_cfg, &qxs_imem }, +}; + +static struct qcom_icc_node qns_hscnoc_cnoc = { + .name = "qns_hscnoc_cnoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_hscnoc }, +}; + +static struct qcom_icc_node alm_gpu_tcu = { + .name = "alm_gpu_tcu", + .channels = 2, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x930000, 0xa45000 }, + .prio = 1, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node alm_qtc = { + .name = "alm_qtc", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x2c0000 }, + .prio = 3, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node alm_sys_tcu0 = { + .name = "alm_sys_tcu0", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xa42000 }, + .prio = 6, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node alm_sys_tcu1 = { + .name = "alm_sys_tcu1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x81f000 }, + .prio = 6, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node alm_sys_tcu2 = { + .name = "alm_sys_tcu2", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x30000 }, + .prio = 6, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node chm_apps = { + .name = "chm_apps", + .channels = 6, + .buswidth = 32, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_aggre_north = { + .name = "qnm_aggre_north", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x935000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_aggre_south = { + .name = "qnm_aggre_south", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x31000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_gpu0 = { + .name = "qnm_gpu0", + .channels = 4, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 4, + .port_offsets = { 0x931000, 0x932000, 0x933000, 0x934000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_gpu1 = { + .name = "qnm_gpu1", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0xa40000, 0xa41000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_hpass_adas_hscnoc = { + .name = "qnm_hpass_adas_hscnoc", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x240000, 0x245000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_hpass_audio_hscnoc = { + .name = "qnm_hpass_audio_hscnoc", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x241000 }, + .prio = 3, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_mnoc_hf = { + .name = "qnm_mnoc_hf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x81d000, 0x820000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_mnoc_sf = { + .name = "qnm_mnoc_sf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x81e000, 0x821000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_nsp0_hscnoc = { + .name = "qnm_nsp0_hscnoc", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x32000, 0x33000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_nsp1_hscnoc = { + .name = "qnm_nsp1_hscnoc", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x34000, 0x35000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_nsp2_hscnoc = { + .name = "qnm_nsp2_hscnoc", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x36000, 0x37000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_nsp3_hscnoc = { + .name = "qnm_nsp3_hscnoc", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x38000, 0x39000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_pcie = { + .name = "qnm_pcie", + .channels = 1, + .buswidth = 64, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x2c1000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 2, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc }, +}; + +static struct qcom_icc_node qnm_sailss_md0_hscnoc = { + .name = "qnm_sailss_md0_hscnoc", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x243000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qnm_snoc_sf = { + .name = "qnm_snoc_sf", + .channels = 1, + .buswidth = 64, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xa43000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 3, + .link_nodes = { &qns_hscnoc_cnoc, &qns_llcc, + &qns_pcie }, +}; + +static struct qcom_icc_node qns_a1noc_hscnoc = { + .name = "qns_a1noc_hscnoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_aggre_north }, +}; + +static struct qcom_icc_node qns_a2noc_hscnoc = { + .name = "qns_a2noc_hscnoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_aggre_south }, +}; + +static struct qcom_icc_node qns_hpass_agnoc_audio = { + .name = "qns_hpass_agnoc_audio", + .channels = 1, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_hpass_audio_hscnoc }, +}; + +static struct qcom_icc_node qns_mem_noc_hf = { + .name = "qns_mem_noc_hf", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_mnoc_hf }, +}; + +static struct qcom_icc_node qns_mem_noc_sf = { + .name = "qns_mem_noc_sf", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_mnoc_sf }, +}; + +static struct qcom_icc_node qns_nsp0_hsc_noc = { + .name = "qns_nsp0_hsc_noc", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_nsp0_hscnoc }, +}; + +static struct qcom_icc_node qns_nsp1_hsc_noc = { + .name = "qns_nsp1_hsc_noc", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_nsp1_hscnoc }, +}; + +static struct qcom_icc_node qns_nsp2_hsc_noc = { + .name = "qns_nsp2_hsc_noc", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_nsp2_hscnoc }, +}; + +static struct qcom_icc_node qns_nsp3_hsc_noc = { + .name = "qns_nsp3_hsc_noc", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qnm_nsp3_hscnoc }, +}; + +static struct qcom_icc_node qns_pcie_hscnoc = { + .name = "qns_pcie_hscnoc", + .channels = 1, + .buswidth = 64, + .num_links = 1, + .link_nodes = { &qnm_pcie }, +}; + +static struct qcom_icc_node qns_hscnoc_sf = { + .name = "qns_hscnoc_sf", + .channels = 1, + .buswidth = 64, + .num_links = 1, + .link_nodes = { &qnm_snoc_sf }, +}; + +static struct qcom_icc_node qhm_qup2 = { + .name = "qhm_qup2", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1b000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node qxm_crypto_0 = { + .name = "qxm_crypto_0", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1c000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node qxm_crypto_1 = { + .name = "qxm_crypto_1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1d000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node qxm_crypto_2 = { + .name = "qxm_crypto_2", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1e000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node xm_sdc4 = { + .name = "xm_sdc4", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x16000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node xm_ufs_mem = { + .name = "xm_ufs_mem", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x17000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node xm_usb2 = { + .name = "xm_usb2", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x19000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node xm_usb3_0 = { + .name = "xm_usb3_0", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x18000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node xm_usb3_1 = { + .name = "xm_usb3_1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1a000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_hscnoc }, +}; + +static struct qcom_icc_node qhm_qup0 = { + .name = "qhm_qup0", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x13000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_hscnoc }, +}; + +static struct qcom_icc_node qhm_qup1 = { + .name = "qhm_qup1", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x14000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_hscnoc }, +}; + +static struct qcom_icc_node xm_emac_0 = { + .name = "xm_emac_0", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x16000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_hscnoc }, +}; + +static struct qcom_icc_node xm_emac_1 = { + .name = "xm_emac_1", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x17000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_hscnoc }, +}; + +static struct qcom_icc_node qnm_hpass_dsp0 = { + .name = "qnm_hpass_dsp0", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_hpass_agnoc_audio }, +}; + +static struct qcom_icc_node qnm_hpass_dsp1 = { + .name = "qnm_hpass_dsp1", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_hpass_agnoc_audio }, +}; + +static struct qcom_icc_node qnm_hpass_dsp2 = { + .name = "qnm_hpass_dsp2", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_hpass_agnoc_audio }, +}; + +static struct qcom_icc_node qnm_camnoc_hf = { + .name = "qnm_camnoc_hf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x57000, 0x58000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_camnoc_nrt_icp_sf = { + .name = "qnm_camnoc_nrt_icp_sf", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1a000 }, + .prio = 4, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_camnoc_rt_cdm_sf = { + .name = "qnm_camnoc_rt_cdm_sf", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x5b000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_camnoc_sf = { + .name = "qnm_camnoc_sf", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x1b000, 0x1c000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_dprx0 = { + .name = "qnm_dprx0", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x5c000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_dprx1 = { + .name = "qnm_dprx1", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x5d000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_mdp0 = { + .name = "qnm_mdp0", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x59000, 0x5a000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_mdp1 = { + .name = "qnm_mdp1", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x5e000, 0x5f000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_node qnm_video_cv_cpu = { + .name = "qnm_video_cv_cpu", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x21000 }, + .prio = 4, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_eva = { + .name = "qnm_video_eva", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x22000, 0x23000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_mvp0 = { + .name = "qnm_video_mvp0", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x1d000, 0x1e000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_mvp1 = { + .name = "qnm_video_mvp1", + .channels = 2, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x1f000, 0x20000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_video_v_cpu = { + .name = "qnm_video_v_cpu", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x24000 }, + .prio = 4, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_node qnm_nsp_data00 = { + .name = "qnm_nsp_data00", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_nsp0_hsc_noc }, +}; + +static struct qcom_icc_node qnm_nsp_data01 = { + .name = "qnm_nsp_data01", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_nsp1_hsc_noc }, +}; + +static struct qcom_icc_node qnm_nsp_data02 = { + .name = "qnm_nsp_data02", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_nsp2_hsc_noc }, +}; + +static struct qcom_icc_node qnm_nsp_data03 = { + .name = "qnm_nsp_data03", + .channels = 2, + .buswidth = 32, + .num_links = 1, + .link_nodes = { &qns_nsp3_hsc_noc }, +}; + +static struct qcom_icc_node qxm_pcie_dma_0 = { + .name = "qxm_pcie_dma_0", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x49000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 0, + }, + .num_links = 2, + .link_nodes = { &qns_pcie_hscnoc, &qns_pcie_obnoc_dma }, +}; + +static struct qcom_icc_node qxm_pcie_dma_1 = { + .name = "qxm_pcie_dma_1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x4a000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 0, + }, + .num_links = 2, + .link_nodes = { &qns_pcie_hscnoc, &qns_pcie_obnoc_dma }, +}; + +static struct qcom_icc_node qxm_pcie_dma_2 = { + .name = "qxm_pcie_dma_2", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x4b000 }, + .prio = 0, + .urg_fwd = 0, + .prio_fwd_disable = 0, + }, + .num_links = 2, + .link_nodes = { &qns_pcie_hscnoc, &qns_pcie_obnoc_dma }, +}; + +static struct qcom_icc_node xm_pcie_0 = { + .name = "xm_pcie_0", + .channels = 1, + .buswidth = 64, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x18000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_pcie_hscnoc }, +}; + +static struct qcom_icc_node xm_pcie_1 = { + .name = "xm_pcie_1", + .channels = 1, + .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x19000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_pcie_hscnoc }, +}; + +static struct qcom_icc_node xm_pcie_2 = { + .name = "xm_pcie_2", + .channels = 1, + .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1a000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_pcie_hscnoc }, +}; + +static struct qcom_icc_node xm_pcie_3 = { + .name = "xm_pcie_3", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1b000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_pcie_hscnoc }, +}; + +static struct qcom_icc_node qnm_aggre1_noc = { + .name = "qnm_aggre1_noc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qns_hscnoc_sf }, +}; + +static struct qcom_icc_node qnm_aggre2_noc = { + .name = "qnm_aggre2_noc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qns_hscnoc_sf }, +}; + +static struct qcom_icc_node qnm_cnoc_data = { + .name = "qnm_cnoc_data", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1a000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_hscnoc_sf }, +}; + +static struct qcom_icc_node qnm_nsi_noc = { + .name = "qnm_nsi_noc", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x19000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_hscnoc_sf }, +}; + +static struct qcom_icc_node qnm_safe_dma = { + .name = "qnm_safe_dma", + .channels = 1, + .buswidth = 64, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1b000 }, + .prio = 0, + .urg_fwd = 1, + .prio_fwd_disable = 0, + }, + .num_links = 1, + .link_nodes = { &qns_hscnoc_sf }, +}; + +static struct qcom_icc_node qns_a1noc_snoc = { + .name = "qns_a1noc_snoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_aggre1_noc }, +}; + +static struct qcom_icc_node qns_a2noc_snoc = { + .name = "qns_a2noc_snoc", + .channels = 1, + .buswidth = 16, + .num_links = 1, + .link_nodes = { &qnm_aggre2_noc }, +}; + +static struct qcom_icc_node qhm_qspi = { + .name = "qhm_qspi", + .channels = 1, + .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x18000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qnm_sailss_md1 = { + .name = "qnm_sailss_md1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x16000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qxm_qup3 = { + .name = "qxm_qup3", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x17000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a1noc_snoc }, +}; + +static struct qcom_icc_node qxm_ipa = { + .name = "qxm_ipa", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x13000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_snoc }, +}; + +static struct qcom_icc_node qxm_soccp = { + .name = "qxm_soccp", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x16000 }, + .prio = 2, + .urg_fwd = 1, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_snoc }, +}; + +static struct qcom_icc_node xm_qdss_etr_0 = { + .name = "xm_qdss_etr_0", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x14000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_snoc }, +}; + +static struct qcom_icc_node xm_qdss_etr_1 = { + .name = "xm_qdss_etr_1", + .channels = 1, + .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x15000 }, + .prio = 2, + .urg_fwd = 0, + .prio_fwd_disable = 1, + }, + .num_links = 1, + .link_nodes = { &qns_a2noc_snoc }, +}; + +static struct qcom_icc_bcm bcm_c0n0 = { + .name = "C0N0", + .enable_mask = BIT(0), + .num_nodes = 2, + .nodes = { &qnm_nsp_data00, &qns_nsp0_hsc_noc }, +}; + +static struct qcom_icc_bcm bcm_c1n0 = { + .name = "C1N0", + .enable_mask = BIT(0), + .num_nodes = 2, + .nodes = { &qnm_nsp_data01, &qns_nsp1_hsc_noc }, +}; + +static struct qcom_icc_bcm bcm_c2n0 = { + .name = "C2N0", + .enable_mask = BIT(0), + .num_nodes = 2, + .nodes = { &qnm_nsp_data02, &qns_nsp2_hsc_noc }, +}; + +static struct qcom_icc_bcm bcm_c3n0 = { + .name = "C3N0", + .enable_mask = BIT(0), + .num_nodes = 2, + .nodes = { &qnm_nsp_data03, &qns_nsp3_hsc_noc }, +}; + +static struct qcom_icc_bcm bcm_ce0 = { + .name = "CE0", + .num_nodes = 1, + .nodes = { &qxm_crypto_0 }, +}; + +static struct qcom_icc_bcm bcm_ce1 = { + .name = "CE1", + .num_nodes = 1, + .nodes = { &qxm_crypto_1 }, +}; + +static struct qcom_icc_bcm bcm_ce2 = { + .name = "CE2", + .num_nodes = 1, + .nodes = { &qxm_crypto_2 }, +}; + +static struct qcom_icc_bcm bcm_cn0 = { + .name = "CN0", + .keepalive = true, + .enable_mask = BIT(0), + .num_nodes = 6, + .nodes = { &qsm_cfg, &qhm_mm_rscc, + &qnm_hscnoc, &qnm_cnoc_pcie_dma, + &qnm_hscnoc_pcie, &qnm_pcie_ibnoc_dma }, +}; + +static struct qcom_icc_bcm bcm_cn1 = { + .name = "CN1", + .num_nodes = 2, + .nodes = { &qhs_display_1_cfg, &qhs_display_cfg }, +}; + +static struct qcom_icc_bcm bcm_mc0 = { + .name = "MC0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_mm0 = { + .name = "MM0", + .num_nodes = 1, + .nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_bcm bcm_mm1 = { + .name = "MM1", + .enable_mask = BIT(0), + .num_nodes = 14, + .nodes = { &qnm_camnoc_hf, &qnm_camnoc_nrt_icp_sf, + &qnm_camnoc_rt_cdm_sf, &qnm_camnoc_sf, + &qnm_dprx0, &qnm_dprx1, + &qnm_mdp0, &qnm_mdp1, + &qnm_video_cv_cpu, &qnm_video_eva, + &qnm_video_mvp0, &qnm_video_mvp1, + &qnm_video_v_cpu, &qns_mem_noc_sf }, +}; + +static struct qcom_icc_bcm bcm_qup0 = { + .name = "QUP0", + .vote_scale = 1, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qup0_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup1 = { + .name = "QUP1", + .vote_scale = 1, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qup1_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup2 = { + .name = "QUP2", + .vote_scale = 1, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qup2_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup3 = { + .name = "QUP3", + .vote_scale = 1, + .keepalive = true, + .num_nodes = 1, + .nodes = { &qup3_core_slave }, +}; + +static struct qcom_icc_bcm bcm_sh0 = { + .name = "SH0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_llcc }, +}; + +static struct qcom_icc_bcm bcm_sh1 = { + .name = "SH1", + .enable_mask = BIT(0), + .num_nodes = 24, + .nodes = { &alm_gpu_tcu, &alm_qtc, + &alm_sys_tcu0, &alm_sys_tcu1, + &alm_sys_tcu2, &chm_apps, + &qnm_aggre_north, &qnm_aggre_south, + &qnm_gpu0, &qnm_gpu1, + &qnm_hpass_adas_hscnoc, &qnm_hpass_audio_hscnoc, + &qnm_mnoc_hf, &qnm_mnoc_sf, + &qnm_nsp0_hscnoc, &qnm_nsp1_hscnoc, + &qnm_nsp2_hscnoc, &qnm_nsp3_hscnoc, + &qnm_pcie, &qnm_sailss_md0_hscnoc, + &qnm_snoc_sf, &xm_gic, + &qns_hscnoc_cnoc, &qns_pcie }, +}; + +static struct qcom_icc_bcm bcm_sn0 = { + .name = "SN0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_hscnoc_sf }, +}; + +static struct qcom_icc_bcm bcm_sn1 = { + .name = "SN1", + .enable_mask = BIT(0), + .num_nodes = 14, + .nodes = { &qns_a1noc_hscnoc, &qns_a2noc_hscnoc, + &qxm_pcie_dma_0, &qxm_pcie_dma_1, + &qxm_pcie_dma_2, &xm_pcie_0, + &xm_pcie_1, &xm_pcie_2, + &xm_pcie_3, &qns_pcie_hscnoc, + &qns_pcie_obnoc_dma, &qnm_cnoc_data, + &qnm_nsi_noc, &qnm_safe_dma }, +}; + +static struct qcom_icc_bcm bcm_sn2 = { + .name = "SN2", + .num_nodes = 1, + .nodes = { &qnm_aggre1_noc }, +}; + +static struct qcom_icc_bcm bcm_sn3 = { + .name = "SN3", + .num_nodes = 1, + .nodes = { &qnm_aggre2_noc }, +}; + +static struct qcom_icc_node * const aggre1_noc_nodes[] = { + [MASTER_QSPI_0] = &qhm_qspi, + [MASTER_SAILSS_MD1] = &qnm_sailss_md1, + [MASTER_QUP_3] = &qxm_qup3, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, +}; + +static const struct regmap_config nord_aggre1_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1c400, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_aggre1_noc = { + .config = &nord_aggre1_noc_regmap_config, + .nodes = aggre1_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), +}; + +static struct qcom_icc_bcm * const aggre1_noc_tile_bcms[] = { + &bcm_ce0, + &bcm_ce1, + &bcm_ce2, + &bcm_sn1, +}; + +static struct qcom_icc_node * const aggre1_noc_tile_nodes[] = { + [MASTER_QUP_2] = &qhm_qup2, + [MASTER_CRYPTO_CORE0] = &qxm_crypto_0, + [MASTER_CRYPTO_CORE1] = &qxm_crypto_1, + [MASTER_CRYPTO_CORE2] = &qxm_crypto_2, + [MASTER_SDCC_4] = &xm_sdc4, + [MASTER_UFS_MEM] = &xm_ufs_mem, + [MASTER_USB2] = &xm_usb2, + [MASTER_USB3_0] = &xm_usb3_0, + [MASTER_USB3_1] = &xm_usb3_1, + [SLAVE_A1NOC_HSCNOC] = &qns_a1noc_hscnoc, +}; + +static const struct regmap_config nord_aggre1_noc_tile_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x23400, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_aggre1_noc_tile = { + .config = &nord_aggre1_noc_tile_regmap_config, + .nodes = aggre1_noc_tile_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_tile_nodes), + .bcms = aggre1_noc_tile_bcms, + .num_bcms = ARRAY_SIZE(aggre1_noc_tile_bcms), +}; + +static struct qcom_icc_node * const aggre2_noc_nodes[] = { + [MASTER_IPA] = &qxm_ipa, + [MASTER_SOCCP_AGGR_NOC] = &qxm_soccp, + [MASTER_QDSS_ETR] = &xm_qdss_etr_0, + [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1, + [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, +}; + +static const struct regmap_config nord_aggre2_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1b400, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_aggre2_noc = { + .config = &nord_aggre2_noc_regmap_config, + .nodes = aggre2_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), +}; + +static struct qcom_icc_bcm * const aggre2_noc_tile_bcms[] = { + &bcm_sn1, +}; + +static struct qcom_icc_node * const aggre2_noc_tile_nodes[] = { + [MASTER_QUP_0] = &qhm_qup0, + [MASTER_QUP_1] = &qhm_qup1, + [MASTER_EMAC_0] = &xm_emac_0, + [MASTER_EMAC_1] = &xm_emac_1, + [SLAVE_A2NOC_HSCNOC] = &qns_a2noc_hscnoc, +}; + +static const struct regmap_config nord_aggre2_noc_tile_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1b400, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_aggre2_noc_tile = { + .config = &nord_aggre2_noc_tile_regmap_config, + .nodes = aggre2_noc_tile_nodes, + .num_nodes = ARRAY_SIZE(aggre2_noc_tile_nodes), + .bcms = aggre2_noc_tile_bcms, + .num_bcms = ARRAY_SIZE(aggre2_noc_tile_bcms), +}; + +static struct qcom_icc_bcm * const clk_virt_bcms[] = { + &bcm_qup0, + &bcm_qup1, + &bcm_qup2, + &bcm_qup3, +}; + +static struct qcom_icc_node * const clk_virt_nodes[] = { + [MASTER_QUP_CORE_0] = &qup0_core_master, + [MASTER_QUP_CORE_1] = &qup1_core_master, + [MASTER_QUP_CORE_2] = &qup2_core_master, + [MASTER_QUP_CORE_3] = &qup3_core_master, + [SLAVE_QUP_CORE_0] = &qup0_core_slave, + [SLAVE_QUP_CORE_1] = &qup1_core_slave, + [SLAVE_QUP_CORE_2] = &qup2_core_slave, + [SLAVE_QUP_CORE_3] = &qup3_core_slave, +}; + +static const struct qcom_icc_desc nord_clk_virt = { + .nodes = clk_virt_nodes, + .num_nodes = ARRAY_SIZE(clk_virt_nodes), + .bcms = clk_virt_bcms, + .num_bcms = ARRAY_SIZE(clk_virt_bcms), +}; + +static struct qcom_icc_bcm * const cnoc_cfg_bcms[] = { + &bcm_cn0, + &bcm_cn1, +}; + +static struct qcom_icc_node * const cnoc_cfg_nodes[] = { + [MASTER_CNOC_CFG] = &qsm_cfg, + [SLAVE_PS_ETH_0] = &ps_eth_0, + [SLAVE_PS_ETH_1] = &ps_eth_1, + [SLAVE_SHS_SERVER] = &ps_shs_server, + [SLAVE_AHB2PHY_0] = &qhs_ahb2phy0, + [SLAVE_AHB2PHY_1] = &qhs_ahb2phy1, + [SLAVE_AHB2PHY_2] = &qhs_ahb2phy2, + [SLAVE_AHB2PHY_3] = &qhs_ahb2phy3, + [SLAVE_AHB2PHY_ETH_0] = &qhs_ahb2phy_eth_0, + [SLAVE_AHB2PHY_ETH_1] = &qhs_ahb2phy_eth_1, + [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg, + [SLAVE_CRYPTO_1_CFG] = &qhs_crypto1_cfg, + [SLAVE_CRYPTO_2_CFG] = &qhs_crypto2_cfg, + [SLAVE_DISPLAY_1_CFG] = &qhs_display_1_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_display_cfg, + [SLAVE_DPRX0] = &qhs_dprx0, + [SLAVE_DPRX1] = &qhs_dprx1, + [SLAVE_EVA_CFG] = &qhs_eva_cfg, + [SLAVE_GFX3D_CFG] = &qhs_gpuss_0_cfg, + [SLAVE_GFX3D_1_CFG] = &qhs_gpuss_1_cfg, + [SLAVE_I2C] = &qhs_i2c, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_MCW_PCIE] = &qhs_mcw_pcie, + [SLAVE_MM_RSCC] = &qhs_mm_rscc, + [SLAVE_NE_CLK_CTL] = &qhs_ne_clk_ctl, + [SLAVE_NSPSS0_CFG] = &qhs_nspss0_cfg, + [SLAVE_NSPSS1_CFG] = &qhs_nspss1_cfg, + [SLAVE_NSPSS2_CFG] = &qhs_nspss2_cfg, + [SLAVE_NSPSS3_CFG] = &qhs_nspss3_cfg, + [SLAVE_NW_CLK_CTL] = &qhs_nw_clk_ctl, + [SLAVE_PRNG] = &qhs_prng, + [SLAVE_QDSS_CFG] = &qhs_qdss_cfg, + [SLAVE_QSPI_0] = &qhs_qspi, + [SLAVE_QUP_0] = &qhs_qup0, + [SLAVE_QUP_3] = &qhs_qup3, + [SLAVE_QUP_1] = &qhs_qup1, + [SLAVE_QUP_2] = &qhs_qup2, + [SLAVE_SAFEDMA_CFG] = &qhs_safedma_cfg, + [SLAVE_SDCC_4] = &qhs_sdc4, + [SLAVE_SE_CLK_CTL] = &qhs_se_clk_ctl, + [SLAVE_TCSR] = &qhs_tcsr, + [SLAVE_TLMM] = &qhs_tlmm, + [SLAVE_TSC_CFG] = &qhs_tsc_cfg, + [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg, + [SLAVE_USB2] = &qhs_usb2, + [SLAVE_USB3_0] = &qhs_usb3_0, + [SLAVE_USB3_1] = &qhs_usb3_1, + [SLAVE_VENUS_CFG] = &qhs_venus_cfg, + [SLAVE_COMPUTENOC_CFG] = &qss_computenoc_cfg, + [SLAVE_PCIE_NOC_CFG] = &qss_pcie_noc_cfg, + [SLAVE_QTC_CFG] = &qss_qtc_cfg, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_SYS_TCU0_CFG] = &xs_sys_tcu0_cfg, + [SLAVE_SYS_TCU1_CFG] = &xs_sys_tcu1_cfg, + [SLAVE_SYS_TCU2_CFG] = &xs_sys_tcu2_cfg, +}; + +static const struct regmap_config nord_cnoc_cfg_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xd200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_cnoc_cfg = { + .config = &nord_cnoc_cfg_regmap_config, + .nodes = cnoc_cfg_nodes, + .num_nodes = ARRAY_SIZE(cnoc_cfg_nodes), + .bcms = cnoc_cfg_bcms, + .num_bcms = ARRAY_SIZE(cnoc_cfg_bcms), +}; + +static struct qcom_icc_bcm * const cnoc_main_bcms[] = { + &bcm_cn0, +}; + +static struct qcom_icc_node * const cnoc_main_nodes[] = { + [MASTER_MM_RSCC] = &qhm_mm_rscc, + [MASTER_HSCNOC_CNOC] = &qnm_hscnoc, + [SLAVE_AOSS] = &qhs_aoss, + [SLAVE_HBCU] = &qhs_hbcu, + [SLAVE_IPA_CFG] = &qhs_ipa, + [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router, + [SLAVE_SOCCP] = &qhs_soccp, + [SLAVE_TME_CFG] = &qhs_tme_cfg, + [SLAVE_PCIE_DMA] = &qns_pcie_dma, + [SLAVE_CNOC_CFG] = &qss_cfg, + [SLAVE_DDRSS_CFG] = &qss_ddrss_cfg, + [SLAVE_IMEM] = &qxs_imem, +}; + +static const struct regmap_config nord_cnoc_main_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1d200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_cnoc_main = { + .config = &nord_cnoc_main_regmap_config, + .nodes = cnoc_main_nodes, + .num_nodes = ARRAY_SIZE(cnoc_main_nodes), + .bcms = cnoc_main_bcms, + .num_bcms = ARRAY_SIZE(cnoc_main_bcms), +}; + +static struct qcom_icc_node * const hpass_ag_noc_nodes[] = { + [MASTER_HPASS_PROC_0] = &qnm_hpass_dsp0, + [MASTER_HPASS_PROC_1] = &qnm_hpass_dsp1, + [MASTER_HPASS_PROC_2] = &qnm_hpass_dsp2, + [SLAVE_HPASS_AGNOC_AUDIO] = &qns_hpass_agnoc_audio, +}; + +static const struct regmap_config nord_hpass_ag_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x37080, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_hpass_ag_noc = { + .config = &nord_hpass_ag_noc_regmap_config, + .nodes = hpass_ag_noc_nodes, + .num_nodes = ARRAY_SIZE(hpass_ag_noc_nodes), +}; + +static struct qcom_icc_bcm * const hscnoc_bcms[] = { + &bcm_sh0, + &bcm_sh1, +}; + +static struct qcom_icc_node * const hscnoc_nodes[] = { + [MASTER_GPU_TCU] = &alm_gpu_tcu, + [MASTER_QTC_TCU] = &alm_qtc, + [MASTER_SYS_TCU_0] = &alm_sys_tcu0, + [MASTER_SYS_TCU_1] = &alm_sys_tcu1, + [MASTER_SYS_TCU_2] = &alm_sys_tcu2, + [MASTER_APPSS_PROC] = &chm_apps, + [MASTER_A1NOC_TILE_HSCNOC] = &qnm_aggre_north, + [MASTER_A2NOC_TILE_HSCNOC] = &qnm_aggre_south, + [MASTER_GFX3D] = &qnm_gpu0, + [MASTER_GFX3D_1] = &qnm_gpu1, + [MASTER_HPASS_ADAS_HSCNOC] = &qnm_hpass_adas_hscnoc, + [MASTER_HPASS_AUDIO_HSCNOC] = &qnm_hpass_audio_hscnoc, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_NSP0_HSCNOC] = &qnm_nsp0_hscnoc, + [MASTER_NSP1_HSCNOC] = &qnm_nsp1_hscnoc, + [MASTER_NSP2_HSCNOC] = &qnm_nsp2_hscnoc, + [MASTER_NSP3_HSCNOC] = &qnm_nsp3_hscnoc, + [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie, + [MASTER_SAILSS_MD0_HSCNOC] = &qnm_sailss_md0_hscnoc, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_GIC] = &xm_gic, + [SLAVE_HSCNOC_CNOC] = &qns_hscnoc_cnoc, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie, +}; + +static const struct regmap_config nord_hscnoc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xa45080, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_hscnoc = { + .config = &nord_hscnoc_regmap_config, + .nodes = hscnoc_nodes, + .num_nodes = ARRAY_SIZE(hscnoc_nodes), + .bcms = hscnoc_bcms, + .num_bcms = ARRAY_SIZE(hscnoc_bcms), +}; + +static struct qcom_icc_bcm * const mc_virt_bcms[] = { + &bcm_mc0, +}; + +static struct qcom_icc_node * const mc_virt_nodes[] = { + [MASTER_LLCC] = &llcc_mc, + [SLAVE_EBI1] = &ebi, +}; + +static const struct qcom_icc_desc nord_mc_virt = { + .nodes = mc_virt_nodes, + .num_nodes = ARRAY_SIZE(mc_virt_nodes), + .bcms = mc_virt_bcms, + .num_bcms = ARRAY_SIZE(mc_virt_bcms), +}; + +static struct qcom_icc_bcm * const mmss_noc_bcms[] = { + &bcm_mm0, + &bcm_mm1, +}; + +static struct qcom_icc_node * const mmss_noc_nodes[] = { + [MASTER_CAMNOC_HF] = &qnm_camnoc_hf, + [MASTER_CAMNOC_NRT_ICP_SF] = &qnm_camnoc_nrt_icp_sf, + [MASTER_CAMNOC_RT_CDM_SF] = &qnm_camnoc_rt_cdm_sf, + [MASTER_CAMNOC_SF] = &qnm_camnoc_sf, + [MASTER_DPRX0] = &qnm_dprx0, + [MASTER_DPRX1] = &qnm_dprx1, + [MASTER_MDP0] = &qnm_mdp0, + [MASTER_MDP1] = &qnm_mdp1, + [MASTER_VIDEO_CV_PROC] = &qnm_video_cv_cpu, + [MASTER_VIDEO_EVA] = &qnm_video_eva, + [MASTER_VIDEO_MVP0] = &qnm_video_mvp0, + [MASTER_VIDEO_MVP1] = &qnm_video_mvp1, + [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf, +}; + +static const struct regmap_config nord_mmss_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x72800, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_mmss_noc = { + .config = &nord_mmss_noc_regmap_config, + .nodes = mmss_noc_nodes, + .num_nodes = ARRAY_SIZE(mmss_noc_nodes), + .bcms = mmss_noc_bcms, + .num_bcms = ARRAY_SIZE(mmss_noc_bcms), +}; + +static struct qcom_icc_bcm * const nsp_data_noc_0_bcms[] = { + &bcm_c0n0, +}; + +static struct qcom_icc_node * const nsp_data_noc_0_nodes[] = { + [MASTER_NSP0_PROC] = &qnm_nsp_data00, + [SLAVE_NSP0_HSC_NOC] = &qns_nsp0_hsc_noc, +}; + +static const struct regmap_config nord_nsp_data_noc_0_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x2a200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_nsp_data_noc_0 = { + .config = &nord_nsp_data_noc_0_regmap_config, + .nodes = nsp_data_noc_0_nodes, + .num_nodes = ARRAY_SIZE(nsp_data_noc_0_nodes), + .bcms = nsp_data_noc_0_bcms, + .num_bcms = ARRAY_SIZE(nsp_data_noc_0_bcms), +}; + +static struct qcom_icc_bcm * const nsp_data_noc_1_bcms[] = { + &bcm_c1n0, +}; + +static struct qcom_icc_node * const nsp_data_noc_1_nodes[] = { + [MASTER_NSP1_PROC] = &qnm_nsp_data01, + [SLAVE_NSP1_HSC_NOC] = &qns_nsp1_hsc_noc, +}; + +static const struct regmap_config nord_nsp_data_noc_1_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x2a200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_nsp_data_noc_1 = { + .config = &nord_nsp_data_noc_1_regmap_config, + .nodes = nsp_data_noc_1_nodes, + .num_nodes = ARRAY_SIZE(nsp_data_noc_1_nodes), + .bcms = nsp_data_noc_1_bcms, + .num_bcms = ARRAY_SIZE(nsp_data_noc_1_bcms), +}; + +static struct qcom_icc_bcm * const nsp_data_noc_2_bcms[] = { + &bcm_c2n0, +}; + +static struct qcom_icc_node * const nsp_data_noc_2_nodes[] = { + [MASTER_NSP2_PROC] = &qnm_nsp_data02, + [SLAVE_NSP2_HSC_NOC] = &qns_nsp2_hsc_noc, +}; + +static const struct regmap_config nord_nsp_data_noc_2_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x2a200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_nsp_data_noc_2 = { + .config = &nord_nsp_data_noc_2_regmap_config, + .nodes = nsp_data_noc_2_nodes, + .num_nodes = ARRAY_SIZE(nsp_data_noc_2_nodes), + .bcms = nsp_data_noc_2_bcms, + .num_bcms = ARRAY_SIZE(nsp_data_noc_2_bcms), +}; + +static struct qcom_icc_bcm * const nsp_data_noc_3_bcms[] = { + &bcm_c3n0, +}; + +static struct qcom_icc_node * const nsp_data_noc_3_nodes[] = { + [MASTER_NSP3_PROC] = &qnm_nsp_data03, + [SLAVE_NSP3_HSC_NOC] = &qns_nsp3_hsc_noc, +}; + +static const struct regmap_config nord_nsp_data_noc_3_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x2a200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_nsp_data_noc_3 = { + .config = &nord_nsp_data_noc_3_regmap_config, + .nodes = nsp_data_noc_3_nodes, + .num_nodes = ARRAY_SIZE(nsp_data_noc_3_nodes), + .bcms = nsp_data_noc_3_bcms, + .num_bcms = ARRAY_SIZE(nsp_data_noc_3_bcms), +}; + +static struct qcom_icc_node * const pcie_cfg_nodes[] = { + [MASTER_PCIE_NOC_CFG] = &qsm_pcie_noc_cfg, + [SLAVE_PCIE_AHB2PHY_CFG] = &qhs_pcie_ahb2phy_cfg, + [SLAVE_PCIE_CFG_0] = &qhs_pcie_cfg_0, + [SLAVE_PCIE_CFG_1] = &qhs_pcie_cfg_1, + [SLAVE_PCIE_CFG_2] = &qhs_pcie_cfg_2, + [SLAVE_PCIE_CFG_3] = &qhs_pcie_cfg_3, + [SLAVE_PCIE_DMA_0_CFG] = &qhs_pcie_dma_0_cfg, + [SLAVE_PCIE_DMA_1_CFG] = &qhs_pcie_dma_1_cfg, + [SLAVE_PCIE_DMA_2_CFG] = &qhs_pcie_dma_2_cfg, +}; + +static const struct regmap_config nord_pcie_cfg_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x7200, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_pcie_cfg = { + .config = &nord_pcie_cfg_regmap_config, + .nodes = pcie_cfg_nodes, + .num_nodes = ARRAY_SIZE(pcie_cfg_nodes), +}; + +static struct qcom_icc_bcm * const pcie_data_inbound_bcms[] = { + &bcm_sn1, +}; + +static struct qcom_icc_node * const pcie_data_inbound_nodes[] = { + [MASTER_PCIE_DMA_0] = &qxm_pcie_dma_0, + [MASTER_PCIE_DMA_1] = &qxm_pcie_dma_1, + [MASTER_PCIE_DMA_2] = &qxm_pcie_dma_2, + [MASTER_PCIE_0] = &xm_pcie_0, + [MASTER_PCIE_1] = &xm_pcie_1, + [MASTER_PCIE_2] = &xm_pcie_2, + [MASTER_PCIE_3] = &xm_pcie_3, + [SLAVE_PCIE_HSCNOC] = &qns_pcie_hscnoc, + [SLAVE_PCIE_OBNOC_DMA] = &qns_pcie_obnoc_dma, +}; + +static const struct regmap_config nord_pcie_data_inbound_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x4b080, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_pcie_data_inbound = { + .config = &nord_pcie_data_inbound_regmap_config, + .nodes = pcie_data_inbound_nodes, + .num_nodes = ARRAY_SIZE(pcie_data_inbound_nodes), + .bcms = pcie_data_inbound_bcms, + .num_bcms = ARRAY_SIZE(pcie_data_inbound_bcms), +}; + +static struct qcom_icc_bcm * const pcie_data_outbound_bcms[] = { + &bcm_cn0, +}; + +static struct qcom_icc_node * const pcie_data_outbound_nodes[] = { + [MASTER_CNOC_PCIE_DMA] = &qnm_cnoc_pcie_dma, + [MASTER_ANOC_PCIE_HSCNOC] = &qnm_hscnoc_pcie, + [MASTER_PCIE_IBNOC_DMA] = &qnm_pcie_ibnoc_dma, + [SLAVE_PCIE_DMA_0] = &qxs_pcie_dma_0, + [SLAVE_PCIE_DMA_1] = &qxs_pcie_dma_1, + [SLAVE_PCIE_DMA_2] = &qxs_pcie_dma_2, + [SLAVE_PCIE_0] = &xs_pcie_0, + [SLAVE_PCIE_1] = &xs_pcie_1, + [SLAVE_PCIE_2] = &xs_pcie_2, + [SLAVE_PCIE_3] = &xs_pcie_3, +}; + +static const struct regmap_config nord_pcie_data_outbound_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x17000, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_pcie_data_outbound = { + .config = &nord_pcie_data_outbound_regmap_config, + .nodes = pcie_data_outbound_nodes, + .num_nodes = ARRAY_SIZE(pcie_data_outbound_nodes), + .bcms = pcie_data_outbound_bcms, + .num_bcms = ARRAY_SIZE(pcie_data_outbound_bcms), +}; + +static struct qcom_icc_bcm * const system_noc_bcms[] = { + &bcm_sn0, + &bcm_sn1, + &bcm_sn2, + &bcm_sn3, +}; + +static struct qcom_icc_node * const system_noc_nodes[] = { + [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, + [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, + [MASTER_CNOC_SNOC] = &qnm_cnoc_data, + [MASTER_NSINOC_SNOC] = &qnm_nsi_noc, + [MASTER_SAFE_DMA] = &qnm_safe_dma, + [SLAVE_SNOC_HSCNOC_SF] = &qns_hscnoc_sf, +}; + +static const struct regmap_config nord_system_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1c080, + .fast_io = true, +}; + +static const struct qcom_icc_desc nord_system_noc = { + .config = &nord_system_noc_regmap_config, + .nodes = system_noc_nodes, + .num_nodes = ARRAY_SIZE(system_noc_nodes), + .bcms = system_noc_bcms, + .num_bcms = ARRAY_SIZE(system_noc_bcms), +}; + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,nord-aggre1-noc", .data = &nord_aggre1_noc }, + { .compatible = "qcom,nord-aggre1-noc-tile", .data = &nord_aggre1_noc_tile }, + { .compatible = "qcom,nord-aggre2-noc", .data = &nord_aggre2_noc }, + { .compatible = "qcom,nord-aggre2-noc-tile", .data = &nord_aggre2_noc_tile }, + { .compatible = "qcom,nord-clk-virt", .data = &nord_clk_virt }, + { .compatible = "qcom,nord-cnoc-cfg", .data = &nord_cnoc_cfg }, + { .compatible = "qcom,nord-cnoc-main", .data = &nord_cnoc_main }, + { .compatible = "qcom,nord-hpass-ag-noc", .data = &nord_hpass_ag_noc }, + { .compatible = "qcom,nord-hscnoc", .data = &nord_hscnoc }, + { .compatible = "qcom,nord-mc-virt", .data = &nord_mc_virt }, + { .compatible = "qcom,nord-mmss-noc", .data = &nord_mmss_noc }, + { .compatible = "qcom,nord-nsp-data-noc-0", .data = &nord_nsp_data_noc_0 }, + { .compatible = "qcom,nord-nsp-data-noc-1", .data = &nord_nsp_data_noc_1 }, + { .compatible = "qcom,nord-nsp-data-noc-2", .data = &nord_nsp_data_noc_2 }, + { .compatible = "qcom,nord-nsp-data-noc-3", .data = &nord_nsp_data_noc_3 }, + { .compatible = "qcom,nord-pcie-cfg", .data = &nord_pcie_cfg }, + { .compatible = "qcom,nord-pcie-data-inbound", .data = &nord_pcie_data_inbound }, + { .compatible = "qcom,nord-pcie-data-outbound", .data = &nord_pcie_data_outbound }, + { .compatible = "qcom,nord-system-noc", .data = &nord_system_noc }, + { } +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qcom_icc_rpmh_probe, + .remove = qcom_icc_rpmh_remove, + .driver = { + .name = "qnoc-nord", + .of_match_table = qnoc_of_match, + .sync_state = icc_sync_state, + }, +}; + +static int __init qnoc_driver_init(void) +{ + return platform_driver_register(&qnoc_driver); +} +core_initcall(qnoc_driver_init); + +static void __exit qnoc_driver_exit(void) +{ + platform_driver_unregister(&qnoc_driver); +} +module_exit(qnoc_driver_exit); + +MODULE_DESCRIPTION("Qualcomm Nord NoC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/qcom/shikra.c b/drivers/interconnect/qcom/shikra.c new file mode 100644 index 000000000000..bc40d1592fb3 --- /dev/null +++ b/drivers/interconnect/qcom/shikra.c @@ -0,0 +1,1837 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icc-rpm.h" + +static const char * const sys_noc_intf_clocks[] = { + "emac0_axi", + "emac1_axi", + "usb2_axi", + "usb3_axi", +}; + +static const char * const memnoc_intf_clocks[] = { + "gpu_axi", +}; + +enum { + SHIKRA_MASTER_QUP_CORE_0 = 1, + SHIKRA_SNOC_CNOC_MAS, + SHIKRA_MASTER_QDSS_DAP, + SHIKRA_MASTER_LLCC, + SHIKRA_MASTER_GRAPHICS_3D, + SHIKRA_MASTER_MNOC_HF_MEM_NOC, + SHIKRA_MASTER_ANOC_PCIE_MEM_NOC, + SHIKRA_MASTER_SNOC_SF_MEM_NOC, + SHIKRA_MASTER_AMPSS_M0, + SHIKRA_MASTER_SYS_TCU, + SHIKRA_MASTER_CAMNOC_SF, + SHIKRA_MASTER_VIDEO_P0, + SHIKRA_MASTER_VIDEO_PROC, + SHIKRA_MASTER_CAMNOC_HF, + SHIKRA_MASTER_MDP_PORT0, + SHIKRA_MASTER_MMRT_VIRT, + SHIKRA_MASTER_SNOC_CFG, + SHIKRA_MASTER_TIC, + SHIKRA_MASTER_ANOC_SNOC, + SHIKRA_MASTER_MEMNOC_PCIE, + SHIKRA_MASTER_MEMNOC_SNOC, + SHIKRA_MASTER_PIMEM, + SHIKRA_MASTER_PCIE2_0, + SHIKRA_MASTER_QDSS_BAM, + SHIKRA_MASTER_QPIC, + SHIKRA_MASTER_QUP_0, + SHIKRA_CNOC_SNOC_MAS, + SHIKRA_MASTER_AUDIO, + SHIKRA_MASTER_EMAC_0, + SHIKRA_MASTER_EMAC_1, + SHIKRA_MASTER_QDSS_ETR, + SHIKRA_MASTER_SDCC_1, + SHIKRA_MASTER_SDCC_2, + SHIKRA_MASTER_USB2_0, + SHIKRA_MASTER_USB3, + SHIKRA_MASTER_CRYPTO_CORE0, + + SHIKRA_SLAVE_QUP_CORE_0, + SHIKRA_SLAVE_AHB2PHY_USB, + SHIKRA_SLAVE_APSS_THROTTLE_CFG, + SHIKRA_SLAVE_AUDIO, + SHIKRA_SLAVE_BOOT_ROM, + SHIKRA_SLAVE_CAMERA_NRT_THROTTLE_CFG, + SHIKRA_SLAVE_CAMERA_CFG, + SHIKRA_SLAVE_CDSP_THROTTLE_CFG, + SHIKRA_SLAVE_CLK_CTL, + SHIKRA_SLAVE_DSP_CFG, + SHIKRA_SLAVE_RBCPR_CX_CFG, + SHIKRA_SLAVE_RBCPR_MX_CFG, + SHIKRA_SLAVE_CRYPTO_0_CFG, + SHIKRA_SLAVE_DDR_SS_CFG, + SHIKRA_SLAVE_DISPLAY_CFG, + SHIKRA_SLAVE_EMAC0_CFG, + SHIKRA_SLAVE_EMAC1_CFG, + SHIKRA_SLAVE_GPU_CFG, + SHIKRA_SLAVE_GPU_THROTTLE_CFG, + SHIKRA_SLAVE_HWKM, + SHIKRA_SLAVE_IMEM_CFG, + SHIKRA_SLAVE_MAPSS, + SHIKRA_SLAVE_MDSP_MPU_CFG, + SHIKRA_SLAVE_MESSAGE_RAM, + SHIKRA_SLAVE_MSS, + SHIKRA_SLAVE_PCIE_CFG, + SHIKRA_SLAVE_PDM, + SHIKRA_SLAVE_PIMEM_CFG, + SHIKRA_SLAVE_PKA_WRAPPER_CFG, + SHIKRA_SLAVE_PMIC_ARB, + SHIKRA_SLAVE_QDSS_CFG, + SHIKRA_SLAVE_QM_CFG, + SHIKRA_SLAVE_QM_MPU_CFG, + SHIKRA_SLAVE_QPIC, + SHIKRA_SLAVE_QUP_0, + SHIKRA_SLAVE_RPM, + SHIKRA_SLAVE_SDCC_1, + SHIKRA_SLAVE_SDCC_2, + SHIKRA_SLAVE_SECURITY, + SHIKRA_SLAVE_SNOC_CFG, + SHIKRA_SNOC_SF_THROTTLE_CFG, + SHIKRA_SLAVE_TLMM, + SHIKRA_SLAVE_TSCSS, + SHIKRA_SLAVE_USB2, + SHIKRA_SLAVE_USB3, + SHIKRA_SLAVE_VENUS_CFG, + SHIKRA_SLAVE_VENUS_THROTTLE_CFG, + SHIKRA_SLAVE_VSENSE_CTRL_CFG, + SHIKRA_SLAVE_SERVICE_CNOC, + SHIKRA_SLAVE_EBI_CH0, + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, + SHIKRA_SLAVE_MEM_NOC_PCIE_SNOC, + SHIKRA_SLAVE_MMNRT_VIRT, + SHIKRA_SLAVE_MM_MEMNOC, + SHIKRA_SLAVE_APPSS, + SHIKRA_SLAVE_MCUSS, + SHIKRA_SLAVE_WCSS, + SHIKRA_SLAVE_MEMNOC_SF, + SHIKRA_SNOC_CNOC_SLV, + SHIKRA_SLAVE_BOOTIMEM, + SHIKRA_SLAVE_OCIMEM, + SHIKRA_SLAVE_PIMEM, + SHIKRA_SLAVE_SERVICE_SNOC, + SHIKRA_SLAVE_PCIE2_0, + SHIKRA_SLAVE_QDSS_STM, + SHIKRA_SLAVE_TCU, + SHIKRA_SLAVE_PCIE_MEMNOC, + SHIKRA_SLAVE_ANOC_SNOC, +}; + +/* Master nodes */ +static const u16 qup0_core_master_links[] = { + SHIKRA_SLAVE_QUP_CORE_0, +}; + +static struct qcom_icc_node qup0_core_master = { + .id = SHIKRA_MASTER_QUP_CORE_0, + .name = "qup0_core_master", + .buswidth = 4, + .mas_rpm_id = 170, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qup0_core_master_links), + .links = qup0_core_master_links, +}; + +static const u16 qnm_snoc_cnoc_links[] = { + SHIKRA_SLAVE_AHB2PHY_USB, + SHIKRA_SLAVE_APSS_THROTTLE_CFG, + SHIKRA_SLAVE_AUDIO, + SHIKRA_SLAVE_BOOT_ROM, + SHIKRA_SLAVE_CAMERA_NRT_THROTTLE_CFG, + SHIKRA_SLAVE_CAMERA_CFG, + SHIKRA_SLAVE_CDSP_THROTTLE_CFG, + SHIKRA_SLAVE_CLK_CTL, + SHIKRA_SLAVE_DSP_CFG, + SHIKRA_SLAVE_RBCPR_CX_CFG, + SHIKRA_SLAVE_RBCPR_MX_CFG, + SHIKRA_SLAVE_CRYPTO_0_CFG, + SHIKRA_SLAVE_DDR_SS_CFG, + SHIKRA_SLAVE_DISPLAY_CFG, + SHIKRA_SLAVE_EMAC0_CFG, + SHIKRA_SLAVE_EMAC1_CFG, + SHIKRA_SLAVE_GPU_CFG, + SHIKRA_SLAVE_GPU_THROTTLE_CFG, + SHIKRA_SLAVE_HWKM, + SHIKRA_SLAVE_IMEM_CFG, + SHIKRA_SLAVE_MAPSS, + SHIKRA_SLAVE_MDSP_MPU_CFG, + SHIKRA_SLAVE_MESSAGE_RAM, + SHIKRA_SLAVE_MSS, + SHIKRA_SLAVE_PCIE_CFG, + SHIKRA_SLAVE_PDM, + SHIKRA_SLAVE_PIMEM_CFG, + SHIKRA_SLAVE_PKA_WRAPPER_CFG, + SHIKRA_SLAVE_PMIC_ARB, + SHIKRA_SLAVE_QDSS_CFG, + SHIKRA_SLAVE_QM_CFG, + SHIKRA_SLAVE_QM_MPU_CFG, + SHIKRA_SLAVE_QPIC, + SHIKRA_SLAVE_QUP_0, + SHIKRA_SLAVE_RPM, + SHIKRA_SLAVE_SDCC_1, + SHIKRA_SLAVE_SDCC_2, + SHIKRA_SLAVE_SECURITY, + SHIKRA_SLAVE_SNOC_CFG, + SHIKRA_SNOC_SF_THROTTLE_CFG, + SHIKRA_SLAVE_TLMM, + SHIKRA_SLAVE_TSCSS, + SHIKRA_SLAVE_USB2, + SHIKRA_SLAVE_USB3, + SHIKRA_SLAVE_VENUS_CFG, + SHIKRA_SLAVE_VENUS_THROTTLE_CFG, + SHIKRA_SLAVE_VSENSE_CTRL_CFG, + SHIKRA_SLAVE_SERVICE_CNOC, +}; + +static struct qcom_icc_node qnm_snoc_cnoc = { + .id = SHIKRA_SNOC_CNOC_MAS, + .name = "qnm_snoc_cnoc", + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_snoc_cnoc_links), + .links = qnm_snoc_cnoc_links, +}; + +static const u16 xm_dap_links[] = { + SHIKRA_SLAVE_AHB2PHY_USB, + SHIKRA_SLAVE_APSS_THROTTLE_CFG, + SHIKRA_SLAVE_AUDIO, + SHIKRA_SLAVE_BOOT_ROM, + SHIKRA_SLAVE_CAMERA_NRT_THROTTLE_CFG, + SHIKRA_SLAVE_CAMERA_CFG, + SHIKRA_SLAVE_CDSP_THROTTLE_CFG, + SHIKRA_SLAVE_CLK_CTL, + SHIKRA_SLAVE_DSP_CFG, + SHIKRA_SLAVE_RBCPR_CX_CFG, + SHIKRA_SLAVE_RBCPR_MX_CFG, + SHIKRA_SLAVE_CRYPTO_0_CFG, + SHIKRA_SLAVE_DDR_SS_CFG, + SHIKRA_SLAVE_DISPLAY_CFG, + SHIKRA_SLAVE_EMAC0_CFG, + SHIKRA_SLAVE_EMAC1_CFG, + SHIKRA_SLAVE_GPU_CFG, + SHIKRA_SLAVE_GPU_THROTTLE_CFG, + SHIKRA_SLAVE_HWKM, + SHIKRA_SLAVE_IMEM_CFG, + SHIKRA_SLAVE_MAPSS, + SHIKRA_SLAVE_MDSP_MPU_CFG, + SHIKRA_SLAVE_MESSAGE_RAM, + SHIKRA_SLAVE_MSS, + SHIKRA_SLAVE_PCIE_CFG, + SHIKRA_SLAVE_PDM, + SHIKRA_SLAVE_PIMEM_CFG, + SHIKRA_SLAVE_PKA_WRAPPER_CFG, + SHIKRA_SLAVE_PMIC_ARB, + SHIKRA_SLAVE_QDSS_CFG, + SHIKRA_SLAVE_QM_CFG, + SHIKRA_SLAVE_QM_MPU_CFG, + SHIKRA_SLAVE_QPIC, + SHIKRA_SLAVE_QUP_0, + SHIKRA_SLAVE_RPM, + SHIKRA_SLAVE_SDCC_1, + SHIKRA_SLAVE_SDCC_2, + SHIKRA_SLAVE_SECURITY, + SHIKRA_SLAVE_SNOC_CFG, + SHIKRA_SNOC_SF_THROTTLE_CFG, + SHIKRA_SLAVE_TLMM, + SHIKRA_SLAVE_TSCSS, + SHIKRA_SLAVE_USB2, + SHIKRA_SLAVE_USB3, + SHIKRA_SLAVE_VENUS_CFG, + SHIKRA_SLAVE_VENUS_THROTTLE_CFG, + SHIKRA_SLAVE_VSENSE_CTRL_CFG, + SHIKRA_SLAVE_SERVICE_CNOC, +}; + +static struct qcom_icc_node xm_dap = { + .id = SHIKRA_MASTER_QDSS_DAP, + .name = "xm_dap", + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_dap_links), + .links = xm_dap_links, +}; + +static const u16 llcc_mc_links[] = { + SHIKRA_SLAVE_EBI_CH0, +}; + +static struct qcom_icc_node llcc_mc = { + .id = SHIKRA_MASTER_LLCC, + .name = "llcc_mc", + .buswidth = 4, + .channels = 2, + .mas_rpm_id = 190, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(llcc_mc_links), + .links = llcc_mc_links, +}; + +static const u16 qnm_gpu_links[] = { + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, + SHIKRA_SLAVE_MEM_NOC_PCIE_SNOC, +}; + +static struct qcom_icc_node qnm_gpu = { + .id = SHIKRA_MASTER_GRAPHICS_3D, + .name = "qnm_gpu", + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_port = 6, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 0, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_gpu_links), + .links = qnm_gpu_links, +}; + +static const u16 qnm_mnoc_hf_links[] = { + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, + SHIKRA_SLAVE_MEM_NOC_PCIE_SNOC, +}; + +static struct qcom_icc_node qnm_mnoc_hf = { + .id = SHIKRA_MASTER_MNOC_HF_MEM_NOC, + .name = "qnm_mnoc_hf", + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_port = 7, + .qos.urg_fwd_en = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.areq_prio = 0, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_mnoc_hf_links), + .links = qnm_mnoc_hf_links, +}; + +static const u16 qnm_pcie_links[] = { + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, +}; + +static struct qcom_icc_node qnm_pcie = { + .id = SHIKRA_MASTER_ANOC_PCIE_MEM_NOC, + .name = "qnm_pcie", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 4, + .qos.urg_fwd_en = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.areq_prio = 0, + .mas_rpm_id = 185, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_pcie_links), + .links = qnm_pcie_links, +}; + +static const u16 qnm_snoc_sf_links[] = { + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, + SHIKRA_SLAVE_MEM_NOC_PCIE_SNOC, +}; + +static struct qcom_icc_node qnm_snoc_sf = { + .id = SHIKRA_MASTER_SNOC_SF_MEM_NOC, + .name = "qnm_snoc_sf", + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_port = 3, + .qos.urg_fwd_en = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.areq_prio = 0, + .mas_rpm_id = 76, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_snoc_sf_links), + .links = qnm_snoc_sf_links, +}; + +static const u16 xm_apps_links[] = { + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, + SHIKRA_SLAVE_MEM_NOC_PCIE_SNOC, +}; + +static struct qcom_icc_node xm_apps = { + .id = SHIKRA_MASTER_AMPSS_M0, + .name = "xm_apps", + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_port = 5, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 0, + .mas_rpm_id = 0, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_apps_links), + .links = xm_apps_links, +}; + +static const u16 xm_tcu_links[] = { + SHIKRA_SLAVE_LLCC, + SHIKRA_SLAVE_MEMNOC_SNOC, +}; + +static struct qcom_icc_node xm_tcu = { + .id = SHIKRA_MASTER_SYS_TCU, + .name = "xm_tcu", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 2, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 6, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_tcu_links), + .links = xm_tcu_links, +}; + +static const u16 qnm_camera_nrt_links[] = { + SHIKRA_SLAVE_MMNRT_VIRT, +}; + +static struct qcom_icc_node qnm_camera_nrt = { + .id = SHIKRA_MASTER_CAMNOC_SF, + .name = "qnm_camera_nrt", + .buswidth = 32, + .qos.ap_owned = true, + .qos.qos_port = 3, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 3, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_camera_nrt_links), + .links = qnm_camera_nrt_links, +}; + +static const u16 qxm_venus0_links[] = { + SHIKRA_SLAVE_MMNRT_VIRT, +}; + +static struct qcom_icc_node qxm_venus0 = { + .id = SHIKRA_MASTER_VIDEO_P0, + .name = "qxm_venus0", + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_port = 8, + .qos.urg_fwd_en = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.areq_prio = 0, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qxm_venus0_links), + .links = qxm_venus0_links, +}; + +static const u16 qxm_venus_cpu_links[] = { + SHIKRA_SLAVE_MMNRT_VIRT, +}; + +static struct qcom_icc_node qxm_venus_cpu = { + .id = SHIKRA_MASTER_VIDEO_PROC, + .name = "qxm_venus_cpu", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 12, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qxm_venus_cpu_links), + .links = qxm_venus_cpu_links, +}; + +static const u16 qnm_camera_rt_links[] = { + SHIKRA_SLAVE_MM_MEMNOC, +}; + +static struct qcom_icc_node qnm_camera_rt = { + .id = SHIKRA_MASTER_CAMNOC_HF, + .name = "qnm_camera_rt", + .buswidth = 32, + .qos.ap_owned = true, + .qos.qos_port = 9, + .qos.urg_fwd_en = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.areq_prio = 0, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_camera_rt_links), + .links = qnm_camera_rt_links, +}; + +static const u16 qxm_mdp0_links[] = { + SHIKRA_SLAVE_MM_MEMNOC, +}; + +static struct qcom_icc_node qxm_mdp0 = { + .id = SHIKRA_MASTER_MDP_PORT0, + .name = "qxm_mdp0", + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_port = 4, + .qos.urg_fwd_en = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.areq_prio = 0, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qxm_mdp0_links), + .links = qxm_mdp0_links, +}; + +static const u16 mmrt_virt_master_links[] = { + SHIKRA_SLAVE_MM_MEMNOC, +}; + +static struct qcom_icc_node mmrt_virt_master = { + .id = SHIKRA_MASTER_MMRT_VIRT, + .name = "mmrt_virt_master", + .buswidth = 16, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mmrt_virt_master_links), + .links = mmrt_virt_master_links, +}; + +static const u16 qhm_snoc_cfg_links[] = { + SHIKRA_SLAVE_SERVICE_SNOC, +}; + +static struct qcom_icc_node qhm_snoc_cfg = { + .id = SHIKRA_MASTER_SNOC_CFG, + .name = "qhm_snoc_cfg", + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qhm_snoc_cfg_links), + .links = qhm_snoc_cfg_links, +}; + +static const u16 qhm_tic_links[] = { + SHIKRA_SLAVE_APPSS, + SHIKRA_SLAVE_MCUSS, + SHIKRA_SLAVE_WCSS, + SHIKRA_SLAVE_MEMNOC_SF, + SHIKRA_SNOC_CNOC_SLV, + SHIKRA_SLAVE_BOOTIMEM, + SHIKRA_SLAVE_OCIMEM, + SHIKRA_SLAVE_PIMEM, + SHIKRA_SLAVE_QDSS_STM, + SHIKRA_SLAVE_TCU, +}; + +static struct qcom_icc_node qhm_tic = { + .id = SHIKRA_MASTER_TIC, + .name = "qhm_tic", + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qhm_tic_links), + .links = qhm_tic_links, +}; + +static const u16 qnm_anoc_snoc_links[] = { + SHIKRA_SLAVE_MEMNOC_SF, +}; + +static struct qcom_icc_node qnm_anoc_snoc = { + .id = SHIKRA_MASTER_ANOC_SNOC, + .name = "qnm_anoc_snoc", + .buswidth = 16, + .mas_rpm_id = 110, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_anoc_snoc_links), + .links = qnm_anoc_snoc_links, +}; + +static const u16 qnm_memnoc_pcie_links[] = { + SHIKRA_SLAVE_PCIE2_0, +}; + +static struct qcom_icc_node qnm_memnoc_pcie = { + .id = SHIKRA_MASTER_MEMNOC_PCIE, + .name = "qnm_memnoc_pcie", + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_memnoc_pcie_links), + .links = qnm_memnoc_pcie_links, +}; + +static const u16 qnm_memnoc_snoc_links[] = { + SHIKRA_SLAVE_APPSS, + SHIKRA_SLAVE_MCUSS, + SHIKRA_SLAVE_WCSS, + SHIKRA_SNOC_CNOC_SLV, + SHIKRA_SLAVE_BOOTIMEM, + SHIKRA_SLAVE_OCIMEM, + SHIKRA_SLAVE_PIMEM, + SHIKRA_SLAVE_QDSS_STM, + SHIKRA_SLAVE_TCU, +}; + +static struct qcom_icc_node qnm_memnoc_snoc = { + .id = SHIKRA_MASTER_MEMNOC_SNOC, + .name = "qnm_memnoc_snoc", + .buswidth = 8, + .mas_rpm_id = 184, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_memnoc_snoc_links), + .links = qnm_memnoc_snoc_links, +}; + +static const u16 qxm_pimem_links[] = { + SHIKRA_SLAVE_MEMNOC_SF, + SHIKRA_SLAVE_OCIMEM, +}; + +static struct qcom_icc_node qxm_pimem = { + .id = SHIKRA_MASTER_PIMEM, + .name = "qxm_pimem", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 14, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qxm_pimem_links), + .links = qxm_pimem_links, +}; + +static const u16 xm_pcie2_0_links[] = { + SHIKRA_SLAVE_PCIE_MEMNOC, +}; + +static struct qcom_icc_node xm_pcie2_0 = { + .id = SHIKRA_MASTER_PCIE2_0, + .name = "xm_pcie2_0", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 21, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = 186, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_pcie2_0_links), + .links = xm_pcie2_0_links, +}; + +static const u16 qhm_qdss_bam_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node qhm_qdss_bam = { + .id = SHIKRA_MASTER_QDSS_BAM, + .name = "qhm_qdss_bam", + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_port = 2, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qhm_qdss_bam_links), + .links = qhm_qdss_bam_links, +}; + +static const u16 qhm_qpic_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node qhm_qpic = { + .id = SHIKRA_MASTER_QPIC, + .name = "qhm_qpic", + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_port = 1, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qhm_qpic_links), + .links = qhm_qpic_links, +}; + +static const u16 qhm_qup0_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node qhm_qup0 = { + .id = SHIKRA_MASTER_QUP_0, + .name = "qhm_qup0", + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_port = 0, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = 166, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qhm_qup0_links), + .links = qhm_qup0_links, +}; + +static const u16 qnm_cnoc_snoc_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node qnm_cnoc_snoc = { + .id = SHIKRA_CNOC_SNOC_MAS, + .name = "qnm_cnoc_snoc", + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_port = 7, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qnm_cnoc_snoc_links), + .links = qnm_cnoc_snoc_links, +}; + +static const u16 qxm_audio_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node qxm_audio = { + .id = SHIKRA_MASTER_AUDIO, + .name = "qxm_audio", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 22, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 3, + .mas_rpm_id = 78, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(qxm_audio_links), + .links = qxm_audio_links, +}; + +static const u16 xm_emac_0_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_emac_0 = { + .id = SHIKRA_MASTER_EMAC_0, + .name = "xm_emac_0", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 19, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_emac_0_links), + .links = xm_emac_0_links, +}; + +static const u16 xm_emac_1_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_emac_1 = { + .id = SHIKRA_MASTER_EMAC_1, + .name = "xm_emac_1", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 20, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_emac_1_links), + .links = xm_emac_1_links, +}; + +static const u16 xm_qdss_etr_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_qdss_etr = { + .id = SHIKRA_MASTER_QDSS_ETR, + .name = "xm_qdss_etr", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 11, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_qdss_etr_links), + .links = xm_qdss_etr_links, +}; + +static const u16 xm_sdc1_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_sdc1 = { + .id = SHIKRA_MASTER_SDCC_1, + .name = "xm_sdc1", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 13, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_sdc1_links), + .links = xm_sdc1_links, +}; + +static const u16 xm_sdc2_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_sdc2 = { + .id = SHIKRA_MASTER_SDCC_2, + .name = "xm_sdc2", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 17, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_sdc2_links), + .links = xm_sdc2_links, +}; + +static const u16 xm_usb2_0_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_usb2_0 = { + .id = SHIKRA_MASTER_USB2_0, + .name = "xm_usb2_0", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 24, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_usb2_0_links), + .links = xm_usb2_0_links, +}; + +static const u16 xm_usb3_0_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node xm_usb3_0 = { + .id = SHIKRA_MASTER_USB3, + .name = "xm_usb3_0", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 18, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(xm_usb3_0_links), + .links = xm_usb3_0_links, +}; + +static const u16 crypto_c0_links[] = { + SHIKRA_SLAVE_ANOC_SNOC, +}; + +static struct qcom_icc_node crypto_c0 = { + .id = SHIKRA_MASTER_CRYPTO_CORE0, + .name = "crypto_c0", + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_port = 16, + .qos.urg_fwd_en = false, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.areq_prio = 2, + .mas_rpm_id = 23, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(crypto_c0_links), + .links = crypto_c0_links, +}; + +/* Slave nodes */ +static struct qcom_icc_node qup0_core_slave = { + .id = SHIKRA_SLAVE_QUP_CORE_0, + .name = "qup0_core_slave", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 264, +}; + +static struct qcom_icc_node qhs_ahb2phy_usb = { + .id = SHIKRA_SLAVE_AHB2PHY_USB, + .name = "qhs_ahb2phy_usb", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_apss_throttle_cfg = { + .id = SHIKRA_SLAVE_APSS_THROTTLE_CFG, + .name = "qhs_apss_throttle_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_audio = { + .id = SHIKRA_SLAVE_AUDIO, + .name = "qhs_audio", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_boot_rom = { + .id = SHIKRA_SLAVE_BOOT_ROM, + .name = "qhs_boot_rom", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_camera_nrt_throttle_cfg = { + .id = SHIKRA_SLAVE_CAMERA_NRT_THROTTLE_CFG, + .name = "qhs_camera_nrt_throttle_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_camera_ss_cfg = { + .id = SHIKRA_SLAVE_CAMERA_CFG, + .name = "qhs_camera_ss_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_cdsp_throttle_cfg = { + .id = SHIKRA_SLAVE_CDSP_THROTTLE_CFG, + .name = "qhs_cdsp_throttle_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_clk_ctl = { + .id = SHIKRA_SLAVE_CLK_CTL, + .name = "qhs_clk_ctl", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_compute_dsp_cfg = { + .id = SHIKRA_SLAVE_DSP_CFG, + .name = "qhs_compute_dsp_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_cpr_cx = { + .id = SHIKRA_SLAVE_RBCPR_CX_CFG, + .name = "qhs_cpr_cx", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_cpr_mx = { + .id = SHIKRA_SLAVE_RBCPR_MX_CFG, + .name = "qhs_cpr_mx", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_crypto0_cfg = { + .id = SHIKRA_SLAVE_CRYPTO_0_CFG, + .name = "qhs_crypto0_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_ddr_ss_cfg = { + .id = SHIKRA_SLAVE_DDR_SS_CFG, + .name = "qhs_ddr_ss_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_disp_ss_cfg = { + .id = SHIKRA_SLAVE_DISPLAY_CFG, + .name = "qhs_disp_ss_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_emac0_cfg = { + .id = SHIKRA_SLAVE_EMAC0_CFG, + .name = "qhs_emac0_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_emac1_cfg = { + .id = SHIKRA_SLAVE_EMAC1_CFG, + .name = "qhs_emac1_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_gpu_cfg = { + .id = SHIKRA_SLAVE_GPU_CFG, + .name = "qhs_gpu_cfg", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_gpu_throttle_cfg = { + .id = SHIKRA_SLAVE_GPU_THROTTLE_CFG, + .name = "qhs_gpu_throttle_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_hwkm = { + .id = SHIKRA_SLAVE_HWKM, + .name = "qhs_hwkm", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_imem_cfg = { + .id = SHIKRA_SLAVE_IMEM_CFG, + .name = "qhs_imem_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_mapss = { + .id = SHIKRA_SLAVE_MAPSS, + .name = "qhs_mapss", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_mdsp_mpu_cfg = { + .id = SHIKRA_SLAVE_MDSP_MPU_CFG, + .name = "qhs_mdsp_mpu_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_mesg_ram = { + .id = SHIKRA_SLAVE_MESSAGE_RAM, + .name = "qhs_mesg_ram", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_mss = { + .id = SHIKRA_SLAVE_MSS, + .name = "qhs_mss", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_pcie_cfg = { + .id = SHIKRA_SLAVE_PCIE_CFG, + .name = "qhs_pcie_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_pdm = { + .id = SHIKRA_SLAVE_PDM, + .name = "qhs_pdm", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_pimem_cfg = { + .id = SHIKRA_SLAVE_PIMEM_CFG, + .name = "qhs_pimem_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_pka_wrapper = { + .id = SHIKRA_SLAVE_PKA_WRAPPER_CFG, + .name = "qhs_pka_wrapper", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_pmic_arb = { + .id = SHIKRA_SLAVE_PMIC_ARB, + .name = "qhs_pmic_arb", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_qdss_cfg = { + .id = SHIKRA_SLAVE_QDSS_CFG, + .name = "qhs_qdss_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_qm_cfg = { + .id = SHIKRA_SLAVE_QM_CFG, + .name = "qhs_qm_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_qm_mpu_cfg = { + .id = SHIKRA_SLAVE_QM_MPU_CFG, + .name = "qhs_qm_mpu_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_qpic = { + .id = SHIKRA_SLAVE_QPIC, + .name = "qhs_qpic", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_qup0 = { + .id = SHIKRA_SLAVE_QUP_0, + .name = "qhs_qup0", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_rpm = { + .id = SHIKRA_SLAVE_RPM, + .name = "qhs_rpm", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_sdc1 = { + .id = SHIKRA_SLAVE_SDCC_1, + .name = "qhs_sdc1", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_sdc2 = { + .id = SHIKRA_SLAVE_SDCC_2, + .name = "qhs_sdc2", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_security = { + .id = SHIKRA_SLAVE_SECURITY, + .name = "qhs_security", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static const u16 qhs_snoc_cfg_links[] = { + SHIKRA_MASTER_SNOC_CFG, +}; + +static struct qcom_icc_node qhs_snoc_cfg = { + .id = SHIKRA_SLAVE_SNOC_CFG, + .name = "qhs_snoc_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = 1, + .links = qhs_snoc_cfg_links, +}; + +static struct qcom_icc_node qhs_snoc_sf_throttle_cfg = { + .id = SHIKRA_SNOC_SF_THROTTLE_CFG, + .name = "qhs_snoc_sf_throttle_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_tlmm = { + .id = SHIKRA_SLAVE_TLMM, + .name = "qhs_tlmm", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_tscss = { + .id = SHIKRA_SLAVE_TSCSS, + .name = "qhs_tscss", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_usb2 = { + .id = SHIKRA_SLAVE_USB2, + .name = "qhs_usb2", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_usb3 = { + .id = SHIKRA_SLAVE_USB3, + .name = "qhs_usb3", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_venus_cfg = { + .id = SHIKRA_SLAVE_VENUS_CFG, + .name = "qhs_venus_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_venus_throttle_cfg = { + .id = SHIKRA_SLAVE_VENUS_THROTTLE_CFG, + .name = "qhs_venus_throttle_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_vsense_ctrl_cfg = { + .id = SHIKRA_SLAVE_VSENSE_CTRL_CFG, + .name = "qhs_vsense_ctrl_cfg", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node srvc_cnoc = { + .id = SHIKRA_SLAVE_SERVICE_CNOC, + .name = "srvc_cnoc", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node ebi = { + .id = SHIKRA_SLAVE_EBI_CH0, + .name = "ebi", + .channels = 2, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 0, +}; + +static const u16 qns_llcc_links[] = { + SHIKRA_MASTER_LLCC, +}; + +static struct qcom_icc_node qns_llcc = { + .id = SHIKRA_SLAVE_LLCC, + .name = "qns_llcc", + .channels = 2, + .buswidth = 16, + .mas_rpm_id = -1, + .slv_rpm_id = 312, + .num_links = 1, + .links = qns_llcc_links, +}; + +static const u16 qns_memnoc_snoc_links[] = { + SHIKRA_MASTER_MEMNOC_SNOC, +}; + +static struct qcom_icc_node qns_memnoc_snoc = { + .id = SHIKRA_SLAVE_MEMNOC_SNOC, + .name = "qns_memnoc_snoc", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 314, + .num_links = 1, + .links = qns_memnoc_snoc_links, +}; + +static const u16 qns_pcie_links[] = { + SHIKRA_MASTER_MEMNOC_PCIE, +}; + +static struct qcom_icc_node qns_pcie = { + .id = SHIKRA_SLAVE_MEM_NOC_PCIE_SNOC, + .name = "qns_pcie", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = 1, + .links = qns_pcie_links, +}; + +static const u16 mmnrt_virt_slave_links[] = { + SHIKRA_MASTER_MMRT_VIRT, +}; + +static struct qcom_icc_node mmnrt_virt_slave = { + .id = SHIKRA_SLAVE_MMNRT_VIRT, + .name = "mmnrt_virt_slave", + .channels = 1, + .buswidth = 16, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = 1, + .links = mmnrt_virt_slave_links, +}; + +static const u16 qns_mm_memnoc_links[] = { + SHIKRA_MASTER_MNOC_HF_MEM_NOC, +}; + +static struct qcom_icc_node qns_mm_memnoc = { + .id = SHIKRA_SLAVE_MM_MEMNOC, + .name = "qns_mm_memnoc", + .channels = 1, + .buswidth = 16, + .mas_rpm_id = -1, + .slv_rpm_id = -1, + .num_links = 1, + .links = qns_mm_memnoc_links, +}; + +static struct qcom_icc_node qhs_apss = { + .id = SHIKRA_SLAVE_APPSS, + .name = "qhs_apss", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qhs_mcuss = { + .id = SHIKRA_SLAVE_MCUSS, + .name = "qhs_mcuss", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 319, +}; + +static struct qcom_icc_node qhs_wcss = { + .id = SHIKRA_SLAVE_WCSS, + .name = "qhs_wcss", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 23, +}; + +static const u16 qns_memnoc_sf_links[] = { + SHIKRA_MASTER_SNOC_SF_MEM_NOC, +}; + +static struct qcom_icc_node qns_memnoc_sf = { + .id = SHIKRA_SLAVE_MEMNOC_SF, + .name = "qns_memnoc_sf", + .channels = 1, + .buswidth = 16, + .mas_rpm_id = -1, + .slv_rpm_id = 313, + .num_links = 1, + .links = qns_memnoc_sf_links, +}; + +static const u16 qns_snoc_cnoc_links[] = { + SHIKRA_SNOC_CNOC_MAS, +}; + +static struct qcom_icc_node qns_snoc_cnoc = { + .id = SHIKRA_SNOC_CNOC_SLV, + .name = "qns_snoc_cnoc", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 25, + .num_links = 1, + .links = qns_snoc_cnoc_links, +}; + +static struct qcom_icc_node qxs_bootimem = { + .id = SHIKRA_SLAVE_BOOTIMEM, + .name = "qxs_bootimem", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node qxs_imem = { + .id = SHIKRA_SLAVE_OCIMEM, + .name = "qxs_imem", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 26, +}; + +static struct qcom_icc_node qxs_pimem = { + .id = SHIKRA_SLAVE_PIMEM, + .name = "qxs_pimem", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node srvc_snoc = { + .id = SHIKRA_SLAVE_SERVICE_SNOC, + .name = "srvc_snoc", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node xs_pcie2_0 = { + .id = SHIKRA_SLAVE_PCIE2_0, + .name = "xs_pcie2_0", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static struct qcom_icc_node xs_qdss_stm = { + .id = SHIKRA_SLAVE_QDSS_STM, + .name = "xs_qdss_stm", + .channels = 1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 30, +}; + +static struct qcom_icc_node xs_sys_tcu_cfg = { + .id = SHIKRA_SLAVE_TCU, + .name = "xs_sys_tcu_cfg", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = -1, +}; + +static const u16 qns_pcie_memnoc_links[] = { + SHIKRA_MASTER_ANOC_PCIE_MEM_NOC, +}; + +static struct qcom_icc_node qns_pcie_memnoc = { + .id = SHIKRA_SLAVE_PCIE_MEMNOC, + .name = "qns_pcie_memnoc", + .channels = 1, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 317, + .num_links = 1, + .links = qns_pcie_memnoc_links, +}; + +static const u16 qns_anoc_snoc_links[] = { + SHIKRA_MASTER_ANOC_SNOC, +}; + +static struct qcom_icc_node qns_anoc_snoc = { + .id = SHIKRA_SLAVE_ANOC_SNOC, + .name = "qns_anoc_snoc", + .channels = 1, + .buswidth = 16, + .mas_rpm_id = -1, + .slv_rpm_id = 141, + .num_links = 1, + .links = qns_anoc_snoc_links, +}; + +/* NoC descriptors */ +static struct qcom_icc_node * const shikra_clk_virt_nodes[] = { + [MASTER_QUP_CORE_0] = &qup0_core_master, + [SLAVE_QUP_CORE_0] = &qup0_core_slave, +}; + +static const struct qcom_icc_desc shikra_clk_virt = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_clk_virt_nodes, + .num_nodes = ARRAY_SIZE(shikra_clk_virt_nodes), + .bus_clk_desc = &qup_clk, + .keep_alive = true, +}; + +static struct qcom_icc_node * const shikra_config_noc_nodes[] = { + [SNOC_CNOC_MAS] = &qnm_snoc_cnoc, + [MASTER_QDSS_DAP] = &xm_dap, + [SLAVE_AHB2PHY_USB] = &qhs_ahb2phy_usb, + [SLAVE_APSS_THROTTLE_CFG] = &qhs_apss_throttle_cfg, + [SLAVE_AUDIO] = &qhs_audio, + [SLAVE_BOOT_ROM] = &qhs_boot_rom, + [SLAVE_CAMERA_NRT_THROTTLE_CFG] = &qhs_camera_nrt_throttle_cfg, + [SLAVE_CAMERA_CFG] = &qhs_camera_ss_cfg, + [SLAVE_CDSP_THROTTLE_CFG] = &qhs_cdsp_throttle_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_DSP_CFG] = &qhs_compute_dsp_cfg, + [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx, + [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx, + [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg, + [SLAVE_DDR_SS_CFG] = &qhs_ddr_ss_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_disp_ss_cfg, + [SLAVE_EMAC0_CFG] = &qhs_emac0_cfg, + [SLAVE_EMAC1_CFG] = &qhs_emac1_cfg, + [SLAVE_GPU_CFG] = &qhs_gpu_cfg, + [SLAVE_GPU_THROTTLE_CFG] = &qhs_gpu_throttle_cfg, + [SLAVE_HWKM] = &qhs_hwkm, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_MAPSS] = &qhs_mapss, + [SLAVE_MDSP_MPU_CFG] = &qhs_mdsp_mpu_cfg, + [SLAVE_MESSAGE_RAM] = &qhs_mesg_ram, + [SLAVE_MSS] = &qhs_mss, + [SLAVE_PCIE_CFG] = &qhs_pcie_cfg, + [SLAVE_PDM] = &qhs_pdm, + [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg, + [SLAVE_PKA_WRAPPER_CFG] = &qhs_pka_wrapper, + [SLAVE_PMIC_ARB] = &qhs_pmic_arb, + [SLAVE_QDSS_CFG] = &qhs_qdss_cfg, + [SLAVE_QM_CFG] = &qhs_qm_cfg, + [SLAVE_QM_MPU_CFG] = &qhs_qm_mpu_cfg, + [SLAVE_QPIC] = &qhs_qpic, + [SLAVE_QUP_0] = &qhs_qup0, + [SLAVE_RPM] = &qhs_rpm, + [SLAVE_SDCC_1] = &qhs_sdc1, + [SLAVE_SDCC_2] = &qhs_sdc2, + [SLAVE_SECURITY] = &qhs_security, + [SLAVE_SNOC_CFG] = &qhs_snoc_cfg, + [SNOC_SF_THROTTLE_CFG] = &qhs_snoc_sf_throttle_cfg, + [SLAVE_TLMM] = &qhs_tlmm, + [SLAVE_TSCSS] = &qhs_tscss, + [SLAVE_USB2] = &qhs_usb2, + [SLAVE_USB3] = &qhs_usb3, + [SLAVE_VENUS_CFG] = &qhs_venus_cfg, + [SLAVE_VENUS_THROTTLE_CFG] = &qhs_venus_throttle_cfg, + [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, + [SLAVE_SERVICE_CNOC] = &srvc_cnoc, +}; + +static const struct regmap_config shikra_config_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x8080, + .fast_io = true, +}; + +static const struct qcom_icc_desc shikra_config_noc = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_config_noc_nodes, + .num_nodes = ARRAY_SIZE(shikra_config_noc_nodes), + .bus_clk_desc = &bus_1_clk, + .regmap_cfg = &shikra_config_noc_regmap_config, + .keep_alive = true, +}; + +static struct qcom_icc_node * const shikra_mc_virt_nodes[] = { + [MASTER_LLCC] = &llcc_mc, + [SLAVE_EBI_CH0] = &ebi, +}; + +static const struct qcom_icc_desc shikra_mc_virt = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_mc_virt_nodes, + .num_nodes = ARRAY_SIZE(shikra_mc_virt_nodes), + .bus_clk_desc = &bimc_clk, + .keep_alive = true, + .ab_coeff = 152, +}; + +static struct qcom_icc_node * const shikra_mem_noc_core_nodes[] = { + [MASTER_GRAPHICS_3D] = &qnm_gpu, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_ANOC_PCIE_MEM_NOC] = &qnm_pcie, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_AMPSS_M0] = &xm_apps, + [MASTER_SYS_TCU] = &xm_tcu, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MEMNOC_SNOC] = &qns_memnoc_snoc, + [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie, +}; + +static const struct regmap_config shikra_mem_noc_core_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x43080, + .fast_io = true, +}; + +static const struct qcom_icc_desc shikra_mem_noc_core = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_mem_noc_core_nodes, + .num_nodes = ARRAY_SIZE(shikra_mem_noc_core_nodes), + .bus_clk_desc = &mem_1_clk, + .regmap_cfg = &shikra_mem_noc_core_regmap_config, + .intf_clocks = memnoc_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(memnoc_intf_clocks), + .qos_offset = 0x28000, + .keep_alive = true, + .ab_coeff = 142, +}; + +static struct qcom_icc_node * const shikra_mmnrt_virt_nodes[] = { + [MASTER_CAMNOC_SF] = &qnm_camera_nrt, + [MASTER_VIDEO_P0] = &qxm_venus0, + [MASTER_VIDEO_PROC] = &qxm_venus_cpu, + [SLAVE_MMNRT_VIRT] = &mmnrt_virt_slave, +}; + +static const struct regmap_config shikra_sys_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x6a080, + .fast_io = true, +}; + +static const struct qcom_icc_desc shikra_mmnrt_virt = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_mmnrt_virt_nodes, + .num_nodes = ARRAY_SIZE(shikra_mmnrt_virt_nodes), + .bus_clk_desc = &mmaxi_0_clk, + .regmap_cfg = &shikra_sys_noc_regmap_config, + .qos_offset = 0x51000, + .keep_alive = true, + .ab_coeff = 142, +}; + +static struct qcom_icc_node * const shikra_mmrt_virt_nodes[] = { + [MASTER_CAMNOC_HF] = &qnm_camera_rt, + [MASTER_MDP_PORT0] = &qxm_mdp0, + [MASTER_MMRT_VIRT] = &mmrt_virt_master, + [SLAVE_MM_MEMNOC] = &qns_mm_memnoc, +}; + +static const struct qcom_icc_desc shikra_mmrt_virt = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_mmrt_virt_nodes, + .num_nodes = ARRAY_SIZE(shikra_mmrt_virt_nodes), + .bus_clk_desc = &mmaxi_1_clk, + .regmap_cfg = &shikra_sys_noc_regmap_config, + .qos_offset = 0x51000, + .keep_alive = true, + .ab_coeff = 142, +}; + +static struct qcom_icc_node * const shikra_sys_noc_nodes[] = { + [MASTER_SNOC_CFG] = &qhm_snoc_cfg, + [MASTER_TIC] = &qhm_tic, + [MASTER_ANOC_SNOC] = &qnm_anoc_snoc, + [MASTER_MEMNOC_PCIE] = &qnm_memnoc_pcie, + [MASTER_MEMNOC_SNOC] = &qnm_memnoc_snoc, + [MASTER_PIMEM] = &qxm_pimem, + [MASTER_PCIE2_0] = &xm_pcie2_0, + [MASTER_QDSS_BAM] = &qhm_qdss_bam, + [MASTER_QPIC] = &qhm_qpic, + [MASTER_QUP_0] = &qhm_qup0, + [CNOC_SNOC_MAS] = &qnm_cnoc_snoc, + [MASTER_AUDIO] = &qxm_audio, + [MASTER_EMAC_0] = &xm_emac_0, + [MASTER_EMAC_1] = &xm_emac_1, + [MASTER_QDSS_ETR] = &xm_qdss_etr, + [MASTER_SDCC_1] = &xm_sdc1, + [MASTER_SDCC_2] = &xm_sdc2, + [MASTER_USB2_0] = &xm_usb2_0, + [MASTER_USB3] = &xm_usb3_0, + [MASTER_CRYPTO_CORE0] = &crypto_c0, + [SLAVE_APPSS] = &qhs_apss, + [SLAVE_MCUSS] = &qhs_mcuss, + [SLAVE_WCSS] = &qhs_wcss, + [SLAVE_MEMNOC_SF] = &qns_memnoc_sf, + [SNOC_CNOC_SLV] = &qns_snoc_cnoc, + [SLAVE_BOOTIMEM] = &qxs_bootimem, + [SLAVE_OCIMEM] = &qxs_imem, + [SLAVE_PIMEM] = &qxs_pimem, + [SLAVE_SERVICE_SNOC] = &srvc_snoc, + [SLAVE_PCIE2_0] = &xs_pcie2_0, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_TCU] = &xs_sys_tcu_cfg, + [SLAVE_PCIE_MEMNOC] = &qns_pcie_memnoc, + [SLAVE_ANOC_SNOC] = &qns_anoc_snoc, +}; + +static const struct qcom_icc_desc shikra_sys_noc = { + .type = QCOM_ICC_QNOC, + .nodes = shikra_sys_noc_nodes, + .num_nodes = ARRAY_SIZE(shikra_sys_noc_nodes), + .bus_clk_desc = &bus_2_clk, + .regmap_cfg = &shikra_sys_noc_regmap_config, + .intf_clocks = sys_noc_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(sys_noc_intf_clocks), + .qos_offset = 0x51000, + .keep_alive = true, +}; + +static const struct of_device_id shikra_qnoc_of_match[] = { + { .compatible = "qcom,shikra-clk-virt", .data = &shikra_clk_virt }, + { .compatible = "qcom,shikra-config-noc", .data = &shikra_config_noc }, + { .compatible = "qcom,shikra-mc-virt", .data = &shikra_mc_virt }, + { .compatible = "qcom,shikra-mem-noc-core", .data = &shikra_mem_noc_core }, + { .compatible = "qcom,shikra-mmnrt-virt", .data = &shikra_mmnrt_virt }, + { .compatible = "qcom,shikra-mmrt-virt", .data = &shikra_mmrt_virt }, + { .compatible = "qcom,shikra-sys-noc", .data = &shikra_sys_noc }, + { }, +}; +MODULE_DEVICE_TABLE(of, shikra_qnoc_of_match); + +static struct platform_driver shikra_qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-shikra", + .of_match_table = shikra_qnoc_of_match, + .sync_state = icc_sync_state, + }, +}; + +static int __init qnoc_driver_init(void) +{ + return platform_driver_register(&shikra_qnoc_driver); +} +core_initcall(qnoc_driver_init); + +static void __exit qnoc_driver_exit(void) +{ + platform_driver_unregister(&shikra_qnoc_driver); +} +module_exit(qnoc_driver_exit); + +MODULE_DESCRIPTION("Qualcomm Shikra NoC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 00683bf06258..390256ed91f4 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -381,16 +381,6 @@ config SENSORS_BH1770 To compile this driver as a module, choose M here: the module will be called bh1770glc. If unsure, say N here. -config SENSORS_APDS990X - tristate "APDS990X combined als and proximity sensors" - depends on I2C - help - Say Y here if you want to build a driver for Avago APDS990x - combined ambient light and proximity sensor chip. - - To compile this driver as a module, choose M here: the - module will be called apds990x. If unsure, say N here. - config HMC6352 tristate "Honeywell HMC6352 compass" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b32a2597d246..fed47c7672b9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -20,7 +20,6 @@ obj-$(CONFIG_RPMB) += rpmb-core.o obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o -obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o obj-$(CONFIG_KGDB_TESTS) += kgdbts.o obj-$(CONFIG_SGI_XP) += sgi-xp/ diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c deleted file mode 100644 index b69c3a1c94d1..000000000000 --- a/drivers/misc/apds990x.c +++ /dev/null @@ -1,1284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * This file is part of the APDS990x sensor driver. - * Chip is combined proximity and ambient light sensor. - * - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Samu Onkalo - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register map */ -#define APDS990X_ENABLE 0x00 /* Enable of states and interrupts */ -#define APDS990X_ATIME 0x01 /* ALS ADC time */ -#define APDS990X_PTIME 0x02 /* Proximity ADC time */ -#define APDS990X_WTIME 0x03 /* Wait time */ -#define APDS990X_AILTL 0x04 /* ALS interrupt low threshold low byte */ -#define APDS990X_AILTH 0x05 /* ALS interrupt low threshold hi byte */ -#define APDS990X_AIHTL 0x06 /* ALS interrupt hi threshold low byte */ -#define APDS990X_AIHTH 0x07 /* ALS interrupt hi threshold hi byte */ -#define APDS990X_PILTL 0x08 /* Proximity interrupt low threshold low byte */ -#define APDS990X_PILTH 0x09 /* Proximity interrupt low threshold hi byte */ -#define APDS990X_PIHTL 0x0a /* Proximity interrupt hi threshold low byte */ -#define APDS990X_PIHTH 0x0b /* Proximity interrupt hi threshold hi byte */ -#define APDS990X_PERS 0x0c /* Interrupt persistence filters */ -#define APDS990X_CONFIG 0x0d /* Configuration */ -#define APDS990X_PPCOUNT 0x0e /* Proximity pulse count */ -#define APDS990X_CONTROL 0x0f /* Gain control register */ -#define APDS990X_REV 0x11 /* Revision Number */ -#define APDS990X_ID 0x12 /* Device ID */ -#define APDS990X_STATUS 0x13 /* Device status */ -#define APDS990X_CDATAL 0x14 /* Clear ADC low data register */ -#define APDS990X_CDATAH 0x15 /* Clear ADC high data register */ -#define APDS990X_IRDATAL 0x16 /* IR ADC low data register */ -#define APDS990X_IRDATAH 0x17 /* IR ADC high data register */ -#define APDS990X_PDATAL 0x18 /* Proximity ADC low data register */ -#define APDS990X_PDATAH 0x19 /* Proximity ADC high data register */ - -/* Control */ -#define APDS990X_MAX_AGAIN 3 - -/* Enable register */ -#define APDS990X_EN_PIEN (0x1 << 5) -#define APDS990X_EN_AIEN (0x1 << 4) -#define APDS990X_EN_WEN (0x1 << 3) -#define APDS990X_EN_PEN (0x1 << 2) -#define APDS990X_EN_AEN (0x1 << 1) -#define APDS990X_EN_PON (0x1 << 0) -#define APDS990X_EN_DISABLE_ALL 0 - -/* Status register */ -#define APDS990X_ST_PINT (0x1 << 5) -#define APDS990X_ST_AINT (0x1 << 4) - -/* I2C access types */ -#define APDS990x_CMD_TYPE_MASK (0x03 << 5) -#define APDS990x_CMD_TYPE_RB (0x00 << 5) /* Repeated byte */ -#define APDS990x_CMD_TYPE_INC (0x01 << 5) /* Auto increment */ -#define APDS990x_CMD_TYPE_SPE (0x03 << 5) /* Special function */ - -#define APDS990x_ADDR_SHIFT 0 -#define APDS990x_CMD 0x80 - -/* Interrupt ack commands */ -#define APDS990X_INT_ACK_ALS 0x6 -#define APDS990X_INT_ACK_PS 0x5 -#define APDS990X_INT_ACK_BOTH 0x7 - -/* ptime */ -#define APDS990X_PTIME_DEFAULT 0xff /* Recommended conversion time 2.7ms*/ - -/* wtime */ -#define APDS990X_WTIME_DEFAULT 0xee /* ~50ms wait time */ - -#define APDS990X_TIME_TO_ADC 1024 /* One timetick as ADC count value */ - -/* Persistence */ -#define APDS990X_APERS_SHIFT 0 -#define APDS990X_PPERS_SHIFT 4 - -/* Supported ID:s */ -#define APDS990X_ID_0 0x0 -#define APDS990X_ID_4 0x4 -#define APDS990X_ID_29 0x29 - -/* pgain and pdiode settings */ -#define APDS_PGAIN_1X 0x0 -#define APDS_PDIODE_IR 0x2 - -#define APDS990X_LUX_OUTPUT_SCALE 10 - -/* Reverse chip factors for threshold calculation */ -struct reverse_factors { - u32 afactor; - int cf1; - int irf1; - int cf2; - int irf2; -}; - -struct apds990x_chip { - struct apds990x_platform_data *pdata; - struct i2c_client *client; - struct mutex mutex; /* avoid parallel access */ - struct regulator_bulk_data regs[2]; - wait_queue_head_t wait; - - int prox_en; - bool prox_continuous_mode; - bool lux_wait_fresh_res; - - /* Chip parameters */ - struct apds990x_chip_factors cf; - struct reverse_factors rcf; - u16 atime; /* als integration time */ - u16 arate; /* als reporting rate */ - u16 a_max_result; /* Max possible ADC value with current atime */ - u8 again_meas; /* Gain used in last measurement */ - u8 again_next; /* Next calculated gain */ - u8 pgain; - u8 pdiode; - u8 pdrive; - u8 lux_persistence; - u8 prox_persistence; - - u32 lux_raw; - u32 lux; - u16 lux_clear; - u16 lux_ir; - u16 lux_calib; - u32 lux_thres_hi; - u32 lux_thres_lo; - - u32 prox_thres; - u16 prox_data; - u16 prox_calib; - - char chipname[10]; - u8 revision; -}; - -#define APDS_CALIB_SCALER 8192 -#define APDS_LUX_NEUTRAL_CALIB_VALUE (1 * APDS_CALIB_SCALER) -#define APDS_PROX_NEUTRAL_CALIB_VALUE (1 * APDS_CALIB_SCALER) - -#define APDS_PROX_DEF_THRES 600 -#define APDS_PROX_HYSTERESIS 50 -#define APDS_LUX_DEF_THRES_HI 101 -#define APDS_LUX_DEF_THRES_LO 100 -#define APDS_DEFAULT_PROX_PERS 1 - -#define APDS_TIMEOUT 2000 -#define APDS_STARTUP_DELAY 25000 /* us */ -#define APDS_RANGE 65535 -#define APDS_PROX_RANGE 1023 -#define APDS_LUX_GAIN_LO_LIMIT 100 -#define APDS_LUX_GAIN_LO_LIMIT_STRICT 25 - -#define TIMESTEP 87 /* 2.7ms is about 87 / 32 */ -#define TIME_STEP_SCALER 32 - -#define APDS_LUX_AVERAGING_TIME 50 /* tolerates 50/60Hz ripple */ -#define APDS_LUX_DEFAULT_RATE 200 - -static const u8 again[] = {1, 8, 16, 120}; /* ALS gain steps */ - -/* Following two tables must match i.e 10Hz rate means 1 as persistence value */ -static const u16 arates_hz[] = {10, 5, 2, 1}; -static const u8 apersis[] = {1, 2, 4, 5}; - -/* Regulators */ -static const char reg_vcc[] = "Vdd"; -static const char reg_vled[] = "Vled"; - -static int apds990x_read_byte(struct apds990x_chip *chip, u8 reg, u8 *data) -{ - struct i2c_client *client = chip->client; - s32 ret; - - reg &= ~APDS990x_CMD_TYPE_MASK; - reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB; - - ret = i2c_smbus_read_byte_data(client, reg); - *data = ret; - return (int)ret; -} - -static int apds990x_read_word(struct apds990x_chip *chip, u8 reg, u16 *data) -{ - struct i2c_client *client = chip->client; - s32 ret; - - reg &= ~APDS990x_CMD_TYPE_MASK; - reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC; - - ret = i2c_smbus_read_word_data(client, reg); - *data = ret; - return (int)ret; -} - -static int apds990x_write_byte(struct apds990x_chip *chip, u8 reg, u8 data) -{ - struct i2c_client *client = chip->client; - s32 ret; - - reg &= ~APDS990x_CMD_TYPE_MASK; - reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB; - - ret = i2c_smbus_write_byte_data(client, reg, data); - return (int)ret; -} - -static int apds990x_write_word(struct apds990x_chip *chip, u8 reg, u16 data) -{ - struct i2c_client *client = chip->client; - s32 ret; - - reg &= ~APDS990x_CMD_TYPE_MASK; - reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC; - - ret = i2c_smbus_write_word_data(client, reg, data); - return (int)ret; -} - -static int apds990x_mode_on(struct apds990x_chip *chip) -{ - /* ALS is mandatory, proximity optional */ - u8 reg = APDS990X_EN_AIEN | APDS990X_EN_PON | APDS990X_EN_AEN | - APDS990X_EN_WEN; - - if (chip->prox_en) - reg |= APDS990X_EN_PIEN | APDS990X_EN_PEN; - - return apds990x_write_byte(chip, APDS990X_ENABLE, reg); -} - -static u16 apds990x_lux_to_threshold(struct apds990x_chip *chip, u32 lux) -{ - u32 thres; - u32 cpl; - u32 ir; - - if (lux == 0) - return 0; - else if (lux == APDS_RANGE) - return APDS_RANGE; - - /* - * Reported LUX value is a combination of the IR and CLEAR channel - * values. However, interrupt threshold is only for clear channel. - * This function approximates needed HW threshold value for a given - * LUX value in the current lightning type. - * IR level compared to visible light varies heavily depending on the - * source of the light - * - * Calculate threshold value for the next measurement period. - * Math: threshold = lux * cpl where - * cpl = atime * again / (glass_attenuation * device_factor) - * (count-per-lux) - * - * First remove calibration. Division by four is to avoid overflow - */ - lux = lux * (APDS_CALIB_SCALER / 4) / (chip->lux_calib / 4); - - /* Multiplication by 64 is to increase accuracy */ - cpl = ((u32)chip->atime * (u32)again[chip->again_next] * - APDS_PARAM_SCALE * 64) / (chip->cf.ga * chip->cf.df); - - thres = lux * cpl / 64; - /* - * Convert IR light from the latest result to match with - * new gain step. This helps to adapt with the current - * source of light. - */ - ir = (u32)chip->lux_ir * (u32)again[chip->again_next] / - (u32)again[chip->again_meas]; - - /* - * Compensate count with IR light impact - * IAC1 > IAC2 (see apds990x_get_lux for formulas) - */ - if (chip->lux_clear * APDS_PARAM_SCALE >= - chip->rcf.afactor * chip->lux_ir) - thres = (chip->rcf.cf1 * thres + chip->rcf.irf1 * ir) / - APDS_PARAM_SCALE; - else - thres = (chip->rcf.cf2 * thres + chip->rcf.irf2 * ir) / - APDS_PARAM_SCALE; - - if (thres >= chip->a_max_result) - thres = chip->a_max_result - 1; - return thres; -} - -static inline int apds990x_set_atime(struct apds990x_chip *chip, u32 time_ms) -{ - u8 reg_value; - - chip->atime = time_ms; - /* Formula is specified in the data sheet */ - reg_value = 256 - ((time_ms * TIME_STEP_SCALER) / TIMESTEP); - /* Calculate max ADC value for given integration time */ - chip->a_max_result = (u16)(256 - reg_value) * APDS990X_TIME_TO_ADC; - return apds990x_write_byte(chip, APDS990X_ATIME, reg_value); -} - -/* Called always with mutex locked */ -static int apds990x_refresh_pthres(struct apds990x_chip *chip, int data) -{ - int ret, lo, hi; - - /* If the chip is not in use, don't try to access it */ - if (pm_runtime_suspended(&chip->client->dev)) - return 0; - - if (data < chip->prox_thres) { - lo = 0; - hi = chip->prox_thres; - } else { - lo = chip->prox_thres - APDS_PROX_HYSTERESIS; - if (chip->prox_continuous_mode) - hi = chip->prox_thres; - else - hi = APDS_RANGE; - } - - ret = apds990x_write_word(chip, APDS990X_PILTL, lo); - ret |= apds990x_write_word(chip, APDS990X_PIHTL, hi); - return ret; -} - -/* Called always with mutex locked */ -static int apds990x_refresh_athres(struct apds990x_chip *chip) -{ - int ret; - /* If the chip is not in use, don't try to access it */ - if (pm_runtime_suspended(&chip->client->dev)) - return 0; - - ret = apds990x_write_word(chip, APDS990X_AILTL, - apds990x_lux_to_threshold(chip, chip->lux_thres_lo)); - ret |= apds990x_write_word(chip, APDS990X_AIHTL, - apds990x_lux_to_threshold(chip, chip->lux_thres_hi)); - - return ret; -} - -/* Called always with mutex locked */ -static void apds990x_force_a_refresh(struct apds990x_chip *chip) -{ - /* This will force ALS interrupt after the next measurement. */ - apds990x_write_word(chip, APDS990X_AILTL, APDS_LUX_DEF_THRES_LO); - apds990x_write_word(chip, APDS990X_AIHTL, APDS_LUX_DEF_THRES_HI); -} - -/* Called always with mutex locked */ -static void apds990x_force_p_refresh(struct apds990x_chip *chip) -{ - /* This will force proximity interrupt after the next measurement. */ - apds990x_write_word(chip, APDS990X_PILTL, APDS_PROX_DEF_THRES - 1); - apds990x_write_word(chip, APDS990X_PIHTL, APDS_PROX_DEF_THRES); -} - -/* Called always with mutex locked */ -static int apds990x_calc_again(struct apds990x_chip *chip) -{ - int curr_again = chip->again_meas; - int next_again = chip->again_meas; - int ret = 0; - - /* Calculate suitable als gain */ - if (chip->lux_clear == chip->a_max_result) - next_again -= 2; /* ALS saturated. Decrease gain by 2 steps */ - else if (chip->lux_clear > chip->a_max_result / 2) - next_again--; - else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) - next_again += 2; /* Too dark. Increase gain by 2 steps */ - else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT) - next_again++; - - /* Limit gain to available range */ - if (next_again < 0) - next_again = 0; - else if (next_again > APDS990X_MAX_AGAIN) - next_again = APDS990X_MAX_AGAIN; - - /* Let's check can we trust the measured result */ - if (chip->lux_clear == chip->a_max_result) - /* Result can be totally garbage due to saturation */ - ret = -ERANGE; - else if (next_again != curr_again && - chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) - /* - * Gain is changed and measurement result is very small. - * Result can be totally garbage due to underflow - */ - ret = -ERANGE; - - chip->again_next = next_again; - apds990x_write_byte(chip, APDS990X_CONTROL, - (chip->pdrive << 6) | - (chip->pdiode << 4) | - (chip->pgain << 2) | - (chip->again_next << 0)); - - /* - * Error means bad result -> re-measurement is needed. The forced - * refresh uses fastest possible persistence setting to get result - * as soon as possible. - */ - if (ret < 0) - apds990x_force_a_refresh(chip); - else - apds990x_refresh_athres(chip); - - return ret; -} - -/* Called always with mutex locked */ -static int apds990x_get_lux(struct apds990x_chip *chip, int clear, int ir) -{ - int iac, iac1, iac2; /* IR adjusted counts */ - u32 lpc; /* Lux per count */ - - /* Formulas: - * iac1 = CF1 * CLEAR_CH - IRF1 * IR_CH - * iac2 = CF2 * CLEAR_CH - IRF2 * IR_CH - */ - iac1 = (chip->cf.cf1 * clear - chip->cf.irf1 * ir) / APDS_PARAM_SCALE; - iac2 = (chip->cf.cf2 * clear - chip->cf.irf2 * ir) / APDS_PARAM_SCALE; - - iac = max(iac1, iac2); - iac = max(iac, 0); - - lpc = APDS990X_LUX_OUTPUT_SCALE * (chip->cf.df * chip->cf.ga) / - (u32)(again[chip->again_meas] * (u32)chip->atime); - - return (iac * lpc) / APDS_PARAM_SCALE; -} - -static int apds990x_ack_int(struct apds990x_chip *chip, u8 mode) -{ - struct i2c_client *client = chip->client; - s32 ret; - u8 reg = APDS990x_CMD | APDS990x_CMD_TYPE_SPE; - - switch (mode & (APDS990X_ST_AINT | APDS990X_ST_PINT)) { - case APDS990X_ST_AINT: - reg |= APDS990X_INT_ACK_ALS; - break; - case APDS990X_ST_PINT: - reg |= APDS990X_INT_ACK_PS; - break; - default: - reg |= APDS990X_INT_ACK_BOTH; - break; - } - - ret = i2c_smbus_read_byte_data(client, reg); - return (int)ret; -} - -static irqreturn_t apds990x_irq(int irq, void *data) -{ - struct apds990x_chip *chip = data; - u8 status; - - apds990x_read_byte(chip, APDS990X_STATUS, &status); - apds990x_ack_int(chip, status); - - mutex_lock(&chip->mutex); - if (!pm_runtime_suspended(&chip->client->dev)) { - if (status & APDS990X_ST_AINT) { - apds990x_read_word(chip, APDS990X_CDATAL, - &chip->lux_clear); - apds990x_read_word(chip, APDS990X_IRDATAL, - &chip->lux_ir); - /* Store used gain for calculations */ - chip->again_meas = chip->again_next; - - chip->lux_raw = apds990x_get_lux(chip, - chip->lux_clear, - chip->lux_ir); - - if (apds990x_calc_again(chip) == 0) { - /* Result is valid */ - chip->lux = chip->lux_raw; - chip->lux_wait_fresh_res = false; - wake_up(&chip->wait); - sysfs_notify(&chip->client->dev.kobj, - NULL, "lux0_input"); - } - } - - if ((status & APDS990X_ST_PINT) && chip->prox_en) { - u16 clr_ch; - - apds990x_read_word(chip, APDS990X_CDATAL, &clr_ch); - /* - * If ALS channel is saturated at min gain, - * proximity gives false posivite values. - * Just ignore them. - */ - if (chip->again_meas == 0 && - clr_ch == chip->a_max_result) - chip->prox_data = 0; - else - apds990x_read_word(chip, - APDS990X_PDATAL, - &chip->prox_data); - - apds990x_refresh_pthres(chip, chip->prox_data); - if (chip->prox_data < chip->prox_thres) - chip->prox_data = 0; - else if (!chip->prox_continuous_mode) - chip->prox_data = APDS_PROX_RANGE; - sysfs_notify(&chip->client->dev.kobj, - NULL, "prox0_raw"); - } - } - mutex_unlock(&chip->mutex); - return IRQ_HANDLED; -} - -static int apds990x_configure(struct apds990x_chip *chip) -{ - /* It is recommended to use disabled mode during these operations */ - apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL); - - /* conversion and wait times for different state machince states */ - apds990x_write_byte(chip, APDS990X_PTIME, APDS990X_PTIME_DEFAULT); - apds990x_write_byte(chip, APDS990X_WTIME, APDS990X_WTIME_DEFAULT); - apds990x_set_atime(chip, APDS_LUX_AVERAGING_TIME); - - apds990x_write_byte(chip, APDS990X_CONFIG, 0); - - /* Persistence levels */ - apds990x_write_byte(chip, APDS990X_PERS, - (chip->lux_persistence << APDS990X_APERS_SHIFT) | - (chip->prox_persistence << APDS990X_PPERS_SHIFT)); - - apds990x_write_byte(chip, APDS990X_PPCOUNT, chip->pdata->ppcount); - - /* Start with relatively small gain */ - chip->again_meas = 1; - chip->again_next = 1; - apds990x_write_byte(chip, APDS990X_CONTROL, - (chip->pdrive << 6) | - (chip->pdiode << 4) | - (chip->pgain << 2) | - (chip->again_next << 0)); - return 0; -} - -static int apds990x_detect(struct apds990x_chip *chip) -{ - struct i2c_client *client = chip->client; - int ret; - u8 id; - - ret = apds990x_read_byte(chip, APDS990X_ID, &id); - if (ret < 0) { - dev_err(&client->dev, "ID read failed\n"); - return ret; - } - - ret = apds990x_read_byte(chip, APDS990X_REV, &chip->revision); - if (ret < 0) { - dev_err(&client->dev, "REV read failed\n"); - return ret; - } - - switch (id) { - case APDS990X_ID_0: - case APDS990X_ID_4: - case APDS990X_ID_29: - snprintf(chip->chipname, sizeof(chip->chipname), "APDS-990x"); - break; - default: - ret = -ENODEV; - break; - } - return ret; -} - -#ifdef CONFIG_PM -static int apds990x_chip_on(struct apds990x_chip *chip) -{ - int err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), - chip->regs); - if (err < 0) - return err; - - usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY); - - /* Refresh all configs in case of regulators were off */ - chip->prox_data = 0; - apds990x_configure(chip); - apds990x_mode_on(chip); - return 0; -} -#endif - -static int apds990x_chip_off(struct apds990x_chip *chip) -{ - apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL); - regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); - return 0; -} - -static ssize_t apds990x_lux_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - ssize_t ret; - u32 result; - long time_left; - - if (pm_runtime_suspended(dev)) - return -EIO; - - time_left = wait_event_interruptible_timeout(chip->wait, - !chip->lux_wait_fresh_res, - msecs_to_jiffies(APDS_TIMEOUT)); - if (!time_left) - return -EIO; - - mutex_lock(&chip->mutex); - result = (chip->lux * chip->lux_calib) / APDS_CALIB_SCALER; - if (result > (APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE)) - result = APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE; - - ret = sprintf(buf, "%d.%d\n", - result / APDS990X_LUX_OUTPUT_SCALE, - result % APDS990X_LUX_OUTPUT_SCALE); - mutex_unlock(&chip->mutex); - return ret; -} - -static DEVICE_ATTR(lux0_input, S_IRUGO, apds990x_lux_show, NULL); - -static ssize_t apds990x_lux_range_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", APDS_RANGE); -} - -static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, apds990x_lux_range_show, NULL); - -static ssize_t apds990x_lux_calib_format_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", APDS_CALIB_SCALER); -} - -static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO, - apds990x_lux_calib_format_show, NULL); - -static ssize_t apds990x_lux_calib_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", chip->lux_calib); -} - -static ssize_t apds990x_lux_calib_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; - - chip->lux_calib = value; - - return len; -} - -static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, apds990x_lux_calib_show, - apds990x_lux_calib_store); - -static ssize_t apds990x_rate_avail(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int i; - int pos = 0; - - for (i = 0; i < ARRAY_SIZE(arates_hz); i++) - pos += sprintf(buf + pos, "%d ", arates_hz[i]); - sprintf(buf + pos - 1, "\n"); - return pos; -} - -static ssize_t apds990x_rate_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->arate); -} - -static int apds990x_set_arate(struct apds990x_chip *chip, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(arates_hz); i++) - if (rate >= arates_hz[i]) - break; - - if (i == ARRAY_SIZE(arates_hz)) - return -EINVAL; - - /* Pick up corresponding persistence value */ - chip->lux_persistence = apersis[i]; - chip->arate = arates_hz[i]; - - /* If the chip is not in use, don't try to access it */ - if (pm_runtime_suspended(&chip->client->dev)) - return 0; - - /* Persistence levels */ - return apds990x_write_byte(chip, APDS990X_PERS, - (chip->lux_persistence << APDS990X_APERS_SHIFT) | - (chip->prox_persistence << APDS990X_PPERS_SHIFT)); -} - -static ssize_t apds990x_rate_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; - - mutex_lock(&chip->mutex); - ret = apds990x_set_arate(chip, value); - mutex_unlock(&chip->mutex); - - if (ret < 0) - return ret; - return len; -} - -static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, apds990x_rate_avail, NULL); - -static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, apds990x_rate_show, - apds990x_rate_store); - -static ssize_t apds990x_prox_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - ssize_t ret; - struct apds990x_chip *chip = dev_get_drvdata(dev); - - if (pm_runtime_suspended(dev) || !chip->prox_en) - return -EIO; - - mutex_lock(&chip->mutex); - ret = sprintf(buf, "%d\n", chip->prox_data); - mutex_unlock(&chip->mutex); - return ret; -} - -static DEVICE_ATTR(prox0_raw, S_IRUGO, apds990x_prox_show, NULL); - -static ssize_t apds990x_prox_range_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", APDS_PROX_RANGE); -} - -static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, apds990x_prox_range_show, NULL); - -static ssize_t apds990x_prox_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->prox_en); -} - -static ssize_t apds990x_prox_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; - - mutex_lock(&chip->mutex); - - if (!chip->prox_en) - chip->prox_data = 0; - - if (value) - chip->prox_en++; - else if (chip->prox_en > 0) - chip->prox_en--; - - if (!pm_runtime_suspended(dev)) - apds990x_mode_on(chip); - mutex_unlock(&chip->mutex); - return len; -} - -static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, apds990x_prox_enable_show, - apds990x_prox_enable_store); - -static const char *reporting_modes[] = {"trigger", "periodic"}; - -static ssize_t apds990x_prox_reporting_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", - reporting_modes[!!chip->prox_continuous_mode]); -} - -static ssize_t apds990x_prox_reporting_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - int ret; - - ret = sysfs_match_string(reporting_modes, buf); - if (ret < 0) - return ret; - - chip->prox_continuous_mode = ret; - return len; -} - -static DEVICE_ATTR(prox0_reporting_mode, S_IRUGO | S_IWUSR, - apds990x_prox_reporting_mode_show, - apds990x_prox_reporting_mode_store); - -static ssize_t apds990x_prox_reporting_avail_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s %s\n", reporting_modes[0], reporting_modes[1]); -} - -static DEVICE_ATTR(prox0_reporting_mode_avail, S_IRUGO | S_IWUSR, - apds990x_prox_reporting_avail_show, NULL); - - -static ssize_t apds990x_lux_thresh_above_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->lux_thres_hi); -} - -static ssize_t apds990x_lux_thresh_below_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->lux_thres_lo); -} - -static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target, - const char *buf) -{ - unsigned long thresh; - int ret; - - ret = kstrtoul(buf, 0, &thresh); - if (ret) - return ret; - - if (thresh > APDS_RANGE) - return -EINVAL; - - mutex_lock(&chip->mutex); - *target = thresh; - /* - * Don't update values in HW if we are still waiting for - * first interrupt to come after device handle open call. - */ - if (!chip->lux_wait_fresh_res) - apds990x_refresh_athres(chip); - mutex_unlock(&chip->mutex); - return ret; - -} - -static ssize_t apds990x_lux_thresh_above_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_hi, buf); - - if (ret < 0) - return ret; - return len; -} - -static ssize_t apds990x_lux_thresh_below_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_lo, buf); - - if (ret < 0) - return ret; - return len; -} - -static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR, - apds990x_lux_thresh_above_show, - apds990x_lux_thresh_above_store); - -static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR, - apds990x_lux_thresh_below_show, - apds990x_lux_thresh_below_store); - -static ssize_t apds990x_prox_threshold_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->prox_thres); -} - -static ssize_t apds990x_prox_threshold_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; - - if ((value > APDS_RANGE) || (value == 0) || - (value < APDS_PROX_HYSTERESIS)) - return -EINVAL; - - mutex_lock(&chip->mutex); - chip->prox_thres = value; - - apds990x_force_p_refresh(chip); - mutex_unlock(&chip->mutex); - return len; -} - -static DEVICE_ATTR(prox0_thresh_above_value, S_IRUGO | S_IWUSR, - apds990x_prox_threshold_show, - apds990x_prox_threshold_store); - -static ssize_t apds990x_power_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", !pm_runtime_suspended(dev)); -} - -static ssize_t apds990x_power_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; - - if (value) { - pm_runtime_get_sync(dev); - mutex_lock(&chip->mutex); - chip->lux_wait_fresh_res = true; - apds990x_force_a_refresh(chip); - apds990x_force_p_refresh(chip); - mutex_unlock(&chip->mutex); - } else { - if (!pm_runtime_suspended(dev)) - pm_runtime_put(dev); - } - return len; -} - -static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, - apds990x_power_state_show, - apds990x_power_state_store); - -static ssize_t apds990x_chip_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%s %d\n", chip->chipname, chip->revision); -} - -static DEVICE_ATTR(chip_id, S_IRUGO, apds990x_chip_id_show, NULL); - -static struct attribute *sysfs_attrs_ctrl[] = { - &dev_attr_lux0_calibscale.attr, - &dev_attr_lux0_calibscale_default.attr, - &dev_attr_lux0_input.attr, - &dev_attr_lux0_sensor_range.attr, - &dev_attr_lux0_rate.attr, - &dev_attr_lux0_rate_avail.attr, - &dev_attr_lux0_thresh_above_value.attr, - &dev_attr_lux0_thresh_below_value.attr, - &dev_attr_prox0_raw_en.attr, - &dev_attr_prox0_raw.attr, - &dev_attr_prox0_sensor_range.attr, - &dev_attr_prox0_thresh_above_value.attr, - &dev_attr_prox0_reporting_mode.attr, - &dev_attr_prox0_reporting_mode_avail.attr, - &dev_attr_chip_id.attr, - &dev_attr_power_state.attr, - NULL -}; - -static const struct attribute_group apds990x_attribute_group[] = { - {.attrs = sysfs_attrs_ctrl }, -}; - -static int apds990x_probe(struct i2c_client *client) -{ - struct apds990x_chip *chip; - int err; - - chip = kzalloc_obj(*chip); - if (!chip) - return -ENOMEM; - - i2c_set_clientdata(client, chip); - chip->client = client; - - init_waitqueue_head(&chip->wait); - mutex_init(&chip->mutex); - chip->pdata = client->dev.platform_data; - - if (chip->pdata == NULL) { - dev_err(&client->dev, "platform data is mandatory\n"); - err = -EINVAL; - goto fail1; - } - - if (chip->pdata->cf.ga == 0) { - /* set uncovered sensor default parameters */ - chip->cf.ga = 1966; /* 0.48 * APDS_PARAM_SCALE */ - chip->cf.cf1 = 4096; /* 1.00 * APDS_PARAM_SCALE */ - chip->cf.irf1 = 9134; /* 2.23 * APDS_PARAM_SCALE */ - chip->cf.cf2 = 2867; /* 0.70 * APDS_PARAM_SCALE */ - chip->cf.irf2 = 5816; /* 1.42 * APDS_PARAM_SCALE */ - chip->cf.df = 52; - } else { - chip->cf = chip->pdata->cf; - } - - /* precalculate inverse chip factors for threshold control */ - chip->rcf.afactor = - (chip->cf.irf1 - chip->cf.irf2) * APDS_PARAM_SCALE / - (chip->cf.cf1 - chip->cf.cf2); - chip->rcf.cf1 = APDS_PARAM_SCALE * APDS_PARAM_SCALE / - chip->cf.cf1; - chip->rcf.irf1 = chip->cf.irf1 * APDS_PARAM_SCALE / - chip->cf.cf1; - chip->rcf.cf2 = APDS_PARAM_SCALE * APDS_PARAM_SCALE / - chip->cf.cf2; - chip->rcf.irf2 = chip->cf.irf2 * APDS_PARAM_SCALE / - chip->cf.cf2; - - /* Set something to start with */ - chip->lux_thres_hi = APDS_LUX_DEF_THRES_HI; - chip->lux_thres_lo = APDS_LUX_DEF_THRES_LO; - chip->lux_calib = APDS_LUX_NEUTRAL_CALIB_VALUE; - - chip->prox_thres = APDS_PROX_DEF_THRES; - chip->pdrive = chip->pdata->pdrive; - chip->pdiode = APDS_PDIODE_IR; - chip->pgain = APDS_PGAIN_1X; - chip->prox_calib = APDS_PROX_NEUTRAL_CALIB_VALUE; - chip->prox_persistence = APDS_DEFAULT_PROX_PERS; - chip->prox_continuous_mode = false; - - chip->regs[0].supply = reg_vcc; - chip->regs[1].supply = reg_vled; - - err = regulator_bulk_get(&client->dev, - ARRAY_SIZE(chip->regs), chip->regs); - if (err < 0) { - dev_err(&client->dev, "Cannot get regulators\n"); - goto fail1; - } - - err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), chip->regs); - if (err < 0) { - dev_err(&client->dev, "Cannot enable regulators\n"); - goto fail2; - } - - usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY); - - err = apds990x_detect(chip); - if (err < 0) { - dev_err(&client->dev, "APDS990X not found\n"); - goto fail3; - } - - pm_runtime_set_active(&client->dev); - - apds990x_configure(chip); - apds990x_set_arate(chip, APDS_LUX_DEFAULT_RATE); - apds990x_mode_on(chip); - - pm_runtime_enable(&client->dev); - - if (chip->pdata->setup_resources) { - err = chip->pdata->setup_resources(); - if (err) { - err = -EINVAL; - goto fail4; - } - } - - err = sysfs_create_group(&chip->client->dev.kobj, - apds990x_attribute_group); - if (err < 0) { - dev_err(&chip->client->dev, "Sysfs registration failed\n"); - goto fail5; - } - - err = request_threaded_irq(client->irq, NULL, - apds990x_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW | - IRQF_ONESHOT, - "apds990x", chip); - if (err) { - dev_err(&client->dev, "could not get IRQ %d\n", - client->irq); - goto fail6; - } - return err; -fail6: - sysfs_remove_group(&chip->client->dev.kobj, - &apds990x_attribute_group[0]); -fail5: - if (chip->pdata && chip->pdata->release_resources) - chip->pdata->release_resources(); -fail4: - pm_runtime_disable(&client->dev); -fail3: - regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); -fail2: - regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); -fail1: - kfree(chip); - return err; -} - -static void apds990x_remove(struct i2c_client *client) -{ - struct apds990x_chip *chip = i2c_get_clientdata(client); - - free_irq(client->irq, chip); - sysfs_remove_group(&chip->client->dev.kobj, - apds990x_attribute_group); - - if (chip->pdata && chip->pdata->release_resources) - chip->pdata->release_resources(); - - if (!pm_runtime_suspended(&client->dev)) - apds990x_chip_off(chip); - - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - - regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); - - kfree(chip); -} - -#ifdef CONFIG_PM_SLEEP -static int apds990x_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct apds990x_chip *chip = i2c_get_clientdata(client); - - apds990x_chip_off(chip); - return 0; -} - -static int apds990x_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct apds990x_chip *chip = i2c_get_clientdata(client); - - /* - * If we were enabled at suspend time, it is expected - * everything works nice and smoothly. Chip_on is enough - */ - apds990x_chip_on(chip); - - return 0; -} -#endif - -#ifdef CONFIG_PM -static int apds990x_runtime_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct apds990x_chip *chip = i2c_get_clientdata(client); - - apds990x_chip_off(chip); - return 0; -} - -static int apds990x_runtime_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct apds990x_chip *chip = i2c_get_clientdata(client); - - apds990x_chip_on(chip); - return 0; -} - -#endif - -static const struct i2c_device_id apds990x_id[] = { - { "apds990x" }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, apds990x_id); - -static const struct dev_pm_ops apds990x_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(apds990x_suspend, apds990x_resume) - SET_RUNTIME_PM_OPS(apds990x_runtime_suspend, - apds990x_runtime_resume, - NULL) -}; - -static struct i2c_driver apds990x_driver = { - .driver = { - .name = "apds990x", - .pm = &apds990x_pm_ops, - }, - .probe = apds990x_probe, - .remove = apds990x_remove, - .id_table = apds990x_id, -}; - -module_i2c_driver(apds990x_driver); - -MODULE_DESCRIPTION("APDS990X combined ALS and proximity sensor"); -MODULE_AUTHOR("Samu Onkalo, Nokia Corporation"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c index 2b6a994c6fe1..c4d54ca2fa80 100644 --- a/drivers/misc/cardreader/rtsx_pcr.c +++ b/drivers/misc/cardreader/rtsx_pcr.c @@ -42,21 +42,21 @@ static struct mfd_cell rtsx_pcr_cells[] = { }; static const struct pci_device_id rtsx_pci_ids[] = { - { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5260), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5261), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5228), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(0x10EC, 0x5264), PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { 0, } + { PCI_DEVICE(0x10EC, 0x5209), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5229), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5289), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5227), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x522A), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5249), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5287), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5286), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x524A), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x525A), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5260), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5261), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5228), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5264), .class = PCI_CLASS_OTHERS << 16, .class_mask = 0xFF0000 }, + { } }; MODULE_DEVICE_TABLE(pci, rtsx_pci_ids); diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index f145e8e36cb3..b9a67629496b 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -6,6 +6,8 @@ #ifndef _MEI_HW_MEI_REGS_H_ #define _MEI_HW_MEI_REGS_H_ +#include + /* * MEI device IDs */ @@ -142,6 +144,8 @@ # define PCI_CFG_HFS_2_PM_CM_RESET_ERROR 0x5000000 /* CME reset due to exception */ # define PCI_CFG_HFS_2_PM_EVENT_MASK 0xf000000 #define PCI_CFG_HFS_3 0x60 +# define PCI_CFG_HFS_3_EXT_SKU_MSK GENMASK(3, 0) /* IOE detection bits */ +# define PCI_CFG_HFS_3_EXT_SKU_IOE 0x00000001 # define PCI_CFG_HFS_3_FW_SKU_MSK 0x00000070 # define PCI_CFG_HFS_3_FW_SKU_IGN 0x00000000 # define PCI_CFG_HFS_3_FW_SKU_SPS 0x00000060 diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index e286763b52ec..e7fbc02fb70f 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -4,13 +4,13 @@ * Intel Management Engine Interface (Intel MEI) Linux driver */ -#include - -#include +#include +#include #include +#include +#include #include #include -#include #include "mei_dev.h" #include "hbm.h" @@ -1584,18 +1584,58 @@ static bool mei_me_fw_type_sps_ign(const struct pci_dev *pdev) fw_type == PCI_CFG_HFS_3_FW_SKU_SPS; } -#define MEI_CFG_KIND_ITOUCH \ - .kind = "itouch" - -#define MEI_CFG_TYPE_GSC \ - .kind = "gsc" - -#define MEI_CFG_TYPE_GSCFI \ - .kind = "gscfi" - #define MEI_CFG_FW_SPS_IGN \ .quirk_probe = mei_me_fw_type_sps_ign +static enum mei_dev_kind mei_cfg_kind_mei(const struct device *parent) +{ + return MEI_DEV_KIND_MEI; +} + +#define MEI_CFG_KIND_MEI \ + .get_kind = mei_cfg_kind_mei + +static enum mei_dev_kind mei_cfg_kind_itouch(const struct device *parent) +{ + return MEI_DEV_KIND_ITOUCH; +} + +#define MEI_CFG_KIND_ITOUCH \ + .get_kind = mei_cfg_kind_itouch + +static enum mei_dev_kind mei_cfg_kind_gsc(const struct device *parent) +{ + return MEI_DEV_KIND_GSC; +} + +#define MEI_CFG_KIND_GSC \ + .get_kind = mei_cfg_kind_gsc + +static enum mei_dev_kind mei_cfg_kind_gscfi(const struct device *parent) +{ + return MEI_DEV_KIND_GSCFI; +} + +#define MEI_CFG_KIND_GSCFI \ + .get_kind = mei_cfg_kind_gscfi + +static enum mei_dev_kind mei_cfg_kind_ioe(const struct device *parent) +{ + const struct pci_dev *pdev = to_pci_dev(parent); + unsigned int devfn; + u32 reg; + int ret; + + devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); + ret = pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_3, ®); + trace_mei_pci_cfg_read(parent, "PCI_CFG_HFS_3", PCI_CFG_HFS_3, reg, ret); + return FIELD_GET(PCI_CFG_HFS_3_EXT_SKU_MSK, reg) == PCI_CFG_HFS_3_EXT_SKU_IOE ? + MEI_DEV_KIND_IOE : MEI_DEV_KIND_MEI; +} + +#define MEI_CFG_KIND_IOE \ + .get_kind = mei_cfg_kind_ioe + #define MEI_CFG_FW_VER_SUPP \ .fw_ver_supported = 1 @@ -1630,27 +1670,32 @@ static bool mei_me_fw_type_sps_ign(const struct pci_dev *pdev) /* ICH Legacy devices */ static const struct mei_cfg mei_me_ich_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_ICH_HFS, }; /* ICH devices */ static const struct mei_cfg mei_me_ich10_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_ICH10_HFS, }; /* PCH6 devices */ static const struct mei_cfg mei_me_pch6_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH_HFS, }; /* PCH7 devices */ static const struct mei_cfg mei_me_pch7_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH_HFS, MEI_CFG_FW_VER_SUPP, }; /* PCH Cougar Point and Patsburg with quirk for Node Manager exclusion */ static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_FW_NM, @@ -1658,6 +1703,7 @@ static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = { /* PCH8 Lynx Point and newer devices */ static const struct mei_cfg mei_me_pch8_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, }; @@ -1671,6 +1717,7 @@ static const struct mei_cfg mei_me_pch8_itouch_cfg = { /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */ static const struct mei_cfg mei_me_pch8_sps_4_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_FW_SPS_4, @@ -1678,6 +1725,7 @@ static const struct mei_cfg mei_me_pch8_sps_4_cfg = { /* LBG with quirk for SPS (4.0) Firmware exclusion */ static const struct mei_cfg mei_me_pch12_sps_4_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_FW_SPS_4, @@ -1685,6 +1733,7 @@ static const struct mei_cfg mei_me_pch12_sps_4_cfg = { /* Cannon Lake and newer devices */ static const struct mei_cfg mei_me_pch12_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_DMA_128, @@ -1692,6 +1741,7 @@ static const struct mei_cfg mei_me_pch12_cfg = { /* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion */ static const struct mei_cfg mei_me_pch12_sps_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_DMA_128, @@ -1710,6 +1760,7 @@ static const struct mei_cfg mei_me_pch12_itouch_sps_cfg = { /* Tiger Lake and newer devices */ static const struct mei_cfg mei_me_pch15_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_DMA_128, @@ -1718,6 +1769,7 @@ static const struct mei_cfg mei_me_pch15_cfg = { /* Tiger Lake with quirk for SPS 5.0 and newer Firmware exclusion */ static const struct mei_cfg mei_me_pch15_sps_cfg = { + MEI_CFG_KIND_MEI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, MEI_CFG_DMA_128, @@ -1727,25 +1779,34 @@ static const struct mei_cfg mei_me_pch15_sps_cfg = { /* Graphics System Controller */ static const struct mei_cfg mei_me_gsc_cfg = { - MEI_CFG_TYPE_GSC, + MEI_CFG_KIND_GSC, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, }; /* Graphics System Controller Firmware Interface */ static const struct mei_cfg mei_me_gscfi_cfg = { - MEI_CFG_TYPE_GSCFI, + MEI_CFG_KIND_GSCFI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, }; /* Chassis System Controller Firmware Interface */ static const struct mei_cfg mei_me_csc_cfg = { - MEI_CFG_TYPE_GSCFI, + MEI_CFG_KIND_GSCFI, MEI_CFG_PCH8_HFS, MEI_CFG_FW_VER_SUPP, }; +/* Nova Lake with possible IOE devices */ +static const struct mei_cfg mei_me_pch22_ioe_cfg = { + MEI_CFG_KIND_IOE, + MEI_CFG_PCH8_HFS, + MEI_CFG_FW_VER_SUPP, + MEI_CFG_DMA_128, + MEI_CFG_TRC, +}; + /* * mei_cfg_list - A list of platform platform specific configurations. * Note: has to be synchronized with enum mei_cfg_idx. @@ -1769,6 +1830,7 @@ static const struct mei_cfg *const mei_cfg_list[] = { [MEI_ME_GSC_CFG] = &mei_me_gsc_cfg, [MEI_ME_GSCFI_CFG] = &mei_me_gscfi_cfg, [MEI_ME_CSC_CFG] = &mei_me_csc_cfg, + [MEI_ME_PCH22_IOE_CFG] = &mei_me_pch22_ioe_cfg, }; const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx) @@ -1812,7 +1874,7 @@ struct mei_device *mei_me_dev_init(struct device *parent, dev->fw_f_fw_ver_supported = cfg->fw_ver_supported; - dev->kind = cfg->kind; + dev->kind = cfg->get_kind(parent); return dev; } diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index 8da8662a9d61..0038a6d431fd 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h @@ -19,7 +19,7 @@ * * @fw_status: FW status * @quirk_probe: device exclusion quirk - * @kind: MEI head kind + * @get_kind: MEI head kind helper * @dma_size: device DMA buffers size * @fw_ver_supported: is fw version retrievable from FW * @hw_trc_supported: does the hw support trc register @@ -27,7 +27,7 @@ struct mei_cfg { const struct mei_fw_status fw_status; bool (*quirk_probe)(const struct pci_dev *pdev); - const char *kind; + enum mei_dev_kind (*get_kind)(const struct device *parent); size_t dma_size[DMA_DSCR_NUM]; u32 fw_ver_supported:1; u32 hw_trc_supported:1; @@ -105,6 +105,7 @@ static inline bool mei_me_hw_use_polling(const struct mei_me_hw *hw) * @MEI_ME_GSC_CFG: Graphics System Controller * @MEI_ME_GSCFI_CFG: Graphics System Controller Firmware Interface * @MEI_ME_CSC_CFG: Chassis System Controller Firmware Interface + * @MEI_ME_PCH22_IOE_CFG: Platform Controller Hub Gen22 and newer with IOE detection * @MEI_ME_NUM_CFG: Upper Sentinel. */ enum mei_cfg_idx { @@ -126,7 +127,8 @@ enum mei_cfg_idx { MEI_ME_GSC_CFG, MEI_ME_GSCFI_CFG, MEI_ME_CSC_CFG, - MEI_ME_NUM_CFG, + MEI_ME_PCH22_IOE_CFG, + MEI_ME_NUM_CFG }; const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 54f70f513482..4fbf0b323616 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -1165,6 +1165,16 @@ void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state) } } +static const char * const mei_kind_names[] = { + "mei", + "itouch", + "gsc", + "gscfi", + "ivsc", + "ioe", +}; +static_assert(ARRAY_SIZE(mei_kind_names) == MEI_DEV_KIND_MAX); + /** * kind_show - display device kind * @@ -1178,14 +1188,11 @@ static ssize_t kind_show(struct device *device, struct device_attribute *attr, char *buf) { struct mei_device *dev = dev_get_drvdata(device); - ssize_t ret; - if (dev->kind) - ret = sprintf(buf, "%s\n", dev->kind); - else - ret = sprintf(buf, "%s\n", "mei"); + if (dev->kind < MEI_DEV_KIND_MEI || dev->kind >= MEI_DEV_KIND_MAX) + return -EINVAL; - return ret; + return sysfs_emit(buf, "%s\n", mei_kind_names[dev->kind]); } static DEVICE_ATTR_RO(kind); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index d8634a726990..e651b06704a1 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -469,6 +469,27 @@ struct mei_dev_timeouts { unsigned long link_reset_wait; /* link reset wait timeout, in jiffies */ }; +/** + * enum mei_dev_kind - device type + * + * @MEI_DEV_KIND_MEI: basic device + * @MEI_DEV_KIND_ITOUCH: itouch support + * @MEI_DEV_KIND_GSC: discete graphics content protection + * @MEI_DEV_KIND_GSCFI: discete graphics chassis controller + * @MEI_DEV_KIND_IVSC: visual sensing controller + * @MEI_DEV_KIND_IOE: IO extender + * @MEI_DEV_KIND_MAX: sentinel + */ +enum mei_dev_kind { + MEI_DEV_KIND_MEI, + MEI_DEV_KIND_ITOUCH, + MEI_DEV_KIND_GSC, + MEI_DEV_KIND_GSCFI, + MEI_DEV_KIND_IVSC, + MEI_DEV_KIND_IOE, + MEI_DEV_KIND_MAX +}; + /** * struct mei_device - MEI private device struct * @@ -650,7 +671,7 @@ struct mei_device { struct list_head device_list; struct mutex cl_bus_lock; - const char *kind; + enum mei_dev_kind kind; #if IS_ENABLED(CONFIG_DEBUG_FS) struct dentry *dbgfs_dir; @@ -911,8 +932,7 @@ static inline ssize_t mei_fw_status_str(struct mei_device *dev, */ static inline bool kind_is_gsc(struct mei_device *dev) { - /* check kind for NULL because it may be not set, like at the fist call to hw_start */ - return dev->kind && (strcmp(dev->kind, "gsc") == 0); + return dev->kind == MEI_DEV_KIND_GSC; } /** @@ -924,7 +944,6 @@ static inline bool kind_is_gsc(struct mei_device *dev) */ static inline bool kind_is_gscfi(struct mei_device *dev) { - /* check kind for NULL because it may be not set, like at the fist call to hw_start */ - return dev->kind && (strcmp(dev->kind, "gscfi") == 0); + return dev->kind == MEI_DEV_KIND_GSCFI; } #endif diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 9efeafa8f1ca..55e0b8a98827 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -130,7 +130,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {PCI_DEVICE_DATA(INTEL, MEI_WCL_P, MEI_ME_PCH15_CFG)}, - {PCI_DEVICE_DATA(INTEL, MEI_NVL_S, MEI_ME_PCH15_CFG)}, + {PCI_DEVICE_DATA(INTEL, MEI_NVL_S, MEI_ME_PCH22_IOE_CFG)}, {PCI_DEVICE_DATA(INTEL, MEI_NVL_H, MEI_ME_PCH15_CFG)}, /* required last entry */ diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 98d1bc2c7f4b..f5441bc5efe2 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -84,6 +84,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENOMEM; goto end; } + dev->kind = MEI_DEV_KIND_MEI; hw = to_txe_hw(dev); hw->mem_addr = pcim_iomap_table(pdev); diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c index 9787b9cee71c..5100234ba5b6 100644 --- a/drivers/misc/mei/platform-vsc.c +++ b/drivers/misc/mei/platform-vsc.c @@ -350,7 +350,7 @@ static int mei_vsc_probe(struct platform_device *pdev) mei_device_init(mei_dev, dev, false, &mei_vsc_hw_ops); mei_dev->fw_f_fw_ver_supported = 0; - mei_dev->kind = "ivsc"; + mei_dev->kind = MEI_DEV_KIND_IVSC; hw = mei_dev_to_vsc_hw(mei_dev); atomic_set(&hw->write_lock_cnt, 0); diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index fd147fd2800f..19c4fa017f24 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -149,129 +149,6 @@ static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip, iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr); } -/* pch_phub_save_reg_conf - saves register configuration */ -static void __maybe_unused pch_phub_save_reg_conf(struct pci_dev *pdev) -{ - unsigned int i; - struct pch_phub_reg *chip = pci_get_drvdata(pdev); - - void __iomem *p = chip->pch_phub_base_address; - - chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG); - chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG); - chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG); - chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG); - chip->comp_resp_timeout_reg = - ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG); - chip->bus_slave_control_reg = - ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG); - chip->deadlock_avoid_type_reg = - ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG); - chip->intpin_reg_wpermit_reg0 = - ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0); - chip->intpin_reg_wpermit_reg1 = - ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1); - chip->intpin_reg_wpermit_reg2 = - ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2); - chip->intpin_reg_wpermit_reg3 = - ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3); - dev_dbg(&pdev->dev, "%s : " - "chip->phub_id_reg=%x, " - "chip->q_pri_val_reg=%x, " - "chip->rc_q_maxsize_reg=%x, " - "chip->bri_q_maxsize_reg=%x, " - "chip->comp_resp_timeout_reg=%x, " - "chip->bus_slave_control_reg=%x, " - "chip->deadlock_avoid_type_reg=%x, " - "chip->intpin_reg_wpermit_reg0=%x, " - "chip->intpin_reg_wpermit_reg1=%x, " - "chip->intpin_reg_wpermit_reg2=%x, " - "chip->intpin_reg_wpermit_reg3=%x\n", __func__, - chip->phub_id_reg, - chip->q_pri_val_reg, - chip->rc_q_maxsize_reg, - chip->bri_q_maxsize_reg, - chip->comp_resp_timeout_reg, - chip->bus_slave_control_reg, - chip->deadlock_avoid_type_reg, - chip->intpin_reg_wpermit_reg0, - chip->intpin_reg_wpermit_reg1, - chip->intpin_reg_wpermit_reg2, - chip->intpin_reg_wpermit_reg3); - for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { - chip->int_reduce_control_reg[i] = - ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i); - dev_dbg(&pdev->dev, "%s : " - "chip->int_reduce_control_reg[%d]=%x\n", - __func__, i, chip->int_reduce_control_reg[i]); - } - chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); - if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) - chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET); -} - -/* pch_phub_restore_reg_conf - restore register configuration */ -static void __maybe_unused pch_phub_restore_reg_conf(struct pci_dev *pdev) -{ - unsigned int i; - struct pch_phub_reg *chip = pci_get_drvdata(pdev); - void __iomem *p; - p = chip->pch_phub_base_address; - - iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG); - iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG); - iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG); - iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG); - iowrite32(chip->comp_resp_timeout_reg, - p + PCH_PHUB_COMP_RESP_TIMEOUT_REG); - iowrite32(chip->bus_slave_control_reg, - p + PCH_PHUB_BUS_SLAVE_CONTROL_REG); - iowrite32(chip->deadlock_avoid_type_reg, - p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG); - iowrite32(chip->intpin_reg_wpermit_reg0, - p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0); - iowrite32(chip->intpin_reg_wpermit_reg1, - p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1); - iowrite32(chip->intpin_reg_wpermit_reg2, - p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2); - iowrite32(chip->intpin_reg_wpermit_reg3, - p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3); - dev_dbg(&pdev->dev, "%s : " - "chip->phub_id_reg=%x, " - "chip->q_pri_val_reg=%x, " - "chip->rc_q_maxsize_reg=%x, " - "chip->bri_q_maxsize_reg=%x, " - "chip->comp_resp_timeout_reg=%x, " - "chip->bus_slave_control_reg=%x, " - "chip->deadlock_avoid_type_reg=%x, " - "chip->intpin_reg_wpermit_reg0=%x, " - "chip->intpin_reg_wpermit_reg1=%x, " - "chip->intpin_reg_wpermit_reg2=%x, " - "chip->intpin_reg_wpermit_reg3=%x\n", __func__, - chip->phub_id_reg, - chip->q_pri_val_reg, - chip->rc_q_maxsize_reg, - chip->bri_q_maxsize_reg, - chip->comp_resp_timeout_reg, - chip->bus_slave_control_reg, - chip->deadlock_avoid_type_reg, - chip->intpin_reg_wpermit_reg0, - chip->intpin_reg_wpermit_reg1, - chip->intpin_reg_wpermit_reg2, - chip->intpin_reg_wpermit_reg3); - for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) { - iowrite32(chip->int_reduce_control_reg[i], - p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i); - dev_dbg(&pdev->dev, "%s : " - "chip->int_reduce_control_reg[%d]=%x\n", - __func__, i, chip->int_reduce_control_reg[i]); - } - - iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); - if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) - iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET); -} - /** * pch_phub_read_serial_rom() - Reading Serial ROM * @chip: Pointer to the PHUB register structure @@ -660,6 +537,14 @@ static const struct bin_attribute pch_bin_attr = { .write = pch_phub_bin_write, }; +enum { + PCH_EG20T, + PCH_ML7213, + PCH_ML7223M, + PCH_ML7223N, + PCH_ML7831, +}; + static int pch_phub_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -702,7 +587,7 @@ static int pch_phub_probe(struct pci_dev *pdev, chip->pdev = pdev; /* Save pci device struct */ - if (id->driver_data == 1) { /* EG20T PCH */ + if (id->driver_data == PCH_EG20T) { /* EG20T PCH */ const char *board_name; unsigned int prefetch = 0x000affaa; @@ -750,7 +635,7 @@ static int pch_phub_probe(struct pci_dev *pdev, CLKCFG_UART_MASK); } } - } else if (id->driver_data == 2) { /* ML7213 IOH */ + } else if (id->driver_data == PCH_ML7213) { /* ML7213 IOH */ ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); if (ret) goto err_sysfs_create; @@ -763,7 +648,7 @@ static int pch_phub_probe(struct pci_dev *pdev, iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); chip->pch_opt_rom_start_address =\ PCH_PHUB_ROM_START_ADDR_ML7213; - } else if (id->driver_data == 3) { /* ML7223 IOH Bus-m*/ + } else if (id->driver_data == PCH_ML7223M) { /* ML7223 IOH Bus-m*/ /* set the prefech value * Device8(GbE) */ @@ -773,7 +658,7 @@ static int pch_phub_probe(struct pci_dev *pdev, chip->pch_opt_rom_start_address =\ PCH_PHUB_ROM_START_ADDR_ML7223; chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; - } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/ + } else if (id->driver_data == PCH_ML7223N) { /* ML7223 IOH Bus-n*/ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); if (ret) @@ -790,7 +675,7 @@ static int pch_phub_probe(struct pci_dev *pdev, chip->pch_opt_rom_start_address =\ PCH_PHUB_ROM_START_ADDR_ML7223; chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; - } else if (id->driver_data == 5) { /* ML7831 */ + } else if (id->driver_data == PCH_ML7831) { /* ML7831 */ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); if (ret) @@ -854,11 +739,11 @@ static int __maybe_unused pch_phub_resume(struct device *dev_d) } static const struct pci_device_id pch_phub_pcidev_id[] = { - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5, }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), .driver_data = PCH_EG20T }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), .driver_data = PCH_ML7213 }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), .driver_data = PCH_ML7223M }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), .driver_data = PCH_ML7223N }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), .driver_data = PCH_ML7831 }, { } }; MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 1d54680d6ed2..4677d5a30941 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -400,12 +400,9 @@ static void tifm_7xx1_remove(struct pci_dev *dev) } static const struct pci_device_id tifm_7xx1_pci_tbl[] = { - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */ - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, + { PCI_VDEVICE(TI, PCI_DEVICE_ID_TI_XX21_XX11_FM) }, /* xx21 - the one I have */ + { PCI_VDEVICE(TI, PCI_DEVICE_ID_TI_XX12_FM) }, + { PCI_VDEVICE(TI, PCI_DEVICE_ID_TI_XX20_FM) }, { } }; diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index b777bc3fdde2..46bba9bef553 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -420,7 +420,7 @@ static int qp_memcpy_from_queue_iter(struct iov_iter *to, /* * Allocates two list of PPNs --- one for the pages in the produce queue, - * and the other for the pages in the consume queue. Intializes the list + * and the other for the pages in the consume queue. Initializes the list * of PPNs with the page frame numbers of the KVA for the two queues (and * the queue headers). */ diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 3bdaee925dee..98f2e23c6a4b 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -109,12 +109,12 @@ static int adt7316_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adt7316_i2c_id[] = { - { "adt7316" }, - { "adt7317" }, - { "adt7318" }, - { "adt7516" }, - { "adt7517" }, - { "adt7519" }, + { .name = "adt7316" }, + { .name = "adt7317" }, + { .name = "adt7318" }, + { .name = "adt7516" }, + { .name = "adt7517" }, + { .name = "adt7519" }, { } }; diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c index f91325d11394..1debcc36c1af 100644 --- a/drivers/staging/iio/addac/adt7316-spi.c +++ b/drivers/staging/iio/addac/adt7316-spi.c @@ -106,7 +106,18 @@ static int adt7316_spi_probe(struct spi_device *spi_dev) return -EINVAL; } - /* switch from default I2C protocol to SPI protocol */ + /* + * The device powers up in I2C mode. Switching to SPI mode + * requires sending a sequence of SPI writes as described in + * the datasheet "ADT7316/ADT7317/ADT7318", Rev. B, + * in the "Serial Interface Selection" section. + * + * During this sequence, the device may still be in I2C mode, + * so SPI transactions may not be recognized and can fail. + * Such errors are therefore ignored. + * + * TL;DR: Do not change this! + */ adt7316_spi_write(spi_dev, 0, 0); adt7316_spi_write(spi_dev, 0, 0); adt7316_spi_write(spi_dev, 0, 0); diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index b87ea1781b27..659821a1e2cb 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -5,21 +5,25 @@ * Copyright 2011 Analog Devices Inc. */ -#include - +#include #include -#include +#include #include -#include +#include #include -#include +#include +#include #include +#include #include -#include #include #include +#include #include +#include +#include + #include #include @@ -113,8 +117,8 @@ struct ad9832_state { static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout) { - unsigned long long freqreg = (u64)fout * - (u64)((u64)1L << AD9832_FREQ_BITS); + u64 freqreg = (u64)fout << AD9832_FREQ_BITS; + do_div(freqreg, mclk); return freqreg; } diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index bdb2580e29bf..4359b358e0e5 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -5,18 +5,21 @@ * Copyright 2010-2011 Analog Devices Inc. */ +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include + +#include #include #include @@ -164,7 +167,7 @@ static ssize_t ad9834_write(struct device *dev, break; case AD9834_OPBITEN: if (st->control & AD9834_MODE) { - ret = -EINVAL; /* AD9843 reserved mode */ + ret = -EINVAL; /* AD9834 reserved mode */ break; } @@ -239,7 +242,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev, st->control &= ~AD9834_OPBITEN; st->control |= AD9834_MODE; } else if (st->control & AD9834_OPBITEN) { - ret = -EINVAL; /* AD9843 reserved mode */ + ret = -EINVAL; /* AD9834 reserved mode */ } else { st->control |= AD9834_MODE; } @@ -389,17 +392,14 @@ static int ad9834_probe(struct spi_device *spi) return dev_err_probe(&spi->dev, ret, "Failed to enable specified AVDD supply\n"); indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) { - ret = -ENOMEM; - return ret; - } + if (!indio_dev) + return -ENOMEM; st = iio_priv(indio_dev); mutex_init(&st->lock); st->mclk = devm_clk_get_enabled(&spi->dev, NULL); - if (IS_ERR(st->mclk)) { - dev_err(&spi->dev, "Failed to enable master clock\n"); - return PTR_ERR(st->mclk); - } + if (IS_ERR(st->mclk)) + return dev_err_probe(&spi->dev, PTR_ERR(st->mclk), + "Failed to enable master clock\n"); st->spi = spi; st->devid = spi_get_device_id(spi)->driver_data; @@ -441,10 +441,9 @@ static int ad9834_probe(struct spi_device *spi) st->data = cpu_to_be16(AD9834_REG_CMD | st->control); ret = spi_sync(st->spi, &st->msg); - if (ret) { - dev_err(&spi->dev, "device init failed\n"); - return ret; - } + if (ret) + return dev_err_probe(&spi->dev, ret, + "device init failed\n"); ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, 1000000); if (ret) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index dde2ec9d1f6a..798e62bae29b 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -726,8 +726,8 @@ static int ad5933_probe(struct i2c_client *client) } static const struct i2c_device_id ad5933_id[] = { - { "ad5933" }, - { "ad5934" }, + { .name = "ad5933" }, + { .name = "ad5934" }, { } }; diff --git a/drivers/virt/acrn/irqfd.c b/drivers/virt/acrn/irqfd.c index aab15f94166a..ac583c843f70 100644 --- a/drivers/virt/acrn/irqfd.c +++ b/drivers/virt/acrn/irqfd.c @@ -16,6 +16,9 @@ #include "acrn_drv.h" +/* Cleanup work has been queued; set via test_and_set_bit(). */ +#define HSM_IRQFD_FLAG_SHUTDOWN 0 + /** * struct hsm_irqfd - Properties of HSM irqfd * @vm: Associated VM pointer @@ -25,6 +28,7 @@ * @list: Entry within &acrn_vm.irqfds of irqfds of a VM * @pt: Structure for select/poll on the associated eventfd * @msi: MSI data + * @flags: Internal lifecycle flags (HSM_IRQFD_FLAG_*) */ struct hsm_irqfd { struct acrn_vm *vm; @@ -34,6 +38,7 @@ struct hsm_irqfd { struct list_head list; poll_table pt; struct acrn_msi_entry msi; + unsigned long flags; }; static void acrn_irqfd_inject(struct hsm_irqfd *irqfd) @@ -44,49 +49,47 @@ static void acrn_irqfd_inject(struct hsm_irqfd *irqfd) irqfd->msi.msi_data); } -static void hsm_irqfd_shutdown(struct hsm_irqfd *irqfd) +/* Queue the cleanup work at most once. Safe from atomic context. */ +static void hsm_irqfd_queue_shutdown(struct hsm_irqfd *irqfd) { + if (!test_and_set_bit(HSM_IRQFD_FLAG_SHUTDOWN, &irqfd->flags)) + queue_work(irqfd->vm->irqfd_wq, &irqfd->shutdown); +} + +/* Sole owner of @irqfd: unhook waitqueue, drop eventfd ref, free. */ +static void hsm_irqfd_shutdown_work(struct work_struct *work) +{ + struct hsm_irqfd *irqfd = container_of(work, struct hsm_irqfd, + shutdown); + struct acrn_vm *vm = irqfd->vm; u64 cnt; - lockdep_assert_held(&irqfd->vm->irqfds_lock); + mutex_lock(&vm->irqfds_lock); + if (!list_empty(&irqfd->list)) + list_del_init(&irqfd->list); + mutex_unlock(&vm->irqfds_lock); - /* remove from wait queue */ - list_del_init(&irqfd->list); eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); eventfd_ctx_put(irqfd->eventfd); kfree(irqfd); } -static void hsm_irqfd_shutdown_work(struct work_struct *work) -{ - struct hsm_irqfd *irqfd; - struct acrn_vm *vm; - - irqfd = container_of(work, struct hsm_irqfd, shutdown); - vm = irqfd->vm; - mutex_lock(&vm->irqfds_lock); - if (!list_empty(&irqfd->list)) - hsm_irqfd_shutdown(irqfd); - mutex_unlock(&vm->irqfds_lock); -} - /* Called with wqh->lock held and interrupts disabled */ static int hsm_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key) { unsigned long poll_bits = (unsigned long)key; struct hsm_irqfd *irqfd; - struct acrn_vm *vm; irqfd = container_of(wait, struct hsm_irqfd, wait); - vm = irqfd->vm; + if (poll_bits & POLLIN) /* An event has been signaled, inject an interrupt */ acrn_irqfd_inject(irqfd); if (poll_bits & POLLHUP) - /* Do shutdown work in thread to hold wqh->lock */ - queue_work(vm->irqfd_wq, &irqfd->shutdown); + /* Defer teardown to the cleanup work; can't sleep here. */ + hsm_irqfd_queue_shutdown(irqfd); return 0; } @@ -142,6 +145,12 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args) init_waitqueue_func_entry(&irqfd->wait, hsm_irqfd_wakeup); init_poll_funcptr(&irqfd->pt, hsm_irqfd_poll_func); + /* + * Hold irqfds_lock across waitqueue install and list_add so the + * irqfd is not visible to deassign/deinit before its waitqueue + * entry is in place, and any racing EPOLLHUP cleanup work blocks + * on irqfds_lock until publication completes. + */ mutex_lock(&vm->irqfds_lock); list_for_each_entry(tmp, &vm->irqfds, list) { if (irqfd->eventfd != tmp->eventfd) @@ -150,14 +159,12 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args) mutex_unlock(&vm->irqfds_lock); goto fail; } - list_add_tail(&irqfd->list, &vm->irqfds); - mutex_unlock(&vm->irqfds_lock); - /* Check the pending event in this stage */ events = vfs_poll(fd_file(f), &irqfd->pt); - + list_add_tail(&irqfd->list, &vm->irqfds); if (events & EPOLLIN) acrn_irqfd_inject(irqfd); + mutex_unlock(&vm->irqfds_lock); return 0; fail: @@ -180,13 +187,17 @@ static int acrn_irqfd_deassign(struct acrn_vm *vm, mutex_lock(&vm->irqfds_lock); list_for_each_entry_safe(irqfd, tmp, &vm->irqfds, list) { if (irqfd->eventfd == eventfd) { - hsm_irqfd_shutdown(irqfd); + list_del_init(&irqfd->list); + hsm_irqfd_queue_shutdown(irqfd); break; } } mutex_unlock(&vm->irqfds_lock); eventfd_ctx_put(eventfd); + /* Wait for cleanup work to finish so the eventfd is fully detached. */ + flush_workqueue(vm->irqfd_wq); + return 0; } @@ -219,9 +230,15 @@ void acrn_irqfd_deinit(struct acrn_vm *vm) struct hsm_irqfd *irqfd, *next; dev_dbg(acrn_dev.this_device, "VM %u irqfd deinit.\n", vm->vmid); - destroy_workqueue(vm->irqfd_wq); + mutex_lock(&vm->irqfds_lock); - list_for_each_entry_safe(irqfd, next, &vm->irqfds, list) - hsm_irqfd_shutdown(irqfd); + list_for_each_entry_safe(irqfd, next, &vm->irqfds, list) { + list_del_init(&irqfd->list); + hsm_irqfd_queue_shutdown(irqfd); + } mutex_unlock(&vm->irqfds_lock); + + /* Drain all cleanup work before tearing the workqueue down. */ + flush_workqueue(vm->irqfd_wq); + destroy_workqueue(vm->irqfd_wq); } diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index e2a568c9a43a..0069e6f854d7 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -539,8 +539,8 @@ static void ds2482_remove(struct i2c_client *client) * Driver data (common to all clients) */ static const struct i2c_device_id ds2482_id[] = { - { "ds2482" }, - { "ds2484" }, + { .name = "ds2482" }, + { .name = "ds2484" }, { } }; MODULE_DEVICE_TABLE(i2c, ds2482_id); diff --git a/include/dt-bindings/interconnect/qcom,eliza-rpmh.h b/include/dt-bindings/interconnect/qcom,eliza-rpmh.h index 95db2fe647de..dfe99feefb27 100644 --- a/include/dt-bindings/interconnect/qcom,eliza-rpmh.h +++ b/include/dt-bindings/interconnect/qcom,eliza-rpmh.h @@ -57,6 +57,7 @@ #define SLAVE_PCIE_ANOC_CFG 27 #define SLAVE_QDSS_STM 28 #define SLAVE_TCU 29 +#define SLAVE_SDCC_1 30 #define MASTER_GEM_NOC_CNOC 0 #define MASTER_GEM_NOC_PCIE_SNOC 1 diff --git a/include/dt-bindings/interconnect/qcom,hawi-rpmh.h b/include/dt-bindings/interconnect/qcom,hawi-rpmh.h new file mode 100644 index 000000000000..a8b649679846 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,hawi-rpmh.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_HAWI_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_HAWI_H + +#define MASTER_QSPI_0 0 +#define MASTER_QUP_2 1 +#define MASTER_QUP_3 2 +#define MASTER_QUP_4 3 +#define MASTER_CRYPTO 4 +#define MASTER_IPA 5 +#define MASTER_QUP_1 6 +#define MASTER_SOCCP_PROC 7 +#define MASTER_QDSS_ETR 8 +#define MASTER_QDSS_ETR_1 9 +#define MASTER_SDCC_2 10 +#define MASTER_SDCC_4 11 +#define MASTER_UFS_MEM 12 +#define MASTER_USB3 13 +#define SLAVE_A1NOC_SNOC 14 + +#define MASTER_DDR_EFF_VETO 0 +#define MASTER_QUP_CORE_0 1 +#define MASTER_QUP_CORE_1 2 +#define MASTER_QUP_CORE_2 3 +#define MASTER_QUP_CORE_3 4 +#define MASTER_QUP_CORE_4 5 +#define SLAVE_DDR_EFF_VETO 6 +#define SLAVE_QUP_CORE_0 7 +#define SLAVE_QUP_CORE_1 8 +#define SLAVE_QUP_CORE_2 9 +#define SLAVE_QUP_CORE_3 10 +#define SLAVE_QUP_CORE_4 11 + +#define MASTER_GEM_NOC_CNOC 0 +#define MASTER_GEM_NOC_PCIE_SNOC 1 +#define SLAVE_AOSS 2 +#define SLAVE_IPA_CFG 3 +#define SLAVE_IPC_ROUTER_FENCE 4 +#define SLAVE_SOCCP 5 +#define SLAVE_TME_CFG 6 +#define SLAVE_CNOC_CFG 7 +#define SLAVE_DDRSS_CFG 8 +#define SLAVE_IMEM 9 +#define SLAVE_PCIE_0 10 +#define SLAVE_PCIE_1 11 + +#define MASTER_GIC 0 +#define MASTER_GPU_TCU 1 +#define MASTER_SYS_TCU 2 +#define MASTER_APPSS_PROC 3 +#define MASTER_GFX3D 4 +#define MASTER_LPASS_GEM_NOC 5 +#define MASTER_MSS_PROC 6 +#define MASTER_MNOC_HF_MEM_NOC 7 +#define MASTER_MNOC_SF_MEM_NOC 8 +#define MASTER_COMPUTE_NOC 9 +#define MASTER_ANOC_PCIE_GEM_NOC 10 +#define MASTER_QPACE 11 +#define MASTER_SNOC_SF_MEM_NOC 12 +#define MASTER_WLAN_Q6 13 +#define SLAVE_GEM_NOC_CNOC 14 +#define SLAVE_LLCC 15 +#define SLAVE_MEM_NOC_PCIE_SNOC 16 + +#define MASTER_LPIAON_NOC_LLCLPI_NOC 0 +#define SLAVE_LPASS_LPI_CC 1 +#define SLAVE_LLCC_ISLAND 2 +#define SLAVE_SERVICE_LLCLPI_NOC 3 +#define SLAVE_SERVICE_LLCLPI_NOC_CHIPCX 4 + +#define MASTER_LPIAON_NOC 0 +#define SLAVE_LPASS_GEM_NOC 1 + +#define MASTER_LPASS_LPINOC 0 +#define SLAVE_LPIAON_NOC_LLCLPI_NOC 1 +#define SLAVE_LPIAON_NOC_LPASS_AG_NOC 2 + +#define MASTER_LPASS_PROC 0 +#define SLAVE_LPICX_NOC_LPIAON_NOC 1 + +#define MASTER_LLCC 0 +#define MASTER_DDR_RT 1 +#define SLAVE_EBI1 2 +#define SLAVE_DDR_RT 3 + +#define MASTER_CAMNOC_HF 0 +#define MASTER_CAMNOC_NRT_ICP_SF 1 +#define MASTER_CAMNOC_RT_CDM_SF 2 +#define MASTER_CAMNOC_SF 3 +#define MASTER_MDP 4 +#define MASTER_MDSS_DCP 5 +#define MASTER_CDSP_HCP 6 +#define MASTER_VIDEO_CV_PROC 7 +#define MASTER_VIDEO_EVA 8 +#define MASTER_VIDEO_MVP 9 +#define MASTER_VIDEO_V_PROC 10 +#define SLAVE_MNOC_HF_MEM_NOC 11 +#define SLAVE_MNOC_SF_MEM_NOC 12 + +#define MASTER_CDSP_PROC 0 +#define SLAVE_CDSP_MEM_NOC 1 + +#define MASTER_PCIE_ANOC_CFG 0 +#define MASTER_PCIE_0 1 +#define MASTER_PCIE_1 2 +#define SLAVE_ANOC_PCIE_GEM_NOC 3 +#define SLAVE_SERVICE_PCIE_ANOC 4 + +#define MASTER_CFG_CENTER 0 +#define MASTER_CFG_EAST 1 +#define MASTER_CFG_MM 2 +#define MASTER_CFG_NORTH 3 +#define MASTER_CFG_SOUTH 4 +#define MASTER_CFG_SOUTHWEST 5 +#define SLAVE_AHB2PHY_SOUTH 6 +#define SLAVE_BOOT_ROM 7 +#define SLAVE_CAMERA_CFG 8 +#define SLAVE_CLK_CTL 9 +#define SLAVE_CRYPTO_CFG 10 +#define SLAVE_DISPLAY_CFG 11 +#define SLAVE_EVA_CFG 12 +#define SLAVE_GFX3D_CFG 13 +#define SLAVE_I2C 14 +#define SLAVE_IMEM_CFG 15 +#define SLAVE_IPC_ROUTER_CFG 16 +#define SLAVE_IRIS_CFG 17 +#define SLAVE_CNOC_MSS 18 +#define SLAVE_PCIE_0_CFG 19 +#define SLAVE_PCIE_1_CFG 20 +#define SLAVE_PRNG 21 +#define SLAVE_QSPI_0 22 +#define SLAVE_QUP_1 23 +#define SLAVE_QUP_2 24 +#define SLAVE_QUP_3 25 +#define SLAVE_QUP_4 26 +#define SLAVE_SDCC_2 27 +#define SLAVE_SDCC_4 28 +#define SLAVE_TLMM 29 +#define SLAVE_UFS_MEM_CFG 30 +#define SLAVE_USB3 31 +#define SLAVE_VSENSE_CTRL_CFG 32 +#define SLAVE_PCIE_ANOC_CFG 33 +#define SLAVE_QDSS_CFG 34 +#define SLAVE_QDSS_STM 35 +#define SLAVE_TCSR 36 +#define SLAVE_TCU 37 + +#define MASTER_CNOC_STARDUST 0 +#define SLAVE_STARDUST_CENTER_CFG 1 +#define SLAVE_STARDUST_EAST_CFG 2 +#define SLAVE_STARDUST_MM_CFG 3 +#define SLAVE_STARDUST_NORTH_CFG 4 +#define SLAVE_STARDUST_SOUTH_CFG 5 +#define SLAVE_STARDUST_SOUTHWEST_CFG 6 + +#define MASTER_A1NOC_SNOC 0 +#define MASTER_APSS_NOC 1 +#define MASTER_CNOC_SNOC 2 +#define SLAVE_SNOC_GEM_NOC_SF 3 + +#endif diff --git a/include/dt-bindings/interconnect/qcom,nord-rpmh.h b/include/dt-bindings/interconnect/qcom,nord-rpmh.h new file mode 100644 index 000000000000..5bdce6a9bab7 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,nord-rpmh.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_NORD_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_NORD_H + +#define MASTER_QSPI_0 0 +#define MASTER_SAILSS_MD1 1 +#define MASTER_QUP_3 2 +#define SLAVE_A1NOC_SNOC 3 + +#define MASTER_QUP_2 0 +#define MASTER_CRYPTO_CORE0 1 +#define MASTER_CRYPTO_CORE1 2 +#define MASTER_CRYPTO_CORE2 3 +#define MASTER_SDCC_4 4 +#define MASTER_UFS_MEM 5 +#define MASTER_USB2 6 +#define MASTER_USB3_0 7 +#define MASTER_USB3_1 8 +#define SLAVE_A1NOC_HSCNOC 9 + +#define MASTER_IPA 0 +#define MASTER_SOCCP_AGGR_NOC 1 +#define MASTER_QDSS_ETR 2 +#define MASTER_QDSS_ETR_1 3 +#define SLAVE_A2NOC_SNOC 4 + +#define MASTER_QUP_0 0 +#define MASTER_QUP_1 1 +#define MASTER_EMAC_0 2 +#define MASTER_EMAC_1 3 +#define SLAVE_A2NOC_HSCNOC 4 + +#define MASTER_QUP_CORE_0 0 +#define MASTER_QUP_CORE_1 1 +#define MASTER_QUP_CORE_2 2 +#define MASTER_QUP_CORE_3 3 +#define SLAVE_QUP_CORE_0 4 +#define SLAVE_QUP_CORE_1 5 +#define SLAVE_QUP_CORE_2 6 +#define SLAVE_QUP_CORE_3 7 + +#define MASTER_CNOC_CFG 0 +#define SLAVE_PS_ETH_0 1 +#define SLAVE_PS_ETH_1 2 +#define SLAVE_SHS_SERVER 3 +#define SLAVE_AHB2PHY_0 4 +#define SLAVE_AHB2PHY_1 5 +#define SLAVE_AHB2PHY_2 6 +#define SLAVE_AHB2PHY_3 7 +#define SLAVE_AHB2PHY_ETH_0 8 +#define SLAVE_AHB2PHY_ETH_1 9 +#define SLAVE_CAMERA_CFG 10 +#define SLAVE_CLK_CTL 11 +#define SLAVE_CRYPTO_0_CFG 12 +#define SLAVE_CRYPTO_1_CFG 13 +#define SLAVE_CRYPTO_2_CFG 14 +#define SLAVE_DISPLAY_1_CFG 15 +#define SLAVE_DISPLAY_CFG 16 +#define SLAVE_DPRX0 17 +#define SLAVE_DPRX1 18 +#define SLAVE_EVA_CFG 19 +#define SLAVE_GFX3D_CFG 20 +#define SLAVE_GFX3D_1_CFG 21 +#define SLAVE_I2C 22 +#define SLAVE_IMEM_CFG 23 +#define SLAVE_MCW_PCIE 24 +#define SLAVE_MM_RSCC 25 +#define SLAVE_NE_CLK_CTL 26 +#define SLAVE_NSPSS0_CFG 27 +#define SLAVE_NSPSS1_CFG 28 +#define SLAVE_NSPSS2_CFG 29 +#define SLAVE_NSPSS3_CFG 30 +#define SLAVE_NW_CLK_CTL 31 +#define SLAVE_PRNG 32 +#define SLAVE_QDSS_CFG 33 +#define SLAVE_QSPI_0 34 +#define SLAVE_QUP_0 35 +#define SLAVE_QUP_3 36 +#define SLAVE_QUP_1 37 +#define SLAVE_QUP_2 38 +#define SLAVE_SAFEDMA_CFG 39 +#define SLAVE_SDCC_4 40 +#define SLAVE_SE_CLK_CTL 41 +#define SLAVE_TCSR 42 +#define SLAVE_TLMM 43 +#define SLAVE_TSC_CFG 44 +#define SLAVE_UFS_MEM_CFG 45 +#define SLAVE_USB2 46 +#define SLAVE_USB3_0 47 +#define SLAVE_USB3_1 48 +#define SLAVE_VENUS_CFG 49 +#define SLAVE_COMPUTENOC_CFG 50 +#define SLAVE_PCIE_NOC_CFG 51 +#define SLAVE_QTC_CFG 52 +#define SLAVE_QDSS_STM 53 +#define SLAVE_SYS_TCU0_CFG 54 +#define SLAVE_SYS_TCU1_CFG 55 +#define SLAVE_SYS_TCU2_CFG 56 + +#define MASTER_MM_RSCC 0 +#define MASTER_HSCNOC_CNOC 1 +#define SLAVE_AOSS 2 +#define SLAVE_HBCU 3 +#define SLAVE_IPA_CFG 4 +#define SLAVE_IPC_ROUTER_CFG 5 +#define SLAVE_SOCCP 6 +#define SLAVE_TME_CFG 7 +#define SLAVE_PCIE_DMA 8 +#define SLAVE_CNOC_CFG 9 +#define SLAVE_DDRSS_CFG 10 +#define SLAVE_IMEM 11 + +#define MASTER_HPASS_PROC_0 0 +#define MASTER_HPASS_PROC_1 1 +#define MASTER_HPASS_PROC_2 2 +#define SLAVE_HPASS_AGNOC_AUDIO 3 + +#define MASTER_GPU_TCU 0 +#define MASTER_QTC_TCU 1 +#define MASTER_SYS_TCU_0 2 +#define MASTER_SYS_TCU_1 3 +#define MASTER_SYS_TCU_2 4 +#define MASTER_APPSS_PROC 5 +#define MASTER_A1NOC_TILE_HSCNOC 6 +#define MASTER_A2NOC_TILE_HSCNOC 7 +#define MASTER_GFX3D 8 +#define MASTER_GFX3D_1 9 +#define MASTER_HPASS_ADAS_HSCNOC 10 +#define MASTER_HPASS_AUDIO_HSCNOC 11 +#define MASTER_MNOC_HF_MEM_NOC 12 +#define MASTER_MNOC_SF_MEM_NOC 13 +#define MASTER_NSP0_HSCNOC 14 +#define MASTER_NSP1_HSCNOC 15 +#define MASTER_NSP2_HSCNOC 16 +#define MASTER_NSP3_HSCNOC 17 +#define MASTER_ANOC_PCIE_GEM_NOC 18 +#define MASTER_SAILSS_MD0_HSCNOC 19 +#define MASTER_SNOC_SF_MEM_NOC 20 +#define MASTER_GIC 21 +#define SLAVE_HSCNOC_CNOC 22 +#define SLAVE_LLCC 23 +#define SLAVE_MEM_NOC_PCIE_SNOC 24 + +#define MASTER_LLCC 0 +#define SLAVE_EBI1 1 + +#define MASTER_CAMNOC_HF 0 +#define MASTER_CAMNOC_NRT_ICP_SF 1 +#define MASTER_CAMNOC_RT_CDM_SF 2 +#define MASTER_CAMNOC_SF 3 +#define MASTER_DPRX0 4 +#define MASTER_DPRX1 5 +#define MASTER_MDP0 6 +#define MASTER_MDP1 7 +#define MASTER_VIDEO_CV_PROC 8 +#define MASTER_VIDEO_EVA 9 +#define MASTER_VIDEO_MVP0 10 +#define MASTER_VIDEO_MVP1 11 +#define MASTER_VIDEO_V_PROC 12 +#define SLAVE_MNOC_HF_MEM_NOC 13 +#define SLAVE_MNOC_SF_MEM_NOC 14 + +#define MASTER_NSP0_PROC 0 +#define SLAVE_NSP0_HSC_NOC 1 + +#define MASTER_NSP1_PROC 0 +#define SLAVE_NSP1_HSC_NOC 1 + +#define MASTER_NSP2_PROC 0 +#define SLAVE_NSP2_HSC_NOC 1 + +#define MASTER_NSP3_PROC 0 +#define SLAVE_NSP3_HSC_NOC 1 + +#define MASTER_PCIE_NOC_CFG 0 +#define SLAVE_PCIE_AHB2PHY_CFG 1 +#define SLAVE_PCIE_CFG_0 2 +#define SLAVE_PCIE_CFG_1 3 +#define SLAVE_PCIE_CFG_2 4 +#define SLAVE_PCIE_CFG_3 5 +#define SLAVE_PCIE_DMA_0_CFG 6 +#define SLAVE_PCIE_DMA_1_CFG 7 +#define SLAVE_PCIE_DMA_2_CFG 8 + +#define MASTER_PCIE_DMA_0 0 +#define MASTER_PCIE_DMA_1 1 +#define MASTER_PCIE_DMA_2 2 +#define MASTER_PCIE_0 3 +#define MASTER_PCIE_1 4 +#define MASTER_PCIE_2 5 +#define MASTER_PCIE_3 6 +#define SLAVE_PCIE_HSCNOC 7 +#define SLAVE_PCIE_OBNOC_DMA 8 + +#define MASTER_CNOC_PCIE_DMA 0 +#define MASTER_ANOC_PCIE_HSCNOC 1 +#define MASTER_PCIE_IBNOC_DMA 2 +#define SLAVE_PCIE_DMA_0 3 +#define SLAVE_PCIE_DMA_1 4 +#define SLAVE_PCIE_DMA_2 5 +#define SLAVE_PCIE_0 6 +#define SLAVE_PCIE_1 7 +#define SLAVE_PCIE_2 8 +#define SLAVE_PCIE_3 9 + +#define MASTER_A1NOC_SNOC 0 +#define MASTER_A2NOC_SNOC 1 +#define MASTER_CNOC_SNOC 2 +#define MASTER_NSINOC_SNOC 3 +#define MASTER_SAFE_DMA 4 +#define SLAVE_SNOC_HSCNOC_SF 5 + +#endif diff --git a/include/dt-bindings/interconnect/qcom,shikra.h b/include/dt-bindings/interconnect/qcom,shikra.h new file mode 100644 index 000000000000..a42ea22ee162 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,shikra.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SHIKRA_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_SHIKRA_H + +#define MASTER_QUP_CORE_0 0 +#define SLAVE_QUP_CORE_0 1 + +#define SNOC_CNOC_MAS 0 +#define MASTER_QDSS_DAP 1 +#define SLAVE_AHB2PHY_USB 2 +#define SLAVE_APSS_THROTTLE_CFG 3 +#define SLAVE_AUDIO 4 +#define SLAVE_BOOT_ROM 5 +#define SLAVE_CAMERA_NRT_THROTTLE_CFG 6 +#define SLAVE_CAMERA_CFG 7 +#define SLAVE_CDSP_THROTTLE_CFG 8 +#define SLAVE_CLK_CTL 9 +#define SLAVE_DSP_CFG 10 +#define SLAVE_RBCPR_CX_CFG 11 +#define SLAVE_RBCPR_MX_CFG 12 +#define SLAVE_CRYPTO_0_CFG 13 +#define SLAVE_DDR_SS_CFG 14 +#define SLAVE_DISPLAY_CFG 15 +#define SLAVE_EMAC0_CFG 16 +#define SLAVE_EMAC1_CFG 17 +#define SLAVE_GPU_CFG 18 +#define SLAVE_GPU_THROTTLE_CFG 19 +#define SLAVE_HWKM 20 +#define SLAVE_IMEM_CFG 21 +#define SLAVE_MAPSS 22 +#define SLAVE_MDSP_MPU_CFG 23 +#define SLAVE_MESSAGE_RAM 24 +#define SLAVE_MSS 25 +#define SLAVE_PCIE_CFG 26 +#define SLAVE_PDM 27 +#define SLAVE_PIMEM_CFG 28 +#define SLAVE_PKA_WRAPPER_CFG 29 +#define SLAVE_PMIC_ARB 30 +#define SLAVE_QDSS_CFG 31 +#define SLAVE_QM_CFG 32 +#define SLAVE_QM_MPU_CFG 33 +#define SLAVE_QPIC 34 +#define SLAVE_QUP_0 35 +#define SLAVE_RPM 36 +#define SLAVE_SDCC_1 37 +#define SLAVE_SDCC_2 38 +#define SLAVE_SECURITY 39 +#define SLAVE_SNOC_CFG 40 +#define SNOC_SF_THROTTLE_CFG 41 +#define SLAVE_TLMM 42 +#define SLAVE_TSCSS 43 +#define SLAVE_USB2 44 +#define SLAVE_USB3 45 +#define SLAVE_VENUS_CFG 46 +#define SLAVE_VENUS_THROTTLE_CFG 47 +#define SLAVE_VSENSE_CTRL_CFG 48 +#define SLAVE_SERVICE_CNOC 49 + +#define MASTER_LLCC 0 +#define SLAVE_EBI_CH0 1 + +#define MASTER_GRAPHICS_3D 0 +#define MASTER_MNOC_HF_MEM_NOC 1 +#define MASTER_ANOC_PCIE_MEM_NOC 2 +#define MASTER_SNOC_SF_MEM_NOC 3 +#define MASTER_AMPSS_M0 4 +#define MASTER_SYS_TCU 5 +#define SLAVE_LLCC 6 +#define SLAVE_MEMNOC_SNOC 7 +#define SLAVE_MEM_NOC_PCIE_SNOC 8 + +#define MASTER_CAMNOC_SF 0 +#define MASTER_VIDEO_P0 1 +#define MASTER_VIDEO_PROC 2 +#define SLAVE_MMNRT_VIRT 3 + +#define MASTER_CAMNOC_HF 0 +#define MASTER_MDP_PORT0 1 +#define MASTER_MMRT_VIRT 2 +#define SLAVE_MM_MEMNOC 3 + +#define MASTER_SNOC_CFG 0 +#define MASTER_TIC 1 +#define MASTER_ANOC_SNOC 2 +#define MASTER_MEMNOC_PCIE 3 +#define MASTER_MEMNOC_SNOC 4 +#define MASTER_PIMEM 5 +#define MASTER_PCIE2_0 6 +#define MASTER_QDSS_BAM 7 +#define MASTER_QPIC 8 +#define MASTER_QUP_0 9 +#define CNOC_SNOC_MAS 10 +#define MASTER_AUDIO 11 +#define MASTER_EMAC_0 12 +#define MASTER_EMAC_1 13 +#define MASTER_QDSS_ETR 14 +#define MASTER_SDCC_1 15 +#define MASTER_SDCC_2 16 +#define MASTER_USB2_0 17 +#define MASTER_USB3 18 +#define MASTER_CRYPTO_CORE0 19 +#define SLAVE_APPSS 20 +#define SLAVE_MCUSS 21 +#define SLAVE_WCSS 22 +#define SLAVE_MEMNOC_SF 23 +#define SNOC_CNOC_SLV 24 +#define SLAVE_BOOTIMEM 25 +#define SLAVE_OCIMEM 26 +#define SLAVE_PIMEM 27 +#define SLAVE_SERVICE_SNOC 28 +#define SLAVE_PCIE2_0 29 +#define SLAVE_QDSS_STM 30 +#define SLAVE_TCU 31 +#define SLAVE_PCIE_MEMNOC 32 +#define SLAVE_ANOC_SNOC 33 + +#endif diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 1cf85d772bea..ddf18c970e34 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -141,6 +141,8 @@ struct csdev_access { .base = (_addr), \ }) +#define CORESIGHT_DESC_CPU_BOUND BIT(0) + /** * struct coresight_desc - description of a component required from drivers * @type: as defined by @coresight_dev_type. @@ -153,6 +155,8 @@ struct csdev_access { * in the component's sysfs sub-directory. * @name: name for the coresight device, also shown under sysfs. * @access: Describe access to the device + * @flags: The descritpion flags. + * @cpu: The CPU this component is affined to. */ struct coresight_desc { enum coresight_dev_type type; @@ -163,6 +167,8 @@ struct coresight_desc { const struct attribute_group **groups; const char *name; struct csdev_access access; + u32 flags; + int cpu; }; /** @@ -251,6 +257,7 @@ struct coresight_trace_id_map { * by @coresight_ops. * @access: Device i/o access abstraction for this device. * @dev: The device entity associated to this component. + * @path: Activated path pointer (only used for source device). * @mode: The device mode, i.e sysFS, Perf or disabled. This is actually * an 'enum cs_mode' but stored in an atomic type. Access is always * through atomic APIs, ensuring SMP-safe synchronisation between @@ -260,6 +267,7 @@ struct coresight_trace_id_map { * device's spinlock when the coresight_mutex held and mode == * CS_MODE_SYSFS. Otherwise it must be accessed from inside the * spinlock. + * @cpu: The CPU this component is affined to (-1 for not CPU bound). * @orphan: true if the component has connections that haven't been linked. * @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs * by writing a 1 to the 'enable_sink' file. A sink can be @@ -284,8 +292,10 @@ struct coresight_device { const struct coresight_ops *ops; struct csdev_access access; struct device dev; + struct coresight_path *path; atomic_t mode; int refcnt; + int cpu; bool orphan; /* sink specific fields */ bool sysfs_sink_activated; @@ -334,9 +344,9 @@ struct coresight_path { }; enum cs_mode { - CS_MODE_DISABLED, - CS_MODE_SYSFS, - CS_MODE_PERF, + CS_MODE_DISABLED = 0, + CS_MODE_SYSFS = BIT(0), + CS_MODE_PERF = BIT(1), }; #define coresight_ops(csdev) csdev->ops @@ -387,15 +397,12 @@ struct coresight_ops_link { /** * struct coresight_ops_source - basic operations for a source * Operations available for sources. - * @cpu_id: returns the value of the CPU number this component - * is associated to. * @enable: enables tracing for a source. * @disable: disables tracing for a source. * @resume_perf: resumes tracing for a source in perf session. * @pause_perf: pauses tracing for a source in perf session. */ struct coresight_ops_source { - int (*cpu_id)(struct coresight_device *csdev); int (*enable)(struct coresight_device *csdev, struct perf_event *event, enum cs_mode mode, struct coresight_path *path); void (*disable)(struct coresight_device *csdev, @@ -433,6 +440,8 @@ struct coresight_ops_panic { struct coresight_ops { int (*trace_id)(struct coresight_device *csdev, enum cs_mode mode, struct coresight_device *sink); + int (*pm_save_disable)(struct coresight_device *csdev); + void (*pm_restore_enable)(struct coresight_device *csdev); const struct coresight_ops_sink *sink_ops; const struct coresight_ops_link *link_ops; const struct coresight_ops_source *source_ops; @@ -602,6 +611,12 @@ static inline bool coresight_is_percpu_source(struct coresight_device *csdev) (csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_PROC); } +static inline bool coresight_is_software_source(struct coresight_device *csdev) +{ + return csdev && coresight_is_device_source(csdev) && + (csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE); +} + static inline bool coresight_is_percpu_sink(struct coresight_device *csdev) { return csdev && (csdev->type == CORESIGHT_DEV_TYPE_SINK) && diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 22ba327ec227..0fb3a2a62eb0 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -180,7 +180,6 @@ enum cpuhp_state { CPUHP_AP_DUMMY_TIMER_STARTING, CPUHP_AP_ARM_XEN_STARTING, CPUHP_AP_ARM_XEN_RUNSTATE_STARTING, - CPUHP_AP_ARM_CORESIGHT_STARTING, CPUHP_AP_ARM_CORESIGHT_CTI_STARTING, CPUHP_AP_ARM64_ISNDEP_STARTING, CPUHP_AP_SMPCFD_DYING, @@ -200,6 +199,7 @@ enum cpuhp_state { CPUHP_AP_IRQ_AFFINITY_ONLINE, CPUHP_AP_BLK_MQ_ONLINE, CPUHP_AP_ARM_MVEBU_SYNC_CLOCKS, + CPUHP_AP_ARM_CORESIGHT_ONLINE, CPUHP_AP_X86_INTEL_EPB_ONLINE, CPUHP_AP_PERF_ONLINE, CPUHP_AP_PERF_X86_ONLINE, diff --git a/include/linux/dtlk.h b/include/linux/dtlk.h deleted file mode 100644 index 27b95e70bde3..000000000000 --- a/include/linux/dtlk.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#define DTLK_MINOR 0 -#define DTLK_IO_EXTENT 0x02 - - /* ioctl's use magic number of 0xa3 */ -#define DTLK_INTERROGATE 0xa390 /* get settings from the DoubleTalk */ -#define DTLK_STATUS 0xa391 /* get status from the DoubleTalk */ - - -#define DTLK_CLEAR 0x18 /* stops speech */ - -#define DTLK_MAX_RETRIES (loops_per_jiffy/(10000/HZ)) - - /* TTS Port Status Flags */ -#define TTS_READABLE 0x80 /* mask for bit which is nonzero if a - byte can be read from the TTS port */ -#define TTS_SPEAKING 0x40 /* mask for SYNC bit, which is nonzero - while DoubleTalk is producing - output with TTS, PCM or CVSD - synthesizers or tone generators - (that is, all but LPC) */ -#define TTS_SPEAKING2 0x20 /* mask for SYNC2 bit, - which falls to zero up to 0.4 sec - before speech stops */ -#define TTS_WRITABLE 0x10 /* mask for RDY bit, which when set to - 1, indicates the TTS port is ready - to accept a byte of data. The RDY - bit goes zero 2-3 usec after - writing, and goes 1 again 180-190 - usec later. */ -#define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1, - indicates that less than 300 free - bytes are available in the TTS - input buffer. AF is always 0 in the - PCM, TGN and CVSD modes. */ -#define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1, - indicates that less than 300 bytes - of data remain in DoubleTalk's - input (TTS or PCM) buffer. AE is - always 1 in the TGN and CVSD - modes. */ - - /* LPC speak commands */ -#define LPC_5220_NORMAL 0x60 /* 5220 format decoding table, normal rate */ -#define LPC_5220_FAST 0x64 /* 5220 format decoding table, fast rate */ -#define LPC_D6_NORMAL 0x20 /* D6 format decoding table, normal rate */ -#define LPC_D6_FAST 0x24 /* D6 format decoding table, fast rate */ - - /* LPC Port Status Flags (valid only after one of the LPC - speak commands) */ -#define LPC_SPEAKING 0x80 /* mask for TS bit: When set to 1, - indicates the LPC synthesizer is - producing speech.*/ -#define LPC_BUFFER_LOW 0x40 /* mask for BL bit: When set to 1, - indicates that the hardware LPC - data buffer has less than 30 bytes - remaining. (Total internal buffer - size = 4096 bytes.) */ -#define LPC_BUFFER_EMPTY 0x20 /* mask for BE bit: When set to 1, - indicates that the LPC data buffer - ran out of data (error condition if - TS is also 1). */ - - /* data returned by Interrogate command */ -struct dtlk_settings -{ - unsigned short serial_number; /* 0-7Fh:0-7Fh */ - unsigned char rom_version[24]; /* null terminated string */ - unsigned char mode; /* 0=Character; 1=Phoneme; 2=Text */ - unsigned char punc_level; /* nB; 0-7 */ - unsigned char formant_freq; /* nF; 0-9 */ - unsigned char pitch; /* nP; 0-99 */ - unsigned char speed; /* nS; 0-9 */ - unsigned char volume; /* nV; 0-9 */ - unsigned char tone; /* nX; 0-2 */ - unsigned char expression; /* nE; 0-9 */ - unsigned char ext_dict_loaded; /* 1=exception dictionary loaded */ - unsigned char ext_dict_status; /* 1=exception dictionary enabled */ - unsigned char free_ram; /* # pages (truncated) remaining for - text buffer */ - unsigned char articulation; /* nA; 0-9 */ - unsigned char reverb; /* nR; 0-9 */ - unsigned char eob; /* 7Fh value indicating end of - parameter block */ - unsigned char has_indexing; /* nonzero if indexing is implemented */ -}; diff --git a/include/linux/firmware/intel/stratix10-smc.h b/include/linux/firmware/intel/stratix10-smc.h index 935dba3633b5..9116512169dc 100644 --- a/include/linux/firmware/intel/stratix10-smc.h +++ b/include/linux/firmware/intel/stratix10-smc.h @@ -514,6 +514,25 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_SVC_VERSION \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_SVC_FUNCID_VERSION) +/** + * Request INTEL_SIP_SMC_ATF_BUILD_VER + * + * Sync call used to query the ATF Build Version + * + * Call register usage: + * a0 INTEL_SIP_SMC_ATF_BUILD_VER + * a1-a7 not used + * + * Return status: + * a0 INTEL_SIP_SMC_STATUS_OK + * a1 Major + * a2 Minor + * a3 Patch + */ +#define INTEL_SIP_SMC_ATF_BUILD_VERSION 155 +#define INTEL_SIP_SMC_ATF_BUILD_VER \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_ATF_BUILD_VERSION) + /** * SMC call protocol for FPGA Crypto Service (FCS) * FUNCID starts from 90 @@ -605,25 +624,21 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) /** * Request INTEL_SIP_SMC_FCS_GET_PROVISION_DATA - * Sync call to dump all the fuses and key hashes + * Async call to dump all the fuses and key hashes * * Call register usage: * a0 INTEL_SIP_SMC_FCS_GET_PROVISION_DATA - * a1 the physical address for firmware to write structure of fuse and - * key hashes - * a2-a7 not used + * a1-a7 not used * * Return status: * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FCS_ERROR or * INTEL_SIP_SMC_FCS_REJECTED - * a1 mailbox error - * a2 physical address for the structure of fuse and key hashes - * a3 the size of structure + * a1-a3 not used * */ #define INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA 94 #define INTEL_SIP_SMC_FCS_GET_PROVISION_DATA \ - INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA) + INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA) /** * Request INTEL_SIP_SMC_HWMON_READTEMP diff --git a/include/linux/firmware/intel/stratix10-svc-client.h b/include/linux/firmware/intel/stratix10-svc-client.h index 91013161e9db..3edd93502bf8 100644 --- a/include/linux/firmware/intel/stratix10-svc-client.h +++ b/include/linux/firmware/intel/stratix10-svc-client.h @@ -154,6 +154,10 @@ struct stratix10_svc_chan; * * @COMMAND_HWMON_READVOLT: query the voltage from the hardware monitor, * return status is SVC_STATUS_OK or SVC_STATUS_ERROR + * + * @COMMAND_SMC_ATF_BUILD_VER: Non-mailbox SMC ATF Build Version, + * return status is SVC_STATUS_OK + * */ enum stratix10_svc_command_code { /* for FPGA */ @@ -187,7 +191,8 @@ enum stratix10_svc_command_code { COMMAND_SMC_SVC_VERSION = 200, /* for HWMON */ COMMAND_HWMON_READTEMP, - COMMAND_HWMON_READVOLT + COMMAND_HWMON_READVOLT, + COMMAND_SMC_ATF_BUILD_VER }; /** diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h index 4d15c2a9802c..3f95ed1fdf9e 100644 --- a/include/linux/iio/backend.h +++ b/include/linux/iio/backend.h @@ -261,6 +261,7 @@ int iio_backend_extend_chan_spec(struct iio_backend *back, bool iio_backend_has_caps(struct iio_backend *back, u32 caps); void *iio_backend_get_priv(const struct iio_backend *conv); struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name); +struct iio_backend *devm_iio_backend_get_by_index(struct device *dev, unsigned int index); struct iio_backend *devm_iio_backend_fwnode_get(struct device *dev, const char *name, struct fwnode_handle *fwnode); diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index d37f82678f71..745c98ef4e04 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -34,8 +34,16 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, void *data, int64_t timestamp) { if (ACCESS_PRIVATE(indio_dev, scan_timestamp)) { - size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1; - ((int64_t *)data)[ts_offset] = timestamp; + size_t ts_offset = ACCESS_PRIVATE(indio_dev, scan_timestamp_offset); + + /* + * The size of indio_dev->scan_bytes is always aligned to the + * largest scan element's alignment (see iio_compute_scan_bytes()). + * So there may be padding after the timestamp. ts_offset contains + * the offset in bytes that was already computed for correctly + * aligning the timestamp. + */ + *(int64_t *)(data + ts_offset) = timestamp; } return iio_push_to_buffers(indio_dev, data); @@ -71,7 +79,7 @@ static inline int iio_push_to_buffers_with_ts(struct iio_dev *indio_dev, int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev, const void *data, size_t data_sz, - int64_t timestamp); + s64 timestamp); bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, const unsigned long *mask); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 2c91b7659ce9..711c00f67371 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -176,9 +176,32 @@ struct iio_event_spec { unsigned long mask_shared_by_all; }; +/** + * define IIO_SCAN_FORMAT_SIGNED_INT - signed integer data format + * + * &iio_scan_type.format value for signed integers (two's complement). + */ +#define IIO_SCAN_FORMAT_SIGNED_INT 's' + +/** + * define IIO_SCAN_FORMAT_UNSIGNED_INT - unsigned integer data format + * + * &iio_scan_type.format value for unsigned integers. + */ +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u' + +/** + * define IIO_SCAN_FORMAT_FLOAT - floating-point data format + * + * &iio_scan_type.format value for IEEE 754 floating-point numbers. + */ +#define IIO_SCAN_FORMAT_FLOAT 'f' + /** * struct iio_scan_type - specification for channel data format in buffer - * @sign: 's' or 'u' to specify signed or unsigned + * @sign: Deprecated, use @format instead. + * @format: Data format, can have any of the IIO_SCAN_FORMAT_* + * values. * @realbits: Number of valid bits of data * @storagebits: Realbits + padding * @shift: Shift right by this before masking out realbits. @@ -189,7 +212,10 @@ struct iio_event_spec { * @endianness: little or big endian */ struct iio_scan_type { - char sign; + union { + char sign; + char format; + }; u8 realbits; u8 storagebits; u8 shift; @@ -327,15 +353,15 @@ static inline bool iio_channel_has_available(const struct iio_chan_spec *chan, (chan->info_mask_shared_by_all_available & BIT(type)); } -#define IIO_CHAN_SOFT_TIMESTAMP(_si) { \ +#define IIO_CHAN_SOFT_TIMESTAMP(_si) (struct iio_chan_spec) { \ .type = IIO_TIMESTAMP, \ .channel = -1, \ .scan_index = _si, \ .scan_type = { \ .sign = 's', \ - .realbits = 64, \ + .realbits = 64, \ .storagebits = 64, \ - }, \ + }, \ } s64 iio_get_time_ns(const struct iio_dev *indio_dev); @@ -584,6 +610,8 @@ struct iio_buffer_setup_ops { * and owner * @buffer: [DRIVER] any buffer present * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux + * @scan_timestamp_offset: [INTERN] cache of the offset (in bytes) for the + * timestamp in the scan buffer * @available_scan_masks: [DRIVER] optional array of allowed bitmasks. Sort the * array in order of preference, the most preferred * masks first. @@ -610,6 +638,7 @@ struct iio_dev { struct iio_buffer *buffer; int scan_bytes; + unsigned int __private scan_timestamp_offset; const unsigned long *available_scan_masks; unsigned int __private masklength; diff --git a/include/linux/platform_data/apds990x.h b/include/linux/platform_data/apds990x.h deleted file mode 100644 index 37684f68c04f..000000000000 --- a/include/linux/platform_data/apds990x.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * This file is part of the APDS990x sensor driver. - * Chip is combined proximity and ambient light sensor. - * - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Samu Onkalo - */ - -#ifndef __APDS990X_H__ -#define __APDS990X_H__ - - -#define APDS_IRLED_CURR_12mA 0x3 -#define APDS_IRLED_CURR_25mA 0x2 -#define APDS_IRLED_CURR_50mA 0x1 -#define APDS_IRLED_CURR_100mA 0x0 - -/** - * struct apds990x_chip_factors - defines effect of the cover window - * @ga: Total glass attenuation - * @cf1: clear channel factor 1 for raw to lux conversion - * @irf1: IR channel factor 1 for raw to lux conversion - * @cf2: clear channel factor 2 for raw to lux conversion - * @irf2: IR channel factor 2 for raw to lux conversion - * @df: device factor for conversion formulas - * - * Structure for tuning ALS calculation to match with environment. - * Values depend on the material above the sensor and the sensor - * itself. If the GA is zero, driver will use uncovered sensor default values - * format: decimal value * APDS_PARAM_SCALE except df which is plain integer. - */ -struct apds990x_chip_factors { - int ga; - int cf1; - int irf1; - int cf2; - int irf2; - int df; -}; -#define APDS_PARAM_SCALE 4096 - -/** - * struct apds990x_platform_data - platform data for apsd990x.c driver - * @cf: chip factor data - * @pdrive: IR-led driving current - * @ppcount: number of IR pulses used for proximity estimation - * @setup_resources: interrupt line setup call back function - * @release_resources: interrupt line release call back function - * - * Proximity detection result depends heavily on correct ppcount, pdrive - * and cover window. - * - */ - -struct apds990x_platform_data { - struct apds990x_chip_factors cf; - u8 pdrive; - u8 ppcount; - int (*setup_resources)(void); - int (*release_resources)(void); -}; - -#endif diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 6d269b844271..c9295c707041 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -53,6 +53,7 @@ enum iio_chan_type { IIO_CHROMATICITY, IIO_ATTENTION, IIO_ALTCURRENT, + IIO_COVERAGE, }; enum iio_modifier { @@ -113,6 +114,7 @@ enum iio_modifier { IIO_MOD_ACTIVE, IIO_MOD_REACTIVE, IIO_MOD_APPARENT, + IIO_MOD_QUATERNION_AXIS, }; enum iio_event_type { diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index c3c2052c9206..83ce50def5ac 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -11,16 +11,27 @@ use crate::{ bindings, device::Device, - error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR}, - ffi::{c_int, c_long, c_uint, c_ulong}, - fs::{File, Kiocb}, - iov::{IovIterDest, IovIterSource}, + error::{ + to_result, + VTABLE_DEFAULT_ERROR, // + }, + fs::{ + File, + Kiocb, // + }, + iov::{ + IovIterDest, + IovIterSource, // + }, mm::virt::VmaNew, prelude::*, seq_file::SeqFile, - types::{ForeignOwnable, Opaque}, + types::{ + ForeignOwnable, + Opaque, // + }, }; -use core::{marker::PhantomData, pin::Pin}; +use core::marker::PhantomData; /// Options for creating a misc device. #[derive(Copy, Clone)] diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs index 87a1fe63533a..41e26c825060 100644 --- a/samples/rust/rust_misc_device.rs +++ b/samples/rust/rust_misc_device.rs @@ -97,14 +97,36 @@ use kernel::{ device::Device, - fs::{File, Kiocb}, - ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, - iov::{IovIterDest, IovIterSource}, - miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration}, + fs::{ + File, + Kiocb, // + }, + ioctl::{ + _IO, + _IOC_SIZE, + _IOR, + _IOW, // + }, + iov::{ + IovIterDest, + IovIterSource, // + }, + miscdevice::{ + MiscDevice, + MiscDeviceOptions, + MiscDeviceRegistration, // + }, new_mutex, prelude::*, - sync::{aref::ARef, Mutex}, - uaccess::{UserSlice, UserSliceReader, UserSliceWriter}, + sync::{ + aref::ARef, + Mutex, // + }, + uaccess::{ + UserSlice, + UserSliceReader, + UserSliceWriter, // + }, }; const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80); diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index 03ca33869ce8..bc3ef4c77c2b 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CHROMATICITY] = "chromaticity", [IIO_ATTENTION] = "attention", [IIO_ALTCURRENT] = "altcurrent", + [IIO_COVERAGE] = "coverage", }; static const char * const iio_ev_type_text[] = { @@ -145,6 +146,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_ACTIVE] = "active", [IIO_MOD_REACTIVE] = "reactive", [IIO_MOD_APPARENT] = "apparent", + [IIO_MOD_QUATERNION_AXIS] = "quaternionaxis", }; static bool event_is_known(struct iio_event_data *event) @@ -193,6 +195,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_CHROMATICITY: case IIO_ATTENTION: case IIO_ALTCURRENT: + case IIO_COVERAGE: break; default: return false; diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c index bc82bb6a7a2a..000193612aad 100644 --- a/tools/iio/iio_generic_buffer.c +++ b/tools/iio/iio_generic_buffer.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -89,12 +90,19 @@ static void print1byte(uint8_t input, struct iio_channel_info *info) */ input >>= info->shift; input &= info->mask; - if (info->is_signed) { + switch (info->format) { + case 's': { int8_t val = (int8_t)(input << (8 - info->bits_used)) >> (8 - info->bits_used); printf("%05f ", ((float)val + info->offset) * info->scale); - } else { + break; + } + case 'u': printf("%05f ", ((float)input + info->offset) * info->scale); + break; + case 'f': + printf(" "); + break; } } @@ -112,12 +120,30 @@ static void print2byte(uint16_t input, struct iio_channel_info *info) */ input >>= info->shift; input &= info->mask; - if (info->is_signed) { + switch (info->format) { + case 's': { int16_t val = (int16_t)(input << (16 - info->bits_used)) >> (16 - info->bits_used); printf("%05f ", ((float)val + info->offset) * info->scale); - } else { + break; + } + case 'u': printf("%05f ", ((float)input + info->offset) * info->scale); + break; + case 'f': { +#if defined(__FLT16_MAX__) + union { + uint16_t u; + _Float16 f; + } converter; + + converter.u = input; + printf("%05f ", ((float)converter.f + info->offset) * info->scale); +#else + printf(" "); +#endif + break; + } } } @@ -135,12 +161,26 @@ static void print4byte(uint32_t input, struct iio_channel_info *info) */ input >>= info->shift; input &= info->mask; - if (info->is_signed) { + switch (info->format) { + case 's': { int32_t val = (int32_t)(input << (32 - info->bits_used)) >> (32 - info->bits_used); printf("%05f ", ((float)val + info->offset) * info->scale); - } else { + break; + } + case 'u': printf("%05f ", ((float)input + info->offset) * info->scale); + break; + case 'f': { + union { + uint32_t u; + float f; + } converter; + + converter.u = input; + printf("%05f ", (converter.f + info->offset) * info->scale); + break; + } } } @@ -158,7 +198,8 @@ static void print8byte(uint64_t input, struct iio_channel_info *info) */ input >>= info->shift; input &= info->mask; - if (info->is_signed) { + switch (info->format) { + case 's': { int64_t val = (int64_t)(input << (64 - info->bits_used)) >> (64 - info->bits_used); /* special case for timestamp */ @@ -167,8 +208,21 @@ static void print8byte(uint64_t input, struct iio_channel_info *info) else printf("%05f ", ((float)val + info->offset) * info->scale); - } else { + break; + } + case 'u': printf("%05f ", ((float)input + info->offset) * info->scale); + break; + case 'f': { + union { + uint64_t u; + double f; + } converter; + + converter.u = input; + printf("%05f ", (converter.f + info->offset) * info->scale); + break; + } } } diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c index c5c5082cb24e..e274a0d8376b 100644 --- a/tools/iio/iio_utils.c +++ b/tools/iio/iio_utils.c @@ -70,7 +70,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name) /** * iioutils_get_type() - find and process _type attribute data - * @is_signed: output whether channel is signed + * @format: output channel format * @bytes: output how many bytes the channel storage occupies * @bits_used: output number of valid bits of data * @shift: output amount of bits to shift right data before applying bit mask @@ -83,7 +83,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name) * * Returns a value >= 0 on success, otherwise a negative error code. **/ -static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes, +static int iioutils_get_type(char *format, unsigned int *bytes, unsigned int *bits_used, unsigned int *shift, uint64_t *mask, unsigned int *be, const char *device_dir, int buffer_idx, @@ -93,7 +93,7 @@ static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes, int ret; DIR *dp; char *scan_el_dir, *builtname, *builtname_generic, *filename = 0; - char signchar, endianchar; + char formatchar, endianchar; unsigned padint; const struct dirent *ent; @@ -140,7 +140,7 @@ static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes, ret = fscanf(sysfsfp, "%ce:%c%u/%u>>%u", &endianchar, - &signchar, + &formatchar, bits_used, &padint, shift); if (ret < 0) { @@ -162,7 +162,7 @@ static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes, else *mask = (1ULL << *bits_used) - 1ULL; - *is_signed = (signchar == 's'); + *format = formatchar; if (fclose(sysfsfp)) { ret = -errno; fprintf(stderr, "Failed to close %s\n", @@ -487,7 +487,7 @@ int build_channel_array(const char *device_dir, int buffer_idx, if ((ret < 0) && (ret != -ENOENT)) goto error_cleanup_array; - ret = iioutils_get_type(¤t->is_signed, + ret = iioutils_get_type(¤t->format, ¤t->bytes, ¤t->bits_used, ¤t->shift, diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h index 663c94a6c705..8c72f002d050 100644 --- a/tools/iio/iio_utils.h +++ b/tools/iio/iio_utils.h @@ -32,7 +32,7 @@ extern const char *iio_dir; * @shift: amount of bits to shift right data before applying bit mask * @mask: a bit mask for the raw output * @be: flag if data is big endian - * @is_signed: is the raw value stored signed + * @format: format of the raw value * @location: data offset for this channel inside the buffer (in bytes) **/ struct iio_channel_info { @@ -46,7 +46,7 @@ struct iio_channel_info { unsigned shift; uint64_t mask; unsigned be; - unsigned is_signed; + char format; unsigned location; };