diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml index c1d225fcf2d5..56fc71d6a081 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml @@ -23,6 +23,7 @@ properties: - enum: - qcom,qcm2290-cpufreq-hw - qcom,sc7180-cpufreq-hw + - qcom,sdm670-cpufreq-hw - qcom,sdm845-cpufreq-hw - qcom,sm6115-cpufreq-hw - qcom,sm6350-cpufreq-hw @@ -36,11 +37,13 @@ properties: - qcom,sa8775p-cpufreq-epss - qcom,sc7280-cpufreq-epss - qcom,sc8280xp-cpufreq-epss + - qcom,sdx75-cpufreq-epss - qcom,sm6375-cpufreq-epss - qcom,sm8250-cpufreq-epss - qcom,sm8350-cpufreq-epss - qcom,sm8450-cpufreq-epss - qcom,sm8550-cpufreq-epss + - qcom,sm8650-cpufreq-epss - const: qcom,cpufreq-epss reg: @@ -128,6 +131,7 @@ allOf: - qcom,qdu1000-cpufreq-epss - qcom,sc7180-cpufreq-hw - qcom,sc8280xp-cpufreq-epss + - qcom,sdm670-cpufreq-hw - qcom,sdm845-cpufreq-hw - qcom,sm6115-cpufreq-hw - qcom,sm6350-cpufreq-hw diff --git a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml index 7e1bb992ce90..547265b8b118 100644 --- a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml +++ b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml @@ -27,8 +27,12 @@ select: enum: - qcom,apq8064 - qcom,apq8096 + - qcom,ipq5332 + - qcom,ipq6018 - qcom,ipq8064 - qcom,ipq8074 + - qcom,ipq9574 + - qcom,msm8909 - qcom,msm8939 - qcom,msm8960 - qcom,msm8974 @@ -43,7 +47,9 @@ patternProperties: - if: properties: compatible: - const: operating-points-v2-kryo-cpu + enum: + - operating-points-v2-krait-cpu + - operating-points-v2-kryo-cpu then: $ref: /schemas/opp/opp-v2-kryo-cpu.yaml# diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml b/Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml new file mode 100644 index 000000000000..50d3fabe958d --- /dev/null +++ b/Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/devfreq/event/rockchip,dfi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip DFI + +maintainers: + - Sascha Hauer + +properties: + compatible: + enum: + - rockchip,rk3399-dfi + - rockchip,rk3568-dfi + - rockchip,rk3588-dfi + + clocks: + maxItems: 1 + + clock-names: + items: + - const: pclk_ddr_mon + + interrupts: + minItems: 1 + maxItems: 4 + + reg: + maxItems: 1 + + rockchip,pmu: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "PMU general register files". + +required: + - compatible + - interrupts + - reg + +if: + properties: + compatible: + contains: + enum: + - rockchip,rk3399-dfi + +then: + required: + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + + bus { + #address-cells = <2>; + #size-cells = <2>; + + dfi: dfi@ff630000 { + compatible = "rockchip,rk3399-dfi"; + reg = <0x00 0xff630000 0x00 0x4000>; + interrupts = ; + rockchip,pmu = <&pmugrf>; + clocks = <&cru PCLK_DDR_MON>; + clock-names = "pclk_ddr_mon"; + }; + }; diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt deleted file mode 100644 index 148191b0fc15..000000000000 --- a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt +++ /dev/null @@ -1,18 +0,0 @@ - -* Rockchip rk3399 DFI device - -Required properties: -- compatible: Must be "rockchip,rk3399-dfi". -- reg: physical base address of each DFI and length of memory mapped region -- rockchip,pmu: phandle to the syscon managing the "pmu general register files" -- clocks: phandles for clock specified in "clock-names" property -- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon"; - -Example: - dfi: dfi@ff630000 { - compatible = "rockchip,rk3399-dfi"; - reg = <0x00 0xff630000 0x00 0x4000>; - rockchip,pmu = <&pmugrf>; - clocks = <&cru PCLK_DDR_MON>; - clock-names = "pclk_ddr_mon"; - }; diff --git a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml index d0ca2af89f1e..918776d16ef3 100644 --- a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml @@ -18,9 +18,17 @@ properties: - fsl,imx31-gpio - fsl,imx35-gpio - fsl,imx7d-gpio + - items: + - enum: + - fsl,imx27-gpio + - const: fsl,imx21-gpio - items: - const: fsl,imx35-gpio - const: fsl,imx31-gpio + - items: + - enum: + - fsl,imx25-gpio + - const: fsl,imx35-gpio - items: - enum: - fsl,imx50-gpio diff --git a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml index 7c2d152e8617..a27f92950257 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml @@ -20,6 +20,7 @@ description: | properties: compatible: oneOf: + - const: fsl,imx8ulp-gpio - const: fsl,vf610-gpio - items: - const: fsl,imx7ulp-gpio @@ -27,16 +28,18 @@ properties: - items: - enum: - fsl,imx93-gpio - - fsl,imx8ulp-gpio - - const: fsl,imx7ulp-gpio + - fsl,imx95-gpio + - const: fsl,imx8ulp-gpio reg: - description: The first reg tuple represents the PORT module, the second tuple - represents the GPIO module. + minItems: 1 maxItems: 2 interrupts: - maxItems: 1 + items: + - description: GPIO Trustzone non-secure interrupt number + - description: GPIO Trustzone secure interrupt number + minItems: 1 interrupt-controller: true @@ -59,7 +62,8 @@ properties: - const: port gpio-ranges: - maxItems: 1 + minItems: 1 + maxItems: 4 patternProperties: "^.+-hog(-[0-9]+)?$": @@ -77,6 +81,30 @@ required: - "#gpio-cells" - gpio-controller +allOf: + - if: + properties: + compatible: + contains: + enum: + - fsl,vf610-gpio + - fsl,imx7ulp-gpio + then: + properties: + interrupts: + maxItems: 1 + reg: + items: + - description: PORT register base address + - description: GPIO register base address + else: + properties: + interrupts: + minItems: 2 + reg: + items: + - description: GPIO register base address + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt deleted file mode 100644 index 8dc41ed99685..000000000000 --- a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt +++ /dev/null @@ -1,38 +0,0 @@ -Intel IXP4xx XScale Networking Processors GPIO - -This GPIO controller is found in the Intel IXP4xx processors. -It supports 16 GPIO lines. - -The interrupt portions of the GPIO controller is hierarchical: -the synchronous edge detector is part of the GPIO block, but the -actual enabling/disabling of the interrupt line is done in the -main IXP4xx interrupt controller which has a 1:1 mapping for -the first 12 GPIO lines to 12 system interrupts. - -The remaining 4 GPIO lines can not be used for receiving -interrupts. - -The interrupt parent of this GPIO controller must be the -IXP4xx interrupt controller. - -Required properties: - -- compatible : Should be - "intel,ixp4xx-gpio" -- reg : Should contain registers location and length -- gpio-controller : marks this as a GPIO controller -- #gpio-cells : Should be 2, see gpio/gpio.txt -- interrupt-controller : marks this as an interrupt controller -- #interrupt-cells : a standard two-cell interrupt, see - interrupt-controller/interrupts.txt - -Example: - -gpio0: gpio@c8004000 { - compatible = "intel,ixp4xx-gpio"; - reg = <0xc8004000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; -}; diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml new file mode 100644 index 000000000000..bfcb1f364c3a --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/intel,ixp4xx-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Intel IXP4xx XScale Networking Processors GPIO Controller + +description: | + This GPIO controller is found in the Intel IXP4xx + processors. It supports 16 GPIO lines. + The interrupt portions of the GPIO controller is hierarchical. + The synchronous edge detector is part of the GPIO block, but the + actual enabling/disabling of the interrupt line is done in the + main IXP4xx interrupt controller which has a 1-to-1 mapping for + the first 12 GPIO lines to 12 system interrupts. + The remaining 4 GPIO lines can not be used for receiving + interrupts. + The interrupt parent of this GPIO controller must be the + IXP4xx interrupt controller. + GPIO 14 and 15 can be used as clock outputs rather than GPIO, + and this can be enabled by a special flag. + +maintainers: + - Linus Walleij + +properties: + compatible: + const: intel,ixp4xx-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 2 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + intel,ixp4xx-gpio14-clkout: + description: If defined, enables clock output on GPIO 14 + instead of GPIO. + type: boolean + + intel,ixp4xx-gpio15-clkout: + description: If defined, enables clock output on GPIO 15 + instead of GPIO. + type: boolean + +required: + - compatible + - reg + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + +additionalProperties: false + +examples: + - | + #include + gpio@c8004000 { + compatible = "intel,ixp4xx-gpio"; + reg = <0xc8004000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml index fb86e8ce6349..cf3b1b270aa8 100644 --- a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml @@ -11,9 +11,22 @@ maintainers: properties: compatible: - enum: - - loongson,ls2k-gpio - - loongson,ls7a-gpio + oneOf: + - enum: + - loongson,ls2k-gpio + - loongson,ls2k0500-gpio0 + - loongson,ls2k0500-gpio1 + - loongson,ls2k2000-gpio0 + - loongson,ls2k2000-gpio1 + - loongson,ls2k2000-gpio2 + - loongson,ls3a5000-gpio + - loongson,ls7a-gpio + - items: + - const: loongson,ls2k1000-gpio + - const: loongson,ls2k-gpio + - items: + - const: loongson,ls7a1000-gpio + - const: loongson,ls7a-gpio reg: maxItems: 1 @@ -49,7 +62,7 @@ examples: #include gpio0: gpio@1fe00500 { - compatible = "loongson,ls2k-gpio"; + compatible = "loongson,ls2k1000-gpio", "loongson,ls2k-gpio"; reg = <0x1fe00500 0x38>; ngpios = <64>; #gpio-cells = <2>; diff --git a/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml b/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml index 4e4af3cfc0fe..1f58ee99be28 100644 --- a/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/rockchip,rk3399-dmc.yaml @@ -18,7 +18,7 @@ properties: $ref: /schemas/types.yaml#/definitions/phandle description: Node to get DDR loading. Refer to - Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt. + Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml. clocks: maxItems: 1 diff --git a/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml b/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml index bbbad31ae4ca..fd04d060c1de 100644 --- a/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml +++ b/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml @@ -26,7 +26,9 @@ description: | properties: compatible: - const: operating-points-v2-kryo-cpu + enum: + - operating-points-v2-krait-cpu + - operating-points-v2-kryo-cpu nvmem-cells: description: | @@ -47,6 +49,8 @@ patternProperties: opp-microvolt: true + opp-peak-kBps: true + opp-supported-hw: description: | A single 32 bit bitmap value, representing compatible HW. @@ -63,14 +67,22 @@ patternProperties: 5: MSM8996SG, speedbin 1 6: MSM8996SG, speedbin 2 7-31: unused - enum: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x9, 0xd, 0xe, 0xf, - 0x10, 0x20, 0x30, 0x70] + + Bitmap for IPQ806x SoC: + 0: IPQ8062 + 1: IPQ8064/IPQ8066/IPQ8068 + 2: IPQ8065/IPQ8069 + 3-31: unused + + Other platforms use bits directly corresponding to speedbin index. clock-latency-ns: true required-opps: true + patternProperties: + '^opp-microvolt-speed[0-9]+-pvs[0-9]+$': true + required: - opp-hz @@ -256,6 +268,22 @@ examples: }; }; + /* Dummy opp table to give example for named opp-microvolt */ + opp-table-2 { + compatible = "operating-points-v2-krait-cpu"; + nvmem-cells = <&speedbin_efuse>; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + opp-microvolt-speed0-pvs0 = <1000000 950000 1050000>; + opp-microvolt-speed0-pvs1 = <925000 878750 971250>; + opp-microvolt-speed0-pvs2 = <875000 831250 918750>; + opp-microvolt-speed0-pvs3 = <800000 760000 840000>; + opp-supported-hw = <0x7>; + clock-latency-ns = <100000>; + }; + }; + smem { compatible = "qcom,smem"; memory-region = <&smem_mem>; diff --git a/Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml b/Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml new file mode 100644 index 000000000000..aa581e550be2 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/adi,max77503-regulator.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright (c) 2023 Analog Devices, Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/adi,max77503-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX77503 Buck Converter + +maintainers: + - Gokhan Celik + +description: | + The Analog Devices MAX77503 is a single channel 14V input, 1.5A + high-efficiency buck converter. This converter has 94% efficiency + for 2-Cell/3-Cell battery applications. + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + enum: + - adi,max77503 + + reg: + description: I2C address of the device + items: + - enum: [0x1e, 0x24, 0x37] + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@1e { + compatible = "adi,max77503"; + reg = <0x1e>; + + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <5000000>; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/da9210.txt b/Documentation/devicetree/bindings/regulator/da9210.txt deleted file mode 100644 index 58065ca9e3b4..000000000000 --- a/Documentation/devicetree/bindings/regulator/da9210.txt +++ /dev/null @@ -1,29 +0,0 @@ -* Dialog Semiconductor DA9210 Multi-phase 12A DCDC BUCK Converter - -Required properties: - -- compatible: must be "dlg,da9210" -- reg: the i2c slave address of the regulator. It should be 0x68. - -Optional properties: - -- interrupts: a reference to the DA9210 interrupt, if available. - -Any standard regulator properties can be used to configure the single da9210 -DCDC. - -Example: - - da9210@68 { - compatible = "dlg,da9210"; - reg = <0x68>; - - interrupt-parent = <...>; - interrupts = <...>; - - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <1570000>; - regulator-min-microamp = <1600000>; - regulator-max-microamp = <4600000>; - regulator-boot-on; - }; diff --git a/Documentation/devicetree/bindings/regulator/dlg,da9210.yaml b/Documentation/devicetree/bindings/regulator/dlg,da9210.yaml new file mode 100644 index 000000000000..81f23de36de4 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/dlg,da9210.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/dlg,da9210.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Dialog Semiconductor DA9210 Multi-Phase 12A DC-DC Buck Converter + +maintainers: + - Support Opensource + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + const: dlg,da9210 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@68 { + compatible = "dlg,da9210"; + reg = <0x68>; + + interrupt-parent = <&irqc0>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1570000>; + regulator-min-microamp = <1600000>; + regulator-max-microamp = <4600000>; + regulator-boot-on; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml index ac0281b1cceb..ce7751b9129c 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml @@ -100,6 +100,11 @@ properties: vin-supply: description: Input supply phandle. + interrupts: + maxItems: 1 + description: + Interrupt signaling a critical under-voltage event. + required: - compatible - regulator-name diff --git a/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml b/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml index 05f72391185e..7394c0a339c5 100644 --- a/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml +++ b/Documentation/devicetree/bindings/regulator/maxim,max20086.yaml @@ -43,6 +43,7 @@ properties: "^OUT[1-4]$": type: object $ref: regulator.yaml# + unevaluatedProperties: false additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml index 78c0b63243f7..6d6bbfbd26d4 100644 --- a/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml +++ b/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml @@ -30,10 +30,12 @@ properties: "^LDO([1-9]|1[0-5])$": type: object $ref: regulator.yaml# + unevaluatedProperties: false "^BUCK|BUCKBOOST$": type: object $ref: regulator.yaml# + unevaluatedProperties: false additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml new file mode 100644 index 000000000000..c50402fcba72 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml @@ -0,0 +1,250 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mediatek,mt6358-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6358 Regulator + +maintainers: + - Zhiyong Tao + +description: + Regulator node of the PMIC. This node should under the PMIC's device node. + All voltage regulators provided by the PMIC are described as sub-nodes of + this node. + +properties: + compatible: + oneOf: + - const: mediatek,mt6358-regulator + - items: + - const: mediatek,mt6366-regulator + - const: mediatek,mt6358-regulator + + vsys-ldo1-supply: + description: Supply for LDOs vfe28, vxo22, vcn28, vaux18, vaud28, vsim1, vusb, vbif28 + vsys-ldo2-supply: + description: Supply for LDOs vldo28 (MT6358 only), vio28, vmc, vmch, vsim2 + vsys-ldo3-supply: + description: Supply for LDOs vcn33, vcama[12] (MT6358 only), vemc, vibr + vsys-vcore-supply: + description: Supply for buck regulator vcore + vsys-vdram1-supply: + description: Supply for buck regulator vdram1 + vsys-vgpu-supply: + description: Supply for buck regulator vgpu + vsys-vmodem-supply: + description: Supply for buck regulator vmodem + vsys-vpa-supply: + description: Supply for buck regulator vpa + vsys-vproc11-supply: + description: Supply for buck regulator vproc11 + vsys-vproc12-supply: + description: Supply for buck regulator vproc12 + vsys-vs1-supply: + description: Supply for buck regulator vs1 + vsys-vs2-supply: + description: Supply for buck regulator vs2 + vs1-ldo1-supply: + description: + Supply for LDOs vrf18, vefuse, vcn18, vcamio (MT6358 only), vio18, vm18 (MT6366 only) + vs2-ldo1-supply: + description: Supply for LDOs vdram2, vmddr (MT6366 only) + vs2-ldo2-supply: + description: Supply for LDOs vrf12, va12 + vs2-ldo3-supply: + description: + Supply for LDOs vsram-core (MT6366 only), vsram-gpu, vsram-others, vsram-proc11, vsram-proc12 + vs2-ldo4-supply: + description: Supply for LDO vcamd + +patternProperties: + "^(buck_)?v(core|dram1|gpu|modem|pa|proc1[12]|s[12])$": + description: Buck regulators + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: + description: | + Buck regulatpr operating modes allowed. Valid values below. + Users should use the macros from dt-bindings/regulator/mediatek,mt6397-regulator.h + 0 (MT6397_BUCK_MODE_AUTO): Auto PFM/PWM mode + 1 (MT6397_BUCK_MODE_FORCE_PWM): Forced PWM mode + items: + enum: [0, 1] + unevaluatedProperties: false + + "^(ldo_)?v(a|rf)12$": + description: LDOs with fixed 1.2V output and 0~100/10mV tuning + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + + "^(ldo_)?v((aux|cn|io|rf)18|camio)$": + description: + LDOs with fixed 1.8V output and 0~100/10mV tuning (vcn18 on MT6366 has variable output) + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + + "^(ldo_)?vxo22$": + description: LDOs with fixed 2.2V output and 0~100/10mV tuning + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + + "^(ldo_)?v(aud|bif|cn|fe|io)28$": + description: LDOs with fixed 2.8V output and 0~100/10mV tuning + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + + "^(ldo_)?vusb$": + description: LDOs with fixed 3.0V output and 0~100/10mV tuning + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + + "^(ldo_)?vsram[_-](core|gpu|others|proc1[12])$": + description: LDOs with variable output + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + + "^(ldo_)?v(cama[12]|camd|cn33|dram2|efuse|emc|ibr|ldo28|m18|mc|mch|mddr|sim[12])$": + description: LDOs with variable output and 0~100/10mV tuning + type: object + $ref: regulator.yaml# + properties: + regulator-allowed-modes: false + unevaluatedProperties: false + +required: + - compatible + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + const: mediatek,mt6358-regulator + then: + patternProperties: + # Old regulator node name scheme (with prefix and underscores) only + # ([^y-] is used to avoid matching -supply + "^(? + + regulator { + compatible = "mediatek,mt6358-regulator"; + + buck_vgpu { + regulator-name = "vgpu"; + regulator-min-microvolt = <625000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <200>; + regulator-allowed-modes = ; + }; + + ldo_vsram_gpu { + regulator-name = "vsram_gpu"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <240>; + }; + }; + + - | + #include + + regulator { + compatible = "mediatek,mt6366-regulator", "mediatek,mt6358-regulator"; + + vdram1 { + regulator-name = "pp1125_emi_vdd2"; + regulator-min-microvolt = <1125000>; + regulator-max-microvolt = <1125000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = ; + regulator-always-on; + }; + + vproc11 { + regulator-name = "ppvar_dvdd_proc_bc_mt6366"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1200000>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <200>; + regulator-allowed-modes = ; + regulator-always-on; + }; + + vmddr { + regulator-name = "pm0750_emi_vmddr"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <750000>; + regulator-enable-ramp-delay = <325>; + regulator-always-on; + }; + + vsram-proc11 { + regulator-name = "pp0900_dvdd_sram_bc"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1120000>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <240>; + regulator-always-on; + }; + }; +... diff --git a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt deleted file mode 100644 index b6384306db5c..000000000000 --- a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt +++ /dev/null @@ -1,350 +0,0 @@ -MediaTek MT6358 Regulator - -All voltage regulators provided by the MT6358 PMIC are described as the -subnodes of the MT6358 regulators node. Each regulator is named according -to its regulator type, buck_ and ldo_. The definition for each -of these nodes is defined using the standard binding for regulators at -Documentation/devicetree/bindings/regulator/regulator.txt. - -The valid names for regulators are:: -BUCK: - buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu, - buck_vs2, buck_vmodem, buck_vs1 -LDO: - ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio, - ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others, - ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28, - ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18, - ldo_vcn33, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28, ldo_vsim2 - -Example: - - pmic { - compatible = "mediatek,mt6358"; - - mt6358regulator: mt6358regulator { - compatible = "mediatek,mt6358-regulator"; - - mt6358_vdram1_reg: buck_vdram1 { - regulator-compatible = "buck_vdram1"; - regulator-name = "vdram1"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <2087500>; - regulator-ramp-delay = <12500>; - regulator-enable-ramp-delay = <0>; - regulator-always-on; - }; - - mt6358_vcore_reg: buck_vcore { - regulator-name = "vcore"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <200>; - regulator-always-on; - }; - - mt6358_vpa_reg: buck_vpa { - regulator-name = "vpa"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <3650000>; - regulator-ramp-delay = <50000>; - regulator-enable-ramp-delay = <250>; - }; - - mt6358_vproc11_reg: buck_vproc11 { - regulator-name = "vproc11"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <200>; - regulator-always-on; - }; - - mt6358_vproc12_reg: buck_vproc12 { - regulator-name = "vproc12"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <200>; - regulator-always-on; - }; - - mt6358_vgpu_reg: buck_vgpu { - regulator-name = "vgpu"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <200>; - }; - - mt6358_vs2_reg: buck_vs2 { - regulator-name = "vs2"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <2087500>; - regulator-ramp-delay = <12500>; - regulator-enable-ramp-delay = <0>; - regulator-always-on; - }; - - mt6358_vmodem_reg: buck_vmodem { - regulator-name = "vmodem"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <900>; - regulator-always-on; - }; - - mt6358_vs1_reg: buck_vs1 { - regulator-name = "vs1"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <2587500>; - regulator-ramp-delay = <12500>; - regulator-enable-ramp-delay = <0>; - regulator-always-on; - }; - - mt6358_vdram2_reg: ldo_vdram2 { - regulator-name = "vdram2"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <3300>; - }; - - mt6358_vsim1_reg: ldo_vsim1 { - regulator-name = "vsim1"; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <3100000>; - regulator-enable-ramp-delay = <540>; - }; - - mt6358_vibr_reg: ldo_vibr { - regulator-name = "vibr"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <3300000>; - regulator-enable-ramp-delay = <60>; - }; - - mt6358_vrf12_reg: ldo_vrf12 { - compatible = "regulator-fixed"; - regulator-name = "vrf12"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-enable-ramp-delay = <120>; - }; - - mt6358_vio18_reg: ldo_vio18 { - compatible = "regulator-fixed"; - regulator-name = "vio18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <2700>; - regulator-always-on; - }; - - mt6358_vusb_reg: ldo_vusb { - regulator-name = "vusb"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3100000>; - regulator-enable-ramp-delay = <270>; - regulator-always-on; - }; - - mt6358_vcamio_reg: ldo_vcamio { - compatible = "regulator-fixed"; - regulator-name = "vcamio"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vcamd_reg: ldo_vcamd { - regulator-name = "vcamd"; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vcn18_reg: ldo_vcn18 { - compatible = "regulator-fixed"; - regulator-name = "vcn18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vfe28_reg: ldo_vfe28 { - compatible = "regulator-fixed"; - regulator-name = "vfe28"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vsram_proc11_reg: ldo_vsram_proc11 { - regulator-name = "vsram_proc11"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <240>; - regulator-always-on; - }; - - mt6358_vcn28_reg: ldo_vcn28 { - compatible = "regulator-fixed"; - regulator-name = "vcn28"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vsram_others_reg: ldo_vsram_others { - regulator-name = "vsram_others"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <240>; - regulator-always-on; - }; - - mt6358_vsram_gpu_reg: ldo_vsram_gpu { - regulator-name = "vsram_gpu"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <240>; - }; - - mt6358_vxo22_reg: ldo_vxo22 { - compatible = "regulator-fixed"; - regulator-name = "vxo22"; - regulator-min-microvolt = <2200000>; - regulator-max-microvolt = <2200000>; - regulator-enable-ramp-delay = <120>; - regulator-always-on; - }; - - mt6358_vefuse_reg: ldo_vefuse { - regulator-name = "vefuse"; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <1900000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vaux18_reg: ldo_vaux18 { - compatible = "regulator-fixed"; - regulator-name = "vaux18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vmch_reg: ldo_vmch { - regulator-name = "vmch"; - regulator-min-microvolt = <2900000>; - regulator-max-microvolt = <3300000>; - regulator-enable-ramp-delay = <60>; - }; - - mt6358_vbif28_reg: ldo_vbif28 { - compatible = "regulator-fixed"; - regulator-name = "vbif28"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vsram_proc12_reg: ldo_vsram_proc12 { - regulator-name = "vsram_proc12"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - regulator-ramp-delay = <6250>; - regulator-enable-ramp-delay = <240>; - regulator-always-on; - }; - - mt6358_vcama1_reg: ldo_vcama1 { - regulator-name = "vcama1"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vemc_reg: ldo_vemc { - regulator-name = "vemc"; - regulator-min-microvolt = <2900000>; - regulator-max-microvolt = <3300000>; - regulator-enable-ramp-delay = <60>; - regulator-always-on; - }; - - mt6358_vio28_reg: ldo_vio28 { - compatible = "regulator-fixed"; - regulator-name = "vio28"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_va12_reg: ldo_va12 { - compatible = "regulator-fixed"; - regulator-name = "va12"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-enable-ramp-delay = <270>; - regulator-always-on; - }; - - mt6358_vrf18_reg: ldo_vrf18 { - compatible = "regulator-fixed"; - regulator-name = "vrf18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-enable-ramp-delay = <120>; - }; - - mt6358_vcn33_reg: ldo_vcn33 { - regulator-name = "vcn33"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3500000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vcama2_reg: ldo_vcama2 { - regulator-name = "vcama2"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vmc_reg: ldo_vmc { - regulator-name = "vmc"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-enable-ramp-delay = <60>; - }; - - mt6358_vldo28_reg: ldo_vldo28 { - regulator-name = "vldo28"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <3000000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vaud28_reg: ldo_vaud28 { - compatible = "regulator-fixed"; - regulator-name = "vaud28"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vsim2_reg: ldo_vsim2 { - regulator-name = "vsim2"; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <3100000>; - regulator-enable-ramp-delay = <540>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml b/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml index eb61e04ef852..b5181719daa1 100644 --- a/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml +++ b/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml @@ -48,10 +48,12 @@ properties: "^LDO[1-4]$": type: object $ref: regulator.yaml# + unevaluatedProperties: false "^BUCK|BOOST$": type: object $ref: regulator.yaml# + unevaluatedProperties: false additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index 127a6f39b7f0..acd37f28ef53 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -50,6 +50,7 @@ description: | For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2 For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 For PMI8998, bob + For PMC8380, smps1 - smps8, ldo1 - lodo3 For PMR735A, smps1 - smps3, ldo1 - ldo7 For PMX55, smps1 - smps7, ldo1 - ldo16 For PMX65, smps1 - smps8, ldo1 - ldo21 @@ -78,6 +79,7 @@ properties: - qcom,pm8998-rpmh-regulators - qcom,pmc8180-rpmh-regulators - qcom,pmc8180c-rpmh-regulators + - qcom,pmc8380-rpmh-regulators - qcom,pmg1110-rpmh-regulators - qcom,pmi8998-rpmh-regulators - qcom,pmm8155au-rpmh-regulators @@ -364,6 +366,16 @@ allOf: patternProperties: "^vdd-s([1-9]|1[0-3])-supply$": true + - if: + properties: + compatible: + enum: + - qcom,pmc8380-rpmh-regulators + then: + patternProperties: + "^vdd-l[1-3]-supply$": true + "^vdd-s[1-8]-supply$": true + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml index bdf34c2de96b..7a1b7d2abbd4 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml @@ -17,12 +17,15 @@ properties: - qcom,pm660l-regulators - qcom,pm8004-regulators - qcom,pm8005-regulators + - qcom,pm8019-regulators - qcom,pm8226-regulators - qcom,pm8841-regulators + - qcom,pm8909-regulators - qcom,pm8916-regulators - qcom,pm8941-regulators - qcom,pm8950-regulators - qcom,pm8994-regulators + - qcom,pma8084-regulators - qcom,pmi8994-regulators - qcom,pmp8074-regulators - qcom,pms405-regulators @@ -32,7 +35,7 @@ properties: $ref: /schemas/types.yaml#/definitions/phandle patternProperties: - "^(5vs[1-2]|(l|s)[1-9][0-9]?|lvs[1-3])$": + "^(5vs[1-2]|(l|s)[1-9][0-9]?|lvs[1-4])$": description: List of regulators and its properties type: object $ref: regulator.yaml# @@ -176,6 +179,25 @@ allOf: patternProperties: "^vdd_s[1-4]-supply$": true + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8019-regulators + then: + properties: + vdd_l1-supply: true + vdd_l2_l3-supply: true + vdd_l4_l5_l6-supply: true + vdd_l7_l8_l11-supply: true + vdd_l9-supply: true + vdd_l10-supply: true + vdd_l12-supply: true + vdd_l13_l14-supply: true + patternProperties: + "^vdd_s[1-4]-supply$": true + - if: properties: compatible: @@ -206,6 +228,24 @@ allOf: patternProperties: "^vdd_s[1-8]-supply$": true + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8909-regulators + then: + properties: + vdd_s1-supply: true + vdd_s2-supply: true + vdd_l1-supply: true + vdd_l2_l5-supply: true + vdd_l3_l6_l10-supply: true + vdd_l4_l7-supply: true + vdd_l8_l11_l15_l18-supply: true + vdd_l9_l12_l14_l17-supply: true + vdd_l13-supply: true + - if: properties: compatible: @@ -295,6 +335,32 @@ allOf: patternProperties: "^vdd_s[1-9][0-2]?-supply$": true + - if: + properties: + compatible: + contains: + enum: + - qcom,pma8084-regulators + then: + properties: + vdd_l1_l11-supply: true + vdd_l2_l3_l4_l27-supply: true + vdd_l5_l7-supply: true + vdd_l6_l12_l14_l15_l26-supply: true + vdd_l8-supply: true + vdd_l9_l10_l13_l20_l23_l24-supply: true + vdd_l16_l25-supply: true + vdd_l17-supply: true + vdd_l18-supply: true + vdd_l19-supply: true + vdd_l21-supply: true + vdd_l22-supply: true + vdd_lvs1_2-supply: true + vdd_lvs3_4-supply: true + vdd_5vs1-supply: true + patternProperties: + "^vdd_s([1-9]|1[0-2])-supply$": true + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml index a6f34bdd1d3c..e1ab3f523ad6 100644 --- a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml +++ b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml @@ -46,6 +46,8 @@ properties: patternProperties: "^.*@[0-9a-f]+": type: object + additionalProperties: true + properties: reg: items: diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml index 28b8ace63044..3b47b68b92cb 100644 --- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml +++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml @@ -68,6 +68,8 @@ properties: patternProperties: "^.*@[0-9a-f]+": type: object + additionalProperties: true + properties: reg: items: diff --git a/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml new file mode 100644 index 000000000000..bb8b6863b109 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/arm,pl022-peripheral-props.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Peripheral-specific properties for Arm PL022 SPI controller + +maintainers: + - Linus Walleij + +select: false + +properties: + pl022,interface: + description: SPI interface type + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # SPI + - 1 # Texas Instruments Synchronous Serial Frame Format + - 2 # Microwire (Half Duplex) + + pl022,com-mode: + description: Specifies the transfer mode + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # interrupt mode + - 1 # polling mode + - 2 # DMA mode + default: 1 + + pl022,rx-level-trig: + description: Rx FIFO watermark level + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 4 + + pl022,tx-level-trig: + description: Tx FIFO watermark level + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 4 + + pl022,ctrl-len: + description: Microwire interface - Control length + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x03 + maximum: 0x1f + + pl022,wait-state: + description: Microwire interface - Wait state + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + pl022,duplex: + description: Microwire interface - Full/Half duplex + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + +additionalProperties: true +... diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml index 9ae1611175f2..48e97e240265 100644 --- a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml +++ b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml @@ -50,6 +50,7 @@ properties: patternProperties: "@[0-9a-f]+$": type: object + additionalProperties: true properties: spi-rx-bus-width: diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml b/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml index 93f14dd01afc..88be13268962 100644 --- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml +++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.yaml @@ -44,9 +44,17 @@ properties: - const: tx - const: rx + interconnects: + maxItems: 1 + interrupts: maxItems: 1 + operating-points-v2: true + + power-domains: + maxItems: 1 + reg: maxItems: 1 @@ -62,7 +70,9 @@ unevaluatedProperties: false examples: - | #include + #include #include + #include spi@7575000 { compatible = "qcom,spi-qup-v2.2.1"; @@ -76,6 +86,9 @@ examples: pinctrl-1 = <&blsp1_spi1_sleep>; dmas = <&blsp1_dma 12>, <&blsp1_dma 13>; dma-names = "tx", "rx"; + power-domains = <&rpmpd MSM8996_VDDCX>; + operating-points-v2 = <&spi_opp_table>; + interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>; #address-cells = <1>; #size-cells = <0>; }; diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml index e59183e53690..bed829837df1 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml @@ -39,6 +39,12 @@ properties: power-domains: maxItems: 1 + renesas,csi-no-ss: + type: boolean + description: + The CSI Slave Selection (SS) pin won't be used to enable transmission and + reception. Only available when in target mode. + required: - compatible - reg @@ -50,6 +56,9 @@ required: - '#address-cells' - '#size-cells' +dependencies: + renesas,csi-no-ss: [ spi-slave ] + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml b/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml index 339fb39529f3..ac1503de0478 100644 --- a/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml +++ b/Documentation/devicetree/bindings/spi/rockchip-sfc.yaml @@ -47,6 +47,8 @@ properties: patternProperties: "^flash@[0-3]$": type: object + additionalProperties: true + properties: reg: minimum: 0 diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml index a47cb144b09f..6348a387a21c 100644 --- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml +++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml @@ -160,6 +160,8 @@ properties: patternProperties: "^.*@[0-9a-f]+$": type: object + additionalProperties: true + properties: reg: minimum: 0 diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml index 782a014b63a7..15938f81fdce 100644 --- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml +++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml @@ -113,8 +113,14 @@ properties: minItems: 2 maxItems: 4 + st,spi-midi-ns: + description: | + Only for STM32H7, (Master Inter-Data Idleness) minimum time + delay in nanoseconds inserted between two consecutive data frames. + # The controller specific properties go here. allOf: + - $ref: arm,pl022-peripheral-props.yaml# - $ref: cdns,qspi-nor-peripheral-props.yaml# - $ref: samsung,spi-peripheral-props.yaml# - $ref: nvidia,tegra210-quad-peripheral-props.yaml# diff --git a/Documentation/devicetree/bindings/spi/spi-pl022.yaml b/Documentation/devicetree/bindings/spi/spi-pl022.yaml index 5e5a704a766e..7f174b7d0a26 100644 --- a/Documentation/devicetree/bindings/spi/spi-pl022.yaml +++ b/Documentation/devicetree/bindings/spi/spi-pl022.yaml @@ -74,57 +74,6 @@ properties: resets: maxItems: 1 -patternProperties: - "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$": - type: object - # SPI slave nodes must be children of the SPI master node and can - # contain the following properties. - properties: - pl022,interface: - description: SPI interface type - $ref: /schemas/types.yaml#/definitions/uint32 - enum: - - 0 # SPI - - 1 # Texas Instruments Synchronous Serial Frame Format - - 2 # Microwire (Half Duplex) - - pl022,com-mode: - description: Specifies the transfer mode - $ref: /schemas/types.yaml#/definitions/uint32 - enum: - - 0 # interrupt mode - - 1 # polling mode - - 2 # DMA mode - default: 1 - - pl022,rx-level-trig: - description: Rx FIFO watermark level - $ref: /schemas/types.yaml#/definitions/uint32 - minimum: 0 - maximum: 4 - - pl022,tx-level-trig: - description: Tx FIFO watermark level - $ref: /schemas/types.yaml#/definitions/uint32 - minimum: 0 - maximum: 4 - - pl022,ctrl-len: - description: Microwire interface - Control length - $ref: /schemas/types.yaml#/definitions/uint32 - minimum: 0x03 - maximum: 0x1f - - pl022,wait-state: - description: Microwire interface - Wait state - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1] - - pl022,duplex: - description: Microwire interface - Full/Half duplex - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1] - required: - compatible - reg diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml index 9ca1a843c820..ae0f082bd377 100644 --- a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml +++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml @@ -18,15 +18,6 @@ maintainers: allOf: - $ref: spi-controller.yaml# - - if: - properties: - compatible: - contains: - const: st,stm32f4-spi - - then: - properties: - st,spi-midi-ns: false properties: compatible: @@ -59,17 +50,6 @@ properties: - const: rx - const: tx -patternProperties: - "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$": - type: object - # SPI slave nodes must be children of the SPI master node and can - # contain the following properties. - properties: - st,spi-midi-ns: - description: | - Only for STM32H7, (Master Inter-Data Idleness) minimum time - delay in nanoseconds inserted between two consecutive data frames. - required: - compatible - reg diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst index de6fc79ad6f0..3e588b9d678c 100644 --- a/Documentation/driver-api/gpio/consumer.rst +++ b/Documentation/driver-api/gpio/consumer.rst @@ -29,6 +29,10 @@ warnings. These stubs are used for two use cases: will use it under other compile-time configurations. In this case the consumer must make sure not to call into these functions, or the user will be met with console warnings that may be perceived as intimidating. + Combining truly optional GPIOLIB usage with calls to + ``[devm_]gpiod_get_optional()`` is a *bad idea*, and will result in weird + error messages. Use the ordinary getter functions with optional GPIOLIB: + some open coding of error handling should be expected when you do this. All the functions that work with the descriptor-based GPIO interface are prefixed with ``gpiod_``. The ``gpio_`` prefix is used for the legacy diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst index 56d9913a3370..d79f69390991 100644 --- a/Documentation/firmware-guide/acpi/enumeration.rst +++ b/Documentation/firmware-guide/acpi/enumeration.rst @@ -64,6 +64,49 @@ If the driver needs to perform more complex initialization like getting and configuring GPIOs it can get its ACPI handle and extract this information from ACPI tables. +ACPI device objects +=================== + +Generally speaking, there are two categories of devices in a system in which +ACPI is used as an interface between the platform firmware and the OS: Devices +that can be discovered and enumerated natively, through a protocol defined for +the specific bus that they are on (for example, configuration space in PCI), +without the platform firmware assistance, and devices that need to be described +by the platform firmware so that they can be discovered. Still, for any device +known to the platform firmware, regardless of which category it falls into, +there can be a corresponding ACPI device object in the ACPI Namespace in which +case the Linux kernel will create a struct acpi_device object based on it for +that device. + +Those struct acpi_device objects are never used for binding drivers to natively +discoverable devices, because they are represented by other types of device +objects (for example, struct pci_dev for PCI devices) that are bound to by +device drivers (the corresponding struct acpi_device object is then used as +an additional source of information on the configuration of the given device). +Moreover, the core ACPI device enumeration code creates struct platform_device +objects for the majority of devices that are discovered and enumerated with the +help of the platform firmware and those platform device objects can be bound to +by platform drivers in direct analogy with the natively enumerable devices +case. Therefore it is logically inconsistent and so generally invalid to bind +drivers to struct acpi_device objects, including drivers for devices that are +discovered with the help of the platform firmware. + +Historically, ACPI drivers that bound directly to struct acpi_device objects +were implemented for some devices enumerated with the help of the platform +firmware, but this is not recommended for any new drivers. As explained above, +platform device objects are created for those devices as a rule (with a few +exceptions that are not relevant here) and so platform drivers should be used +for handling them, even though the corresponding ACPI device objects are the +only source of device configuration information in that case. + +For every device having a corresponding struct acpi_device object, the pointer +to it is returned by the ACPI_COMPANION() macro, so it is always possible to +get to the device configuration information stored in the ACPI device object +this way. Accordingly, struct acpi_device can be regarded as a part of the +interface between the kernel and the ACPI Namespace, whereas device objects of +other types (for example, struct pci_dev or struct platform_device) are used +for interacting with the rest of the system. + DMA support =========== diff --git a/MAINTAINERS b/MAINTAINERS index 5ed9ad875708..d2c13694bf57 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2224,7 +2224,7 @@ M: Imre Kaloz L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml -F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt +F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion* F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 67de96c7717d..0daf6c5b5c1c 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -561,22 +561,6 @@ static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = { &ams_delta_nand_gpio_table, }; -/* - * Some drivers may not use GPIO lookup tables but need to be provided - * with GPIO numbers. The same applies to GPIO based IRQ lines - some - * drivers may even not use GPIO layer but expect just IRQ numbers. - * We could either define GPIO lookup tables then use them on behalf - * of those devices, or we can use GPIO driver level methods for - * identification of GPIO and IRQ numbers. For the purpose of the latter, - * defina a helper function which identifies GPIO chips by their labels. - */ -static int gpiochip_match_by_label(struct gpio_chip *chip, void *data) -{ - char *label = data; - - return !strcmp(label, chip->label); -} - static struct gpiod_hog ams_delta_gpio_hogs[] = { GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout", GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW), @@ -616,14 +600,28 @@ static void __init modem_assign_irq(struct gpio_chip *chip) */ static void __init omap_gpio_deps_init(void) { + struct gpio_device *gdev; struct gpio_chip *chip; - chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label); - if (!chip) { - pr_err("%s: OMAP GPIO chip not found\n", __func__); + /* + * Some drivers may not use GPIO lookup tables but need to be provided + * with GPIO numbers. The same applies to GPIO based IRQ lines - some + * drivers may even not use GPIO layer but expect just IRQ numbers. + * We could either define GPIO lookup tables then use them on behalf + * of those devices, or we can use GPIO driver level methods for + * identification of GPIO and IRQ numbers. + * + * This reference will be leaked but that's alright as this device + * never goes down. + */ + gdev = gpio_device_find_by_label(OMAP_GPIO_LABEL); + if (!gdev) { + pr_err("%s: OMAP GPIO device not found\n", __func__); return; } + chip = gpio_device_get_chip(gdev); + /* * Start with FIQ initialization as it may have to request * and release successfully each OMAP GPIO pin in turn. diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 7e061d671fde..c917cb2c6e17 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -51,11 +51,6 @@ #define PALMTE_HDQ_GPIO 11 #define PALMTE_HEADPHONES_GPIO 14 #define PALMTE_SPEAKER_GPIO 15 -#define PALMTE_DC_GPIO OMAP_MPUIO(2) -#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4) -#define PALMTE_MMC1_GPIO OMAP_MPUIO(6) -#define PALMTE_MMC2_GPIO OMAP_MPUIO(7) -#define PALMTE_MMC3_GPIO OMAP_MPUIO(11) static const unsigned int palmte_keymap[] = { KEY(0, 0, KEY_F1), /* Calendar */ diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 225dc6818751..2d4a35e6dd18 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -32,8 +33,9 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); -static int acpi_ac_add(struct acpi_device *device); -static void acpi_ac_remove(struct acpi_device *device); +static int acpi_ac_probe(struct platform_device *pdev); +static void acpi_ac_remove(struct platform_device *pdev); + static void acpi_ac_notify(acpi_handle handle, u32 event, void *data); static const struct acpi_device_id ac_device_ids[] = { @@ -50,17 +52,6 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); static int ac_sleep_before_get_state_ms; static int ac_only; -static struct acpi_driver acpi_ac_driver = { - .name = "ac", - .class = ACPI_AC_CLASS, - .ids = ac_device_ids, - .ops = { - .add = acpi_ac_add, - .remove = acpi_ac_remove, - }, - .drv.pm = &acpi_ac_pm, -}; - struct acpi_ac { struct power_supply *charger; struct power_supply_desc charger_desc; @@ -128,15 +119,12 @@ static enum power_supply_property ac_props[] = { /* Driver Model */ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_device *device = data; - struct acpi_ac *ac = acpi_driver_data(device); - - if (!ac) - return; + struct acpi_ac *ac = data; + struct acpi_device *adev = ac->device; switch (event) { default: - acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n", + acpi_handle_debug(adev->handle, "Unsupported event [0x%x]\n", event); fallthrough; case ACPI_AC_NOTIFY_STATUS: @@ -153,10 +141,10 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) msleep(ac_sleep_before_get_state_ms); acpi_ac_get_state(ac); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, + acpi_bus_generate_netlink_event(adev->pnp.device_class, + dev_name(&adev->dev), event, (u32) ac->state); - acpi_notifier_call_chain(device, event, (u32) ac->state); + acpi_notifier_call_chain(adev, event, (u32) ac->state); kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE); } } @@ -213,24 +201,22 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { {}, }; -static int acpi_ac_add(struct acpi_device *device) +static int acpi_ac_probe(struct platform_device *pdev) { + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct power_supply_config psy_cfg = {}; - int result = 0; - struct acpi_ac *ac = NULL; - - - if (!device) - return -EINVAL; + struct acpi_ac *ac; + int result; ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); if (!ac) return -ENOMEM; - ac->device = device; - strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_AC_CLASS); - device->driver_data = ac; + ac->device = adev; + strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); + strcpy(acpi_device_class(adev), ACPI_AC_CLASS); + + platform_set_drvdata(pdev, ac); result = acpi_ac_get_state(ac); if (result) @@ -238,26 +224,26 @@ static int acpi_ac_add(struct acpi_device *device) psy_cfg.drv_data = ac; - ac->charger_desc.name = acpi_device_bid(device); + ac->charger_desc.name = acpi_device_bid(adev); ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS; ac->charger_desc.properties = ac_props; ac->charger_desc.num_properties = ARRAY_SIZE(ac_props); ac->charger_desc.get_property = get_ac_property; - ac->charger = power_supply_register(&ac->device->dev, + ac->charger = power_supply_register(&pdev->dev, &ac->charger_desc, &psy_cfg); if (IS_ERR(ac->charger)) { result = PTR_ERR(ac->charger); goto err_release_ac; } - pr_info("%s [%s] (%s)\n", acpi_device_name(device), - acpi_device_bid(device), ac->state ? "on-line" : "off-line"); + pr_info("%s [%s] (%s-line)\n", acpi_device_name(adev), + acpi_device_bid(adev), str_on_off(ac->state)); ac->battery_nb.notifier_call = acpi_ac_battery_notify; register_acpi_notifier(&ac->battery_nb); - result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY, - acpi_ac_notify); + result = acpi_dev_install_notify_handler(adev, ACPI_ALL_NOTIFY, + acpi_ac_notify, ac); if (result) goto err_unregister; @@ -275,16 +261,9 @@ err_release_ac: #ifdef CONFIG_PM_SLEEP static int acpi_ac_resume(struct device *dev) { - struct acpi_ac *ac; + struct acpi_ac *ac = dev_get_drvdata(dev); unsigned int old_state; - if (!dev) - return -EINVAL; - - ac = acpi_driver_data(to_acpi_device(dev)); - if (!ac) - return -EINVAL; - old_state = ac->state; if (acpi_ac_get_state(ac)) return 0; @@ -297,16 +276,11 @@ static int acpi_ac_resume(struct device *dev) #define acpi_ac_resume NULL #endif -static void acpi_ac_remove(struct acpi_device *device) +static void acpi_ac_remove(struct platform_device *pdev) { - struct acpi_ac *ac = NULL; + struct acpi_ac *ac = platform_get_drvdata(pdev); - if (!device || !acpi_driver_data(device)) - return; - - ac = acpi_driver_data(device); - - acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY, + acpi_dev_remove_notify_handler(ac->device, ACPI_ALL_NOTIFY, acpi_ac_notify); power_supply_unregister(ac->charger); unregister_acpi_notifier(&ac->battery_nb); @@ -314,6 +288,16 @@ static void acpi_ac_remove(struct acpi_device *device) kfree(ac); } +static struct platform_driver acpi_ac_driver = { + .probe = acpi_ac_probe, + .remove_new = acpi_ac_remove, + .driver = { + .name = "ac", + .acpi_match_table = ac_device_ids, + .pm = &acpi_ac_pm, + }, +}; + static int __init acpi_ac_init(void) { int result; @@ -326,7 +310,7 @@ static int __init acpi_ac_init(void) dmi_check_system(ac_dmi_table); - result = acpi_bus_register_driver(&acpi_ac_driver); + result = platform_driver_register(&acpi_ac_driver); if (result < 0) return -ENODEV; @@ -335,7 +319,7 @@ static int __init acpi_ac_init(void) static void __exit acpi_ac_exit(void) { - acpi_bus_unregister_driver(&acpi_ac_driver); + platform_driver_unregister(&acpi_ac_driver); } module_init(acpi_ac_init); module_exit(acpi_ac_exit); diff --git a/drivers/acpi/acpi_fpdt.c b/drivers/acpi/acpi_fpdt.c index a2056c4c8cb7..271092f2700a 100644 --- a/drivers/acpi/acpi_fpdt.c +++ b/drivers/acpi/acpi_fpdt.c @@ -194,12 +194,19 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_header = (void *)subtable_header + offset; offset += record_header->length; + if (!record_header->length) { + pr_err(FW_BUG "Zero-length record found in FPTD.\n"); + result = -EINVAL; + goto err; + } + switch (record_header->type) { case RECORD_S3_RESUME: if (subtable_type != SUBTABLE_S3PT) { pr_err(FW_BUG "Invalid record %d for subtable %s\n", record_header->type, signature); - return -EINVAL; + result = -EINVAL; + goto err; } if (record_resume) { pr_err("Duplicate resume performance record found.\n"); @@ -208,7 +215,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_resume = (struct resume_performance_record *)record_header; result = sysfs_create_group(fpdt_kobj, &resume_attr_group); if (result) - return result; + goto err; break; case RECORD_S3_SUSPEND: if (subtable_type != SUBTABLE_S3PT) { @@ -223,13 +230,14 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_suspend = (struct suspend_performance_record *)record_header; result = sysfs_create_group(fpdt_kobj, &suspend_attr_group); if (result) - return result; + goto err; break; case RECORD_BOOT: if (subtable_type != SUBTABLE_FBPT) { pr_err(FW_BUG "Invalid %d for subtable %s\n", record_header->type, signature); - return -EINVAL; + result = -EINVAL; + goto err; } if (record_boot) { pr_err("Duplicate boot performance record found.\n"); @@ -238,7 +246,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_boot = (struct boot_performance_record *)record_header; result = sysfs_create_group(fpdt_kobj, &boot_attr_group); if (result) - return result; + goto err; break; default: @@ -247,6 +255,18 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) } } return 0; + +err: + if (record_boot) + sysfs_remove_group(fpdt_kobj, &boot_attr_group); + + if (record_suspend) + sysfs_remove_group(fpdt_kobj, &suspend_attr_group); + + if (record_resume) + sysfs_remove_group(fpdt_kobj, &resume_attr_group); + + return result; } static int __init acpi_init_fpdt(void) @@ -255,6 +275,7 @@ static int __init acpi_init_fpdt(void) struct acpi_table_header *header; struct fpdt_subtable_entry *subtable; u32 offset = sizeof(*header); + int result; status = acpi_get_table(ACPI_SIG_FPDT, 0, &header); @@ -263,8 +284,8 @@ static int __init acpi_init_fpdt(void) fpdt_kobj = kobject_create_and_add("fpdt", acpi_kobj); if (!fpdt_kobj) { - acpi_put_table(header); - return -ENOMEM; + result = -ENOMEM; + goto err_nomem; } while (offset < header->length) { @@ -272,8 +293,10 @@ static int __init acpi_init_fpdt(void) switch (subtable->type) { case SUBTABLE_FBPT: case SUBTABLE_S3PT: - fpdt_process_subtable(subtable->address, + result = fpdt_process_subtable(subtable->address, subtable->type); + if (result) + goto err_subtable; break; default: /* Other types are reserved in ACPI 6.4 spec. */ @@ -282,6 +305,12 @@ static int __init acpi_init_fpdt(void) offset += sizeof(*subtable); } return 0; +err_subtable: + kobject_put(fpdt_kobj); + +err_nomem: + acpi_put_table(header); + return result; } fs_initcall(acpi_init_fpdt); diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 539e700de4d2..875de44961bf 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -368,7 +368,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) }, - { "INT33C7", }, /* BayTrail LPSS devices */ { "80860F09", LPSS_ADDR(byt_pwm_dev_desc) }, @@ -376,8 +375,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "80860F0E", LPSS_ADDR(byt_spi_dev_desc) }, { "80860F14", LPSS_ADDR(byt_sdio_dev_desc) }, { "80860F41", LPSS_ADDR(byt_i2c_dev_desc) }, - { "INT33B2", }, - { "INT33FC", }, /* Braswell LPSS devices */ { "80862286", LPSS_ADDR(lpss_dma_desc) }, @@ -396,7 +393,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT3434", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT3435", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, - { "INT3437", }, /* Wildcat Point LPSS devices */ { "INT3438", LPSS_ADDR(lpt_spi_dev_desc) }, @@ -578,6 +574,7 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle) { struct acpi_handle_list dep_devices; acpi_status status; + bool ret = false; int i; if (!acpi_has_method(adev->handle, "_DEP")) @@ -591,11 +588,14 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle) } for (i = 0; i < dep_devices.count; i++) { - if (dep_devices.handles[i] == handle) - return true; + if (dep_devices.handles[i] == handle) { + ret = true; + break; + } } - return false; + acpi_handle_list_free(&dep_devices); + return ret; } static void acpi_lpss_link_consumer(struct device *dev1, @@ -657,10 +657,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev, int ret; dev_desc = (const struct lpss_device_desc *)id->driver_data; - if (!dev_desc) { - pdev = acpi_create_platform_device(adev, NULL); - return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1; - } + if (!dev_desc) + return -EINVAL; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 7a453c5ff303..32a2c006908b 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -336,33 +337,14 @@ static ssize_t idlecpus_show(struct device *dev, static DEVICE_ATTR_RW(idlecpus); -static int acpi_pad_add_sysfs(struct acpi_device *device) -{ - int result; +static struct attribute *acpi_pad_attrs[] = { + &dev_attr_idlecpus.attr, + &dev_attr_idlepct.attr, + &dev_attr_rrtime.attr, + NULL +}; - result = device_create_file(&device->dev, &dev_attr_idlecpus); - if (result) - return -ENODEV; - result = device_create_file(&device->dev, &dev_attr_idlepct); - if (result) { - device_remove_file(&device->dev, &dev_attr_idlecpus); - return -ENODEV; - } - result = device_create_file(&device->dev, &dev_attr_rrtime); - if (result) { - device_remove_file(&device->dev, &dev_attr_idlecpus); - device_remove_file(&device->dev, &dev_attr_idlepct); - return -ENODEV; - } - return 0; -} - -static void acpi_pad_remove_sysfs(struct acpi_device *device) -{ - device_remove_file(&device->dev, &dev_attr_idlecpus); - device_remove_file(&device->dev, &dev_attr_idlepct); - device_remove_file(&device->dev, &dev_attr_rrtime); -} +ATTRIBUTE_GROUPS(acpi_pad); /* * Query firmware how many CPUs should be idle @@ -416,13 +398,13 @@ static void acpi_pad_handle_notify(acpi_handle handle) static void acpi_pad_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_device *device = data; + struct acpi_device *adev = data; switch (event) { case ACPI_PROCESSOR_AGGREGATOR_NOTIFY: acpi_pad_handle_notify(handle); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, 0); + acpi_bus_generate_netlink_event(adev->pnp.device_class, + dev_name(&adev->dev), event, 0); break; default: pr_warn("Unsupported event [0x%x]\n", event); @@ -430,35 +412,33 @@ static void acpi_pad_notify(acpi_handle handle, u32 event, } } -static int acpi_pad_add(struct acpi_device *device) +static int acpi_pad_probe(struct platform_device *pdev) { + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); acpi_status status; - strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS); + strcpy(acpi_device_name(adev), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME); + strcpy(acpi_device_class(adev), ACPI_PROCESSOR_AGGREGATOR_CLASS); - if (acpi_pad_add_sysfs(device)) - return -ENODEV; + status = acpi_install_notify_handler(adev->handle, + ACPI_DEVICE_NOTIFY, acpi_pad_notify, adev); - status = acpi_install_notify_handler(device->handle, - ACPI_DEVICE_NOTIFY, acpi_pad_notify, device); - if (ACPI_FAILURE(status)) { - acpi_pad_remove_sysfs(device); + if (ACPI_FAILURE(status)) return -ENODEV; - } return 0; } -static void acpi_pad_remove(struct acpi_device *device) +static void acpi_pad_remove(struct platform_device *pdev) { + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); + mutex_lock(&isolated_cpus_lock); acpi_pad_idle_cpus(0); mutex_unlock(&isolated_cpus_lock); - acpi_remove_notify_handler(device->handle, + acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, acpi_pad_notify); - acpi_pad_remove_sysfs(device); } static const struct acpi_device_id pad_device_ids[] = { @@ -467,13 +447,13 @@ static const struct acpi_device_id pad_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, pad_device_ids); -static struct acpi_driver acpi_pad_driver = { - .name = "processor_aggregator", - .class = ACPI_PROCESSOR_AGGREGATOR_CLASS, - .ids = pad_device_ids, - .ops = { - .add = acpi_pad_add, - .remove = acpi_pad_remove, +static struct platform_driver acpi_pad_driver = { + .probe = acpi_pad_probe, + .remove_new = acpi_pad_remove, + .driver = { + .dev_groups = acpi_pad_groups, + .name = "processor_aggregator", + .acpi_match_table = pad_device_ids, }, }; @@ -487,12 +467,12 @@ static int __init acpi_pad_init(void) if (power_saving_mwait_eax == 0) return -EINVAL; - return acpi_bus_register_driver(&acpi_pad_driver); + return platform_driver_register(&acpi_pad_driver); } static void __exit acpi_pad_exit(void) { - acpi_bus_unregister_driver(&acpi_pad_driver); + platform_driver_unregister(&acpi_pad_driver); } module_init(acpi_pad_init); diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index b411948594ff..0b7a01f38b65 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -2062,7 +2062,7 @@ static int acpi_video_bus_add(struct acpi_device *device) goto err_del; error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, - acpi_video_bus_notify); + acpi_video_bus_notify, device); if (error) goto err_remove; diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 247989060e29..bf65e3461531 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -59,6 +59,10 @@ static struct acpi_table_erst *erst_tab; #define ERST_RANGE_NVRAM 0x0002 #define ERST_RANGE_SLOW 0x0004 +/* ERST Exec max timings */ +#define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000 +#define ERST_EXEC_TIMING_MAX_SHIFT 32 + /* * ERST Error Log Address Range, used as buffer for reading/writing * error records. @@ -68,6 +72,7 @@ static struct erst_erange { u64 size; void __iomem *vaddr; u32 attr; + u64 timings; } erst_erange; /* @@ -97,6 +102,19 @@ static inline int erst_errno(int command_status) } } +static inline u64 erst_get_timeout(void) +{ + u64 timeout = FIRMWARE_TIMEOUT; + + if (erst_erange.attr & ERST_RANGE_SLOW) { + timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >> + ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC; + if (timeout < FIRMWARE_TIMEOUT) + timeout = FIRMWARE_TIMEOUT; + } + return timeout; +} + static int erst_timedout(u64 *t, u64 spin_unit) { if ((s64)*t < spin_unit) { @@ -191,9 +209,11 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx, { int rc; u64 val; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 stall_time; + timeout = erst_get_timeout(); + if (ctx->var1 > FIRMWARE_MAX_STALL) { if (!in_nmi()) pr_warn(FW_WARN @@ -389,6 +409,13 @@ static int erst_get_erange(struct erst_erange *range) if (rc) return rc; range->attr = apei_exec_ctx_get_output(&ctx); + rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_TIMINGS); + if (rc == 0) + range->timings = apei_exec_ctx_get_output(&ctx); + else if (rc == -ENOENT) + range->timings = 0; + else + return rc; return 0; } @@ -621,10 +648,12 @@ EXPORT_SYMBOL_GPL(erst_get_record_id_end); static int __erst_write_to_storage(u64 offset) { struct apei_exec_context ctx; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 val; int rc; + timeout = erst_get_timeout(); + erst_exec_ctx_init(&ctx); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE); if (rc) @@ -660,10 +689,12 @@ static int __erst_write_to_storage(u64 offset) static int __erst_read_from_storage(u64 record_id, u64 offset) { struct apei_exec_context ctx; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 val; int rc; + timeout = erst_get_timeout(); + erst_exec_ctx_init(&ctx); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ); if (rc) @@ -703,10 +734,12 @@ static int __erst_read_from_storage(u64 record_id, u64 offset) static int __erst_clear_from_storage(u64 record_id) { struct apei_exec_context ctx; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 val; int rc; + timeout = erst_get_timeout(); + erst_exec_ctx_init(&ctx); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR); if (rc) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index ef59d6ea16da..63ad0541db38 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -209,6 +209,20 @@ err_pool_alloc: return -ENOMEM; } +/** + * ghes_estatus_pool_region_free - free previously allocated memory + * from the ghes_estatus_pool. + * @addr: address of memory to free. + * @size: size of memory to free. + * + * Returns none. + */ +void ghes_estatus_pool_region_free(unsigned long addr, u32 size) +{ + gen_pool_free(ghes_estatus_pool, addr, size); +} +EXPORT_SYMBOL_GPL(ghes_estatus_pool_region_free); + static int map_gen_v2(struct ghes *ghes) { return apei_map_generic_address(&ghes->generic_v2->read_ack_register); @@ -564,6 +578,7 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata) pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) { unsigned int devfn; int aer_severity; + u8 *aer_info; devfn = PCI_DEVFN(pcie_err->device_id.device, pcie_err->device_id.function); @@ -577,11 +592,17 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata) if (gdata->flags & CPER_SEC_RESET) aer_severity = AER_FATAL; + aer_info = (void *)gen_pool_alloc(ghes_estatus_pool, + sizeof(struct aer_capability_regs)); + if (!aer_info) + return; + memcpy(aer_info, pcie_err->aer_info, sizeof(struct aer_capability_regs)); + aer_recover_queue(pcie_err->device_id.segment, pcie_err->device_id.bus, devfn, aer_severity, (struct aer_capability_regs *) - pcie_err->aer_info); + aer_info); } #endif } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 969bf81e8d54..b379401ff1c2 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1214,7 +1214,7 @@ static int acpi_battery_add(struct acpi_device *device) device_init_wakeup(&device->dev, 1); result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY, - acpi_battery_notify); + acpi_battery_notify, device); if (result) goto fail_pm; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a4aa53b7e2bb..72e64c0718c9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -556,12 +556,12 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device, int acpi_dev_install_notify_handler(struct acpi_device *adev, u32 handler_type, - acpi_notify_handler handler) + acpi_notify_handler handler, void *context) { acpi_status status; status = acpi_install_notify_handler(adev->handle, handler_type, - handler, adev); + handler, context); if (ACPI_FAILURE(status)) return -ENODEV; diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index b9bbf0746199..23373faa35ec 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -158,8 +158,8 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia return 0; len = snprintf(modalias, size, "acpi:"); - if (len <= 0) - return len; + if (len >= size) + return -ENOMEM; size -= len; @@ -168,8 +168,6 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia continue; count = snprintf(&modalias[len], size, "%s:", id->id); - if (count < 0) - return -EINVAL; if (count >= size) return -ENOMEM; @@ -177,7 +175,7 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia len += count; size -= count; } - modalias[len] = '\0'; + return len; } @@ -212,8 +210,10 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); ACPI_FREE(buf.pointer); - if (len <= 0) - return len; + if (len >= size) + return -ENOMEM; + + size -= len; of_compatible = acpi_dev->data.of_compatible; if (of_compatible->type == ACPI_TYPE_PACKAGE) { @@ -226,8 +226,6 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias for (i = 0; i < nval; i++, obj++) { count = snprintf(&modalias[len], size, "C%s", obj->string.pointer); - if (count < 0) - return -EINVAL; if (count >= size) return -ENOMEM; @@ -235,7 +233,7 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias len += count; size -= count; } - modalias[len] = '\0'; + return len; } @@ -410,7 +408,7 @@ static ssize_t uid_show(struct device *dev, { struct acpi_device *acpi_dev = to_acpi_device(dev); - return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id); + return sprintf(buf, "%s\n", acpi_device_uid(acpi_dev)); } static DEVICE_ATTR_RO(uid); @@ -554,7 +552,7 @@ int acpi_device_setup_files(struct acpi_device *dev) if (dev->pnp.type.bus_address) result = device_create_file(&dev->dev, &dev_attr_adr); - if (dev->pnp.unique_id) + if (acpi_device_uid(dev)) result = device_create_file(&dev->dev, &dev_attr_uid); if (acpi_has_method(dev->handle, "_SUN")) { @@ -635,7 +633,7 @@ void acpi_device_remove_files(struct acpi_device *dev) if (acpi_has_method(dev->handle, "_HRV")) device_remove_file(&dev->dev, &dev_attr_hrv); - if (dev->pnp.unique_id) + if (acpi_device_uid(dev)) device_remove_file(&dev->dev, &dev_attr_uid); if (dev->pnp.type.bus_address) device_remove_file(&dev->dev, &dev_attr_adr); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index c95d0edb0be9..a59c11df7375 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1924,6 +1924,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-dk1xxx"), }, }, + { + /* + * HP 250 G7 Notebook PC + */ + .callback = ec_honor_dsdt_gpe, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G7 Notebook PC"), + }, + }, { /* * Samsung hardware diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index 46c6f8c35b43..7652515a6be1 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -57,7 +57,7 @@ static int acpi_hed_add(struct acpi_device *device) hed_handle = device->handle; err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, - acpi_hed_notify); + acpi_hed_notify, device); if (err) hed_handle = NULL; diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 7d88db451cfb..992385537757 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -3340,7 +3340,7 @@ static int acpi_nfit_add(struct acpi_device *adev) int rc = 0; rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY, - acpi_nfit_notify); + acpi_nfit_notify, adev); if (rc) return rc; diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c index d4405e1ca9b9..df9328c850bd 100644 --- a/drivers/acpi/osi.c +++ b/drivers/acpi/osi.c @@ -110,7 +110,7 @@ void __init acpi_osi_setup(char *str) break; } else if (osi->string[0] == '\0') { osi->enable = enable; - strncpy(osi->string, str, OSI_STRING_LENGTH_MAX); + strscpy(osi->string, str, OSI_STRING_LENGTH_MAX); break; } } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f725813d0cce..e154ad0be263 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -149,7 +149,7 @@ void acpi_os_printf(const char *fmt, ...) } EXPORT_SYMBOL(acpi_os_printf); -void acpi_os_vprintf(const char *fmt, va_list args) +void __printf(1, 0) acpi_os_vprintf(const char *fmt, va_list args) { static char buffer[512]; @@ -493,7 +493,7 @@ EXPORT_SYMBOL(acpi_os_unmap_generic_address); #ifdef ACPI_FUTURE_USAGE acpi_status -acpi_os_get_physical_address(void *virt, acpi_physical_address * phys) +acpi_os_get_physical_address(void *virt, acpi_physical_address *phys) { if (!phys || !virt) return AE_BAD_PARAMETER; @@ -784,7 +784,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width) #ifdef CONFIG_PCI acpi_status -acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, +acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, u32 reg, u64 *value, u32 width) { int result, size; @@ -816,7 +816,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, } acpi_status -acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, +acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, u32 reg, u64 value, u32 width) { int result, size; @@ -1067,6 +1067,7 @@ acpi_status acpi_os_execute(acpi_execute_type type, struct acpi_os_dpc *dpc; struct workqueue_struct *queue; int ret; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -1197,7 +1198,7 @@ bool acpi_queue_hotplug_work(struct work_struct *work) } acpi_status -acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) +acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle *handle) { struct semaphore *sem = NULL; @@ -1522,6 +1523,7 @@ acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) __acquires(lockp) { acpi_cpu_flags flags; + spin_lock_irqsave(lockp, flags); return flags; } @@ -1554,7 +1556,7 @@ void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags) ******************************************************************************/ acpi_status -acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) +acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t **cache) { *cache = kmem_cache_create(name, size, 0, 0, NULL); if (*cache == NULL) @@ -1575,10 +1577,10 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) * ******************************************************************************/ -acpi_status acpi_os_purge_cache(acpi_cache_t * cache) +acpi_status acpi_os_purge_cache(acpi_cache_t *cache) { kmem_cache_shrink(cache); - return (AE_OK); + return AE_OK; } /******************************************************************************* @@ -1594,10 +1596,10 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache) * ******************************************************************************/ -acpi_status acpi_os_delete_cache(acpi_cache_t * cache) +acpi_status acpi_os_delete_cache(acpi_cache_t *cache) { kmem_cache_destroy(cache); - return (AE_OK); + return AE_OK; } /******************************************************************************* @@ -1614,10 +1616,10 @@ acpi_status acpi_os_delete_cache(acpi_cache_t * cache) * ******************************************************************************/ -acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) +acpi_status acpi_os_release_object(acpi_cache_t *cache, void *object) { kmem_cache_free(cache, object); - return (AE_OK); + return AE_OK; } #endif @@ -1708,6 +1710,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control) { int rc = 0; + if (__acpi_os_prepare_sleep) rc = __acpi_os_prepare_sleep(sleep_state, pm1a_control, pm1b_control); @@ -1730,6 +1733,7 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, u32 val_b) { int rc = 0; + if (__acpi_os_prepare_extended_sleep) rc = __acpi_os_prepare_extended_sleep(sleep_state, val_a, val_b); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 84030804a763..58b89b8d950e 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -1055,9 +1055,9 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, * exists and returns 0, we must preserve any PCI resource * assignments made by firmware for this host bridge. */ - obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1, - DSM_PCI_PRESERVE_BOOT_CONFIG, NULL); - if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0) + obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1, + DSM_PCI_PRESERVE_BOOT_CONFIG, NULL, ACPI_TYPE_INTEGER); + if (obj && obj->integer.value == 0) host_bridge->preserve_config = 1; ACPI_FREE(obj); diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 7020584096bf..c78453c74ef5 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -69,7 +69,7 @@ struct prm_module_info { bool updatable; struct list_head module_list; - struct prm_handler_info handlers[]; + struct prm_handler_info handlers[] __counted_by(handler_count); }; static u64 efi_pa_va_lookup(u64 pa) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 413e4fcadcaf..6979a3f9f90a 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -55,6 +55,7 @@ static const guid_t ads_guid = GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6, 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b); +/* ACPI _DSD data buffer GUID: edb12dd0-363d-4085-a3d2-49522ca160c4 */ static const guid_t buffer_prop_guid = GUID_INIT(0xedb12dd0, 0x363d, 0x4085, 0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4); @@ -1102,25 +1103,26 @@ static int acpi_data_prop_read(const struct acpi_device_data *data, switch (proptype) { case DEV_PROP_STRING: break; - case DEV_PROP_U8 ... DEV_PROP_U64: + default: if (obj->type == ACPI_TYPE_BUFFER) { if (nval > obj->buffer.length) return -EOVERFLOW; - break; + } else { + if (nval > obj->package.count) + return -EOVERFLOW; } - fallthrough; - default: - if (nval > obj->package.count) - return -EOVERFLOW; break; } if (nval == 0) return -EINVAL; - if (obj->type != ACPI_TYPE_BUFFER) - items = obj->package.elements; - else + if (obj->type == ACPI_TYPE_BUFFER) { + if (proptype != DEV_PROP_U8) + return -EPROTO; items = obj; + } else { + items = obj->package.elements; + } switch (proptype) { case DEV_PROP_U8: diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 297a88587031..15a3bdbd0755 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -385,127 +385,144 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) } EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); -static const struct dmi_system_id medion_laptop[] = { +/* + * DMI matches for boards where the DSDT specifies the kbd IRQ as + * level active-low and using the override changes this to rising edge, + * stopping the keyboard from working. + */ +static const struct dmi_system_id irq1_level_low_skip_override[] = { { - .ident = "MEDION P15651", + /* MEDION P15651 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_BOARD_NAME, "M15T"), }, }, { - .ident = "MEDION S17405", + /* MEDION S17405 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_BOARD_NAME, "M17T"), }, }, { - .ident = "MEDION S17413", + /* MEDION S17413 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_BOARD_NAME, "M1xA"), }, }, - { } -}; - -static const struct dmi_system_id asus_laptop[] = { { - .ident = "Asus Vivobook K3402ZA", + /* Asus Vivobook K3402ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"), }, }, { - .ident = "Asus Vivobook K3502ZA", + /* Asus Vivobook K3502ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"), }, }, { - .ident = "Asus Vivobook S5402ZA", + /* Asus Vivobook S5402ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"), }, }, { - .ident = "Asus Vivobook S5602ZA", + /* Asus Vivobook S5602ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), }, }, { - .ident = "Asus ExpertBook B1402CBA", + /* Asus ExpertBook B1402CBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"), }, }, { - .ident = "Asus ExpertBook B1502CBA", + /* Asus ExpertBook B1502CBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"), }, }, { - .ident = "Asus ExpertBook B2402CBA", + /* Asus ExpertBook B2402CBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"), }, }, { - .ident = "Asus ExpertBook B2402FBA", + /* Asus ExpertBook B2402FBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B2402FBA"), }, }, { - .ident = "Asus ExpertBook B2502", + /* Asus ExpertBook B2502 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"), }, }, - { } -}; - -static const struct dmi_system_id tongfang_gm_rg[] = { { - .ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD", + /* LG Electronics 17U70P */ .matches = { - DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_BOARD_NAME, "17U70P"), }, }, { } }; -static const struct dmi_system_id maingear_laptop[] = { +/* + * DMI matches for AMD Zen boards where the DSDT specifies the kbd IRQ + * as falling edge and this must be overridden to rising edge, + * to have a working keyboard. + */ +static const struct dmi_system_id irq1_edge_low_force_override[] = { { - .ident = "MAINGEAR Vector Pro 2 15", + /* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), + }, + }, + { + /* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"), + }, + }, + { + /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"), + }, + }, + { + /* MAINGEAR Vector Pro 2 15 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"), } }, { - .ident = "MAINGEAR Vector Pro 2 17", + /* MAINGEAR Vector Pro 2 17 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"), }, }, - { } -}; - -static const struct dmi_system_id pcspecialist_laptop[] = { { /* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */ .matches = { @@ -527,17 +544,6 @@ static const struct dmi_system_id pcspecialist_laptop[] = { { } }; -static const struct dmi_system_id lg_laptop[] = { - { - .ident = "LG Electronics 17U70P", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), - DMI_MATCH(DMI_BOARD_NAME, "17U70P"), - }, - }, - { } -}; - struct irq_override_cmp { const struct dmi_system_id *system; unsigned char irq; @@ -548,12 +554,8 @@ struct irq_override_cmp { }; static const struct irq_override_cmp override_table[] = { - { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, - { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, - { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, + { irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, + { irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, }; static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 691d4b7686ee..fa5dd71a80fa 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -289,10 +289,10 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -static int acpi_scan_device_not_present(struct acpi_device *adev) +static int acpi_scan_device_not_enumerated(struct acpi_device *adev) { if (!acpi_device_enumerated(adev)) { - dev_warn(&adev->dev, "Still not present\n"); + dev_warn(&adev->dev, "Still not enumerated\n"); return -EALREADY; } acpi_bus_trim(adev); @@ -304,7 +304,7 @@ static int acpi_scan_device_check(struct acpi_device *adev) int error; acpi_bus_get_status(adev); - if (adev->status.present || adev->status.functional) { + if (acpi_device_is_present(adev)) { /* * This function is only called for device objects for which * matching scan handlers exist. The only situation in which @@ -327,7 +327,7 @@ static int acpi_scan_device_check(struct acpi_device *adev) error = -ENODEV; } } else { - error = acpi_scan_device_not_present(adev); + error = acpi_scan_device_not_enumerated(adev); } return error; } @@ -338,8 +338,8 @@ static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used) int error; acpi_bus_get_status(adev); - if (!(adev->status.present || adev->status.functional)) { - acpi_scan_device_not_present(adev); + if (!acpi_device_is_present(adev)) { + acpi_scan_device_not_enumerated(adev); return 0; } if (handler && handler->hotplug.scan_dependent) @@ -2032,6 +2032,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) mutex_unlock(&acpi_dep_list_lock); } + acpi_handle_list_free(&dep_devices); return count; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index fb9da37a79d8..d98ff69303b3 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -245,7 +245,7 @@ static bool update_trip_devices(struct acpi_thermal *tz, struct acpi_thermal_trip *acpi_trip, int index, bool compare) { - struct acpi_handle_list devices; + struct acpi_handle_list devices = { 0 }; char method[] = "_PSL"; acpi_status status; @@ -255,18 +255,21 @@ static bool update_trip_devices(struct acpi_thermal *tz, method[3] = '0' + index; } - memset(&devices, 0, sizeof(devices)); - status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices); if (ACPI_FAILURE(status)) { acpi_handle_info(tz->device->handle, "%s evaluation failure\n", method); return false; } - if (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices))) + if (acpi_handle_list_equal(&acpi_trip->devices, &devices)) { + acpi_handle_list_free(&devices); + return true; + } + + if (compare) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); - memcpy(&acpi_trip->devices, &devices, sizeof(devices)); + acpi_handle_list_replace(&acpi_trip->devices, &devices); return true; } @@ -808,6 +811,17 @@ static void acpi_thermal_check_fn(struct work_struct *work) mutex_unlock(&tz->thermal_check_lock); } +static void acpi_thermal_free_thermal_zone(struct acpi_thermal *tz) +{ + int i; + + acpi_handle_list_free(&tz->trips.passive.trip.devices); + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + acpi_handle_list_free(&tz->trips.active[i].trip.devices); + + kfree(tz); +} + static int acpi_thermal_add(struct acpi_device *device) { struct acpi_thermal_trip *acpi_trip; @@ -922,7 +936,7 @@ static int acpi_thermal_add(struct acpi_device *device) acpi_device_bid(device), deci_kelvin_to_celsius(tz->temp_dk)); result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, - acpi_thermal_notify); + acpi_thermal_notify, device); if (result) goto flush_wq; @@ -934,7 +948,7 @@ flush_wq: free_trips: kfree(tz->trip_table); free_memory: - kfree(tz); + acpi_thermal_free_thermal_zone(tz); return result; } @@ -954,7 +968,7 @@ static void acpi_thermal_remove(struct acpi_device *device) flush_workqueue(acpi_thermal_pm_queue); acpi_thermal_unregister_thermal_zone(tz); - kfree(tz); + acpi_thermal_free_thermal_zone(tz); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 2ea14648a661..28c75242fca9 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -342,9 +342,8 @@ acpi_evaluate_reference(acpi_handle handle, u32 i = 0; - if (!list) { + if (!list) return AE_BAD_PARAMETER; - } /* Evaluate object. */ @@ -370,7 +369,8 @@ acpi_evaluate_reference(acpi_handle handle, goto end; } - if (package->package.count > ACPI_MAX_HANDLES) { + list->handles = kcalloc(package->package.count, sizeof(*list->handles), GFP_KERNEL); + if (!list->handles) { kfree(package); return AE_NO_MEMORY; } @@ -399,10 +399,11 @@ acpi_evaluate_reference(acpi_handle handle, acpi_handle_debug(list->handles[i], "Found in reference list\n"); } - end: +end: if (ACPI_FAILURE(status)) { list->count = 0; - //kfree(list->handles); + kfree(list->handles); + list->handles = NULL; } kfree(buffer.pointer); @@ -412,6 +413,61 @@ acpi_evaluate_reference(acpi_handle handle, EXPORT_SYMBOL(acpi_evaluate_reference); +/** + * acpi_handle_list_equal - Check if two ACPI handle lists are the same + * @list1: First list to compare. + * @list2: Second list to compare. + * + * Return true if the given ACPI handle lists are of the same size and + * contain the same ACPI handles in the same order. Otherwise, return false. + */ +bool acpi_handle_list_equal(struct acpi_handle_list *list1, + struct acpi_handle_list *list2) +{ + return list1->count == list2->count && + !memcmp(list1->handles, list2->handles, + list1->count * sizeof(acpi_handle)); +} +EXPORT_SYMBOL_GPL(acpi_handle_list_equal); + +/** + * acpi_handle_list_replace - Replace one ACPI handle list with another + * @dst: ACPI handle list to replace. + * @src: Source ACPI handle list. + * + * Free the handles table in @dst, move the handles table from @src to @dst, + * copy count from @src to @dst and clear @src. + */ +void acpi_handle_list_replace(struct acpi_handle_list *dst, + struct acpi_handle_list *src) +{ + if (dst->count) + kfree(dst->handles); + + dst->count = src->count; + dst->handles = src->handles; + + src->handles = NULL; + src->count = 0; +} +EXPORT_SYMBOL_GPL(acpi_handle_list_replace); + +/** + * acpi_handle_list_free - Free the handles table in an ACPI handle list + * @list: ACPI handle list to free. + * + * Free the handles table in @list and clear its count field. + */ +void acpi_handle_list_free(struct acpi_handle_list *list) +{ + if (!list->count) + return; + + kfree(list->handles); + list->count = 0; +} +EXPORT_SYMBOL_GPL(acpi_handle_list_free); + acpi_status acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld) { @@ -523,7 +579,7 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) vaf.va = &args; path = acpi_handle_path(handle); - printk("%sACPI: %s: %pV", level, path ? path : "" , &vaf); + printk("%sACPI: %s: %pV", level, path ? path : "", &vaf); va_end(args); kfree(path); @@ -768,20 +824,43 @@ bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs) } EXPORT_SYMBOL(acpi_check_dsm); +/** + * acpi_dev_uid_match - Match device by supplied UID + * @adev: ACPI device to match. + * @uid2: Unique ID of the device. + * + * Matches UID in @adev with given @uid2. + * + * Returns: + * - %true if matches. + * - %false otherwise. + */ +bool acpi_dev_uid_match(struct acpi_device *adev, const char *uid2) +{ + const char *uid1 = acpi_device_uid(adev); + + return uid1 && uid2 && !strcmp(uid1, uid2); +} +EXPORT_SYMBOL_GPL(acpi_dev_uid_match); + /** * acpi_dev_hid_uid_match - Match device by supplied HID and UID * @adev: ACPI device to match. * @hid2: Hardware ID of the device. * @uid2: Unique ID of the device, pass NULL to not check _UID. * - * Matches HID and UID in @adev with given @hid2 and @uid2. - * Returns true if matches. + * Matches HID and UID in @adev with given @hid2 and @uid2. Absence of @uid2 + * will be treated as a match. If user wants to validate @uid2, it should be + * done before calling this function. + * + * Returns: + * - %true if matches or @uid2 is NULL. + * - %false otherwise. */ bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2) { const char *hid1 = acpi_device_hid(adev); - const char *uid1 = acpi_device_uid(adev); if (strcmp(hid1, hid2)) return false; @@ -789,7 +868,7 @@ bool acpi_dev_hid_uid_match(struct acpi_device *adev, if (!uid2) return true; - return uid1 && !strcmp(uid1, uid2); + return acpi_dev_uid_match(adev, uid2); } EXPORT_SYMBOL(acpi_dev_hid_uid_match); @@ -863,8 +942,7 @@ static int acpi_dev_match_cb(struct device *dev, const void *data) if (acpi_match_device_ids(adev, match->hid)) return 0; - if (match->uid && (!adev->pnp.unique_id || - strcmp(adev->pnp.unique_id, match->uid))) + if (match->uid && !acpi_dev_uid_match(adev, match->uid)) return 0; if (match->hrv == -1) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 442396f6ed1f..9fdcc620c652 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -130,6 +130,16 @@ static int video_detect_force_native(const struct dmi_system_id *d) return 0; } +static int video_detect_portege_r100(const struct dmi_system_id *d) +{ + struct pci_dev *dev; + /* Search for Trident CyberBlade XP4m32 to confirm Portégé R100 */ + dev = pci_get_device(PCI_VENDOR_ID_TRIDENT, 0x2100, NULL); + if (dev) + acpi_backlight_dmi = acpi_backlight_vendor; + return 0; +} + static const struct dmi_system_id video_detect_dmi_table[] = { /* * Models which should use the vendor backlight interface, @@ -229,14 +239,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), }, }, - { - .callback = video_detect_force_vendor, - /* Xiaomi Mi Pad 2 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), - }, - }, /* * Models which should use the vendor backlight interface, @@ -270,6 +272,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, + /* + * Toshiba Portégé R100 has working both acpi_video and toshiba_acpi + * vendor driver. But none of them gets activated as it has a VGA with + * no kernel driver (Trident CyberBlade XP4m32). + * The DMI strings are generic so check for the VGA chip in callback. + */ + { + .callback = video_detect_portege_r100, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"), + DMI_MATCH(DMI_BOARD_NAME, "Portable PC") + }, + }, + /* * Models which need acpi_video backlight control where the GPU drivers * do not call acpi_video_register_backlight() because no internal panel @@ -799,6 +817,56 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"), }, }, + + /* + * x86 android tablets which directly control the backlight through + * an external backlight controller, typically TI's LP8557. + * The backlight is directly controlled by the lp855x driver on these. + * This setup means that neither i915's native nor acpi_video backlight + * control works. Add a "vendor" quirk to disable both. Note these + * devices do not use vendor control in the typical meaning of + * vendor specific SMBIOS or ACPI calls being used. + */ + { + .callback = video_detect_force_vendor, + /* Lenovo Yoga Book X90F / X90L */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), + }, + }, + { + .callback = video_detect_force_vendor, + /* + * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10" + * Lenovo Yoga Tablet 2 use the same mainboard) + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), + DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"), + DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"), + /* Partial match on beginning of BIOS version */ + DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), + }, + }, + { + .callback = video_detect_force_vendor, + /* Lenovo Yoga Tab 3 Pro YT3-X90F */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"), + }, + }, + { + .callback = video_detect_force_vendor, + /* Xiaomi Mi Pad 2 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), + DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), + }, + }, { }, }; diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index 08f7c6708206..7d64e655f1b8 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -417,11 +417,10 @@ static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *d int ret = -EINVAL; guid_parse(uuid, dsm_guid); - obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL); /* Check if the _DSM is present and as expected. */ - if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 || - obj->buffer.length > sizeof(u32)) { + obj = acpi_evaluate_dsm_typed(handle, dsm_guid, rev, 0, NULL, ACPI_TYPE_BUFFER); + if (!obj || obj->buffer.length == 0 || obj->buffer.length > sizeof(u32)) { acpi_handle_debug(handle, "_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev); goto out; diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 63d834dd3811..bc65ebfcdf76 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -184,8 +184,7 @@ bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *s if (acpi_match_device_ids(adev, override_status_ids[i].hid)) continue; - if (!adev->pnp.unique_id || - strcmp(adev->pnp.unique_id, override_status_ids[i].uid)) + if (!acpi_dev_uid_match(adev, override_status_ids[i].uid)) continue; } diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index 72115917e0bd..44ec20918a4d 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -228,3 +228,24 @@ void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd) device_pm_check_callbacks(dev); } EXPORT_SYMBOL_GPL(dev_pm_domain_set); + +/** + * dev_pm_domain_set_performance_state - Request a new performance state. + * @dev: The device to make the request for. + * @state: Target performance state for the device. + * + * This function should be called when a new performance state needs to be + * requested for a device that is attached to a PM domain. Note that, the + * support for performance scaling for PM domains is optional. + * + * Returns 0 on success and when performance scaling isn't supported, negative + * error code on failure. + */ +int dev_pm_domain_set_performance_state(struct device *dev, unsigned int state) +{ + if (dev->pm_domain && dev->pm_domain->set_performance_state) + return dev->pm_domain->set_performance_state(dev, state); + + return 0; +} +EXPORT_SYMBOL_GPL(dev_pm_domain_set_performance_state); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 5cb2023581d4..e38fc140d113 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -419,6 +419,25 @@ static void genpd_restore_performance_state(struct device *dev, genpd_set_performance_state(dev, state); } +static int genpd_dev_pm_set_performance_state(struct device *dev, + unsigned int state) +{ + struct generic_pm_domain *genpd = dev_to_genpd(dev); + int ret = 0; + + genpd_lock(genpd); + if (pm_runtime_suspended(dev)) { + dev_gpd_data(dev)->rpm_pstate = state; + } else { + ret = genpd_set_performance_state(dev, state); + if (!ret) + dev_gpd_data(dev)->rpm_pstate = 0; + } + genpd_unlock(genpd); + + return ret; +} + /** * dev_pm_genpd_set_performance_state- Set performance state of device's power * domain. @@ -437,7 +456,6 @@ static void genpd_restore_performance_state(struct device *dev, int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) { struct generic_pm_domain *genpd; - int ret = 0; genpd = dev_to_genpd_safe(dev); if (!genpd) @@ -447,17 +465,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) !dev->power.subsys_data->domain_data)) return -EINVAL; - genpd_lock(genpd); - if (pm_runtime_suspended(dev)) { - dev_gpd_data(dev)->rpm_pstate = state; - } else { - ret = genpd_set_performance_state(dev, state); - if (!ret) - dev_gpd_data(dev)->rpm_pstate = 0; - } - genpd_unlock(genpd); - - return ret; + return genpd_dev_pm_set_performance_state(dev, state); } EXPORT_SYMBOL_GPL(dev_pm_genpd_set_performance_state); @@ -2079,6 +2087,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd, genpd->domain.ops.restore_noirq = genpd_restore_noirq; genpd->domain.ops.complete = genpd_complete; genpd->domain.start = genpd_dev_pm_start; + genpd->domain.set_performance_state = genpd_dev_pm_set_performance_state; if (genpd->flags & GENPD_FLAG_PM_CLK) { genpd->dev_ops.stop = pm_clk_suspend; diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index c5d151e9c481..92592f944a3d 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -334,6 +334,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min, return 0; } +static int rbtree_all(const void *key, const struct rb_node *node) +{ + return 0; +} + /** * regcache_sync - Sync the register cache with the hardware. * @@ -351,6 +356,7 @@ int regcache_sync(struct regmap *map) unsigned int i; const char *name; bool bypass; + struct rb_node *node; if (WARN_ON(map->cache_type == REGCACHE_NONE)) return -EINVAL; @@ -392,6 +398,30 @@ out: /* Restore the bypass state */ map->cache_bypass = bypass; map->no_sync_defaults = false; + + /* + * If we did any paging with cache bypassed and a cached + * paging register then the register and cache state might + * have gone out of sync, force writes of all the paging + * registers. + */ + rb_for_each(node, 0, &map->range_tree, rbtree_all) { + struct regmap_range_node *this = + rb_entry(node, struct regmap_range_node, node); + + /* If there's nothing in the cache there's nothing to sync */ + ret = regcache_read(map, this->selector_reg, &i); + if (ret != 0) + continue; + + ret = _regmap_write(map, this->selector_reg, i); + if (ret != 0) { + dev_err(map->dev, "Failed to write %x = %x: %d\n", + this->selector_reg, i, ret); + break; + } + } + map->unlock(map->lock_arg); regmap_async_complete(map); diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index f36027591e1a..bdd80b73c3e6 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -48,7 +48,7 @@ static ssize_t regmap_name_read_file(struct file *file, name = map->dev->driver->name; ret = snprintf(buf, PAGE_SIZE, "%s\n", name); - if (ret < 0) { + if (ret >= PAGE_SIZE) { kfree(buf); return ret; } diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c index 264d29b3fced..e14cc03a17f6 100644 --- a/drivers/base/regmap/regmap-kunit.c +++ b/drivers/base/regmap/regmap-kunit.c @@ -442,10 +442,18 @@ static struct regmap_range_cfg test_range = { .range_max = 40, }; -static bool test_range_volatile(struct device *dev, unsigned int reg) +static bool test_range_window_volatile(struct device *dev, unsigned int reg) { if (reg >= test_range.window_start && - reg <= test_range.selector_reg + test_range.window_len) + reg <= test_range.window_start + test_range.window_len) + return true; + + return false; +} + +static bool test_range_all_volatile(struct device *dev, unsigned int reg) +{ + if (test_range_window_volatile(dev, reg)) return true; if (reg >= test_range.range_min && reg <= test_range.range_max) @@ -465,7 +473,7 @@ static void basic_ranges(struct kunit *test) config = test_regmap_config; config.cache_type = t->type; - config.volatile_reg = test_range_volatile; + config.volatile_reg = test_range_all_volatile; config.ranges = &test_range; config.num_ranges = 1; config.max_register = test_range.range_max; @@ -875,6 +883,59 @@ static void cache_present(struct kunit *test) regmap_exit(map); } +/* Check that caching the window register works with sync */ +static void cache_range_window_reg(struct kunit *test) +{ + struct regcache_types *t = (struct regcache_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + config.cache_type = t->type; + config.volatile_reg = test_range_window_volatile; + config.ranges = &test_range; + config.num_ranges = 1; + config.max_register = test_range.range_max; + + map = gen_regmap(&config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + /* Write new values to the entire range */ + for (i = test_range.range_min; i <= test_range.range_max; i++) + KUNIT_ASSERT_EQ(test, 0, regmap_write(map, i, 0)); + + val = data->vals[test_range.selector_reg] & test_range.selector_mask; + KUNIT_ASSERT_EQ(test, val, 2); + + /* Write to the first register in the range to reset the page */ + KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0)); + val = data->vals[test_range.selector_reg] & test_range.selector_mask; + KUNIT_ASSERT_EQ(test, val, 0); + + /* Trigger a cache sync */ + regcache_mark_dirty(map); + KUNIT_ASSERT_EQ(test, 0, regcache_sync(map)); + + /* Write to the first register again, the page should be reset */ + KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0)); + val = data->vals[test_range.selector_reg] & test_range.selector_mask; + KUNIT_ASSERT_EQ(test, val, 0); + + /* Trigger another cache sync */ + regcache_mark_dirty(map); + KUNIT_ASSERT_EQ(test, 0, regcache_sync(map)); + + /* Write to the last register again, the page should be reset */ + KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_max, 0)); + val = data->vals[test_range.selector_reg] & test_range.selector_mask; + KUNIT_ASSERT_EQ(test, val, 2); +} + struct raw_test_types { const char *name; @@ -1217,6 +1278,7 @@ static struct kunit_case regmap_test_cases[] = { KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params), KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params), + KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_gen_params), KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params), KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params), diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 123b4bbfcfee..f911606897b8 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -90,7 +90,7 @@ config ARM_VEXPRESS_SPC_CPUFREQ config ARM_BRCMSTB_AVS_CPUFREQ tristate "Broadcom STB AVS CPUfreq driver" - depends on ARCH_BRCMSTB || COMPILE_TEST + depends on (ARCH_BRCMSTB && !ARM_SCMI_CPUFREQ) || COMPILE_TEST default y help Some Broadcom STB SoCs use a co-processor running proprietary firmware @@ -124,8 +124,8 @@ config ARM_IMX_CPUFREQ_DT tristate "Freescale i.MX8M cpufreq support" depends on ARCH_MXC && CPUFREQ_DT help - This adds cpufreq driver support for Freescale i.MX8M series SoCs, - based on cpufreq-dt. + This adds cpufreq driver support for Freescale i.MX7/i.MX8M + series SoCs, based on cpufreq-dt. If in doubt, say N. diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index fb2875ce1fdd..11b3e34b7696 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -142,9 +142,11 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "nvidia,tegra234", }, { .compatible = "qcom,apq8096", }, + { .compatible = "qcom,msm8909", }, { .compatible = "qcom,msm8996", }, { .compatible = "qcom,msm8998", }, { .compatible = "qcom,qcm2290", }, + { .compatible = "qcom,qcm6490", }, { .compatible = "qcom,qcs404", }, { .compatible = "qcom,qdu1000", }, { .compatible = "qcom,sa8155p" }, @@ -176,7 +178,9 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "ti,omap3", }, { .compatible = "ti,am625", }, { .compatible = "ti,am62a7", }, + { .compatible = "ti,am62p5", }, + { .compatible = "qcom,ipq6018", }, { .compatible = "qcom,ipq8064", }, { .compatible = "qcom,apq8064", }, { .compatible = "qcom,msm8974", }, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e40af67d8b08..f48eb297e39d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1555,7 +1555,7 @@ static int cpufreq_online(unsigned int cpu) /* * Register with the energy model before - * sched_cpufreq_governor_change() is called, which will result + * sugov_eas_rebuild_sd() is called, which will result * in rebuilding of the sched domains, which should only be done * once the energy model is properly initialized for the policy * first. diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index b6bd0ff35323..56500b25d77c 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -187,8 +187,7 @@ static ssize_t down_threshold_store(struct gov_attr_set *attr_set, ret = sscanf(buf, "%u", &input); /* cannot be lower than 1 otherwise freq will not fall */ - if (ret != 1 || input < 1 || input > 100 || - input >= dbs_data->up_threshold) + if (ret != 1 || input < 1 || input >= dbs_data->up_threshold) return -EINVAL; cs_tuners->down_threshold = input; diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index a33df3c66c88..40a9ff18da06 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -131,23 +131,23 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) len += sysfs_emit_at(buf, len, " From : To\n"); len += sysfs_emit_at(buf, len, " : "); for (i = 0; i < stats->state_num; i++) { - if (len >= PAGE_SIZE) + if (len >= PAGE_SIZE - 1) break; len += sysfs_emit_at(buf, len, "%9u ", stats->freq_table[i]); } - if (len >= PAGE_SIZE) - return PAGE_SIZE; + if (len >= PAGE_SIZE - 1) + return PAGE_SIZE - 1; len += sysfs_emit_at(buf, len, "\n"); for (i = 0; i < stats->state_num; i++) { - if (len >= PAGE_SIZE) + if (len >= PAGE_SIZE - 1) break; len += sysfs_emit_at(buf, len, "%9u: ", stats->freq_table[i]); for (j = 0; j < stats->state_num; j++) { - if (len >= PAGE_SIZE) + if (len >= PAGE_SIZE - 1) break; if (pending) @@ -157,12 +157,12 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) len += sysfs_emit_at(buf, len, "%9u ", count); } - if (len >= PAGE_SIZE) + if (len >= PAGE_SIZE - 1) break; len += sysfs_emit_at(buf, len, "\n"); } - if (len >= PAGE_SIZE) { + if (len >= PAGE_SIZE - 1) { pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n"); return -EFBIG; } diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 50a4d7846580..2c42fee76daa 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -15,8 +15,11 @@ #include #include -static DEFINE_PER_CPU(unsigned int, cpu_is_managed); -static DEFINE_MUTEX(userspace_mutex); +struct userspace_policy { + unsigned int is_managed; + unsigned int setspeed; + struct mutex mutex; +}; /** * cpufreq_set - set the CPU frequency @@ -28,19 +31,19 @@ static DEFINE_MUTEX(userspace_mutex); static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) { int ret = -EINVAL; - unsigned int *setspeed = policy->governor_data; + struct userspace_policy *userspace = policy->governor_data; pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq); - mutex_lock(&userspace_mutex); - if (!per_cpu(cpu_is_managed, policy->cpu)) + mutex_lock(&userspace->mutex); + if (!userspace->is_managed) goto err; - *setspeed = freq; + userspace->setspeed = freq; ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); err: - mutex_unlock(&userspace_mutex); + mutex_unlock(&userspace->mutex); return ret; } @@ -51,67 +54,74 @@ static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy) { - unsigned int *setspeed; + struct userspace_policy *userspace; - setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL); - if (!setspeed) + userspace = kzalloc(sizeof(*userspace), GFP_KERNEL); + if (!userspace) return -ENOMEM; - policy->governor_data = setspeed; + mutex_init(&userspace->mutex); + + policy->governor_data = userspace; return 0; } +/* + * Any routine that writes to the policy struct will hold the "rwsem" of + * policy struct that means it is free to free "governor_data" here. + */ static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy) { - mutex_lock(&userspace_mutex); kfree(policy->governor_data); policy->governor_data = NULL; - mutex_unlock(&userspace_mutex); } static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy) { - unsigned int *setspeed = policy->governor_data; + struct userspace_policy *userspace = policy->governor_data; BUG_ON(!policy->cur); pr_debug("started managing cpu %u\n", policy->cpu); - mutex_lock(&userspace_mutex); - per_cpu(cpu_is_managed, policy->cpu) = 1; - *setspeed = policy->cur; - mutex_unlock(&userspace_mutex); + mutex_lock(&userspace->mutex); + userspace->is_managed = 1; + userspace->setspeed = policy->cur; + mutex_unlock(&userspace->mutex); return 0; } static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy) { - unsigned int *setspeed = policy->governor_data; + struct userspace_policy *userspace = policy->governor_data; pr_debug("managing cpu %u stopped\n", policy->cpu); - mutex_lock(&userspace_mutex); - per_cpu(cpu_is_managed, policy->cpu) = 0; - *setspeed = 0; - mutex_unlock(&userspace_mutex); + mutex_lock(&userspace->mutex); + userspace->is_managed = 0; + userspace->setspeed = 0; + mutex_unlock(&userspace->mutex); } static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy) { - unsigned int *setspeed = policy->governor_data; + struct userspace_policy *userspace = policy->governor_data; - mutex_lock(&userspace_mutex); + mutex_lock(&userspace->mutex); pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", - policy->cpu, policy->min, policy->max, policy->cur, *setspeed); + policy->cpu, policy->min, policy->max, policy->cur, userspace->setspeed); - if (policy->max < *setspeed) - __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - else if (policy->min > *setspeed) - __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); + if (policy->max < userspace->setspeed) + __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); + else if (policy->min > userspace->setspeed) + __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); else - __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, userspace->setspeed, + CPUFREQ_RELATION_L); - mutex_unlock(&userspace_mutex); + mutex_unlock(&userspace->mutex); } static struct cpufreq_governor cpufreq_gov_userspace = { diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index dc50c9fb488d..a534a1f7f1ee 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -571,13 +571,9 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) static inline void update_turbo_state(void) { u64 misc_en; - struct cpudata *cpu; - cpu = all_cpu_data[0]; rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); - global.turbo_disabled = - (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || - cpu->pstate.max_pstate == cpu->pstate.turbo_pstate); + global.turbo_disabled = misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE; } static int min_perf_pct_min(void) diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index ec75e79659ac..df3567c1e93b 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -378,10 +379,9 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) static u32 read_gpio(struct device_node *np) { - const u32 *reg = of_get_property(np, "reg", NULL); - u32 offset; + u64 offset; - if (reg == NULL) + if (of_property_read_reg(np, 0, &offset, NULL) < 0) return 0; /* That works for all keylargos but shall be fixed properly * some day... The problem is that it seems we can't rely @@ -389,7 +389,6 @@ static u32 read_gpio(struct device_node *np) * relative to the base of KeyLargo or to the base of the * GPIO space, and the device-tree doesn't help. */ - offset = *reg; if (offset < KEYLARGO_GPIO_LEVELS0) offset += KEYLARGO_GPIO_LEVELS0; return offset; diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c index 84d7033e5efe..15367ac08b2b 100644 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c @@ -30,6 +30,14 @@ #include +enum ipq806x_versions { + IPQ8062_VERSION = 0, + IPQ8064_VERSION, + IPQ8065_VERSION, +}; + +#define IPQ6000_VERSION BIT(2) + struct qcom_cpufreq_drv; struct qcom_cpufreq_match_data { @@ -40,16 +48,38 @@ struct qcom_cpufreq_match_data { const char **genpd_names; }; +struct qcom_cpufreq_drv_cpu { + int opp_token; +}; + struct qcom_cpufreq_drv { - int *opp_tokens; u32 versions; const struct qcom_cpufreq_match_data *data; + struct qcom_cpufreq_drv_cpu cpus[]; }; static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; +static int qcom_cpufreq_simple_get_version(struct device *cpu_dev, + struct nvmem_cell *speedbin_nvmem, + char **pvs_name, + struct qcom_cpufreq_drv *drv) +{ + u8 *speedbin; + + *pvs_name = NULL; + speedbin = nvmem_cell_read(speedbin_nvmem, NULL); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + + dev_dbg(cpu_dev, "speedbin: %d\n", *speedbin); + drv->versions = 1 << *speedbin; + kfree(speedbin); + return 0; +} + static void get_krait_bin_format_a(struct device *cpu_dev, - int *speed, int *pvs, int *pvs_ver, + int *speed, int *pvs, u8 *buf) { u32 pte_efuse; @@ -180,8 +210,7 @@ static int qcom_cpufreq_krait_name_version(struct device *cpu_dev, switch (len) { case 4: - get_krait_bin_format_a(cpu_dev, &speed, &pvs, &pvs_ver, - speedbin); + get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin); break; case 8: get_krait_bin_format_b(cpu_dev, &speed, &pvs, &pvs_ver, @@ -203,6 +232,114 @@ len_error: return ret; } +static int qcom_cpufreq_ipq8064_name_version(struct device *cpu_dev, + struct nvmem_cell *speedbin_nvmem, + char **pvs_name, + struct qcom_cpufreq_drv *drv) +{ + int speed = 0, pvs = 0; + int msm_id, ret = 0; + u8 *speedbin; + size_t len; + + speedbin = nvmem_cell_read(speedbin_nvmem, &len); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + + if (len != 4) { + dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n"); + ret = -ENODEV; + goto exit; + } + + get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin); + + ret = qcom_smem_get_soc_id(&msm_id); + if (ret) + goto exit; + + switch (msm_id) { + case QCOM_ID_IPQ8062: + drv->versions = BIT(IPQ8062_VERSION); + break; + case QCOM_ID_IPQ8064: + case QCOM_ID_IPQ8066: + case QCOM_ID_IPQ8068: + drv->versions = BIT(IPQ8064_VERSION); + break; + case QCOM_ID_IPQ8065: + case QCOM_ID_IPQ8069: + drv->versions = BIT(IPQ8065_VERSION); + break; + default: + dev_err(cpu_dev, + "SoC ID %u is not part of IPQ8064 family, limiting to 1.0GHz!\n", + msm_id); + drv->versions = BIT(IPQ8062_VERSION); + break; + } + + /* IPQ8064 speed is never fused. Only pvs values are fused. */ + snprintf(*pvs_name, sizeof("speed0-pvsXX"), "speed0-pvs%d", pvs); + +exit: + kfree(speedbin); + return ret; +} + +static int qcom_cpufreq_ipq6018_name_version(struct device *cpu_dev, + struct nvmem_cell *speedbin_nvmem, + char **pvs_name, + struct qcom_cpufreq_drv *drv) +{ + u32 msm_id; + int ret; + u8 *speedbin; + *pvs_name = NULL; + + ret = qcom_smem_get_soc_id(&msm_id); + if (ret) + return ret; + + speedbin = nvmem_cell_read(speedbin_nvmem, NULL); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + + switch (msm_id) { + case QCOM_ID_IPQ6005: + case QCOM_ID_IPQ6010: + case QCOM_ID_IPQ6018: + case QCOM_ID_IPQ6028: + /* Fuse Value Freq BIT to set + * --------------------------------- + * 2’b0 No Limit BIT(0) + * 2’b1 1.5 GHz BIT(1) + */ + drv->versions = 1 << (unsigned int)(*speedbin); + break; + case QCOM_ID_IPQ6000: + /* + * IPQ6018 family only has one bit to advertise the CPU + * speed-bin, but that is not enough for IPQ6000 which + * is only rated up to 1.2GHz. + * So for IPQ6000 manually set BIT(2) based on SMEM ID. + */ + drv->versions = IPQ6000_VERSION; + break; + default: + dev_err(cpu_dev, + "SoC ID %u is not part of IPQ6018 family, limiting to 1.2GHz!\n", + msm_id); + drv->versions = IPQ6000_VERSION; + break; + } + + kfree(speedbin); + return 0; +} + +static const char *generic_genpd_names[] = { "perf", NULL }; + static const struct qcom_cpufreq_match_data match_data_kryo = { .get_version = qcom_cpufreq_kryo_name_version, }; @@ -211,12 +348,25 @@ static const struct qcom_cpufreq_match_data match_data_krait = { .get_version = qcom_cpufreq_krait_name_version, }; +static const struct qcom_cpufreq_match_data match_data_msm8909 = { + .get_version = qcom_cpufreq_simple_get_version, + .genpd_names = generic_genpd_names, +}; + static const char *qcs404_genpd_names[] = { "cpr", NULL }; static const struct qcom_cpufreq_match_data match_data_qcs404 = { .genpd_names = qcs404_genpd_names, }; +static const struct qcom_cpufreq_match_data match_data_ipq6018 = { + .get_version = qcom_cpufreq_ipq6018_name_version, +}; + +static const struct qcom_cpufreq_match_data match_data_ipq8064 = { + .get_version = qcom_cpufreq_ipq8064_name_version, +}; + static int qcom_cpufreq_probe(struct platform_device *pdev) { struct qcom_cpufreq_drv *drv; @@ -237,48 +387,39 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) if (!np) return -ENOENT; - ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); + ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu") || + of_device_is_compatible(np, "operating-points-v2-krait-cpu"); if (!ret) { of_node_put(np); return -ENOENT; } - drv = kzalloc(sizeof(*drv), GFP_KERNEL); + drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()), + GFP_KERNEL); if (!drv) return -ENOMEM; match = pdev->dev.platform_data; drv->data = match->data; - if (!drv->data) { - ret = -ENODEV; - goto free_drv; - } + if (!drv->data) + return -ENODEV; if (drv->data->get_version) { speedbin_nvmem = of_nvmem_cell_get(np, NULL); - if (IS_ERR(speedbin_nvmem)) { - ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), - "Could not get nvmem cell\n"); - goto free_drv; - } + if (IS_ERR(speedbin_nvmem)) + return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), + "Could not get nvmem cell\n"); ret = drv->data->get_version(cpu_dev, speedbin_nvmem, &pvs_name, drv); if (ret) { nvmem_cell_put(speedbin_nvmem); - goto free_drv; + return ret; } nvmem_cell_put(speedbin_nvmem); } of_node_put(np); - drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens), - GFP_KERNEL); - if (!drv->opp_tokens) { - ret = -ENOMEM; - goto free_drv; - } - for_each_possible_cpu(cpu) { struct dev_pm_opp_config config = { .supported_hw = NULL, @@ -304,9 +445,9 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) } if (config.supported_hw || config.genpd_names) { - drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config); - if (drv->opp_tokens[cpu] < 0) { - ret = drv->opp_tokens[cpu]; + drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config); + if (drv->cpus[cpu].opp_token < 0) { + ret = drv->cpus[cpu].opp_token; dev_err(cpu_dev, "Failed to set OPP config\n"); goto free_opp; } @@ -325,11 +466,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) free_opp: for_each_possible_cpu(cpu) - dev_pm_opp_clear_config(drv->opp_tokens[cpu]); - kfree(drv->opp_tokens); -free_drv: - kfree(drv); - + dev_pm_opp_clear_config(drv->cpus[cpu].opp_token); return ret; } @@ -341,10 +478,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev) platform_device_unregister(cpufreq_dt_pdev); for_each_possible_cpu(cpu) - dev_pm_opp_clear_config(drv->opp_tokens[cpu]); - - kfree(drv->opp_tokens); - kfree(drv); + dev_pm_opp_clear_config(drv->cpus[cpu].opp_token); } static struct platform_driver qcom_cpufreq_driver = { @@ -357,9 +491,11 @@ static struct platform_driver qcom_cpufreq_driver = { static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { { .compatible = "qcom,apq8096", .data = &match_data_kryo }, + { .compatible = "qcom,msm8909", .data = &match_data_msm8909 }, { .compatible = "qcom,msm8996", .data = &match_data_kryo }, { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, - { .compatible = "qcom,ipq8064", .data = &match_data_krait }, + { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 }, + { .compatible = "qcom,ipq8064", .data = &match_data_ipq8064 }, { .compatible = "qcom,apq8064", .data = &match_data_krait }, { .compatible = "qcom,msm8974", .data = &match_data_krait }, { .compatible = "qcom,msm8960", .data = &match_data_krait }, diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c index 88ef5e57ccd0..59865ea455a8 100644 --- a/drivers/cpufreq/tegra194-cpufreq.c +++ b/drivers/cpufreq/tegra194-cpufreq.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -21,10 +20,11 @@ #define KHZ 1000 #define REF_CLK_MHZ 408 /* 408 MHz */ -#define US_DELAY 500 #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ) #define MAX_CNT ~0U +#define MAX_DELTA_KHZ 115200 + #define NDIV_MASK 0x1FF #define CORE_OFFSET(cpu) (cpu * 8) @@ -39,6 +39,12 @@ /* cpufreq transisition latency */ #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */ +struct tegra_cpu_data { + u32 cpuid; + u32 clusterid; + void __iomem *freq_core_reg; +}; + struct tegra_cpu_ctr { u32 cpu; u32 coreclk_cnt, last_coreclk_cnt; @@ -62,6 +68,7 @@ struct tegra_cpufreq_soc { int maxcpus_per_cluster; unsigned int num_clusters; phys_addr_t actmon_cntr_base; + u32 refclk_delta_min; }; struct tegra194_cpufreq_data { @@ -69,6 +76,7 @@ struct tegra194_cpufreq_data { struct cpufreq_frequency_table **bpmp_luts; const struct tegra_cpufreq_soc *soc; bool icc_dram_bw_scaling; + struct tegra_cpu_data *cpu_data; }; static struct workqueue_struct *read_counters_wq; @@ -116,14 +124,8 @@ static void tegra234_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid) static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); - void __iomem *freq_core_reg; - u64 mpidr_id; - /* use physical id to get address of per core frequency register */ - mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; - freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); - - *ndiv = readl(freq_core_reg) & NDIV_MASK; + *ndiv = readl(data->cpu_data[cpu].freq_core_reg) & NDIV_MASK; return 0; } @@ -131,19 +133,10 @@ static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv) static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); - void __iomem *freq_core_reg; - u32 cpu, cpuid, clusterid; - u64 mpidr_id; + u32 cpu; - for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) { - data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); - - /* use physical id to get address of per core frequency register */ - mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; - freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); - - writel(ndiv, freq_core_reg); - } + for_each_cpu(cpu, policy->cpus) + writel(ndiv, data->cpu_data[cpu].freq_core_reg); } /* @@ -157,19 +150,35 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); void __iomem *actmon_reg; - u32 cpuid, clusterid; + u32 delta_refcnt; + int cnt = 0; u64 val; - data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid); - actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid); + actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid, + data->cpu_data[c->cpu].cpuid); val = readq(actmon_reg); c->last_refclk_cnt = upper_32_bits(val); c->last_coreclk_cnt = lower_32_bits(val); - udelay(US_DELAY); - val = readq(actmon_reg); - c->refclk_cnt = upper_32_bits(val); - c->coreclk_cnt = lower_32_bits(val); + + /* + * The sampling window is based on the minimum number of reference + * clock cycles which is known to give a stable value of CPU frequency. + */ + do { + val = readq(actmon_reg); + c->refclk_cnt = upper_32_bits(val); + c->coreclk_cnt = lower_32_bits(val); + if (c->refclk_cnt < c->last_refclk_cnt) + delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt); + else + delta_refcnt = c->refclk_cnt - c->last_refclk_cnt; + if (++cnt >= 0xFFFF) { + pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n", + c->cpu, delta_refcnt, cnt); + break; + } + } while (delta_refcnt < data->soc->refclk_delta_min); } static struct tegra_cpufreq_ops tegra234_cpufreq_ops = { @@ -184,6 +193,7 @@ static const struct tegra_cpufreq_soc tegra234_cpufreq_soc = { .actmon_cntr_base = 0x9000, .maxcpus_per_cluster = 4, .num_clusters = 3, + .refclk_delta_min = 16000, }; static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = { @@ -191,6 +201,7 @@ static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = { .actmon_cntr_base = 0x4000, .maxcpus_per_cluster = 8, .num_clusters = 1, + .refclk_delta_min = 16000, }; static void tegra194_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid) @@ -231,15 +242,33 @@ static inline u32 map_ndiv_to_freq(struct mrq_cpu_ndiv_limits_response static void tegra194_read_counters(struct tegra_cpu_ctr *c) { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + u32 delta_refcnt; + int cnt = 0; u64 val; val = read_freq_feedback(); c->last_refclk_cnt = lower_32_bits(val); c->last_coreclk_cnt = upper_32_bits(val); - udelay(US_DELAY); - val = read_freq_feedback(); - c->refclk_cnt = lower_32_bits(val); - c->coreclk_cnt = upper_32_bits(val); + + /* + * The sampling window is based on the minimum number of reference + * clock cycles which is known to give a stable value of CPU frequency. + */ + do { + val = read_freq_feedback(); + c->refclk_cnt = lower_32_bits(val); + c->coreclk_cnt = upper_32_bits(val); + if (c->refclk_cnt < c->last_refclk_cnt) + delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt); + else + delta_refcnt = c->refclk_cnt - c->last_refclk_cnt; + if (++cnt >= 0xFFFF) { + pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n", + c->cpu, delta_refcnt, cnt); + break; + } + } while (delta_refcnt < data->soc->refclk_delta_min); } static void tegra_read_counters(struct work_struct *work) @@ -297,9 +326,8 @@ static unsigned int tegra194_calculate_speed(u32 cpu) u32 rate_mhz; /* - * udelay() is required to reconstruct cpu frequency over an - * observation window. Using workqueue to call udelay() with - * interrupts enabled. + * Reconstruct cpu frequency over an observation/sampling window. + * Using workqueue to keep interrupts enabled during the interval. */ read_counters_work.c.cpu = cpu; INIT_WORK_ONSTACK(&read_counters_work.work, tegra_read_counters); @@ -357,19 +385,17 @@ static void tegra194_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) static unsigned int tegra194_get_speed(u32 cpu) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + u32 clusterid = data->cpu_data[cpu].clusterid; struct cpufreq_frequency_table *pos; - u32 cpuid, clusterid; unsigned int rate; u64 ndiv; int ret; - data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); - /* reconstruct actual cpu freq using counters */ rate = tegra194_calculate_speed(cpu); /* get last written ndiv value */ - ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv); + ret = data->soc->ops->get_cpu_ndiv(cpu, data->cpu_data[cpu].cpuid, clusterid, &ndiv); if (WARN_ON_ONCE(ret)) return rate; @@ -383,9 +409,9 @@ static unsigned int tegra194_get_speed(u32 cpu) if (pos->driver_data != ndiv) continue; - if (abs(pos->frequency - rate) > 115200) { - pr_warn("cpufreq: cpu%d,cur:%u,set:%u,set ndiv:%llu\n", - cpu, rate, pos->frequency, ndiv); + if (abs(pos->frequency - rate) > MAX_DELTA_KHZ) { + pr_warn("cpufreq: cpu%d,cur:%u,set:%u,delta:%d,set ndiv:%llu\n", + cpu, rate, pos->frequency, abs(rate - pos->frequency), ndiv); } else { rate = pos->frequency; } @@ -450,6 +476,8 @@ static int tegra_cpufreq_init_cpufreq_table(struct cpufreq_policy *policy, if (IS_ERR(opp)) continue; + dev_pm_opp_put(opp); + ret = dev_pm_opp_enable(cpu_dev, pos->frequency * KHZ); if (ret < 0) return ret; @@ -473,13 +501,12 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); int maxcpus_per_cluster = data->soc->maxcpus_per_cluster; + u32 clusterid = data->cpu_data[policy->cpu].clusterid; struct cpufreq_frequency_table *freq_table; struct cpufreq_frequency_table *bpmp_lut; u32 start_cpu, cpu; - u32 clusterid; int ret; - data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid); if (clusterid >= data->soc->num_clusters || !data->bpmp_luts[clusterid]) return -EINVAL; @@ -578,6 +605,7 @@ static const struct tegra_cpufreq_soc tegra194_cpufreq_soc = { .ops = &tegra194_cpufreq_ops, .maxcpus_per_cluster = 2, .num_clusters = 4, + .refclk_delta_min = 16000, }; static void tegra194_cpufreq_free_resources(void) @@ -657,6 +685,28 @@ tegra_cpufreq_bpmp_read_lut(struct platform_device *pdev, struct tegra_bpmp *bpm return freq_table; } +static int tegra194_cpufreq_store_physids(unsigned int cpu, struct tegra194_cpufreq_data *data) +{ + int num_cpus = data->soc->maxcpus_per_cluster * data->soc->num_clusters; + u32 cpuid, clusterid; + u64 mpidr_id; + + if (cpu > (num_cpus - 1)) { + pr_err("cpufreq: wrong num of cpus or clusters in soc data\n"); + return -EINVAL; + } + + data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); + + mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; + + data->cpu_data[cpu].cpuid = cpuid; + data->cpu_data[cpu].clusterid = clusterid; + data->cpu_data[cpu].freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); + + return 0; +} + static int tegra194_cpufreq_probe(struct platform_device *pdev) { const struct tegra_cpufreq_soc *soc; @@ -664,6 +714,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) struct tegra_bpmp *bpmp; struct device *cpu_dev; int err, i; + u32 cpu; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -671,7 +722,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) soc = of_device_get_match_data(&pdev->dev); - if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters) { + if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters && soc->refclk_delta_min) { data->soc = soc; } else { dev_err(&pdev->dev, "soc data missing\n"); @@ -690,6 +741,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) return PTR_ERR(data->regs); } + data->cpu_data = devm_kcalloc(&pdev->dev, data->soc->num_clusters * + data->soc->maxcpus_per_cluster, + sizeof(*data->cpu_data), GFP_KERNEL); + if (!data->cpu_data) + return -ENOMEM; + platform_set_drvdata(pdev, data); bpmp = tegra_bpmp_get(&pdev->dev); @@ -711,6 +768,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) } } + for_each_possible_cpu(cpu) { + err = tegra194_cpufreq_store_physids(cpu, data); + if (err) + goto err_free_res; + } + tegra194_cpufreq_driver.driver_data = data; /* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */ diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 3c37d7899660..46c41e2ca727 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -338,6 +338,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = { { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, { .compatible = "ti,am625", .data = &am625_soc_data, }, { .compatible = "ti,am62a7", .data = &am625_soc_data, }, + { .compatible = "ti,am62p5", .data = &am625_soc_data, }, /* legacy */ { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, }, { .compatible = "ti,omap3630", .data = &omap36xx_soc_data, }, diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 474d81831ad3..b3a68d5833bd 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -88,7 +88,7 @@ static unsigned long find_available_min_freq(struct devfreq *devfreq) struct dev_pm_opp *opp; unsigned long min_freq = 0; - opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq); + opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &min_freq, 0); if (IS_ERR(opp)) min_freq = 0; else @@ -102,7 +102,7 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq) struct dev_pm_opp *opp; unsigned long max_freq = ULONG_MAX; - opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq); + opp = dev_pm_opp_find_freq_floor_indexed(devfreq->dev.parent, &max_freq, 0); if (IS_ERR(opp)) max_freq = 0; else @@ -196,7 +196,7 @@ static int set_freq_table(struct devfreq *devfreq) return -ENOMEM; for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) { - opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq); + opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &freq, 0); if (IS_ERR(opp)) { devm_kfree(devfreq->dev.parent, devfreq->freq_table); return PTR_ERR(opp); @@ -2036,18 +2036,18 @@ struct dev_pm_opp *devfreq_recommended_opp(struct device *dev, if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) { /* The freq is an upper bound. opp should be lower */ - opp = dev_pm_opp_find_freq_floor(dev, freq); + opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ERANGE)) - opp = dev_pm_opp_find_freq_ceil(dev, freq); + opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0); } else { /* The freq is an lower bound. opp should be higher */ - opp = dev_pm_opp_find_freq_ceil(dev, freq); + opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ERANGE)) - opp = dev_pm_opp_find_freq_floor(dev, freq); + opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0); } return opp; diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index 896a6cc93b00..56bac4702006 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c @@ -12,9 +12,9 @@ #include #include #include -#include -#include +#include #include +#include #include #include #include @@ -507,7 +507,6 @@ static int of_get_devfreq_events(struct device_node *np, struct device *dev = info->dev; struct device_node *events_np, *node; int i, j, count; - const struct of_device_id *of_id; int ret; events_np = of_get_child_by_name(np, "events"); @@ -525,13 +524,7 @@ static int of_get_devfreq_events(struct device_node *np, } info->num_events = count; - of_id = of_match_device(exynos_ppmu_id_match, dev); - if (of_id) - info->ppmu_type = (enum exynos_ppmu_type)of_id->data; - else { - of_node_put(events_np); - return -EINVAL; - } + info->ppmu_type = (enum exynos_ppmu_type)device_get_match_data(dev); j = 0; for_each_child_of_node(events_np, node) { diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index 39ac069cabc7..e2a1e4463b6f 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -16,30 +16,71 @@ #include #include #include +#include #include +#include +#include +#include +#include +#include #include +#include +#include -#define RK3399_DMC_NUM_CH 2 +#define DMC_MAX_CHANNELS 4 + +#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16) /* DDRMON_CTRL */ #define DDRMON_CTRL 0x04 -#define CLR_DDRMON_CTRL (0x1f0000 << 0) -#define LPDDR4_EN (0x10001 << 4) -#define HARDWARE_EN (0x10001 << 3) -#define LPDDR3_EN (0x10001 << 2) -#define SOFTWARE_EN (0x10001 << 1) -#define SOFTWARE_DIS (0x10000 << 1) -#define TIME_CNT_EN (0x10001 << 0) +#define DDRMON_CTRL_DDR4 BIT(5) +#define DDRMON_CTRL_LPDDR4 BIT(4) +#define DDRMON_CTRL_HARDWARE_EN BIT(3) +#define DDRMON_CTRL_LPDDR23 BIT(2) +#define DDRMON_CTRL_SOFTWARE_EN BIT(1) +#define DDRMON_CTRL_TIMER_CNT_EN BIT(0) +#define DDRMON_CTRL_DDR_TYPE_MASK (DDRMON_CTRL_DDR4 | \ + DDRMON_CTRL_LPDDR4 | \ + DDRMON_CTRL_LPDDR23) +#define DDRMON_CH0_WR_NUM 0x20 +#define DDRMON_CH0_RD_NUM 0x24 #define DDRMON_CH0_COUNT_NUM 0x28 #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c #define DDRMON_CH1_COUNT_NUM 0x3c #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 -struct dmc_usage { - u32 access; - u32 total; +#define PERF_EVENT_CYCLES 0x0 +#define PERF_EVENT_READ_BYTES 0x1 +#define PERF_EVENT_WRITE_BYTES 0x2 +#define PERF_EVENT_READ_BYTES0 0x3 +#define PERF_EVENT_WRITE_BYTES0 0x4 +#define PERF_EVENT_READ_BYTES1 0x5 +#define PERF_EVENT_WRITE_BYTES1 0x6 +#define PERF_EVENT_READ_BYTES2 0x7 +#define PERF_EVENT_WRITE_BYTES2 0x8 +#define PERF_EVENT_READ_BYTES3 0x9 +#define PERF_EVENT_WRITE_BYTES3 0xa +#define PERF_EVENT_BYTES 0xb +#define PERF_ACCESS_TYPE_MAX 0xc + +/** + * struct dmc_count_channel - structure to hold counter values from the DDR controller + * @access: Number of read and write accesses + * @clock_cycles: DDR clock cycles + * @read_access: number of read accesses + * @write_access: number of write accesses + */ +struct dmc_count_channel { + u64 access; + u64 clock_cycles; + u64 read_access; + u64 write_access; +}; + +struct dmc_count { + struct dmc_count_channel c[DMC_MAX_CHANNELS]; }; /* @@ -49,98 +90,157 @@ struct dmc_usage { */ struct rockchip_dfi { struct devfreq_event_dev *edev; - struct devfreq_event_desc *desc; - struct dmc_usage ch_usage[RK3399_DMC_NUM_CH]; + struct devfreq_event_desc desc; + struct dmc_count last_event_count; + + struct dmc_count last_perf_count; + struct dmc_count total_count; + seqlock_t count_seqlock; /* protects last_perf_count and total_count */ + struct device *dev; void __iomem *regs; struct regmap *regmap_pmu; struct clk *clk; + int usecount; + struct mutex mutex; + u32 ddr_type; + unsigned int channel_mask; + unsigned int max_channels; + enum cpuhp_state cpuhp_state; + struct hlist_node node; + struct pmu pmu; + struct hrtimer timer; + unsigned int cpu; + int active_events; + int burst_len; + int buswidth[DMC_MAX_CHANNELS]; + int ddrmon_stride; + bool ddrmon_ctrl_single; }; -static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) +static int rockchip_dfi_enable(struct rockchip_dfi *dfi) { - struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); - void __iomem *dfi_regs = info->regs; - u32 val; - u32 ddr_type; + void __iomem *dfi_regs = dfi->regs; + int i, ret = 0; - /* get ddr type */ - regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); - ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & - RK3399_PMUGRF_DDRTYPE_MASK; + mutex_lock(&dfi->mutex); - /* clear DDRMON_CTRL setting */ - writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); + dfi->usecount++; + if (dfi->usecount > 1) + goto out; - /* set ddr type to dfi */ - if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3) - writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); - else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4) - writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); - - /* enable count, use software mode */ - writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL); -} - -static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) -{ - struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); - void __iomem *dfi_regs = info->regs; - - writel_relaxed(SOFTWARE_DIS, dfi_regs + DDRMON_CTRL); -} - -static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev) -{ - struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); - u32 tmp, max = 0; - u32 i, busier_ch = 0; - void __iomem *dfi_regs = info->regs; - - rockchip_dfi_stop_hardware_counter(edev); - - /* Find out which channel is busier */ - for (i = 0; i < RK3399_DMC_NUM_CH; i++) { - info->ch_usage[i].access = readl_relaxed(dfi_regs + - DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4; - info->ch_usage[i].total = readl_relaxed(dfi_regs + - DDRMON_CH0_COUNT_NUM + i * 20); - tmp = info->ch_usage[i].access; - if (tmp > max) { - busier_ch = i; - max = tmp; - } - } - rockchip_dfi_start_hardware_counter(edev); - - return busier_ch; -} - -static int rockchip_dfi_disable(struct devfreq_event_dev *edev) -{ - struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); - - rockchip_dfi_stop_hardware_counter(edev); - clk_disable_unprepare(info->clk); - - return 0; -} - -static int rockchip_dfi_enable(struct devfreq_event_dev *edev) -{ - struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); - int ret; - - ret = clk_prepare_enable(info->clk); + ret = clk_prepare_enable(dfi->clk); if (ret) { - dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret); - return ret; + dev_err(&dfi->edev->dev, "failed to enable dfi clk: %d\n", ret); + goto out; } - rockchip_dfi_start_hardware_counter(edev); + for (i = 0; i < dfi->max_channels; i++) { + u32 ctrl = 0; + + if (!(dfi->channel_mask & BIT(i))) + continue; + + /* clear DDRMON_CTRL setting */ + writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_TIMER_CNT_EN | + DDRMON_CTRL_SOFTWARE_EN | DDRMON_CTRL_HARDWARE_EN), + dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL); + + /* set ddr type to dfi */ + switch (dfi->ddr_type) { + case ROCKCHIP_DDRTYPE_LPDDR2: + case ROCKCHIP_DDRTYPE_LPDDR3: + ctrl = DDRMON_CTRL_LPDDR23; + break; + case ROCKCHIP_DDRTYPE_LPDDR4: + case ROCKCHIP_DDRTYPE_LPDDR4X: + ctrl = DDRMON_CTRL_LPDDR4; + break; + default: + break; + } + + writel_relaxed(HIWORD_UPDATE(ctrl, DDRMON_CTRL_DDR_TYPE_MASK), + dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL); + + /* enable count, use software mode */ + writel_relaxed(HIWORD_UPDATE(DDRMON_CTRL_SOFTWARE_EN, DDRMON_CTRL_SOFTWARE_EN), + dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL); + + if (dfi->ddrmon_ctrl_single) + break; + } +out: + mutex_unlock(&dfi->mutex); + + return ret; +} + +static void rockchip_dfi_disable(struct rockchip_dfi *dfi) +{ + void __iomem *dfi_regs = dfi->regs; + int i; + + mutex_lock(&dfi->mutex); + + dfi->usecount--; + + WARN_ON_ONCE(dfi->usecount < 0); + + if (dfi->usecount > 0) + goto out; + + for (i = 0; i < dfi->max_channels; i++) { + if (!(dfi->channel_mask & BIT(i))) + continue; + + writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_SOFTWARE_EN), + dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL); + + if (dfi->ddrmon_ctrl_single) + break; + } + + clk_disable_unprepare(dfi->clk); +out: + mutex_unlock(&dfi->mutex); +} + +static void rockchip_dfi_read_counters(struct rockchip_dfi *dfi, struct dmc_count *res) +{ + u32 i; + void __iomem *dfi_regs = dfi->regs; + + for (i = 0; i < dfi->max_channels; i++) { + if (!(dfi->channel_mask & BIT(i))) + continue; + res->c[i].read_access = readl_relaxed(dfi_regs + + DDRMON_CH0_RD_NUM + i * dfi->ddrmon_stride); + res->c[i].write_access = readl_relaxed(dfi_regs + + DDRMON_CH0_WR_NUM + i * dfi->ddrmon_stride); + res->c[i].access = readl_relaxed(dfi_regs + + DDRMON_CH0_DFI_ACCESS_NUM + i * dfi->ddrmon_stride); + res->c[i].clock_cycles = readl_relaxed(dfi_regs + + DDRMON_CH0_COUNT_NUM + i * dfi->ddrmon_stride); + } +} + +static int rockchip_dfi_event_disable(struct devfreq_event_dev *edev) +{ + struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev); + + rockchip_dfi_disable(dfi); + return 0; } +static int rockchip_dfi_event_enable(struct devfreq_event_dev *edev) +{ + struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev); + + return rockchip_dfi_enable(dfi); +} + static int rockchip_dfi_set_event(struct devfreq_event_dev *edev) { return 0; @@ -149,77 +249,576 @@ static int rockchip_dfi_set_event(struct devfreq_event_dev *edev) static int rockchip_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata) { - struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); - int busier_ch; + struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev); + struct dmc_count count; + struct dmc_count *last = &dfi->last_event_count; + u32 access = 0, clock_cycles = 0; + int i; - busier_ch = rockchip_dfi_get_busier_ch(edev); + rockchip_dfi_read_counters(dfi, &count); - edata->load_count = info->ch_usage[busier_ch].access; - edata->total_count = info->ch_usage[busier_ch].total; + /* We can only report one channel, so find the busiest one */ + for (i = 0; i < dfi->max_channels; i++) { + u32 a, c; + + if (!(dfi->channel_mask & BIT(i))) + continue; + + a = count.c[i].access - last->c[i].access; + c = count.c[i].clock_cycles - last->c[i].clock_cycles; + + if (a > access) { + access = a; + clock_cycles = c; + } + } + + edata->load_count = access * 4; + edata->total_count = clock_cycles; + + dfi->last_event_count = count; return 0; } static const struct devfreq_event_ops rockchip_dfi_ops = { - .disable = rockchip_dfi_disable, - .enable = rockchip_dfi_enable, + .disable = rockchip_dfi_event_disable, + .enable = rockchip_dfi_event_enable, .get_event = rockchip_dfi_get_event, .set_event = rockchip_dfi_set_event, }; +#ifdef CONFIG_PERF_EVENTS + +static void rockchip_ddr_perf_counters_add(struct rockchip_dfi *dfi, + const struct dmc_count *now, + struct dmc_count *res) +{ + const struct dmc_count *last = &dfi->last_perf_count; + int i; + + for (i = 0; i < dfi->max_channels; i++) { + res->c[i].read_access = dfi->total_count.c[i].read_access + + (u32)(now->c[i].read_access - last->c[i].read_access); + res->c[i].write_access = dfi->total_count.c[i].write_access + + (u32)(now->c[i].write_access - last->c[i].write_access); + res->c[i].access = dfi->total_count.c[i].access + + (u32)(now->c[i].access - last->c[i].access); + res->c[i].clock_cycles = dfi->total_count.c[i].clock_cycles + + (u32)(now->c[i].clock_cycles - last->c[i].clock_cycles); + } +} + +static ssize_t ddr_perf_cpumask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pmu *pmu = dev_get_drvdata(dev); + struct rockchip_dfi *dfi = container_of(pmu, struct rockchip_dfi, pmu); + + return cpumap_print_to_pagebuf(true, buf, cpumask_of(dfi->cpu)); +} + +static struct device_attribute ddr_perf_cpumask_attr = + __ATTR(cpumask, 0444, ddr_perf_cpumask_show, NULL); + +static struct attribute *ddr_perf_cpumask_attrs[] = { + &ddr_perf_cpumask_attr.attr, + NULL, +}; + +static const struct attribute_group ddr_perf_cpumask_attr_group = { + .attrs = ddr_perf_cpumask_attrs, +}; + +PMU_EVENT_ATTR_STRING(cycles, ddr_pmu_cycles, "event="__stringify(PERF_EVENT_CYCLES)) + +#define DFI_PMU_EVENT_ATTR(_name, _var, _str) \ + PMU_EVENT_ATTR_STRING(_name, _var, _str); \ + PMU_EVENT_ATTR_STRING(_name.unit, _var##_unit, "MB"); \ + PMU_EVENT_ATTR_STRING(_name.scale, _var##_scale, "9.536743164e-07") + +DFI_PMU_EVENT_ATTR(read-bytes0, ddr_pmu_read_bytes0, "event="__stringify(PERF_EVENT_READ_BYTES0)); +DFI_PMU_EVENT_ATTR(write-bytes0, ddr_pmu_write_bytes0, "event="__stringify(PERF_EVENT_WRITE_BYTES0)); + +DFI_PMU_EVENT_ATTR(read-bytes1, ddr_pmu_read_bytes1, "event="__stringify(PERF_EVENT_READ_BYTES1)); +DFI_PMU_EVENT_ATTR(write-bytes1, ddr_pmu_write_bytes1, "event="__stringify(PERF_EVENT_WRITE_BYTES1)); + +DFI_PMU_EVENT_ATTR(read-bytes2, ddr_pmu_read_bytes2, "event="__stringify(PERF_EVENT_READ_BYTES2)); +DFI_PMU_EVENT_ATTR(write-bytes2, ddr_pmu_write_bytes2, "event="__stringify(PERF_EVENT_WRITE_BYTES2)); + +DFI_PMU_EVENT_ATTR(read-bytes3, ddr_pmu_read_bytes3, "event="__stringify(PERF_EVENT_READ_BYTES3)); +DFI_PMU_EVENT_ATTR(write-bytes3, ddr_pmu_write_bytes3, "event="__stringify(PERF_EVENT_WRITE_BYTES3)); + +DFI_PMU_EVENT_ATTR(read-bytes, ddr_pmu_read_bytes, "event="__stringify(PERF_EVENT_READ_BYTES)); +DFI_PMU_EVENT_ATTR(write-bytes, ddr_pmu_write_bytes, "event="__stringify(PERF_EVENT_WRITE_BYTES)); + +DFI_PMU_EVENT_ATTR(bytes, ddr_pmu_bytes, "event="__stringify(PERF_EVENT_BYTES)); + +#define DFI_ATTR_MB(_name) \ + &_name.attr.attr, \ + &_name##_unit.attr.attr, \ + &_name##_scale.attr.attr + +static struct attribute *ddr_perf_events_attrs[] = { + &ddr_pmu_cycles.attr.attr, + DFI_ATTR_MB(ddr_pmu_read_bytes), + DFI_ATTR_MB(ddr_pmu_write_bytes), + DFI_ATTR_MB(ddr_pmu_read_bytes0), + DFI_ATTR_MB(ddr_pmu_write_bytes0), + DFI_ATTR_MB(ddr_pmu_read_bytes1), + DFI_ATTR_MB(ddr_pmu_write_bytes1), + DFI_ATTR_MB(ddr_pmu_read_bytes2), + DFI_ATTR_MB(ddr_pmu_write_bytes2), + DFI_ATTR_MB(ddr_pmu_read_bytes3), + DFI_ATTR_MB(ddr_pmu_write_bytes3), + DFI_ATTR_MB(ddr_pmu_bytes), + NULL, +}; + +static const struct attribute_group ddr_perf_events_attr_group = { + .name = "events", + .attrs = ddr_perf_events_attrs, +}; + +PMU_FORMAT_ATTR(event, "config:0-7"); + +static struct attribute *ddr_perf_format_attrs[] = { + &format_attr_event.attr, + NULL, +}; + +static const struct attribute_group ddr_perf_format_attr_group = { + .name = "format", + .attrs = ddr_perf_format_attrs, +}; + +static const struct attribute_group *attr_groups[] = { + &ddr_perf_events_attr_group, + &ddr_perf_cpumask_attr_group, + &ddr_perf_format_attr_group, + NULL, +}; + +static int rockchip_ddr_perf_event_init(struct perf_event *event) +{ + struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu); + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + if (event->attach_state & PERF_ATTACH_TASK) + return -EINVAL; + + if (event->cpu < 0) { + dev_warn(dfi->dev, "Can't provide per-task data!\n"); + return -EINVAL; + } + + return 0; +} + +static u64 rockchip_ddr_perf_event_get_count(struct perf_event *event) +{ + struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu); + int blen = dfi->burst_len; + struct dmc_count total, now; + unsigned int seq; + u64 count = 0; + int i; + + rockchip_dfi_read_counters(dfi, &now); + + do { + seq = read_seqbegin(&dfi->count_seqlock); + rockchip_ddr_perf_counters_add(dfi, &now, &total); + } while (read_seqretry(&dfi->count_seqlock, seq)); + + switch (event->attr.config) { + case PERF_EVENT_CYCLES: + count = total.c[0].clock_cycles; + break; + case PERF_EVENT_READ_BYTES: + for (i = 0; i < dfi->max_channels; i++) + count += total.c[i].read_access * blen * dfi->buswidth[i]; + break; + case PERF_EVENT_WRITE_BYTES: + for (i = 0; i < dfi->max_channels; i++) + count += total.c[i].write_access * blen * dfi->buswidth[i]; + break; + case PERF_EVENT_READ_BYTES0: + count = total.c[0].read_access * blen * dfi->buswidth[0]; + break; + case PERF_EVENT_WRITE_BYTES0: + count = total.c[0].write_access * blen * dfi->buswidth[0]; + break; + case PERF_EVENT_READ_BYTES1: + count = total.c[1].read_access * blen * dfi->buswidth[1]; + break; + case PERF_EVENT_WRITE_BYTES1: + count = total.c[1].write_access * blen * dfi->buswidth[1]; + break; + case PERF_EVENT_READ_BYTES2: + count = total.c[2].read_access * blen * dfi->buswidth[2]; + break; + case PERF_EVENT_WRITE_BYTES2: + count = total.c[2].write_access * blen * dfi->buswidth[2]; + break; + case PERF_EVENT_READ_BYTES3: + count = total.c[3].read_access * blen * dfi->buswidth[3]; + break; + case PERF_EVENT_WRITE_BYTES3: + count = total.c[3].write_access * blen * dfi->buswidth[3]; + break; + case PERF_EVENT_BYTES: + for (i = 0; i < dfi->max_channels; i++) + count += total.c[i].access * blen * dfi->buswidth[i]; + break; + } + + return count; +} + +static void rockchip_ddr_perf_event_update(struct perf_event *event) +{ + u64 now; + s64 prev; + + if (event->attr.config >= PERF_ACCESS_TYPE_MAX) + return; + + now = rockchip_ddr_perf_event_get_count(event); + prev = local64_xchg(&event->hw.prev_count, now); + local64_add(now - prev, &event->count); +} + +static void rockchip_ddr_perf_event_start(struct perf_event *event, int flags) +{ + u64 now = rockchip_ddr_perf_event_get_count(event); + + local64_set(&event->hw.prev_count, now); +} + +static int rockchip_ddr_perf_event_add(struct perf_event *event, int flags) +{ + struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu); + + dfi->active_events++; + + if (dfi->active_events == 1) { + dfi->total_count = (struct dmc_count){}; + rockchip_dfi_read_counters(dfi, &dfi->last_perf_count); + hrtimer_start(&dfi->timer, ns_to_ktime(NSEC_PER_SEC), HRTIMER_MODE_REL); + } + + if (flags & PERF_EF_START) + rockchip_ddr_perf_event_start(event, flags); + + return 0; +} + +static void rockchip_ddr_perf_event_stop(struct perf_event *event, int flags) +{ + rockchip_ddr_perf_event_update(event); +} + +static void rockchip_ddr_perf_event_del(struct perf_event *event, int flags) +{ + struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu); + + rockchip_ddr_perf_event_stop(event, PERF_EF_UPDATE); + + dfi->active_events--; + + if (dfi->active_events == 0) + hrtimer_cancel(&dfi->timer); +} + +static enum hrtimer_restart rockchip_dfi_timer(struct hrtimer *timer) +{ + struct rockchip_dfi *dfi = container_of(timer, struct rockchip_dfi, timer); + struct dmc_count now, total; + + rockchip_dfi_read_counters(dfi, &now); + + write_seqlock(&dfi->count_seqlock); + + rockchip_ddr_perf_counters_add(dfi, &now, &total); + dfi->total_count = total; + dfi->last_perf_count = now; + + write_sequnlock(&dfi->count_seqlock); + + hrtimer_forward_now(&dfi->timer, ns_to_ktime(NSEC_PER_SEC)); + + return HRTIMER_RESTART; +}; + +static int ddr_perf_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct rockchip_dfi *dfi = hlist_entry_safe(node, struct rockchip_dfi, node); + int target; + + if (cpu != dfi->cpu) + return 0; + + target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) + return 0; + + perf_pmu_migrate_context(&dfi->pmu, cpu, target); + dfi->cpu = target; + + return 0; +} + +static void rockchip_ddr_cpuhp_remove_state(void *data) +{ + struct rockchip_dfi *dfi = data; + + cpuhp_remove_multi_state(dfi->cpuhp_state); + + rockchip_dfi_disable(dfi); +} + +static void rockchip_ddr_cpuhp_remove_instance(void *data) +{ + struct rockchip_dfi *dfi = data; + + cpuhp_state_remove_instance_nocalls(dfi->cpuhp_state, &dfi->node); +} + +static void rockchip_ddr_perf_remove(void *data) +{ + struct rockchip_dfi *dfi = data; + + perf_pmu_unregister(&dfi->pmu); +} + +static int rockchip_ddr_perf_init(struct rockchip_dfi *dfi) +{ + struct pmu *pmu = &dfi->pmu; + int ret; + + seqlock_init(&dfi->count_seqlock); + + pmu->module = THIS_MODULE; + pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE; + pmu->task_ctx_nr = perf_invalid_context; + pmu->attr_groups = attr_groups; + pmu->event_init = rockchip_ddr_perf_event_init; + pmu->add = rockchip_ddr_perf_event_add; + pmu->del = rockchip_ddr_perf_event_del; + pmu->start = rockchip_ddr_perf_event_start; + pmu->stop = rockchip_ddr_perf_event_stop; + pmu->read = rockchip_ddr_perf_event_update; + + dfi->cpu = raw_smp_processor_id(); + + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "rockchip_ddr_perf_pmu", + NULL, + ddr_perf_offline_cpu); + + if (ret < 0) { + dev_err(dfi->dev, "cpuhp_setup_state_multi failed: %d\n", ret); + return ret; + } + + dfi->cpuhp_state = ret; + + rockchip_dfi_enable(dfi); + + ret = devm_add_action_or_reset(dfi->dev, rockchip_ddr_cpuhp_remove_state, dfi); + if (ret) + return ret; + + ret = cpuhp_state_add_instance_nocalls(dfi->cpuhp_state, &dfi->node); + if (ret) { + dev_err(dfi->dev, "Error %d registering hotplug\n", ret); + return ret; + } + + ret = devm_add_action_or_reset(dfi->dev, rockchip_ddr_cpuhp_remove_instance, dfi); + if (ret) + return ret; + + hrtimer_init(&dfi->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + dfi->timer.function = rockchip_dfi_timer; + + switch (dfi->ddr_type) { + case ROCKCHIP_DDRTYPE_LPDDR2: + case ROCKCHIP_DDRTYPE_LPDDR3: + dfi->burst_len = 8; + break; + case ROCKCHIP_DDRTYPE_LPDDR4: + case ROCKCHIP_DDRTYPE_LPDDR4X: + dfi->burst_len = 16; + break; + } + + ret = perf_pmu_register(pmu, "rockchip_ddr", -1); + if (ret) + return ret; + + return devm_add_action_or_reset(dfi->dev, rockchip_ddr_perf_remove, dfi); +} +#else +static int rockchip_ddr_perf_init(struct rockchip_dfi *dfi) +{ + return 0; +} +#endif + +static int rk3399_dfi_init(struct rockchip_dfi *dfi) +{ + struct regmap *regmap_pmu = dfi->regmap_pmu; + u32 val; + + dfi->clk = devm_clk_get(dfi->dev, "pclk_ddr_mon"); + if (IS_ERR(dfi->clk)) + return dev_err_probe(dfi->dev, PTR_ERR(dfi->clk), + "Cannot get the clk pclk_ddr_mon\n"); + + /* get ddr type */ + regmap_read(regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); + dfi->ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val); + + dfi->channel_mask = GENMASK(1, 0); + dfi->max_channels = 2; + + dfi->buswidth[0] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH0, val) == 0 ? 4 : 2; + dfi->buswidth[1] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH1, val) == 0 ? 4 : 2; + + dfi->ddrmon_stride = 0x14; + dfi->ddrmon_ctrl_single = true; + + return 0; +}; + +static int rk3568_dfi_init(struct rockchip_dfi *dfi) +{ + struct regmap *regmap_pmu = dfi->regmap_pmu; + u32 reg2, reg3; + + regmap_read(regmap_pmu, RK3568_PMUGRF_OS_REG2, ®2); + regmap_read(regmap_pmu, RK3568_PMUGRF_OS_REG3, ®3); + + /* lower 3 bits of the DDR type */ + dfi->ddr_type = FIELD_GET(RK3568_PMUGRF_OS_REG2_DRAMTYPE_INFO, reg2); + + /* + * For version three and higher the upper two bits of the DDR type are + * in RK3568_PMUGRF_OS_REG3 + */ + if (FIELD_GET(RK3568_PMUGRF_OS_REG3_SYSREG_VERSION, reg3) >= 0x3) + dfi->ddr_type |= FIELD_GET(RK3568_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3; + + dfi->channel_mask = BIT(0); + dfi->max_channels = 1; + + dfi->buswidth[0] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2; + + dfi->ddrmon_stride = 0x0; /* not relevant, we only have a single channel on this SoC */ + dfi->ddrmon_ctrl_single = true; + + return 0; +}; + +static int rk3588_dfi_init(struct rockchip_dfi *dfi) +{ + struct regmap *regmap_pmu = dfi->regmap_pmu; + u32 reg2, reg3, reg4; + + regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG2, ®2); + regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG3, ®3); + regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG4, ®4); + + /* lower 3 bits of the DDR type */ + dfi->ddr_type = FIELD_GET(RK3588_PMUGRF_OS_REG2_DRAMTYPE_INFO, reg2); + + /* + * For version three and higher the upper two bits of the DDR type are + * in RK3588_PMUGRF_OS_REG3 + */ + if (FIELD_GET(RK3588_PMUGRF_OS_REG3_SYSREG_VERSION, reg3) >= 0x3) + dfi->ddr_type |= FIELD_GET(RK3588_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3; + + dfi->buswidth[0] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2; + dfi->buswidth[1] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg2) == 0 ? 4 : 2; + dfi->buswidth[2] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg4) == 0 ? 4 : 2; + dfi->buswidth[3] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg4) == 0 ? 4 : 2; + dfi->channel_mask = FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg2) | + FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg4) << 2; + dfi->max_channels = 4; + + dfi->ddrmon_stride = 0x4000; + + return 0; +}; + static const struct of_device_id rockchip_dfi_id_match[] = { - { .compatible = "rockchip,rk3399-dfi" }, + { .compatible = "rockchip,rk3399-dfi", .data = rk3399_dfi_init }, + { .compatible = "rockchip,rk3568-dfi", .data = rk3568_dfi_init }, + { .compatible = "rockchip,rk3588-dfi", .data = rk3588_dfi_init }, { }, }; + MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); static int rockchip_dfi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct rockchip_dfi *data; + struct rockchip_dfi *dfi; struct devfreq_event_desc *desc; struct device_node *np = pdev->dev.of_node, *node; + int (*soc_init)(struct rockchip_dfi *dfi); + int ret; - data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); - if (!data) + soc_init = of_device_get_match_data(&pdev->dev); + if (!soc_init) + return -EINVAL; + + dfi = devm_kzalloc(dev, sizeof(*dfi), GFP_KERNEL); + if (!dfi) return -ENOMEM; - data->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->regs)) - return PTR_ERR(data->regs); + dfi->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(dfi->regs)) + return PTR_ERR(dfi->regs); - data->clk = devm_clk_get(dev, "pclk_ddr_mon"); - if (IS_ERR(data->clk)) - return dev_err_probe(dev, PTR_ERR(data->clk), - "Cannot get the clk pclk_ddr_mon\n"); - - /* try to find the optional reference to the pmu syscon */ node = of_parse_phandle(np, "rockchip,pmu", 0); - if (node) { - data->regmap_pmu = syscon_node_to_regmap(node); - of_node_put(node); - if (IS_ERR(data->regmap_pmu)) - return PTR_ERR(data->regmap_pmu); - } - data->dev = dev; + if (!node) + return dev_err_probe(&pdev->dev, -ENODEV, "Can't find pmu_grf registers\n"); - desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); - if (!desc) - return -ENOMEM; + dfi->regmap_pmu = syscon_node_to_regmap(node); + of_node_put(node); + if (IS_ERR(dfi->regmap_pmu)) + return PTR_ERR(dfi->regmap_pmu); + dfi->dev = dev; + mutex_init(&dfi->mutex); + + desc = &dfi->desc; desc->ops = &rockchip_dfi_ops; - desc->driver_data = data; + desc->driver_data = dfi; desc->name = np->name; - data->desc = desc; - data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc); - if (IS_ERR(data->edev)) { + ret = soc_init(dfi); + if (ret) + return ret; + + dfi->edev = devm_devfreq_event_add_edev(&pdev->dev, desc); + if (IS_ERR(dfi->edev)) { dev_err(&pdev->dev, "failed to add devfreq-event device\n"); - return PTR_ERR(data->edev); + return PTR_ERR(dfi->edev); } - platform_set_drvdata(pdev, data); + ret = rockchip_ddr_perf_init(dfi); + if (ret) + return ret; + + platform_set_drvdata(pdev, dfi); return 0; } @@ -229,6 +828,7 @@ static struct platform_driver rockchip_dfi_driver = { .driver = { .name = "rockchip-dfi", .of_match_table = rockchip_dfi_id_match, + .suppress_bind_attrs = true, }, }; module_platform_driver(rockchip_dfi_driver); diff --git a/drivers/devfreq/mtk-cci-devfreq.c b/drivers/devfreq/mtk-cci-devfreq.c index 83a73f0ccd80..11bc3d03494c 100644 --- a/drivers/devfreq/mtk-cci-devfreq.c +++ b/drivers/devfreq/mtk-cci-devfreq.c @@ -137,6 +137,8 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq, if (drv->pre_freq == *freq) return 0; + mutex_lock(&drv->reg_lock); + inter_voltage = drv->inter_voltage; cci_pll = clk_get_parent(drv->cci_clk); @@ -144,11 +146,10 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq, opp = devfreq_recommended_opp(dev, &opp_rate, 1); if (IS_ERR(opp)) { dev_err(dev, "failed to find opp for freq: %ld\n", opp_rate); - return PTR_ERR(opp); + ret = PTR_ERR(opp); + goto out_unlock; } - mutex_lock(&drv->reg_lock); - voltage = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); @@ -227,9 +228,9 @@ static int mtk_ccifreq_opp_notifier(struct notifier_block *nb, drv = container_of(nb, struct mtk_ccifreq_drv, opp_nb); if (event == OPP_EVENT_ADJUST_VOLTAGE) { + mutex_lock(&drv->reg_lock); freq = dev_pm_opp_get_freq(opp); - mutex_lock(&drv->reg_lock); /* current opp item is changed */ if (freq == drv->pre_freq) { volt = dev_pm_opp_get_voltage(opp); diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index daff40702615..fd2c5ffedf41 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -381,17 +382,16 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) } regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); - ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & - RK3399_PMUGRF_DDRTYPE_MASK; + ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val); switch (ddr_type) { - case RK3399_PMUGRF_DDRTYPE_DDR3: + case ROCKCHIP_DDRTYPE_DDR3: data->odt_dis_freq = data->ddr3_odt_dis_freq; break; - case RK3399_PMUGRF_DDRTYPE_LPDDR3: + case ROCKCHIP_DDRTYPE_LPDDR3: data->odt_dis_freq = data->lpddr3_odt_dis_freq; break; - case RK3399_PMUGRF_DDRTYPE_LPDDR4: + case ROCKCHIP_DDRTYPE_LPDDR4: data->odt_dis_freq = data->lpddr4_odt_dis_freq; break; default: diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 673bafb8be58..913948876c93 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1790,9 +1790,11 @@ config GPIO_LATCH connected to other GPIOs. config GPIO_MOCKUP - tristate "GPIO Testing Driver" + tristate "GPIO Testing Driver (DEPRECATED)" select IRQ_SIM help + This module is DEPRECATED. Please consider using gpio-sim instead. + This enables GPIO Testing driver, which provides a way to test GPIO subsystem through sysfs (or char device) and debugfs. User could use it through the script in diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 54d7c450c596..c2edfbb231fc 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -317,13 +317,11 @@ skip_irq: return 0; } -static int altera_gpio_remove(struct platform_device *pdev) +static void altera_gpio_remove(struct platform_device *pdev) { struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev); of_mm_gpiochip_remove(&altera_gc->mmchip); - - return 0; } static const struct of_device_id altera_gpio_of_match[] = { @@ -338,7 +336,7 @@ static struct platform_driver altera_gpio_driver = { .of_match_table = altera_gpio_of_match, }, .probe = altera_gpio_probe, - .remove = altera_gpio_remove, + .remove_new = altera_gpio_remove, }; static int __init altera_gpio_init(void) diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index 07c6d090058d..0a2ea9db4682 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -122,13 +122,11 @@ static int pt_gpio_probe(struct platform_device *pdev) return ret; } -static int pt_gpio_remove(struct platform_device *pdev) +static void pt_gpio_remove(struct platform_device *pdev) { struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev); gpiochip_remove(&pt_gpio->gc); - - return 0; } static const struct acpi_device_id pt_gpio_acpi_match[] = { @@ -145,7 +143,7 @@ static struct platform_driver pt_gpio_driver = { .acpi_match_table = ACPI_PTR(pt_gpio_acpi_match), }, .probe = pt_gpio_probe, - .remove = pt_gpio_remove, + .remove_new = pt_gpio_remove, }; module_platform_driver(pt_gpio_driver); diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index bccdbfd5ec80..a789af4a5c85 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -371,7 +371,7 @@ static int brcmstb_gpio_sanity_check_banks(struct device *dev, } } -static int brcmstb_gpio_remove(struct platform_device *pdev) +static void brcmstb_gpio_remove(struct platform_device *pdev) { struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev); struct brcmstb_gpio_bank *bank; @@ -395,8 +395,6 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) */ list_for_each_entry(bank, &priv->bank_list, node) gpiochip_remove(&bank->gc); - - return 0; } static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, @@ -757,7 +755,7 @@ static struct platform_driver brcmstb_gpio_driver = { .pm = &brcmstb_gpio_pm_ops, }, .probe = brcmstb_gpio_probe, - .remove = brcmstb_gpio_remove, + .remove_new = brcmstb_gpio_remove, .shutdown = brcmstb_gpio_shutdown, }; module_platform_driver(brcmstb_gpio_driver); diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c index 3720b90cad10..6a439cf78459 100644 --- a/drivers/gpio/gpio-cadence.c +++ b/drivers/gpio/gpio-cadence.c @@ -268,14 +268,12 @@ err_revert_dir: return ret; } -static int cdns_gpio_remove(struct platform_device *pdev) +static void cdns_gpio_remove(struct platform_device *pdev) { struct cdns_gpio_chip *cgpio = platform_get_drvdata(pdev); iowrite32(cgpio->bypass_orig, cgpio->regs + CDNS_GPIO_BYPASS_MODE); clk_disable_unprepare(cgpio->pclk); - - return 0; } static const struct of_device_id cdns_of_ids[] = { @@ -290,7 +288,7 @@ static struct platform_driver cdns_gpio_driver = { .of_match_table = cdns_of_ids, }, .probe = cdns_gpio_probe, - .remove = cdns_gpio_remove, + .remove_new = cdns_gpio_remove, }; module_platform_driver(cdns_gpio_driver); diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 8db5717bdabe..bb499e362912 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -16,10 +16,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -486,7 +486,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) struct davinci_gpio_platform_data *pdata = dev->platform_data; struct davinci_gpio_regs __iomem *g; struct irq_domain *irq_domain = NULL; - const struct of_device_id *match; struct irq_chip *irq_chip; struct davinci_gpio_irq_data *irqdata; gpio_get_irq_chip_cb_t gpio_get_irq_chip; @@ -495,10 +494,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) * Use davinci_gpio_get_irq_chip by default to handle non DT cases */ gpio_get_irq_chip = davinci_gpio_get_irq_chip; - match = of_match_device(of_match_ptr(davinci_gpio_ids), - dev); - if (match) - gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data; + if (dev->of_node) + gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)device_get_match_data(dev); ngpio = pdata->ngpio; diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c index 71fa437b491f..7ead1f51128a 100644 --- a/drivers/gpio/gpio-dln2.c +++ b/drivers/gpio/gpio-dln2.c @@ -504,17 +504,15 @@ static int dln2_gpio_probe(struct platform_device *pdev) return 0; } -static int dln2_gpio_remove(struct platform_device *pdev) +static void dln2_gpio_remove(struct platform_device *pdev) { dln2_unregister_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV); - - return 0; } static struct platform_driver dln2_gpio_driver = { .driver.name = "dln2-gpio", .probe = dln2_gpio_probe, - .remove = dln2_gpio_remove, + .remove_new = dln2_gpio_remove, }; module_platform_driver(dln2_gpio_driver); diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index c22fcaa44a61..4a4f61bf6c58 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -21,7 +21,6 @@ #include #include -#include "gpiolib.h" #include "gpiolib-acpi.h" #define GPIO_SWPORTA_DR 0x00 diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 5320cf1de89c..be7f2fa5aa7b 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -91,12 +92,20 @@ enum sprd_eic_type { struct sprd_eic { struct gpio_chip chip; + struct notifier_block irq_nb; void __iomem *base[SPRD_EIC_MAX_BANK]; enum sprd_eic_type type; spinlock_t lock; int irq; }; +static ATOMIC_NOTIFIER_HEAD(sprd_eic_irq_notifier); + +static struct sprd_eic *to_sprd_eic(struct notifier_block *nb) +{ + return container_of(nb, struct sprd_eic, irq_nb); +} + struct sprd_eic_variant_data { enum sprd_eic_type type; u32 num_eics; @@ -494,13 +503,6 @@ retry: sprd_eic_irq_unmask(data); } -static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data) -{ - enum sprd_eic_type type = *(enum sprd_eic_type *)data; - - return !strcmp(chip->label, sprd_eic_label_name[type]); -} - static void sprd_eic_handle_one_type(struct gpio_chip *chip) { struct sprd_eic *sprd_eic = gpiochip_get_data(chip); @@ -546,27 +548,29 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip) static void sprd_eic_irq_handler(struct irq_desc *desc) { struct irq_chip *ic = irq_desc_get_chip(desc); - struct gpio_chip *chip; - enum sprd_eic_type type; chained_irq_enter(ic, desc); /* * Since the digital-chip EIC 4 sub-modules (debounce, latch, async - * and sync) share one same interrupt line, we should iterate each - * EIC module to check if there are EIC interrupts were triggered. + * and sync) share one same interrupt line, we should notify all of + * them to let them check if there are EIC interrupts were triggered. */ - for (type = SPRD_EIC_DEBOUNCE; type < SPRD_EIC_MAX; type++) { - chip = gpiochip_find(&type, sprd_eic_match_chip_by_type); - if (!chip) - continue; - - sprd_eic_handle_one_type(chip); - } + atomic_notifier_call_chain(&sprd_eic_irq_notifier, 0, NULL); chained_irq_exit(ic, desc); } +static int sprd_eic_irq_notify(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct sprd_eic *sprd_eic = to_sprd_eic(nb); + + sprd_eic_handle_one_type(&sprd_eic->chip); + + return NOTIFY_OK; +} + static const struct irq_chip sprd_eic_irq = { .name = "sprd-eic", .irq_ack = sprd_eic_irq_ack, @@ -576,21 +580,30 @@ static const struct irq_chip sprd_eic_irq = { .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, GPIOCHIP_IRQ_RESOURCE_HELPERS, }; + +static void sprd_eic_unregister_notifier(void *data) +{ + struct notifier_block *nb = data; + + atomic_notifier_chain_unregister(&sprd_eic_irq_notifier, nb); +} + static int sprd_eic_probe(struct platform_device *pdev) { const struct sprd_eic_variant_data *pdata; + struct device *dev = &pdev->dev; struct gpio_irq_chip *irq; struct sprd_eic *sprd_eic; struct resource *res; int ret, i; - pdata = of_device_get_match_data(&pdev->dev); + pdata = of_device_get_match_data(dev); if (!pdata) { - dev_err(&pdev->dev, "No matching driver data found.\n"); + dev_err(dev, "No matching driver data found.\n"); return -EINVAL; } - sprd_eic = devm_kzalloc(&pdev->dev, sizeof(*sprd_eic), GFP_KERNEL); + sprd_eic = devm_kzalloc(dev, sizeof(*sprd_eic), GFP_KERNEL); if (!sprd_eic) return -ENOMEM; @@ -612,7 +625,7 @@ static int sprd_eic_probe(struct platform_device *pdev) if (!res) break; - sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res); + sprd_eic->base[i] = devm_ioremap_resource(dev, res); if (IS_ERR(sprd_eic->base[i])) return PTR_ERR(sprd_eic->base[i]); } @@ -620,7 +633,7 @@ static int sprd_eic_probe(struct platform_device *pdev) sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type]; sprd_eic->chip.ngpio = pdata->num_eics; sprd_eic->chip.base = -1; - sprd_eic->chip.parent = &pdev->dev; + sprd_eic->chip.parent = dev; sprd_eic->chip.direction_input = sprd_eic_direction_input; switch (sprd_eic->type) { case SPRD_EIC_DEBOUNCE: @@ -647,13 +660,21 @@ static int sprd_eic_probe(struct platform_device *pdev) irq->num_parents = 1; irq->parents = &sprd_eic->irq; - ret = devm_gpiochip_add_data(&pdev->dev, &sprd_eic->chip, sprd_eic); + ret = devm_gpiochip_add_data(dev, &sprd_eic->chip, sprd_eic); if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret); + dev_err(dev, "Could not register gpiochip %d.\n", ret); return ret; } - return 0; + sprd_eic->irq_nb.notifier_call = sprd_eic_irq_notify; + ret = atomic_notifier_chain_register(&sprd_eic_irq_notifier, + &sprd_eic->irq_nb); + if (ret) + return dev_err_probe(dev, ret, + "Failed to register with the interrupt notifier"); + + return devm_add_action_or_reset(dev, sprd_eic_unregister_notifier, + &sprd_eic->irq_nb); } static const struct of_device_id sprd_eic_of_match[] = { diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index f54ca5a1775e..3875fd940ccb 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -163,7 +163,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, unsigned long config); -#define F7188X_GPIO_BANK(_base, _ngpio, _regbase, _label) \ +#define F7188X_GPIO_BANK(_ngpio, _regbase, _label) \ { \ .chip = { \ .label = _label, \ @@ -174,7 +174,7 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, .direction_output = f7188x_gpio_direction_out, \ .set = f7188x_gpio_set, \ .set_config = f7188x_gpio_set_config, \ - .base = _base, \ + .base = -1, \ .ngpio = _ngpio, \ .can_sleep = true, \ }, \ @@ -191,98 +191,98 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, #define f7188x_gpio_data_single(type) ((type) == nct6126d) static struct f7188x_gpio_bank f71869_gpio_bank[] = { - F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 6, 0x90, DRVNAME "-6"), + F7188X_GPIO_BANK(6, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"), + F7188X_GPIO_BANK(6, 0x90, DRVNAME "-6"), }; static struct f7188x_gpio_bank f71869a_gpio_bank[] = { - F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"), - F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"), + F7188X_GPIO_BANK(6, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"), + F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"), }; static struct f7188x_gpio_bank f71882_gpio_bank[] = { - F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 4, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 4, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(4, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(4, 0xB0, DRVNAME "-4"), }; static struct f7188x_gpio_bank f71889a_gpio_bank[] = { - F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"), - F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"), + F7188X_GPIO_BANK(7, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(7, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"), + F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"), }; static struct f7188x_gpio_bank f71889_gpio_bank[] = { - F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"), - F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"), + F7188X_GPIO_BANK(7, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(7, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"), + F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"), }; static struct f7188x_gpio_bank f81866_gpio_bank[] = { - F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"), - F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"), - F7188X_GPIO_BANK(80, 8, 0x88, DRVNAME "-8"), + F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-5"), + F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"), + F7188X_GPIO_BANK(8, 0x88, DRVNAME "-8"), }; static struct f7188x_gpio_bank f81804_gpio_bank[] = { - F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-3"), - F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-4"), - F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-5"), - F7188X_GPIO_BANK(90, 8, 0x98, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0x90, DRVNAME "-4"), + F7188X_GPIO_BANK(8, 0x80, DRVNAME "-5"), + F7188X_GPIO_BANK(8, 0x98, DRVNAME "-6"), }; static struct f7188x_gpio_bank f81865_gpio_bank[] = { - F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"), + F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-5"), + F7188X_GPIO_BANK(5, 0x90, DRVNAME "-6"), }; static struct f7188x_gpio_bank nct6126d_gpio_bank[] = { - F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"), - F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"), - F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"), - F7188X_GPIO_BANK(30, 8, 0xEC, DRVNAME "-3"), - F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"), - F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"), - F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"), - F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"), + F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-0"), + F7188X_GPIO_BANK(8, 0xE4, DRVNAME "-1"), + F7188X_GPIO_BANK(8, 0xE8, DRVNAME "-2"), + F7188X_GPIO_BANK(8, 0xEC, DRVNAME "-3"), + F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-4"), + F7188X_GPIO_BANK(8, 0xF4, DRVNAME "-5"), + F7188X_GPIO_BANK(8, 0xF8, DRVNAME "-6"), + F7188X_GPIO_BANK(8, 0xFC, DRVNAME "-7"), }; static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 5ce59dcf02e3..97d345b59352 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -324,13 +324,11 @@ dis_clk: return ret; } -static int ftgpio_gpio_remove(struct platform_device *pdev) +static void ftgpio_gpio_remove(struct platform_device *pdev) { struct ftgpio_gpio *g = platform_get_drvdata(pdev); clk_disable_unprepare(g->clk); - - return 0; } static const struct of_device_id ftgpio_gpio_of_match[] = { @@ -352,6 +350,6 @@ static struct platform_driver ftgpio_gpio_driver = { .of_match_table = ftgpio_gpio_of_match, }, .probe = ftgpio_gpio_probe, - .remove = ftgpio_gpio_remove, + .remove_new = ftgpio_gpio_remove, }; builtin_platform_driver(ftgpio_gpio_driver); diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c index c14b5cc5e519..991549888904 100644 --- a/drivers/gpio/gpio-fxl6408.c +++ b/drivers/gpio/gpio-fxl6408.c @@ -84,7 +84,7 @@ static const struct regmap_config regmap = { .rd_table = &rd_table, .volatile_table = &volatile_table, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .num_reg_defaults_raw = FXL6408_REG_INT_STS + 1, }; diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 0163c95f6dd7..017c7170eb57 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -431,7 +431,7 @@ static int grgpio_probe(struct platform_device *ofdev) return 0; } -static int grgpio_remove(struct platform_device *ofdev) +static void grgpio_remove(struct platform_device *ofdev) { struct grgpio_priv *priv = platform_get_drvdata(ofdev); @@ -439,8 +439,6 @@ static int grgpio_remove(struct platform_device *ofdev) if (priv->domain) irq_domain_remove(priv->domain); - - return 0; } static const struct of_device_id grgpio_match[] = { @@ -457,7 +455,7 @@ static struct platform_driver grgpio_driver = { .of_match_table = grgpio_match, }, .probe = grgpio_probe, - .remove = grgpio_remove, + .remove_new = grgpio_remove, }; module_platform_driver(grgpio_driver); diff --git a/drivers/gpio/gpio-hisi.c b/drivers/gpio/gpio-hisi.c index 29a03de37fd8..ef5cc654a24e 100644 --- a/drivers/gpio/gpio-hisi.c +++ b/drivers/gpio/gpio-hisi.c @@ -255,7 +255,7 @@ static void hisi_gpio_get_pdata(struct device *dev, hisi_gpio->irq = platform_get_irq(pdev, idx); dev_info(dev, - "get hisi_gpio[%d] with %d lines\n", idx, + "get hisi_gpio[%d] with %u lines\n", idx, hisi_gpio->line_num); idx++; diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c index 87863f0230f5..aca69329455f 100644 --- a/drivers/gpio/gpio-ljca.c +++ b/drivers/gpio/gpio-ljca.c @@ -421,7 +421,7 @@ static int ljca_gpio_probe(struct platform_device *pdev) return ret; } -static int ljca_gpio_remove(struct platform_device *pdev) +static void ljca_gpio_remove(struct platform_device *pdev) { struct ljca_gpio_dev *ljca_gpio = platform_get_drvdata(pdev); @@ -429,7 +429,6 @@ static int ljca_gpio_remove(struct platform_device *pdev) ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca); mutex_destroy(&ljca_gpio->irq_lock); mutex_destroy(&ljca_gpio->trans_lock); - return 0; } #define LJCA_GPIO_DRV_NAME "ljca-gpio" @@ -442,7 +441,7 @@ MODULE_DEVICE_TABLE(platform, ljca_gpio_id); static struct platform_driver ljca_gpio_driver = { .driver.name = LJCA_GPIO_DRV_NAME, .probe = ljca_gpio_probe, - .remove = ljca_gpio_remove, + .remove_new = ljca_gpio_remove, }; module_platform_driver(ljca_gpio_driver); diff --git a/drivers/gpio/gpio-loongson-64bit.c b/drivers/gpio/gpio-loongson-64bit.c index 06213bbfabdd..6749d4dd6d64 100644 --- a/drivers/gpio/gpio-loongson-64bit.c +++ b/drivers/gpio/gpio-loongson-64bit.c @@ -26,6 +26,7 @@ struct loongson_gpio_chip_data { unsigned int conf_offset; unsigned int out_offset; unsigned int in_offset; + unsigned int inten_offset; }; struct loongson_gpio_chip { @@ -117,19 +118,29 @@ static void loongson_gpio_set(struct gpio_chip *chip, unsigned int pin, int valu static int loongson_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) { + unsigned int u; struct platform_device *pdev = to_platform_device(chip->parent); + struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip); + + if (lgpio->chip_data->mode == BIT_CTRL_MODE) { + /* Get the register index from offset then multiply by bytes per register */ + u = readl(lgpio->reg_base + lgpio->chip_data->inten_offset + (offset / 32) * 4); + u |= BIT(offset % 32); + writel(u, lgpio->reg_base + lgpio->chip_data->inten_offset + (offset / 32) * 4); + } else { + writeb(1, lgpio->reg_base + lgpio->chip_data->inten_offset + offset); + } return platform_get_irq(pdev, offset); } static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgpio, - struct device_node *np, void __iomem *reg_base) + void __iomem *reg_base) { int ret; u32 ngpios; lgpio->reg_base = reg_base; - if (lgpio->chip_data->mode == BIT_CTRL_MODE) { ret = bgpio_init(&lgpio->chip, dev, 8, lgpio->reg_base + lgpio->chip_data->in_offset, @@ -148,15 +159,15 @@ static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgp lgpio->chip.direction_output = loongson_gpio_direction_output; lgpio->chip.set = loongson_gpio_set; lgpio->chip.parent = dev; + device_property_read_u32(dev, "ngpios", &ngpios); + lgpio->chip.ngpio = ngpios; spin_lock_init(&lgpio->lock); } - device_property_read_u32(dev, "ngpios", &ngpios); - - lgpio->chip.can_sleep = 0; - lgpio->chip.ngpio = ngpios; lgpio->chip.label = lgpio->chip_data->label; - lgpio->chip.to_irq = loongson_gpio_to_irq; + lgpio->chip.can_sleep = false; + if (lgpio->chip_data->inten_offset) + lgpio->chip.to_irq = loongson_gpio_to_irq; return devm_gpiochip_add_data(dev, &lgpio->chip, lgpio); } @@ -165,7 +176,6 @@ static int loongson_gpio_probe(struct platform_device *pdev) { void __iomem *reg_base; struct loongson_gpio_chip *lgpio; - struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; lgpio = devm_kzalloc(dev, sizeof(*lgpio), GFP_KERNEL); @@ -178,7 +188,7 @@ static int loongson_gpio_probe(struct platform_device *pdev) if (IS_ERR(reg_base)) return PTR_ERR(reg_base); - return loongson_gpio_init(dev, lgpio, np, reg_base); + return loongson_gpio_init(dev, lgpio, reg_base); } static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = { @@ -187,6 +197,57 @@ static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = { .conf_offset = 0x0, .in_offset = 0x20, .out_offset = 0x10, + .inten_offset = 0x30, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls2k0500_data0 = { + .label = "ls2k0500_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x0, + .in_offset = 0x8, + .out_offset = 0x10, + .inten_offset = 0xb0, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls2k0500_data1 = { + .label = "ls2k0500_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x0, + .in_offset = 0x8, + .out_offset = 0x10, + .inten_offset = 0x98, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data0 = { + .label = "ls2k2000_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x0, + .in_offset = 0xc, + .out_offset = 0x8, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data1 = { + .label = "ls2k2000_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x0, + .in_offset = 0x20, + .out_offset = 0x10, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data2 = { + .label = "ls2k2000_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x84, + .in_offset = 0x88, + .out_offset = 0x80, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls3a5000_data = { + .label = "ls3a5000_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x0, + .in_offset = 0xc, + .out_offset = 0x8, }; static const struct loongson_gpio_chip_data loongson_gpio_ls7a_data = { @@ -202,6 +263,30 @@ static const struct of_device_id loongson_gpio_of_match[] = { .compatible = "loongson,ls2k-gpio", .data = &loongson_gpio_ls2k_data, }, + { + .compatible = "loongson,ls2k0500-gpio0", + .data = &loongson_gpio_ls2k0500_data0, + }, + { + .compatible = "loongson,ls2k0500-gpio1", + .data = &loongson_gpio_ls2k0500_data1, + }, + { + .compatible = "loongson,ls2k2000-gpio0", + .data = &loongson_gpio_ls2k2000_data0, + }, + { + .compatible = "loongson,ls2k2000-gpio1", + .data = &loongson_gpio_ls2k2000_data1, + }, + { + .compatible = "loongson,ls2k2000-gpio2", + .data = &loongson_gpio_ls2k2000_data2, + }, + { + .compatible = "loongson,ls3a5000-gpio", + .data = &loongson_gpio_ls3a5000_data, + }, { .compatible = "loongson,ls7a-gpio", .data = &loongson_gpio_ls7a_data, @@ -215,6 +300,22 @@ static const struct acpi_device_id loongson_gpio_acpi_match[] = { .id = "LOON0002", .driver_data = (kernel_ulong_t)&loongson_gpio_ls7a_data, }, + { + .id = "LOON0007", + .driver_data = (kernel_ulong_t)&loongson_gpio_ls3a5000_data, + }, + { + .id = "LOON000A", + .driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data0, + }, + { + .id = "LOON000B", + .driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data1, + }, + { + .id = "LOON000C", + .driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data2, + }, {} }; MODULE_DEVICE_TABLE(acpi, loongson_gpio_acpi_match); diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index ed3f653a1dfc..5c6bb57a8c99 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -381,7 +381,7 @@ static int lpc18xx_gpio_probe(struct platform_device *pdev) return 0; } -static int lpc18xx_gpio_remove(struct platform_device *pdev) +static void lpc18xx_gpio_remove(struct platform_device *pdev) { struct lpc18xx_gpio_chip *gc = platform_get_drvdata(pdev); @@ -389,8 +389,6 @@ static int lpc18xx_gpio_remove(struct platform_device *pdev) irq_domain_remove(gc->pin_ic->domain); clk_disable_unprepare(gc->clk); - - return 0; } static const struct of_device_id lpc18xx_gpio_match[] = { @@ -401,7 +399,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_gpio_match); static struct platform_driver lpc18xx_gpio_driver = { .probe = lpc18xx_gpio_probe, - .remove = lpc18xx_gpio_remove, + .remove_new = lpc18xx_gpio_remove, .driver = { .name = "lpc18xx-gpio", .of_match_table = lpc18xx_gpio_match, diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index ca7eb5e8bfaa..7fb298b4571b 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -20,7 +20,6 @@ #include #include -#include "gpiolib.h" #include "gpiolib-acpi.h" /* @@ -205,15 +204,13 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) return 0; } -static int mb86s70_gpio_remove(struct platform_device *pdev) +static void mb86s70_gpio_remove(struct platform_device *pdev) { struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev); acpi_gpiochip_free_interrupts(&gchip->gc); gpiochip_remove(&gchip->gc); clk_disable_unprepare(gchip->clk); - - return 0; } static const struct of_device_id mb86s70_gpio_dt_ids[] = { @@ -237,7 +234,7 @@ static struct platform_driver mb86s70_gpio_driver = { .acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids), }, .probe = mb86s70_gpio_probe, - .remove = mb86s70_gpio_remove, + .remove_new = mb86s70_gpio_remove, }; module_platform_driver(mb86s70_gpio_driver); diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index f3c158259636..e855c68c981b 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -121,13 +121,11 @@ static int ltq_mm_probe(struct platform_device *pdev) return of_mm_gpiochip_add_data(pdev->dev.of_node, &chip->mmchip, chip); } -static int ltq_mm_remove(struct platform_device *pdev) +static void ltq_mm_remove(struct platform_device *pdev) { struct ltq_mm *chip = platform_get_drvdata(pdev); of_mm_gpiochip_remove(&chip->mmchip); - - return 0; } static const struct of_device_id ltq_mm_match[] = { @@ -138,7 +136,7 @@ MODULE_DEVICE_TABLE(of, ltq_mm_match); static struct platform_driver ltq_mm_driver = { .probe = ltq_mm_probe, - .remove = ltq_mm_remove, + .remove_new = ltq_mm_remove, .driver = { .name = "gpio-mm-ltq", .of_match_table = ltq_mm_match, diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 74fdf0d87b2c..3ff0ea1e351c 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -56,9 +56,9 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` #include #include #include +#include #include #include -#include #include "gpiolib.h" @@ -702,7 +702,7 @@ static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev, { struct bgpio_pdata *pdata; - if (!of_match_device(bgpio_of_match, &pdev->dev)) + if (!pdev->dev.of_node) return NULL; pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata), diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index b32063ac845a..4870e267a402 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -9,7 +9,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include +#include #include #include #include @@ -24,8 +26,6 @@ #include #include -#include "gpiolib.h" - #define GPIO_MOCKUP_MAX_GC 10 /* * We're storing two values per chip: the GPIO base and the number @@ -39,11 +39,15 @@ * struct gpio_pin_status - structure describing a GPIO status * @dir: Configures direction of gpio as "in" or "out" * @value: Configures status of the gpio as 0(low) or 1(high) + * @pull: Configures the current pull of the GPIO as 0 (pull-down) or + * 1 (pull-up) + * @requested: Request status of this GPIO */ struct gpio_mockup_line_status { int dir; int value; int pull; + bool requested; }; struct gpio_mockup_chip { @@ -56,7 +60,6 @@ struct gpio_mockup_chip { struct gpio_mockup_dbgfs_private { struct gpio_mockup_chip *chip; - struct gpio_desc *desc; unsigned int offset; }; @@ -91,9 +94,8 @@ static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) struct gpio_mockup_chip *chip = gpiochip_get_data(gc); int val; - mutex_lock(&chip->lock); - val = __gpio_mockup_get(chip, offset); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + val = __gpio_mockup_get(chip, offset); return val; } @@ -104,12 +106,12 @@ static int gpio_mockup_get_multiple(struct gpio_chip *gc, struct gpio_mockup_chip *chip = gpiochip_get_data(gc); unsigned int bit, val; - mutex_lock(&chip->lock); - for_each_set_bit(bit, mask, gc->ngpio) { - val = __gpio_mockup_get(chip, bit); - __assign_bit(bit, bits, val); + scoped_guard(mutex, &chip->lock) { + for_each_set_bit(bit, mask, gc->ngpio) { + val = __gpio_mockup_get(chip, bit); + __assign_bit(bit, bits, val); + } } - mutex_unlock(&chip->lock); return 0; } @@ -125,9 +127,9 @@ static void gpio_mockup_set(struct gpio_chip *gc, { struct gpio_mockup_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); + __gpio_mockup_set(chip, offset, value); - mutex_unlock(&chip->lock); } static void gpio_mockup_set_multiple(struct gpio_chip *gc, @@ -136,23 +138,21 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, struct gpio_mockup_chip *chip = gpiochip_get_data(gc); unsigned int bit; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); + for_each_set_bit(bit, mask, gc->ngpio) __gpio_mockup_set(chip, bit, test_bit(bit, bits)); - mutex_unlock(&chip->lock); } static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, unsigned int offset, int value) { - struct gpio_chip *gc = &chip->gc; - struct gpio_desc *desc = gpiochip_get_desc(gc, offset); + struct gpio_mockup_line_status *line = &chip->lines[offset]; int curr, irq, irq_type, ret = 0; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); - if (test_bit(FLAG_REQUESTED, &desc->flags) && - !test_bit(FLAG_IS_OUT, &desc->flags)) { + if (line->requested && line->dir == GPIO_LINE_DIRECTION_IN) { curr = __gpio_mockup_get(chip, offset); if (curr == value) goto out; @@ -180,13 +180,11 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, set_value: /* Change the value unless we're actively driving the line. */ - if (!test_bit(FLAG_REQUESTED, &desc->flags) || - !test_bit(FLAG_IS_OUT, &desc->flags)) + if (!line->requested || line->dir == GPIO_LINE_DIRECTION_IN) __gpio_mockup_set(chip, offset, value); out: chip->lines[offset].pull = value; - mutex_unlock(&chip->lock); return ret; } @@ -211,10 +209,10 @@ static int gpio_mockup_dirout(struct gpio_chip *gc, { struct gpio_mockup_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT; - __gpio_mockup_set(chip, offset, value); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) { + chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT; + __gpio_mockup_set(chip, offset, value); + } return 0; } @@ -223,9 +221,8 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset) { struct gpio_mockup_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN; - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN; return 0; } @@ -235,9 +232,8 @@ static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset) struct gpio_mockup_chip *chip = gpiochip_get_data(gc); int direction; - mutex_lock(&chip->lock); - direction = chip->lines[offset].dir; - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + direction = chip->lines[offset].dir; return direction; } @@ -249,10 +245,23 @@ static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) return irq_create_mapping(chip->irq_sim_domain, offset); } +static int gpio_mockup_request(struct gpio_chip *gc, unsigned int offset) +{ + struct gpio_mockup_chip *chip = gpiochip_get_data(gc); + + scoped_guard(mutex, &chip->lock) + chip->lines[offset].requested = true; + + return 0; +} + static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset) { struct gpio_mockup_chip *chip = gpiochip_get_data(gc); + guard(mutex)(&chip->lock); + + chip->lines[offset].requested = false; __gpio_mockup_set(chip, offset, chip->lines[offset].pull); } @@ -345,6 +354,7 @@ static const struct file_operations gpio_mockup_debugfs_ops = { static void gpio_mockup_debugfs_setup(struct device *dev, struct gpio_mockup_chip *chip) { + struct device *child __free(put_device) = NULL; struct gpio_mockup_dbgfs_private *priv; struct gpio_chip *gc; const char *devname; @@ -352,8 +362,16 @@ static void gpio_mockup_debugfs_setup(struct device *dev, int i; gc = &chip->gc; - devname = dev_name(&gc->gpiodev->dev); + /* + * There can only be a single GPIO device per platform device in + * gpio-mockup so using device_find_any_child() is OK. + */ + child = device_find_any_child(dev); + if (!child) + return; + + devname = dev_name(child); chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir); for (i = 0; i < gc->ngpio; i++) { @@ -367,7 +385,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev, priv->chip = chip; priv->offset = i; - priv->desc = gpiochip_get_desc(gc, i); debugfs_create_file(name, 0600, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); @@ -438,6 +455,7 @@ static int gpio_mockup_probe(struct platform_device *pdev) gc->get_direction = gpio_mockup_get_direction; gc->set_config = gpio_mockup_set_config; gc->to_irq = gpio_mockup_to_irq; + gc->request = gpio_mockup_request; gc->free = gpio_mockup_free; chip->lines = devm_kcalloc(dev, gc->ngpio, diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c index b49e3ca64015..a199dce3394a 100644 --- a/drivers/gpio/gpio-mpc5200.c +++ b/drivers/gpio/gpio-mpc5200.c @@ -165,13 +165,11 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) return 0; } -static int mpc52xx_gpiochip_remove(struct platform_device *ofdev) +static void mpc52xx_gpiochip_remove(struct platform_device *ofdev) { struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev); of_mm_gpiochip_remove(&chip->mmchip); - - return 0; } static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { @@ -185,7 +183,7 @@ static struct platform_driver mpc52xx_wkup_gpiochip_driver = { .of_match_table = mpc52xx_wkup_gpiochip_match, }, .probe = mpc52xx_wkup_gpiochip_probe, - .remove = mpc52xx_gpiochip_remove, + .remove_new = mpc52xx_gpiochip_remove, }; /* @@ -338,7 +336,7 @@ static struct platform_driver mpc52xx_simple_gpiochip_driver = { .of_match_table = mpc52xx_simple_gpiochip_match, }, .probe = mpc52xx_simple_gpiochip_probe, - .remove = mpc52xx_gpiochip_remove, + .remove_new = mpc52xx_gpiochip_remove, }; static struct platform_driver * const drivers[] = { diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index ebf2f511df59..c0125ac73906 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -419,7 +419,7 @@ err: return ret; } -static int mpc8xxx_remove(struct platform_device *pdev) +static void mpc8xxx_remove(struct platform_device *pdev) { struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev); @@ -427,8 +427,6 @@ static int mpc8xxx_remove(struct platform_device *pdev) irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, NULL, NULL); irq_domain_remove(mpc8xxx_gc->irq); } - - return 0; } #ifdef CONFIG_ACPI @@ -441,7 +439,7 @@ MODULE_DEVICE_TABLE(acpi, gpio_acpi_ids); static struct platform_driver mpc8xxx_plat_driver = { .probe = mpc8xxx_probe, - .remove = mpc8xxx_remove, + .remove_new = mpc8xxx_remove, .driver = { .name = "gpio-mpc8xxx", .of_match_table = mpc8xxx_gpio_ids, diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 67497116ce27..8f80ca8ec1ed 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -42,9 +42,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -1122,7 +1123,6 @@ static void mvebu_gpio_remove_irq_domain(void *data) static int mvebu_gpio_probe(struct platform_device *pdev) { struct mvebu_gpio_chip *mvchip; - const struct of_device_id *match; struct device_node *np = pdev->dev.of_node; struct irq_chip_generic *gc; struct irq_chip_type *ct; @@ -1132,11 +1132,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) int i, cpu, id; int err; - match = of_match_device(mvebu_gpio_of_match, &pdev->dev); - if (match) - soc_variant = (unsigned long) match->data; - else - soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; + soc_variant = (unsigned long)device_get_match_data(&pdev->dev); /* Some gpio controllers do not provide irq support */ err = platform_irq_count(pdev); diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a927680c66f8..76d5d87e9681 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1048,15 +1048,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct device *pm_dev) bank->chip.label = "mpuio"; if (bank->regs->wkup_en) bank->chip.parent = &omap_mpuio_device.dev; - bank->chip.base = OMAP_MPUIO(0); } else { label = devm_kasprintf(bank->chip.parent, GFP_KERNEL, "gpio-%d-%d", gpio, gpio + bank->width - 1); if (!label) return -ENOMEM; bank->chip.label = label; - bank->chip.base = -1; } + bank->chip.base = -1; bank->chip.ngpio = bank->width; irq = &bank->chip.irq; @@ -1489,7 +1488,7 @@ static int omap_gpio_probe(struct platform_device *pdev) return 0; } -static int omap_gpio_remove(struct platform_device *pdev) +static void omap_gpio_remove(struct platform_device *pdev) { struct gpio_bank *bank = platform_get_drvdata(pdev); @@ -1498,8 +1497,6 @@ static int omap_gpio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (bank->dbck_flag) clk_unprepare(bank->dbck); - - return 0; } static int __maybe_unused omap_gpio_runtime_suspend(struct device *dev) @@ -1560,7 +1557,7 @@ static const struct dev_pm_ops gpio_pm_ops = { static struct platform_driver omap_gpio_driver = { .probe = omap_gpio_probe, - .remove = omap_gpio_remove, + .remove_new = omap_gpio_remove, .driver = { .name = "omap_gpio", .pm = &gpio_pm_ops, diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index bdd50a78e414..00ffa168e405 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -8,22 +8,30 @@ * Derived from drivers/i2c/chips/pca9539.c */ -#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 PCA953X_INPUT 0x00 #define PCA953X_OUTPUT 0x01 @@ -118,6 +126,7 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id); #ifdef CONFIG_GPIO_PCA953X_IRQ +#include #include static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true }; @@ -211,7 +220,6 @@ struct pca953x_chip { struct i2c_client *client; struct gpio_chip gpio_chip; - const char *const *names; unsigned long driver_data; struct regulator *regulator; @@ -414,7 +422,7 @@ static const struct regmap_config pca953x_i2c_regmap = { .volatile_reg = pca953x_volatile_register, .disable_locking = true, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 0x7f, }; @@ -430,7 +438,7 @@ static const struct regmap_config pca953x_ai_i2c_regmap = { .volatile_reg = pca953x_volatile_register, .disable_locking = true, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 0x7f, }; @@ -520,12 +528,10 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) struct pca953x_chip *chip = gpiochip_get_data(gc); u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off); u8 bit = BIT(off % BANK_SZ); - int ret; - mutex_lock(&chip->i2c_lock); - ret = regmap_write_bits(chip->regmap, dirreg, bit, bit); - mutex_unlock(&chip->i2c_lock); - return ret; + guard(mutex)(&chip->i2c_lock); + + return regmap_write_bits(chip->regmap, dirreg, bit, bit); } static int pca953x_gpio_direction_output(struct gpio_chip *gc, @@ -537,17 +543,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, u8 bit = BIT(off % BANK_SZ); int ret; - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); + /* set output level */ ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); if (ret) - goto exit; + return ret; /* then direction */ - ret = regmap_write_bits(chip->regmap, dirreg, bit, 0); -exit: - mutex_unlock(&chip->i2c_lock); - return ret; + return regmap_write_bits(chip->regmap, dirreg, bit, 0); } static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) @@ -558,9 +562,8 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) u32 reg_val; int ret; - mutex_lock(&chip->i2c_lock); - ret = regmap_read(chip->regmap, inreg, ®_val); - mutex_unlock(&chip->i2c_lock); + scoped_guard(mutex, &chip->i2c_lock) + ret = regmap_read(chip->regmap, inreg, ®_val); if (ret < 0) return ret; @@ -573,9 +576,9 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) u8 outreg = chip->recalc_addr(chip, chip->regs->output, off); u8 bit = BIT(off % BANK_SZ); - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); + regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); - mutex_unlock(&chip->i2c_lock); } static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) @@ -586,9 +589,8 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) u32 reg_val; int ret; - mutex_lock(&chip->i2c_lock); - ret = regmap_read(chip->regmap, dirreg, ®_val); - mutex_unlock(&chip->i2c_lock); + scoped_guard(mutex, &chip->i2c_lock) + ret = regmap_read(chip->regmap, dirreg, ®_val); if (ret < 0) return ret; @@ -605,9 +607,8 @@ static int pca953x_gpio_get_multiple(struct gpio_chip *gc, DECLARE_BITMAP(reg_val, MAX_LINE); int ret; - mutex_lock(&chip->i2c_lock); - ret = pca953x_read_regs(chip, chip->regs->input, reg_val); - mutex_unlock(&chip->i2c_lock); + scoped_guard(mutex, &chip->i2c_lock) + ret = pca953x_read_regs(chip, chip->regs->input, reg_val); if (ret) return ret; @@ -622,16 +623,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, DECLARE_BITMAP(reg_val, MAX_LINE); int ret; - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); + ret = pca953x_read_regs(chip, chip->regs->output, reg_val); if (ret) - goto exit; + return; bitmap_replace(reg_val, reg_val, bits, mask, gc->ngpio); pca953x_write_regs(chip, chip->regs->output, reg_val); -exit: - mutex_unlock(&chip->i2c_lock); } static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, @@ -639,7 +639,6 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, unsigned long config) { enum pin_config_param param = pinconf_to_config_param(config); - u8 pull_en_reg = chip->recalc_addr(chip, PCAL953X_PULL_EN, offset); u8 pull_sel_reg = chip->recalc_addr(chip, PCAL953X_PULL_SEL, offset); u8 bit = BIT(offset % BANK_SZ); @@ -652,7 +651,7 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, if (!(chip->driver_data & PCA_PCAL)) return -ENOTSUPP; - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); /* Configure pull-up/pull-down */ if (param == PIN_CONFIG_BIAS_PULL_UP) @@ -662,17 +661,13 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, else ret = 0; if (ret) - goto exit; + return ret; /* Disable/Enable pull-up/pull-down */ if (param == PIN_CONFIG_BIAS_DISABLE) - ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); + return regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); else - ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); - -exit: - mutex_unlock(&chip->i2c_lock); - return ret; + return regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); } static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, @@ -693,9 +688,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) { - struct gpio_chip *gc; - - gc = &chip->gpio_chip; + struct gpio_chip *gc = &chip->gpio_chip; gc->direction_input = pca953x_gpio_direction_input; gc->direction_output = pca953x_gpio_direction_output; @@ -712,7 +705,6 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) gc->label = dev_name(&chip->client->dev); gc->parent = &chip->client->dev; gc->owner = THIS_MODULE; - gc->names = chip->names; } #ifdef CONFIG_GPIO_PCA953X_IRQ @@ -793,11 +785,11 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); + struct device *dev = &chip->client->dev; irq_hw_number_t hwirq = irqd_to_hwirq(d); if (!(type & IRQ_TYPE_EDGE_BOTH)) { - dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", - d->irq, type); + dev_err(dev, "irq %d: unsupported type %d\n", d->irq, type); return -EINVAL; } @@ -902,10 +894,8 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) bitmap_zero(pending, MAX_LINE); - mutex_lock(&chip->i2c_lock); - ret = pca953x_irq_pending(chip, pending); - mutex_unlock(&chip->i2c_lock); - + scoped_guard(mutex, &chip->i2c_lock) + ret = pca953x_irq_pending(chip, pending); if (ret) { ret = 0; @@ -928,13 +918,15 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; + struct device *dev = &client->dev; DECLARE_BITMAP(reg_direction, MAX_LINE); DECLARE_BITMAP(irq_stat, MAX_LINE); + struct gpio_chip *gc = &chip->gpio_chip; struct gpio_irq_chip *girq; int ret; if (dmi_first_match(pca953x_dmi_acpi_irq_info)) { - ret = pca953x_acpi_get_irq(&client->dev); + ret = pca953x_acpi_get_irq(dev); if (ret > 0) client->irq = ret; } @@ -958,7 +950,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) * this purpose. */ pca953x_read_regs(chip, chip->regs->direction, reg_direction); - bitmap_and(chip->irq_stat, irq_stat, reg_direction, chip->gpio_chip.ngpio); + bitmap_and(chip->irq_stat, irq_stat, reg_direction, gc->ngpio); mutex_init(&chip->irq_lock); girq = &chip->gpio_chip.irq; @@ -972,33 +964,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) girq->threaded = true; girq->first = irq_base; /* FIXME: get rid of this */ - ret = devm_request_threaded_irq(&client->dev, client->irq, - NULL, pca953x_irq_handler, - IRQF_ONESHOT | IRQF_SHARED, - dev_name(&client->dev), chip); - if (ret) { - dev_err(&client->dev, "failed to request irq %d\n", - client->irq); - return ret; - } + ret = devm_request_threaded_irq(dev, client->irq, NULL, pca953x_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), + chip); + if (ret) + return dev_err_probe(dev, client->irq, "failed to request irq\n"); return 0; } #else /* CONFIG_GPIO_PCA953X_IRQ */ -static int pca953x_irq_setup(struct pca953x_chip *chip, - int irq_base) +static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; + struct device *dev = &client->dev; if (client->irq && irq_base != -1 && (chip->driver_data & PCA_INT)) - dev_warn(&client->dev, "interrupt support not compiled in\n"); + dev_warn(dev, "interrupt support not compiled in\n"); return 0; } #endif -static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) +static int device_pca95xx_init(struct pca953x_chip *chip) { DECLARE_BITMAP(val, MAX_LINE); u8 regaddr; @@ -1008,68 +996,81 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1); if (ret) - goto out; + return ret; regaddr = chip->recalc_addr(chip, chip->regs->direction, 0); ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1); if (ret) - goto out; + return ret; - /* set platform specific polarity inversion */ - if (invert) - bitmap_fill(val, MAX_LINE); - else - bitmap_zero(val, MAX_LINE); + /* clear polarity inversion */ + bitmap_zero(val, MAX_LINE); - ret = pca953x_write_regs(chip, chip->regs->invert, val); -out: - return ret; + return pca953x_write_regs(chip, chip->regs->invert, val); } -static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) +static int device_pca957x_init(struct pca953x_chip *chip) { DECLARE_BITMAP(val, MAX_LINE); unsigned int i; int ret; - ret = device_pca95xx_init(chip, invert); + ret = device_pca95xx_init(chip); if (ret) - goto out; + return ret; /* To enable register 6, 7 to control pull up and pull down */ for (i = 0; i < NBANK(chip); i++) bitmap_set_value8(val, 0x02, i * BANK_SZ); - ret = pca953x_write_regs(chip, PCA957X_BKEN, val); - if (ret) - goto out; + return pca953x_write_regs(chip, PCA957X_BKEN, val); +} +static void pca953x_disable_regulator(void *reg) +{ + regulator_disable(reg); +} + +static int pca953x_get_and_enable_regulator(struct pca953x_chip *chip) +{ + struct device *dev = &chip->client->dev; + struct regulator *reg = chip->regulator; + int ret; + + reg = devm_regulator_get(dev, "vcc"); + if (IS_ERR(reg)) + return dev_err_probe(dev, PTR_ERR(reg), "reg get err\n"); + + ret = regulator_enable(reg); + if (ret) + return dev_err_probe(dev, ret, "reg en err\n"); + + ret = devm_add_action_or_reset(dev, pca953x_disable_regulator, reg); + if (ret) + return ret; + + chip->regulator = reg; return 0; -out: - return ret; } static int pca953x_probe(struct i2c_client *client) { + struct device *dev = &client->dev; struct pca953x_platform_data *pdata; struct pca953x_chip *chip; - int irq_base = 0; + int irq_base; int ret; - u32 invert = 0; - struct regulator *reg; const struct regmap_config *regmap_config; - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; - pdata = dev_get_platdata(&client->dev); + pdata = dev_get_platdata(dev); if (pdata) { irq_base = pdata->irq_base; chip->gpio_start = pdata->gpio_base; - invert = pdata->invert; - chip->names = pdata->names; } else { struct gpio_desc *reset_gpio; @@ -1083,8 +1084,7 @@ static int pca953x_probe(struct i2c_client *client) * using "reset" GPIO. Otherwise any of those platform * must use _DSD method with corresponding property. */ - reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", - GPIOD_OUT_LOW); + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(reset_gpio)) return PTR_ERR(reset_gpio); } @@ -1094,26 +1094,19 @@ static int pca953x_probe(struct i2c_client *client) if (!chip->driver_data) return -ENODEV; - reg = devm_regulator_get(&client->dev, "vcc"); - if (IS_ERR(reg)) - return dev_err_probe(&client->dev, PTR_ERR(reg), "reg get err\n"); - - ret = regulator_enable(reg); - if (ret) { - dev_err(&client->dev, "reg en err: %d\n", ret); + ret = pca953x_get_and_enable_regulator(chip); + if (ret) return ret; - } - chip->regulator = reg; i2c_set_clientdata(client, chip); pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); if (NBANK(chip) > 2 || PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { - dev_info(&client->dev, "using AI\n"); + dev_info(dev, "using AI\n"); regmap_config = &pca953x_ai_i2c_regmap; } else { - dev_info(&client->dev, "using no AI\n"); + dev_info(dev, "using no AI\n"); regmap_config = &pca953x_i2c_regmap; } @@ -1126,10 +1119,8 @@ static int pca953x_probe(struct i2c_client *client) } chip->regmap = devm_regmap_init_i2c(client, regmap_config); - if (IS_ERR(chip->regmap)) { - ret = PTR_ERR(chip->regmap); - goto err_exit; - } + if (IS_ERR(chip->regmap)) + return PTR_ERR(chip->regmap); regcache_mark_dirty(chip->regmap); @@ -1158,53 +1149,24 @@ static int pca953x_probe(struct i2c_client *client) */ if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { chip->regs = &pca957x_regs; - ret = device_pca957x_init(chip, invert); + ret = device_pca957x_init(chip); } else { chip->regs = &pca953x_regs; - ret = device_pca95xx_init(chip, invert); + ret = device_pca95xx_init(chip); } if (ret) - goto err_exit; + return ret; ret = pca953x_irq_setup(chip, irq_base); if (ret) - goto err_exit; + return ret; - ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); - if (ret) - goto err_exit; - - if (pdata && pdata->setup) { - ret = pdata->setup(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) - dev_warn(&client->dev, "setup failed, %d\n", ret); - } - - return 0; - -err_exit: - regulator_disable(chip->regulator); - return ret; + return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip); } -static void pca953x_remove(struct i2c_client *client) +static int pca953x_regcache_sync(struct pca953x_chip *chip) { - struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); - struct pca953x_chip *chip = i2c_get_clientdata(client); - - if (pdata && pdata->teardown) { - pdata->teardown(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - } - - regulator_disable(chip->regulator); -} - -#ifdef CONFIG_PM_SLEEP -static int pca953x_regcache_sync(struct device *dev) -{ - struct pca953x_chip *chip = dev_get_drvdata(dev); + struct device *dev = &chip->client->dev; int ret; u8 regaddr; @@ -1251,13 +1213,32 @@ static int pca953x_regcache_sync(struct device *dev) return 0; } +static int pca953x_restore_context(struct pca953x_chip *chip) +{ + int ret; + + guard(mutex)(&chip->i2c_lock); + + regcache_cache_only(chip->regmap, false); + regcache_mark_dirty(chip->regmap); + ret = pca953x_regcache_sync(chip); + if (ret) + return ret; + + return regcache_sync(chip->regmap); +} + +static void pca953x_save_context(struct pca953x_chip *chip) +{ + guard(mutex)(&chip->i2c_lock); + regcache_cache_only(chip->regmap, true); +} + static int pca953x_suspend(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); - mutex_lock(&chip->i2c_lock); - regcache_cache_only(chip->regmap, true); - mutex_unlock(&chip->i2c_lock); + pca953x_save_context(chip); if (atomic_read(&chip->wakeup_path)) device_set_wakeup_path(dev); @@ -1280,25 +1261,14 @@ static int pca953x_resume(struct device *dev) } } - mutex_lock(&chip->i2c_lock); - regcache_cache_only(chip->regmap, false); - regcache_mark_dirty(chip->regmap); - ret = pca953x_regcache_sync(dev); - if (ret) { - mutex_unlock(&chip->i2c_lock); - return ret; - } - - ret = regcache_sync(chip->regmap); - mutex_unlock(&chip->i2c_lock); - if (ret) { + ret = pca953x_restore_context(chip); + if (ret) dev_err(dev, "Failed to restore register map: %d\n", ret); - return ret; - } - return 0; + return ret; } -#endif + +static DEFINE_SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); /* convenience to stop overlong match-table lines */ #define OF_653X(__nrgpio, __int) ((void *)(__nrgpio | PCAL653X_TYPE | __int)) @@ -1356,17 +1326,14 @@ static const struct of_device_id pca953x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pca953x_dt_ids); -static SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); - static struct i2c_driver pca953x_driver = { .driver = { .name = "pca953x", - .pm = &pca953x_pm_ops, + .pm = pm_sleep_ptr(&pca953x_pm_ops), .of_match_table = pca953x_dt_ids, .acpi_match_table = pca953x_acpi_ids, }, .probe = pca953x_probe, - .remove = pca953x_remove, .id_table = pca953x_id, }; diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 86e69cde04da..d8b1baae6357 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -583,14 +583,13 @@ err0: return ret; } -static int gpio_rcar_remove(struct platform_device *pdev) +static void gpio_rcar_remove(struct platform_device *pdev) { struct gpio_rcar_priv *p = platform_get_drvdata(pdev); gpiochip_remove(&p->gpio_chip); pm_runtime_disable(&pdev->dev); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -658,7 +657,7 @@ static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, gpio_rcar_resume); static struct platform_driver gpio_rcar_device_driver = { .probe = gpio_rcar_probe, - .remove = gpio_rcar_remove, + .remove_new = gpio_rcar_remove, .driver = { .name = "gpio_rcar", .pm = &gpio_rcar_pm_ops, diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index b35b9604413f..23040a8cea34 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -778,14 +778,12 @@ static int rockchip_gpio_probe(struct platform_device *pdev) return 0; } -static int rockchip_gpio_remove(struct platform_device *pdev) +static void rockchip_gpio_remove(struct platform_device *pdev) { struct rockchip_pin_bank *bank = platform_get_drvdata(pdev); clk_disable_unprepare(bank->clk); gpiochip_remove(&bank->gpio_chip); - - return 0; } static const struct of_device_id rockchip_gpio_match[] = { @@ -796,7 +794,7 @@ static const struct of_device_id rockchip_gpio_match[] = { static struct platform_driver rockchip_gpio_driver = { .probe = rockchip_gpio_probe, - .remove = rockchip_gpio_remove, + .remove_new = rockchip_gpio_remove, .driver = { .name = "rockchip-gpio", .of_match_table = rockchip_gpio_match, diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c index 44bf1709a648..1928209491e1 100644 --- a/drivers/gpio/gpio-sim.c +++ b/drivers/gpio/gpio-sim.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,8 +32,7 @@ #include #include #include - -#include "gpiolib.h" +#include #define GPIO_SIM_NGPIO_MAX 1024 #define GPIO_SIM_PROP_MAX 4 /* Max 3 properties + sentinel. */ @@ -41,6 +42,8 @@ static DEFINE_IDA(gpio_sim_ida); struct gpio_sim_chip { struct gpio_chip gc; + struct device *dev; + unsigned long *request_map; unsigned long *direction_map; unsigned long *value_map; unsigned long *pull_map; @@ -64,16 +67,11 @@ static int gpio_sim_apply_pull(struct gpio_sim_chip *chip, unsigned int offset, int value) { int irq, irq_type, ret; - struct gpio_desc *desc; - struct gpio_chip *gc; - - gc = &chip->gc; - desc = &gc->gpiodev->descs[offset]; guard(mutex)(&chip->lock); - if (test_bit(FLAG_REQUESTED, &desc->flags) && - !test_bit(FLAG_IS_OUT, &desc->flags)) { + if (test_bit(offset, chip->request_map) && + test_bit(offset, chip->direction_map)) { if (value == !!test_bit(offset, chip->value_map)) goto set_pull; @@ -100,8 +98,8 @@ static int gpio_sim_apply_pull(struct gpio_sim_chip *chip, set_value: /* Change the value unless we're actively driving the line. */ - if (!test_bit(FLAG_REQUESTED, &desc->flags) || - !test_bit(FLAG_IS_OUT, &desc->flags)) + if (!test_bit(offset, chip->request_map) || + test_bit(offset, chip->direction_map)) __assign_bit(offset, chip->value_map, value); set_pull: @@ -181,8 +179,8 @@ static int gpio_sim_get_direction(struct gpio_chip *gc, unsigned int offset) return direction ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT; } -static int gpio_sim_set_config(struct gpio_chip *gc, - unsigned int offset, unsigned long config) +static int gpio_sim_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) { struct gpio_sim_chip *chip = gpiochip_get_data(gc); @@ -205,13 +203,25 @@ static int gpio_sim_to_irq(struct gpio_chip *gc, unsigned int offset) return irq_create_mapping(chip->irq_sim, offset); } -static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset) +static int gpio_sim_request(struct gpio_chip *gc, unsigned int offset) { struct gpio_sim_chip *chip = gpiochip_get_data(gc); scoped_guard(mutex, &chip->lock) + __set_bit(offset, chip->request_map); + + return 0; +} + +static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset) +{ + struct gpio_sim_chip *chip = gpiochip_get_data(gc); + + scoped_guard(mutex, &chip->lock) { __assign_bit(offset, chip->value_map, !!test_bit(offset, chip->pull_map)); + __clear_bit(offset, chip->request_map); + } } static ssize_t gpio_sim_sysfs_val_show(struct device *dev, @@ -283,6 +293,13 @@ static void gpio_sim_mutex_destroy(void *data) mutex_destroy(lock); } +static void gpio_sim_put_device(void *data) +{ + struct device *dev = data; + + put_device(dev); +} + static void gpio_sim_dispose_mappings(void *data) { struct gpio_sim_chip *chip = data; @@ -296,7 +313,7 @@ static void gpio_sim_sysfs_remove(void *data) { struct gpio_sim_chip *chip = data; - sysfs_remove_groups(&chip->gc.gpiodev->dev.kobj, chip->attr_groups); + sysfs_remove_groups(&chip->dev->kobj, chip->attr_groups); } static int gpio_sim_setup_sysfs(struct gpio_sim_chip *chip) @@ -353,14 +370,18 @@ static int gpio_sim_setup_sysfs(struct gpio_sim_chip *chip) chip->attr_groups[i] = attr_group; } - ret = sysfs_create_groups(&chip->gc.gpiodev->dev.kobj, - chip->attr_groups); + ret = sysfs_create_groups(&chip->dev->kobj, chip->attr_groups); if (ret) return ret; return devm_add_action_or_reset(dev, gpio_sim_sysfs_remove, chip); } +static int gpio_sim_dev_match_fwnode(struct device *dev, void *data) +{ + return device_match_fwnode(dev, data); +} + static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) { struct gpio_sim_chip *chip; @@ -388,6 +409,10 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) if (!chip) return -ENOMEM; + chip->request_map = devm_bitmap_zalloc(dev, num_lines, GFP_KERNEL); + if (!chip->request_map) + return -ENOMEM; + chip->direction_map = devm_bitmap_alloc(dev, num_lines, GFP_KERNEL); if (!chip->direction_map) return -ENOMEM; @@ -433,6 +458,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) gc->get_direction = gpio_sim_get_direction; gc->set_config = gpio_sim_set_config; gc->to_irq = gpio_sim_to_irq; + gc->request = gpio_sim_request; gc->free = gpio_sim_free; gc->can_sleep = true; @@ -440,8 +466,16 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) if (ret) return ret; - /* Used by sysfs and configfs callbacks. */ - dev_set_drvdata(&gc->gpiodev->dev, chip); + chip->dev = device_find_child(dev, swnode, gpio_sim_dev_match_fwnode); + if (!chip->dev) + return -ENODEV; + + ret = devm_add_action_or_reset(dev, gpio_sim_put_device, chip->dev); + if (ret) + return ret; + + /* Used by sysfs callbacks. */ + dev_set_drvdata(chip->dev, chip); return gpio_sim_setup_sysfs(chip); } @@ -1438,10 +1472,10 @@ static const struct config_item_type gpio_sim_device_config_group_type = { static struct config_group * gpio_sim_config_make_device_group(struct config_group *group, const char *name) { - struct gpio_sim_device *dev __free(kfree) = NULL; int id; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + struct gpio_sim_device *dev __free(kfree) = kzalloc(sizeof(*dev), + GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index f96d260a4a19..e8c1485b9c73 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -215,7 +215,7 @@ err_remove_domain: return ret; } -static int tb10x_gpio_remove(struct platform_device *pdev) +static void tb10x_gpio_remove(struct platform_device *pdev) { struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev); @@ -225,8 +225,6 @@ static int tb10x_gpio_remove(struct platform_device *pdev) kfree(tb10x_gpio->domain->gc); irq_domain_remove(tb10x_gpio->domain); } - - return 0; } static const struct of_device_id tb10x_gpio_dt_ids[] = { @@ -237,7 +235,7 @@ MODULE_DEVICE_TABLE(of, tb10x_gpio_dt_ids); static struct platform_driver tb10x_gpio_driver = { .probe = tb10x_gpio_probe, - .remove = tb10x_gpio_remove, + .remove_new = tb10x_gpio_remove, .driver = { .name = "tb10x-gpio", .of_match_table = tb10x_gpio_dt_ids, diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c index 8e03614c7a24..90f8e9e9915e 100644 --- a/drivers/gpio/gpio-ts5500.c +++ b/drivers/gpio/gpio-ts5500.c @@ -412,13 +412,11 @@ static int ts5500_dio_probe(struct platform_device *pdev) return 0; } -static int ts5500_dio_remove(struct platform_device *pdev) +static void ts5500_dio_remove(struct platform_device *pdev) { struct ts5500_priv *priv = platform_get_drvdata(pdev); ts5500_disable_irq(priv); - - return 0; } static const struct platform_device_id ts5500_dio_ids[] = { @@ -435,7 +433,7 @@ static struct platform_driver ts5500_dio_driver = { .name = "ts5500-dio", }, .probe = ts5500_dio_probe, - .remove = ts5500_dio_remove, + .remove_new = ts5500_dio_remove, .id_table = ts5500_dio_ids, }; diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index 9725b7aa18a7..1f440707f8f4 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -414,13 +414,11 @@ static int uniphier_gpio_probe(struct platform_device *pdev) return 0; } -static int uniphier_gpio_remove(struct platform_device *pdev) +static void uniphier_gpio_remove(struct platform_device *pdev) { struct uniphier_gpio_priv *priv = platform_get_drvdata(pdev); irq_domain_remove(priv->domain); - - return 0; } static int __maybe_unused uniphier_gpio_suspend(struct device *dev) @@ -482,7 +480,7 @@ MODULE_DEVICE_TABLE(of, uniphier_gpio_match); static struct platform_driver uniphier_gpio_driver = { .probe = uniphier_gpio_probe, - .remove = uniphier_gpio_remove, + .remove_new = uniphier_gpio_remove, .driver = { .name = "uniphier-gpio", .of_match_table = uniphier_gpio_match, diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 656d6b1dddb5..444501c56a3b 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -25,6 +25,7 @@ struct fsl_gpio_soc_data { /* SoCs has a Port Data Direction Register (PDDR) */ bool have_paddr; + bool have_dual_base; }; struct vf610_gpio_port { @@ -60,13 +61,26 @@ struct vf610_gpio_port { #define PORT_INT_EITHER_EDGE 0xb #define PORT_INT_LOGIC_ONE 0xc +#define IMX8ULP_GPIO_BASE_OFF 0x40 +#define IMX8ULP_BASE_OFF 0x80 + +static const struct fsl_gpio_soc_data vf610_data = { + .have_dual_base = true, +}; + static const struct fsl_gpio_soc_data imx_data = { .have_paddr = true, + .have_dual_base = true, +}; + +static const struct fsl_gpio_soc_data imx8ulp_data = { + .have_paddr = true, }; static const struct of_device_id vf610_gpio_dt_ids[] = { - { .compatible = "fsl,vf610-gpio", .data = NULL, }, + { .compatible = "fsl,vf610-gpio", .data = &vf610_data }, { .compatible = "fsl,imx7ulp-gpio", .data = &imx_data, }, + { .compatible = "fsl,imx8ulp-gpio", .data = &imx8ulp_data, }, { /* sentinel */ } }; @@ -86,7 +100,7 @@ static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio) unsigned long mask = BIT(gpio); unsigned long offset = GPIO_PDIR; - if (port->sdata && port->sdata->have_paddr) { + if (port->sdata->have_paddr) { mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR); if (mask) offset = GPIO_PDOR; @@ -110,7 +124,7 @@ static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) unsigned long mask = BIT(gpio); u32 val; - if (port->sdata && port->sdata->have_paddr) { + if (port->sdata->have_paddr) { val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR); val &= ~mask; vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR); @@ -128,7 +142,7 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, vf610_gpio_set(chip, gpio, value); - if (port->sdata && port->sdata->have_paddr) { + if (port->sdata->have_paddr) { val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR); val |= mask; vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR); @@ -264,19 +278,41 @@ static int vf610_gpio_probe(struct platform_device *pdev) struct gpio_irq_chip *girq; int i; int ret; + bool dual_base; port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; port->sdata = of_device_get_match_data(dev); - port->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(port->base)) - return PTR_ERR(port->base); - port->gpio_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(port->gpio_base)) - return PTR_ERR(port->gpio_base); + dual_base = port->sdata->have_dual_base; + + /* + * Handle legacy compatible combinations which used two reg values + * for the i.MX8ULP and i.MX93. + */ + if (device_is_compatible(dev, "fsl,imx7ulp-gpio") && + (device_is_compatible(dev, "fsl,imx93-gpio") || + (device_is_compatible(dev, "fsl,imx8ulp-gpio")))) + dual_base = true; + + if (dual_base) { + port->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(port->base)) + return PTR_ERR(port->base); + + port->gpio_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(port->gpio_base)) + return PTR_ERR(port->gpio_base); + } else { + port->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(port->base)) + return PTR_ERR(port->base); + + port->gpio_base = port->base + IMX8ULP_GPIO_BASE_OFF; + port->base = port->base + IMX8ULP_BASE_OFF; + } port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index a809609ee957..bd5befa807c3 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -15,7 +15,6 @@ #include #include -#include "gpiolib.h" #include "gpiolib-acpi.h" /* Common property names */ @@ -296,15 +295,13 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev) return ret; } -static int xgene_gpio_sb_remove(struct platform_device *pdev) +static void xgene_gpio_sb_remove(struct platform_device *pdev) { struct xgene_gpio_sb *priv = platform_get_drvdata(pdev); acpi_gpiochip_free_interrupts(&priv->gc); irq_domain_remove(priv->irq_domain); - - return 0; } static const struct of_device_id xgene_gpio_sb_of_match[] = { @@ -328,7 +325,7 @@ static struct platform_driver xgene_gpio_sb_driver = { .acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match), }, .probe = xgene_gpio_sb_probe, - .remove = xgene_gpio_sb_remove, + .remove_new = xgene_gpio_sb_remove, }; module_platform_driver(xgene_gpio_sb_driver); diff --git a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c index 2d23b27d55af..d445eea03687 100644 --- a/drivers/gpio/gpio-xgs-iproc.c +++ b/drivers/gpio/gpio-xgs-iproc.c @@ -291,7 +291,7 @@ static int iproc_gpio_probe(struct platform_device *pdev) return 0; } -static int iproc_gpio_remove(struct platform_device *pdev) +static void iproc_gpio_remove(struct platform_device *pdev) { struct iproc_gpio_chip *chip = platform_get_drvdata(pdev); @@ -302,8 +302,6 @@ static int iproc_gpio_remove(struct platform_device *pdev) val &= ~IPROC_CCA_INT_F_GPIOINT; writel_relaxed(val, chip->intr + IPROC_CCA_INT_MASK); } - - return 0; } static const struct of_device_id bcm_iproc_gpio_of_match[] = { @@ -318,7 +316,7 @@ static struct platform_driver bcm_iproc_gpio_driver = { .of_match_table = bcm_iproc_gpio_of_match, }, .probe = iproc_gpio_probe, - .remove = iproc_gpio_remove, + .remove_new = iproc_gpio_remove, }; module_platform_driver(bcm_iproc_gpio_driver); diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index a16945e8319e..823198368250 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -332,7 +332,7 @@ static int __maybe_unused xgpio_suspend(struct device *dev) * * Return: 0 always */ -static int xgpio_remove(struct platform_device *pdev) +static void xgpio_remove(struct platform_device *pdev) { struct xgpio_instance *gpio = platform_get_drvdata(pdev); @@ -340,8 +340,6 @@ static int xgpio_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable_unprepare(gpio->clk); - - return 0; } /** @@ -715,7 +713,7 @@ MODULE_DEVICE_TABLE(of, xgpio_of_match); static struct platform_driver xgpio_plat_driver = { .probe = xgpio_probe, - .remove = xgpio_remove, + .remove_new = xgpio_remove, .driver = { .name = "gpio-xilinx", .of_match_table = xgpio_of_match, diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 324e942c0650..466e23031afc 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1010,7 +1010,7 @@ err_pm_dis: * * Return: 0 always */ -static int zynq_gpio_remove(struct platform_device *pdev) +static void zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); int ret; @@ -1022,7 +1022,6 @@ static int zynq_gpio_remove(struct platform_device *pdev) clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); - return 0; } static struct platform_driver zynq_gpio_driver = { @@ -1032,7 +1031,7 @@ static struct platform_driver zynq_gpio_driver = { .of_match_table = zynq_gpio_of_match, }, .probe = zynq_gpio_probe, - .remove = zynq_gpio_remove, + .remove_new = zynq_gpio_remove, }; module_platform_driver(zynq_gpio_driver); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 51e41676de0b..88066826d8e5 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -143,7 +143,6 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) */ static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin) { - struct gpio_chip *chip; acpi_handle handle; acpi_status status; @@ -151,41 +150,18 @@ static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin) if (ACPI_FAILURE(status)) return ERR_PTR(-ENODEV); - chip = gpiochip_find(handle, acpi_gpiochip_find); - if (!chip) + struct gpio_device *gdev __free(gpio_device_put) = + gpio_device_find(handle, acpi_gpiochip_find); + if (!gdev) return ERR_PTR(-EPROBE_DEFER); - return gpiochip_get_desc(chip, pin); + /* + * FIXME: keep track of the reference to the GPIO device somehow + * instead of putting it here. + */ + return gpio_device_get_desc(gdev, pin); } -/** - * acpi_get_and_request_gpiod - Translate ACPI GPIO pin to GPIO descriptor and - * hold a refcount to the GPIO device. - * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") - * @pin: ACPI GPIO pin number (0-based, controller-relative) - * @label: Label to pass to gpiod_request() - * - * This function is a simple pass-through to acpi_get_gpiod(), except that - * as it is intended for use outside of the GPIO layer (in a similar fashion to - * gpiod_get_index() for example) it also holds a reference to the GPIO device. - */ -struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char *label) -{ - struct gpio_desc *gpio; - int ret; - - gpio = acpi_get_gpiod(path, pin); - if (IS_ERR(gpio)) - return gpio; - - ret = gpiod_request(gpio, label); - if (ret) - return ERR_PTR(ret); - - return gpio; -} -EXPORT_SYMBOL_GPL(acpi_get_and_request_gpiod); - static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) { struct acpi_gpio_event *event = data; @@ -437,6 +413,11 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, if (!handler) return AE_OK; + if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) { + dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin); + return AE_OK; + } + desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event"); if (IS_ERR(desc)) { dev_err(chip->parent, @@ -461,11 +442,6 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, goto fail_unlock_irq; } - if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) { - dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin); - return AE_OK; - } - event = kzalloc(sizeof(*event), GFP_KERNEL); if (!event) goto fail_unlock_irq; @@ -1655,6 +1631,26 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_wake = "SYNA1202:00@16", }, }, + { + /* + * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to + * a "dolby" button. At the ACPI level an _AEI event-handler + * is connected which sets an ACPI variable to 1 on both + * edges. This variable can be polled + cleared to 0 using + * WMI. But since the variable is set on both edges the WMI + * interface is pretty useless even when polling. + * So instead the x86-android-tablets code instantiates + * a gpio-keys platform device for it. + * Ignore the _AEI handler for the pin, so that it is not busy. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"), + DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_interrupt = "INT33FC:00@3", + }, + }, {} /* Terminating entry */ }; diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index e39d344feb28..31fc71a612c2 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -572,7 +572,7 @@ struct linereq { DECLARE_KFIFO_PTR(events, struct gpio_v2_line_event); atomic_t seqno; struct mutex config_mutex; - struct line lines[]; + struct line lines[] __counted_by(num_lines); }; #define GPIO_V2_LINE_BIAS_FLAGS \ @@ -1656,6 +1656,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) lr = kzalloc(struct_size(lr, lines, ulr.num_lines), GFP_KERNEL); if (!lr) return -ENOMEM; + lr->num_lines = ulr.num_lines; lr->gdev = gpio_device_get(gdev); @@ -1684,7 +1685,6 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) lr->event_buffer_size = GPIO_V2_LINES_MAX * 16; atomic_set(&lr->seqno, 0); - lr->num_lines = ulr.num_lines; /* Request each GPIO */ for (i = 0; i < ulr.num_lines; i++) { diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 6b6576419117..e6d46d140b6a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -127,10 +127,10 @@ static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) chip->of_xlate(chip, gpiospec, NULL) >= 0; } -static struct gpio_chip *of_find_gpiochip_by_xlate( - struct of_phandle_args *gpiospec) +static struct gpio_device * +of_find_gpio_device_by_xlate(struct of_phandle_args *gpiospec) { - return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate); + return gpio_device_find(gpiospec, of_gpiochip_match_node_and_xlate); } static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, @@ -192,6 +192,15 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np, */ { "himax,hx8357", "gpios-reset", false }, { "himax,hx8369", "gpios-reset", false }, + /* + * The rb-gpios semantics was undocumented and qi,lb60 (along with + * the ingenic driver) got it wrong. The active state encodes the + * NAND ready state, which is high level. Since there's no signal + * inverter on this board, it should be active-high. Let's fix that + * here for older DTs so we can re-use the generic nand_gpio_waitrdy() + * helper, and be consistent with what other drivers do. + */ + { "qi,lb60", "rb-gpios", true }, #endif }; unsigned int i; @@ -363,7 +372,6 @@ static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags) { struct of_phandle_args gpiospec; - struct gpio_chip *chip; struct gpio_desc *desc; int ret; @@ -375,13 +383,15 @@ static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np, return ERR_PTR(ret); } - chip = of_find_gpiochip_by_xlate(&gpiospec); - if (!chip) { + struct gpio_device *gdev __free(gpio_device_put) = + of_find_gpio_device_by_xlate(&gpiospec); + if (!gdev) { desc = ERR_PTR(-EPROBE_DEFER); goto out; } - desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags); + desc = of_xlate_and_get_gpiod_flags(gpio_device_get_chip(gdev), + &gpiospec, flags); if (IS_ERR(desc)) goto out; @@ -612,6 +622,33 @@ static struct gpio_desc *of_find_mt2701_gpio(struct device_node *np, return desc; } +/* + * Trigger sources are special, they allow us to use any GPIO as a LED trigger + * and have the name "trigger-sources" no matter which kind of phandle it is + * pointing to, whether to a GPIO, a USB host, a network PHY etc. So in this case + * we allow looking something up that is not named "foo-gpios". + */ +static struct gpio_desc *of_find_trigger_gpio(struct device_node *np, + const char *con_id, + unsigned int idx, + enum of_gpio_flags *of_flags) +{ + struct gpio_desc *desc; + + if (!IS_ENABLED(CONFIG_LEDS_TRIGGER_GPIO)) + return ERR_PTR(-ENOENT); + + if (!con_id || strcmp(con_id, "trigger-sources")) + return ERR_PTR(-ENOENT); + + desc = of_get_named_gpiod_flags(np, con_id, idx, of_flags); + if (!gpiod_not_found(desc)) + pr_debug("%s is used as a trigger\n", of_node_full_name(np)); + + return desc; +} + + typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np, const char *con_id, unsigned int idx, @@ -619,6 +656,7 @@ typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np, static const of_find_gpio_quirk of_find_gpio_quirks[] = { of_find_gpio_rename, of_find_mt2701_gpio, + of_find_trigger_gpio, NULL }; @@ -814,16 +852,16 @@ static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) return device_match_of_node(&chip->gpiodev->dev, data); } -static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) +static struct gpio_device *of_find_gpio_device_by_node(struct device_node *np) { - return gpiochip_find(np, of_gpiochip_match_node); + return gpio_device_find(np, of_gpiochip_match_node); } static int of_gpio_notify(struct notifier_block *nb, unsigned long action, void *arg) { + struct gpio_device *gdev __free(gpio_device_put) = NULL; struct of_reconfig_data *rd = arg; - struct gpio_chip *chip; int ret; /* @@ -835,38 +873,38 @@ static int of_gpio_notify(struct notifier_block *nb, unsigned long action, switch (of_reconfig_get_state_change(action, arg)) { case OF_RECONFIG_CHANGE_ADD: if (!of_property_read_bool(rd->dn, "gpio-hog")) - return NOTIFY_OK; /* not for us */ + return NOTIFY_DONE; /* not for us */ if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) - return NOTIFY_OK; + return NOTIFY_DONE; - chip = of_find_gpiochip_by_node(rd->dn->parent); - if (chip == NULL) - return NOTIFY_OK; /* not for us */ + gdev = of_find_gpio_device_by_node(rd->dn->parent); + if (!gdev) + return NOTIFY_DONE; /* not for us */ - ret = of_gpiochip_add_hog(chip, rd->dn); + ret = of_gpiochip_add_hog(gpio_device_get_chip(gdev), rd->dn); if (ret < 0) { pr_err("%s: failed to add hogs for %pOF\n", __func__, rd->dn); of_node_clear_flag(rd->dn, OF_POPULATED); return notifier_from_errno(ret); } - break; + return NOTIFY_OK; case OF_RECONFIG_CHANGE_REMOVE: if (!of_node_check_flag(rd->dn, OF_POPULATED)) - return NOTIFY_OK; /* already depopulated */ + return NOTIFY_DONE; /* already depopulated */ - chip = of_find_gpiochip_by_node(rd->dn->parent); - if (chip == NULL) - return NOTIFY_OK; /* not for us */ + gdev = of_find_gpio_device_by_node(rd->dn->parent); + if (!gdev) + return NOTIFY_DONE; /* not for us */ - of_gpiochip_remove_hog(chip, rd->dn); + of_gpiochip_remove_hog(gpio_device_get_chip(gdev), rd->dn); of_node_clear_flag(rd->dn, OF_POPULATED); - break; + return NOTIFY_OK; } - return NOTIFY_OK; + return NOTIFY_DONE; } struct notifier_block gpio_of_notifier = { diff --git a/drivers/gpio/gpiolib-swnode.c b/drivers/gpio/gpiolib-swnode.c index b5a6eaf3729b..fa52bdb1a29a 100644 --- a/drivers/gpio/gpiolib-swnode.c +++ b/drivers/gpio/gpiolib-swnode.c @@ -31,22 +31,17 @@ static void swnode_format_propname(const char *con_id, char *propname, strscpy(propname, "gpios", max_size); } -static int swnode_gpiochip_match_name(struct gpio_chip *chip, void *data) +static struct gpio_device *swnode_get_gpio_device(struct fwnode_handle *fwnode) { - return !strcmp(chip->label, data); -} + const struct software_node *gdev_node; + struct gpio_device *gdev; -static struct gpio_chip *swnode_get_chip(struct fwnode_handle *fwnode) -{ - const struct software_node *chip_node; - struct gpio_chip *chip; - - chip_node = to_software_node(fwnode); - if (!chip_node || !chip_node->name) + gdev_node = to_software_node(fwnode); + if (!gdev_node || !gdev_node->name) return ERR_PTR(-EINVAL); - chip = gpiochip_find((void *)chip_node->name, swnode_gpiochip_match_name); - return chip ?: ERR_PTR(-EPROBE_DEFER); + gdev = gpio_device_find_by_label(gdev_node->name); + return gdev ?: ERR_PTR(-EPROBE_DEFER); } struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode, @@ -55,7 +50,6 @@ struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode, { const struct software_node *swnode; struct fwnode_reference_args args; - struct gpio_chip *chip; struct gpio_desc *desc; char propname[32]; /* 32 is max size of property name */ int error; @@ -77,12 +71,17 @@ struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode, return ERR_PTR(error); } - chip = swnode_get_chip(args.fwnode); + struct gpio_device *gdev __free(gpio_device_put) = + swnode_get_gpio_device(args.fwnode); fwnode_handle_put(args.fwnode); - if (IS_ERR(chip)) - return ERR_CAST(chip); + if (IS_ERR(gdev)) + return ERR_CAST(gdev); - desc = gpiochip_get_desc(chip, args.args[0]); + /* + * FIXME: The GPIO device reference is put at return but the descriptor + * is passed on. Find a proper solution. + */ + desc = gpio_device_get_desc(gdev, args.args[0]); *flags = args.args[1]; /* We expect native GPIO flags */ pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n", diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 50503a4525eb..6f309a3b2d9a 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -814,7 +814,7 @@ static int __init gpiolib_sysfs_init(void) * gpiochip_sysfs_register() acquires a mutex. This is unsafe * and needs to be fixed. * - * Also it would be nice to use gpiochip_find() here so we + * Also it would be nice to use gpio_device_find() here so we * can keep gpio_chips local to gpiolib.c, but the yield of * gpio_lock prevents us from doing this. */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 40a0022ea719..cbafcd95243e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -146,27 +147,49 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) } EXPORT_SYMBOL_GPL(gpio_to_desc); -/** - * gpiochip_get_desc - get the GPIO descriptor corresponding to the given - * hardware number for this chip - * @gc: GPIO chip - * @hwnum: hardware number of the GPIO for this chip - * - * Returns: - * A pointer to the GPIO descriptor or ``ERR_PTR(-EINVAL)`` if no GPIO exists - * in the given chip for the specified hardware number. - */ +/* This function is deprecated and will be removed soon, don't use. */ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum) { - struct gpio_device *gdev = gc->gpiodev; + return gpio_device_get_desc(gc->gpiodev, hwnum); +} +EXPORT_SYMBOL_GPL(gpiochip_get_desc); + +/** + * gpio_device_get_desc() - get the GPIO descriptor corresponding to the given + * hardware number for this GPIO device + * @gdev: GPIO device to get the descriptor from + * @hwnum: hardware number of the GPIO for this chip + * + * Returns: + * A pointer to the GPIO descriptor or %EINVAL if no GPIO exists in the given + * chip for the specified hardware number or %ENODEV if the underlying chip + * already vanished. + * + * The reference count of struct gpio_device is *NOT* increased like when the + * GPIO is being requested for exclusive usage. It's up to the caller to make + * sure the GPIO device will stay alive together with the descriptor returned + * by this function. + */ +struct gpio_desc * +gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum) +{ + struct gpio_chip *gc; + + /* + * FIXME: This will be locked once we protect gdev->chip everywhere + * with SRCU. + */ + gc = gdev->chip; + if (!gc) + return ERR_PTR(-ENODEV); if (hwnum >= gdev->ngpio) return ERR_PTR(-EINVAL); return &gdev->descs[hwnum]; } -EXPORT_SYMBOL_GPL(gpiochip_get_desc); +EXPORT_SYMBOL_GPL(gpio_device_get_desc); /** * desc_to_gpio - convert a GPIO descriptor to the integer namespace @@ -197,6 +220,61 @@ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_to_chip); +/** + * gpiod_to_gpio_device() - Return the GPIO device to which this descriptor + * belongs. + * @desc: Descriptor for which to return the GPIO device. + * + * This *DOES NOT* increase the reference count of the GPIO device as it's + * expected that the descriptor is requested and the users already holds a + * reference to the device. + * + * Returns: + * Address of the GPIO device owning this descriptor. + */ +struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc) +{ + if (!desc) + return NULL; + + return desc->gdev; +} +EXPORT_SYMBOL_GPL(gpiod_to_gpio_device); + +/** + * gpio_device_get_base() - Get the base GPIO number allocated by this device + * @gdev: GPIO device + * + * Returns: + * First GPIO number in the global GPIO numberspace for this device. + */ +int gpio_device_get_base(struct gpio_device *gdev) +{ + return gdev->base; +} +EXPORT_SYMBOL_GPL(gpio_device_get_base); + +/** + * gpio_device_get_chip() - Get the gpio_chip implementation of this GPIO device + * @gdev: GPIO device + * + * Returns: + * Address of the GPIO chip backing this device. + * + * Until we can get rid of all non-driver users of struct gpio_chip, we must + * provide a way of retrieving the pointer to it from struct gpio_device. This + * is *NOT* safe as the GPIO API is considered to be hot-unpluggable and the + * chip can dissapear at any moment (unlike reference-counted struct + * gpio_device). + * + * Use at your own risk. + */ +struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev) +{ + return gdev->chip; +} +EXPORT_SYMBOL_GPL(gpio_device_get_chip); + /* dynamic allocation of GPIOs, e.g. on a hotplugged device */ static int gpiochip_find_base(int ngpio) { @@ -1014,16 +1092,10 @@ void gpiochip_remove(struct gpio_chip *gc) } EXPORT_SYMBOL_GPL(gpiochip_remove); -/** - * gpiochip_find() - iterator for locating a specific gpio_chip - * @data: data to pass to match function - * @match: Callback function to check gpio_chip +/* + * FIXME: This will be removed soon. * - * Similar to bus_find_device. It returns a reference to a gpio_chip as - * determined by a user supplied @match callback. The callback should return - * 0 if the device doesn't match and non-zero if it does. If the callback is - * non-zero, this function will return to the caller and not iterate over any - * more gpio_chips. + * This function is depracated, don't use. */ struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *gc, @@ -1031,32 +1103,142 @@ struct gpio_chip *gpiochip_find(void *data, { struct gpio_device *gdev; struct gpio_chip *gc = NULL; - unsigned long flags; - spin_lock_irqsave(&gpio_lock, flags); - list_for_each_entry(gdev, &gpio_devices, list) - if (gdev->chip && match(gdev->chip, data)) { - gc = gdev->chip; - break; - } - - spin_unlock_irqrestore(&gpio_lock, flags); + gdev = gpio_device_find(data, match); + if (gdev) { + gc = gdev->chip; + gpio_device_put(gdev); + } return gc; } EXPORT_SYMBOL_GPL(gpiochip_find); -static int gpiochip_match_name(struct gpio_chip *gc, void *data) +/** + * gpio_device_find() - find a specific GPIO device + * @data: data to pass to match function + * @match: Callback function to check gpio_chip + * + * Returns: + * New reference to struct gpio_device. + * + * Similar to bus_find_device(). It returns a reference to a gpio_device as + * determined by a user supplied @match callback. The callback should return + * 0 if the device doesn't match and non-zero if it does. If the callback + * returns non-zero, this function will return to the caller and not iterate + * over any more gpio_devices. + * + * The callback takes the GPIO chip structure as argument. During the execution + * of the callback function the chip is protected from being freed. TODO: This + * actually has yet to be implemented. + * + * If the function returns non-NULL, the returned reference must be freed by + * the caller using gpio_device_put(). + */ +struct gpio_device *gpio_device_find(void *data, + int (*match)(struct gpio_chip *gc, + void *data)) { - const char *name = data; + struct gpio_device *gdev; - return !strcmp(gc->label, name); + /* + * Not yet but in the future the spinlock below will become a mutex. + * Annotate this function before anyone tries to use it in interrupt + * context like it happened with gpiochip_find(). + */ + might_sleep(); + + guard(spinlock_irqsave)(&gpio_lock); + + list_for_each_entry(gdev, &gpio_devices, list) { + if (gdev->chip && match(gdev->chip, data)) + return gpio_device_get(gdev); + } + + return NULL; +} +EXPORT_SYMBOL_GPL(gpio_device_find); + +static int gpio_chip_match_by_label(struct gpio_chip *gc, void *label) +{ + return gc->label && !strcmp(gc->label, label); } -static struct gpio_chip *find_chip_by_name(const char *name) +/** + * gpio_device_find_by_label() - wrapper around gpio_device_find() finding the + * GPIO device by its backing chip's label + * @label: Label to lookup + * + * Returns: + * Reference to the GPIO device or NULL. Reference must be released with + * gpio_device_put(). + */ +struct gpio_device *gpio_device_find_by_label(const char *label) { - return gpiochip_find((void *)name, gpiochip_match_name); + return gpio_device_find((void *)label, gpio_chip_match_by_label); } +EXPORT_SYMBOL_GPL(gpio_device_find_by_label); + +static int gpio_chip_match_by_fwnode(struct gpio_chip *gc, void *fwnode) +{ + return device_match_fwnode(&gc->gpiodev->dev, fwnode); +} + +/** + * gpio_device_find_by_fwnode() - wrapper around gpio_device_find() finding + * the GPIO device by its fwnode + * @fwnode: Firmware node to lookup + * + * Returns: + * Reference to the GPIO device or NULL. Reference must be released with + * gpio_device_put(). + */ +struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode) +{ + return gpio_device_find((void *)fwnode, gpio_chip_match_by_fwnode); +} +EXPORT_SYMBOL_GPL(gpio_device_find_by_fwnode); + +/** + * gpio_device_get() - Increase the reference count of this GPIO device + * @gdev: GPIO device to increase the refcount for + * + * Returns: + * Pointer to @gdev. + */ +struct gpio_device *gpio_device_get(struct gpio_device *gdev) +{ + return to_gpio_device(get_device(&gdev->dev)); +} +EXPORT_SYMBOL_GPL(gpio_device_get); + +/** + * gpio_device_put() - Decrease the reference count of this GPIO device and + * possibly free all resources associated with it. + * @gdev: GPIO device to decrease the reference count for + */ +void gpio_device_put(struct gpio_device *gdev) +{ + put_device(&gdev->dev); +} +EXPORT_SYMBOL_GPL(gpio_device_put); + +/** + * gpio_device_to_device() - Retrieve the address of the underlying struct + * device. + * @gdev: GPIO device for which to return the address. + * + * This does not increase the reference count of the GPIO device nor the + * underlying struct device. + * + * Returns: + * Address of struct device backing this GPIO device. + */ +struct device *gpio_device_to_device(struct gpio_device *gdev) +{ + return &gdev->dev; +} +EXPORT_SYMBOL_GPL(gpio_device_to_device); #ifdef CONFIG_GPIOLIB_IRQCHIP @@ -2700,7 +2882,6 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) PIN_CONFIG_PERSIST_STATE, !transitory); } -EXPORT_SYMBOL_GPL(gpiod_set_transitory); /** * gpiod_is_active_low - test whether a GPIO is active-low or not @@ -3786,7 +3967,6 @@ EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table); */ void gpiod_add_hogs(struct gpiod_hog *hogs) { - struct gpio_chip *gc; struct gpiod_hog *hog; mutex_lock(&gpio_machine_hogs_mutex); @@ -3798,9 +3978,10 @@ void gpiod_add_hogs(struct gpiod_hog *hogs) * The chip may have been registered earlier, so check if it * exists and, if so, try to hog the line now. */ - gc = find_chip_by_name(hog->chip_label); - if (gc) - gpiochip_machine_hog(gc, hog); + struct gpio_device *gdev __free(gpio_device_put) = + gpio_device_find_by_label(hog->chip_label); + if (gdev) + gpiochip_machine_hog(gpio_device_get_chip(gdev), hog); } mutex_unlock(&gpio_machine_hogs_mutex); @@ -3823,8 +4004,6 @@ static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) const char *dev_id = dev ? dev_name(dev) : NULL; struct gpiod_lookup_table *table; - mutex_lock(&gpio_lookup_lock); - list_for_each_entry(table, &gpio_lookup_list, list) { if (table->dev_id && dev_id) { /* @@ -3832,21 +4011,18 @@ static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) * a match */ if (!strcmp(table->dev_id, dev_id)) - goto found; + return table; } else { /* * One of the pointers is NULL, so both must be to have * a match */ if (dev_id == table->dev_id) - goto found; + return table; } } - table = NULL; -found: - mutex_unlock(&gpio_lookup_lock); - return table; + return NULL; } static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, @@ -3855,14 +4031,15 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, struct gpio_desc *desc = ERR_PTR(-ENOENT); struct gpiod_lookup_table *table; struct gpiod_lookup *p; + struct gpio_chip *gc; + + guard(mutex)(&gpio_lookup_lock); table = gpiod_find_lookup_table(dev); if (!table) return desc; for (p = &table->table[0]; p->key; p++) { - struct gpio_chip *gc; - /* idx must always match exactly */ if (p->idx != idx) continue; @@ -3883,9 +4060,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return ERR_PTR(-EPROBE_DEFER); } - gc = find_chip_by_name(p->key); - - if (!gc) { + struct gpio_device *gdev __free(gpio_device_put) = + gpio_device_find_by_label(p->key); + if (!gdev) { /* * As the lookup table indicates a chip with * p->key should exist, assume it may @@ -3898,6 +4075,8 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return ERR_PTR(-EPROBE_DEFER); } + gc = gpio_device_get_chip(gdev); + if (gc->ngpio <= p->chip_hwnum) { dev_err(dev, "requested GPIO %u (%u) is out of range [0..%u] for chip %s\n", @@ -3906,7 +4085,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return ERR_PTR(-EINVAL); } - desc = gpiochip_get_desc(gc, p->chip_hwnum); + desc = gpio_device_get_desc(gdev, p->chip_hwnum); *flags = p->flags; return desc; @@ -3921,15 +4100,18 @@ static int platform_gpio_count(struct device *dev, const char *con_id) struct gpiod_lookup *p; unsigned int count = 0; - table = gpiod_find_lookup_table(dev); - if (!table) - return -ENOENT; + scoped_guard(mutex, &gpio_lookup_lock) { + table = gpiod_find_lookup_table(dev); + if (!table) + return -ENOENT; - for (p = &table->table[0]; p->key; p++) { - if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) || - (!con_id && !p->con_id)) - count++; + for (p = &table->table[0]; p->key; p++) { + if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) || + (!con_id && !p->con_id)) + count++; + } } + if (!count) return -ENOENT; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index a0a67569300b..3ccacf3c1288 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -86,16 +86,6 @@ static inline struct gpio_device *to_gpio_device(struct device *dev) return container_of(dev, struct gpio_device, dev); } -static inline struct gpio_device *gpio_device_get(struct gpio_device *gdev) -{ - return to_gpio_device(get_device(&gdev->dev)); -} - -static inline void gpio_device_put(struct gpio_device *gdev) -{ - put_device(&gdev->dev); -} - /* gpio suffixes used for ACPI and device tree lookup */ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; @@ -122,8 +112,6 @@ struct gpio_array { unsigned long invert_mask[]; }; -struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); - #define for_each_gpio_desc(gc, desc) \ for (unsigned int __i = 0; \ __i < gc->ngpio && (desc = gpiochip_get_desc(gc, __i)); \ @@ -144,6 +132,8 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, struct gpio_array *array_info, unsigned long *value_bitmap); +int gpiod_set_transitory(struct gpio_desc *desc, bool transitory); + extern spinlock_t gpio_lock; extern struct list_head gpio_devices; diff --git a/drivers/hte/Kconfig b/drivers/hte/Kconfig index cf29e0218bae..8e0fd818a73e 100644 --- a/drivers/hte/Kconfig +++ b/drivers/hte/Kconfig @@ -17,6 +17,7 @@ if HTE config HTE_TEGRA194 tristate "NVIDIA Tegra194 HTE Support" depends on ARCH_TEGRA_194_SOC + depends on GPIOLIB help Enable this option for integrated hardware timestamping engine also known as generic timestamping engine (GTE) support on NVIDIA Tegra194 diff --git a/drivers/hte/hte-tegra194.c b/drivers/hte/hte-tegra194.c index 6fe6897047ac..341a134cb7d0 100644 --- a/drivers/hte/hte-tegra194.c +++ b/drivers/hte/hte-tegra194.c @@ -132,7 +132,7 @@ struct tegra_hte_soc { const struct tegra_hte_data *prov_data; struct tegra_hte_line_data *line_data; struct hte_chip *chip; - struct gpio_chip *c; + struct gpio_device *gdev; void __iomem *regs; }; @@ -418,7 +418,7 @@ static int tegra_hte_line_xlate(struct hte_chip *gc, * HTE/GTE namespace. */ if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO && !args) { - line_id = desc->attr.line_id - gs->c->base; + line_id = desc->attr.line_id - gpio_device_get_base(gs->gdev); map = gs->prov_data->map; map_sz = gs->prov_data->map_sz; } else if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO && args) { @@ -645,7 +645,7 @@ static bool tegra_hte_match_from_linedata(const struct hte_chip *chip, if (!hte_dev || (hte_dev->prov_data->type != HTE_TEGRA_TYPE_GPIO)) return false; - return hte_dev->c == gpiod_to_chip(hdesc->attr.line_data); + return hte_dev->gdev == gpiod_to_gpio_device(hdesc->attr.line_data); } static const struct of_device_id tegra_hte_of_match[] = { @@ -673,14 +673,11 @@ static void tegra_gte_disable(void *data) tegra_hte_writel(gs, HTE_TECTRL, 0); } -static int tegra_get_gpiochip_from_name(struct gpio_chip *chip, void *data) +static void tegra_hte_put_gpio_device(void *data) { - return !strcmp(chip->label, data); -} + struct gpio_device *gdev = data; -static int tegra_gpiochip_match(struct gpio_chip *chip, void *data) -{ - return chip->fwnode == of_node_to_fwnode(data); + gpio_device_put(gdev); } static int tegra_hte_probe(struct platform_device *pdev) @@ -760,8 +757,8 @@ static int tegra_hte_probe(struct platform_device *pdev) if (of_device_is_compatible(dev->of_node, "nvidia,tegra194-gte-aon")) { - hte_dev->c = gpiochip_find("tegra194-gpio-aon", - tegra_get_gpiochip_from_name); + hte_dev->gdev = + gpio_device_find_by_label("tegra194-gpio-aon"); } else { gpio_ctrl = of_parse_phandle(dev->of_node, "nvidia,gpio-controller", @@ -772,14 +769,19 @@ static int tegra_hte_probe(struct platform_device *pdev) return -ENODEV; } - hte_dev->c = gpiochip_find(gpio_ctrl, - tegra_gpiochip_match); + hte_dev->gdev = + gpio_device_find_by_fwnode(of_fwnode_handle(gpio_ctrl)); of_node_put(gpio_ctrl); } - if (!hte_dev->c) + if (!hte_dev->gdev) return dev_err_probe(dev, -EPROBE_DEFER, "wait for gpio controller\n"); + + ret = devm_add_action_or_reset(dev, tegra_hte_put_gpio_device, + hte_dev->gdev); + if (ret) + return ret; } hte_dev->chip = gc; diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c index 78d9f52e2a71..1ccdd61b6d13 100644 --- a/drivers/hwmon/xgene-hwmon.c +++ b/drivers/hwmon/xgene-hwmon.c @@ -57,12 +57,6 @@ (MSG_TYPE_SET(MSG_TYPE_PWRMGMT) | \ MSG_SUBTYPE_SET(hndl) | TPC_CMD_SET(cmd) | type) -/* PCC defines */ -#define PCC_SIGNATURE_MASK 0x50424300 -#define PCCC_GENERATE_DB_INT BIT(15) -#define PCCS_CMD_COMPLETE BIT(0) -#define PCCS_SCI_DOORBEL BIT(1) -#define PCCS_PLATFORM_NOTIFICATION BIT(3) /* * Arbitrary retries in case the remote processor is slow to respond * to PCC commands @@ -142,15 +136,15 @@ static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg) /* Write signature for subspace */ WRITE_ONCE(generic_comm_base->signature, - cpu_to_le32(PCC_SIGNATURE_MASK | ctx->mbox_idx)); + cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx)); /* Write to the shared command region */ WRITE_ONCE(generic_comm_base->command, - cpu_to_le16(MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT)); + cpu_to_le16(MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR)); /* Flip CMD COMPLETE bit */ val = le16_to_cpu(READ_ONCE(generic_comm_base->status)); - val &= ~PCCS_CMD_COMPLETE; + val &= ~PCC_STATUS_CMD_COMPLETE; WRITE_ONCE(generic_comm_base->status, cpu_to_le16(val)); /* Copy the message to the PCC comm space */ @@ -544,7 +538,7 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg) msg = generic_comm_base + 1; /* Check if platform sends interrupt */ if (!xgene_word_tst_and_clr(&generic_comm_base->status, - PCCS_SCI_DOORBEL)) + PCC_STATUS_SCI_DOORBELL)) return; /* @@ -566,7 +560,7 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg) TPC_CMD(((u32 *)msg)[0]) == TPC_ALARM))) { /* Check if platform completes command */ if (xgene_word_tst_and_clr(&generic_comm_base->status, - PCCS_CMD_COMPLETE)) { + PCC_STATUS_CMD_COMPLETE)) { ctx->sync_msg.msg = ((u32 *)msg)[0]; ctx->sync_msg.param1 = ((u32 *)msg)[1]; ctx->sync_msg.param2 = ((u32 *)msg)[2]; diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index fbc1ffbd2fa7..658396c9eeab 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -91,14 +91,6 @@ #define SLIMPRO_IIC_MSG_DWORD_COUNT 3 -/* PCC related defines */ -#define PCC_SIGNATURE 0x50424300 -#define PCC_STS_CMD_COMPLETE BIT(0) -#define PCC_STS_SCI_DOORBELL BIT(1) -#define PCC_STS_ERR BIT(2) -#define PCC_STS_PLAT_NOTIFY BIT(3) -#define PCC_CMD_GENERATE_DB_INT BIT(15) - struct slimpro_i2c_dev { struct i2c_adapter adapter; struct device *dev; @@ -160,11 +152,11 @@ static void slimpro_i2c_pcc_rx_cb(struct mbox_client *cl, void *msg) /* Check if platform sends interrupt */ if (!xgene_word_tst_and_clr(&generic_comm_base->status, - PCC_STS_SCI_DOORBELL)) + PCC_STATUS_SCI_DOORBELL)) return; if (xgene_word_tst_and_clr(&generic_comm_base->status, - PCC_STS_CMD_COMPLETE)) { + PCC_STATUS_CMD_COMPLETE)) { msg = generic_comm_base + 1; /* Response message msg[1] contains the return value. */ @@ -186,10 +178,10 @@ static void slimpro_i2c_pcc_tx_prepare(struct slimpro_i2c_dev *ctx, u32 *msg) cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx)); WRITE_ONCE(generic_comm_base->command, - cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INT)); + cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR)); status = le16_to_cpu(READ_ONCE(generic_comm_base->status)); - status &= ~PCC_STS_CMD_COMPLETE; + status &= ~PCC_STATUS_CMD_COMPLETE; WRITE_ONCE(generic_comm_base->status, cpu_to_le16(status)); /* Copy the message to the PCC comm space */ diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 5ca03bd34c8d..78987ead6be0 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -14,8 +14,7 @@ #include #include #include -/* FIXME: stop poking around inside gpiolib */ -#include "../../gpio/gpiolib.h" +#include struct gpiomux { struct i2c_mux_gpio_platform_data data; @@ -178,7 +177,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) } for (i = 0; i < ngpios; i++) { - struct device *gpio_dev; + struct gpio_device *gdev; + struct device *dev; struct gpio_desc *gpiod; enum gpiod_flags flag; @@ -197,9 +197,9 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) if (!muxc->mux_locked) continue; - /* FIXME: find a proper way to access the GPIO device */ - gpio_dev = &gpiod->gdev->dev; - muxc->mux_locked = i2c_root_adapter(gpio_dev) == root; + gdev = gpiod_to_gpio_device(gpiod); + dev = gpio_device_to_device(gdev); + muxc->mux_locked = i2c_root_adapter(dev) == root; } if (muxc->mux_locked) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index a44d4b3e5beb..94885e411085 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -91,6 +91,14 @@ struct pcc_chan_reg { * @cmd_update: PCC register bundle for the command complete update register * @error: PCC register bundle for the error status register * @plat_irq: platform interrupt + * @type: PCC subspace type + * @plat_irq_flags: platform interrupt flags + * @chan_in_use: this flag is used just to check if the interrupt needs + * handling when it is shared. Since only one transfer can occur + * at a time and mailbox takes care of locking, this flag can be + * accessed without a lock. Note: the type only support the + * communication from OSPM to Platform, like type3, use it, and + * other types completely ignore it. */ struct pcc_chan_info { struct pcc_mbox_chan chan; @@ -100,12 +108,17 @@ struct pcc_chan_info { struct pcc_chan_reg cmd_update; struct pcc_chan_reg error; int plat_irq; + u8 type; + unsigned int plat_irq_flags; + bool chan_in_use; }; #define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan) static struct pcc_chan_info *chan_info; static int pcc_chan_count; +static int pcc_send_data(struct mbox_chan *chan, void *data); + /* * PCC can be used with perf critical drivers such as CPPC * So it makes sense to locally cache the virtual address and @@ -221,6 +234,41 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags) return acpi_register_gsi(NULL, interrupt, trigger, polarity); } +static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan) +{ + return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) == + ACPI_LEVEL_SENSITIVE; +} + +static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) +{ + u64 val; + int ret; + + ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); + if (ret) + return false; + + if (!pchan->cmd_complete.gas) + return true; + + /* + * Judge if the channel respond the interrupt based on the value of + * command complete. + */ + val &= pchan->cmd_complete.status_mask; + + /* + * If this is PCC slave subspace channel, and the command complete + * bit 0 indicates that Platform is sending a notification and OSPM + * needs to respond this interrupt to process this command. + */ + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) + return !val; + + return !!val; +} + /** * pcc_mbox_irq - PCC mailbox interrupt handler * @irq: interrupt number @@ -236,16 +284,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) int ret; pchan = chan->con_priv; - - ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); - if (ret) + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE && + !pchan->chan_in_use) return IRQ_NONE; - if (val) { /* Ensure GAS exists and value is non-zero */ - val &= pchan->cmd_complete.status_mask; - if (!val) - return IRQ_NONE; - } + if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; ret = pcc_chan_reg_read(&pchan->error, &val); if (ret) @@ -262,6 +306,16 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) mbox_chan_received_data(chan, NULL); + /* + * The PCC slave subspace channel needs to set the command complete bit + * and ring doorbell after processing message. + * + * The PCC master subspace channel clears chan_in_use to free channel. + */ + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) + pcc_send_data(chan, NULL); + pchan->chan_in_use = false; + return IRQ_HANDLED; } @@ -340,7 +394,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) if (ret) return ret; - return pcc_chan_reg_read_modify_write(&pchan->db); + ret = pcc_chan_reg_read_modify_write(&pchan->db); + if (!ret && pchan->plat_irq > 0) + pchan->chan_in_use = true; + + return ret; } /** @@ -353,11 +411,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) static int pcc_startup(struct mbox_chan *chan) { struct pcc_chan_info *pchan = chan->con_priv; + unsigned long irqflags; int rc; if (pchan->plat_irq > 0) { - rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0, - MBOX_IRQ_NAME, chan); + irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ? + IRQF_SHARED | IRQF_ONESHOT : 0; + rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, + irqflags, MBOX_IRQ_NAME, chan); if (unlikely(rc)) { dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n", pchan->plat_irq); @@ -463,6 +524,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, pcct_ss->platform_interrupt); return -EINVAL; } + pchan->plat_irq_flags = pcct_ss->flags; if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) { struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss; @@ -484,6 +546,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, "PLAT IRQ ACK"); } + if (pcc_chan_plat_irq_can_be_shared(pchan) && + !pchan->plat_irq_ack.gas) { + pr_err("PCC subspace has level IRQ with no ACK register\n"); + return -EINVAL; + } + return ret; } @@ -698,6 +766,7 @@ static int pcc_mbox_probe(struct platform_device *pdev) pcc_parse_subspace_shmem(pchan, pcct_entry); + pchan->type = pcct_entry->type; pcct_entry = (struct acpi_subtable_header *) ((unsigned long) pcct_entry + pcct_entry->length); } diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c index 6748226b8bd1..c816dc137245 100644 --- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c +++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c @@ -380,18 +380,6 @@ static int ingenic_nand_init_chip(struct platform_device *pdev, return ret; } - /* - * The rb-gpios semantics was undocumented and qi,lb60 (along with - * the ingenic driver) got it wrong. The active state encodes the - * NAND ready state, which is high level. Since there's no signal - * inverter on this board, it should be active-high. Let's fix that - * here for older DTs so we can re-use the generic nand_gpio_waitrdy() - * helper, and be consistent with what other drivers do. - */ - if (of_machine_is_compatible("qi,lb60") && - gpiod_is_active_low(nand->busy_gpio)) - gpiod_toggle_active_low(nand->busy_gpio); - nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); if (IS_ERR(nand->wp_gpio)) { diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 919cc53bc02e..84f345c69ea5 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -813,6 +813,31 @@ struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, } EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_ceil); +/** + * dev_pm_opp_find_level_floor() - Search for a rounded floor level + * @dev: device for which we do this operation + * @level: Start level + * + * Search for the matching floor *available* OPP from a starting level + * for a device. + * + * Return: matching *opp and refreshes *level accordingly, else returns + * ERR_PTR in case of error and should be handled using IS_ERR. Error return + * values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp *dev_pm_opp_find_level_floor(struct device *dev, + unsigned long *level) +{ + return _find_key_floor(dev, level, 0, true, _read_level, NULL); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_floor); + /** * dev_pm_opp_find_bw_ceil() - Search for a rounded ceil bandwidth * @dev: device for which we do this operation @@ -1030,7 +1055,7 @@ static int _set_performance_state(struct device *dev, struct device *pd_dev, if (!pd_dev) return 0; - ret = dev_pm_genpd_set_performance_state(pd_dev, pstate); + ret = dev_pm_domain_set_performance_state(pd_dev, pstate); if (ret) { dev_err(dev, "Failed to set performance state of %s: %d (%d)\n", dev_name(pd_dev), pstate, ret); @@ -1051,32 +1076,28 @@ static int _opp_set_required_opps_genpd(struct device *dev, { struct device **genpd_virt_devs = opp_table->genpd_virt_devs ? opp_table->genpd_virt_devs : &dev; - int i, ret = 0; - - /* - * Acquire genpd_virt_dev_lock to make sure we don't use a genpd_dev - * after it is freed from another thread. - */ - mutex_lock(&opp_table->genpd_virt_dev_lock); + int index, target, delta, ret; /* Scaling up? Set required OPPs in normal order, else reverse */ if (!scaling_down) { - for (i = 0; i < opp_table->required_opp_count; i++) { - ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i); - if (ret) - break; - } + index = 0; + target = opp_table->required_opp_count; + delta = 1; } else { - for (i = opp_table->required_opp_count - 1; i >= 0; i--) { - ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i); - if (ret) - break; - } + index = opp_table->required_opp_count - 1; + target = -1; + delta = -1; } - mutex_unlock(&opp_table->genpd_virt_dev_lock); + while (index != target) { + ret = _set_performance_state(dev, genpd_virt_devs[index], opp, index); + if (ret) + return ret; - return ret; + index += delta; + } + + return 0; } /* This is only called for PM domain for now */ @@ -1107,6 +1128,28 @@ void _update_set_required_opps(struct opp_table *opp_table) opp_table->set_required_opps = _opp_set_required_opps_generic; } +static int _set_opp_level(struct device *dev, struct opp_table *opp_table, + struct dev_pm_opp *opp) +{ + unsigned int level = 0; + int ret = 0; + + if (opp) { + if (!opp->level) + return 0; + + level = opp->level; + } + + /* Request a new performance state through the device's PM domain. */ + ret = dev_pm_domain_set_performance_state(dev, level); + if (ret) + dev_err(dev, "Failed to set performance state %u (%d)\n", level, + ret); + + return ret; +} + static void _find_current_opp(struct device *dev, struct opp_table *opp_table) { struct dev_pm_opp *opp = ERR_PTR(-ENODEV); @@ -1154,8 +1197,13 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table) if (opp_table->regulators) regulator_disable(opp_table->regulators[0]); + ret = _set_opp_level(dev, opp_table, NULL); + if (ret) + goto out; + ret = _set_required_opps(dev, opp_table, NULL, false); +out: opp_table->enabled = false; return ret; } @@ -1198,6 +1246,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, return ret; } + ret = _set_opp_level(dev, opp_table, opp); + if (ret) + return ret; + ret = _set_opp_bw(opp_table, opp, dev); if (ret) { dev_err(dev, "Failed to set bw: %d\n", ret); @@ -1241,6 +1293,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, return ret; } + ret = _set_opp_level(dev, opp_table, opp); + if (ret) + return ret; + ret = _set_required_opps(dev, opp_table, opp, false); if (ret) { dev_err(dev, "Failed to set required opps: %d\n", ret); @@ -1410,7 +1466,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) return ERR_PTR(-ENOMEM); mutex_init(&opp_table->lock); - mutex_init(&opp_table->genpd_virt_dev_lock); INIT_LIST_HEAD(&opp_table->dev_list); INIT_LIST_HEAD(&opp_table->lazy); @@ -1446,7 +1501,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) remove_opp_dev: _of_clear_opp_table(opp_table); _remove_opp_dev(opp_dev, opp_table); - mutex_destroy(&opp_table->genpd_virt_dev_lock); mutex_destroy(&opp_table->lock); err: kfree(opp_table); @@ -1614,7 +1668,6 @@ static void _opp_table_kref_release(struct kref *kref) list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) _remove_opp_dev(opp_dev, opp_table); - mutex_destroy(&opp_table->genpd_virt_dev_lock); mutex_destroy(&opp_table->lock); kfree(opp_table); } @@ -2002,8 +2055,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, * _opp_add_v1() - Allocate a OPP based on v1 bindings. * @opp_table: OPP table * @dev: device for which we do this operation - * @freq: Frequency in Hz for this OPP - * @u_volt: Voltage in uVolts for this OPP + * @data: The OPP data for the OPP to add * @dynamic: Dynamically added OPPs. * * This function adds an opp definition to the opp table and returns status. @@ -2021,10 +2073,10 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, * -ENOMEM Memory allocation failure */ int _opp_add_v1(struct opp_table *opp_table, struct device *dev, - unsigned long freq, long u_volt, bool dynamic) + struct dev_pm_opp_data *data, bool dynamic) { struct dev_pm_opp *new_opp; - unsigned long tol; + unsigned long tol, u_volt = data->u_volt; int ret; if (!assert_single_clk(opp_table)) @@ -2035,7 +2087,8 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev, return -ENOMEM; /* populate the opp table */ - new_opp->rates[0] = freq; + new_opp->rates[0] = data->freq; + new_opp->level = data->level; tol = u_volt * opp_table->voltage_tolerance_v1 / 100; new_opp->supplies[0].u_volt = u_volt; new_opp->supplies[0].u_volt_min = u_volt - tol; @@ -2064,12 +2117,7 @@ free_opp: return ret; } -/** - * _opp_set_supported_hw() - Set supported platforms - * @dev: Device for which supported-hw has to be set. - * @versions: Array of hierarchy of versions to match. - * @count: Number of elements in the array. - * +/* * This is required only for the V2 bindings, and it enables a platform to * specify the hierarchy of versions it supports. OPP layer will then enable * OPPs, which are available for those versions, based on its 'opp-supported-hw' @@ -2092,14 +2140,6 @@ static int _opp_set_supported_hw(struct opp_table *opp_table, return 0; } -/** - * _opp_put_supported_hw() - Releases resources blocked for supported hw - * @opp_table: OPP table returned by _opp_set_supported_hw(). - * - * This is required only for the V2 bindings, and is called for a matching - * _opp_set_supported_hw(). Until this is called, the opp_table structure - * will not be freed. - */ static void _opp_put_supported_hw(struct opp_table *opp_table) { if (opp_table->supported_hw) { @@ -2109,11 +2149,7 @@ static void _opp_put_supported_hw(struct opp_table *opp_table) } } -/** - * _opp_set_prop_name() - Set prop-extn name - * @dev: Device for which the prop-name has to be set. - * @name: name to postfix to properties. - * +/* * This is required only for the V2 bindings, and it enables a platform to * specify the extn to be used for certain property names. The properties to * which the extension will apply are opp-microvolt and opp-microamp. OPP core @@ -2131,14 +2167,6 @@ static int _opp_set_prop_name(struct opp_table *opp_table, const char *name) return 0; } -/** - * _opp_put_prop_name() - Releases resources blocked for prop-name - * @opp_table: OPP table returned by _opp_set_prop_name(). - * - * This is required only for the V2 bindings, and is called for a matching - * _opp_set_prop_name(). Until this is called, the opp_table structure - * will not be freed. - */ static void _opp_put_prop_name(struct opp_table *opp_table) { if (opp_table->prop_name) { @@ -2147,12 +2175,7 @@ static void _opp_put_prop_name(struct opp_table *opp_table) } } -/** - * _opp_set_regulators() - Set regulator names for the device - * @dev: Device for which regulator name is being set. - * @names: Array of pointers to the names of the regulator. - * @count: Number of regulators. - * +/* * In order to support OPP switching, OPP layer needs to know the name of the * device's regulators, as the core would be required to switch voltages as * well. @@ -2214,10 +2237,6 @@ free_regulators: return ret; } -/** - * _opp_put_regulators() - Releases resources blocked for regulator - * @opp_table: OPP table returned from _opp_set_regulators(). - */ static void _opp_put_regulators(struct opp_table *opp_table) { int i; @@ -2249,11 +2268,7 @@ static void _put_clks(struct opp_table *opp_table, int count) opp_table->clks = NULL; } -/** - * _opp_set_clknames() - Set clk names for the device - * @dev: Device for which clk names is being set. - * @names: Clk names. - * +/* * In order to support OPP switching, OPP layer needs to get pointers to the * clocks for the device. Simple cases work fine without using this routine * (i.e. by passing connection-id as NULL), but for a device with multiple @@ -2337,10 +2352,6 @@ free_clks: return ret; } -/** - * _opp_put_clknames() - Releases resources blocked for clks. - * @opp_table: OPP table returned from _opp_set_clknames(). - */ static void _opp_put_clknames(struct opp_table *opp_table) { if (!opp_table->clks) @@ -2352,11 +2363,7 @@ static void _opp_put_clknames(struct opp_table *opp_table) _put_clks(opp_table, opp_table->clk_count); } -/** - * _opp_set_config_regulators_helper() - Register custom set regulator helper. - * @dev: Device for which the helper is getting registered. - * @config_regulators: Custom set regulator helper. - * +/* * This is useful to support platforms with multiple regulators per device. * * This must be called before any OPPs are initialized for the device. @@ -2371,20 +2378,13 @@ static int _opp_set_config_regulators_helper(struct opp_table *opp_table, return 0; } -/** - * _opp_put_config_regulators_helper() - Releases resources blocked for - * config_regulators helper. - * @opp_table: OPP table returned from _opp_set_config_regulators_helper(). - * - * Release resources blocked for platform specific config_regulators helper. - */ static void _opp_put_config_regulators_helper(struct opp_table *opp_table) { if (opp_table->config_regulators) opp_table->config_regulators = NULL; } -static void _detach_genpd(struct opp_table *opp_table) +static void _opp_detach_genpd(struct opp_table *opp_table) { int index; @@ -2403,12 +2403,7 @@ static void _detach_genpd(struct opp_table *opp_table) opp_table->genpd_virt_devs = NULL; } -/** - * _opp_attach_genpd - Attach genpd(s) for the device and save virtual device pointer - * @dev: Consumer device for which the genpd is getting attached. - * @names: Null terminated array of pointers containing names of genpd to attach. - * @virt_devs: Pointer to return the array of virtual devices. - * +/* * Multiple generic power domains for a device are supported with the help of * virtual genpd devices, which are created for each consumer device - genpd * pair. These are the device structures which are attached to the power domain @@ -2435,21 +2430,11 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, if (opp_table->genpd_virt_devs) return 0; - /* - * If the genpd's OPP table isn't already initialized, parsing of the - * required-opps fail for dev. We should retry this after genpd's OPP - * table is added. - */ - if (!opp_table->required_opp_count) - return -EPROBE_DEFER; - - mutex_lock(&opp_table->genpd_virt_dev_lock); - opp_table->genpd_virt_devs = kcalloc(opp_table->required_opp_count, sizeof(*opp_table->genpd_virt_devs), GFP_KERNEL); if (!opp_table->genpd_virt_devs) - goto unlock; + return -ENOMEM; while (*name) { if (index >= opp_table->required_opp_count) { @@ -2472,36 +2457,15 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, if (virt_devs) *virt_devs = opp_table->genpd_virt_devs; - mutex_unlock(&opp_table->genpd_virt_dev_lock); return 0; err: - _detach_genpd(opp_table); -unlock: - mutex_unlock(&opp_table->genpd_virt_dev_lock); + _opp_detach_genpd(opp_table); return ret; } -/** - * _opp_detach_genpd() - Detach genpd(s) from the device. - * @opp_table: OPP table returned by _opp_attach_genpd(). - * - * This detaches the genpd(s), resets the virtual device pointers, and puts the - * OPP table. - */ -static void _opp_detach_genpd(struct opp_table *opp_table) -{ - /* - * Acquire genpd_virt_dev_lock to make sure virt_dev isn't getting - * used in parallel. - */ - mutex_lock(&opp_table->genpd_virt_dev_lock); - _detach_genpd(opp_table); - mutex_unlock(&opp_table->genpd_virt_dev_lock); -} - static void _opp_clear_config(struct opp_config_data *data) { if (data->flags & OPP_CONFIG_GENPD) @@ -2642,7 +2606,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_config); /** * dev_pm_opp_clear_config() - Releases resources blocked for OPP configuration. - * @opp_table: OPP table returned from dev_pm_opp_set_config(). + * @token: The token returned by dev_pm_opp_set_config() previously. * * This allows all device OPP configurations to be cleared at once. This must be * called once for each call made to dev_pm_opp_set_config(), in order to free @@ -2825,10 +2789,9 @@ unlock: } /** - * dev_pm_opp_add() - Add an OPP table from a table definitions - * @dev: device for which we do this operation - * @freq: Frequency in Hz for this OPP - * @u_volt: Voltage in uVolts for this OPP + * dev_pm_opp_add_dynamic() - Add an OPP table from a table definitions + * @dev: The device for which we do this operation + * @data: The OPP data for the OPP to add * * This function adds an opp definition to the opp table and returns status. * The opp is made available by default and it can be controlled using @@ -2841,7 +2804,7 @@ unlock: * Duplicate OPPs (both freq and volt are same) and !opp->available * -ENOMEM Memory allocation failure */ -int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) +int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *data) { struct opp_table *opp_table; int ret; @@ -2853,13 +2816,13 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) /* Fix regulator count for dynamic OPPs */ opp_table->regulator_count = 1; - ret = _opp_add_v1(opp_table, dev, freq, u_volt, true); + ret = _opp_add_v1(opp_table, dev, data, true); if (ret) dev_pm_opp_put_opp_table(opp_table); return ret; } -EXPORT_SYMBOL_GPL(dev_pm_opp_add); +EXPORT_SYMBOL_GPL(dev_pm_opp_add_dynamic); /** * _opp_set_availability() - helper to set the availability of an opp diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c index 17543c0aa5b6..ec030b19164a 100644 --- a/drivers/opp/debugfs.c +++ b/drivers/opp/debugfs.c @@ -56,7 +56,7 @@ static void opp_debug_create_bw(struct dev_pm_opp *opp, struct dentry *pdentry) { struct dentry *d; - char name[11]; + char name[20]; int i; for (i = 0; i < opp_table->path_count; i++) { diff --git a/drivers/opp/of.c b/drivers/opp/of.c index ada4963c7cfa..81fa27599d58 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -208,9 +208,9 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, mutex_lock(&opp_table_lock); list_add(&opp_table->lazy, &lazy_opp_tables); mutex_unlock(&opp_table_lock); - } - else + } else { _update_set_required_opps(opp_table); + } goto put_np; @@ -296,24 +296,41 @@ void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) of_node_put(opp->np); } +static int _link_required_opps(struct dev_pm_opp *opp, + struct opp_table *required_table, int index) +{ + struct device_node *np; + + np = of_parse_required_opp(opp->np, index); + if (unlikely(!np)) + return -ENODEV; + + opp->required_opps[index] = _find_opp_of_np(required_table, np); + of_node_put(np); + + if (!opp->required_opps[index]) { + pr_err("%s: Unable to find required OPP node: %pOF (%d)\n", + __func__, opp->np, index); + return -ENODEV; + } + + return 0; +} + /* Populate all required OPPs which are part of "required-opps" list */ static int _of_opp_alloc_required_opps(struct opp_table *opp_table, struct dev_pm_opp *opp) { - struct dev_pm_opp **required_opps; struct opp_table *required_table; - struct device_node *np; int i, ret, count = opp_table->required_opp_count; if (!count) return 0; - required_opps = kcalloc(count, sizeof(*required_opps), GFP_KERNEL); - if (!required_opps) + opp->required_opps = kcalloc(count, sizeof(*opp->required_opps), GFP_KERNEL); + if (!opp->required_opps) return -ENOMEM; - opp->required_opps = required_opps; - for (i = 0; i < count; i++) { required_table = opp_table->required_opp_tables[i]; @@ -321,21 +338,9 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table, if (IS_ERR_OR_NULL(required_table)) continue; - np = of_parse_required_opp(opp->np, i); - if (unlikely(!np)) { - ret = -ENODEV; + ret = _link_required_opps(opp, required_table, i); + if (ret) goto free_required_opps; - } - - required_opps[i] = _find_opp_of_np(required_table, np); - of_node_put(np); - - if (!required_opps[i]) { - pr_err("%s: Unable to find required OPP node: %pOF (%d)\n", - __func__, opp->np, i); - ret = -ENODEV; - goto free_required_opps; - } } return 0; @@ -350,22 +355,13 @@ free_required_opps: static int lazy_link_required_opps(struct opp_table *opp_table, struct opp_table *new_table, int index) { - struct device_node *required_np; struct dev_pm_opp *opp; + int ret; list_for_each_entry(opp, &opp_table->opp_list, node) { - required_np = of_parse_required_opp(opp->np, index); - if (unlikely(!required_np)) - return -ENODEV; - - opp->required_opps[index] = _find_opp_of_np(new_table, required_np); - of_node_put(required_np); - - if (!opp->required_opps[index]) { - pr_err("%s: Unable to find required OPP node: %pOF (%d)\n", - __func__, opp->np, index); - return -ENODEV; - } + ret = _link_required_opps(opp, new_table, index); + if (ret) + return ret; } return 0; @@ -1079,11 +1075,15 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) while (nr) { unsigned long freq = be32_to_cpup(val++) * 1000; unsigned long volt = be32_to_cpup(val++); + struct dev_pm_opp_data data = { + .freq = freq, + .u_volt = volt, + }; - ret = _opp_add_v1(opp_table, dev, freq, volt, false); + ret = _opp_add_v1(opp_table, dev, &data, false); if (ret) { dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", - __func__, freq, ret); + __func__, data.freq, ret); goto remove_static_opp; } nr -= 2; diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 8a5ea38f3a3d..08366f90f16b 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -160,7 +160,6 @@ enum opp_table_access { * @rate_clk_single: Currently configured frequency for single clk. * @current_opp: Currently configured OPP for the table. * @suspend_opp: Pointer to OPP to be used during device suspend. - * @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers. * @genpd_virt_devs: List of virtual devices for multiple genpd support. * @required_opp_tables: List of device OPP tables that are required by OPPs in * this table. @@ -212,7 +211,6 @@ struct opp_table { struct dev_pm_opp *current_opp; struct dev_pm_opp *suspend_opp; - struct mutex genpd_virt_dev_lock; struct device **genpd_virt_devs; struct opp_table **required_opp_tables; unsigned int required_opp_count; @@ -251,7 +249,7 @@ struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table); void _opp_free(struct dev_pm_opp *opp); int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2); int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table); -int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic); +int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic); void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu); struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk); void _put_opp_list_kref(struct opp_table *opp_table); diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 9c8fd69ae5ad..40d84cb0c601 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "../pci.h" @@ -997,6 +998,15 @@ static void aer_recover_work_func(struct work_struct *work) continue; } cper_print_aer(pdev, entry.severity, entry.regs); + /* + * Memory for aer_capability_regs(entry.regs) is being allocated from the + * ghes_estatus_pool to protect it from overwriting when multiple sections + * are present in the error status. Thus free the same after processing + * the data. + */ + ghes_estatus_pool_region_free((unsigned long)entry.regs, + sizeof(struct aer_capability_regs)); + if (entry.severity == AER_NONFATAL) pcie_do_recovery(pdev, pci_channel_io_normal, aer_root_reset); diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c index e2b7827c4563..f0e6d14281d6 100644 --- a/drivers/perf/arm_cspmu/arm_cspmu.c +++ b/drivers/perf/arm_cspmu/arm_cspmu.c @@ -1061,7 +1061,7 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu) static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid) { - u32 acpi_uid; + u64 acpi_uid; struct device *cpu_dev; struct acpi_device *acpi_dev; @@ -1071,10 +1071,8 @@ static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid) acpi_dev = ACPI_COMPANION(cpu_dev); while (acpi_dev) { - if (!strcmp(acpi_device_hid(acpi_dev), - ACPI_PROCESSOR_CONTAINER_HID) && - !kstrtouint(acpi_device_uid(acpi_dev), 0, &acpi_uid) && - acpi_uid == container_uid) + if (acpi_dev_hid_uid_match(acpi_dev, ACPI_PROCESSOR_CONTAINER_HID, NULL) && + !acpi_dev_uid_to_integer(acpi_dev, &acpi_uid) && acpi_uid == container_uid) return 0; acpi_dev = acpi_dev_parent(acpi_dev); diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c index 2887edb4eb0b..f16783d03db7 100644 --- a/drivers/perf/qcom_l3_pmu.c +++ b/drivers/perf/qcom_l3_pmu.c @@ -742,8 +742,8 @@ static int qcom_l3_cache_pmu_probe(struct platform_device *pdev) l3pmu = devm_kzalloc(&pdev->dev, sizeof(*l3pmu), GFP_KERNEL); name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "l3cache_%s_%s", - acpi_dev_parent(acpi_dev)->pnp.unique_id, - acpi_dev->pnp.unique_id); + acpi_device_uid(acpi_dev_parent(acpi_dev)), + acpi_device_uid(acpi_dev)); if (!l3pmu || !name) return -ENOMEM; diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 3be04ab760d3..999f453344d2 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1694,7 +1694,7 @@ const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_ unsigned int i; for (i = 0; table[i]; i++) { - if (!strcmp(adev->pnp.unique_id, table[i]->uid)) { + if (acpi_dev_uid_match(adev, table[i]->uid)) { data = table[i]; break; } diff --git a/drivers/pinctrl/pinctrl-da9062.c b/drivers/pinctrl/pinctrl-da9062.c index 0e0ac3f3ffef..3998b27cbe0e 100644 --- a/drivers/pinctrl/pinctrl-da9062.c +++ b/drivers/pinctrl/pinctrl-da9062.c @@ -17,17 +17,12 @@ #include #include +#include #include #include #include -/* - * We need this get the gpio_desc from a tuple to decide if - * the gpio is active low without a vendor specific dt-binding. - */ -#include "../gpio/gpiolib.h" - #define DA9062_TYPE(offset) (4 * (offset % 2)) #define DA9062_PIN_SHIFT(offset) (4 * (offset % 2)) #define DA9062_PIN_ALTERNATE 0x00 /* gpio alternate mode */ diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c index 897cdd9c3aae..0412a644fece 100644 --- a/drivers/platform/surface/surface_acpi_notify.c +++ b/drivers/platform/surface/surface_acpi_notify.c @@ -741,6 +741,7 @@ static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle) struct acpi_handle_list dep_devices; acpi_handle supplier = ACPI_HANDLE(&pdev->dev); acpi_status status; + bool ret = false; int i; if (!acpi_has_method(handle, "_DEP")) @@ -753,11 +754,14 @@ static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle) } for (i = 0; i < dep_devices.count; i++) { - if (dep_devices.handles[i] == supplier) - return true; + if (dep_devices.handles[i] == supplier) { + ret = true; + break; + } } - return false; + acpi_handle_list_free(&dep_devices); + return ret; } static acpi_status san_consumer_setup(acpi_handle handle, u32 lvl, diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index ef4b3141efcd..16e36ac0a7b4 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -162,9 +162,8 @@ out_free_init_name: } int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity) + struct gpio_desc *gpio) { - char *path = agpio->resource_source.string_ptr; struct clk_init_data init = { .ops = &skl_int3472_clock_ops, .flags = CLK_GET_RATE_NOCACHE, @@ -174,26 +173,12 @@ int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, if (int3472->clock.cl) return -EBUSY; - int3472->clock.ena_gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0], - "int3472,clk-enable"); - if (IS_ERR(int3472->clock.ena_gpio)) { - ret = PTR_ERR(int3472->clock.ena_gpio); - int3472->clock.ena_gpio = NULL; - return dev_err_probe(int3472->dev, ret, "getting clk-enable GPIO\n"); - } - - if (polarity == GPIO_ACTIVE_LOW) - gpiod_toggle_active_low(int3472->clock.ena_gpio); - - /* Ensure the pin is in output mode and non-active state */ - gpiod_direction_output(int3472->clock.ena_gpio, 0); + int3472->clock.ena_gpio = gpio; init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(int3472->adev)); - if (!init.name) { - ret = -ENOMEM; - goto out_put_gpio; - } + if (!init.name) + return -ENOMEM; int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472); @@ -219,8 +204,6 @@ err_unregister_clk: clk_unregister(int3472->clock.clk); out_free_init_name: kfree(init.name); -out_put_gpio: - gpiod_put(int3472->clock.ena_gpio); return ret; } @@ -232,7 +215,6 @@ void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472) clkdev_drop(int3472->clock.cl); clk_unregister(int3472->clock.clk); - gpiod_put(int3472->clock.ena_gpio); } /* @@ -273,14 +255,13 @@ static const struct dmi_system_id skl_int3472_regulator_second_sensor[] = { }; int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio) + struct gpio_desc *gpio) { - char *path = agpio->resource_source.string_ptr; struct regulator_init_data init_data = { }; struct regulator_config cfg = { }; const char *second_sensor = NULL; const struct dmi_system_id *id; - int i, j, ret; + int i, j; id = dmi_first_match(skl_int3472_regulator_second_sensor); if (id) @@ -314,16 +295,7 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, int3472->regulator.supply_name, &int3472_gpio_regulator_ops); - int3472->regulator.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0], - "int3472,regulator"); - if (IS_ERR(int3472->regulator.gpio)) { - ret = PTR_ERR(int3472->regulator.gpio); - int3472->regulator.gpio = NULL; - return dev_err_probe(int3472->dev, ret, "getting regulator GPIO\n"); - } - - /* Ensure the pin is in output mode and non-active state */ - gpiod_direction_output(int3472->regulator.gpio, 0); + int3472->regulator.gpio = gpio; cfg.dev = &int3472->adev->dev; cfg.init_data = &init_data; @@ -332,21 +304,11 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, int3472->regulator.rdev = regulator_register(int3472->dev, &int3472->regulator.rdesc, &cfg); - if (IS_ERR(int3472->regulator.rdev)) { - ret = PTR_ERR(int3472->regulator.rdev); - goto err_free_gpio; - } - return 0; - -err_free_gpio: - gpiod_put(int3472->regulator.gpio); - - return ret; + return PTR_ERR_OR_ZERO(int3472->regulator.rdev); } void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472) { regulator_unregister(int3472->regulator.rdev); - gpiod_put(int3472->regulator.gpio); } diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h index 9f29baa13860..145dec66df64 100644 --- a/drivers/platform/x86/intel/int3472/common.h +++ b/drivers/platform/x86/intel/int3472/common.h @@ -117,16 +117,15 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev, const char **name_ret); int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity); + struct gpio_desc *gpio); int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472); void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio); + struct gpio_desc *gpio); void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472); -int skl_int3472_register_pled(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity); +int skl_int3472_register_pled(struct int3472_discrete_device *int3472, struct gpio_desc *gpio); void skl_int3472_unregister_pled(struct int3472_discrete_device *int3472); #endif diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index e33c2d75975c..07b302e09340 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -52,21 +52,15 @@ static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *i } } -static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, - const char *func, u32 polarity) +static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, + struct acpi_resource_gpio *agpio, + const char *func, u32 polarity) { char *path = agpio->resource_source.string_ptr; - struct gpiod_lookup *table_entry; struct acpi_device *adev; acpi_handle handle; acpi_status status; - if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) { - dev_warn(int3472->dev, "Too many GPIOs mapped\n"); - return -EINVAL; - } - status = acpi_get_handle(NULL, path, &handle); if (ACPI_FAILURE(status)) return -EINVAL; @@ -75,18 +69,62 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 if (!adev) return -ENODEV; - table_entry = &int3472->gpios.table[int3472->n_sensor_gpios]; table_entry->key = acpi_dev_name(adev); table_entry->chip_hwnum = agpio->pin_table[0]; table_entry->con_id = func; table_entry->idx = 0; table_entry->flags = polarity; + return 0; +} + +static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, + struct acpi_resource_gpio *agpio, + const char *func, u32 polarity) +{ + int ret; + + if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) { + dev_warn(int3472->dev, "Too many GPIOs mapped\n"); + return -EINVAL; + } + + ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios], + agpio, func, polarity); + if (ret) + return ret; + int3472->n_sensor_gpios++; return 0; } +/* This should *really* only be used when there's no other way... */ +static struct gpio_desc * +skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, + struct acpi_resource_gpio *agpio, + const char *func, u32 polarity) +{ + struct gpio_desc *desc; + int ret; + + struct gpiod_lookup_table *lookup __free(kfree) = + kzalloc(struct_size(lookup, table, 2), GFP_KERNEL); + if (!lookup) + return ERR_PTR(-ENOMEM); + + lookup->dev_id = dev_name(int3472->dev); + ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, polarity); + if (ret) + return ERR_PTR(ret); + + gpiod_add_lookup_table(lookup); + desc = devm_gpiod_get(int3472->dev, func, GPIOD_OUT_LOW); + gpiod_remove_lookup_table(lookup); + + return desc; +} + static void int3472_get_func_and_polarity(u8 type, const char **func, u32 *polarity) { switch (type) { @@ -156,6 +194,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, struct acpi_resource_gpio *agpio; u8 active_value, pin, type; union acpi_object *obj; + struct gpio_desc *gpio; const char *err_msg; const char *func; u32 polarity; @@ -206,22 +245,38 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, break; case INT3472_GPIO_TYPE_CLK_ENABLE: - ret = skl_int3472_register_gpio_clock(int3472, agpio, polarity); - if (ret) - err_msg = "Failed to register clock\n"; - - break; case INT3472_GPIO_TYPE_PRIVACY_LED: - ret = skl_int3472_register_pled(int3472, agpio, polarity); - if (ret) - err_msg = "Failed to register LED\n"; - - break; case INT3472_GPIO_TYPE_POWER_ENABLE: - ret = skl_int3472_register_regulator(int3472, agpio); - if (ret) - err_msg = "Failed to map regulator to sensor\n"; + gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, polarity); + if (IS_ERR(gpio)) { + ret = PTR_ERR(gpio); + err_msg = "Failed to get GPIO\n"; + break; + } + switch (type) { + case INT3472_GPIO_TYPE_CLK_ENABLE: + ret = skl_int3472_register_gpio_clock(int3472, gpio); + if (ret) + err_msg = "Failed to register clock\n"; + + break; + case INT3472_GPIO_TYPE_PRIVACY_LED: + ret = skl_int3472_register_pled(int3472, gpio); + if (ret) + err_msg = "Failed to register LED\n"; + + break; + case INT3472_GPIO_TYPE_POWER_ENABLE: + ret = skl_int3472_register_regulator(int3472, gpio); + if (ret) + err_msg = "Failed to map regulator to sensor\n"; + + break; + default: /* Never reached */ + ret = -EINVAL; + break; + } break; default: dev_warn(int3472->dev, diff --git a/drivers/platform/x86/intel/int3472/led.c b/drivers/platform/x86/intel/int3472/led.c index bca1ce7d0d0c..9cbed694e2ca 100644 --- a/drivers/platform/x86/intel/int3472/led.c +++ b/drivers/platform/x86/intel/int3472/led.c @@ -16,26 +16,15 @@ static int int3472_pled_set(struct led_classdev *led_cdev, return 0; } -int skl_int3472_register_pled(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity) +int skl_int3472_register_pled(struct int3472_discrete_device *int3472, struct gpio_desc *gpio) { - char *p, *path = agpio->resource_source.string_ptr; + char *p; int ret; if (int3472->pled.classdev.dev) return -EBUSY; - int3472->pled.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0], - "int3472,privacy-led"); - if (IS_ERR(int3472->pled.gpio)) - return dev_err_probe(int3472->dev, PTR_ERR(int3472->pled.gpio), - "getting privacy LED GPIO\n"); - - if (polarity == GPIO_ACTIVE_LOW) - gpiod_toggle_active_low(int3472->pled.gpio); - - /* Ensure the pin is in output mode and non-active state */ - gpiod_direction_output(int3472->pled.gpio, 0); + int3472->pled.gpio = gpio; /* Generate the name, replacing the ':' in the ACPI devname with '_' */ snprintf(int3472->pled.name, sizeof(int3472->pled.name), @@ -50,7 +39,7 @@ int skl_int3472_register_pled(struct int3472_discrete_device *int3472, ret = led_classdev_register(int3472->dev, &int3472->pled.classdev); if (ret) - goto err_free_gpio; + return ret; int3472->pled.lookup.provider = int3472->pled.name; int3472->pled.lookup.dev_id = int3472->sensor_name; @@ -58,10 +47,6 @@ int skl_int3472_register_pled(struct int3472_discrete_device *int3472, led_add_lookup(&int3472->pled.lookup); return 0; - -err_free_gpio: - gpiod_put(int3472->pled.gpio); - return ret; } void skl_int3472_unregister_pled(struct int3472_discrete_device *int3472) @@ -71,5 +56,4 @@ void skl_int3472_unregister_pled(struct int3472_discrete_device *int3472) led_remove_lookup(&int3472->pled.lookup); led_classdev_unregister(&int3472->pled.classdev); - gpiod_put(int3472->pled.gpio); } diff --git a/drivers/platform/x86/x86-android-tablets/asus.c b/drivers/platform/x86/x86-android-tablets/asus.c index f9c4083be86d..227afbb51078 100644 --- a/drivers/platform/x86/x86-android-tablets/asus.c +++ b/drivers/platform/x86/x86-android-tablets/asus.c @@ -303,6 +303,7 @@ static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst = .index = 28, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "atmel_mxt_ts_irq", }, }, }; diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c index 2fd6060a31bb..8a1f22aaac00 100644 --- a/drivers/platform/x86/x86-android-tablets/core.c +++ b/drivers/platform/x86/x86-android-tablets/core.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -21,33 +21,39 @@ #include #include "x86-android-tablets.h" -/* For gpiochip_get_desc() which is EXPORT_SYMBOL_GPL() */ -#include "../../../gpio/gpiolib.h" -#include "../../../gpio/gpiolib-acpi.h" -static int gpiochip_find_match_label(struct gpio_chip *gc, void *data) -{ - return gc->label && !strcmp(gc->label, data); -} +static struct platform_device *x86_android_tablet_device; -int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc) +int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, + bool active_low, enum gpiod_flags dflags, + struct gpio_desc **desc) { + struct gpiod_lookup_table *lookup; struct gpio_desc *gpiod; - struct gpio_chip *chip; - chip = gpiochip_find((void *)label, gpiochip_find_match_label); - if (!chip) { - pr_err("error cannot find GPIO chip %s\n", label); - return -ENODEV; - } + lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL); + if (!lookup) + return -ENOMEM; + + lookup->dev_id = KBUILD_MODNAME; + lookup->table[0].key = chip; + lookup->table[0].chip_hwnum = pin; + lookup->table[0].con_id = con_id; + lookup->table[0].flags = active_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH; + + gpiod_add_lookup_table(lookup); + gpiod = devm_gpiod_get(&x86_android_tablet_device->dev, con_id, dflags); + gpiod_remove_lookup_table(lookup); + kfree(lookup); - gpiod = gpiochip_get_desc(chip, pin); if (IS_ERR(gpiod)) { - pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin); + pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), chip, pin); return PTR_ERR(gpiod); } - *desc = gpiod; + if (desc) + *desc = gpiod; + return 0; } @@ -77,7 +83,8 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data) return irq; case X86_ACPI_IRQ_TYPE_GPIOINT: /* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */ - ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod); + ret = x86_android_tablet_get_gpiod(data->chip, data->index, data->con_id, + false, GPIOD_ASIS, &gpiod); if (ret) return ret; @@ -224,7 +231,7 @@ put_ctrl_adev: return ret; } -static void x86_android_tablet_cleanup(void) +static void x86_android_tablet_remove(struct platform_device *pdev) { int i; @@ -255,11 +262,10 @@ static void x86_android_tablet_cleanup(void) software_node_unregister(bat_swnode); } -static __init int x86_android_tablet_init(void) +static __init int x86_android_tablet_probe(struct platform_device *pdev) { const struct x86_dev_info *dev_info; const struct dmi_system_id *id; - struct gpio_chip *chip; int i, ret = 0; id = dmi_first_match(x86_android_tablet_ids); @@ -267,20 +273,8 @@ static __init int x86_android_tablet_init(void) return -ENODEV; dev_info = id->driver_data; - - /* - * The broken DSDTs on these devices often also include broken - * _AEI (ACPI Event Interrupt) handlers, disable these. - */ - if (dev_info->invalid_aei_gpiochip) { - chip = gpiochip_find(dev_info->invalid_aei_gpiochip, - gpiochip_find_match_label); - if (!chip) { - pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip); - return -ENODEV; - } - acpi_gpiochip_free_interrupts(chip); - } + /* Allow x86_android_tablet_device use before probe() exits */ + x86_android_tablet_device = pdev; /* * Since this runs from module_init() it cannot use -EPROBE_DEFER, @@ -303,7 +297,7 @@ static __init int x86_android_tablet_init(void) if (dev_info->init) { ret = dev_info->init(); if (ret < 0) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return ret; } exit_handler = dev_info->exit; @@ -311,7 +305,7 @@ static __init int x86_android_tablet_init(void) i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL); if (!i2c_clients) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return -ENOMEM; } @@ -319,7 +313,7 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < i2c_client_count; i++) { ret = x86_instantiate_i2c_client(dev_info, i); if (ret < 0) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return ret; } } @@ -327,7 +321,7 @@ static __init int x86_android_tablet_init(void) /* + 1 to make space for (optional) gpio_keys_button pdev */ pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL); if (!pdevs) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return -ENOMEM; } @@ -335,14 +329,14 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < pdev_count; i++) { pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]); if (IS_ERR(pdevs[i])) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return PTR_ERR(pdevs[i]); } } serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL); if (!serdevs) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return -ENOMEM; } @@ -350,7 +344,7 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < serdev_count; i++) { ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i); if (ret < 0) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return ret; } } @@ -361,30 +355,34 @@ static __init int x86_android_tablet_init(void) buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL); if (!buttons) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return -ENOMEM; } for (i = 0; i < dev_info->gpio_button_count; i++) { ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip, - dev_info->gpio_button[i].pin, &gpiod); + dev_info->gpio_button[i].pin, + dev_info->gpio_button[i].button.desc, + false, GPIOD_IN, &gpiod); if (ret < 0) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return ret; } buttons[i] = dev_info->gpio_button[i].button; buttons[i].gpio = desc_to_gpio(gpiod); + /* Release gpiod so that gpio-keys can request it */ + devm_gpiod_put(&x86_android_tablet_device->dev, gpiod); } pdata.buttons = buttons; pdata.nbuttons = dev_info->gpio_button_count; - pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys", + pdevs[pdev_count] = platform_device_register_data(&pdev->dev, "gpio-keys", PLATFORM_DEVID_AUTO, &pdata, sizeof(pdata)); if (IS_ERR(pdevs[pdev_count])) { - x86_android_tablet_cleanup(); + x86_android_tablet_remove(pdev); return PTR_ERR(pdevs[pdev_count]); } pdev_count++; @@ -393,8 +391,29 @@ static __init int x86_android_tablet_init(void) return 0; } +static struct platform_driver x86_android_tablet_driver = { + .driver = { + .name = KBUILD_MODNAME, + }, + .remove_new = x86_android_tablet_remove, +}; + +static int __init x86_android_tablet_init(void) +{ + x86_android_tablet_device = platform_create_bundle(&x86_android_tablet_driver, + x86_android_tablet_probe, + NULL, 0, NULL, 0); + + return PTR_ERR_OR_ZERO(x86_android_tablet_device); +} module_init(x86_android_tablet_init); -module_exit(x86_android_tablet_cleanup); + +static void __exit x86_android_tablet_exit(void) +{ + platform_device_unregister(x86_android_tablet_device); + platform_driver_unregister(&x86_android_tablet_driver); +} +module_exit(x86_android_tablet_exit); MODULE_AUTHOR("Hans de Goede "); MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver"); diff --git a/drivers/platform/x86/x86-android-tablets/lenovo.c b/drivers/platform/x86/x86-android-tablets/lenovo.c index 26a4ef670ad7..5c803cdb5586 100644 --- a/drivers/platform/x86/x86-android-tablets/lenovo.c +++ b/drivers/platform/x86/x86-android-tablets/lenovo.c @@ -95,6 +95,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 56, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "goodix_ts_irq", }, }, { /* Wacom Digitizer in keyboard half */ @@ -111,6 +112,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 49, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "wacom_irq", }, }, { /* LP8557 Backlight controller */ @@ -136,6 +138,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 77, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "hideep_ts_irq", }, }, }; @@ -321,6 +324,7 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init .index = 2, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, + .con_id = "bq24292i_irq", }, }, { /* BQ27541 fuel-gauge */ @@ -431,7 +435,8 @@ static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void) int ret; /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */ - ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod); + ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap", + false, GPIOD_IN, &gpiod); if (ret) return ret; @@ -560,7 +565,6 @@ static const struct software_node fg_bq25890_1_supply_node = { /* bq25892 charger settings for the flat lipo battery behind the screen */ static const struct property_entry lenovo_yt3_bq25892_0_props[] = { PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers), - PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"), PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40), PROPERTY_ENTRY_BOOL("linux,skip-reset"), /* Values taken from Android Factory Image */ @@ -615,6 +619,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { .index = 5, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "bq25892_0_irq", }, }, { /* bq27500 fuel-gauge for the round li-ion cells in the hinge */ @@ -640,6 +645,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { .index = 77, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "hideep_ts_irq", }, }, { /* LP8557 Backlight controller */ @@ -655,7 +661,6 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { static int __init lenovo_yt3_init(void) { - struct gpio_desc *gpiod; int ret; /* @@ -665,31 +670,23 @@ static int __init lenovo_yt3_init(void) * * The bq25890_charger driver controls these through I2C, but this only * works if not overridden by the pins. Set these pins here: - * 1. Set /CE to 0 to allow charging. + * 1. Set /CE to 1 to allow charging. * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of * the main "bq25892_1" charger is used when necessary. */ /* /CE pin */ - ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod); + ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce", + true, GPIOD_OUT_HIGH, NULL); if (ret < 0) return ret; - /* - * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw" - * gpio_desc, that is there is no way to pass lookup-flags like - * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since - * the /CE pin is active-low, but not marked as such in the gpio_desc. - */ - gpiod_set_value(gpiod, 0); - /* OTG pin */ - ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod); + ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg", + false, GPIOD_OUT_LOW, NULL); if (ret < 0) return ret; - gpiod_set_value(gpiod, 0); - /* Enable the regulators used by the touchscreen */ intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); diff --git a/drivers/platform/x86/x86-android-tablets/other.c b/drivers/platform/x86/x86-android-tablets/other.c index e79549c6aae1..bc6bbf7ec6ea 100644 --- a/drivers/platform/x86/x86-android-tablets/other.c +++ b/drivers/platform/x86/x86-android-tablets/other.c @@ -47,6 +47,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = .index = 3, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "NVT-ts_irq", }, }, { /* BMA250E accelerometer */ @@ -62,6 +63,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = .index = 25, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, + .con_id = "bma250e_irq", }, }, }; @@ -174,6 +176,7 @@ static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = { .index = 23, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, + .con_id = "bma250e_irq", }, }, }; @@ -312,6 +315,7 @@ static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __in .index = 23, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, + .con_id = "kxtj21009_irq", }, }, { /* goodix touchscreen */ @@ -402,6 +406,7 @@ static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst .index = 3, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "ft5416_irq", }, }, }; @@ -460,6 +465,7 @@ static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initcons .index = 17, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, + .con_id = "ft5416_irq", }, }, }; @@ -505,11 +511,6 @@ static const struct x86_gpio_button peaq_c1010_button __initconst = { const struct x86_dev_info peaq_c1010_info __initconst = { .gpio_button = &peaq_c1010_button, .gpio_button_count = 1, - /* - * Move the ACPI event handler used by the broken WMI interface out of - * the way. This is the only event handler on INT33FC:00. - */ - .invalid_aei_gpiochip = "INT33FC:00", }; /* diff --git a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h index e46e1128acc8..9d2fb7fded6d 100644 --- a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h +++ b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h @@ -10,6 +10,7 @@ #ifndef __PDX86_X86_ANDROID_TABLETS_H #define __PDX86_X86_ANDROID_TABLETS_H +#include #include #include #include @@ -37,6 +38,7 @@ struct x86_acpi_irq_data { int index; int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */ int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */ + const char *con_id; }; /* Structs to describe devices to instantiate */ @@ -66,7 +68,6 @@ struct x86_gpio_button { }; struct x86_dev_info { - char *invalid_aei_gpiochip; const char * const *modules; const struct software_node *bat_swnode; struct gpiod_lookup_table * const *gpiod_lookup_tables; @@ -82,7 +83,9 @@ struct x86_dev_info { void (*exit)(void); }; -int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc); +int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, + bool active_low, enum gpiod_flags dflags, + struct gpio_desc **desc); int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data); /* diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 6ab272c84b7b..a0927081a003 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -250,12 +250,9 @@ static int __init pnpacpi_add_device(struct acpi_device *device) dev->capabilities |= PNP_DISABLE; if (strlen(acpi_device_name(device))) - strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); + strscpy(dev->name, acpi_device_name(device), sizeof(dev->name)); else - strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); - - /* Handle possible string truncation */ - dev->name[sizeof(dev->name) - 1] = '\0'; + strscpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); if (dev->active) pnpacpi_parse_allocated_resource(dev); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 2f31b212b1a5..70af7821d3fa 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -454,8 +454,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, switch (tag) { case LARGE_TAG_ANSISTR: - strncpy(dev->name, p + 3, - len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len); + memcpy(dev->name, p + 3, + len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len); dev->name[len >= PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0'; break; diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index 40a2cc649c79..2feed036c1cd 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -892,7 +892,7 @@ static int rapl_write_pl_data(struct rapl_domain *rd, int pl, return -EINVAL; if (rd->rpl[pl].locked) { - pr_warn("%s:%s:%s locked by BIOS\n", rd->rp->name, rd->name, pl_names[pl]); + pr_debug("%s:%s:%s locked by BIOS\n", rd->rp->name, rd->name, pl_names[pl]); return -EACCES; } diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 965d4f0c18a6..f3ec24691378 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -564,6 +564,16 @@ config REGULATOR_MAX5970 The MAX5970/5978 is a smart switch with no output regulation, but fault protection and voltage and current monitoring capabilities. +config REGULATOR_MAX77503 + tristate "Analog Devices MAX77503 Regulator" + depends on I2C + select REGMAP_I2C + help + This driver controls a Analog Devices MAX77503 14V input, 1.5A + high-efficiency buck converter via I2C bus. + Say M here if you want to include support for the regulator as a + module. + config REGULATOR_MAX77541 tristate "Analog Devices MAX77541/77540 Regulator" depends on MFD_MAX77541 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 23074714a81a..b2b059b5ee56 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX5970) += max5970-regulator.o +obj-$(CONFIG_REGULATOR_MAX77503) += max77503-regulator.o obj-$(CONFIG_REGULATOR_MAX77541) += max77541-regulator.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 1d354db0c1bd..e0c96f10e570 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -73,7 +73,7 @@ struct da9062_regulators { int irq_ldo_lim; unsigned n_regulators; /* Array size to be defined during init. Keep at end. */ - struct da9062_regulator regulator[]; + struct da9062_regulator regulator[] __counted_by(n_regulators); }; /* Regulator operations */ diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index a0621665a6d2..82bf321ae06f 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -158,7 +158,7 @@ struct da9063_regulator { struct da9063_regulators { unsigned int n_regulators; /* Array size to be defined during init. Keep at end. */ - struct da9063_regulator regulator[]; + struct da9063_regulator regulator[] __counted_by(n_regulators); }; /* BUCK modes for DA9063 */ diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 80098035bb13..b551a400bdd1 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -13,7 +13,7 @@ // // Copyright (C) 2020 Dialog Semiconductor -#include +#include #include #include #include @@ -1117,17 +1117,6 @@ static const struct of_device_id da9121_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, da9121_dt_ids); -static inline int da9121_of_get_id(struct device *dev) -{ - const struct of_device_id *id = of_match_device(da9121_dt_ids, dev); - - if (!id) { - dev_err(dev, "%s: Failed\n", __func__); - return -EINVAL; - } - return (uintptr_t)id->data; -} - static int da9121_i2c_probe(struct i2c_client *i2c) { struct da9121 *chip; @@ -1141,7 +1130,7 @@ static int da9121_i2c_probe(struct i2c_client *i2c) } chip->pdata = i2c->dev.platform_data; - chip->subvariant_id = da9121_of_get_id(&i2c->dev); + chip->subvariant_id = (enum da9121_subvariant)i2c_get_match_data(i2c); ret = da9121_assign_chip_model(i2c, chip); if (ret < 0) diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 252f74ab9bc0..02b85ca4a6fc 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -135,16 +135,6 @@ static int da9210_i2c_probe(struct i2c_client *i2c) struct regulator_dev *rdev = NULL; struct regulator_config config = { }; int error; - const struct of_device_id *match; - - if (i2c->dev.of_node && !pdata) { - match = of_match_device(of_match_ptr(da9210_dt_ids), - &i2c->dev); - if (!match) { - dev_err(&i2c->dev, "Error: No device match found\n"); - return -ENODEV; - } - } chip = devm_kzalloc(&i2c->dev, sizeof(struct da9210), GFP_KERNEL); if (!chip) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 48f312167e53..17c9bf204385 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -659,7 +659,6 @@ MODULE_DEVICE_TABLE(of, fan53555_dt_ids); static int fan53555_regulator_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device_node *np = client->dev.of_node; struct fan53555_device_info *di; struct fan53555_platform_data *pdata; @@ -682,10 +681,8 @@ static int fan53555_regulator_probe(struct i2c_client *client) "Platform data not found!\n"); di->regulator = pdata->regulator; - if (client->dev.of_node) { - di->vendor = - (unsigned long)of_device_get_match_data(&client->dev); - } else { + di->vendor = (uintptr_t)i2c_get_match_data(client); + if (!dev_fwnode(&client->dev)) { /* if no ramp constraint set, get the pdata ramp_delay */ if (!di->regulator->constraints.ramp_delay) { if (pdata->slew_rate >= ARRAY_SIZE(slew_rates)) @@ -695,8 +692,6 @@ static int fan53555_regulator_probe(struct i2c_client *client) di->regulator->constraints.ramp_delay = slew_rates[pdata->slew_rate]; } - - di->vendor = id->driver_data; } regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 55130efae9b8..cb93e5cdcfa9 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,8 @@ #include #include +/* Default time in millisecond to wait for emergency shutdown */ +#define FV_DEF_EMERG_SHUTDWN_TMO 10 struct fixed_voltage_data { struct regulator_desc desc; @@ -105,6 +108,49 @@ static int reg_is_enabled(struct regulator_dev *rdev) return priv->enable_counter > 0; } +static irqreturn_t reg_fixed_under_voltage_irq_handler(int irq, void *data) +{ + struct fixed_voltage_data *priv = data; + struct regulator_dev *rdev = priv->dev; + + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, + NULL); + + return IRQ_HANDLED; +} + +/** + * reg_fixed_get_irqs - Get and register the optional IRQ for fixed voltage + * regulator. + * @dev: Pointer to the device structure. + * @priv: Pointer to fixed_voltage_data structure containing private data. + * + * This function tries to get the IRQ from the device firmware node. + * If it's an optional IRQ and not found, it returns 0. + * Otherwise, it attempts to request the threaded IRQ. + * + * Return: 0 on success, or error code on failure. + */ +static int reg_fixed_get_irqs(struct device *dev, + struct fixed_voltage_data *priv) +{ + int ret; + + ret = fwnode_irq_get(dev_fwnode(dev), 0); + /* This is optional IRQ. If not found we will get -EINVAL */ + if (ret == -EINVAL) + return 0; + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get IRQ\n"); + + ret = devm_request_threaded_irq(dev, ret, NULL, + reg_fixed_under_voltage_irq_handler, + IRQF_ONESHOT, "under-voltage", priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); + + return 0; +} /** * of_get_fixed_voltage_config - extract fixed_voltage_config structure info @@ -294,6 +340,10 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, drvdata->desc.fixed_uV); + ret = reg_fixed_get_irqs(dev, drvdata); + if (ret) + return ret; + return 0; } diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c index 11b358efbc92..e53911c80719 100644 --- a/drivers/regulator/lochnagar-regulator.c +++ b/drivers/regulator/lochnagar-regulator.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -243,7 +242,6 @@ static int lochnagar_regulator_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct lochnagar *lochnagar = dev_get_drvdata(dev->parent); struct regulator_config config = { }; - const struct of_device_id *of_id; const struct regulator_desc *desc; struct regulator_dev *rdev; int ret; @@ -252,12 +250,10 @@ static int lochnagar_regulator_probe(struct platform_device *pdev) config.regmap = lochnagar->regmap; config.driver_data = lochnagar; - of_id = of_match_device(lochnagar_of_match, dev); - if (!of_id) + desc = device_get_match_data(dev); + if (!desc) return -EINVAL; - desc = of_id->data; - rdev = devm_regulator_register(dev, desc, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index d892c2a5df7b..3f70c2225dba 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -58,12 +58,6 @@ #define LTC3589_VRRCR_SW3_RAMP_MASK GENMASK(5, 4) #define LTC3589_VRRCR_LDO2_RAMP_MASK GENMASK(7, 6) -enum ltc3589_variant { - LTC3589, - LTC3589_1, - LTC3589_2, -}; - enum ltc3589_reg { LTC3589_SW1, LTC3589_SW2, @@ -76,10 +70,14 @@ enum ltc3589_reg { LTC3589_NUM_REGULATORS, }; +struct ltc3589_info { + const unsigned int *volt_table; + int fixed_uV; +}; + struct ltc3589 { struct regmap *regmap; struct device *dev; - enum ltc3589_variant variant; struct regulator_desc regulator_descs[LTC3589_NUM_REGULATORS]; struct regulator_dev *regulators[LTC3589_NUM_REGULATORS]; }; @@ -379,8 +377,8 @@ static irqreturn_t ltc3589_isr(int irq, void *dev_id) static int ltc3589_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device *dev = &client->dev; + const struct ltc3589_info *info; struct regulator_desc *descs; struct ltc3589 *ltc3589; int i, ret; @@ -390,21 +388,13 @@ static int ltc3589_probe(struct i2c_client *client) return -ENOMEM; i2c_set_clientdata(client, ltc3589); - if (client->dev.of_node) - ltc3589->variant = (uintptr_t)of_device_get_match_data(&client->dev); - else - ltc3589->variant = id->driver_data; + info = i2c_get_match_data(client); ltc3589->dev = dev; descs = ltc3589->regulator_descs; memcpy(descs, ltc3589_regulators, sizeof(ltc3589_regulators)); - if (ltc3589->variant == LTC3589) { - descs[LTC3589_LDO3].fixed_uV = 1800000; - descs[LTC3589_LDO4].volt_table = ltc3589_ldo4; - } else { - descs[LTC3589_LDO3].fixed_uV = 2800000; - descs[LTC3589_LDO4].volt_table = ltc3589_12_ldo4; - } + descs[LTC3589_LDO3].fixed_uV = info->fixed_uV; + descs[LTC3589_LDO4].volt_table = info->volt_table; ltc3589->regmap = devm_regmap_init_i2c(client, <c3589_regmap_config); if (IS_ERR(ltc3589->regmap)) { @@ -444,28 +434,29 @@ static int ltc3589_probe(struct i2c_client *client) return 0; } +static const struct ltc3589_info ltc3589_info = { + .fixed_uV = 1800000, + .volt_table = ltc3589_ldo4, +}; + +static const struct ltc3589_info ltc3589_12_info = { + .fixed_uV = 2800000, + .volt_table = ltc3589_12_ldo4, +}; + static const struct i2c_device_id ltc3589_i2c_id[] = { - { "ltc3589", LTC3589 }, - { "ltc3589-1", LTC3589_1 }, - { "ltc3589-2", LTC3589_2 }, + { "ltc3589", (kernel_ulong_t)<c3589_info }, + { "ltc3589-1", (kernel_ulong_t)<c3589_12_info }, + { "ltc3589-2", (kernel_ulong_t)<c3589_12_info }, { } }; MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id); static const struct of_device_id __maybe_unused ltc3589_of_match[] = { - { - .compatible = "lltc,ltc3589", - .data = (void *)LTC3589, - }, - { - .compatible = "lltc,ltc3589-1", - .data = (void *)LTC3589_1, - }, - { - .compatible = "lltc,ltc3589-2", - .data = (void *)LTC3589_2, - }, - { }, + { .compatible = "lltc,ltc3589", .data = <c3589_info }, + { .compatible = "lltc,ltc3589-1", .data = <c3589_12_info }, + { .compatible = "lltc,ltc3589-2", .data = <c3589_12_info }, + { } }; MODULE_DEVICE_TABLE(of, ltc3589_of_match); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 90aa5b723c03..0f133129252e 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #define MAX1586_V3_MAX_VSEL 31 @@ -213,16 +213,9 @@ static int max1586_pmic_probe(struct i2c_client *client) struct regulator_config config = { }; struct max1586_data *max1586; int i, id, ret; - const struct of_device_id *match; pdata = dev_get_platdata(&client->dev); if (client->dev.of_node && !pdata) { - match = of_match_device(of_match_ptr(max1586_of_match), - &client->dev); - if (!match) { - dev_err(&client->dev, "Error: No device match found\n"); - return -ENODEV; - } ret = of_get_max1586_platform_data(&client->dev, &pdata_of); if (ret < 0) return ret; diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index 32f47b896fd1..59eb23d467ec 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -223,7 +223,7 @@ static int max20086_i2c_probe(struct i2c_client *i2c) return -ENOMEM; chip->dev = &i2c->dev; - chip->info = device_get_match_data(chip->dev); + chip->info = i2c_get_match_data(i2c); i2c_set_clientdata(i2c, chip); @@ -275,45 +275,42 @@ static int max20086_i2c_probe(struct i2c_client *i2c) return 0; } -static const struct i2c_device_id max20086_i2c_id[] = { - { "max20086" }, - { "max20087" }, - { "max20088" }, - { "max20089" }, - { /* Sentinel */ }, +static const struct max20086_chip_info max20086_chip_info = { + .id = MAX20086_DEVICE_ID_MAX20086, + .num_outputs = 4, }; +static const struct max20086_chip_info max20087_chip_info = { + .id = MAX20086_DEVICE_ID_MAX20087, + .num_outputs = 4, +}; + +static const struct max20086_chip_info max20088_chip_info = { + .id = MAX20086_DEVICE_ID_MAX20088, + .num_outputs = 2, +}; + +static const struct max20086_chip_info max20089_chip_info = { + .id = MAX20086_DEVICE_ID_MAX20089, + .num_outputs = 2, +}; + +static const struct i2c_device_id max20086_i2c_id[] = { + { "max20086", (kernel_ulong_t)&max20086_chip_info }, + { "max20087", (kernel_ulong_t)&max20087_chip_info }, + { "max20088", (kernel_ulong_t)&max20088_chip_info }, + { "max20089", (kernel_ulong_t)&max20089_chip_info }, + { /* Sentinel */ } +}; MODULE_DEVICE_TABLE(i2c, max20086_i2c_id); static const struct of_device_id max20086_dt_ids[] __maybe_unused = { - { - .compatible = "maxim,max20086", - .data = &(const struct max20086_chip_info) { - .id = MAX20086_DEVICE_ID_MAX20086, - .num_outputs = 4, - } - }, { - .compatible = "maxim,max20087", - .data = &(const struct max20086_chip_info) { - .id = MAX20086_DEVICE_ID_MAX20087, - .num_outputs = 4, - } - }, { - .compatible = "maxim,max20088", - .data = &(const struct max20086_chip_info) { - .id = MAX20086_DEVICE_ID_MAX20088, - .num_outputs = 2, - } - }, { - .compatible = "maxim,max20089", - .data = &(const struct max20086_chip_info) { - .id = MAX20086_DEVICE_ID_MAX20089, - .num_outputs = 2, - } - }, - { /* Sentinel */ }, + { .compatible = "maxim,max20086", .data = &max20086_chip_info }, + { .compatible = "maxim,max20087", .data = &max20087_chip_info }, + { .compatible = "maxim,max20088", .data = &max20088_chip_info }, + { .compatible = "maxim,max20089", .data = &max20089_chip_info }, + { /* Sentinel */ } }; - MODULE_DEVICE_TABLE(of, max20086_dt_ids); static struct i2c_driver max20086_regulator_driver = { diff --git a/drivers/regulator/max5970-regulator.c b/drivers/regulator/max5970-regulator.c index b56a174cde3d..bc88a40a88d4 100644 --- a/drivers/regulator/max5970-regulator.c +++ b/drivers/regulator/max5970-regulator.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,132 @@ enum max597x_regulator_id { MAX597X_SW1, }; +static int max5970_read_adc(struct regmap *regmap, int reg, long *val) +{ + u8 reg_data[2]; + int ret; + + ret = regmap_bulk_read(regmap, reg, ®_data[0], 2); + if (ret < 0) + return ret; + + *val = (reg_data[0] << 2) | (reg_data[1] & 3); + + return 0; +} + +static int max5970_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct regulator_dev **rdevs = dev_get_drvdata(dev); + struct max5970_regulator *ddata = rdev_get_drvdata(rdevs[channel]); + struct regmap *regmap = ddata->regmap; + int ret; + + switch (type) { + case hwmon_curr: + switch (attr) { + case hwmon_curr_input: + ret = max5970_read_adc(regmap, MAX5970_REG_CURRENT_H(channel), val); + if (ret < 0) + return ret; + /* + * Calculate current from ADC value, IRNG range & shunt resistor value. + * ddata->irng holds the voltage corresponding to the maximum value the + * 10-bit ADC can measure. + * To obtain the output, multiply the ADC value by the IRNG range (in + * millivolts) and then divide it by the maximum value of the 10-bit ADC. + */ + *val = (*val * ddata->irng) >> 10; + /* Convert the voltage meansurement across shunt resistor to current */ + *val = (*val * 1000) / ddata->shunt_micro_ohms; + return 0; + default: + return -EOPNOTSUPP; + } + + case hwmon_in: + switch (attr) { + case hwmon_in_input: + ret = max5970_read_adc(regmap, MAX5970_REG_VOLTAGE_H(channel), val); + if (ret < 0) + return ret; + /* + * Calculate voltage from ADC value and MON range. + * ddata->mon_rng holds the voltage corresponding to the maximum value the + * 10-bit ADC can measure. + * To obtain the output, multiply the ADC value by the MON range (in + * microvolts) and then divide it by the maximum value of the 10-bit ADC. + */ + *val = mul_u64_u32_shr(*val, ddata->mon_rng, 10); + /* uV to mV */ + *val = *val / 1000; + return 0; + default: + return -EOPNOTSUPP; + } + default: + return -EOPNOTSUPP; + } +} + +static umode_t max5970_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + struct regulator_dev **rdevs = (struct regulator_dev **)data; + struct max5970_regulator *ddata; + + if (channel >= MAX5970_NUM_SWITCHES || !rdevs[channel]) + return 0; + + ddata = rdev_get_drvdata(rdevs[channel]); + + if (channel >= ddata->num_switches) + return 0; + + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_input: + return 0444; + default: + break; + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_input: + /* Current measurement requires knowledge of the shunt resistor value. */ + if (ddata->shunt_micro_ohms) + return 0444; + break; + default: + break; + } + break; + default: + break; + } + return 0; +} + +static const struct hwmon_ops max5970_hwmon_ops = { + .is_visible = max5970_is_visible, + .read = max5970_read, +}; + +static const struct hwmon_channel_info *max5970_info[] = { + HWMON_CHANNEL_INFO(in, HWMON_I_INPUT, HWMON_I_INPUT), + HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT, HWMON_C_INPUT), + NULL +}; + +static const struct hwmon_chip_info max5970_chip_info = { + .ops = &max5970_hwmon_ops, + .info = max5970_info, +}; + static int max597x_uvp_ovp_check_mode(struct regulator_dev *rdev, int severity) { int ret, reg; @@ -431,7 +558,8 @@ static int max597x_regulator_probe(struct platform_device *pdev) struct i2c_client *i2c = to_i2c_client(pdev->dev.parent); struct regulator_config config = { }; struct regulator_dev *rdev; - struct regulator_dev *rdevs[MAX5970_NUM_SWITCHES]; + struct regulator_dev **rdevs = NULL; + struct device *hwmon_dev; int num_switches; int ret, i; @@ -442,6 +570,11 @@ static int max597x_regulator_probe(struct platform_device *pdev) if (!max597x) return -ENOMEM; + rdevs = devm_kcalloc(&i2c->dev, MAX5970_NUM_SWITCHES, sizeof(struct regulator_dev *), + GFP_KERNEL); + if (!rdevs) + return -ENOMEM; + i2c_set_clientdata(i2c, max597x); if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5978")) @@ -451,7 +584,6 @@ static int max597x_regulator_probe(struct platform_device *pdev) else return -ENODEV; - i2c_set_clientdata(i2c, max597x); num_switches = max597x->num_switches; for (i = 0; i < num_switches; i++) { @@ -485,6 +617,15 @@ static int max597x_regulator_probe(struct platform_device *pdev) max597x->shunt_micro_ohms[i] = data->shunt_micro_ohms; } + if (IS_REACHABLE(CONFIG_HWMON)) { + hwmon_dev = devm_hwmon_device_register_with_info(&i2c->dev, "max5970", rdevs, + &max5970_chip_info, NULL); + if (IS_ERR(hwmon_dev)) { + return dev_err_probe(&i2c->dev, PTR_ERR(hwmon_dev), + "Unable to register hwmon device\n"); + } + } + if (i2c->irq) { ret = max597x_setup_irq(&i2c->dev, i2c->irq, rdevs, num_switches, diff --git a/drivers/regulator/max77503-regulator.c b/drivers/regulator/max77503-regulator.c new file mode 100644 index 000000000000..4a6ba4dd2acd --- /dev/null +++ b/drivers/regulator/max77503-regulator.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Analog Devices, Inc. + * ADI regulator driver for MAX77503. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX77503_REG_CFG 0x00 +#define MAX77503_REG_VOUT 0x01 + +#define MAX77503_BIT_EN BIT(0) +#define MAX77503_BIT_CURR_LIM BIT(3) +#define MAX77503_BIT_ADEN BIT(6) + +#define MAX77503_BITS_SOFT_START GENMASK(5, 4) +#define MAX77503_BITS_MX_VOUT GENMASK(7, 0) + +#define MAX77503_AD_ENABLED 0x1 +#define MAX77503_AD_DISABLED 0x0 + +struct max77503_dev { + struct device *dev; + struct device_node *of_node; + struct regulator_desc desc; + struct regulator_dev *rdev; + struct regmap *regmap; +}; + +static const struct regmap_config max77503_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x2, +}; + +static const struct regulator_ops max77503_buck_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_ascend, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_soft_start = regulator_set_soft_start_regmap, +}; + +static const struct linear_range max77503_buck_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0x00, 0x54, 50000) +}; + +static const unsigned int max77503_current_limit_table[] = { + 500000, 2000000 +}; + +static const struct regulator_desc max77503_regulators_desc = { + .name = "max77503", + .enable_reg = MAX77503_REG_CFG, + .enable_mask = MAX77503_BIT_EN, + .ops = &max77503_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = max77503_buck_ranges, + .n_linear_ranges = ARRAY_SIZE(max77503_buck_ranges), + .vsel_reg = MAX77503_REG_VOUT, + .vsel_mask = MAX77503_BITS_MX_VOUT, + .soft_start_reg = MAX77503_REG_CFG, + .soft_start_mask = MAX77503_BITS_SOFT_START, + .active_discharge_reg = MAX77503_REG_CFG, + .active_discharge_mask = MAX77503_BIT_ADEN, + .active_discharge_off = MAX77503_AD_DISABLED, + .active_discharge_on = MAX77503_AD_ENABLED, + .csel_reg = MAX77503_REG_CFG, + .csel_mask = MAX77503_BIT_CURR_LIM, + .curr_table = max77503_current_limit_table, + .n_current_limits = ARRAY_SIZE(max77503_current_limit_table), + .owner = THIS_MODULE, +}; + +static int max77503_regulator_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct regulator_config config = {}; + struct regulator_dev *rdev; + + config.dev = dev; + config.of_node = dev->of_node; + config.regmap = devm_regmap_init_i2c(client, &max77503_regmap_config); + if (IS_ERR(config.regmap)) { + dev_err(dev, "Failed to init regmap"); + return PTR_ERR(config.regmap); + } + + rdev = devm_regulator_register(dev, &max77503_regulators_desc, &config); + if (IS_ERR(rdev)) { + dev_err(dev, "Failed to register regulator MAX77503"); + return PTR_ERR(rdev); + } + + return 0; +} + +static const struct of_device_id of_max77503_match_tbl[] = { + { .compatible = "adi,max77503", }, + { } +}; + +MODULE_DEVICE_TABLE(of, of_max77503_match_tbl); + +static const struct i2c_device_id max77503_regulator_id[] = { + {"max77503"}, + { } +}; + +MODULE_DEVICE_TABLE(i2c, max77503_regulator_id); + +static struct i2c_driver max77503_regulator_driver = { + .driver = { + .name = "max77503", + .of_match_table = of_max77503_match_tbl + }, + .probe = max77503_regulator_probe, + .id_table = max77503_regulator_id, +}; + +module_i2c_driver(max77503_regulator_driver); + +MODULE_AUTHOR("Gokhan Celik "); +MODULE_DESCRIPTION("MAX77503 regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index e03279dc43f4..057aaef6f086 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -24,7 +24,7 @@ struct mc13xxx_regulator_priv { u32 powermisc_pwgt_state; struct mc13xxx_regulator *mc13xxx_regulators; int num_regulators; - struct regulator_dev *regulators[]; + struct regulator_dev *regulators[] __counted_by(num_regulators); }; extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c index d068ac93d373..3457e650a994 100644 --- a/drivers/regulator/mp5416.c +++ b/drivers/regulator/mp5416.c @@ -200,7 +200,7 @@ static int mp5416_i2c_probe(struct i2c_client *client) return PTR_ERR(regmap); } - desc = of_device_get_match_data(dev); + desc = i2c_get_match_data(client); if (!desc) return -ENODEV; @@ -223,14 +223,14 @@ static int mp5416_i2c_probe(struct i2c_client *client) static const struct of_device_id mp5416_of_match[] = { { .compatible = "mps,mp5416", .data = &mp5416_regulators_desc }, { .compatible = "mps,mp5496", .data = &mp5496_regulators_desc }, - {}, + {} }; MODULE_DEVICE_TABLE(of, mp5416_of_match); static const struct i2c_device_id mp5416_id[] = { - { "mp5416", }, - { "mp5496", }, - { }, + { "mp5416", (kernel_ulong_t)&mp5416_regulators_desc }, + { "mp5496", (kernel_ulong_t)&mp5496_regulators_desc }, + {} }; MODULE_DEVICE_TABLE(i2c, mp5416_id); diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 9911be2e6bac..48dcee5287f3 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -315,7 +315,7 @@ static int mp886x_i2c_probe(struct i2c_client *client) if (IS_ERR(di->en_gpio)) return PTR_ERR(di->en_gpio); - di->ci = of_device_get_match_data(dev); + di->ci = i2c_get_match_data(client); di->dev = dev; regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config); @@ -341,20 +341,14 @@ static int mp886x_i2c_probe(struct i2c_client *client) } static const struct of_device_id mp886x_dt_ids[] = { - { - .compatible = "mps,mp8867", - .data = &mp8867_ci - }, - { - .compatible = "mps,mp8869", - .data = &mp8869_ci - }, + { .compatible = "mps,mp8867", .data = &mp8867_ci }, + { .compatible = "mps,mp8869", .data = &mp8869_ci }, { } }; MODULE_DEVICE_TABLE(of, mp886x_dt_ids); static const struct i2c_device_id mp886x_id[] = { - { "mp886x", }, + { "mp886x", (kernel_ulong_t)&mp8869_ci }, { }, }; MODULE_DEVICE_TABLE(i2c, mp886x_id); diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c index 65fbd95f1dbb..e4745f616cea 100644 --- a/drivers/regulator/mt6358-regulator.c +++ b/drivers/regulator/mt6358-regulator.c @@ -13,8 +13,7 @@ #include #include -#define MT6358_BUCK_MODE_AUTO 0 -#define MT6358_BUCK_MODE_FORCE_PWM 1 +#include /* * MT6358 regulators' information @@ -26,8 +25,6 @@ struct mt6358_regulator_info { struct regulator_desc desc; u32 status_reg; u32 qi; - const u32 *index_table; - unsigned int n_table; u32 da_vsel_reg; u32 da_vsel_mask; u32 modeset_reg; @@ -36,12 +33,13 @@ struct mt6358_regulator_info { #define to_regulator_info(x) container_of((x), struct mt6358_regulator_info, desc) -#define MT6358_BUCK(match, vreg, min, max, step, \ - vosel_mask, _da_vsel_reg, _da_vsel_mask, \ - _modeset_reg, _modeset_shift) \ +#define MT6358_BUCK(match, vreg, supply, min, max, step, \ + vosel_mask, _da_vsel_reg, _da_vsel_mask, \ + _modeset_reg, _modeset_shift) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_buck_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -64,36 +62,37 @@ struct mt6358_regulator_info { .modeset_mask = BIT(_modeset_shift), \ } -#define MT6358_LDO(match, vreg, ldo_volt_table, \ - ldo_index_table, enreg, enbit, vosel, \ - vosel_mask) \ +#define MT6358_LDO(match, vreg, supply, volt_ranges, enreg, enbit, vosel, vosel_mask) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_volt_table_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MT6358_ID_##vreg, \ .owner = THIS_MODULE, \ - .n_voltages = ARRAY_SIZE(ldo_volt_table), \ - .volt_table = ldo_volt_table, \ - .vsel_reg = vosel, \ - .vsel_mask = vosel_mask, \ + .n_voltages = ARRAY_SIZE(volt_ranges##_ranges) * 11, \ + .linear_ranges = volt_ranges##_ranges, \ + .linear_range_selectors_bitfield = volt_ranges##_selectors, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges##_ranges), \ + .vsel_range_reg = vosel, \ + .vsel_range_mask = vosel_mask, \ + .vsel_reg = MT6358_##vreg##_ANA_CON0, \ + .vsel_mask = GENMASK(3, 0), \ .enable_reg = enreg, \ .enable_mask = BIT(enbit), \ }, \ .status_reg = MT6358_LDO_##vreg##_CON1, \ .qi = BIT(15), \ - .index_table = ldo_index_table, \ - .n_table = ARRAY_SIZE(ldo_index_table), \ } -#define MT6358_LDO1(match, vreg, min, max, step, \ - _da_vsel_reg, _da_vsel_mask, \ - vosel, vosel_mask) \ +#define MT6358_LDO1(match, vreg, supply, min, max, step, \ + _da_vsel_reg, _da_vsel_mask, vosel, vosel_mask) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_volt_range_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -113,20 +112,23 @@ struct mt6358_regulator_info { .qi = BIT(0), \ } -#define MT6358_REG_FIXED(match, vreg, \ - enreg, enbit, volt) \ +#define MT6358_REG_FIXED(match, vreg, supply, enreg, enbit, volt) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_volt_fixed_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MT6358_ID_##vreg, \ .owner = THIS_MODULE, \ - .n_voltages = 1, \ + .n_voltages = 11, \ + .vsel_reg = MT6358_##vreg##_ANA_CON0, \ + .vsel_mask = GENMASK(3, 0), \ .enable_reg = enreg, \ .enable_mask = BIT(enbit), \ .min_uV = volt, \ + .uV_step = 10000, \ }, \ .status_reg = MT6358_LDO_##vreg##_CON1, \ .qi = BIT(15), \ @@ -138,6 +140,7 @@ struct mt6358_regulator_info { [MT6366_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = "vsys-" match, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_buck_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -160,36 +163,37 @@ struct mt6358_regulator_info { .modeset_mask = BIT(_modeset_shift), \ } -#define MT6366_LDO(match, vreg, ldo_volt_table, \ - ldo_index_table, enreg, enbit, vosel, \ - vosel_mask) \ +#define MT6366_LDO(match, vreg, volt_ranges, supply, enreg, enbit, vosel, vosel_mask) \ [MT6366_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_volt_table_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MT6366_ID_##vreg, \ .owner = THIS_MODULE, \ - .n_voltages = ARRAY_SIZE(ldo_volt_table), \ - .volt_table = ldo_volt_table, \ - .vsel_reg = vosel, \ - .vsel_mask = vosel_mask, \ + .n_voltages = ARRAY_SIZE(volt_ranges##_ranges) * 11, \ + .linear_ranges = volt_ranges##_ranges, \ + .linear_range_selectors_bitfield = volt_ranges##_selectors, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges##_ranges), \ + .vsel_range_reg = vosel, \ + .vsel_range_mask = vosel_mask, \ + .vsel_reg = MT6358_##vreg##_ANA_CON0, \ + .vsel_mask = GENMASK(3, 0), \ .enable_reg = enreg, \ .enable_mask = BIT(enbit), \ }, \ .status_reg = MT6358_LDO_##vreg##_CON1, \ .qi = BIT(15), \ - .index_table = ldo_index_table, \ - .n_table = ARRAY_SIZE(ldo_index_table), \ } -#define MT6366_LDO1(match, vreg, min, max, step, \ - _da_vsel_reg, _da_vsel_mask, \ - vosel, vosel_mask) \ +#define MT6366_LDO1(match, vreg, supply, min, max, step, \ + _da_vsel_reg, _da_vsel_mask, vosel, vosel_mask) \ [MT6366_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_volt_range_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -209,166 +213,161 @@ struct mt6358_regulator_info { .qi = BIT(0), \ } -#define MT6366_REG_FIXED(match, vreg, \ - enreg, enbit, volt) \ +#define MT6366_REG_FIXED(match, vreg, supply, enreg, enbit, volt) \ [MT6366_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ + .supply_name = supply, \ .of_match = of_match_ptr(match), \ .ops = &mt6358_volt_fixed_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MT6366_ID_##vreg, \ .owner = THIS_MODULE, \ - .n_voltages = 1, \ + .n_voltages = 11, \ + .vsel_reg = MT6358_##vreg##_ANA_CON0, \ + .vsel_mask = GENMASK(3, 0), \ .enable_reg = enreg, \ .enable_mask = BIT(enbit), \ .min_uV = volt, \ + .uV_step = 10000, \ }, \ .status_reg = MT6358_LDO_##vreg##_CON1, \ .qi = BIT(15), \ } -static const unsigned int vdram2_voltages[] = { - 600000, 1800000, +/* VDRAM2 voltage selector not shown in datasheet */ +static const unsigned int vdram2_selectors[] = { 0, 12 }; +static const struct linear_range vdram2_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), }; -static const unsigned int vsim_voltages[] = { - 1700000, 1800000, 2700000, 3000000, 3100000, +static const unsigned int vsim_selectors[] = { 3, 4, 8, 11, 12 }; +static const struct linear_range vsim_ranges[] = { + REGULATOR_LINEAR_RANGE(1700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3100000, 0, 10, 10000), }; -static const unsigned int vibr_voltages[] = { - 1200000, 1300000, 1500000, 1800000, - 2000000, 2800000, 3000000, 3300000, +static const unsigned int vibr_selectors[] = { 0, 1, 2, 4, 5, 9, 11, 13 }; +static const struct linear_range vibr_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1500000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3300000, 0, 10, 10000), }; -static const unsigned int vusb_voltages[] = { - 3000000, 3100000, +/* VUSB voltage selector not shown in datasheet */ +static const unsigned int vusb_selectors[] = { 3, 4 }; +static const struct linear_range vusb_ranges[] = { + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3100000, 0, 10, 10000), }; -static const unsigned int vcamd_voltages[] = { - 900000, 1000000, 1100000, 1200000, - 1300000, 1500000, 1800000, +static const unsigned int vcamd_selectors[] = { 3, 4, 5, 6, 7, 9, 12 }; +static const struct linear_range vcamd_ranges[] = { + REGULATOR_LINEAR_RANGE(900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1100000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1500000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), }; -static const unsigned int vefuse_voltages[] = { - 1700000, 1800000, 1900000, +static const unsigned int vefuse_selectors[] = { 11, 12, 13 }; +static const struct linear_range vefuse_ranges[] = { + REGULATOR_LINEAR_RANGE(1700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1900000, 0, 10, 10000), }; -static const unsigned int vmch_vemc_voltages[] = { - 2900000, 3000000, 3300000, +static const unsigned int vmch_vemc_selectors[] = { 2, 3, 5 }; +static const struct linear_range vmch_vemc_ranges[] = { + REGULATOR_LINEAR_RANGE(2900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3300000, 0, 10, 10000), }; -static const unsigned int vcama_voltages[] = { - 1800000, 2500000, 2700000, - 2800000, 2900000, 3000000, +static const unsigned int vcama_selectors[] = { 0, 7, 9, 10, 11, 12 }; +static const struct linear_range vcama_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2500000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), }; -static const unsigned int vcn33_voltages[] = { - 3300000, 3400000, 3500000, +static const unsigned int vcn33_selectors[] = { 1, 2, 3 }; +static const struct linear_range vcn33_ranges[] = { + REGULATOR_LINEAR_RANGE(3300000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3400000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3500000, 0, 10, 10000), }; -static const unsigned int vmc_voltages[] = { - 1800000, 2900000, 3000000, 3300000, +static const unsigned int vmc_selectors[] = { 4, 10, 11, 13 }; +static const struct linear_range vmc_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3300000, 0, 10, 10000), }; -static const unsigned int vldo28_voltages[] = { - 2800000, 3000000, +static const unsigned int vldo28_selectors[] = { 1, 3 }; +static const struct linear_range vldo28_ranges[] = { + REGULATOR_LINEAR_RANGE(2800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000), }; -static const u32 vdram2_idx[] = { - 0, 12, +static const unsigned int mt6366_vmddr_selectors[] = { 0, 1, 2, 3, 4, 5, 6, 7, 9, 12 }; +static const struct linear_range mt6366_vmddr_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1100000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1500000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), }; -static const u32 vsim_idx[] = { - 3, 4, 8, 11, 12, -}; - -static const u32 vibr_idx[] = { - 0, 1, 2, 4, 5, 9, 11, 13, -}; - -static const u32 vusb_idx[] = { - 3, 4, -}; - -static const u32 vcamd_idx[] = { - 3, 4, 5, 6, 7, 9, 12, -}; - -static const u32 vefuse_idx[] = { - 11, 12, 13, -}; - -static const u32 vmch_vemc_idx[] = { - 2, 3, 5, -}; - -static const u32 vcama_idx[] = { - 0, 7, 9, 10, 11, 12, -}; - -static const u32 vcn33_idx[] = { - 1, 2, 3, -}; - -static const u32 vmc_idx[] = { - 4, 10, 11, 13, -}; - -static const u32 vldo28_idx[] = { - 1, 3, +static const unsigned int mt6366_vcn18_vm18_selectors[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +static const struct linear_range mt6366_vcn18_vm18_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1100000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1400000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1500000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1600000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1700000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(1900000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2000000, 0, 10, 10000), + REGULATOR_LINEAR_RANGE(2100000, 0, 10, 10000), }; static unsigned int mt6358_map_mode(unsigned int mode) { - return mode == MT6358_BUCK_MODE_AUTO ? + return mode == MT6397_BUCK_MODE_AUTO ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_FAST; } -static int mt6358_set_voltage_sel(struct regulator_dev *rdev, - unsigned int selector) -{ - const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); - int idx, ret; - const u32 *pvol; - - pvol = info->index_table; - - idx = pvol[selector]; - idx <<= ffs(info->desc.vsel_mask) - 1; - ret = regmap_update_bits(rdev->regmap, info->desc.vsel_reg, - info->desc.vsel_mask, idx); - - return ret; -} - -static int mt6358_get_voltage_sel(struct regulator_dev *rdev) -{ - const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); - int idx, ret; - u32 selector; - const u32 *pvol; - - ret = regmap_read(rdev->regmap, info->desc.vsel_reg, &selector); - if (ret != 0) { - dev_info(&rdev->dev, - "Failed to get mt6358 %s vsel reg: %d\n", - info->desc.name, ret); - return ret; - } - - selector = (selector & info->desc.vsel_mask) >> - (ffs(info->desc.vsel_mask) - 1); - pvol = info->index_table; - for (idx = 0; idx < info->desc.n_voltages; idx++) { - if (pvol[idx] == selector) - return idx; - } - - return -EINVAL; -} - static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev) { const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); @@ -410,10 +409,10 @@ static int mt6358_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_FAST: - val = MT6358_BUCK_MODE_FORCE_PWM; + val = MT6397_BUCK_MODE_FORCE_PWM; break; case REGULATOR_MODE_NORMAL: - val = MT6358_BUCK_MODE_AUTO; + val = MT6397_BUCK_MODE_AUTO; break; default: return -EINVAL; @@ -441,9 +440,9 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) } switch ((regval & info->modeset_mask) >> (ffs(info->modeset_mask) - 1)) { - case MT6358_BUCK_MODE_AUTO: + case MT6397_BUCK_MODE_AUTO: return REGULATOR_MODE_NORMAL; - case MT6358_BUCK_MODE_FORCE_PWM: + case MT6397_BUCK_MODE_FORCE_PWM: return REGULATOR_MODE_FAST; default: return -EINVAL; @@ -477,10 +476,10 @@ static const struct regulator_ops mt6358_volt_range_ops = { }; static const struct regulator_ops mt6358_volt_table_ops = { - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_iterate, - .set_voltage_sel = mt6358_set_voltage_sel, - .get_voltage_sel = mt6358_get_voltage_sel, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .map_voltage = regulator_map_voltage_pickable_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -488,8 +487,13 @@ static const struct regulator_ops mt6358_volt_table_ops = { .get_status = mt6358_get_status, }; +/* "Fixed" LDOs with output voltage calibration +0 ~ +10 mV */ static const struct regulator_ops mt6358_volt_fixed_ops = { .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = mt6358_get_buck_voltage_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -498,147 +502,143 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { /* The array is indexed by id(MT6358_ID_XXX) */ static const struct mt6358_regulator_info mt6358_regulators[] = { - MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, + MT6358_BUCK("buck_vdram1", VDRAM1, "vsys-vdram1", 500000, 2087500, 12500, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8), - MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, + MT6358_BUCK("buck_vcore", VCORE, "vsys-vcore", 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1), - MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, + MT6358_BUCK("buck_vpa", VPA, "vsys-vpa", 500000, 3650000, 50000, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), - MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, + MT6358_BUCK("buck_vproc11", VPROC11, "vsys-vproc11", 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1), - MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, + MT6358_BUCK("buck_vproc12", VPROC12, "vsys-vproc12", 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2), - MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, + MT6358_BUCK("buck_vgpu", VGPU, "vsys-vgpu", 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), - MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, + MT6358_BUCK("buck_vs2", VS2, "vsys-vs2", 500000, 2087500, 12500, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), - MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, + MT6358_BUCK("buck_vmodem", VMODEM, "vsys-vmodem", 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8), - MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, + MT6358_BUCK("buck_vs1", VS1, "vsys-vs1", 1000000, 2587500, 12500, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), - MT6358_REG_FIXED("ldo_vrf12", VRF12, - MT6358_LDO_VRF12_CON0, 0, 1200000), - MT6358_REG_FIXED("ldo_vio18", VIO18, - MT6358_LDO_VIO18_CON0, 0, 1800000), - MT6358_REG_FIXED("ldo_vcamio", VCAMIO, - MT6358_LDO_VCAMIO_CON0, 0, 1800000), - MT6358_REG_FIXED("ldo_vcn18", VCN18, MT6358_LDO_VCN18_CON0, 0, 1800000), - MT6358_REG_FIXED("ldo_vfe28", VFE28, MT6358_LDO_VFE28_CON0, 0, 2800000), - MT6358_REG_FIXED("ldo_vcn28", VCN28, MT6358_LDO_VCN28_CON0, 0, 2800000), - MT6358_REG_FIXED("ldo_vxo22", VXO22, MT6358_LDO_VXO22_CON0, 0, 2200000), - MT6358_REG_FIXED("ldo_vaux18", VAUX18, - MT6358_LDO_VAUX18_CON0, 0, 1800000), - MT6358_REG_FIXED("ldo_vbif28", VBIF28, - MT6358_LDO_VBIF28_CON0, 0, 2800000), - MT6358_REG_FIXED("ldo_vio28", VIO28, MT6358_LDO_VIO28_CON0, 0, 2800000), - MT6358_REG_FIXED("ldo_va12", VA12, MT6358_LDO_VA12_CON0, 0, 1200000), - MT6358_REG_FIXED("ldo_vrf18", VRF18, MT6358_LDO_VRF18_CON0, 0, 1800000), - MT6358_REG_FIXED("ldo_vaud28", VAUD28, - MT6358_LDO_VAUD28_CON0, 0, 2800000), - MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx, + MT6358_REG_FIXED("ldo_vrf12", VRF12, "vs2-ldo2", MT6358_LDO_VRF12_CON0, 0, 1200000), + MT6358_REG_FIXED("ldo_vio18", VIO18, "vs1-ldo1", MT6358_LDO_VIO18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vcamio", VCAMIO, "vs1-ldo1", MT6358_LDO_VCAMIO_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vcn18", VCN18, "vs1-ldo1", MT6358_LDO_VCN18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vfe28", VFE28, "vsys-ldo1", MT6358_LDO_VFE28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_vcn28", VCN28, "vsys-ldo1", MT6358_LDO_VCN28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_vxo22", VXO22, "vsys-ldo1", MT6358_LDO_VXO22_CON0, 0, 2200000), + MT6358_REG_FIXED("ldo_vaux18", VAUX18, "vsys-ldo1", MT6358_LDO_VAUX18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vbif28", VBIF28, "vsys-ldo1", MT6358_LDO_VBIF28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_vio28", VIO28, "vsys-ldo2", MT6358_LDO_VIO28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_va12", VA12, "vs2-ldo2", MT6358_LDO_VA12_CON0, 0, 1200000), + MT6358_REG_FIXED("ldo_vrf18", VRF18, "vs1-ldo1", MT6358_LDO_VRF18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vaud28", VAUD28, "vsys-ldo1", MT6358_LDO_VAUD28_CON0, 0, 2800000), + MT6358_LDO("ldo_vdram2", VDRAM2, "vs2-ldo1", vdram2, MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf), - MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx, + MT6358_LDO("ldo_vsim1", VSIM1, "vsys-ldo1", vsim, MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx, + MT6358_LDO("ldo_vibr", VIBR, "vsys-ldo3", vibr, MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx, + MT6358_LDO("ldo_vusb", VUSB, "vsys-ldo1", vusb, MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700), - MT6358_LDO("ldo_vcamd", VCAMD, vcamd_voltages, vcamd_idx, + MT6358_LDO("ldo_vcamd", VCAMD, "vs2-ldo4", vcamd, MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx, + MT6358_LDO("ldo_vefuse", VEFUSE, "vs1-ldo1", vefuse, MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx, + MT6358_LDO("ldo_vmch", VMCH, "vsys-ldo2", vmch_vemc, MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700), - MT6358_LDO("ldo_vcama1", VCAMA1, vcama_voltages, vcama_idx, + MT6358_LDO("ldo_vcama1", VCAMA1, "vsys-ldo3", vcama, MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx, + MT6358_LDO("ldo_vemc", VEMC, "vsys-ldo2", vmch_vemc, MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700), - MT6358_LDO("ldo_vcn33", VCN33, vcn33_voltages, vcn33_idx, + MT6358_LDO("ldo_vcn33", VCN33, "vsys-ldo3", vcn33, MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300), - MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx, + MT6358_LDO("ldo_vcama2", VCAMA2, "vsys-ldo3", vcama, MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx, + MT6358_LDO("ldo_vmc", VMC, "vsys-ldo2", vmc, MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00), - MT6358_LDO("ldo_vldo28", VLDO28, vldo28_voltages, vldo28_idx, + MT6358_LDO("ldo_vldo28", VLDO28, "vsys-ldo2", vldo28, MT6358_LDO_VLDO28_CON0_0, 0, MT6358_VLDO28_ANA_CON0, 0x300), - MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, + MT6358_LDO("ldo_vsim2", VSIM2, "vsys-ldo2", vsim, MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), - MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, + MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), - MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, + MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), - MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, + MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), - MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, + MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), }; /* The array is indexed by id(MT6366_ID_XXX) */ static const struct mt6358_regulator_info mt6366_regulators[] = { - MT6366_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, + MT6366_BUCK("vdram1", VDRAM1, 500000, 2087500, 12500, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8), - MT6366_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, + MT6366_BUCK("vcore", VCORE, 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1), - MT6366_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, + MT6366_BUCK("vpa", VPA, 500000, 3650000, 50000, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), - MT6366_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, + MT6366_BUCK("vproc11", VPROC11, 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1), - MT6366_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, + MT6366_BUCK("vproc12", VPROC12, 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2), - MT6366_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, + MT6366_BUCK("vgpu", VGPU, 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), - MT6366_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, + MT6366_BUCK("vs2", VS2, 500000, 2087500, 12500, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), - MT6366_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, + MT6366_BUCK("vmodem", VMODEM, 500000, 1293750, 6250, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8), - MT6366_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, + MT6366_BUCK("vs1", VS1, 1000000, 2587500, 12500, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), - MT6366_REG_FIXED("ldo_vrf12", VRF12, - MT6358_LDO_VRF12_CON0, 0, 1200000), - MT6366_REG_FIXED("ldo_vio18", VIO18, - MT6358_LDO_VIO18_CON0, 0, 1800000), - MT6366_REG_FIXED("ldo_vcn18", VCN18, MT6358_LDO_VCN18_CON0, 0, 1800000), - MT6366_REG_FIXED("ldo_vfe28", VFE28, MT6358_LDO_VFE28_CON0, 0, 2800000), - MT6366_REG_FIXED("ldo_vcn28", VCN28, MT6358_LDO_VCN28_CON0, 0, 2800000), - MT6366_REG_FIXED("ldo_vxo22", VXO22, MT6358_LDO_VXO22_CON0, 0, 2200000), - MT6366_REG_FIXED("ldo_vaux18", VAUX18, - MT6358_LDO_VAUX18_CON0, 0, 1800000), - MT6366_REG_FIXED("ldo_vbif28", VBIF28, - MT6358_LDO_VBIF28_CON0, 0, 2800000), - MT6366_REG_FIXED("ldo_vio28", VIO28, MT6358_LDO_VIO28_CON0, 0, 2800000), - MT6366_REG_FIXED("ldo_va12", VA12, MT6358_LDO_VA12_CON0, 0, 1200000), - MT6366_REG_FIXED("ldo_vrf18", VRF18, MT6358_LDO_VRF18_CON0, 0, 1800000), - MT6366_REG_FIXED("ldo_vaud28", VAUD28, - MT6358_LDO_VAUD28_CON0, 0, 2800000), - MT6366_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx, + MT6366_REG_FIXED("vrf12", VRF12, "vs2-ldo2", MT6358_LDO_VRF12_CON0, 0, 1200000), + MT6366_REG_FIXED("vio18", VIO18, "vs1-ldo1", MT6358_LDO_VIO18_CON0, 0, 1800000), + MT6366_REG_FIXED("vfe28", VFE28, "vsys-ldo1", MT6358_LDO_VFE28_CON0, 0, 2800000), + MT6366_REG_FIXED("vcn28", VCN28, "vsys-ldo1", MT6358_LDO_VCN28_CON0, 0, 2800000), + MT6366_REG_FIXED("vxo22", VXO22, "vsys-ldo1", MT6358_LDO_VXO22_CON0, 0, 2200000), + MT6366_REG_FIXED("vaux18", VAUX18, "vsys-ldo1", MT6358_LDO_VAUX18_CON0, 0, 1800000), + MT6366_REG_FIXED("vbif28", VBIF28, "vsys-ldo1", MT6358_LDO_VBIF28_CON0, 0, 2800000), + MT6366_REG_FIXED("vio28", VIO28, "vsys-ldo2", MT6358_LDO_VIO28_CON0, 0, 2800000), + MT6366_REG_FIXED("va12", VA12, "vs2-ldo2", MT6358_LDO_VA12_CON0, 0, 1200000), + MT6366_REG_FIXED("vrf18", VRF18, "vs1-ldo1", MT6358_LDO_VRF18_CON0, 0, 1800000), + MT6366_REG_FIXED("vaud28", VAUD28, "vsys-ldo1", MT6358_LDO_VAUD28_CON0, 0, 2800000), + MT6366_LDO("vdram2", VDRAM2, vdram2, "vs2-ldo1", MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10), - MT6366_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx, + MT6366_LDO("vsim1", VSIM1, vsim, "vsys-ldo1", MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00), - MT6366_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx, + MT6366_LDO("vibr", VIBR, vibr, "vsys-ldo3", MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00), - MT6366_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx, + MT6366_LDO("vusb", VUSB, vusb, "vsys-ldo1", MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700), - MT6366_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx, + MT6366_LDO("vefuse", VEFUSE, vefuse, "vs1-ldo1", MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00), - MT6366_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx, + MT6366_LDO("vmch", VMCH, vmch_vemc, "vsys-ldo2", MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700), - MT6366_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx, + MT6366_LDO("vemc", VEMC, vmch_vemc, "vsys-ldo3", MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700), - MT6366_LDO("ldo_vcn33", VCN33, vcn33_voltages, vcn33_idx, + MT6366_LDO("vcn33", VCN33, vcn33, "vsys-ldo3", MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300), - MT6366_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx, + MT6366_LDO("vmc", VMC, vmc, "vsys-ldo2", MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00), - MT6366_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, + MT6366_LDO("vsim2", VSIM2, vsim, "vsys-ldo2", MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), - MT6366_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, + MT6366_LDO("vcn18", VCN18, mt6366_vcn18_vm18, "vs1-ldo1", + MT6358_LDO_VCN18_CON0, 0, MT6358_VCN18_ANA_CON0, 0xf00), + MT6366_LDO("vm18", VM18, mt6366_vcn18_vm18, "vs1-ldo1", + MT6358_LDO_VM18_CON0, 0, MT6358_VM18_ANA_CON0, 0xf00), + MT6366_LDO("vmddr", VMDDR, mt6366_vmddr, "vs2-ldo1", + MT6358_LDO_VMDDR_CON0, 0, MT6358_VMDDR_ANA_CON0, 0xf00), + MT6366_LDO1("vsram-proc11", VSRAM_PROC11, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), - MT6366_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, + MT6366_LDO1("vsram-others", VSRAM_OTHERS, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), - MT6366_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, + MT6366_LDO1("vsram-gpu", VSRAM_GPU, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), - MT6366_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, + MT6366_LDO1("vsram-proc12", VSRAM_PROC12, "vs2-ldo3", 500000, 1293750, 6250, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), + MT6366_LDO1("vsram-core", VSRAM_CORE, "vs2-ldo3", 500000, 1293750, 6250, + MT6358_LDO_VSRAM_CORE_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON5, 0x7f), }; static int mt6358_sync_vcn33_setting(struct device *dev) @@ -688,12 +688,18 @@ static int mt6358_regulator_probe(struct platform_device *pdev) const struct mt6358_regulator_info *mt6358_info; int i, max_regulator, ret; - if (mt6397->chip_id == MT6366_CHIP_ID) { - max_regulator = MT6366_MAX_REGULATOR; - mt6358_info = mt6366_regulators; - } else { + switch (mt6397->chip_id) { + case MT6358_CHIP_ID: max_regulator = MT6358_MAX_REGULATOR; mt6358_info = mt6358_regulators; + break; + case MT6366_CHIP_ID: + max_regulator = MT6366_MAX_REGULATOR; + mt6358_info = mt6366_regulators; + break; + default: + dev_err(&pdev->dev, "unsupported chip ID: %d\n", mt6397->chip_id); + return -EINVAL; } ret = mt6358_sync_vcn33_setting(&pdev->dev); diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 076966366b60..e0dc033aae0f 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -19,7 +19,6 @@ #include #include #include -#include #include static const struct linear_range smps_low_ranges[] = { @@ -1601,16 +1600,13 @@ static int palmas_regulators_probe(struct platform_device *pdev) struct regulator_config config = { }; struct palmas_pmic *pmic; const char *pdev_name; - const struct of_device_id *match; int ret = 0; unsigned int reg; - match = of_match_device(of_match_ptr(of_palmas_match_tbl), &pdev->dev); - - if (!match) + driver_data = (struct palmas_pmic_driver_data *)device_get_match_data(&pdev->dev); + if (!driver_data) return -ENODATA; - driver_data = (struct palmas_pmic_driver_data *)match->data; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 7ab3e4a9bd28..9fe539a34786 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -28,11 +29,6 @@ enum { PV88080_ID_HVBUCK, }; -enum pv88080_types { - TYPE_PV88080_AA, - TYPE_PV88080_BA, -}; - struct pv88080_regulator { struct regulator_desc desc; unsigned int mode_reg; @@ -196,16 +192,6 @@ static const struct pv88080_compatible_regmap pv88080_ba_regs = { .hvbuck_vsel_mask = PV88080_VHVBUCK_MASK, }; -#ifdef CONFIG_OF -static const struct of_device_id pv88080_dt_ids[] = { - { .compatible = "pvs,pv88080", .data = (void *)TYPE_PV88080_AA }, - { .compatible = "pvs,pv88080-aa", .data = (void *)TYPE_PV88080_AA }, - { .compatible = "pvs,pv88080-ba", .data = (void *)TYPE_PV88080_BA }, - {}, -}; -MODULE_DEVICE_TABLE(of, pv88080_dt_ids); -#endif - static unsigned int pv88080_buck_get_mode(struct regulator_dev *rdev) { struct pv88080_regulator *info = rdev_get_drvdata(rdev); @@ -376,11 +362,9 @@ error_i2c: */ static int pv88080_i2c_probe(struct i2c_client *i2c) { - const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); struct pv88080 *chip; const struct pv88080_compatible_regmap *regmap_config; - const struct of_device_id *match; struct regulator_config config = { }; int i, error, ret; unsigned int conf2, conf5; @@ -398,16 +382,9 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) return error; } - if (i2c->dev.of_node) { - match = of_match_node(pv88080_dt_ids, i2c->dev.of_node); - if (!match) { - dev_err(chip->dev, "Failed to get of_match_node\n"); - return -EINVAL; - } - chip->type = (unsigned long)match->data; - } else { - chip->type = id->driver_data; - } + chip->regmap_config = i2c_get_match_data(i2c); + if (!chip->regmap_config) + return -ENODEV; i2c_set_clientdata(i2c, chip); @@ -452,15 +429,6 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) dev_warn(chip->dev, "No IRQ configured\n"); } - switch (chip->type) { - case TYPE_PV88080_AA: - chip->regmap_config = &pv88080_aa_regs; - break; - case TYPE_PV88080_BA: - chip->regmap_config = &pv88080_ba_regs; - break; - } - regmap_config = chip->regmap_config; config.dev = chip->dev; config.regmap = chip->regmap; @@ -546,11 +514,19 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) return 0; } +static const struct of_device_id pv88080_dt_ids[] = { + { .compatible = "pvs,pv88080", .data = &pv88080_aa_regs }, + { .compatible = "pvs,pv88080-aa", .data = &pv88080_aa_regs }, + { .compatible = "pvs,pv88080-ba", .data = &pv88080_ba_regs }, + {} +}; +MODULE_DEVICE_TABLE(of, pv88080_dt_ids); + static const struct i2c_device_id pv88080_i2c_id[] = { - { "pv88080", TYPE_PV88080_AA }, - { "pv88080-aa", TYPE_PV88080_AA }, - { "pv88080-ba", TYPE_PV88080_BA }, - {}, + { "pv88080", (kernel_ulong_t)&pv88080_aa_regs }, + { "pv88080-aa", (kernel_ulong_t)&pv88080_aa_regs }, + { "pv88080-ba", (kernel_ulong_t)&pv88080_ba_regs }, + {} }; MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id); @@ -558,7 +534,7 @@ static struct i2c_driver pv88080_regulator_driver = { .driver = { .name = "pv88080", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(pv88080_dt_ids), + .of_match_table = pv88080_dt_ids, }, .probe = pv88080_i2c_probe, .id_table = pv88080_i2c_id, diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c index a8698ca61143..ba3f9391565f 100644 --- a/drivers/regulator/qcom-labibb-regulator.c +++ b/drivers/regulator/qcom-labibb-regulator.c @@ -764,7 +764,6 @@ static int qcom_labibb_regulator_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct regulator_config cfg = {}; struct device_node *reg_node; - const struct of_device_id *match; const struct labibb_regulator_data *reg_data; struct regmap *reg_regmap; unsigned int type; @@ -776,11 +775,11 @@ static int qcom_labibb_regulator_probe(struct platform_device *pdev) return -ENODEV; } - match = of_match_device(qcom_labibb_match, &pdev->dev); - if (!match) + reg_data = device_get_match_data(&pdev->dev); + if (!reg_data) return -ENODEV; - for (reg_data = match->data; reg_data->name; reg_data++) { + for (; reg_data->name; reg_data++) { char *sc_irq_name; int irq = 0; diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index d990ba19c50e..cf502eec0915 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -1095,7 +1095,22 @@ static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), - RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"), + {} +}; + +static const struct rpmh_vreg_init_data pmc8380_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"), RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"), RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"), @@ -1511,6 +1526,10 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .compatible = "qcom,pmc8180c-rpmh-regulators", .data = pm8150l_vreg_data, }, + { + .compatible = "qcom,pmc8380-rpmh-regulators", + .data = pmc8380_vreg_data, + }, { .compatible = "qcom,pmm8155au-rpmh-regulators", .data = pmm8155au_vreg_data, diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index 9366488f0383..2d5fec1457d1 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -937,7 +937,6 @@ MODULE_DEVICE_TABLE(of, rpm_of_match); static int rpm_reg_probe(struct platform_device *pdev) { const struct rpm_regulator_data *reg; - const struct of_device_id *match; struct regulator_config config = { }; struct regulator_dev *rdev; struct qcom_rpm_reg *vreg; @@ -949,13 +948,13 @@ static int rpm_reg_probe(struct platform_device *pdev) return -ENODEV; } - match = of_match_device(rpm_of_match, &pdev->dev); - if (!match) { + reg = device_get_match_data(&pdev->dev); + if (!reg) { dev_err(&pdev->dev, "failed to match device\n"); return -ENODEV; } - for (reg = match->data; reg->name; reg++) { + for (; reg->name; reg++) { vreg = devm_kmemdup(&pdev->dev, reg->template, sizeof(*vreg), GFP_KERNEL); if (!vreg) return -ENOMEM; diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index c95f6e9c7ab5..94f9092b29ef 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -2118,6 +2118,28 @@ static const struct spmi_regulator_data pm8005_regulators[] = { { } }; +static const struct spmi_regulator_data pm8019_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, + { "l1", 0x4000, "vdd_l1", }, + { "l2", 0x4100, "vdd_l2_l3", }, + { "l3", 0x4200, "vdd_l2_l3", }, + { "l4", 0x4300, "vdd_l4_l5_l6", }, + { "l5", 0x4400, "vdd_l4_l5_l6", }, + { "l6", 0x4500, "vdd_l4_l5_l6", }, + { "l7", 0x4600, "vdd_l7_l8_l11", }, + { "l8", 0x4700, "vdd_l7_l8_l11", }, + { "l9", 0x4800, "vdd_l9", }, + { "l10", 0x4900, "vdd_l10", }, + { "l11", 0x4a00, "vdd_l7_l8_l11", }, + { "l12", 0x4b00, "vdd_l12", }, + { "l13", 0x4c00, "vdd_l13_l14", }, + { "l14", 0x4d00, "vdd_l13_l14", }, + { } +}; + static const struct spmi_regulator_data pm8226_regulators[] = { { "s1", 0x1400, "vdd_s1", }, { "s2", 0x1700, "vdd_s2", }, @@ -2168,6 +2190,29 @@ static const struct spmi_regulator_data pm8841_regulators[] = { { } }; +static const struct spmi_regulator_data pm8909_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "l1", 0x4000, "vdd_l1", }, + { "l2", 0x4100, "vdd_l2_l5", }, + { "l3", 0x4200, "vdd_l3_l6_l10", }, + { "l4", 0x4300, "vdd_l4_l7", }, + { "l5", 0x4400, "vdd_l2_l5", }, + { "l6", 0x4500, "vdd_l3_l6_l10", }, + { "l7", 0x4600, "vdd_l4_l7", }, + { "l8", 0x4700, "vdd_l8_l11_l15_l18", }, + { "l9", 0x4800, "vdd_l9_l12_l14_l17", }, + { "l10", 0x4900, "vdd_l3_l6_l10", }, + { "l11", 0x4a00, "vdd_l8_l11_l15_l18", }, + { "l12", 0x4b00, "vdd_l9_l12_l14_l17", }, + { "l13", 0x4c00, "vdd_l13", }, + { "l14", 0x4d00, "vdd_l9_l12_l14_l17", }, + { "l15", 0x4e00, "vdd_l8_l11_l15_l18", }, + { "l17", 0x5000, "vdd_l9_l12_l14_l17", }, + { "l18", 0x5100, "vdd_l8_l11_l15_l18", }, + { } +}; + static const struct spmi_regulator_data pm8916_regulators[] = { { "s1", 0x1400, "vdd_s1", }, { "s2", 0x1700, "vdd_s2", }, @@ -2314,6 +2359,54 @@ static const struct spmi_regulator_data pm8994_regulators[] = { { } }; +static const struct spmi_regulator_data pma8084_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, + { "s5", 0x2000, "vdd_s5", }, + { "s6", 0x2300, "vdd_s6", }, + { "s7", 0x2600, "vdd_s7", }, + { "s8", 0x2900, "vdd_s8", }, + { "s9", 0x2c00, "vdd_s9", }, + { "s10", 0x2f00, "vdd_s10", }, + { "s11", 0x3200, "vdd_s11", }, + { "s12", 0x3500, "vdd_s12", }, + { "l1", 0x4000, "vdd_l1_l11", }, + { "l2", 0x4100, "vdd_l2_l3_l4_l27", }, + { "l3", 0x4200, "vdd_l2_l3_l4_l27", }, + { "l4", 0x4300, "vdd_l2_l3_l4_l27", }, + { "l5", 0x4400, "vdd_l5_l7", }, + { "l6", 0x4500, "vdd_l6_l12_l14_l15_l26", }, + { "l7", 0x4600, "vdd_l5_l7", }, + { "l8", 0x4700, "vdd_l8", }, + { "l9", 0x4800, "vdd_l9_l10_l13_l20_l23_l24", }, + { "l10", 0x4900, "vdd_l9_l10_l13_l20_l23_l24", }, + { "l11", 0x4a00, "vdd_l1_l11", }, + { "l12", 0x4b00, "vdd_l6_l12_l14_l15_l26", }, + { "l13", 0x4c00, "vdd_l9_l10_l13_l20_l23_l24", }, + { "l14", 0x4d00, "vdd_l6_l12_l14_l15_l26", }, + { "l15", 0x4e00, "vdd_l6_l12_l14_l15_l26", }, + { "l16", 0x4f00, "vdd_l16_l25", }, + { "l17", 0x5000, "vdd_l17", }, + { "l18", 0x5100, "vdd_l18", }, + { "l19", 0x5200, "vdd_l19", }, + { "l20", 0x5300, "vdd_l9_l10_l13_l20_l23_l24", }, + { "l21", 0x5400, "vdd_l21", }, + { "l22", 0x5500, "vdd_l22", }, + { "l23", 0x5600, "vdd_l9_l10_l13_l20_l23_l24", }, + { "l24", 0x5700, "vdd_l9_l10_l13_l20_l23_l24", }, + { "l25", 0x5800, "vdd_l16_l25", }, + { "l26", 0x5900, "vdd_l6_l12_l14_l15_l26", }, + { "l27", 0x5a00, "vdd_l2_l3_l4_l27", }, + { "lvs1", 0x8000, "vdd_lvs1_2", }, + { "lvs2", 0x8100, "vdd_lvs1_2", }, + { "lvs3", 0x8200, "vdd_lvs3_4", }, + { "lvs4", 0x8300, "vdd_lvs3_4", }, + { "5vs1", 0x8400, "vdd_5vs1", }, + { } +}; + static const struct spmi_regulator_data pmi8994_regulators[] = { { "s1", 0x1400, "vdd_s1", }, { "s2", 0x1700, "vdd_s2", }, @@ -2355,12 +2448,15 @@ static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, + { .compatible = "qcom,pm8019-regulators", .data = &pm8019_regulators }, { .compatible = "qcom,pm8226-regulators", .data = &pm8226_regulators }, { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, + { .compatible = "qcom,pm8909-regulators", .data = &pm8909_regulators }, { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, { .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators }, { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, + { .compatible = "qcom,pma8084-regulators", .data = &pma8084_regulators }, { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, { .compatible = "qcom,pmp8074-regulators", .data = &pmp8074_regulators }, { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, @@ -2372,7 +2468,6 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) { const struct spmi_regulator_data *reg; const struct spmi_voltage_range *range; - const struct of_device_id *match; struct regulator_config config = { }; struct regulator_dev *rdev; struct spmi_regulator *vreg; @@ -2395,8 +2490,8 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) if (!regmap) return -ENODEV; - match = of_match_device(qcom_spmi_regulator_match, &pdev->dev); - if (!match) + reg = device_get_match_data(&pdev->dev); + if (!reg) return -ENODEV; if (of_find_property(node, "qcom,saw-reg", &lenp)) { @@ -2407,7 +2502,7 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) dev_err(dev, "ERROR reading SAW regmap\n"); } - for (reg = match->data; reg->name; reg++) { + for (; reg->name; reg++) { if (saw_regmap) { reg_node = of_get_child_by_name(node, reg->name); diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 867a2cf243f6..e374fa6e5f28 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -15,10 +15,8 @@ */ #include -#include #include #include -#include #include #include #include diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c index b64dc5a497fa..2cdc7f0474f8 100644 --- a/drivers/regulator/stm32-booster.c +++ b/drivers/regulator/stm32-booster.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include @@ -83,8 +83,7 @@ static int stm32_booster_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - desc = (const struct regulator_desc *) - of_match_device(dev->driver->of_match_table, dev)->data; + desc = device_get_match_data(dev); config.regmap = regmap; config.dev = dev; diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index d49c0cba09fb..c05b67e26ac8 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -142,7 +142,7 @@ static int sy8824_i2c_probe(struct i2c_client *client) } di->dev = dev; - di->cfg = of_device_get_match_data(dev); + di->cfg = i2c_get_match_data(client); regmap = devm_regmap_init_i2c(client, di->cfg->config); if (IS_ERR(regmap)) { @@ -204,29 +204,17 @@ static const struct sy8824_config sy20278_cfg = { }; static const struct of_device_id sy8824_dt_ids[] = { - { - .compatible = "silergy,sy8824c", - .data = &sy8824c_cfg - }, - { - .compatible = "silergy,sy8824e", - .data = &sy8824e_cfg - }, - { - .compatible = "silergy,sy20276", - .data = &sy20276_cfg - }, - { - .compatible = "silergy,sy20278", - .data = &sy20278_cfg - }, + { .compatible = "silergy,sy8824c", .data = &sy8824c_cfg }, + { .compatible = "silergy,sy8824e", .data = &sy8824e_cfg }, + { .compatible = "silergy,sy20276", .data = &sy20276_cfg }, + { .compatible = "silergy,sy20278", .data = &sy20278_cfg }, { } }; MODULE_DEVICE_TABLE(of, sy8824_dt_ids); static const struct i2c_device_id sy8824_id[] = { - { "sy8824", }, - { }, + { "sy8824", (kernel_ulong_t)&sy8824c_cfg }, + { } }; MODULE_DEVICE_TABLE(i2c, sy8824_id); diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index 86d2d80b4b41..f48214e2c3b4 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -688,7 +687,6 @@ MODULE_DEVICE_TABLE(of, ti_abb_of_match); static int ti_abb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *match; struct resource *res; struct ti_abb *abb; struct regulator_init_data *initdata = NULL; @@ -699,21 +697,15 @@ static int ti_abb_probe(struct platform_device *pdev) char *pname; int ret = 0; - match = of_match_device(ti_abb_of_match, dev); - if (!match) { - /* We do not expect this to happen */ - dev_err(dev, "%s: Unable to match device\n", __func__); - return -ENODEV; - } - if (!match->data) { - dev_err(dev, "%s: Bad data in match\n", __func__); - return -EINVAL; - } - abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL); if (!abb) return -ENOMEM; - abb->regs = match->data; + + abb->regs = device_get_match_data(dev); + if (!abb->regs) { + dev_err(dev, "%s: Bad data in match\n", __func__); + return -EINVAL; + } /* Map ABB resources */ if (abb->regs->setup_off || abb->regs->control_off) { @@ -866,7 +858,7 @@ static struct platform_driver ti_abb_driver = { .driver = { .name = "ti_abb", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(ti_abb_of_match), + .of_match_table = ti_abb_of_match, }, }; module_platform_driver(ti_abb_driver); diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index d8a856c1587a..5199e0437388 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -255,16 +254,6 @@ static int tps51632_probe(struct i2c_client *client) int ret; struct regulator_config config = { }; - if (client->dev.of_node) { - const struct of_device_id *match; - match = of_match_device(of_match_ptr(tps51632_of_match), - &client->dev); - if (!match) { - dev_err(&client->dev, "Error: No device match found\n"); - return -ENODEV; - } - } - tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index f3810d9d1caa..27a96cafd1ea 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -31,10 +31,6 @@ #include "kunpeng_hccs.h" -/* PCC defines */ -#define HCCS_PCC_SIGNATURE_MASK 0x50434300 -#define HCCS_PCC_STATUS_CMD_COMPLETE BIT(0) - /* * Arbitrary retries in case the remote processor is slow to respond * to PCC commands @@ -187,7 +183,7 @@ static int hccs_check_chan_cmd_complete(struct hccs_dev *hdev) * deadline_us(timeout_us) until PCC command complete bit is set(cond) */ ret = readw_poll_timeout(&comm_base->status, status, - status & HCCS_PCC_STATUS_CMD_COMPLETE, + status & PCC_STATUS_CMD_COMPLETE, HCCS_POLL_STATUS_TIME_INTERVAL_US, cl_info->deadline_us); if (unlikely(ret)) @@ -208,7 +204,7 @@ static int hccs_pcc_cmd_send(struct hccs_dev *hdev, u8 cmd, int ret; /* Write signature for this subspace */ - tmp.signature = HCCS_PCC_SIGNATURE_MASK | hdev->chan_id; + tmp.signature = PCC_SIGNATURE | hdev->chan_id; /* Write to the shared command region */ tmp.command = cmd; /* Clear cmd complete bit */ diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2c21d5b96fdc..d4ac184bce95 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -862,7 +862,8 @@ config SPI_RZV2M_CSI tristate "Renesas RZ/V2M CSI controller" depends on ARCH_RENESAS || COMPILE_TEST help - SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI) + SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI). + CSI supports both SPI host and SPI target roles. config SPI_QCOM_QSPI tristate "QTI QSPI controller" diff --git a/drivers/spi/spi-ar934x.c b/drivers/spi/spi-ar934x.c index 58b98cea31d9..5ba988720851 100644 --- a/drivers/spi/spi-ar934x.c +++ b/drivers/spi/spi-ar934x.c @@ -168,27 +168,21 @@ static int ar934x_spi_probe(struct platform_device *pdev) struct ar934x_spi *sp; void __iomem *base; struct clk *clk; - int ret; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get clock\n"); return PTR_ERR(clk); } - ret = clk_prepare_enable(clk); - if (ret) - return ret; - ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*sp)); if (!ctlr) { dev_info(&pdev->dev, "failed to allocate spi controller\n"); - ret = -ENOMEM; - goto err_clk_disable; + return -ENOMEM; } /* disable flash mapping and expose spi controller registers */ @@ -212,25 +206,15 @@ static int ar934x_spi_probe(struct platform_device *pdev) sp->clk_freq = clk_get_rate(clk); sp->ctlr = ctlr; - ret = spi_register_controller(ctlr); - if (!ret) - return 0; - -err_clk_disable: - clk_disable_unprepare(clk); - return ret; + return spi_register_controller(ctlr); } static void ar934x_spi_remove(struct platform_device *pdev) { struct spi_controller *ctlr; - struct ar934x_spi *sp; ctlr = dev_get_drvdata(&pdev->dev); - sp = spi_controller_get_devdata(ctlr); - spi_unregister_controller(ctlr); - clk_disable_unprepare(sp->clk); } static struct platform_driver ar934x_spi_driver = { diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 0103ac0158c0..3c9ed412932f 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -865,18 +865,12 @@ static int a3700_spi_probe(struct platform_device *pdev) init_completion(&spi->done); - spi->clk = devm_clk_get(dev, NULL); + spi->clk = devm_clk_get_prepared(dev, NULL); if (IS_ERR(spi->clk)) { dev_err(dev, "could not find clk: %ld\n", PTR_ERR(spi->clk)); goto error; } - ret = clk_prepare(spi->clk); - if (ret) { - dev_err(dev, "could not prepare clk: %d\n", ret); - goto error; - } - host->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ, clk_get_rate(spi->clk)); host->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk), @@ -888,40 +882,29 @@ static int a3700_spi_probe(struct platform_device *pdev) dev_name(dev), host); if (ret) { dev_err(dev, "could not request IRQ: %d\n", ret); - goto error_clk; + goto error; } ret = devm_spi_register_controller(dev, host); if (ret) { dev_err(dev, "Failed to register host\n"); - goto error_clk; + goto error; } return 0; -error_clk: - clk_unprepare(spi->clk); error: spi_controller_put(host); out: return ret; } -static void a3700_spi_remove(struct platform_device *pdev) -{ - struct spi_controller *host = platform_get_drvdata(pdev); - struct a3700_spi *spi = spi_controller_get_devdata(host); - - clk_unprepare(spi->clk); -} - static struct platform_driver a3700_spi_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(a3700_spi_dt_ids), }, .probe = a3700_spi_probe, - .remove_new = a3700_spi_remove, }; module_platform_driver(a3700_spi_driver); diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 21b0fa646c7d..bbd417c55e7f 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -748,7 +748,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) aspi->ahb_window_size = resource_size(res); aspi->ahb_base_phy = res->start; - aspi->clk = devm_clk_get(&pdev->dev, NULL); + aspi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(aspi->clk)) { dev_err(dev, "missing clock\n"); return PTR_ERR(aspi->clk); @@ -760,12 +760,6 @@ static int aspeed_spi_probe(struct platform_device *pdev) return -EINVAL; } - ret = clk_prepare_enable(aspi->clk); - if (ret) { - dev_err(dev, "can not enable the clock\n"); - return ret; - } - /* IRQ is for DMA, which the driver doesn't support yet */ ctlr->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | data->mode_bits; @@ -777,14 +771,9 @@ static int aspeed_spi_probe(struct platform_device *pdev) ctlr->dev.of_node = dev->of_node; ret = devm_spi_register_controller(dev, ctlr); - if (ret) { + if (ret) dev_err(&pdev->dev, "spi_register_controller failed\n"); - goto disable_clk; - } - return 0; -disable_clk: - clk_disable_unprepare(aspi->clk); return ret; } @@ -793,7 +782,6 @@ static void aspeed_spi_remove(struct platform_device *pdev) struct aspeed_spi *aspi = platform_get_drvdata(pdev); aspeed_spi_enable(aspi, false); - clk_disable_unprepare(aspi->clk); } /* diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index b11d0f993cc7..1cea8e159344 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -132,28 +132,14 @@ static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, dma_cap_set(DMA_SLAVE, mask); ctlr->dma_tx = dma_request_chan(dev, "tx"); - if (IS_ERR_OR_NULL(ctlr->dma_tx)) { - if (IS_ERR(ctlr->dma_tx)) { - err = PTR_ERR(ctlr->dma_tx); - goto at91_usart_spi_error_clear; - } - - dev_dbg(dev, - "DMA TX channel not available, SPI unable to use DMA\n"); - err = -EBUSY; + if (IS_ERR(ctlr->dma_tx)) { + err = PTR_ERR(ctlr->dma_tx); goto at91_usart_spi_error_clear; } ctlr->dma_rx = dma_request_chan(dev, "rx"); - if (IS_ERR_OR_NULL(ctlr->dma_rx)) { - if (IS_ERR(ctlr->dma_rx)) { - err = PTR_ERR(ctlr->dma_rx); - goto at91_usart_spi_error; - } - - dev_dbg(dev, - "DMA RX channel not available, SPI unable to use DMA\n"); - err = -EBUSY; + if (IS_ERR(ctlr->dma_rx)) { + err = PTR_ERR(ctlr->dma_rx); goto at91_usart_spi_error; } diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 1b6d977d111c..c9f1d1e1dcf7 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -200,20 +200,16 @@ static int ath79_spi_probe(struct platform_device *pdev) goto err_put_host; } - sp->clk = devm_clk_get(&pdev->dev, "ahb"); + sp->clk = devm_clk_get_enabled(&pdev->dev, "ahb"); if (IS_ERR(sp->clk)) { ret = PTR_ERR(sp->clk); goto err_put_host; } - ret = clk_prepare_enable(sp->clk); - if (ret) - goto err_put_host; - rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ); if (!rate) { ret = -EINVAL; - goto err_clk_disable; + goto err_put_host; } sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate; @@ -229,8 +225,6 @@ static int ath79_spi_probe(struct platform_device *pdev) err_disable: ath79_spi_disable(sp); -err_clk_disable: - clk_disable_unprepare(sp->clk); err_put_host: spi_controller_put(host); @@ -243,7 +237,6 @@ static void ath79_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&sp->bitbang); ath79_spi_disable(sp); - clk_disable_unprepare(sp->clk); spi_controller_put(sp->bitbang.master); } diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 0258c9a72fdc..b96e55f59d1a 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -485,30 +485,22 @@ static int spi_engine_probe(struct platform_device *pdev) spin_lock_init(&spi_engine->lock); - spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); + spi_engine->clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); if (IS_ERR(spi_engine->clk)) { ret = PTR_ERR(spi_engine->clk); goto err_put_host; } - spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk"); + spi_engine->ref_clk = devm_clk_get_enabled(&pdev->dev, "spi_clk"); if (IS_ERR(spi_engine->ref_clk)) { ret = PTR_ERR(spi_engine->ref_clk); goto err_put_host; } - ret = clk_prepare_enable(spi_engine->clk); - if (ret) - goto err_put_host; - - ret = clk_prepare_enable(spi_engine->ref_clk); - if (ret) - goto err_clk_disable; - spi_engine->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_engine->base)) { ret = PTR_ERR(spi_engine->base); - goto err_ref_clk_disable; + goto err_put_host; } version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION); @@ -518,7 +510,7 @@ static int spi_engine_probe(struct platform_device *pdev) SPI_ENGINE_VERSION_MINOR(version), SPI_ENGINE_VERSION_PATCH(version)); ret = -ENODEV; - goto err_ref_clk_disable; + goto err_put_host; } writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET); @@ -527,7 +519,7 @@ static int spi_engine_probe(struct platform_device *pdev) ret = request_irq(irq, spi_engine_irq, 0, pdev->name, host); if (ret) - goto err_ref_clk_disable; + goto err_put_host; host->dev.of_node = pdev->dev.of_node; host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; @@ -545,10 +537,6 @@ static int spi_engine_probe(struct platform_device *pdev) return 0; err_free_irq: free_irq(irq, host); -err_ref_clk_disable: - clk_disable_unprepare(spi_engine->ref_clk); -err_clk_disable: - clk_disable_unprepare(spi_engine->clk); err_put_host: spi_controller_put(host); return ret; @@ -569,9 +557,6 @@ static void spi_engine_remove(struct platform_device *pdev) writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET); - - clk_disable_unprepare(spi_engine->ref_clk); - clk_disable_unprepare(spi_engine->clk); } static const struct of_device_id spi_engine_match_table[] = { diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index e7bb2714678a..e709887eb2a9 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -11,6 +11,7 @@ * spi-atmel.c, Copyright (C) 2006 Atmel Corporation */ +#include #include #include #include @@ -26,9 +27,10 @@ #include #include #include -#include /* FIXME: using chip internals */ -#include /* FIXME: using chip internals */ +#include /* FIXME: using GPIO lookup tables */ #include +#include +#include #include /* SPI register offsets */ @@ -83,6 +85,7 @@ MODULE_PARM_DESC(polling_limit_us, * struct bcm2835_spi - BCM2835 SPI controller * @regs: base address of register map * @clk: core clock, divided to calculate serial clock + * @cs_gpio: chip-select GPIO descriptor * @clk_hz: core clock cached speed * @irq: interrupt, signals TX FIFO empty or RX FIFO ¾ full * @tfr: SPI transfer currently processed @@ -117,6 +120,7 @@ MODULE_PARM_DESC(polling_limit_us, struct bcm2835_spi { void __iomem *regs; struct clk *clk; + struct gpio_desc *cs_gpio; unsigned long clk_hz; int irq; struct spi_transfer *tfr; @@ -1156,15 +1160,11 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr, bcm2835_spi_reset_hw(bs); } -static int chip_match_name(struct gpio_chip *chip, void *data) -{ - return !strcmp(chip->label, data); -} - static void bcm2835_spi_cleanup(struct spi_device *spi) { struct bcm2835_spidev *target = spi_get_ctldata(spi); struct spi_controller *ctlr = spi->controller; + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); if (target->clear_rx_desc) dmaengine_desc_free(target->clear_rx_desc); @@ -1175,6 +1175,9 @@ static void bcm2835_spi_cleanup(struct spi_device *spi) sizeof(u32), DMA_TO_DEVICE); + gpiod_put(bs->cs_gpio); + spi_set_csgpiod(spi, 0, NULL); + kfree(target); } @@ -1221,7 +1224,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) struct spi_controller *ctlr = spi->controller; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct bcm2835_spidev *target = spi_get_ctldata(spi); - struct gpio_chip *chip; + struct gpiod_lookup_table *lookup __free(kfree) = NULL; int ret; u32 cs; @@ -1288,29 +1291,36 @@ static int bcm2835_spi_setup(struct spi_device *spi) } /* - * Translate native CS to GPIO + * TODO: The code below is a slightly better alternative to the utter + * abuse of the GPIO API that I found here before. It creates a + * temporary lookup table, assigns it to the SPI device, gets the GPIO + * descriptor and then releases the lookup table. * - * FIXME: poking around in the gpiolib internals like this is - * not very good practice. Find a way to locate the real problem - * and fix it. Why is the GPIO descriptor in spi->cs_gpiod - * sometimes not assigned correctly? Erroneous device trees? + * More on the problem that it addresses: + * https://www.spinics.net/lists/linux-gpio/msg36218.html */ - - /* get the gpio chip for the base */ - chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); - if (!chip) - return 0; - - spi_set_csgpiod(spi, 0, gpiochip_request_own_desc(chip, - 8 - (spi_get_chipselect(spi, 0)), - DRV_NAME, - GPIO_LOOKUP_FLAGS_DEFAULT, - GPIOD_OUT_LOW)); - if (IS_ERR(spi_get_csgpiod(spi, 0))) { - ret = PTR_ERR(spi_get_csgpiod(spi, 0)); + lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL); + if (!lookup) { + ret = -ENOMEM; goto err_cleanup; } + lookup->dev_id = dev_name(&spi->dev); + lookup->table[0] = GPIO_LOOKUP("pinctrl-bcm2835", + 8 - (spi_get_chipselect(spi, 0)), + "cs", GPIO_LOOKUP_FLAGS_DEFAULT); + + gpiod_add_lookup_table(lookup); + + bs->cs_gpio = gpiod_get(&spi->dev, "cs", GPIOD_OUT_LOW); + gpiod_remove_lookup_table(lookup); + if (IS_ERR(bs->cs_gpio)) { + ret = PTR_ERR(bs->cs_gpio); + goto err_cleanup; + } + + spi_set_csgpiod(spi, 0, bs->cs_gpio); + /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n", spi_get_chipselect(spi, 0)); @@ -1352,7 +1362,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) if (IS_ERR(bs->regs)) return PTR_ERR(bs->regs); - bs->clk = devm_clk_get(&pdev->dev, NULL); + bs->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(bs->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk), "could not get clk\n"); @@ -1363,14 +1373,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev) if (bs->irq < 0) return bs->irq; - err = clk_prepare_enable(bs->clk); - if (err) - return err; bs->clk_hz = clk_get_rate(bs->clk); err = bcm2835_dma_init(ctlr, &pdev->dev, bs); if (err) - goto out_clk_disable; + return err; /* initialise the hardware with the default polarities */ bcm2835_wr(bs, BCM2835_SPI_CS, @@ -1396,8 +1403,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev) out_dma_release: bcm2835_dma_release(ctlr, bs); -out_clk_disable: - clk_disable_unprepare(bs->clk); return err; } @@ -1415,8 +1420,6 @@ static void bcm2835_spi_remove(struct platform_device *pdev) /* Clear FIFOs, and disable the HW block */ bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - - clk_disable_unprepare(bs->clk); } static const struct of_device_id bcm2835_spi_match[] = { diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 6d2a5d9f2498..06fe155a70c9 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -512,7 +512,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) if (IS_ERR(bs->regs)) return PTR_ERR(bs->regs); - bs->clk = devm_clk_get(&pdev->dev, NULL); + bs->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(bs->clk)) { err = PTR_ERR(bs->clk); dev_err(&pdev->dev, "could not get clk: %d\n", err); @@ -523,19 +523,11 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) if (bs->irq < 0) return bs->irq; - /* this also enables the HW block */ - err = clk_prepare_enable(bs->clk); - if (err) { - dev_err(&pdev->dev, "could not prepare clock: %d\n", err); - return err; - } - /* just checking if the clock returns a sane value */ clk_hz = clk_get_rate(bs->clk); if (!clk_hz) { dev_err(&pdev->dev, "clock returns 0 Hz\n"); - err = -ENODEV; - goto out_clk_disable; + return -ENODEV; } /* reset SPI-HW block */ @@ -547,22 +539,18 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), host); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); - goto out_clk_disable; + return err; } err = spi_register_controller(host); if (err) { dev_err(&pdev->dev, "could not register SPI host: %d\n", err); - goto out_clk_disable; + return err; } bcm2835aux_debugfs_create(bs, dev_name(&pdev->dev)); return 0; - -out_clk_disable: - clk_disable_unprepare(bs->clk); - return err; } static void bcm2835aux_spi_remove(struct platform_device *pdev) @@ -575,9 +563,6 @@ static void bcm2835aux_spi_remove(struct platform_device *pdev) spi_unregister_controller(host); bcm2835aux_spi_reset_hw(bs); - - /* disable the HW block by releasing the clock */ - clk_disable_unprepare(bs->clk); } static const struct of_device_id bcm2835aux_spi_match[] = { diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index b50db71ac4cc..3d7bf62da11c 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -116,6 +116,9 @@ struct cqspi_driver_platdata { #define CQSPI_TIMEOUT_MS 500 #define CQSPI_READ_TIMEOUT_MS 10 +/* Runtime_pm autosuspend delay */ +#define CQSPI_AUTOSUSPEND_TIMEOUT 2000 + #define CQSPI_DUMMY_CLKS_PER_BYTE 8 #define CQSPI_DUMMY_BYTES_MAX 4 #define CQSPI_DUMMY_CLKS_MAX 31 @@ -1407,8 +1410,20 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { int ret; + struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master); + struct device *dev = &cqspi->pdev->dev; + + ret = pm_runtime_resume_and_get(dev); + if (ret) { + dev_err(&mem->spi->dev, "resume failed with %d\n", ret); + return ret; + } ret = cqspi_mem_process(mem, op); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + if (ret) dev_err(&mem->spi->dev, "operation failed with %d\n", ret); @@ -1753,10 +1768,10 @@ static int cqspi_probe(struct platform_device *pdev) if (irq < 0) return -ENXIO; - pm_runtime_enable(dev); - ret = pm_runtime_resume_and_get(dev); - if (ret < 0) - goto probe_pm_failed; + ret = pm_runtime_set_active(dev); + if (ret) + return ret; + ret = clk_prepare_enable(cqspi->clk); if (ret) { @@ -1862,21 +1877,32 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_setup_failed; } + ret = devm_pm_runtime_enable(dev); + if (ret) { + if (cqspi->rx_chan) + dma_release_channel(cqspi->rx_chan); + goto probe_setup_failed; + } + + pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_use_autosuspend(dev); + pm_runtime_get_noresume(dev); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret); goto probe_setup_failed; } + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; probe_setup_failed: cqspi_controller_enable(cqspi, 0); probe_reset_failed: clk_disable_unprepare(cqspi->clk); probe_clk_failed: - pm_runtime_put_sync(dev); -probe_pm_failed: - pm_runtime_disable(dev); return ret; } @@ -1928,7 +1954,8 @@ static int cqspi_resume(struct device *dev) return spi_controller_resume(host); } -static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume); +static DEFINE_RUNTIME_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, + cqspi_resume, NULL); static const struct cqspi_driver_platdata cdns_qspi = { .quirks = CQSPI_DISABLE_DAC_MODE, @@ -2012,7 +2039,7 @@ static struct platform_driver cqspi_platform_driver = { .remove_new = cqspi_remove, .driver = { .name = CQSPI_NAME, - .pm = &cqspi_dev_pm_ops, + .pm = pm_ptr(&cqspi_dev_pm_ops), .of_match_table = cqspi_dt_ids, }, }; diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 12c940ba074a..1f2f8c717df6 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -581,31 +581,19 @@ static int cdns_spi_probe(struct platform_device *pdev) goto remove_ctlr; } - xspi->pclk = devm_clk_get(&pdev->dev, "pclk"); + xspi->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); if (IS_ERR(xspi->pclk)) { dev_err(&pdev->dev, "pclk clock not found.\n"); ret = PTR_ERR(xspi->pclk); goto remove_ctlr; } - ret = clk_prepare_enable(xspi->pclk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable APB clock.\n"); - goto remove_ctlr; - } - if (!spi_controller_is_target(ctlr)) { - xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk"); + xspi->ref_clk = devm_clk_get_enabled(&pdev->dev, "ref_clk"); if (IS_ERR(xspi->ref_clk)) { dev_err(&pdev->dev, "ref_clk clock not found.\n"); ret = PTR_ERR(xspi->ref_clk); - goto clk_dis_apb; - } - - ret = clk_prepare_enable(xspi->ref_clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable device clock.\n"); - goto clk_dis_apb; + goto remove_ctlr; } pm_runtime_use_autosuspend(&pdev->dev); @@ -679,10 +667,7 @@ clk_dis_all: if (!spi_controller_is_target(ctlr)) { pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(xspi->ref_clk); } -clk_dis_apb: - clk_disable_unprepare(xspi->pclk); remove_ctlr: spi_controller_put(ctlr); return ret; @@ -703,8 +688,6 @@ static void cdns_spi_remove(struct platform_device *pdev) cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); - clk_disable_unprepare(xspi->ref_clk); - clk_disable_unprepare(xspi->pclk); pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index f7c378a5f1bc..337aef12abcc 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -49,16 +49,12 @@ static int thunderx_spi_probe(struct pci_dev *pdev, p->regs.tx = 0x1010; p->regs.data = 0x1080; - p->clk = devm_clk_get(dev, NULL); + p->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(p->clk)) { ret = PTR_ERR(p->clk); goto error; } - ret = clk_prepare_enable(p->clk); - if (ret) - goto error; - p->sys_freq = clk_get_rate(p->clk); if (!p->sys_freq) p->sys_freq = SYS_FREQ_DEFAULT; @@ -82,7 +78,6 @@ static int thunderx_spi_probe(struct pci_dev *pdev, return 0; error: - clk_disable_unprepare(p->clk); pci_release_regions(pdev); spi_controller_put(host); return ret; @@ -97,7 +92,6 @@ static void thunderx_spi_remove(struct pci_dev *pdev) if (!p) return; - clk_disable_unprepare(p->clk); pci_release_regions(pdev); /* Put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index c457b550d3ad..5688be245c68 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -915,14 +915,11 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->bitbang.master = host; - dspi->clk = devm_clk_get(&pdev->dev, NULL); + dspi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { ret = -ENODEV; goto free_host; } - ret = clk_prepare_enable(dspi->clk); - if (ret) - goto free_host; host->use_gpio_descriptors = true; host->dev.of_node = pdev->dev.of_node; @@ -947,7 +944,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ret = davinci_spi_request_dma(dspi); if (ret == -EPROBE_DEFER) { - goto free_clk; + goto free_host; } else if (ret) { dev_info(&pdev->dev, "DMA is not supported (%d)\n", ret); dspi->dma_rx = NULL; @@ -991,8 +988,6 @@ free_dma: dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_tx); } -free_clk: - clk_disable_unprepare(dspi->clk); free_host: spi_controller_put(host); err: @@ -1018,8 +1013,6 @@ static void davinci_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&dspi->bitbang); - clk_disable_unprepare(dspi->clk); - if (dspi->dma_rx) { dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_tx); diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c index 5e1c01822967..5391bcac305c 100644 --- a/drivers/spi/spi-dw-bt1.c +++ b/drivers/spi/spi-dw-bt1.c @@ -269,43 +269,32 @@ static int dw_spi_bt1_probe(struct platform_device *pdev) dws->paddr = mem->start; - dwsbt1->clk = devm_clk_get(&pdev->dev, NULL); + dwsbt1->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(dwsbt1->clk)) return PTR_ERR(dwsbt1->clk); - ret = clk_prepare_enable(dwsbt1->clk); - if (ret) - return ret; - dws->bus_num = pdev->id; dws->reg_io_width = 4; dws->max_freq = clk_get_rate(dwsbt1->clk); - if (!dws->max_freq) { - ret = -EINVAL; - goto err_disable_clk; - } + if (!dws->max_freq) + return -EINVAL; init_func = device_get_match_data(&pdev->dev); ret = init_func(pdev, dwsbt1); if (ret) - goto err_disable_clk; + return ret; pm_runtime_enable(&pdev->dev); ret = dw_spi_add_host(&pdev->dev, dws); if (ret) { pm_runtime_disable(&pdev->dev); - goto err_disable_clk; + return ret; } platform_set_drvdata(pdev, dwsbt1); return 0; - -err_disable_clk: - clk_disable_unprepare(dwsbt1->clk); - - return ret; } static void dw_spi_bt1_remove(struct platform_device *pdev) @@ -315,8 +304,6 @@ static void dw_spi_bt1_remove(struct platform_device *pdev) dw_spi_remove_host(&dwsbt1->dws); pm_runtime_disable(&pdev->dev); - - clk_disable_unprepare(dwsbt1->clk); } static const struct of_device_id dw_spi_bt1_of_match[] = { diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 805264c9c65c..46801189a651 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -340,29 +340,20 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) if (dws->irq < 0) return dws->irq; /* -ENXIO */ - dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); + dwsmmio->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(dwsmmio->clk)) return PTR_ERR(dwsmmio->clk); - ret = clk_prepare_enable(dwsmmio->clk); - if (ret) - return ret; /* Optional clock needed to access the registers */ - dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); - if (IS_ERR(dwsmmio->pclk)) { - ret = PTR_ERR(dwsmmio->pclk); - goto out_clk; - } - ret = clk_prepare_enable(dwsmmio->pclk); - if (ret) - goto out_clk; + dwsmmio->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk"); + if (IS_ERR(dwsmmio->pclk)) + return PTR_ERR(dwsmmio->pclk); /* find an optional reset controller */ dwsmmio->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, "spi"); - if (IS_ERR(dwsmmio->rstc)) { - ret = PTR_ERR(dwsmmio->rstc); - goto out_clk; - } + if (IS_ERR(dwsmmio->rstc)) + return PTR_ERR(dwsmmio->rstc); + reset_control_deassert(dwsmmio->rstc); dws->bus_num = pdev->id; @@ -383,7 +374,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) if (init_func) { ret = init_func(pdev, dwsmmio); if (ret) - goto out; + goto out_reset; } pm_runtime_enable(&pdev->dev); @@ -397,9 +388,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) out: pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(dwsmmio->pclk); -out_clk: - clk_disable_unprepare(dwsmmio->clk); +out_reset: reset_control_assert(dwsmmio->rstc); return ret; @@ -411,8 +400,6 @@ static void dw_spi_mmio_remove(struct platform_device *pdev) dw_spi_remove_host(&dwsmmio->dws); pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(dwsmmio->pclk); - clk_disable_unprepare(dwsmmio->clk); reset_control_assert(dwsmmio->rstc); } diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 8318249f8a1f..c9eae046f66c 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1372,19 +1372,16 @@ static int dspi_probe(struct platform_device *pdev) } } - dspi->clk = devm_clk_get(&pdev->dev, "dspi"); + dspi->clk = devm_clk_get_enabled(&pdev->dev, "dspi"); if (IS_ERR(dspi->clk)) { ret = PTR_ERR(dspi->clk); dev_err(&pdev->dev, "unable to get clock\n"); goto out_ctlr_put; } - ret = clk_prepare_enable(dspi->clk); - if (ret) - goto out_ctlr_put; ret = dspi_init(dspi); if (ret) - goto out_clk_put; + goto out_ctlr_put; dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq <= 0) { @@ -1400,7 +1397,7 @@ static int dspi_probe(struct platform_device *pdev) IRQF_SHARED, pdev->name, dspi); if (ret < 0) { dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n"); - goto out_clk_put; + goto out_ctlr_put; } poll_mode: @@ -1432,8 +1429,6 @@ out_release_dma: out_free_irq: if (dspi->irq) free_irq(dspi->irq, dspi); -out_clk_put: - clk_disable_unprepare(dspi->clk); out_ctlr_put: spi_controller_put(ctlr); @@ -1458,7 +1453,6 @@ static void dspi_remove(struct platform_device *pdev) dspi_release_dma(dspi); if (dspi->irq) free_irq(dspi->irq, dspi); - clk_disable_unprepare(dspi->clk); } static void dspi_shutdown(struct platform_device *pdev) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index f4f376a8351b..b956a32a4162 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -166,7 +166,7 @@ static void handle_se_timeout(struct spi_master *spi, * doesn`t support CMD Cancel sequnece */ spin_unlock_irq(&mas->lock); - goto unmap_if_dma; + goto reset_if_dma; } reinit_completion(&mas->cancel_done); @@ -175,7 +175,7 @@ static void handle_se_timeout(struct spi_master *spi, time_left = wait_for_completion_timeout(&mas->cancel_done, HZ); if (time_left) - goto unmap_if_dma; + goto reset_if_dma; spin_lock_irq(&mas->lock); reinit_completion(&mas->abort_done); @@ -193,7 +193,7 @@ static void handle_se_timeout(struct spi_master *spi, mas->abort_failed = true; } -unmap_if_dma: +reset_if_dma: if (mas->cur_xfer_mode == GENI_SE_DMA) { if (xfer) { if (xfer->tx_buf) { diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 938e9e577e4f..18a46569ba46 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -932,14 +932,11 @@ static int lantiq_ssc_probe(struct platform_device *pdev) if (err) goto err_host_put; - spi->spi_clk = devm_clk_get(dev, "gate"); + spi->spi_clk = devm_clk_get_enabled(dev, "gate"); if (IS_ERR(spi->spi_clk)) { err = PTR_ERR(spi->spi_clk); goto err_host_put; } - err = clk_prepare_enable(spi->spi_clk); - if (err) - goto err_host_put; /* * Use the old clk_get_fpi() function on Lantiq platform, till it @@ -952,7 +949,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) #endif if (IS_ERR(spi->fpi_clk)) { err = PTR_ERR(spi->fpi_clk); - goto err_clk_disable; + goto err_host_put; } num_cs = 8; @@ -1010,8 +1007,6 @@ err_wq_destroy: destroy_workqueue(spi->wq); err_clk_put: clk_put(spi->fpi_clk); -err_clk_disable: - clk_disable_unprepare(spi->spi_clk); err_host_put: spi_controller_put(host); @@ -1029,7 +1024,6 @@ static void lantiq_ssc_remove(struct platform_device *pdev) hw_enter_config_mode(spi); destroy_workqueue(spi->wq); - clk_disable_unprepare(spi->spi_clk); clk_put(spi->fpi_clk); } diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index ead0507c63be..e6a65b5c8c31 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -24,7 +24,7 @@ * the SPI/Microwire bus interface. This driver specifically supports an * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel * port to bitbang an SPI-parport bridge. Accordingly, this is an SPI - * master controller driver. The hwmon/lm70 driver is a "SPI protocol + * host controller driver. The hwmon/lm70 driver is a "SPI protocol * driver", layered on top of this one and usable without the lm70llp. * * Datasheet and Schematic: @@ -189,7 +189,7 @@ static void spi_lm70llp_attach(struct parport *p) { struct pardevice *pd; struct spi_lm70llp *pp; - struct spi_master *master; + struct spi_controller *host; int status; struct pardev_cb lm70llp_cb; @@ -202,17 +202,17 @@ static void spi_lm70llp_attach(struct parport *p) * the lm70 driver could verify it, reading the manf ID. */ - master = spi_alloc_master(p->physport->dev, sizeof(*pp)); - if (!master) { + host = spi_alloc_host(p->physport->dev, sizeof(*pp)); + if (!host) { status = -ENOMEM; goto out_fail; } - pp = spi_master_get_devdata(master); + pp = spi_controller_get_devdata(host); /* * SPI and bitbang hookup. */ - pp->bitbang.master = master; + pp->bitbang.master = host; pp->bitbang.chipselect = lm70_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx; pp->bitbang.flags = SPI_3WIRE; @@ -228,7 +228,7 @@ static void spi_lm70llp_attach(struct parport *p) if (!pd) { status = -ENOMEM; - goto out_free_master; + goto out_free_host; } pp->pd = pd; @@ -287,8 +287,8 @@ out_off_and_release: parport_release(pp->pd); out_parport_unreg: parport_unregister_device(pd); -out_free_master: - spi_master_put(master); +out_free_host: + spi_controller_put(host); out_fail: pr_info("spi_lm70llp probe fail, status %d\n", status); } @@ -309,7 +309,7 @@ static void spi_lm70llp_detach(struct parport *p) parport_release(pp->pd); parport_unregister_device(pp->pd); - spi_master_put(pp->bitbang.master); + spi_controller_put(pp->bitbang.master); lm70llp = NULL; } diff --git a/drivers/spi/spi-lp8841-rtc.c b/drivers/spi/spi-lp8841-rtc.c index b357461f1b8b..382e2a69f7a7 100644 --- a/drivers/spi/spi-lp8841-rtc.c +++ b/drivers/spi/spi-lp8841-rtc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * SPI master driver for ICP DAS LP-8841 RTC + * SPI host driver for ICP DAS LP-8841 RTC * * Copyright (C) 2016 Sergei Ianovich * @@ -73,13 +73,13 @@ bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data, /* clock starts at inactive polarity */ for (; likely(bits); bits--) { - /* setup LSB (to slave) on leading edge */ + /* setup LSB (to target) on leading edge */ if ((flags & SPI_CONTROLLER_NO_TX) == 0) setmosi(data, (word & 1)); usleep_range(usecs, usecs + 1); /* T(setup) */ - /* sample LSB (from slave) on trailing edge */ + /* sample LSB (from target) on trailing edge */ word >>= 1; if ((flags & SPI_CONTROLLER_NO_RX) == 0) word |= (getmiso(data) << 31); @@ -95,11 +95,11 @@ bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data, } static int -spi_lp8841_rtc_transfer_one(struct spi_master *master, +spi_lp8841_rtc_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { - struct spi_lp8841_rtc *data = spi_master_get_devdata(master); + struct spi_lp8841_rtc *data = spi_controller_get_devdata(host); unsigned count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; @@ -128,7 +128,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master, ret = -EINVAL; } - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return ret; } @@ -136,7 +136,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master, static void spi_lp8841_rtc_set_cs(struct spi_device *spi, bool enable) { - struct spi_lp8841_rtc *data = spi_master_get_devdata(spi->master); + struct spi_lp8841_rtc *data = spi_controller_get_devdata(spi->controller); data->state = 0; writeb(data->state, data->iomem); @@ -182,48 +182,48 @@ static int spi_lp8841_rtc_probe(struct platform_device *pdev) { int ret; - struct spi_master *master; + struct spi_controller *host; struct spi_lp8841_rtc *data; - master = spi_alloc_master(&pdev->dev, sizeof(*data)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*data)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - master->flags = SPI_CONTROLLER_HALF_DUPLEX; - master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST; - master->bus_num = pdev->id; - master->num_chipselect = 1; - master->setup = spi_lp8841_rtc_setup; - master->set_cs = spi_lp8841_rtc_set_cs; - master->transfer_one = spi_lp8841_rtc_transfer_one; - master->bits_per_word_mask = SPI_BPW_MASK(8); + host->bus_num = pdev->id; + host->num_chipselect = 1; + host->setup = spi_lp8841_rtc_setup; + host->set_cs = spi_lp8841_rtc_set_cs; + host->transfer_one = spi_lp8841_rtc_transfer_one; + host->bits_per_word_mask = SPI_BPW_MASK(8); #ifdef CONFIG_OF - master->dev.of_node = pdev->dev.of_node; + host->dev.of_node = pdev->dev.of_node; #endif - data = spi_master_get_devdata(master); + data = spi_controller_get_devdata(host); data->iomem = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(data->iomem); if (ret) { dev_err(&pdev->dev, "failed to get IO address\n"); - goto err_put_master; + goto err_put_host; } /* register with the SPI framework */ - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { - dev_err(&pdev->dev, "cannot register spi master\n"); - goto err_put_master; + dev_err(&pdev->dev, "cannot register spi host\n"); + goto err_put_host; } return ret; -err_put_master: - spi_master_put(master); +err_put_host: + spi_controller_put(host); return ret; } @@ -239,6 +239,6 @@ static struct platform_driver spi_lp8841_rtc_driver = { }; module_platform_driver(spi_lp8841_rtc_driver); -MODULE_DESCRIPTION("SPI master driver for ICP DAS LP-8841 RTC"); +MODULE_DESCRIPTION("SPI host driver for ICP DAS LP-8841 RTC"); MODULE_AUTHOR("Sergei Ianovich"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 43d134f4b42b..fc75492e50ff 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -151,7 +151,7 @@ struct meson_spicc_data { }; struct meson_spicc_device { - struct spi_master *master; + struct spi_controller *host; struct platform_device *pdev; void __iomem *base; struct clk *core; @@ -399,11 +399,11 @@ static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc) spicc->base + SPICC_ENH_CTL0); } -static int meson_spicc_transfer_one(struct spi_master *master, +static int meson_spicc_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct meson_spicc_device *spicc = spi_master_get_devdata(master); + struct meson_spicc_device *spicc = spi_controller_get_devdata(host); uint64_t timeout; /* Store current transfer */ @@ -454,10 +454,10 @@ static int meson_spicc_transfer_one(struct spi_master *master, return 0; } -static int meson_spicc_prepare_message(struct spi_master *master, +static int meson_spicc_prepare_message(struct spi_controller *host, struct spi_message *message) { - struct meson_spicc_device *spicc = spi_master_get_devdata(master); + struct meson_spicc_device *spicc = spi_controller_get_devdata(host); struct spi_device *spi = message->spi; u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK; @@ -519,9 +519,9 @@ static int meson_spicc_prepare_message(struct spi_master *master, return 0; } -static int meson_spicc_unprepare_transfer(struct spi_master *master) +static int meson_spicc_unprepare_transfer(struct spi_controller *host) { - struct meson_spicc_device *spicc = spi_master_get_devdata(master); + struct meson_spicc_device *spicc = spi_controller_get_devdata(host); u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK; /* Disable all IRQs */ @@ -541,7 +541,7 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master) static int meson_spicc_setup(struct spi_device *spi) { if (!spi->controller_state) - spi->controller_state = spi_master_get_devdata(spi->master); + spi->controller_state = spi_controller_get_devdata(spi->controller); return 0; } @@ -585,7 +585,7 @@ static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw, struct clk_divider *divider = to_clk_divider(hw); struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); - if (!spicc->master->cur_msg) + if (!spicc->host->cur_msg) return 0; return clk_divider_ops.recalc_rate(hw, parent_rate); @@ -597,7 +597,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw, struct clk_divider *divider = to_clk_divider(hw); struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); - if (!spicc->master->cur_msg) + if (!spicc->host->cur_msg) return -EINVAL; return clk_divider_ops.determine_rate(hw, req); @@ -609,7 +609,7 @@ static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_divider *divider = to_clk_divider(hw); struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); - if (!spicc->master->cur_msg) + if (!spicc->host->cur_msg) return -EINVAL; return clk_divider_ops.set_rate(hw, rate, parent_rate); @@ -769,23 +769,23 @@ static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc) static int meson_spicc_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct meson_spicc_device *spicc; int ret, irq; - master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); - if (!master) { - dev_err(&pdev->dev, "master allocation failed\n"); + host = spi_alloc_host(&pdev->dev, sizeof(*spicc)); + if (!host) { + dev_err(&pdev->dev, "host allocation failed\n"); return -ENOMEM; } - spicc = spi_master_get_devdata(master); - spicc->master = master; + spicc = spi_controller_get_devdata(host); + spicc->host = host; spicc->data = of_device_get_match_data(&pdev->dev); if (!spicc->data) { dev_err(&pdev->dev, "failed to get match data\n"); ret = -EINVAL; - goto out_master; + goto out_host; } spicc->pdev = pdev; @@ -797,7 +797,7 @@ static int meson_spicc_probe(struct platform_device *pdev) if (IS_ERR(spicc->base)) { dev_err(&pdev->dev, "io resource mapping failed\n"); ret = PTR_ERR(spicc->base); - goto out_master; + goto out_host; } /* Set master mode and enable controller */ @@ -810,101 +810,83 @@ static int meson_spicc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; - goto out_master; + goto out_host; } ret = devm_request_irq(&pdev->dev, irq, meson_spicc_irq, 0, NULL, spicc); if (ret) { dev_err(&pdev->dev, "irq request failed\n"); - goto out_master; + goto out_host; } - spicc->core = devm_clk_get(&pdev->dev, "core"); + spicc->core = devm_clk_get_enabled(&pdev->dev, "core"); if (IS_ERR(spicc->core)) { dev_err(&pdev->dev, "core clock request failed\n"); ret = PTR_ERR(spicc->core); - goto out_master; + goto out_host; } if (spicc->data->has_pclk) { - spicc->pclk = devm_clk_get(&pdev->dev, "pclk"); + spicc->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); if (IS_ERR(spicc->pclk)) { dev_err(&pdev->dev, "pclk clock request failed\n"); ret = PTR_ERR(spicc->pclk); - goto out_master; + goto out_host; } } - ret = clk_prepare_enable(spicc->core); - if (ret) { - dev_err(&pdev->dev, "core clock enable failed\n"); - goto out_master; - } - - ret = clk_prepare_enable(spicc->pclk); - if (ret) { - dev_err(&pdev->dev, "pclk clock enable failed\n"); - goto out_core_clk; - } - spicc->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(spicc->pinctrl)) { ret = PTR_ERR(spicc->pinctrl); - goto out_clk; + goto out_host; } device_reset_optional(&pdev->dev); - master->num_chipselect = 4; - master->dev.of_node = pdev->dev.of_node; - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH; - master->bits_per_word_mask = SPI_BPW_MASK(32) | - SPI_BPW_MASK(24) | - SPI_BPW_MASK(16) | - SPI_BPW_MASK(8); - master->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX); - master->min_speed_hz = spicc->data->min_speed_hz; - master->max_speed_hz = spicc->data->max_speed_hz; - master->setup = meson_spicc_setup; - master->cleanup = meson_spicc_cleanup; - master->prepare_message = meson_spicc_prepare_message; - master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer; - master->transfer_one = meson_spicc_transfer_one; - master->use_gpio_descriptors = true; + host->num_chipselect = 4; + host->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH; + host->bits_per_word_mask = SPI_BPW_MASK(32) | + SPI_BPW_MASK(24) | + SPI_BPW_MASK(16) | + SPI_BPW_MASK(8); + host->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX); + host->min_speed_hz = spicc->data->min_speed_hz; + host->max_speed_hz = spicc->data->max_speed_hz; + host->setup = meson_spicc_setup; + host->cleanup = meson_spicc_cleanup; + host->prepare_message = meson_spicc_prepare_message; + host->unprepare_transfer_hardware = meson_spicc_unprepare_transfer; + host->transfer_one = meson_spicc_transfer_one; + host->use_gpio_descriptors = true; meson_spicc_oen_enable(spicc); ret = meson_spicc_pow2_clk_init(spicc); if (ret) { dev_err(&pdev->dev, "pow2 clock registration failed\n"); - goto out_clk; + goto out_host; } if (spicc->data->has_enhance_clk_div) { ret = meson_spicc_enh_clk_init(spicc); if (ret) { dev_err(&pdev->dev, "clock registration failed\n"); - goto out_clk; + goto out_host; } } - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { - dev_err(&pdev->dev, "spi master registration failed\n"); - goto out_clk; + dev_err(&pdev->dev, "spi registration failed\n"); + goto out_host; } return 0; -out_clk: - clk_disable_unprepare(spicc->pclk); - -out_core_clk: - clk_disable_unprepare(spicc->core); - -out_master: - spi_master_put(master); +out_host: + spi_controller_put(host); return ret; } @@ -916,10 +898,7 @@ static void meson_spicc_remove(struct platform_device *pdev) /* Disable SPI */ writel(0, spicc->base + SPICC_CONREG); - clk_disable_unprepare(spicc->core); - clk_disable_unprepare(spicc->pclk); - - spi_master_put(spicc->master); + spi_controller_put(spicc->host); } static const struct meson_spicc_data meson_spicc_gx_data = { diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c index 06626f406f68..fd8b26dd4a79 100644 --- a/drivers/spi/spi-meson-spifc.c +++ b/drivers/spi/spi-meson-spifc.c @@ -67,13 +67,13 @@ /** * struct meson_spifc - * @master: the SPI master + * @host: the SPI host * @regmap: regmap for device registers * @clk: input clock of the built-in baud rate generator * @dev: the device structure */ struct meson_spifc { - struct spi_master *master; + struct spi_controller *host; struct regmap *regmap; struct clk *clk; struct device *dev; @@ -237,16 +237,16 @@ static int meson_spifc_txrx(struct meson_spifc *spifc, /** * meson_spifc_transfer_one() - perform a single transfer - * @master: the SPI master + * @host: the SPI host * @spi: the SPI device * @xfer: the current SPI transfer * Return: 0 on success, a negative value on error */ -static int meson_spifc_transfer_one(struct spi_master *master, +static int meson_spifc_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct meson_spifc *spifc = spi_master_get_devdata(master); + struct meson_spifc *spifc = spi_controller_get_devdata(host); int len, done = 0, ret = 0; meson_spifc_setup_speed(spifc, xfer->speed_hz); @@ -256,7 +256,7 @@ static int meson_spifc_transfer_one(struct spi_master *master, while (done < xfer->len && !ret) { len = min_t(int, xfer->len - done, SPIFC_BUFFER_SIZE); ret = meson_spifc_txrx(spifc, xfer, done, len, - spi_transfer_is_last(master, xfer), + spi_transfer_is_last(host, xfer), done + len >= xfer->len); done += len; } @@ -284,19 +284,19 @@ static void meson_spifc_hw_init(struct meson_spifc *spifc) static int meson_spifc_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct meson_spifc *spifc; void __iomem *base; unsigned int rate; int ret = 0; - master = spi_alloc_master(&pdev->dev, sizeof(struct meson_spifc)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(struct meson_spifc)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - spifc = spi_master_get_devdata(master); + spifc = spi_controller_get_devdata(host); spifc->dev = &pdev->dev; base = devm_platform_ioremap_resource(pdev, 0); @@ -312,67 +312,56 @@ static int meson_spifc_probe(struct platform_device *pdev) goto out_err; } - spifc->clk = devm_clk_get(spifc->dev, NULL); + spifc->clk = devm_clk_get_enabled(spifc->dev, NULL); if (IS_ERR(spifc->clk)) { dev_err(spifc->dev, "missing clock\n"); ret = PTR_ERR(spifc->clk); goto out_err; } - ret = clk_prepare_enable(spifc->clk); - if (ret) { - dev_err(spifc->dev, "can't prepare clock\n"); - goto out_err; - } - rate = clk_get_rate(spifc->clk); - master->num_chipselect = 1; - master->dev.of_node = pdev->dev.of_node; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->auto_runtime_pm = true; - master->transfer_one = meson_spifc_transfer_one; - master->min_speed_hz = rate >> 6; - master->max_speed_hz = rate >> 1; + host->num_chipselect = 1; + host->dev.of_node = pdev->dev.of_node; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->auto_runtime_pm = true; + host->transfer_one = meson_spifc_transfer_one; + host->min_speed_hz = rate >> 6; + host->max_speed_hz = rate >> 1; meson_spifc_hw_init(spifc); pm_runtime_set_active(spifc->dev); pm_runtime_enable(spifc->dev); - ret = devm_spi_register_master(spifc->dev, master); + ret = devm_spi_register_controller(spifc->dev, host); if (ret) { - dev_err(spifc->dev, "failed to register spi master\n"); - goto out_clk; + dev_err(spifc->dev, "failed to register spi host\n"); + goto out_pm; } return 0; -out_clk: - clk_disable_unprepare(spifc->clk); +out_pm: pm_runtime_disable(spifc->dev); out_err: - spi_master_put(master); + spi_controller_put(host); return ret; } static void meson_spifc_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct meson_spifc *spifc = spi_master_get_devdata(master); - pm_runtime_get_sync(&pdev->dev); - clk_disable_unprepare(spifc->clk); pm_runtime_disable(&pdev->dev); } #ifdef CONFIG_PM_SLEEP static int meson_spifc_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct meson_spifc *spifc = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct meson_spifc *spifc = spi_controller_get_devdata(host); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -384,8 +373,8 @@ static int meson_spifc_suspend(struct device *dev) static int meson_spifc_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct meson_spifc *spifc = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct meson_spifc *spifc = spi_controller_get_devdata(host); int ret; if (!pm_runtime_suspended(dev)) { @@ -396,7 +385,7 @@ static int meson_spifc_resume(struct device *dev) meson_spifc_hw_init(spifc); - ret = spi_master_resume(master); + ret = spi_controller_resume(host); if (ret) clk_disable_unprepare(spifc->clk); @@ -407,8 +396,8 @@ static int meson_spifc_resume(struct device *dev) #ifdef CONFIG_PM static int meson_spifc_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct meson_spifc *spifc = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct meson_spifc *spifc = spi_controller_get_devdata(host); clk_disable_unprepare(spifc->clk); @@ -417,8 +406,8 @@ static int meson_spifc_runtime_suspend(struct device *dev) static int meson_spifc_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct meson_spifc *spifc = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct meson_spifc *spifc = spi_controller_get_devdata(host); return clk_prepare_enable(spifc->clk); } diff --git a/drivers/spi/spi-microchip-core-qspi.c b/drivers/spi/spi-microchip-core-qspi.c index 4f76ddf97b10..03d125a71fd9 100644 --- a/drivers/spi/spi-microchip-core-qspi.c +++ b/drivers/spi/spi-microchip-core-qspi.c @@ -299,7 +299,7 @@ static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_devi static int mchp_coreqspi_setup_op(struct spi_device *spi_dev) { - struct spi_controller *ctlr = spi_dev->master; + struct spi_controller *ctlr = spi_dev->controller; struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr); u32 control = readl_relaxed(qspi->regs + REG_CONTROL); @@ -368,7 +368,7 @@ static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const str static int mchp_qspi_wait_for_ready(struct spi_mem *mem) { struct mchp_coreqspi *qspi = spi_controller_get_devdata - (mem->spi->master); + (mem->spi->controller); u32 status; int ret; @@ -387,7 +387,7 @@ static int mchp_qspi_wait_for_ready(struct spi_mem *mem) static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { struct mchp_coreqspi *qspi = spi_controller_get_devdata - (mem->spi->master); + (mem->spi->controller); u32 address = op->addr.val; u8 opcode = op->cmd.opcode; u8 opaddr[5]; @@ -505,10 +505,10 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; int ret; - ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*qspi)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*qspi)); if (!ctlr) return dev_err_probe(&pdev->dev, -ENOMEM, - "unable to allocate master for QSPI controller\n"); + "unable to allocate host for QSPI controller\n"); qspi = spi_controller_get_devdata(ctlr); platform_set_drvdata(pdev, qspi); @@ -518,30 +518,23 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(qspi->regs), "failed to map registers\n"); - qspi->clk = devm_clk_get(&pdev->dev, NULL); + qspi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(qspi->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(qspi->clk), "could not get clock\n"); - ret = clk_prepare_enable(qspi->clk); - if (ret) - return dev_err_probe(&pdev->dev, ret, - "failed to enable clock\n"); - init_completion(&qspi->data_completion); mutex_init(&qspi->op_lock); qspi->irq = platform_get_irq(pdev, 0); - if (qspi->irq < 0) { - ret = qspi->irq; - goto out; - } + if (qspi->irq < 0) + return qspi->irq; ret = devm_request_irq(&pdev->dev, qspi->irq, mchp_coreqspi_isr, IRQF_SHARED, pdev->name, qspi); if (ret) { dev_err(&pdev->dev, "request_irq failed %d\n", ret); - goto out; + return ret; } ctlr->bits_per_word_mask = SPI_BPW_MASK(8); @@ -552,18 +545,11 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; ret = devm_spi_register_controller(&pdev->dev, ctlr); - if (ret) { - dev_err_probe(&pdev->dev, ret, - "spi_register_controller failed\n"); - goto out; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "spi_register_controller failed\n"); return 0; - -out: - clk_disable_unprepare(qspi->clk); - - return ret; } static void mchp_coreqspi_remove(struct platform_device *pdev) @@ -574,7 +560,6 @@ static void mchp_coreqspi_remove(struct platform_device *pdev) mchp_coreqspi_disable_ints(qspi); control &= ~CONTROL_ENABLE; writel_relaxed(control, qspi->regs + REG_CONTROL); - clk_disable_unprepare(qspi->clk); } static const struct of_device_id mchp_coreqspi_of_match[] = { diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c index b451cd4860ec..634364c7cfe6 100644 --- a/drivers/spi/spi-microchip-core.c +++ b/drivers/spi/spi-microchip-core.c @@ -244,7 +244,7 @@ static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt) static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) { u32 reg; - struct mchp_corespi *corespi = spi_master_get_devdata(spi->master); + struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); reg = mchp_corespi_read(corespi, REG_SLAVE_SELECT); reg &= ~BIT(spi_get_chipselect(spi, 0)); @@ -255,11 +255,11 @@ static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) static int mchp_corespi_setup(struct spi_device *spi) { - struct mchp_corespi *corespi = spi_master_get_devdata(spi->master); + struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); u32 reg; /* - * Active high slaves need to be specifically set to their inactive + * Active high targets need to be specifically set to their inactive * states during probe by adding them to the "control group" & thus * driving their select line low. */ @@ -271,7 +271,7 @@ static int mchp_corespi_setup(struct spi_device *spi) return 0; } -static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *spi) +static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *spi) { unsigned long clk_hz; u32 control = mchp_corespi_read(spi, REG_CONTROL); @@ -285,7 +285,7 @@ static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *sp /* max. possible spi clock rate is the apb clock rate */ clk_hz = clk_get_rate(spi->clk); - master->max_speed_hz = clk_hz; + host->max_speed_hz = clk_hz; /* * The controller must be configured so that it doesn't remove Chip @@ -305,7 +305,7 @@ static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *sp /* * It is required to enable direct mode, otherwise control over the chip * select is relinquished to the hardware. SSELOUT is enabled too so we - * can deal with active high slaves. + * can deal with active high targets. */ mchp_corespi_write(spi, REG_SLAVE_SELECT, SSELOUT | SSEL_DIRECT); @@ -371,8 +371,8 @@ static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct mchp_corespi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_id; + struct mchp_corespi *spi = spi_controller_get_devdata(host); u32 intfield = mchp_corespi_read(spi, REG_MIS) & 0xf; bool finalise = false; @@ -399,7 +399,7 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id) if (intfield & INT_RX_CHANNEL_OVERFLOW) { mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); finalise = true; - dev_err(&master->dev, + dev_err(&host->dev, "%s: RX OVERFLOW: rxlen: %d, txlen: %d\n", __func__, spi->rx_len, spi->tx_len); } @@ -407,13 +407,13 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id) if (intfield & INT_TX_CHANNEL_UNDERRUN) { mchp_corespi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN); finalise = true; - dev_err(&master->dev, + dev_err(&host->dev, "%s: TX UNDERFLOW: rxlen: %d, txlen: %d\n", __func__, spi->rx_len, spi->tx_len); } if (finalise) - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return IRQ_HANDLED; } @@ -455,16 +455,16 @@ static int mchp_corespi_calculate_clkgen(struct mchp_corespi *spi, return 0; } -static int mchp_corespi_transfer_one(struct spi_master *master, +static int mchp_corespi_transfer_one(struct spi_controller *host, struct spi_device *spi_dev, struct spi_transfer *xfer) { - struct mchp_corespi *spi = spi_master_get_devdata(master); + struct mchp_corespi *spi = spi_controller_get_devdata(host); int ret; ret = mchp_corespi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz); if (ret) { - dev_err(&master->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz); + dev_err(&host->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz); return ret; } @@ -484,11 +484,11 @@ static int mchp_corespi_transfer_one(struct spi_master *master, return 1; } -static int mchp_corespi_prepare_message(struct spi_master *master, +static int mchp_corespi_prepare_message(struct spi_controller *host, struct spi_message *msg) { struct spi_device *spi_dev = msg->spi; - struct mchp_corespi *spi = spi_master_get_devdata(master); + struct mchp_corespi *spi = spi_controller_get_devdata(host); mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); mchp_corespi_set_mode(spi, spi_dev->mode); @@ -498,32 +498,32 @@ static int mchp_corespi_prepare_message(struct spi_master *master, static int mchp_corespi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct mchp_corespi *spi; struct resource *res; u32 num_cs; int ret = 0; - master = devm_spi_alloc_master(&pdev->dev, sizeof(*spi)); - if (!master) + host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi)); + if (!host) return dev_err_probe(&pdev->dev, -ENOMEM, - "unable to allocate master for SPI controller\n"); + "unable to allocate host for SPI controller\n"); - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs)) num_cs = MAX_CS; - master->num_chipselect = num_cs; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->setup = mchp_corespi_setup; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->transfer_one = mchp_corespi_transfer_one; - master->prepare_message = mchp_corespi_prepare_message; - master->set_cs = mchp_corespi_set_cs; - master->dev.of_node = pdev->dev.of_node; + host->num_chipselect = num_cs; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->setup = mchp_corespi_setup; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->transfer_one = mchp_corespi_transfer_one; + host->prepare_message = mchp_corespi_prepare_message; + host->set_cs = mchp_corespi_set_cs; + host->dev.of_node = pdev->dev.of_node; - spi = spi_master_get_devdata(master); + spi = spi_controller_get_devdata(host); spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(spi->regs)) @@ -534,43 +534,36 @@ static int mchp_corespi_probe(struct platform_device *pdev) return spi->irq; ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt, - IRQF_SHARED, dev_name(&pdev->dev), master); + IRQF_SHARED, dev_name(&pdev->dev), host); if (ret) return dev_err_probe(&pdev->dev, ret, "could not request irq\n"); - spi->clk = devm_clk_get(&pdev->dev, NULL); + spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(spi->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), "could not get clk\n"); - ret = clk_prepare_enable(spi->clk); - if (ret) - return dev_err_probe(&pdev->dev, ret, - "failed to enable clock\n"); + mchp_corespi_init(host, spi); - mchp_corespi_init(master, spi); - - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { mchp_corespi_disable(spi); - clk_disable_unprepare(spi->clk); return dev_err_probe(&pdev->dev, ret, - "unable to register master for SPI controller\n"); + "unable to register host for SPI controller\n"); } - dev_info(&pdev->dev, "Registered SPI controller %d\n", master->bus_num); + dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num); return 0; } static void mchp_corespi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct mchp_corespi *spi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct mchp_corespi *spi = spi_controller_get_devdata(host); mchp_corespi_disable_ints(spi); - clk_disable_unprepare(spi->clk); mchp_corespi_disable(spi); } diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 5cecca1bef02..3c1638ba5bee 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -85,7 +85,7 @@ static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi, static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) { struct mpc512x_psc_spi_cs *cs = spi->controller_state; - struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc512x_psc_spi *mps = spi_controller_get_devdata(spi->controller); u32 sicr; u32 ccr; int speed; @@ -143,7 +143,7 @@ static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi) static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, struct spi_transfer *t) { - struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc512x_psc_spi *mps = spi_controller_get_devdata(spi->controller); struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; size_t tx_len = t->len; size_t rx_len = t->len; @@ -280,7 +280,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, return 0; } -static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, +static int mpc512x_psc_spi_msg_xfer(struct spi_controller *host, struct spi_message *m) { struct spi_device *spi; @@ -320,15 +320,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, mpc512x_psc_spi_transfer_setup(spi, NULL); - spi_finalize_current_message(master); + spi_finalize_current_message(host); return status; } -static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) +static int mpc512x_psc_spi_prep_xfer_hw(struct spi_controller *host) { - struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); + struct mpc512x_psc_spi *mps = spi_controller_get_devdata(host); - dev_dbg(&master->dev, "%s()\n", __func__); + dev_dbg(&host->dev, "%s()\n", __func__); /* Zero MR2 */ in_8(psc_addr(mps, mr2)); @@ -340,12 +340,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) return 0; } -static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master) +static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_controller *host) { - struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); + struct mpc512x_psc_spi *mps = spi_controller_get_devdata(host); struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; - dev_dbg(&master->dev, "%s()\n", __func__); + dev_dbg(&host->dev, "%s()\n", __func__); /* disable transmitter/receiver and fifo interrupt */ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); @@ -380,7 +380,7 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi) kfree(spi->controller_state); } -static int mpc512x_psc_spi_port_config(struct spi_master *master, +static int mpc512x_psc_spi_port_config(struct spi_controller *host, struct mpc512x_psc_spi *mps) { struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; @@ -408,7 +408,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, sicr = 0x01000000 | /* SIM = 0001 -- 8 bit */ 0x00800000 | /* GenClk = 1 -- internal clk */ 0x00008000 | /* SPI = 1 */ - 0x00004000 | /* MSTR = 1 -- SPI master */ + 0x00004000 | /* MSTR = 1 -- SPI host */ 0x00000800; /* UseEOF = 1 -- SS low until EOF */ out_be32(psc_addr(mps, sicr), sicr); @@ -459,28 +459,28 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mpc512x_psc_spi *mps; - struct spi_master *master; + struct spi_controller *host; int ret; void *tempp; struct clk *clk; - master = devm_spi_alloc_master(dev, sizeof(*mps)); - if (master == NULL) + host = devm_spi_alloc_host(dev, sizeof(*mps)); + if (host == NULL) return -ENOMEM; - dev_set_drvdata(dev, master); - mps = spi_master_get_devdata(master); + dev_set_drvdata(dev, host); + mps = spi_controller_get_devdata(host); mps->type = (int)device_get_match_data(dev); - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; - master->setup = mpc512x_psc_spi_setup; - master->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw; - master->transfer_one_message = mpc512x_psc_spi_msg_xfer; - master->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw; - master->use_gpio_descriptors = true; - master->cleanup = mpc512x_psc_spi_cleanup; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + host->setup = mpc512x_psc_spi_setup; + host->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw; + host->transfer_one_message = mpc512x_psc_spi_msg_xfer; + host->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw; + host->use_gpio_descriptors = true; + host->cleanup = mpc512x_psc_spi_cleanup; - device_set_node(&master->dev, dev_fwnode(dev)); + device_set_node(&host->dev, dev_fwnode(dev)); tempp = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(tempp)) @@ -509,11 +509,11 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *pdev) if (IS_ERR(clk)) return PTR_ERR(clk); - ret = mpc512x_psc_spi_port_config(master, mps); + ret = mpc512x_psc_spi_port_config(host, mps); if (ret < 0) return ret; - return devm_spi_register_master(dev, master); + return devm_spi_register_controller(dev, host); } static const struct of_device_id mpc512x_psc_spi_of_match[] = { diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 795c08594a4d..28f06122edac 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -60,7 +60,7 @@ static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi, static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi) { struct mpc52xx_psc_spi_cs *cs = spi->controller_state; - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc52xx_psc_spi *mps = spi_controller_get_devdata(spi->controller); struct mpc52xx_psc __iomem *psc = mps->psc; u32 sicr; u16 ccr; @@ -104,7 +104,7 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi) static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, struct spi_transfer *t) { - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc52xx_psc_spi *mps = spi_controller_get_devdata(spi->controller); struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo; unsigned rb = 0; /* number of bytes receieved */ @@ -175,8 +175,8 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, return 0; } -int mpc52xx_psc_spi_transfer_one_message(struct spi_controller *ctlr, - struct spi_message *m) +static int mpc52xx_psc_spi_transfer_one_message(struct spi_controller *ctlr, + struct spi_message *m) { struct spi_device *spi; struct spi_transfer *t = NULL; @@ -263,7 +263,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps) out_8(&fifo->rfcntl, 0); out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL); - /* Configure 8bit codec mode as a SPI master and use EOF flags */ + /* Configure 8bit codec mode as a SPI host and use EOF flags */ /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */ out_be32(&psc->sicr, 0x0180C800); out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */ @@ -295,31 +295,31 @@ static int mpc52xx_psc_spi_of_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mpc52xx_psc_spi *mps; - struct spi_master *master; + struct spi_controller *host; u32 bus_num; int ret; - master = devm_spi_alloc_master(dev, sizeof(*mps)); - if (master == NULL) + host = devm_spi_alloc_host(dev, sizeof(*mps)); + if (host == NULL) return -ENOMEM; - dev_set_drvdata(dev, master); - mps = spi_master_get_devdata(master); + dev_set_drvdata(dev, host); + mps = spi_controller_get_devdata(host); /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; ret = device_property_read_u32(dev, "cell-index", &bus_num); if (ret || bus_num > 5) return dev_err_probe(dev, ret ? : -EINVAL, "Invalid cell-index property\n"); - master->bus_num = bus_num + 1; + host->bus_num = bus_num + 1; - master->num_chipselect = 255; - master->setup = mpc52xx_psc_spi_setup; - master->transfer_one_message = mpc52xx_psc_spi_transfer_one_message; - master->cleanup = mpc52xx_psc_spi_cleanup; + host->num_chipselect = 255; + host->setup = mpc52xx_psc_spi_setup; + host->transfer_one_message = mpc52xx_psc_spi_transfer_one_message; + host->cleanup = mpc52xx_psc_spi_cleanup; - device_set_node(&master->dev, dev_fwnode(dev)); + device_set_node(&host->dev, dev_fwnode(dev)); mps->psc = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(mps->psc)) @@ -337,13 +337,13 @@ static int mpc52xx_psc_spi_of_probe(struct platform_device *pdev) if (ret) return ret; - ret = mpc52xx_psc_spi_port_config(master->bus_num, mps); + ret = mpc52xx_psc_spi_port_config(host->bus_num, mps); if (ret < 0) return dev_err_probe(dev, ret, "can't configure PSC! Is it capable of SPI?\n"); init_completion(&mps->done); - return devm_spi_register_master(dev, master); + return devm_spi_register_controller(dev, host); } static const struct of_device_id mpc52xx_psc_spi_of_match[] = { diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c index ab7df5f64342..4a6c984b6bff 100644 --- a/drivers/spi/spi-mpc52xx.c +++ b/drivers/spi/spi-mpc52xx.c @@ -62,7 +62,7 @@ MODULE_LICENSE("GPL"); /* Driver internal data */ struct mpc52xx_spi { - struct spi_master *master; + struct spi_controller *host; void __iomem *regs; int irq0; /* MODF irq */ int irq1; /* SPIF irq */ @@ -152,7 +152,7 @@ mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data) u8 ctrl1; if (status && irq) - dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n", + dev_err(&ms->host->dev, "spurious irq, status=0x%.2x\n", status); /* Check if there is another transfer waiting. */ @@ -235,7 +235,7 @@ static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms, return FSM_CONTINUE; } else if (status & SPI_STATUS_MODF) { ms->modf_count++; - dev_err(&ms->master->dev, "mode fault\n"); + dev_err(&ms->host->dev, "mode fault\n"); mpc52xx_spi_chipsel(ms, 0); ms->message->status = -EIO; if (ms->message->complete) @@ -280,7 +280,7 @@ static int mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data) { if (status && irq) - dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n", + dev_err(&ms->host->dev, "spurious irq, status=0x%.2x\n", status); if (((int)mftb()) - ms->timestamp < 0) @@ -361,12 +361,12 @@ static void mpc52xx_spi_wq(struct work_struct *work) } /* - * spi_master ops + * spi_controller ops */ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) { - struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master); + struct mpc52xx_spi *ms = spi_controller_get_devdata(spi->controller); unsigned long flags; m->actual_length = 0; @@ -385,7 +385,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) */ static int mpc52xx_spi_probe(struct platform_device *op) { - struct spi_master *master; + struct spi_controller *host; struct mpc52xx_spi *ms; struct gpio_desc *gpio_cs; void __iomem *regs; @@ -406,7 +406,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */ /* Clear the status register and re-read it to check for a MODF - * failure. This driver cannot currently handle multiple masters + * failure. This driver cannot currently handle multiple hosts * on the SPI bus. This fault will also occur if the SPI signals * are not connected to any pins (port_config setting) */ in_8(regs + SPI_STATUS); @@ -419,22 +419,22 @@ static int mpc52xx_spi_probe(struct platform_device *op) goto err_init; } - dev_dbg(&op->dev, "allocating spi_master struct\n"); - master = spi_alloc_master(&op->dev, sizeof(*ms)); - if (!master) { + dev_dbg(&op->dev, "allocating spi_controller struct\n"); + host = spi_alloc_host(&op->dev, sizeof(*ms)); + if (!host) { rc = -ENOMEM; goto err_alloc; } - master->transfer = mpc52xx_spi_transfer; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->dev.of_node = op->dev.of_node; + host->transfer = mpc52xx_spi_transfer; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->dev.of_node = op->dev.of_node; - platform_set_drvdata(op, master); + platform_set_drvdata(op, host); - ms = spi_master_get_devdata(master); - ms->master = master; + ms = spi_controller_get_devdata(host); + ms->host = host; ms->regs = regs; ms->irq0 = irq_of_parse_and_map(op->dev.of_node, 0); ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1); @@ -442,7 +442,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) ms->ipb_freq = mpc5xxx_get_bus_frequency(&op->dev); ms->gpio_cs_count = gpiod_count(&op->dev, NULL); if (ms->gpio_cs_count > 0) { - master->num_chipselect = ms->gpio_cs_count; + host->num_chipselect = ms->gpio_cs_count; ms->gpio_cs = kmalloc_array(ms->gpio_cs_count, sizeof(*ms->gpio_cs), GFP_KERNEL); @@ -489,24 +489,24 @@ static int mpc52xx_spi_probe(struct platform_device *op) if (!ms->irq0) dev_info(&op->dev, "using polled mode\n"); - dev_dbg(&op->dev, "registering spi_master struct\n"); - rc = spi_register_master(master); + dev_dbg(&op->dev, "registering spi_controller struct\n"); + rc = spi_register_controller(host); if (rc) goto err_register; - dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n"); + dev_info(&ms->host->dev, "registered MPC5200 SPI bus\n"); return rc; err_register: - dev_err(&ms->master->dev, "initialization failed\n"); + dev_err(&ms->host->dev, "initialization failed\n"); err_gpio: while (i-- > 0) gpiod_put(ms->gpio_cs[i]); kfree(ms->gpio_cs); err_alloc_gpio: - spi_master_put(master); + spi_controller_put(host); err_alloc: err_init: iounmap(regs); @@ -515,8 +515,8 @@ static int mpc52xx_spi_probe(struct platform_device *op) static void mpc52xx_spi_remove(struct platform_device *op) { - struct spi_master *master = spi_master_get(platform_get_drvdata(op)); - struct mpc52xx_spi *ms = spi_master_get_devdata(master); + struct spi_controller *host = spi_controller_get(platform_get_drvdata(op)); + struct mpc52xx_spi *ms = spi_controller_get_devdata(host); int i; free_irq(ms->irq0, ms); @@ -526,9 +526,9 @@ static void mpc52xx_spi_remove(struct platform_device *op) gpiod_put(ms->gpio_cs[i]); kfree(ms->gpio_cs); - spi_unregister_master(master); + spi_unregister_controller(host); iounmap(ms->regs); - spi_master_put(master); + spi_controller_put(host); } static const struct of_device_id mpc52xx_spi_match[] = { diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 0757985947dd..8d5d170d49cc 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -135,7 +135,7 @@ struct mtk_spi_compatible { * @pad_num: Number of pad_sel entries * @pad_sel: Groups of pins to select * @parent_clk: Parent of sel_clk - * @sel_clk: SPI master mux clock + * @sel_clk: SPI host mux clock * @spi_clk: Peripheral clock * @spi_hclk: AHB bus clock * @cur_transfer: Currently processed SPI transfer @@ -282,7 +282,7 @@ static void mtk_spi_reset(struct mtk_spi *mdata) static int mtk_spi_set_hw_cs_timing(struct spi_device *spi) { - struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller); struct spi_delay *cs_setup = &spi->cs_setup; struct spi_delay *cs_hold = &spi->cs_hold; struct spi_delay *cs_inactive = &spi->cs_inactive; @@ -347,13 +347,13 @@ static int mtk_spi_set_hw_cs_timing(struct spi_device *spi) return 0; } -static int mtk_spi_hw_init(struct spi_master *master, +static int mtk_spi_hw_init(struct spi_controller *host, struct spi_device *spi) { u16 cpha, cpol; u32 reg_val; struct mtk_chip_config *chip_config = spi->controller_data; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); cpha = spi->mode & SPI_CPHA ? 1 : 0; cpol = spi->mode & SPI_CPOL ? 1 : 0; @@ -452,16 +452,16 @@ static int mtk_spi_hw_init(struct spi_master *master, return 0; } -static int mtk_spi_prepare_message(struct spi_master *master, +static int mtk_spi_prepare_message(struct spi_controller *host, struct spi_message *msg) { - return mtk_spi_hw_init(master, msg->spi); + return mtk_spi_hw_init(host, msg->spi); } static void mtk_spi_set_cs(struct spi_device *spi, bool enable) { u32 reg_val; - struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller); if (spi->mode & SPI_CS_HIGH) enable = !enable; @@ -478,11 +478,11 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) } } -static void mtk_spi_prepare_transfer(struct spi_master *master, +static void mtk_spi_prepare_transfer(struct spi_controller *host, u32 speed_hz) { u32 div, sck_time, reg_val; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); if (speed_hz < mdata->spi_clk_hz / 2) div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz); @@ -511,10 +511,10 @@ static void mtk_spi_prepare_transfer(struct spi_master *master, } } -static void mtk_spi_setup_packet(struct spi_master *master) +static void mtk_spi_setup_packet(struct spi_controller *host) { u32 packet_size, packet_loop, reg_val; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); if (mdata->dev_comp->ipm_design) packet_size = min_t(u32, @@ -538,10 +538,10 @@ static void mtk_spi_setup_packet(struct spi_master *master) writel(reg_val, mdata->base + SPI_CFG1_REG); } -static void mtk_spi_enable_transfer(struct spi_master *master) +static void mtk_spi_enable_transfer(struct spi_controller *host) { u32 cmd; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); cmd = readl(mdata->base + SPI_CMD_REG); if (mdata->state == MTK_SPI_IDLE) @@ -566,10 +566,10 @@ static int mtk_spi_get_mult_delta(struct mtk_spi *mdata, u32 xfer_len) return mult_delta; } -static void mtk_spi_update_mdata_len(struct spi_master *master) +static void mtk_spi_update_mdata_len(struct spi_controller *host) { int mult_delta; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); if (mdata->tx_sgl_len && mdata->rx_sgl_len) { if (mdata->tx_sgl_len > mdata->rx_sgl_len) { @@ -594,10 +594,10 @@ static void mtk_spi_update_mdata_len(struct spi_master *master) } } -static void mtk_spi_setup_dma_addr(struct spi_master *master, +static void mtk_spi_setup_dma_addr(struct spi_controller *host, struct spi_transfer *xfer) { - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); if (mdata->tx_sgl) { writel((u32)(xfer->tx_dma & MTK_SPI_32BITS_MASK), @@ -620,19 +620,19 @@ static void mtk_spi_setup_dma_addr(struct spi_master *master, } } -static int mtk_spi_fifo_transfer(struct spi_master *master, +static int mtk_spi_fifo_transfer(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { int cnt, remainder; u32 reg_val; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); mdata->cur_transfer = xfer; mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len); mdata->num_xfered = 0; - mtk_spi_prepare_transfer(master, xfer->speed_hz); - mtk_spi_setup_packet(master); + mtk_spi_prepare_transfer(host, xfer->speed_hz); + mtk_spi_setup_packet(host); if (xfer->tx_buf) { cnt = xfer->len / 4; @@ -645,17 +645,17 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, } } - mtk_spi_enable_transfer(master); + mtk_spi_enable_transfer(host); return 1; } -static int mtk_spi_dma_transfer(struct spi_master *master, +static int mtk_spi_dma_transfer(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { int cmd; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); mdata->tx_sgl = NULL; mdata->rx_sgl = NULL; @@ -664,7 +664,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master, mdata->cur_transfer = xfer; mdata->num_xfered = 0; - mtk_spi_prepare_transfer(master, xfer->speed_hz); + mtk_spi_prepare_transfer(host, xfer->speed_hz); cmd = readl(mdata->base + SPI_CMD_REG); if (xfer->tx_buf) @@ -687,19 +687,19 @@ static int mtk_spi_dma_transfer(struct spi_master *master, mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl); } - mtk_spi_update_mdata_len(master); - mtk_spi_setup_packet(master); - mtk_spi_setup_dma_addr(master, xfer); - mtk_spi_enable_transfer(master); + mtk_spi_update_mdata_len(host); + mtk_spi_setup_packet(host); + mtk_spi_setup_dma_addr(host, xfer); + mtk_spi_enable_transfer(host); return 1; } -static int mtk_spi_transfer_one(struct spi_master *master, +static int mtk_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller); u32 reg_val = 0; /* prepare xfer direction and duplex mode */ @@ -712,13 +712,13 @@ static int mtk_spi_transfer_one(struct spi_master *master, writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); } - if (master->can_dma(master, spi, xfer)) - return mtk_spi_dma_transfer(master, spi, xfer); + if (host->can_dma(host, spi, xfer)) + return mtk_spi_dma_transfer(host, spi, xfer); else - return mtk_spi_fifo_transfer(master, spi, xfer); + return mtk_spi_fifo_transfer(host, spi, xfer); } -static bool mtk_spi_can_dma(struct spi_master *master, +static bool mtk_spi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { @@ -730,7 +730,7 @@ static bool mtk_spi_can_dma(struct spi_master *master, static int mtk_spi_setup(struct spi_device *spi) { - struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + struct mtk_spi *mdata = spi_controller_get_devdata(spi->controller); if (!spi->controller_data) spi->controller_data = (void *)&mtk_default_chip_info; @@ -745,8 +745,8 @@ static int mtk_spi_setup(struct spi_device *spi) static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) { u32 cmd, reg_val, cnt, remainder, len; - struct spi_master *master = dev_id; - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_controller *host = dev_id; + struct mtk_spi *mdata = spi_controller_get_devdata(host); struct spi_transfer *trans = mdata->cur_transfer; reg_val = readl(mdata->base + SPI_STATUS0_REG); @@ -761,7 +761,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - if (!master->can_dma(master, NULL, trans)) { + if (!host->can_dma(host, NULL, trans)) { if (trans->rx_buf) { cnt = mdata->xfer_len / 4; ioread32_rep(mdata->base + SPI_RX_DATA_REG, @@ -779,13 +779,13 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) mdata->num_xfered += mdata->xfer_len; if (mdata->num_xfered == trans->len) { - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return IRQ_HANDLED; } len = trans->len - mdata->num_xfered; mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len); - mtk_spi_setup_packet(master); + mtk_spi_setup_packet(host); cnt = mdata->xfer_len / 4; iowrite32_rep(mdata->base + SPI_TX_DATA_REG, @@ -800,7 +800,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) writel(reg_val, mdata->base + SPI_TX_DATA_REG); } - mtk_spi_enable_transfer(master); + mtk_spi_enable_transfer(host); return IRQ_HANDLED; } @@ -832,14 +832,14 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) cmd &= ~SPI_CMD_RX_DMA; writel(cmd, mdata->base + SPI_CMD_REG); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return IRQ_HANDLED; } - mtk_spi_update_mdata_len(master); - mtk_spi_setup_packet(master); - mtk_spi_setup_dma_addr(master, trans); - mtk_spi_enable_transfer(master); + mtk_spi_update_mdata_len(host); + mtk_spi_setup_packet(host); + mtk_spi_setup_dma_addr(host, trans); + mtk_spi_enable_transfer(host); return IRQ_HANDLED; } @@ -884,10 +884,10 @@ static bool mtk_spi_mem_supports_op(struct spi_mem *mem, return true; } -static void mtk_spi_mem_setup_dma_xfer(struct spi_master *master, +static void mtk_spi_mem_setup_dma_xfer(struct spi_controller *host, const struct spi_mem_op *op) { - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_spi *mdata = spi_controller_get_devdata(host); writel((u32)(mdata->tx_dma & MTK_SPI_32BITS_MASK), mdata->base + SPI_TX_SRC_REG); @@ -911,7 +911,7 @@ static void mtk_spi_mem_setup_dma_xfer(struct spi_master *master, static int mtk_spi_transfer_wait(struct spi_mem *mem, const struct spi_mem_op *op) { - struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master); + struct mtk_spi *mdata = spi_controller_get_devdata(mem->spi->controller); /* * For each byte we wait for 8 cycles of the SPI clock. * Since speed is defined in Hz and we want milliseconds, @@ -941,7 +941,7 @@ static int mtk_spi_transfer_wait(struct spi_mem *mem, static int mtk_spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master); + struct mtk_spi *mdata = spi_controller_get_devdata(mem->spi->controller); u32 reg_val, nio, tx_size; char *tx_tmp_buf, *rx_tmp_buf; int ret = 0; @@ -950,8 +950,8 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, reinit_completion(&mdata->spimem_done); mtk_spi_reset(mdata); - mtk_spi_hw_init(mem->spi->master, mem->spi); - mtk_spi_prepare_transfer(mem->spi->master, mem->spi->max_speed_hz); + mtk_spi_hw_init(mem->spi->controller, mem->spi); + mtk_spi_prepare_transfer(mem->spi->controller, mem->spi->max_speed_hz); reg_val = readl(mdata->base + SPI_CFG3_IPM_REG); /* opcode byte len */ @@ -971,7 +971,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, } else { reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG; mdata->xfer_len = op->data.nbytes; - mtk_spi_setup_packet(mem->spi->master); + mtk_spi_setup_packet(mem->spi->controller); } if (op->addr.nbytes || op->dummy.nbytes) { @@ -1069,9 +1069,9 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, reg_val |= SPI_CMD_RX_DMA; writel(reg_val, mdata->base + SPI_CMD_REG); - mtk_spi_mem_setup_dma_xfer(mem->spi->master, op); + mtk_spi_mem_setup_dma_xfer(mem->spi->controller, op); - mtk_spi_enable_transfer(mem->spi->master); + mtk_spi_enable_transfer(mem->spi->controller); /* Wait for the interrupt. */ ret = mtk_spi_transfer_wait(mem, op); @@ -1115,41 +1115,41 @@ static const struct spi_controller_mem_ops mtk_spi_mem_ops = { static int mtk_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *host; struct mtk_spi *mdata; int i, irq, ret, addr_bits; - master = devm_spi_alloc_master(dev, sizeof(*mdata)); - if (!master) - return dev_err_probe(dev, -ENOMEM, "failed to alloc spi master\n"); + host = devm_spi_alloc_host(dev, sizeof(*mdata)); + if (!host) + return dev_err_probe(dev, -ENOMEM, "failed to alloc spi host\n"); - master->auto_runtime_pm = true; - master->dev.of_node = dev->of_node; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + host->auto_runtime_pm = true; + host->dev.of_node = dev->of_node; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - master->set_cs = mtk_spi_set_cs; - master->prepare_message = mtk_spi_prepare_message; - master->transfer_one = mtk_spi_transfer_one; - master->can_dma = mtk_spi_can_dma; - master->setup = mtk_spi_setup; - master->set_cs_timing = mtk_spi_set_hw_cs_timing; - master->use_gpio_descriptors = true; + host->set_cs = mtk_spi_set_cs; + host->prepare_message = mtk_spi_prepare_message; + host->transfer_one = mtk_spi_transfer_one; + host->can_dma = mtk_spi_can_dma; + host->setup = mtk_spi_setup; + host->set_cs_timing = mtk_spi_set_hw_cs_timing; + host->use_gpio_descriptors = true; - mdata = spi_master_get_devdata(master); + mdata = spi_controller_get_devdata(host); mdata->dev_comp = device_get_match_data(dev); if (mdata->dev_comp->enhance_timing) - master->mode_bits |= SPI_CS_HIGH; + host->mode_bits |= SPI_CS_HIGH; if (mdata->dev_comp->must_tx) - master->flags = SPI_CONTROLLER_MUST_TX; + host->flags = SPI_CONTROLLER_MUST_TX; if (mdata->dev_comp->ipm_design) - master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL | - SPI_RX_QUAD | SPI_TX_QUAD; + host->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL | + SPI_RX_QUAD | SPI_TX_QUAD; if (mdata->dev_comp->ipm_design) { mdata->dev = dev; - master->mem_ops = &mtk_spi_mem_ops; + host->mem_ops = &mtk_spi_mem_ops; init_completion(&mdata->spimem_done); } @@ -1176,7 +1176,7 @@ static int mtk_spi_probe(struct platform_device *pdev) } } - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); mdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdata->base)) return PTR_ERR(mdata->base); @@ -1235,12 +1235,12 @@ static int mtk_spi_probe(struct platform_device *pdev) } if (mdata->dev_comp->need_pad_sel) { - if (mdata->pad_num != master->num_chipselect) + if (mdata->pad_num != host->num_chipselect) return dev_err_probe(dev, -EINVAL, "pad_num does not match num_chipselect(%d != %d)\n", - mdata->pad_num, master->num_chipselect); + mdata->pad_num, host->num_chipselect); - if (!master->cs_gpiods && master->num_chipselect > 1) + if (!host->cs_gpiods && host->num_chipselect > 1) return dev_err_probe(dev, -EINVAL, "cs_gpios not specified and num_chipselect > 1\n"); } @@ -1255,16 +1255,16 @@ static int mtk_spi_probe(struct platform_device *pdev) addr_bits, ret); ret = devm_request_irq(dev, irq, mtk_spi_interrupt, - IRQF_TRIGGER_NONE, dev_name(dev), master); + IRQF_TRIGGER_NONE, dev_name(dev), host); if (ret) return dev_err_probe(dev, ret, "failed to register irq\n"); pm_runtime_enable(dev); - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) { pm_runtime_disable(dev); - return dev_err_probe(dev, ret, "failed to register master\n"); + return dev_err_probe(dev, ret, "failed to register host\n"); } return 0; @@ -1272,8 +1272,8 @@ static int mtk_spi_probe(struct platform_device *pdev) static void mtk_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct mtk_spi *mdata = spi_controller_get_devdata(host); int ret; if (mdata->use_spimem && !completion_done(&mdata->spimem_done)) @@ -1304,10 +1304,10 @@ static void mtk_spi_remove(struct platform_device *pdev) static int mtk_spi_suspend(struct device *dev) { int ret; - struct spi_master *master = dev_get_drvdata(dev); - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_controller_get_devdata(host); - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -1322,8 +1322,8 @@ static int mtk_spi_suspend(struct device *dev) static int mtk_spi_resume(struct device *dev) { int ret; - struct spi_master *master = dev_get_drvdata(dev); - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_controller_get_devdata(host); if (!pm_runtime_suspended(dev)) { ret = clk_prepare_enable(mdata->spi_clk); @@ -1340,7 +1340,7 @@ static int mtk_spi_resume(struct device *dev) } } - ret = spi_master_resume(master); + ret = spi_controller_resume(host); if (ret < 0) { clk_disable_unprepare(mdata->spi_clk); clk_disable_unprepare(mdata->spi_hclk); @@ -1353,8 +1353,8 @@ static int mtk_spi_resume(struct device *dev) #ifdef CONFIG_PM static int mtk_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_controller_get_devdata(host); if (mdata->dev_comp->no_need_unprepare) { clk_disable(mdata->spi_clk); @@ -1369,8 +1369,8 @@ static int mtk_spi_runtime_suspend(struct device *dev) static int mtk_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_controller_get_devdata(host); int ret; if (mdata->dev_comp->no_need_unprepare) { diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c index 91600e5c22e4..4e9053d03d5a 100644 --- a/drivers/spi/spi-mt7621.c +++ b/drivers/spi/spi-mt7621.c @@ -53,7 +53,7 @@ #define MT7621_LSB_FIRST BIT(3) struct mt7621_spi { - struct spi_controller *master; + struct spi_controller *host; void __iomem *base; unsigned int sys_freq; unsigned int speed; @@ -62,7 +62,7 @@ struct mt7621_spi { static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi) { - return spi_controller_get_devdata(spi->master); + return spi_controller_get_devdata(spi->controller); } static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg) @@ -80,17 +80,17 @@ static void mt7621_spi_set_cs(struct spi_device *spi, int enable) struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); int cs = spi_get_chipselect(spi, 0); u32 polar = 0; - u32 master; + u32 host; /* * Select SPI device 7, enable "more buffer mode" and disable * full-duplex (only half-duplex really works on this chip * reliably) */ - master = mt7621_spi_read(rs, MT7621_SPI_MASTER); - master |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE; - master &= ~MASTER_FULL_DUPLEX; - mt7621_spi_write(rs, MT7621_SPI_MASTER, master); + host = mt7621_spi_read(rs, MT7621_SPI_MASTER); + host |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE; + host &= ~MASTER_FULL_DUPLEX; + mt7621_spi_write(rs, MT7621_SPI_MASTER, host); rs->pending_write = 0; @@ -245,10 +245,10 @@ static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs, rs->pending_write = len; } -static int mt7621_spi_transfer_one_message(struct spi_controller *master, +static int mt7621_spi_transfer_one_message(struct spi_controller *host, struct spi_message *m) { - struct mt7621_spi *rs = spi_controller_get_devdata(master); + struct mt7621_spi *rs = spi_controller_get_devdata(host); struct spi_device *spi = m->spi; unsigned int speed = spi->max_speed_hz; struct spi_transfer *t = NULL; @@ -294,7 +294,7 @@ static int mt7621_spi_transfer_one_message(struct spi_controller *master, msg_done: m->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return 0; } @@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, mt7621_spi_match); static int mt7621_spi_probe(struct platform_device *pdev) { const struct of_device_id *match; - struct spi_controller *master; + struct spi_controller *host; struct mt7621_spi *rs; void __iomem *base; struct clk *clk; @@ -344,25 +344,25 @@ static int mt7621_spi_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(clk), "unable to get SYS clock\n"); - master = devm_spi_alloc_master(&pdev->dev, sizeof(*rs)); - if (!master) { - dev_info(&pdev->dev, "master allocation failed\n"); + host = devm_spi_alloc_host(&pdev->dev, sizeof(*rs)); + if (!host) { + dev_info(&pdev->dev, "host allocation failed\n"); return -ENOMEM; } - master->mode_bits = SPI_LSB_FIRST; - master->flags = SPI_CONTROLLER_HALF_DUPLEX; - master->setup = mt7621_spi_setup; - master->transfer_one_message = mt7621_spi_transfer_one_message; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->dev.of_node = pdev->dev.of_node; - master->num_chipselect = 2; + host->mode_bits = SPI_LSB_FIRST; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->setup = mt7621_spi_setup; + host->transfer_one_message = mt7621_spi_transfer_one_message; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->dev.of_node = pdev->dev.of_node; + host->num_chipselect = 2; - dev_set_drvdata(&pdev->dev, master); + dev_set_drvdata(&pdev->dev, host); - rs = spi_controller_get_devdata(master); + rs = spi_controller_get_devdata(host); rs->base = base; - rs->master = master; + rs->host = host; rs->sys_freq = clk_get_rate(clk); rs->pending_write = 0; dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); @@ -373,7 +373,7 @@ static int mt7621_spi_probe(struct platform_device *pdev) return ret; } - return devm_spi_register_controller(&pdev->dev, master); + return devm_spi_register_controller(&pdev->dev, host); } MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index cf4ee8b19e42..62b1c8995fa4 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -275,7 +275,7 @@ static void mtk_nor_adj_prg_size(struct spi_mem_op *op) static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { - struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->master); + struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->controller); if (!op->data.nbytes) return 0; @@ -598,7 +598,7 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op) static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->master); + struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->controller); int ret; if ((op->data.nbytes == 0) || @@ -639,7 +639,7 @@ static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static int mtk_nor_setup(struct spi_device *spi) { - struct mtk_nor *sp = spi_controller_get_devdata(spi->master); + struct mtk_nor *sp = spi_controller_get_devdata(spi->controller); if (spi->max_speed_hz && (spi->max_speed_hz < sp->spi_freq)) { dev_err(&spi->dev, "spi clock should be %u Hz.\n", @@ -651,10 +651,10 @@ static int mtk_nor_setup(struct spi_device *spi) return 0; } -static int mtk_nor_transfer_one_message(struct spi_controller *master, +static int mtk_nor_transfer_one_message(struct spi_controller *host, struct spi_message *m) { - struct mtk_nor *sp = spi_controller_get_devdata(master); + struct mtk_nor *sp = spi_controller_get_devdata(host); struct spi_transfer *t = NULL; unsigned long trx_len = 0; int stat = 0; @@ -696,7 +696,7 @@ static int mtk_nor_transfer_one_message(struct spi_controller *master, m->actual_length = trx_len; msg_done: m->status = stat; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return 0; } @@ -844,7 +844,7 @@ static int mtk_nor_probe(struct platform_device *pdev) return ret; } - ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*sp)); if (!ctlr) { dev_err(&pdev->dev, "failed to allocate spi controller\n"); return -ENOMEM; diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c index 4433a8a9299f..ddd98ddb7913 100644 --- a/drivers/spi/spi-mtk-snfi.c +++ b/drivers/spi/spi-mtk-snfi.c @@ -1255,7 +1255,7 @@ static bool mtk_snand_supports_op(struct spi_mem *mem, static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { - struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->master); + struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->controller); // page ops transfer size must be exactly ((sector_size + spare_size) * // nsectors). Limit the op size if the caller requests more than that. // exec_op will read more than needed and discard the leftover if the @@ -1282,7 +1282,7 @@ static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) static int mtk_snand_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->master); + struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->controller); dev_dbg(ms->dev, "OP %02x ADDR %08llX@%d:%u DATA %d:%u", op->cmd.opcode, op->addr.val, op->addr.buswidth, op->addr.nbytes, @@ -1332,42 +1332,6 @@ static const struct of_device_id mtk_snand_ids[] = { MODULE_DEVICE_TABLE(of, mtk_snand_ids); -static int mtk_snand_enable_clk(struct mtk_snand *ms) -{ - int ret; - - ret = clk_prepare_enable(ms->nfi_clk); - if (ret) { - dev_err(ms->dev, "unable to enable nfi clk\n"); - return ret; - } - ret = clk_prepare_enable(ms->pad_clk); - if (ret) { - dev_err(ms->dev, "unable to enable pad clk\n"); - goto err1; - } - ret = clk_prepare_enable(ms->nfi_hclk); - if (ret) { - dev_err(ms->dev, "unable to enable nfi hclk\n"); - goto err2; - } - - return 0; - -err2: - clk_disable_unprepare(ms->pad_clk); -err1: - clk_disable_unprepare(ms->nfi_clk); - return ret; -} - -static void mtk_snand_disable_clk(struct mtk_snand *ms) -{ - clk_disable_unprepare(ms->nfi_hclk); - clk_disable_unprepare(ms->pad_clk); - clk_disable_unprepare(ms->nfi_clk); -} - static int mtk_snand_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1382,7 +1346,7 @@ static int mtk_snand_probe(struct platform_device *pdev) if (!dev_id) return -EINVAL; - ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*ms)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*ms)); if (!ctlr) return -ENOMEM; platform_set_drvdata(pdev, ctlr); @@ -1406,49 +1370,45 @@ static int mtk_snand_probe(struct platform_device *pdev) ms->dev = &pdev->dev; - ms->nfi_clk = devm_clk_get(&pdev->dev, "nfi_clk"); + ms->nfi_clk = devm_clk_get_enabled(&pdev->dev, "nfi_clk"); if (IS_ERR(ms->nfi_clk)) { ret = PTR_ERR(ms->nfi_clk); dev_err(&pdev->dev, "unable to get nfi_clk, err = %d\n", ret); goto release_ecc; } - ms->pad_clk = devm_clk_get(&pdev->dev, "pad_clk"); + ms->pad_clk = devm_clk_get_enabled(&pdev->dev, "pad_clk"); if (IS_ERR(ms->pad_clk)) { ret = PTR_ERR(ms->pad_clk); dev_err(&pdev->dev, "unable to get pad_clk, err = %d\n", ret); goto release_ecc; } - ms->nfi_hclk = devm_clk_get_optional(&pdev->dev, "nfi_hclk"); + ms->nfi_hclk = devm_clk_get_optional_enabled(&pdev->dev, "nfi_hclk"); if (IS_ERR(ms->nfi_hclk)) { ret = PTR_ERR(ms->nfi_hclk); dev_err(&pdev->dev, "unable to get nfi_hclk, err = %d\n", ret); goto release_ecc; } - ret = mtk_snand_enable_clk(ms); - if (ret) - goto release_ecc; - init_completion(&ms->op_done); ms->irq = platform_get_irq(pdev, 0); if (ms->irq < 0) { ret = ms->irq; - goto disable_clk; + goto release_ecc; } ret = devm_request_irq(ms->dev, ms->irq, mtk_snand_irq, 0x0, "mtk-snand", ms); if (ret) { dev_err(ms->dev, "failed to request snfi irq\n"); - goto disable_clk; + goto release_ecc; } ret = dma_set_mask(ms->dev, DMA_BIT_MASK(32)); if (ret) { dev_err(ms->dev, "failed to set dma mask\n"); - goto disable_clk; + goto release_ecc; } // switch to SNFI mode @@ -1472,7 +1432,7 @@ static int mtk_snand_probe(struct platform_device *pdev) ret = mtk_snand_setup_pagefmt(ms, SZ_2K, SZ_64); if (ret) { dev_err(ms->dev, "failed to set initial page format\n"); - goto disable_clk; + goto release_ecc; } // setup ECC engine @@ -1484,7 +1444,7 @@ static int mtk_snand_probe(struct platform_device *pdev) ret = nand_ecc_register_on_host_hw_engine(&ms->ecc_eng); if (ret) { dev_err(&pdev->dev, "failed to register ecc engine.\n"); - goto disable_clk; + goto release_ecc; } ctlr->num_chipselect = 1; @@ -1496,12 +1456,10 @@ static int mtk_snand_probe(struct platform_device *pdev) ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_controller failed.\n"); - goto disable_clk; + goto release_ecc; } return 0; -disable_clk: - mtk_snand_disable_clk(ms); release_ecc: mtk_ecc_release(ms->ecc); return ret; @@ -1513,7 +1471,6 @@ static void mtk_snand_remove(struct platform_device *pdev) struct mtk_snand *ms = spi_controller_get_devdata(ctlr); spi_unregister_controller(ctlr); - mtk_snand_disable_clk(ms); mtk_ecc_release(ms->ecc); kfree(ms->buf); } diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c index fa8c1f740c70..bd988f53753e 100644 --- a/drivers/spi/spi-mux.c +++ b/drivers/spi/spi-mux.c @@ -129,7 +129,7 @@ static int spi_mux_probe(struct spi_device *spi) struct spi_mux_priv *priv; int ret; - ctlr = spi_alloc_master(&spi->dev, sizeof(*priv)); + ctlr = spi_alloc_host(&spi->dev, sizeof(*priv)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index 00617fd4b2c3..60c9f3048ac9 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -390,7 +390,7 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf, static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf) { - struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master); + struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller); int ret; u32 sts; @@ -434,7 +434,7 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, const void *buf) { - struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master); + struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller); u32 sts; int ret; @@ -493,7 +493,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem, static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc) { - struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master); + struct mxic_spi *mxic = spi_controller_get_devdata(desc->mem->spi->controller); if (!mxic->linear.map) return -EINVAL; @@ -510,7 +510,7 @@ static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc) static int mxic_spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master); + struct mxic_spi *mxic = spi_controller_get_devdata(mem->spi->controller); int i, ret; u8 addr[8], cmd[2]; @@ -577,7 +577,7 @@ static const struct spi_controller_mem_caps mxic_spi_mem_caps = { static void mxic_spi_set_cs(struct spi_device *spi, bool lvl) { - struct mxic_spi *mxic = spi_master_get_devdata(spi->master); + struct mxic_spi *mxic = spi_controller_get_devdata(spi->controller); if (!lvl) { writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_EN, @@ -592,11 +592,11 @@ static void mxic_spi_set_cs(struct spi_device *spi, bool lvl) } } -static int mxic_spi_transfer_one(struct spi_master *master, +static int mxic_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { - struct mxic_spi *mxic = spi_master_get_devdata(master); + struct mxic_spi *mxic = spi_controller_get_devdata(host); unsigned int busw = OP_BUSW_1; int ret; @@ -632,7 +632,7 @@ static int mxic_spi_transfer_one(struct spi_master *master, if (ret) return ret; - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return 0; } @@ -713,8 +713,8 @@ static int mxic_spi_mem_ecc_probe(struct platform_device *pdev, static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mxic_spi *mxic = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mxic_spi *mxic = spi_controller_get_devdata(host); mxic_spi_clk_disable(mxic); clk_disable_unprepare(mxic->ps_clk); @@ -724,8 +724,8 @@ static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev) static int __maybe_unused mxic_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mxic_spi *mxic = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mxic_spi *mxic = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(mxic->ps_clk); @@ -744,21 +744,21 @@ static const struct dev_pm_ops mxic_spi_dev_pm_ops = { static int mxic_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct resource *res; struct mxic_spi *mxic; int ret; - master = devm_spi_alloc_master(&pdev->dev, sizeof(struct mxic_spi)); - if (!master) + host = devm_spi_alloc_host(&pdev->dev, sizeof(struct mxic_spi)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - mxic = spi_master_get_devdata(master); + mxic = spi_controller_get_devdata(host); mxic->dev = &pdev->dev; - master->dev.of_node = pdev->dev.of_node; + host->dev.of_node = pdev->dev.of_node; mxic->ps_clk = devm_clk_get(&pdev->dev, "ps_clk"); if (IS_ERR(mxic->ps_clk)) @@ -786,19 +786,19 @@ static int mxic_spi_probe(struct platform_device *pdev) } pm_runtime_enable(&pdev->dev); - master->auto_runtime_pm = true; + host->auto_runtime_pm = true; - master->num_chipselect = 1; - master->mem_ops = &mxic_spi_mem_ops; - master->mem_caps = &mxic_spi_mem_caps; + host->num_chipselect = 1; + host->mem_ops = &mxic_spi_mem_ops; + host->mem_caps = &mxic_spi_mem_caps; - master->set_cs = mxic_spi_set_cs; - master->transfer_one = mxic_spi_transfer_one; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->mode_bits = SPI_CPOL | SPI_CPHA | - SPI_RX_DUAL | SPI_TX_DUAL | - SPI_RX_QUAD | SPI_TX_QUAD | - SPI_RX_OCTAL | SPI_TX_OCTAL; + host->set_cs = mxic_spi_set_cs; + host->transfer_one = mxic_spi_transfer_one; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->mode_bits = SPI_CPOL | SPI_CPHA | + SPI_RX_DUAL | SPI_TX_DUAL | + SPI_RX_QUAD | SPI_TX_QUAD | + SPI_RX_OCTAL | SPI_TX_OCTAL; mxic_spi_hw_init(mxic); @@ -808,9 +808,9 @@ static int mxic_spi_probe(struct platform_device *pdev) return ret; } - ret = spi_register_master(master); + ret = spi_register_controller(host); if (ret) { - dev_err(&pdev->dev, "spi_register_master failed\n"); + dev_err(&pdev->dev, "spi_register_controller failed\n"); pm_runtime_disable(&pdev->dev); mxic_spi_mem_ecc_remove(mxic); } @@ -820,12 +820,12 @@ static int mxic_spi_probe(struct platform_device *pdev) static void mxic_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct mxic_spi *mxic = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct mxic_spi *mxic = spi_controller_get_devdata(host); pm_runtime_disable(&pdev->dev); mxic_spi_mem_ecc_remove(mxic); - spi_unregister_master(master); + spi_unregister_controller(host); } static const struct of_device_id mxic_spi_of_ids[] = { diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index cd0e7ae07162..1bf080339b5a 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ // -// Freescale MXS SPI master driver +// Freescale MXS SPI host driver // // Copyright 2012 DENX Software Engineering, GmbH. // Copyright 2012 Freescale Semiconductor, Inc. @@ -63,7 +63,7 @@ struct mxs_spi { static int mxs_spi_setup_transfer(struct spi_device *dev, const struct spi_transfer *t) { - struct mxs_spi *spi = spi_master_get_devdata(dev->master); + struct mxs_spi *spi = spi_controller_get_devdata(dev->controller); struct mxs_ssp *ssp = &spi->ssp; const unsigned int hz = min(dev->max_speed_hz, t->speed_hz); @@ -357,10 +357,10 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, return -ETIMEDOUT; } -static int mxs_spi_transfer_one(struct spi_master *master, +static int mxs_spi_transfer_one(struct spi_controller *host, struct spi_message *m) { - struct mxs_spi *spi = spi_master_get_devdata(master); + struct mxs_spi *spi = spi_controller_get_devdata(host); struct mxs_ssp *ssp = &spi->ssp; struct spi_transfer *t; unsigned int flag; @@ -432,15 +432,15 @@ static int mxs_spi_transfer_one(struct spi_master *master, } m->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return status; } static int mxs_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mxs_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mxs_spi *spi = spi_controller_get_devdata(host); struct mxs_ssp *ssp = &spi->ssp; int ret; @@ -460,8 +460,8 @@ static int mxs_spi_runtime_suspend(struct device *dev) static int mxs_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mxs_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mxs_spi *spi = spi_controller_get_devdata(host); struct mxs_ssp *ssp = &spi->ssp; int ret; @@ -478,10 +478,10 @@ static int mxs_spi_runtime_resume(struct device *dev) static int __maybe_unused mxs_spi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -493,7 +493,7 @@ static int __maybe_unused mxs_spi_suspend(struct device *dev) static int __maybe_unused mxs_spi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; if (!pm_runtime_suspended(dev)) @@ -503,7 +503,7 @@ static int __maybe_unused mxs_spi_resume(struct device *dev) if (ret) return ret; - ret = spi_master_resume(master); + ret = spi_controller_resume(host); if (ret < 0 && !pm_runtime_suspended(dev)) mxs_spi_runtime_suspend(dev); @@ -528,7 +528,7 @@ static int mxs_spi_probe(struct platform_device *pdev) const struct of_device_id *of_id = of_match_device(mxs_spi_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; - struct spi_master *master; + struct spi_controller *host; struct mxs_spi *spi; struct mxs_ssp *ssp; struct clk *clk; @@ -561,21 +561,21 @@ static int mxs_spi_probe(struct platform_device *pdev) if (ret) clk_freq = clk_freq_default; - master = spi_alloc_master(&pdev->dev, sizeof(*spi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*spi)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - master->transfer_one_message = mxs_spi_transfer_one; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->mode_bits = SPI_CPOL | SPI_CPHA; - master->num_chipselect = 3; - master->dev.of_node = np; - master->flags = SPI_CONTROLLER_HALF_DUPLEX; - master->auto_runtime_pm = true; + host->transfer_one_message = mxs_spi_transfer_one; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->mode_bits = SPI_CPOL | SPI_CPHA; + host->num_chipselect = 3; + host->dev.of_node = np; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->auto_runtime_pm = true; - spi = spi_master_get_devdata(master); + spi = spi_controller_get_devdata(host); ssp = &spi->ssp; ssp->dev = &pdev->dev; ssp->clk = clk; @@ -587,13 +587,13 @@ static int mxs_spi_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0, dev_name(&pdev->dev), ssp); if (ret) - goto out_master_free; + goto out_host_free; ssp->dmach = dma_request_chan(&pdev->dev, "rx-tx"); if (IS_ERR(ssp->dmach)) { dev_err(ssp->dev, "Failed to request DMA\n"); ret = PTR_ERR(ssp->dmach); - goto out_master_free; + goto out_host_free; } pm_runtime_enable(ssp->dev); @@ -617,9 +617,9 @@ static int mxs_spi_probe(struct platform_device *pdev) if (ret) goto out_pm_runtime_put; - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { - dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret); + dev_err(&pdev->dev, "Cannot register SPI host, %d\n", ret); goto out_pm_runtime_put; } @@ -633,19 +633,19 @@ out_pm_runtime_disable: pm_runtime_disable(ssp->dev); out_dma_release: dma_release_channel(ssp->dmach); -out_master_free: - spi_master_put(master); +out_host_free: + spi_controller_put(host); return ret; } static void mxs_spi_remove(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct mxs_spi *spi; struct mxs_ssp *ssp; - master = platform_get_drvdata(pdev); - spi = spi_master_get_devdata(master); + host = platform_get_drvdata(pdev); + spi = spi_controller_get_devdata(host); ssp = &spi->ssp; pm_runtime_disable(&pdev->dev); @@ -668,6 +668,6 @@ static struct platform_driver mxs_spi_driver = { module_platform_driver(mxs_spi_driver); MODULE_AUTHOR("Marek Vasut "); -MODULE_DESCRIPTION("MXS SPI master driver"); +MODULE_DESCRIPTION("MXS SPI host driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:mxs-spi"); diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index e42248519688..03db9f016a11 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -700,7 +700,7 @@ static int npcm_fiu_probe(struct platform_device *pdev) struct spi_controller *ctrl; struct npcm_fiu_spi *fiu; void __iomem *regbase; - int id, ret; + int id; ctrl = devm_spi_alloc_host(dev, sizeof(*fiu)); if (!ctrl) @@ -738,7 +738,7 @@ static int npcm_fiu_probe(struct platform_device *pdev) fiu->res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); - fiu->clk = devm_clk_get(dev, NULL); + fiu->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(fiu->clk)) return PTR_ERR(fiu->clk); @@ -746,7 +746,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) "nuvoton,spix-mode"); platform_set_drvdata(pdev, fiu); - clk_prepare_enable(fiu->clk); ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; @@ -756,18 +755,11 @@ static int npcm_fiu_probe(struct platform_device *pdev) ctrl->num_chipselect = fiu->info->max_cs; ctrl->dev.of_node = dev->of_node; - ret = devm_spi_register_controller(dev, ctrl); - if (ret) - clk_disable_unprepare(fiu->clk); - - return ret; + return devm_spi_register_controller(dev, ctrl); } static void npcm_fiu_remove(struct platform_device *pdev) { - struct npcm_fiu_spi *fiu = platform_get_drvdata(pdev); - - clk_disable_unprepare(fiu->clk); } MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids); diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index 64585c2a25c5..a7feb20b06ee 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -20,7 +20,7 @@ struct npcm_pspi { struct completion xfer_done; struct reset_control *reset; - struct spi_master *master; + struct spi_controller *host; unsigned int tx_bytes; unsigned int rx_bytes; void __iomem *base; @@ -101,7 +101,7 @@ static inline void npcm_pspi_disable(struct npcm_pspi *priv) static void npcm_pspi_set_mode(struct spi_device *spi) { - struct npcm_pspi *priv = spi_master_get_devdata(spi->master); + struct npcm_pspi *priv = spi_controller_get_devdata(spi->controller); u16 regtemp; u16 mode_val; @@ -159,7 +159,7 @@ static void npcm_pspi_set_baudrate(struct npcm_pspi *priv, unsigned int speed) static void npcm_pspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { - struct npcm_pspi *priv = spi_master_get_devdata(spi->master); + struct npcm_pspi *priv = spi_controller_get_devdata(spi->controller); priv->tx_buf = t->tx_buf; priv->rx_buf = t->rx_buf; @@ -245,11 +245,11 @@ static void npcm_pspi_recv(struct npcm_pspi *priv) } } -static int npcm_pspi_transfer_one(struct spi_master *master, +static int npcm_pspi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { - struct npcm_pspi *priv = spi_master_get_devdata(master); + struct npcm_pspi *priv = spi_controller_get_devdata(host); int status; npcm_pspi_setup_transfer(spi, t); @@ -266,18 +266,18 @@ static int npcm_pspi_transfer_one(struct spi_master *master, return 0; } -static int npcm_pspi_prepare_transfer_hardware(struct spi_master *master) +static int npcm_pspi_prepare_transfer_hardware(struct spi_controller *host) { - struct npcm_pspi *priv = spi_master_get_devdata(master); + struct npcm_pspi *priv = spi_controller_get_devdata(host); npcm_pspi_irq_enable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW); return 0; } -static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master) +static int npcm_pspi_unprepare_transfer_hardware(struct spi_controller *host) { - struct npcm_pspi *priv = spi_master_get_devdata(master); + struct npcm_pspi *priv = spi_controller_get_devdata(host); npcm_pspi_irq_disable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW); @@ -340,37 +340,37 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id) static int npcm_pspi_probe(struct platform_device *pdev) { struct npcm_pspi *priv; - struct spi_master *master; + struct spi_controller *host; unsigned long clk_hz; int irq; int ret; - master = spi_alloc_master(&pdev->dev, sizeof(*priv)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*priv)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - priv = spi_master_get_devdata(master); - priv->master = master; + priv = spi_controller_get_devdata(host); + priv->host = host; priv->is_save_param = false; priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); - goto out_master_put; + goto out_host_put; } priv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(priv->clk); - goto out_master_put; + goto out_host_put; } ret = clk_prepare_enable(priv->clk); if (ret) - goto out_master_put; + goto out_host_put; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -398,42 +398,42 @@ static int npcm_pspi_probe(struct platform_device *pdev) clk_hz = clk_get_rate(priv->clk); - master->max_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MIN_CLK_DIVIDER); - master->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER); - master->mode_bits = SPI_CPHA | SPI_CPOL; - master->dev.of_node = pdev->dev.of_node; - master->bus_num = -1; - master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); - master->transfer_one = npcm_pspi_transfer_one; - master->prepare_transfer_hardware = + host->max_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MIN_CLK_DIVIDER); + host->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER); + host->mode_bits = SPI_CPHA | SPI_CPOL; + host->dev.of_node = pdev->dev.of_node; + host->bus_num = -1; + host->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); + host->transfer_one = npcm_pspi_transfer_one; + host->prepare_transfer_hardware = npcm_pspi_prepare_transfer_hardware; - master->unprepare_transfer_hardware = + host->unprepare_transfer_hardware = npcm_pspi_unprepare_transfer_hardware; - master->use_gpio_descriptors = true; + host->use_gpio_descriptors = true; /* set to default clock rate */ npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) goto out_disable_clk; - pr_info("NPCM Peripheral SPI %d probed\n", master->bus_num); + pr_info("NPCM Peripheral SPI %d probed\n", host->bus_num); return 0; out_disable_clk: clk_disable_unprepare(priv->clk); -out_master_put: - spi_master_put(master); +out_host_put: + spi_controller_put(host); return ret; } static void npcm_pspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct npcm_pspi *priv = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct npcm_pspi *priv = spi_controller_get_devdata(host); npcm_pspi_reset_hw(priv); clk_disable_unprepare(priv->clk); diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index c964f41dcc42..e13f678f2395 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -451,7 +451,7 @@ static int nxp_fspi_check_buswidth(struct nxp_fspi *f, u8 width) static bool nxp_fspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller); int ret; ret = nxp_fspi_check_buswidth(f, op->cmd.buswidth); @@ -520,7 +520,7 @@ static int fspi_readl_poll_tout(struct nxp_fspi *f, void __iomem *base, } /* - * If the slave device content being changed by Write/Erase, need to + * If the target device content being changed by Write/Erase, need to * invalidate the AHB buffer. This can be achieved by doing the reset * of controller after setting MCR0[SWRESET] bit. */ @@ -661,7 +661,7 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f) /* * In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0 - * register and start base address of the slave device. + * register and start base address of the target device. * * (Higher address) * -------- <-- FLSHB2CR0 @@ -680,15 +680,15 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f) * * * Start base address defines the starting address range for given CS and - * FSPI_FLSHXXCR0 defines the size of the slave device connected at given CS. + * FSPI_FLSHXXCR0 defines the size of the target device connected at given CS. * * But, different targets are having different combinations of number of CS, * some targets only have single CS or two CS covering controller's full * memory mapped space area. * Thus, implementation is being done as independent of the size and number - * of the connected slave device. + * of the connected target device. * Assign controller memory mapped space size as the size to the connected - * slave device. + * target device. * Mark FLSHxxCR0 as zero initially and then assign value only to the selected * chip-select Flash configuration register. * @@ -704,8 +704,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi) uint64_t size_kb; /* - * Return, if previously selected slave device is same as current - * requested slave device. + * Return, if previously selected target device is same as current + * requested target device. */ if (f->selected == spi_get_chipselect(spi, 0)) return; @@ -722,7 +722,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi) fspi_writel(f, size_kb, f->iobase + FSPI_FLSHA1CR0 + 4 * spi_get_chipselect(spi, 0)); - dev_dbg(f->dev, "Slave device [CS:%x] selected\n", spi_get_chipselect(spi, 0)); + dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0)); nxp_fspi_clk_disable_unprep(f); @@ -759,7 +759,7 @@ static int nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op) f->memmap_len = len > NXP_FSPI_MIN_IOMAP ? len : NXP_FSPI_MIN_IOMAP; - f->ahb_addr = ioremap_wc(f->memmap_phy + f->memmap_start, + f->ahb_addr = ioremap(f->memmap_phy + f->memmap_start, f->memmap_len); if (!f->ahb_addr) { @@ -912,7 +912,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller); int err = 0; mutex_lock(&f->lock); @@ -952,7 +952,7 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { - struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller); if (op->data.dir == SPI_MEM_DATA_OUT) { if (op->data.nbytes > f->devtype_data->txfifo) @@ -1049,7 +1049,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0); /* - * Config the DLL register to default value, enable the slave clock delay + * Config the DLL register to default value, enable the target clock delay * line delay cell override mode, and use 1 fixed delay cell in DLL delay * chain, this is the suggested setting when clock rate < 100MHz. */ @@ -1062,7 +1062,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) base + FSPI_MCR0); /* - * Disable same device enable bit and configure all slave devices + * Disable same device enable bit and configure all target devices * independently. */ reg = fspi_readl(f, f->iobase + FSPI_MCR2); @@ -1107,7 +1107,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) static const char *nxp_fspi_get_name(struct spi_mem *mem) { - struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->master); + struct nxp_fspi *f = spi_controller_get_devdata(mem->spi->controller); struct device *dev = &mem->spi->dev; const char *name; @@ -1144,7 +1144,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) int ret; u32 reg; - ctlr = spi_alloc_master(&pdev->dev, sizeof(*f)); + ctlr = spi_alloc_host(&pdev->dev, sizeof(*f)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index 3af499838e84..cf7c111088a6 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * OpenCores tiny SPI master driver + * OpenCores tiny SPI host driver * * https://opencores.org/project,tiny_spi * @@ -53,7 +53,7 @@ struct tiny_spi { static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev) { - return spi_master_get_devdata(sdev->master); + return spi_controller_get_devdata(sdev->controller); } static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz) @@ -212,24 +212,24 @@ static int tiny_spi_probe(struct platform_device *pdev) { struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev); struct tiny_spi *hw; - struct spi_master *master; + struct spi_controller *host; int err = -ENODEV; - master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(struct tiny_spi)); + if (!host) return err; - /* setup the master state. */ - master->bus_num = pdev->id; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->setup = tiny_spi_setup; - master->use_gpio_descriptors = true; + /* setup the host state. */ + host->bus_num = pdev->id; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->setup = tiny_spi_setup; + host->use_gpio_descriptors = true; - hw = spi_master_get_devdata(master); + hw = spi_controller_get_devdata(host); platform_set_drvdata(pdev, hw); /* setup the state for the bitbang driver */ - hw->bitbang.master = master; + hw->bitbang.master = host; hw->bitbang.setup_transfer = tiny_spi_setup_transfer; hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; @@ -267,17 +267,17 @@ static int tiny_spi_probe(struct platform_device *pdev) return 0; exit: - spi_master_put(master); + spi_controller_put(host); return err; } static void tiny_spi_remove(struct platform_device *pdev) { struct tiny_spi *hw = platform_get_drvdata(pdev); - struct spi_master *master = hw->bitbang.master; + struct spi_controller *host = hw->bitbang.master; spi_bitbang_stop(&hw->bitbang); - spi_master_put(master); + spi_controller_put(host); } #ifdef CONFIG_OF diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index f89aa9e52c23..2dd1c1bcf4bf 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -315,7 +315,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) int div2; int status; - uwire = spi_master_get_devdata(spi->master); + uwire = spi_controller_get_devdata(spi->controller); /* mode 0..3, clock inverted separately; * standard nCS signaling; @@ -448,25 +448,25 @@ static void uwire_off(struct uwire_spi *uwire) { uwire_write_reg(UWIRE_SR3, 0); clk_disable_unprepare(uwire->ck); - spi_master_put(uwire->bitbang.master); + spi_controller_put(uwire->bitbang.master); } static int uwire_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct uwire_spi *uwire; int status; - master = spi_alloc_master(&pdev->dev, sizeof(*uwire)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*uwire)); + if (!host) return -ENODEV; - uwire = spi_master_get_devdata(master); + uwire = spi_controller_get_devdata(host); uwire_base = devm_ioremap(&pdev->dev, UWIRE_BASE_PHYS, UWIRE_IO_SIZE); if (!uwire_base) { dev_dbg(&pdev->dev, "can't ioremap UWIRE\n"); - spi_master_put(master); + spi_controller_put(host); return -ENOMEM; } @@ -476,7 +476,7 @@ static int uwire_probe(struct platform_device *pdev) if (IS_ERR(uwire->ck)) { status = PTR_ERR(uwire->ck); dev_dbg(&pdev->dev, "no functional clock?\n"); - spi_master_put(master); + spi_controller_put(host); return status; } clk_prepare_enable(uwire->ck); @@ -484,16 +484,16 @@ static int uwire_probe(struct platform_device *pdev) uwire_write_reg(UWIRE_SR3, 1); /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); - master->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); + host->flags = SPI_CONTROLLER_HALF_DUPLEX; - master->bus_num = 2; /* "official" */ - master->num_chipselect = 4; - master->setup = uwire_setup; - master->cleanup = uwire_cleanup; + host->bus_num = 2; /* "official" */ + host->num_chipselect = 4; + host->setup = uwire_setup; + host->cleanup = uwire_cleanup; - uwire->bitbang.master = master; + uwire->bitbang.master = host; uwire->bitbang.chipselect = uwire_chipselect; uwire->bitbang.setup_transfer = uwire_setup_transfer; uwire->bitbang.txrx_bufs = uwire_txrx; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index e5cd82eb9e54..a0c9fea908f5 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -53,6 +53,8 @@ /* per-register bitmasks: */ #define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17) +#define OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY BIT(0) +#define OMAP2_MCSPI_IRQSTATUS_RX0_FULL BIT(2) #define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) #define OMAP2_MCSPI_MODULCTRL_MS BIT(2) @@ -117,7 +119,7 @@ struct omap2_mcspi_regs { struct omap2_mcspi { struct completion txdone; - struct spi_master *master; + struct spi_controller *ctlr; /* Virtual base address of the controller */ void __iomem *base; unsigned long phys; @@ -125,10 +127,12 @@ struct omap2_mcspi { struct omap2_mcspi_dma *dma_channels; struct device *dev; struct omap2_mcspi_regs ctx; + struct clk *ref_clk; int fifo_depth; - bool slave_aborted; + bool target_aborted; unsigned int pin_dir:1; size_t max_xfer_len; + u32 ref_clk_hz; }; struct omap2_mcspi_cs { @@ -141,17 +145,17 @@ struct omap2_mcspi_cs { u32 chconf0, chctrl0; }; -static inline void mcspi_write_reg(struct spi_master *master, +static inline void mcspi_write_reg(struct spi_controller *ctlr, int idx, u32 val) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); writel_relaxed(val, mcspi->base + idx); } -static inline u32 mcspi_read_reg(struct spi_master *master, int idx) +static inline u32 mcspi_read_reg(struct spi_controller *ctlr, int idx) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); return readl_relaxed(mcspi->base + idx); } @@ -235,7 +239,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller); u32 l; /* The controller handles the inverted chip selects @@ -266,39 +270,39 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) } } -static void omap2_mcspi_set_mode(struct spi_master *master) +static void omap2_mcspi_set_mode(struct spi_controller *ctlr) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); struct omap2_mcspi_regs *ctx = &mcspi->ctx; u32 l; /* - * Choose master or slave mode + * Choose host or target mode */ - l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); + l = mcspi_read_reg(ctlr, OMAP2_MCSPI_MODULCTRL); l &= ~(OMAP2_MCSPI_MODULCTRL_STEST); - if (spi_controller_is_slave(master)) { + if (spi_controller_is_target(ctlr)) { l |= (OMAP2_MCSPI_MODULCTRL_MS); } else { l &= ~(OMAP2_MCSPI_MODULCTRL_MS); l |= OMAP2_MCSPI_MODULCTRL_SINGLE; } - mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); + mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, l); ctx->modulctrl = l; } static void omap2_mcspi_set_fifo(const struct spi_device *spi, - struct spi_transfer *t, int enable) + struct spi_transfer *t, int enable, int dma_enabled) { - struct spi_master *master = spi->master; + struct spi_controller *ctlr = spi->controller; struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi *mcspi; unsigned int wcnt; int max_fifo_depth, bytes_per_word; u32 chconf, xferlevel; - mcspi = spi_master_get_devdata(master); + mcspi = spi_controller_get_devdata(ctlr); chconf = mcspi_cached_chconf0(spi); if (enable) { @@ -310,23 +314,31 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi, max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2; else max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH; - - wcnt = t->len / bytes_per_word; + if (dma_enabled) + wcnt = t->len / bytes_per_word; + else + wcnt = 0; if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT) goto disable_fifo; xferlevel = wcnt << 16; if (t->rx_buf != NULL) { chconf |= OMAP2_MCSPI_CHCONF_FFER; - xferlevel |= (bytes_per_word - 1) << 8; + if (dma_enabled) + xferlevel |= (bytes_per_word - 1) << 8; + else + xferlevel |= (max_fifo_depth - 1) << 8; } if (t->tx_buf != NULL) { chconf |= OMAP2_MCSPI_CHCONF_FFET; - xferlevel |= bytes_per_word - 1; + if (dma_enabled) + xferlevel |= bytes_per_word - 1; + else + xferlevel |= (max_fifo_depth - 1); } - mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel); + mcspi_write_reg(ctlr, OMAP2_MCSPI_XFERLEVEL, xferlevel); mcspi_write_chconf0(spi, chconf); mcspi->fifo_depth = max_fifo_depth; @@ -364,9 +376,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) static int mcspi_wait_for_completion(struct omap2_mcspi *mcspi, struct completion *x) { - if (spi_controller_is_slave(mcspi->master)) { + if (spi_controller_is_target(mcspi->ctlr)) { if (wait_for_completion_interruptible(x) || - mcspi->slave_aborted) + mcspi->target_aborted) return -EINTR; } else { wait_for_completion(x); @@ -378,7 +390,7 @@ static int mcspi_wait_for_completion(struct omap2_mcspi *mcspi, static void omap2_mcspi_rx_callback(void *data) { struct spi_device *spi = data; - struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; /* We must disable the DMA RX request */ @@ -390,7 +402,7 @@ static void omap2_mcspi_rx_callback(void *data) static void omap2_mcspi_tx_callback(void *data) { struct spi_device *spi = data; - struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; /* We must disable the DMA TX request */ @@ -407,7 +419,7 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, struct omap2_mcspi_dma *mcspi_dma; struct dma_async_tx_descriptor *tx; - mcspi = spi_master_get_devdata(spi->master); + mcspi = spi_controller_get_devdata(spi->controller); mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); @@ -445,13 +457,13 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, void __iomem *chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; struct dma_async_tx_descriptor *tx; - mcspi = spi_master_get_devdata(spi->master); + mcspi = spi_controller_get_devdata(spi->controller); mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; count = xfer->len; /* * In the "End-of-Transfer Procedure" section for DMA RX in OMAP35x TRM - * it mentions reducing DMA transfer length by one element in master + * it mentions reducing DMA transfer length by one element in host * normal mode. */ if (mcspi->fifo_depth == 0) @@ -514,7 +526,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, omap2_mcspi_set_dma_req(spi, 1, 1); ret = mcspi_wait_for_completion(mcspi, &mcspi_dma->dma_rx_completion); - if (ret || mcspi->slave_aborted) { + if (ret || mcspi->target_aborted) { dmaengine_terminate_sync(mcspi_dma->dma_rx); omap2_mcspi_set_dma_req(spi, 1, 0); return 0; @@ -590,7 +602,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) void __iomem *irqstat_reg; int wait_res; - mcspi = spi_master_get_devdata(spi->master); + mcspi = spi_controller_get_devdata(spi->controller); mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; if (cs->word_len <= 8) { @@ -617,14 +629,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) rx = xfer->rx_buf; tx = xfer->tx_buf; - mcspi->slave_aborted = false; + mcspi->target_aborted = false; reinit_completion(&mcspi_dma->dma_tx_completion); reinit_completion(&mcspi_dma->dma_rx_completion); reinit_completion(&mcspi->txdone); if (tx) { - /* Enable EOW IRQ to know end of tx in slave mode */ - if (spi_controller_is_slave(spi->master)) - mcspi_write_reg(spi->master, + /* Enable EOW IRQ to know end of tx in target mode */ + if (spi_controller_is_target(spi->controller)) + mcspi_write_reg(spi->controller, OMAP2_MCSPI_IRQENABLE, OMAP2_MCSPI_IRQSTATUS_EOW); omap2_mcspi_tx_dma(spi, xfer, cfg); @@ -637,15 +649,15 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) int ret; ret = mcspi_wait_for_completion(mcspi, &mcspi_dma->dma_tx_completion); - if (ret || mcspi->slave_aborted) { + if (ret || mcspi->target_aborted) { dmaengine_terminate_sync(mcspi_dma->dma_tx); omap2_mcspi_set_dma_req(spi, 0, 0); return 0; } - if (spi_controller_is_slave(mcspi->master)) { + if (spi_controller_is_target(mcspi->ctlr)) { ret = mcspi_wait_for_completion(mcspi, &mcspi->txdone); - if (ret || mcspi->slave_aborted) + if (ret || mcspi->target_aborted) return 0; } @@ -656,7 +668,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) OMAP2_MCSPI_IRQSTATUS_EOW) < 0) dev_err(&spi->dev, "EOW timed out\n"); - mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS, + mcspi_write_reg(mcspi->ctlr, OMAP2_MCSPI_IRQSTATUS, OMAP2_MCSPI_IRQSTATUS_EOW); } @@ -880,12 +892,119 @@ out: return count - c; } -static u32 omap2_mcspi_calc_divisor(u32 speed_hz) +static unsigned +omap2_mcspi_txrx_piofifo(struct spi_device *spi, struct spi_transfer *xfer) +{ + struct omap2_mcspi_cs *cs = spi->controller_state; + struct omap2_mcspi *mcspi; + unsigned int count, c; + unsigned int iter, cwc; + int last_request; + void __iomem *base = cs->base; + void __iomem *tx_reg; + void __iomem *rx_reg; + void __iomem *chstat_reg; + void __iomem *irqstat_reg; + int word_len, bytes_per_word; + u8 *rx; + const u8 *tx; + + mcspi = spi_controller_get_devdata(spi->controller); + count = xfer->len; + c = count; + word_len = cs->word_len; + bytes_per_word = mcspi_bytes_per_word(word_len); + + /* + * We store the pre-calculated register addresses on stack to speed + * up the transfer loop. + */ + tx_reg = base + OMAP2_MCSPI_TX0; + rx_reg = base + OMAP2_MCSPI_RX0; + chstat_reg = base + OMAP2_MCSPI_CHSTAT0; + irqstat_reg = base + OMAP2_MCSPI_IRQSTATUS; + + if (c < (word_len >> 3)) + return 0; + + rx = xfer->rx_buf; + tx = xfer->tx_buf; + + do { + /* calculate number of words in current iteration */ + cwc = min((unsigned int)mcspi->fifo_depth / bytes_per_word, + c / bytes_per_word); + last_request = cwc != (mcspi->fifo_depth / bytes_per_word); + if (tx) { + if (mcspi_wait_for_reg_bit(irqstat_reg, + OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY) < 0) { + dev_err(&spi->dev, "TX Empty timed out\n"); + goto out; + } + writel_relaxed(OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY, irqstat_reg); + + for (iter = 0; iter < cwc; iter++, tx += bytes_per_word) { + if (bytes_per_word == 1) + writel_relaxed(*tx, tx_reg); + else if (bytes_per_word == 2) + writel_relaxed(*((u16 *)tx), tx_reg); + else if (bytes_per_word == 4) + writel_relaxed(*((u32 *)tx), tx_reg); + } + } + + if (rx) { + if (!last_request && + mcspi_wait_for_reg_bit(irqstat_reg, + OMAP2_MCSPI_IRQSTATUS_RX0_FULL) < 0) { + dev_err(&spi->dev, "RX_FULL timed out\n"); + goto out; + } + writel_relaxed(OMAP2_MCSPI_IRQSTATUS_RX0_FULL, irqstat_reg); + + for (iter = 0; iter < cwc; iter++, rx += bytes_per_word) { + if (last_request && + mcspi_wait_for_reg_bit(chstat_reg, + OMAP2_MCSPI_CHSTAT_RXS) < 0) { + dev_err(&spi->dev, "RXS timed out\n"); + goto out; + } + if (bytes_per_word == 1) + *rx = readl_relaxed(rx_reg); + else if (bytes_per_word == 2) + *((u16 *)rx) = readl_relaxed(rx_reg); + else if (bytes_per_word == 4) + *((u32 *)rx) = readl_relaxed(rx_reg); + } + } + + if (last_request) { + if (mcspi_wait_for_reg_bit(chstat_reg, + OMAP2_MCSPI_CHSTAT_EOT) < 0) { + dev_err(&spi->dev, "EOT timed out\n"); + goto out; + } + if (mcspi_wait_for_reg_bit(chstat_reg, + OMAP2_MCSPI_CHSTAT_TXFFE) < 0) { + dev_err(&spi->dev, "TXFFE timed out\n"); + goto out; + } + omap2_mcspi_set_enable(spi, 0); + } + c -= cwc * bytes_per_word; + } while (c >= bytes_per_word); + +out: + omap2_mcspi_set_enable(spi, 1); + return count - c; +} + +static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz) { u32 div; for (div = 0; div < 15; div++) - if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div)) + if (speed_hz >= (ref_clk_hz >> div)) return div; return 15; @@ -897,11 +1016,11 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, { struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi *mcspi; - u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0; + u32 ref_clk_hz, l = 0, clkd = 0, div, extclk = 0, clkg = 0; u8 word_len = spi->bits_per_word; u32 speed_hz = spi->max_speed_hz; - mcspi = spi_master_get_devdata(spi->master); + mcspi = spi_controller_get_devdata(spi->controller); if (t != NULL && t->bits_per_word) word_len = t->bits_per_word; @@ -911,14 +1030,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, if (t && t->speed_hz) speed_hz = t->speed_hz; - speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); - if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) { - clkd = omap2_mcspi_calc_divisor(speed_hz); - speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd; + ref_clk_hz = mcspi->ref_clk_hz; + speed_hz = min_t(u32, speed_hz, ref_clk_hz); + if (speed_hz < (ref_clk_hz / OMAP2_MCSPI_MAX_DIVIDER)) { + clkd = omap2_mcspi_calc_divisor(speed_hz, ref_clk_hz); + speed_hz = ref_clk_hz >> clkd; clkg = 0; } else { - div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz; - speed_hz = OMAP2_MCSPI_MAX_FREQ / div; + div = (ref_clk_hz + speed_hz - 1) / speed_hz; + speed_hz = ref_clk_hz / div; clkd = (div - 1) & 0xf; extclk = (div - 1) >> 4; clkg = OMAP2_MCSPI_CHCONF_CLKG; @@ -926,7 +1046,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, l = mcspi_cached_chconf0(spi); - /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS + /* standard 4-wire host mode: SCK, MOSI/out, MISO/in, nCS * REVISIT: this controller could support SPI_3WIRE mode. */ if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) { @@ -1017,13 +1137,13 @@ no_dma: return ret; } -static void omap2_mcspi_release_dma(struct spi_master *master) +static void omap2_mcspi_release_dma(struct spi_controller *ctlr) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); struct omap2_mcspi_dma *mcspi_dma; int i; - for (i = 0; i < master->num_chipselect; i++) { + for (i = 0; i < ctlr->num_chipselect; i++) { mcspi_dma = &mcspi->dma_channels[i]; if (mcspi_dma->dma_rx) { @@ -1054,7 +1174,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) { bool initial_setup = false; int ret; - struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller); struct omap2_mcspi_regs *ctx = &mcspi->ctx; struct omap2_mcspi_cs *cs = spi->controller_state; @@ -1096,24 +1216,24 @@ static irqreturn_t omap2_mcspi_irq_handler(int irq, void *data) struct omap2_mcspi *mcspi = data; u32 irqstat; - irqstat = mcspi_read_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS); + irqstat = mcspi_read_reg(mcspi->ctlr, OMAP2_MCSPI_IRQSTATUS); if (!irqstat) return IRQ_NONE; - /* Disable IRQ and wakeup slave xfer task */ - mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQENABLE, 0); + /* Disable IRQ and wakeup target xfer task */ + mcspi_write_reg(mcspi->ctlr, OMAP2_MCSPI_IRQENABLE, 0); if (irqstat & OMAP2_MCSPI_IRQSTATUS_EOW) complete(&mcspi->txdone); return IRQ_HANDLED; } -static int omap2_mcspi_slave_abort(struct spi_master *master) +static int omap2_mcspi_target_abort(struct spi_controller *ctlr) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); struct omap2_mcspi_dma *mcspi_dma = mcspi->dma_channels; - mcspi->slave_aborted = true; + mcspi->target_aborted = true; complete(&mcspi_dma->dma_rx_completion); complete(&mcspi_dma->dma_tx_completion); complete(&mcspi->txdone); @@ -1121,7 +1241,7 @@ static int omap2_mcspi_slave_abort(struct spi_master *master) return 0; } -static int omap2_mcspi_transfer_one(struct spi_master *master, +static int omap2_mcspi_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *t) { @@ -1129,7 +1249,7 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, /* We only enable one channel at a time -- the one whose message is * -- although this controller would gladly * arbitrate among multiple channels. This corresponds to "single - * channel" master mode. As a side effect, we need to manage the + * channel" host mode. As a side effect, we need to manage the * chipselect with the FORCE bit ... CS != channel enable. */ @@ -1141,13 +1261,13 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, int status = 0; u32 chconf; - mcspi = spi_master_get_devdata(master); + mcspi = spi_controller_get_devdata(ctlr); mcspi_dma = mcspi->dma_channels + spi_get_chipselect(spi, 0); cs = spi->controller_state; cd = spi->controller_data; /* - * The slave driver could have changed spi->mode in which case + * The target driver could have changed spi->mode in which case * it will be different from cs->mode (the current hardware setup). * If so, set par_override (even though its not a parity issue) so * omap2_mcspi_setup_transfer will be called to configure the hardware @@ -1175,7 +1295,7 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, if (cd && cd->cs_per_word) { chconf = mcspi->ctx.modulctrl; chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE; - mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf); + mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf); mcspi->ctx.modulctrl = mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL); } @@ -1201,9 +1321,11 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, unsigned count; if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && - master->cur_msg_mapped && - master->can_dma(master, spi, t)) - omap2_mcspi_set_fifo(spi, t, 1); + ctlr->cur_msg_mapped && + ctlr->can_dma(ctlr, spi, t)) + omap2_mcspi_set_fifo(spi, t, 1, 1); + else if (t->len > OMAP2_MCSPI_MAX_FIFODEPTH) + omap2_mcspi_set_fifo(spi, t, 1, 0); omap2_mcspi_set_enable(spi, 1); @@ -1213,9 +1335,11 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, + OMAP2_MCSPI_TX0); if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && - master->cur_msg_mapped && - master->can_dma(master, spi, t)) + ctlr->cur_msg_mapped && + ctlr->can_dma(ctlr, spi, t)) count = omap2_mcspi_txrx_dma(spi, t); + else if (mcspi->fifo_depth > 0) + count = omap2_mcspi_txrx_piofifo(spi, t); else count = omap2_mcspi_txrx_pio(spi, t); @@ -1228,7 +1352,7 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, omap2_mcspi_set_enable(spi, 0); if (mcspi->fifo_depth > 0) - omap2_mcspi_set_fifo(spi, t, 0); + omap2_mcspi_set_fifo(spi, t, 0, 0); out: /* Restore defaults if they were overriden */ @@ -1240,7 +1364,7 @@ out: if (cd && cd->cs_per_word) { chconf = mcspi->ctx.modulctrl; chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE; - mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf); + mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf); mcspi->ctx.modulctrl = mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL); } @@ -1251,15 +1375,15 @@ out: omap2_mcspi_set_cs(spi, !(spi->mode & SPI_CS_HIGH)); if (mcspi->fifo_depth > 0 && t) - omap2_mcspi_set_fifo(spi, t, 0); + omap2_mcspi_set_fifo(spi, t, 0, 0); return status; } -static int omap2_mcspi_prepare_message(struct spi_master *master, +static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, struct spi_message *msg) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); struct omap2_mcspi_regs *ctx = &mcspi->ctx; struct omap2_mcspi_cs *cs; @@ -1283,29 +1407,29 @@ static int omap2_mcspi_prepare_message(struct spi_master *master, return 0; } -static bool omap2_mcspi_can_dma(struct spi_master *master, +static bool omap2_mcspi_can_dma(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *xfer) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) return false; - if (spi_controller_is_slave(master)) + if (spi_controller_is_target(ctlr)) return true; - master->dma_rx = mcspi_dma->dma_rx; - master->dma_tx = mcspi_dma->dma_tx; + ctlr->dma_rx = mcspi_dma->dma_rx; + ctlr->dma_tx = mcspi_dma->dma_tx; return (xfer->len >= DMA_MIN_BYTES); } static size_t omap2_mcspi_max_xfer_size(struct spi_device *spi) { - struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(spi->controller); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)]; @@ -1317,7 +1441,7 @@ static size_t omap2_mcspi_max_xfer_size(struct spi_device *spi) static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi) { - struct spi_master *master = mcspi->master; + struct spi_controller *ctlr = mcspi->ctlr; struct omap2_mcspi_regs *ctx = &mcspi->ctx; int ret = 0; @@ -1325,11 +1449,11 @@ static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi) if (ret < 0) return ret; - mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, + mcspi_write_reg(ctlr, OMAP2_MCSPI_WAKEUPENABLE, OMAP2_MCSPI_WAKEUPENABLE_WKEN); ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; - omap2_mcspi_set_mode(master); + omap2_mcspi_set_mode(ctlr); pm_runtime_mark_last_busy(mcspi->dev); pm_runtime_put_autosuspend(mcspi->dev); return 0; @@ -1353,8 +1477,8 @@ static int omap_mcspi_runtime_suspend(struct device *dev) */ static int omap_mcspi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); struct omap2_mcspi_regs *ctx = &mcspi->ctx; struct omap2_mcspi_cs *cs; int error; @@ -1364,8 +1488,8 @@ static int omap_mcspi_runtime_resume(struct device *dev) dev_warn(dev, "%s: failed to set pins: %i\n", __func__, error); /* McSPI: context restore */ - mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); - mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); + mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); + mcspi_write_reg(ctlr, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); list_for_each_entry(cs, &ctx->cs, node) { /* @@ -1420,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, omap_mcspi_of_match); static int omap2_mcspi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *ctlr; const struct omap2_mcspi_platform_config *pdata; struct omap2_mcspi *mcspi; struct resource *r; @@ -1430,32 +1554,30 @@ static int omap2_mcspi_probe(struct platform_device *pdev) const struct of_device_id *match; if (of_property_read_bool(node, "spi-slave")) - master = spi_alloc_slave(&pdev->dev, sizeof(*mcspi)); + ctlr = spi_alloc_target(&pdev->dev, sizeof(*mcspi)); else - master = spi_alloc_master(&pdev->dev, sizeof(*mcspi)); - if (!master) + ctlr = spi_alloc_host(&pdev->dev, sizeof(*mcspi)); + if (!ctlr) return -ENOMEM; /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); - master->setup = omap2_mcspi_setup; - master->auto_runtime_pm = true; - master->prepare_message = omap2_mcspi_prepare_message; - master->can_dma = omap2_mcspi_can_dma; - master->transfer_one = omap2_mcspi_transfer_one; - master->set_cs = omap2_mcspi_set_cs; - master->cleanup = omap2_mcspi_cleanup; - master->slave_abort = omap2_mcspi_slave_abort; - master->dev.of_node = node; - master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ; - master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15; - master->use_gpio_descriptors = true; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + ctlr->setup = omap2_mcspi_setup; + ctlr->auto_runtime_pm = true; + ctlr->prepare_message = omap2_mcspi_prepare_message; + ctlr->can_dma = omap2_mcspi_can_dma; + ctlr->transfer_one = omap2_mcspi_transfer_one; + ctlr->set_cs = omap2_mcspi_set_cs; + ctlr->cleanup = omap2_mcspi_cleanup; + ctlr->target_abort = omap2_mcspi_target_abort; + ctlr->dev.of_node = node; + ctlr->use_gpio_descriptors = true; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, ctlr); - mcspi = spi_master_get_devdata(master); - mcspi->master = master; + mcspi = spi_controller_get_devdata(ctlr); + mcspi->ctlr = ctlr; match = of_match_device(omap_mcspi_of_match, &pdev->dev); if (match) { @@ -1463,24 +1585,24 @@ static int omap2_mcspi_probe(struct platform_device *pdev) pdata = match->data; of_property_read_u32(node, "ti,spi-num-cs", &num_cs); - master->num_chipselect = num_cs; + ctlr->num_chipselect = num_cs; if (of_property_read_bool(node, "ti,pindir-d0-out-d1-in")) mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN; } else { pdata = dev_get_platdata(&pdev->dev); - master->num_chipselect = pdata->num_cs; + ctlr->num_chipselect = pdata->num_cs; mcspi->pin_dir = pdata->pin_dir; } regs_offset = pdata->regs_offset; if (pdata->max_xfer_len) { mcspi->max_xfer_len = pdata->max_xfer_len; - master->max_transfer_size = omap2_mcspi_max_xfer_size; + ctlr->max_transfer_size = omap2_mcspi_max_xfer_size; } mcspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(mcspi->base)) { status = PTR_ERR(mcspi->base); - goto free_master; + goto free_ctlr; } mcspi->phys = r->start + regs_offset; mcspi->base += regs_offset; @@ -1489,36 +1611,44 @@ static int omap2_mcspi_probe(struct platform_device *pdev) INIT_LIST_HEAD(&mcspi->ctx.cs); - mcspi->dma_channels = devm_kcalloc(&pdev->dev, master->num_chipselect, + mcspi->dma_channels = devm_kcalloc(&pdev->dev, ctlr->num_chipselect, sizeof(struct omap2_mcspi_dma), GFP_KERNEL); if (mcspi->dma_channels == NULL) { status = -ENOMEM; - goto free_master; + goto free_ctlr; } - for (i = 0; i < master->num_chipselect; i++) { + for (i = 0; i < ctlr->num_chipselect; i++) { sprintf(mcspi->dma_channels[i].dma_rx_ch_name, "rx%d", i); sprintf(mcspi->dma_channels[i].dma_tx_ch_name, "tx%d", i); status = omap2_mcspi_request_dma(mcspi, &mcspi->dma_channels[i]); if (status == -EPROBE_DEFER) - goto free_master; + goto free_ctlr; } status = platform_get_irq(pdev, 0); if (status < 0) - goto free_master; + goto free_ctlr; init_completion(&mcspi->txdone); status = devm_request_irq(&pdev->dev, status, omap2_mcspi_irq_handler, 0, pdev->name, mcspi); if (status) { dev_err(&pdev->dev, "Cannot request IRQ"); - goto free_master; + goto free_ctlr; } + mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); + if (mcspi->ref_clk) + mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk); + else + mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ; + ctlr->max_speed_hz = mcspi->ref_clk_hz; + ctlr->min_speed_hz = mcspi->ref_clk_hz >> 15; + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_enable(&pdev->dev); @@ -1527,7 +1657,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) if (status < 0) goto disable_pm; - status = devm_spi_register_controller(&pdev->dev, master); + status = devm_spi_register_controller(&pdev->dev, ctlr); if (status < 0) goto disable_pm; @@ -1537,18 +1667,18 @@ disable_pm: pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); -free_master: - omap2_mcspi_release_dma(master); - spi_master_put(master); +free_ctlr: + omap2_mcspi_release_dma(ctlr); + spi_controller_put(ctlr); return status; } static void omap2_mcspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); - omap2_mcspi_release_dma(master); + omap2_mcspi_release_dma(ctlr); pm_runtime_dont_use_autosuspend(mcspi->dev); pm_runtime_put_sync(mcspi->dev); @@ -1560,8 +1690,8 @@ MODULE_ALIAS("platform:omap2_mcspi"); static int __maybe_unused omap2_mcspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); int error; error = pinctrl_pm_select_sleep_state(dev); @@ -1569,9 +1699,9 @@ static int __maybe_unused omap2_mcspi_suspend(struct device *dev) dev_warn(mcspi->dev, "%s: failed to set pins: %i\n", __func__, error); - error = spi_master_suspend(master); + error = spi_controller_suspend(ctlr); if (error) - dev_warn(mcspi->dev, "%s: master suspend failed: %i\n", + dev_warn(mcspi->dev, "%s: controller suspend failed: %i\n", __func__, error); return pm_runtime_force_suspend(dev); @@ -1579,13 +1709,13 @@ static int __maybe_unused omap2_mcspi_suspend(struct device *dev) static int __maybe_unused omap2_mcspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); int error; - error = spi_master_resume(master); + error = spi_controller_resume(ctlr); if (error) - dev_warn(mcspi->dev, "%s: master resume failed: %i\n", + dev_warn(mcspi->dev, "%s: controller resume failed: %i\n", __func__, error); return pm_runtime_force_resume(dev); diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 1f10f5c8e34d..eee9ff4bfa5b 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -688,21 +688,17 @@ static int orion_spi_probe(struct platform_device *pdev) devdata = devdata ? devdata : &orion_spi_dev_data; spi->devdata = devdata; - spi->clk = devm_clk_get(&pdev->dev, NULL); + spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { status = PTR_ERR(spi->clk); goto out; } - status = clk_prepare_enable(spi->clk); - if (status) - goto out; - /* The following clock is only used by some SoCs */ spi->axi_clk = devm_clk_get(&pdev->dev, "axi"); if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) { status = -EPROBE_DEFER; - goto out_rel_clk; + goto out; } if (!IS_ERR(spi->axi_clk)) clk_prepare_enable(spi->axi_clk); @@ -795,8 +791,6 @@ out_rel_pm: pm_runtime_disable(&pdev->dev); out_rel_axi_clk: clk_disable_unprepare(spi->axi_clk); -out_rel_clk: - clk_disable_unprepare(spi->clk); out: spi_controller_put(host); return status; @@ -810,7 +804,6 @@ static void orion_spi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(spi->axi_clk); - clk_disable_unprepare(spi->clk); spi_unregister_controller(host); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index 3638e974f5d4..5b2d3e4e21b7 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -77,7 +77,7 @@ struct pci1xxxx_spi { struct pci_dev *dev; u8 total_hw_instances; void __iomem *reg_base; - struct pci1xxxx_spi_internal *spi_int[]; + struct pci1xxxx_spi_internal *spi_int[] __counted_by(total_hw_instances); }; static const struct pci_device_id pci1xxxx_spi_pci_id_table[] = { diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index 883354d0ff52..3f1e5b27776b 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -593,33 +593,20 @@ static int pic32_sqi_probe(struct platform_device *pdev) } /* clocks */ - sqi->sys_clk = devm_clk_get(&pdev->dev, "reg_ck"); + sqi->sys_clk = devm_clk_get_enabled(&pdev->dev, "reg_ck"); if (IS_ERR(sqi->sys_clk)) { ret = PTR_ERR(sqi->sys_clk); dev_err(&pdev->dev, "no sys_clk ?\n"); goto err_free_host; } - sqi->base_clk = devm_clk_get(&pdev->dev, "spi_ck"); + sqi->base_clk = devm_clk_get_enabled(&pdev->dev, "spi_ck"); if (IS_ERR(sqi->base_clk)) { ret = PTR_ERR(sqi->base_clk); dev_err(&pdev->dev, "no base clk ?\n"); goto err_free_host; } - ret = clk_prepare_enable(sqi->sys_clk); - if (ret) { - dev_err(&pdev->dev, "sys clk enable failed\n"); - goto err_free_host; - } - - ret = clk_prepare_enable(sqi->base_clk); - if (ret) { - dev_err(&pdev->dev, "base clk enable failed\n"); - clk_disable_unprepare(sqi->sys_clk); - goto err_free_host; - } - init_completion(&sqi->xfer_done); /* initialize hardware */ @@ -629,7 +616,7 @@ static int pic32_sqi_probe(struct platform_device *pdev) ret = ring_desc_ring_alloc(sqi); if (ret) { dev_err(&pdev->dev, "ring alloc failed\n"); - goto err_disable_clk; + goto err_free_host; } /* install irq handlers */ @@ -669,10 +656,6 @@ static int pic32_sqi_probe(struct platform_device *pdev) err_free_ring: ring_desc_ring_free(sqi); -err_disable_clk: - clk_disable_unprepare(sqi->base_clk); - clk_disable_unprepare(sqi->sys_clk); - err_free_host: spi_controller_put(host); return ret; @@ -685,10 +668,6 @@ static void pic32_sqi_remove(struct platform_device *pdev) /* release resources */ free_irq(sqi->irq, sqi); ring_desc_ring_free(sqi); - - /* disable clk */ - clk_disable_unprepare(sqi->base_clk); - clk_disable_unprepare(sqi->sys_clk); } static const struct of_device_id pic32_sqi_of_ids[] = { diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 52b788dac10a..f55b38c577e4 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -730,17 +730,13 @@ static int pic32_spi_hw_probe(struct platform_device *pdev, return pic32s->tx_irq; /* get clock */ - pic32s->clk = devm_clk_get(&pdev->dev, "mck0"); + pic32s->clk = devm_clk_get_enabled(&pdev->dev, "mck0"); if (IS_ERR(pic32s->clk)) { dev_err(&pdev->dev, "clk not found\n"); ret = PTR_ERR(pic32s->clk); goto err_unmap_mem; } - ret = clk_prepare_enable(pic32s->clk); - if (ret) - goto err_unmap_mem; - pic32_spi_hw_init(pic32s); return 0; @@ -837,7 +833,6 @@ static int pic32_spi_probe(struct platform_device *pdev) err_bailout: pic32_spi_dma_unprep(pic32s); - clk_disable_unprepare(pic32s->clk); err_host: spi_controller_put(host); return ret; @@ -849,7 +844,6 @@ static void pic32_spi_remove(struct platform_device *pdev) pic32s = platform_get_drvdata(pdev); pic32_spi_disable(pic32s); - clk_disable_unprepare(pic32s->clk); pic32_spi_dma_unprep(pic32s); } diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index bb347b6bb6f3..d1b6110b38fc 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2168,19 +2168,13 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) dev_info(&adev->dev, "mapped registers from %pa to %p\n", &adev->res.start, pl022->virtbase); - pl022->clk = devm_clk_get(&adev->dev, NULL); + pl022->clk = devm_clk_get_enabled(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { status = PTR_ERR(pl022->clk); dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n"); goto err_no_clk; } - status = clk_prepare_enable(pl022->clk); - if (status) { - dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n"); - goto err_no_clk_en; - } - /* Initialize transfer pump */ tasklet_init(&pl022->pump_transfers, pump_transfers, (unsigned long)pl022); @@ -2240,8 +2234,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) if (platform_info->enable_dma) pl022_dma_remove(pl022); err_no_irq: - clk_disable_unprepare(pl022->clk); - err_no_clk_en: err_no_clk: err_no_ioremap: amba_release_regions(adev); @@ -2268,7 +2260,6 @@ pl022_remove(struct amba_device *adev) if (pl022->host_info->enable_dma) pl022_dma_remove(pl022); - clk_disable_unprepare(pl022->clk); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); } diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 4b6f6b25219b..2af63040ac6e 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -6,12 +6,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -121,11 +123,14 @@ #define SPI_DELAY_THRESHOLD 1 #define SPI_DELAY_RETRY 10 +#define SPI_BUS_WIDTH 8 + struct spi_qup { void __iomem *base; struct device *dev; struct clk *cclk; /* core clock */ struct clk *iclk; /* interface clock */ + struct icc_path *icc_path; /* interconnect to RAM */ int irq; spinlock_t lock; @@ -148,6 +153,8 @@ struct spi_qup { int mode; struct dma_slave_config rx_conf; struct dma_slave_config tx_conf; + + u32 bw_speed_hz; }; static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer); @@ -180,6 +187,23 @@ static inline bool spi_qup_is_valid_state(struct spi_qup *controller) return opstate & QUP_STATE_VALID; } +static int spi_qup_vote_bw(struct spi_qup *controller, u32 speed_hz) +{ + u32 needed_peak_bw; + int ret; + + if (controller->bw_speed_hz == speed_hz) + return 0; + + needed_peak_bw = Bps_to_icc(speed_hz * SPI_BUS_WIDTH); + ret = icc_set_bw(controller->icc_path, 0, needed_peak_bw); + if (ret) + return ret; + + controller->bw_speed_hz = speed_hz; + return 0; +} + static int spi_qup_set_state(struct spi_qup *controller, u32 state) { unsigned long loop; @@ -450,6 +474,12 @@ static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer, struct scatterlist *tx_sgl, *rx_sgl; int ret; + ret = spi_qup_vote_bw(qup, xfer->speed_hz); + if (ret) { + dev_err(qup->dev, "fail to vote for ICC bandwidth: %d\n", ret); + return -EIO; + } + if (xfer->rx_buf) rx_done = spi_qup_dma_done; else if (xfer->tx_buf) @@ -667,7 +697,7 @@ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer) return -EIO; } - ret = clk_set_rate(controller->cclk, xfer->speed_hz); + ret = dev_pm_opp_set_rate(controller->dev, xfer->speed_hz); if (ret) { dev_err(controller->dev, "fail to set frequency %d", xfer->speed_hz); @@ -993,6 +1023,7 @@ static void spi_qup_set_cs(struct spi_device *spi, bool val) static int spi_qup_probe(struct platform_device *pdev) { struct spi_controller *host; + struct icc_path *icc_path; struct clk *iclk, *cclk; struct spi_qup *controller; struct resource *res; @@ -1018,6 +1049,11 @@ static int spi_qup_probe(struct platform_device *pdev) if (IS_ERR(iclk)) return PTR_ERR(iclk); + icc_path = devm_of_icc_get(dev, NULL); + if (IS_ERR(icc_path)) + return dev_err_probe(dev, PTR_ERR(icc_path), + "failed to get interconnect path\n"); + /* This is optional parameter */ if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq)) max_freq = SPI_MAX_RATE; @@ -1027,6 +1063,15 @@ static int spi_qup_probe(struct platform_device *pdev) return -ENXIO; } + ret = devm_pm_opp_set_clkname(dev, "core"); + if (ret) + return ret; + + /* OPP table is optional */ + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table\n"); + host = spi_alloc_host(dev, sizeof(struct spi_qup)); if (!host) { dev_err(dev, "cannot allocate host\n"); @@ -1060,6 +1105,7 @@ static int spi_qup_probe(struct platform_device *pdev) controller->base = base; controller->iclk = iclk; controller->cclk = cclk; + controller->icc_path = icc_path; controller->irq = irq; ret = spi_qup_init_dma(host, res->start); @@ -1180,6 +1226,7 @@ static int spi_qup_pm_suspend_runtime(struct device *device) writel_relaxed(config, controller->base + QUP_CONFIG); clk_disable_unprepare(controller->cclk); + spi_qup_vote_bw(controller, 0); clk_disable_unprepare(controller->iclk); return 0; @@ -1231,6 +1278,7 @@ static int spi_qup_suspend(struct device *device) return ret; clk_disable_unprepare(controller->cclk); + spi_qup_vote_bw(controller, 0); clk_disable_unprepare(controller->iclk); return 0; } diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 5b010094dace..4b9669da2cf3 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -782,42 +782,30 @@ static int rockchip_spi_probe(struct platform_device *pdev) goto err_put_ctlr; } - rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk"); + rs->apb_pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk"); if (IS_ERR(rs->apb_pclk)) { dev_err(&pdev->dev, "Failed to get apb_pclk\n"); ret = PTR_ERR(rs->apb_pclk); goto err_put_ctlr; } - rs->spiclk = devm_clk_get(&pdev->dev, "spiclk"); + rs->spiclk = devm_clk_get_enabled(&pdev->dev, "spiclk"); if (IS_ERR(rs->spiclk)) { dev_err(&pdev->dev, "Failed to get spi_pclk\n"); ret = PTR_ERR(rs->spiclk); goto err_put_ctlr; } - ret = clk_prepare_enable(rs->apb_pclk); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to enable apb_pclk\n"); - goto err_put_ctlr; - } - - ret = clk_prepare_enable(rs->spiclk); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to enable spi_clk\n"); - goto err_disable_apbclk; - } - spi_enable_chip(rs, false); ret = platform_get_irq(pdev, 0); if (ret < 0) - goto err_disable_spiclk; + goto err_put_ctlr; ret = devm_request_threaded_irq(&pdev->dev, ret, rockchip_spi_isr, NULL, IRQF_ONESHOT, dev_name(&pdev->dev), ctlr); if (ret) - goto err_disable_spiclk; + goto err_put_ctlr; rs->dev = &pdev->dev; rs->freq = clk_get_rate(rs->spiclk); @@ -843,7 +831,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) if (!rs->fifo_len) { dev_err(&pdev->dev, "Failed to get fifo length\n"); ret = -EINVAL; - goto err_disable_spiclk; + goto err_put_ctlr; } pm_runtime_set_autosuspend_delay(&pdev->dev, ROCKCHIP_AUTOSUSPEND_TIMEOUT); @@ -937,10 +925,6 @@ err_free_dma_tx: dma_release_channel(ctlr->dma_tx); err_disable_pm_runtime: pm_runtime_disable(&pdev->dev); -err_disable_spiclk: - clk_disable_unprepare(rs->spiclk); -err_disable_apbclk: - clk_disable_unprepare(rs->apb_pclk); err_put_ctlr: spi_controller_put(ctlr); @@ -950,13 +934,9 @@ err_put_ctlr: static void rockchip_spi_remove(struct platform_device *pdev) { struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev)); - struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); pm_runtime_get_sync(&pdev->dev); - clk_disable_unprepare(rs->spiclk); - clk_disable_unprepare(rs->apb_pclk); - pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); diff --git a/drivers/spi/spi-rzv2m-csi.c b/drivers/spi/spi-rzv2m-csi.c index d0f51b17aa7c..741e0f44c49c 100644 --- a/drivers/spi/spi-rzv2m-csi.c +++ b/drivers/spi/spi-rzv2m-csi.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,9 @@ #define CSI_MODE_SETUP 0x00000040 /* CSI_CLKSEL */ +#define CSI_CLKSEL_SS_ENA BIT(19) +#define CSI_CLKSEL_SS_POL BIT(18) +#define CSI_CLKSEL_SS (CSI_CLKSEL_SS_ENA | CSI_CLKSEL_SS_POL) #define CSI_CLKSEL_CKP BIT(17) #define CSI_CLKSEL_DAP BIT(16) #define CSI_CLKSEL_MODE (CSI_CLKSEL_CKP|CSI_CLKSEL_DAP) @@ -82,6 +86,10 @@ #define CSI_MAX_SPI_SCKO (8 * HZ_PER_MHZ) +#define CSI_CLKSEL_SS_DISABLED 0 +#define CSI_CLKSEL_SS_ENABLED_ACTIVE_LOW BIT(1) +#define CSI_CLKSEL_SS_ENABLED_ACTIVE_HIGH GENMASK(1, 0) + struct rzv2m_csi_priv { void __iomem *base; struct clk *csiclk; @@ -99,6 +107,8 @@ struct rzv2m_csi_priv { wait_queue_head_t wait; u32 errors; u32 status; + bool target_aborted; + bool use_ss_pin; }; static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi, @@ -193,6 +203,14 @@ static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi) return 0; } +static inline void rzv2m_csi_empty_rxfifo(struct rzv2m_csi_priv *csi) +{ + unsigned int i; + + for (i = 0; i < csi->words_to_transfer; i++) + readl(csi->base + CSI_IFIFO); +} + static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) { unsigned int bytes_transferred = max(csi->bytes_received, csi->bytes_sent); @@ -279,32 +297,23 @@ static int rzv2m_csi_wait_for_interrupt(struct rzv2m_csi_priv *csi, rzv2m_csi_enable_irqs(csi, enable_bits); - ret = wait_event_timeout(csi->wait, - ((csi->status & wait_mask) == wait_mask) || - csi->errors, HZ); + if (spi_controller_is_target(csi->controller)) { + ret = wait_event_interruptible(csi->wait, + ((csi->status & wait_mask) == wait_mask) || + csi->errors || csi->target_aborted); + if (ret || csi->target_aborted) + ret = -EINTR; + } else { + ret = wait_event_timeout(csi->wait, + ((csi->status & wait_mask) == wait_mask) || + csi->errors, HZ) == 0 ? -ETIMEDOUT : 0; + } rzv2m_csi_disable_irqs(csi, enable_bits); if (csi->errors) return -EIO; - if (!ret) - return -ETIMEDOUT; - - return 0; -} - -static int rzv2m_csi_wait_for_tx_empty(struct rzv2m_csi_priv *csi) -{ - int ret; - - if (readl(csi->base + CSI_OFIFOL) == 0) - return 0; - - ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_TREND, CSI_CNT_TREND_E); - if (ret == -ETIMEDOUT) - csi->errors |= TX_TIMEOUT_ERROR; - return ret; } @@ -312,7 +321,7 @@ static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi) { int ret; - if (readl(csi->base + CSI_IFIFOL) == csi->bytes_to_transfer) + if (readl(csi->base + CSI_IFIFOL) >= csi->bytes_to_transfer) return 0; ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR, @@ -388,6 +397,7 @@ static void rzv2m_csi_setup_operating_mode(struct rzv2m_csi_priv *csi, static int rzv2m_csi_setup(struct spi_device *spi) { struct rzv2m_csi_priv *csi = spi_controller_get_devdata(spi->controller); + u32 slave_selection = CSI_CLKSEL_SS_DISABLED; int ret; rzv2m_csi_sw_reset(csi, 0); @@ -402,8 +412,17 @@ static int rzv2m_csi_setup(struct spi_device *spi) rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR, !!(spi->mode & SPI_LSB_FIRST)); - /* Set the operation mode as master */ - rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, 0); + /* Set the role, 1 for target and 0 for host */ + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, + !!spi_controller_is_target(csi->controller)); + + if (csi->use_ss_pin) + slave_selection = spi->mode & SPI_CS_HIGH ? + CSI_CLKSEL_SS_ENABLED_ACTIVE_HIGH : + CSI_CLKSEL_SS_ENABLED_ACTIVE_LOW; + + /* Configure the slave selection (SS) pin */ + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SS, slave_selection); /* Give the IP a SW reset */ ret = rzv2m_csi_sw_reset(csi, 1); @@ -431,9 +450,13 @@ static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi) /* Make sure the TX FIFO is empty */ writel(0, csi->base + CSI_OFIFOL); + /* Make sure the RX FIFO is empty */ + writel(0, csi->base + CSI_IFIFOL); + csi->bytes_sent = 0; csi->bytes_received = 0; csi->errors = 0; + csi->target_aborted = false; rzv2m_csi_disable_all_irqs(csi); rzv2m_csi_clear_all_irqs(csi); @@ -452,28 +475,21 @@ static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi) rzv2m_csi_enable_irqs(csi, CSI_INT_OVERF | CSI_INT_UNDER); - /* Make sure the RX FIFO is empty */ - writel(0, csi->base + CSI_IFIFOL); - writel(readl(csi->base + CSI_INT), csi->base + CSI_INT); csi->status = 0; - rzv2m_csi_start_stop_operation(csi, 1, false); - /* TX */ if (csi->txbuf) { ret = rzv2m_csi_fill_txfifo(csi); if (ret) break; - ret = rzv2m_csi_wait_for_tx_empty(csi); - if (ret) - break; - if (csi->bytes_sent == csi->buffer_len) tx_completed = true; } + rzv2m_csi_start_stop_operation(csi, 1, false); + /* * Make sure the RX FIFO contains the desired number of words. * We then either flush its content, or we copy it onto @@ -483,31 +499,28 @@ static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi) if (ret) break; - /* RX */ - if (csi->rxbuf) { + if (!spi_controller_is_target(csi->controller)) rzv2m_csi_start_stop_operation(csi, 0, false); + /* RX */ + if (csi->rxbuf) { ret = rzv2m_csi_read_rxfifo(csi); if (ret) break; if (csi->bytes_received == csi->buffer_len) rx_completed = true; + } else { + rzv2m_csi_empty_rxfifo(csi); } - ret = rzv2m_csi_start_stop_operation(csi, 0, true); - if (ret) - goto pio_quit; - if (csi->errors) { ret = -EIO; - goto pio_quit; + break; } } rzv2m_csi_start_stop_operation(csi, 0, true); - -pio_quit: rzv2m_csi_disable_all_irqs(csi); rzv2m_csi_enable_rx_trigger(csi, false); rzv2m_csi_clear_all_irqs(csi); @@ -529,7 +542,8 @@ static int rzv2m_csi_transfer_one(struct spi_controller *controller, rzv2m_csi_setup_operating_mode(csi, transfer); - rzv2m_csi_setup_clock(csi, transfer->speed_hz); + if (!spi_controller_is_target(csi->controller)) + rzv2m_csi_setup_clock(csi, transfer->speed_hz); ret = rzv2m_csi_pio_transfer(csi); if (ret) { @@ -546,24 +560,48 @@ static int rzv2m_csi_transfer_one(struct spi_controller *controller, return ret; } +static int rzv2m_csi_target_abort(struct spi_controller *ctlr) +{ + struct rzv2m_csi_priv *csi = spi_controller_get_devdata(ctlr); + + csi->target_aborted = true; + wake_up(&csi->wait); + + return 0; +} + static int rzv2m_csi_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct spi_controller *controller; struct device *dev = &pdev->dev; struct rzv2m_csi_priv *csi; struct reset_control *rstc; + bool target_mode; int irq; int ret; - controller = devm_spi_alloc_host(dev, sizeof(*csi)); + target_mode = of_property_read_bool(np, "spi-slave"); + + if (target_mode) + controller = devm_spi_alloc_target(dev, sizeof(*csi)); + else + controller = devm_spi_alloc_host(dev, sizeof(*csi)); + if (!controller) return -ENOMEM; csi = spi_controller_get_devdata(controller); platform_set_drvdata(pdev, csi); + csi->use_ss_pin = false; + if (spi_controller_is_target(controller) && + !of_property_read_bool(np, "renesas,csi-no-ss")) + csi->use_ss_pin = true; + csi->dev = dev; csi->controller = controller; + csi->target_aborted = false; csi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(csi->base)) @@ -589,11 +627,12 @@ static int rzv2m_csi_probe(struct platform_device *pdev) init_waitqueue_head(&csi->wait); - controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH; controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); controller->setup = rzv2m_csi_setup; controller->transfer_one = rzv2m_csi_transfer_one; controller->use_gpio_descriptors = true; + controller->target_abort = rzv2m_csi_target_abort; device_set_node(&controller->dev, dev_fwnode(dev)); diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index ef665f470c5b..e6e3e4ea29f9 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -13,7 +13,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 4d6db6182c5e..f5cd365c913a 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1086,6 +1086,8 @@ static int tegra_slink_probe(struct platform_device *pdev) reset_control_deassert(tspi->rst); spi_irq = platform_get_irq(pdev, 0); + if (spi_irq < 0) + return spi_irq; tspi->irq = spi_irq; ret = request_threaded_irq(tspi->irq, tegra_slink_isr, tegra_slink_isr_thread, IRQF_ONESHOT, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8d6304cb061e..791df0e69105 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2093,10 +2093,6 @@ static int spi_stop_queue(struct spi_controller *ctlr) spin_unlock_irqrestore(&ctlr->queue_lock, flags); - if (ret) { - dev_warn(&ctlr->dev, "could not stop message queue\n"); - return ret; - } return ret; } @@ -2527,8 +2523,6 @@ static void acpi_spi_parse_apple_properties(struct acpi_device *dev, lookup->mode |= SPI_CPHA; } -static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev); - static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) { struct acpi_spi_lookup *lookup = data; @@ -4523,7 +4517,7 @@ static int spi_acpi_controller_match(struct device *dev, const void *data) return ACPI_COMPANION(dev->parent) == data; } -static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev) +struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev) { struct device *dev; @@ -4537,6 +4531,7 @@ static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_devic return container_of(dev, struct spi_controller, dev); } +EXPORT_SYMBOL_GPL(acpi_spi_find_controller_by_adev); static struct spi_device *acpi_spi_find_device_by_adev(struct acpi_device *adev) { diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index d13dc15cc191..655f2c959cd4 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -357,6 +357,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int retval = 0; struct spidev_data *spidev; struct spi_device *spi; + struct spi_controller *ctlr; u32 tmp; unsigned n_ioc; struct spi_ioc_transfer *ioc; @@ -376,6 +377,8 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ESHUTDOWN; } + ctlr = spi->controller; + /* use the buffer lock here for triple duty: * - prevent I/O (from us) so calling spi_setup() is safe; * - prevent concurrent SPI_IOC_WR_* from morphing @@ -388,22 +391,15 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* read requests */ case SPI_IOC_RD_MODE: case SPI_IOC_RD_MODE32: - tmp = spi->mode; + tmp = spi->mode & SPI_MODE_MASK; - { - struct spi_controller *ctlr = spi->controller; - - if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && - ctlr->cs_gpiods[spi_get_chipselect(spi, 0)]) - tmp &= ~SPI_CS_HIGH; - } + if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0)) + tmp &= ~SPI_CS_HIGH; if (cmd == SPI_IOC_RD_MODE) - retval = put_user(tmp & SPI_MODE_MASK, - (__u8 __user *)arg); + retval = put_user(tmp, (__u8 __user *)arg); else - retval = put_user(tmp & SPI_MODE_MASK, - (__u32 __user *)arg); + retval = put_user(tmp, (__u32 __user *)arg); break; case SPI_IOC_RD_LSB_FIRST: retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, @@ -424,7 +420,6 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) else retval = get_user(tmp, (u32 __user *)arg); if (retval == 0) { - struct spi_controller *ctlr = spi->controller; u32 save = spi->mode; if (tmp & ~SPI_MODE_MASK) { @@ -432,8 +427,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } - if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && - ctlr->cs_gpiods[spi_get_chipselect(spi, 0)]) + if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0)) tmp |= SPI_CS_HIGH; tmp |= spi->mode & ~SPI_MODE_MASK; @@ -701,7 +695,9 @@ static const struct file_operations spidev_fops = { * It also simplifies memory management. */ -static struct class *spidev_class; +static const struct class spidev_class = { + .name = "spidev", +}; static const struct spi_device_id spidev_spi_ids[] = { { .name = "dh2228fv" }, @@ -804,7 +800,7 @@ static int spidev_probe(struct spi_device *spi) struct device *dev; spidev->devt = MKDEV(SPIDEV_MAJOR, minor); - dev = device_create(spidev_class, &spi->dev, spidev->devt, + dev = device_create(&spidev_class, &spi->dev, spidev->devt, spidev, "spidev%d.%d", spi->master->bus_num, spi_get_chipselect(spi, 0)); status = PTR_ERR_OR_ZERO(dev); @@ -840,7 +836,7 @@ static void spidev_remove(struct spi_device *spi) mutex_unlock(&spidev->spi_lock); list_del(&spidev->device_entry); - device_destroy(spidev_class, spidev->devt); + device_destroy(&spidev_class, spidev->devt); clear_bit(MINOR(spidev->devt), minors); if (spidev->users == 0) kfree(spidev); @@ -878,15 +874,15 @@ static int __init spidev_init(void) if (status < 0) return status; - spidev_class = class_create("spidev"); - if (IS_ERR(spidev_class)) { + status = class_register(&spidev_class); + if (status) { unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); - return PTR_ERR(spidev_class); + return status; } status = spi_register_driver(&spidev_spi_driver); if (status < 0) { - class_destroy(spidev_class); + class_unregister(&spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); } return status; @@ -896,7 +892,7 @@ module_init(spidev_init); static void __exit spidev_exit(void) { spi_unregister_driver(&spidev_spi_driver); - class_destroy(spidev_class); + class_unregister(&spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); } module_exit(spidev_exit); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 254685085c82..afeed6e72049 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -12,11 +12,9 @@ #include #include -/* TBD: Make dynamic */ -#define ACPI_MAX_HANDLES 10 struct acpi_handle_list { u32 count; - acpi_handle handles[ACPI_MAX_HANDLES]; + acpi_handle* handles; }; /* acpi_utils.h */ @@ -32,6 +30,11 @@ acpi_evaluate_reference(acpi_handle handle, acpi_string pathname, struct acpi_object_list *arguments, struct acpi_handle_list *list); +bool acpi_handle_list_equal(struct acpi_handle_list *list1, + struct acpi_handle_list *list2); +void acpi_handle_list_replace(struct acpi_handle_list *dst, + struct acpi_handle_list *src); +void acpi_handle_list_free(struct acpi_handle_list *list); acpi_status acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code, struct acpi_buffer *status_buf); @@ -517,7 +520,7 @@ int acpi_bus_attach_private_data(acpi_handle, void *); void acpi_bus_detach_private_data(acpi_handle); int acpi_dev_install_notify_handler(struct acpi_device *adev, u32 handler_type, - acpi_notify_handler handler); + acpi_notify_handler handler, void *context); void acpi_dev_remove_notify_handler(struct acpi_device *adev, u32 handler_type, acpi_notify_handler handler); @@ -760,6 +763,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev) adev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set); } +bool acpi_dev_uid_match(struct acpi_device *adev, const char *uid2); bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2); int acpi_dev_uid_to_integer(struct acpi_device *adev, u64 *integer); diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 8d5572ad48cb..a33375e055ad 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -465,6 +465,9 @@ struct acpi_cdat_sslbe { u16 reserved; }; +#define ACPI_CDAT_SSLBIS_US_PORT 0x0100 +#define ACPI_CDAT_SSLBIS_ANY_PORT 0xffff + /******************************************************************************* * * CEDT - CXL Early Discovery Table diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 3c8bba9f1114..be1dd4c1a917 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -73,8 +73,12 @@ int ghes_register_vendor_record_notifier(struct notifier_block *nb); void ghes_unregister_vendor_record_notifier(struct notifier_block *nb); struct list_head *ghes_get_devices(void); + +void ghes_estatus_pool_region_free(unsigned long addr, u32 size); #else static inline struct list_head *ghes_get_devices(void) { return NULL; } + +static inline void ghes_estatus_pool_region_free(unsigned long addr, u32 size) { return; } #endif int ghes_estatus_pool_init(unsigned int num_ghes); diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h index 73e806fe7ce7..9b373d172a77 100644 --- a/include/acpi/pcc.h +++ b/include/acpi/pcc.h @@ -18,7 +18,20 @@ struct pcc_mbox_chan { u16 min_turnaround_time; }; +/* Generic Communications Channel Shared Memory Region */ +#define PCC_SIGNATURE 0x50434300 +/* Generic Communications Channel Command Field */ +#define PCC_CMD_GENERATE_DB_INTR BIT(15) +/* Generic Communications Channel Status Field */ +#define PCC_STATUS_CMD_COMPLETE BIT(0) +#define PCC_STATUS_SCI_DOORBELL BIT(1) +#define PCC_STATUS_ERROR BIT(2) +#define PCC_STATUS_PLATFORM_NOTIFY BIT(3) +/* Initiator Responder Communications Channel Flags */ +#define PCC_CMD_COMPLETION_NOTIFY BIT(0) + #define MAX_PCC_SUBSPACES 256 + #ifdef CONFIG_PCC extern struct pcc_mbox_chan * pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index afd94c9b8b8a..db3a33e19c97 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -787,6 +787,11 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv) struct acpi_device; +static inline bool acpi_dev_uid_match(struct acpi_device *adev, const char *uid2) +{ + return false; +} + static inline bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 1c4385a00f88..db2dfbae8edb 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -159,7 +159,6 @@ int gpiod_set_raw_array_value_cansleep(unsigned int array_size, int gpiod_set_config(struct gpio_desc *desc, unsigned long config); int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce); -int gpiod_set_transitory(struct gpio_desc *desc, bool transitory); void gpiod_toggle_active_low(struct gpio_desc *desc); int gpiod_is_active_low(const struct gpio_desc *desc); @@ -494,13 +493,6 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned int deboun return -ENOSYS; } -static inline int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) -{ - /* GPIO can never have been requested */ - WARN_ON(desc); - return -ENOSYS; -} - static inline void gpiod_toggle_active_low(struct gpio_desc *desc) { /* GPIO can never have been requested */ @@ -614,8 +606,6 @@ void acpi_dev_remove_driver_gpios(struct acpi_device *adev); int devm_acpi_dev_add_driver_gpios(struct device *dev, const struct acpi_gpio_mapping *gpios); -struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char *label); - #else /* CONFIG_GPIOLIB && CONFIG_ACPI */ #include @@ -633,12 +623,6 @@ static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, return -ENXIO; } -static inline struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, - char *label) -{ - return ERR_PTR(-ENOSYS); -} - #endif /* CONFIG_GPIOLIB && CONFIG_ACPI */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 4f0c5d62c8f3..1d454dc944b3 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -3,6 +3,8 @@ #define __LINUX_GPIO_DRIVER_H #include +#include +#include #include #include #include @@ -529,8 +531,7 @@ struct gpio_chip { #endif /* CONFIG_OF_GPIO */ }; -extern const char *gpiochip_is_requested(struct gpio_chip *gc, - unsigned int offset); +const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset); /** * for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range @@ -549,9 +550,9 @@ extern const char *gpiochip_is_requested(struct gpio_chip *gc, for_each_requested_gpio_in_range(chip, i, 0, chip->ngpio, label) /* add/remove chips */ -extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, - struct lock_class_key *lock_key, - struct lock_class_key *request_key); +int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + struct lock_class_key *lock_key, + struct lock_class_key *request_key); /** * gpiochip_add_data() - register a gpio_chip @@ -599,13 +600,26 @@ static inline int gpiochip_add(struct gpio_chip *gc) { return gpiochip_add_data(gc, NULL); } -extern void gpiochip_remove(struct gpio_chip *gc); -extern int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data, - struct lock_class_key *lock_key, - struct lock_class_key *request_key); +void gpiochip_remove(struct gpio_chip *gc); +int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, + void *data, struct lock_class_key *lock_key, + struct lock_class_key *request_key); -extern struct gpio_chip *gpiochip_find(void *data, - int (*match)(struct gpio_chip *gc, void *data)); +struct gpio_chip *gpiochip_find(void *data, + int (*match)(struct gpio_chip *gc, void *data)); + +struct gpio_device *gpio_device_find(void *data, + int (*match)(struct gpio_chip *gc, void *data)); +struct gpio_device *gpio_device_find_by_label(const char *label); +struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode); + +struct gpio_device *gpio_device_get(struct gpio_device *gdev); +void gpio_device_put(struct gpio_device *gdev); + +DEFINE_FREE(gpio_device_put, struct gpio_device *, + if (IS_ERR_OR_NULL(_T)) gpio_device_put(_T)); + +struct device *gpio_device_to_device(struct gpio_device *gdev); bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset); @@ -758,14 +772,23 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, enum gpiod_flags dflags); void gpiochip_free_own_desc(struct gpio_desc *desc); +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); +struct gpio_desc * +gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum); + +struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev); + #ifdef CONFIG_GPIOLIB /* lock/unlock as IRQ */ int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset); - struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); +struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc); + +/* struct gpio_device getters */ +int gpio_device_get_base(struct gpio_device *gdev); #else /* CONFIG_GPIOLIB */ diff --git a/include/linux/mfd/mt6358/registers.h b/include/linux/mfd/mt6358/registers.h index 3d33517f178c..d83e87298ac4 100644 --- a/include/linux/mfd/mt6358/registers.h +++ b/include/linux/mfd/mt6358/registers.h @@ -262,6 +262,12 @@ #define MT6358_LDO_VBIF28_CON3 0x1db0 #define MT6358_VCAMA1_ANA_CON0 0x1e08 #define MT6358_VCAMA2_ANA_CON0 0x1e0c +#define MT6358_VFE28_ANA_CON0 0x1e10 +#define MT6358_VCN28_ANA_CON0 0x1e14 +#define MT6358_VBIF28_ANA_CON0 0x1e18 +#define MT6358_VAUD28_ANA_CON0 0x1e1c +#define MT6358_VAUX18_ANA_CON0 0x1e20 +#define MT6358_VXO22_ANA_CON0 0x1e24 #define MT6358_VCN33_ANA_CON0 0x1e28 #define MT6358_VSIM1_ANA_CON0 0x1e2c #define MT6358_VSIM2_ANA_CON0 0x1e30 @@ -288,4 +294,21 @@ #define MT6358_AUD_TOP_INT_CON0 0x2228 #define MT6358_AUD_TOP_INT_STATUS0 0x2234 +/* + * MT6366 has no VCAM*, but has other regulators in its place. The names + * keep the MT6358 prefix for ease of use in the regulator driver. + */ +#define MT6358_LDO_VSRAM_CON5 0x1bf8 +#define MT6358_LDO_VM18_CON0 MT6358_LDO_VCAMA1_CON0 +#define MT6358_LDO_VM18_CON1 MT6358_LDO_VCAMA1_CON1 +#define MT6358_LDO_VM18_CON2 MT6358_LDO_VCAMA1_CON2 +#define MT6358_LDO_VMDDR_CON0 MT6358_LDO_VCAMA2_CON0 +#define MT6358_LDO_VMDDR_CON1 MT6358_LDO_VCAMA2_CON1 +#define MT6358_LDO_VMDDR_CON2 MT6358_LDO_VCAMA2_CON2 +#define MT6358_LDO_VSRAM_CORE_CON0 MT6358_LDO_VCAMD_CON0 +#define MT6358_LDO_VSRAM_CORE_DBG0 0x1cb6 +#define MT6358_LDO_VSRAM_CORE_DBG1 0x1cb8 +#define MT6358_VM18_ANA_CON0 MT6358_VCAMA1_ANA_CON0 +#define MT6358_VMDDR_ANA_CON0 MT6358_VCAMD_ANA_CON0 + #endif /* __MFD_MT6358_REGISTERS_H__ */ diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h index f377817ce75c..cdd8cfb424f5 100644 --- a/include/linux/platform_data/gpio-omap.h +++ b/include/linux/platform_data/gpio-omap.h @@ -144,9 +144,6 @@ #define OMAP_MAX_GPIO_LINES 192 -#define OMAP_MPUIO(nr) (OMAP_MAX_GPIO_LINES + (nr)) -#define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES) - #ifndef __ASSEMBLER__ struct omap_gpio_reg_offs { u16 revision; diff --git a/include/linux/platform_data/pca953x.h b/include/linux/platform_data/pca953x.h index 96c1a14ab365..3c3787c4d96c 100644 --- a/include/linux/platform_data/pca953x.h +++ b/include/linux/platform_data/pca953x.h @@ -11,21 +11,8 @@ struct pca953x_platform_data { /* number of the first GPIO */ unsigned gpio_base; - /* initial polarity inversion setting */ - u32 invert; - /* interrupt base */ int irq_base; - - void *context; /* param to setup/teardown */ - - int (*setup)(struct i2c_client *client, - unsigned gpio, unsigned ngpio, - void *context); - void (*teardown)(struct i2c_client *client, - unsigned gpio, unsigned ngpio, - void *context); - const char *const *names; }; #endif /* _LINUX_PCA953X_H */ diff --git a/include/linux/pm.h b/include/linux/pm.h index 1400c37b29c7..92a4f69de0e8 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -374,24 +374,39 @@ const struct dev_pm_ops name = { \ RUNTIME_PM_OPS(runtime_suspend_fn, runtime_resume_fn, idle_fn) \ } -#ifdef CONFIG_PM -#define _EXPORT_DEV_PM_OPS(name, license, ns) \ +#define _EXPORT_PM_OPS(name, license, ns) \ const struct dev_pm_ops name; \ __EXPORT_SYMBOL(name, license, ns); \ const struct dev_pm_ops name -#define EXPORT_PM_FN_GPL(name) EXPORT_SYMBOL_GPL(name) -#define EXPORT_PM_FN_NS_GPL(name, ns) EXPORT_SYMBOL_NS_GPL(name, ns) -#else -#define _EXPORT_DEV_PM_OPS(name, license, ns) \ + +#define _DISCARD_PM_OPS(name, license, ns) \ static __maybe_unused const struct dev_pm_ops __static_##name + +#ifdef CONFIG_PM +#define _EXPORT_DEV_PM_OPS(name, license, ns) _EXPORT_PM_OPS(name, license, ns) +#define EXPORT_PM_FN_GPL(name) EXPORT_SYMBOL_GPL(name) +#define EXPORT_PM_FN_NS_GPL(name, ns) EXPORT_SYMBOL_NS_GPL(name, ns) +#else +#define _EXPORT_DEV_PM_OPS(name, license, ns) _DISCARD_PM_OPS(name, license, ns) #define EXPORT_PM_FN_GPL(name) #define EXPORT_PM_FN_NS_GPL(name, ns) #endif -#define EXPORT_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "", "") -#define EXPORT_GPL_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "GPL", "") -#define EXPORT_NS_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "", #ns) -#define EXPORT_NS_GPL_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "GPL", #ns) +#ifdef CONFIG_PM_SLEEP +#define _EXPORT_DEV_SLEEP_PM_OPS(name, license, ns) _EXPORT_PM_OPS(name, license, ns) +#else +#define _EXPORT_DEV_SLEEP_PM_OPS(name, license, ns) _DISCARD_PM_OPS(name, license, ns) +#endif + +#define EXPORT_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "", "") +#define EXPORT_GPL_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "GPL", "") +#define EXPORT_NS_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "", #ns) +#define EXPORT_NS_GPL_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "GPL", #ns) + +#define EXPORT_DEV_SLEEP_PM_OPS(name) _EXPORT_DEV_SLEEP_PM_OPS(name, "", "") +#define EXPORT_GPL_DEV_SLEEP_PM_OPS(name) _EXPORT_DEV_SLEEP_PM_OPS(name, "GPL", "") +#define EXPORT_NS_DEV_SLEEP_PM_OPS(name, ns) _EXPORT_DEV_SLEEP_PM_OPS(name, "", #ns) +#define EXPORT_NS_GPL_DEV_SLEEP_PM_OPS(name, ns) _EXPORT_DEV_SLEEP_PM_OPS(name, "GPL", #ns) /* * Use this if you want to use the same suspend and resume callbacks for suspend @@ -404,19 +419,19 @@ const struct dev_pm_ops name = { \ _DEFINE_DEV_PM_OPS(name, suspend_fn, resume_fn, NULL, NULL, NULL) #define EXPORT_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ - EXPORT_DEV_PM_OPS(name) = { \ + EXPORT_DEV_SLEEP_PM_OPS(name) = { \ SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ } #define EXPORT_GPL_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ - EXPORT_GPL_DEV_PM_OPS(name) = { \ + EXPORT_GPL_DEV_SLEEP_PM_OPS(name) = { \ SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ } #define EXPORT_NS_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn, ns) \ - EXPORT_NS_DEV_PM_OPS(name, ns) = { \ + EXPORT_NS_DEV_SLEEP_PM_OPS(name, ns) = { \ SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ } #define EXPORT_NS_GPL_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn, ns) \ - EXPORT_NS_GPL_DEV_PM_OPS(name, ns) = { \ + EXPORT_NS_GPL_DEV_SLEEP_PM_OPS(name, ns) = { \ SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ } @@ -719,6 +734,7 @@ extern void dev_pm_put_subsys_data(struct device *dev); * @activate: Called before executing probe routines for bus types and drivers. * @sync: Called after successful driver probe. * @dismiss: Called after unsuccessful driver probe and after driver removal. + * @set_performance_state: Called to request a new performance state. * * Power domains provide callbacks that are executed during system suspend, * hibernation, system resume and during runtime PM transitions instead of @@ -731,6 +747,7 @@ struct dev_pm_domain { int (*activate)(struct device *dev); void (*sync)(struct device *dev); void (*dismiss)(struct device *dev); + int (*set_performance_state)(struct device *dev, unsigned int state); }; /* diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index f776fb93eaa0..bda2964a0a56 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -430,6 +430,7 @@ struct device *dev_pm_domain_attach_by_name(struct device *dev, void dev_pm_domain_detach(struct device *dev, bool power_off); int dev_pm_domain_start(struct device *dev); void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd); +int dev_pm_domain_set_performance_state(struct device *dev, unsigned int state); #else static inline int dev_pm_domain_attach(struct device *dev, bool power_on) { @@ -452,6 +453,11 @@ static inline int dev_pm_domain_start(struct device *dev) } static inline void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd) {} +static inline int dev_pm_domain_set_performance_state(struct device *dev, + unsigned int state) +{ + return 0; +} #endif #endif /* _LINUX_PM_DOMAIN_H */ diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 91f87d7e807c..ccd97bcef269 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -92,6 +92,18 @@ struct dev_pm_opp_config { struct device ***virt_devs; }; +/** + * struct dev_pm_opp_data - The data to use to initialize an OPP. + * @level: The performance level for the OPP. + * @freq: The clock rate in Hz for the OPP. + * @u_volt: The voltage in uV for the OPP. + */ +struct dev_pm_opp_data { + unsigned int level; + unsigned long freq; + unsigned long u_volt; +}; + #if defined(CONFIG_PM_OPP) struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); @@ -144,6 +156,9 @@ struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, unsigned int *level); +struct dev_pm_opp *dev_pm_opp_find_level_floor(struct device *dev, + unsigned long *level); + struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, unsigned int *bw, int index); @@ -152,8 +167,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, void dev_pm_opp_put(struct dev_pm_opp *opp); -int dev_pm_opp_add(struct device *dev, unsigned long freq, - unsigned long u_volt); +int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp); + void dev_pm_opp_remove(struct device *dev, unsigned long freq); void dev_pm_opp_remove_all_dynamic(struct device *dev); @@ -308,6 +323,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, return ERR_PTR(-EOPNOTSUPP); } +static inline struct dev_pm_opp *dev_pm_opp_find_level_floor(struct device *dev, + unsigned long *level) +{ + return ERR_PTR(-EOPNOTSUPP); +} + static inline struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, unsigned int *bw, int index) { @@ -322,8 +343,8 @@ static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {} -static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, - unsigned long u_volt) +static inline int +dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp) { return -EOPNOTSUPP; } @@ -519,6 +540,17 @@ static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_ta /* OPP Configuration helpers */ +static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, + unsigned long u_volt) +{ + struct dev_pm_opp_data data = { + .freq = freq, + .u_volt = u_volt, + }; + + return dev_pm_opp_add_dynamic(dev, &data); +} + /* Regulators helpers */ static inline int dev_pm_opp_set_regulators(struct device *dev, const char * const names[]) diff --git a/include/linux/pnp.h b/include/linux/pnp.h index c2a7cfbca713..267fb8a4fb6e 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -291,7 +291,7 @@ static inline void pnp_set_drvdata(struct pnp_dev *pdev, void *data) struct pnp_fixup { char id[7]; - void (*quirk_function) (struct pnp_dev * dev); /* fixup function */ + void (*quirk_function) (struct pnp_dev *dev); /* fixup function */ }; /* config parameters */ @@ -419,8 +419,8 @@ struct pnp_protocol { /* protocol specific suspend/resume */ bool (*can_wakeup) (struct pnp_dev *dev); - int (*suspend) (struct pnp_dev * dev, pm_message_t state); - int (*resume) (struct pnp_dev * dev); + int (*suspend) (struct pnp_dev *dev, pm_message_t state); + int (*resume) (struct pnp_dev *dev); /* used by pnp layer only (look but don't touch) */ unsigned char number; /* protocol number */ @@ -492,7 +492,7 @@ static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } -static inline int pnp_range_reserved(resource_size_t start, resource_size_t end) { return 0;} +static inline int pnp_range_reserved(resource_size_t start, resource_size_t end) { return 0; } /* protocol helpers */ static inline int pnp_is_active(struct pnp_dev *dev) { return 0; } diff --git a/include/linux/regulator/mt6358-regulator.h b/include/linux/regulator/mt6358-regulator.h index c71a6a9fce7a..562386f9b80e 100644 --- a/include/linux/regulator/mt6358-regulator.h +++ b/include/linux/regulator/mt6358-regulator.h @@ -86,6 +86,9 @@ enum { MT6366_ID_VMC, MT6366_ID_VAUD28, MT6366_ID_VSIM2, + MT6366_ID_VM18, + MT6366_ID_VMDDR, + MT6366_ID_VSRAM_CORE, MT6366_ID_RG_MAX, }; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 7f8b478fdeb3..86825c88b576 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -867,6 +867,7 @@ extern int devm_spi_register_controller(struct device *dev, extern void spi_unregister_controller(struct spi_controller *ctlr); #if IS_ENABLED(CONFIG_ACPI) +extern struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev); extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, struct acpi_device *adev, int index); @@ -1086,8 +1087,6 @@ struct spi_transfer { * @state: for use by whichever driver currently owns the message * @resources: for resource management when the SPI message is processed * @prepared: spi_prepare_message was called for the this message - * @t: for use with spi_message_alloc() when message and transfers have - * been allocated together * * A @spi_message is used to execute an atomic sequence of data transfers, * each represented by a struct spi_transfer. The sequence is "atomic" @@ -1142,9 +1141,6 @@ struct spi_message { /* List of spi_res resources when the SPI message is processed */ struct list_head resources; - - /* For embedding transfers into the memory of the message */ - struct spi_transfer t[]; }; static inline void spi_message_init_no_memset(struct spi_message *m) @@ -1203,17 +1199,21 @@ struct spi_transfer *xfers, unsigned int num_xfers) */ static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags) { - struct spi_message *m; + struct spi_message_with_transfers { + struct spi_message m; + struct spi_transfer t[]; + } *mwt; + unsigned i; - m = kzalloc(struct_size(m, t, ntrans), flags); - if (m) { - unsigned i; + mwt = kzalloc(struct_size(mwt, t, ntrans), flags); + if (!mwt) + return NULL; - spi_message_init_no_memset(m); - for (i = 0; i < ntrans; i++) - spi_message_add_tail(&m->t[i], m); - } - return m; + spi_message_init_no_memset(&mwt->m); + for (i = 0; i < ntrans; i++) + spi_message_add_tail(&mwt->t[i], &mwt->m); + + return &mwt->m; } static inline void spi_message_free(struct spi_message *m) diff --git a/include/soc/rockchip/rk3399_grf.h b/include/soc/rockchip/rk3399_grf.h index 3eebabcb2812..39cd44cec982 100644 --- a/include/soc/rockchip/rk3399_grf.h +++ b/include/soc/rockchip/rk3399_grf.h @@ -11,11 +11,8 @@ /* PMU GRF Registers */ #define RK3399_PMUGRF_OS_REG2 0x308 -#define RK3399_PMUGRF_DDRTYPE_SHIFT 13 -#define RK3399_PMUGRF_DDRTYPE_MASK 7 -#define RK3399_PMUGRF_DDRTYPE_DDR3 3 -#define RK3399_PMUGRF_DDRTYPE_LPDDR2 5 -#define RK3399_PMUGRF_DDRTYPE_LPDDR3 6 -#define RK3399_PMUGRF_DDRTYPE_LPDDR4 7 +#define RK3399_PMUGRF_OS_REG2_DDRTYPE GENMASK(15, 13) +#define RK3399_PMUGRF_OS_REG2_BW_CH0 GENMASK(3, 2) +#define RK3399_PMUGRF_OS_REG2_BW_CH1 GENMASK(19, 18) #endif diff --git a/include/soc/rockchip/rk3568_grf.h b/include/soc/rockchip/rk3568_grf.h new file mode 100644 index 000000000000..52853efd6720 --- /dev/null +++ b/include/soc/rockchip/rk3568_grf.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef __SOC_RK3568_GRF_H +#define __SOC_RK3568_GRF_H + +#define RK3568_PMUGRF_OS_REG2 0x208 +#define RK3568_PMUGRF_OS_REG2_DRAMTYPE_INFO GENMASK(15, 13) +#define RK3568_PMUGRF_OS_REG2_BW_CH0 GENMASK(3, 2) + +#define RK3568_PMUGRF_OS_REG3 0x20c +#define RK3568_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3 GENMASK(13, 12) +#define RK3568_PMUGRF_OS_REG3_SYSREG_VERSION GENMASK(31, 28) + +#endif /* __SOC_RK3568_GRF_H */ diff --git a/include/soc/rockchip/rk3588_grf.h b/include/soc/rockchip/rk3588_grf.h new file mode 100644 index 000000000000..630b35a55064 --- /dev/null +++ b/include/soc/rockchip/rk3588_grf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef __SOC_RK3588_GRF_H +#define __SOC_RK3588_GRF_H + +#define RK3588_PMUGRF_OS_REG2 0x208 +#define RK3588_PMUGRF_OS_REG2_DRAMTYPE_INFO GENMASK(15, 13) +#define RK3588_PMUGRF_OS_REG2_BW_CH0 GENMASK(3, 2) +#define RK3588_PMUGRF_OS_REG2_BW_CH1 GENMASK(19, 18) +#define RK3588_PMUGRF_OS_REG2_CH_INFO GENMASK(29, 28) + +#define RK3588_PMUGRF_OS_REG3 0x20c +#define RK3588_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3 GENMASK(13, 12) +#define RK3588_PMUGRF_OS_REG3_SYSREG_VERSION GENMASK(31, 28) + +#define RK3588_PMUGRF_OS_REG4 0x210 +#define RK3588_PMUGRF_OS_REG5 0x214 + +#endif /* __SOC_RK3588_GRF_H */ diff --git a/include/soc/rockchip/rockchip_grf.h b/include/soc/rockchip/rockchip_grf.h new file mode 100644 index 000000000000..e46fd72aea8d --- /dev/null +++ b/include/soc/rockchip/rockchip_grf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Rockchip General Register Files definitions + */ + +#ifndef __SOC_ROCKCHIP_GRF_H +#define __SOC_ROCKCHIP_GRF_H + +/* Rockchip DDRTYPE defines */ +enum { + ROCKCHIP_DDRTYPE_DDR3 = 3, + ROCKCHIP_DDRTYPE_LPDDR2 = 5, + ROCKCHIP_DDRTYPE_LPDDR3 = 6, + ROCKCHIP_DDRTYPE_LPDDR4 = 7, + ROCKCHIP_DDRTYPE_LPDDR4X = 8, +}; + +#endif /* __SOC_ROCKCHIP_GRF_H */ diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 0f12e0a97e43..50a15408c3fc 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -2545,8 +2545,9 @@ static void *get_highmem_page_buffer(struct page *page, pbe->copy_page = tmp; } else { /* Copy of the page will be stored in normal memory */ - kaddr = safe_pages_list; - safe_pages_list = safe_pages_list->next; + kaddr = __get_safe_page(ca->gfp_mask); + if (!kaddr) + return ERR_PTR(-ENOMEM); pbe->copy_page = virt_to_page(kaddr); } pbe->next = highmem_pblist; @@ -2750,8 +2751,9 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca) return ERR_PTR(-ENOMEM); } pbe->orig_address = page_address(page); - pbe->address = safe_pages_list; - safe_pages_list = safe_pages_list->next; + pbe->address = __get_safe_page(ca->gfp_mask); + if (!pbe->address) + return ERR_PTR(-ENOMEM); pbe->next = restore_pblist; restore_pblist = pbe; return pbe->address; @@ -2783,8 +2785,6 @@ next: if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages + nr_zero_pages) return 0; - handle->sync_read = 1; - if (!handle->cur) { if (!buffer) /* This makes the buffer be freed by swsusp_free() */ @@ -2827,7 +2827,6 @@ next: memory_bm_position_reset(&zero_bm); restore_pblist = NULL; handle->buffer = get_buffer(&orig_bm, &ca); - handle->sync_read = 0; if (IS_ERR(handle->buffer)) return PTR_ERR(handle->buffer); } @@ -2837,9 +2836,8 @@ next: handle->buffer = get_buffer(&orig_bm, &ca); if (IS_ERR(handle->buffer)) return PTR_ERR(handle->buffer); - if (handle->buffer != buffer) - handle->sync_read = 0; } + handle->sync_read = (handle->buffer == buffer); handle->cur++; /* Zero pages were not included in the image, memset it and move on. */ diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 68a5c2f06957..a2cb0babb5ec 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -1514,7 +1514,7 @@ end: static void *swsusp_holder; /** - * swsusp_check - Check for swsusp signature in the resume device + * swsusp_check - Open the resume device and check for the swsusp signature. * @exclusive: Open the resume device exclusively. */ @@ -1565,7 +1565,7 @@ put: } /** - * swsusp_close - close swap device. + * swsusp_close - close resume device. * @exclusive: Close the resume device which is exclusively opened. */ diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 71badd819ff1..5888176354e2 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -556,6 +556,31 @@ static const struct kobj_type sugov_tunables_ktype = { /********************** cpufreq governor interface *********************/ +#ifdef CONFIG_ENERGY_MODEL +static void rebuild_sd_workfn(struct work_struct *work) +{ + rebuild_sched_domains_energy(); +} + +static DECLARE_WORK(rebuild_sd_work, rebuild_sd_workfn); + +/* + * EAS shouldn't be attempted without sugov, so rebuild the sched_domains + * on governor changes to make sure the scheduler knows about it. + */ +static void sugov_eas_rebuild_sd(void) +{ + /* + * When called from the cpufreq_register_driver() path, the + * cpu_hotplug_lock is already held, so use a work item to + * avoid nested locking in rebuild_sched_domains(). + */ + schedule_work(&rebuild_sd_work); +} +#else +static inline void sugov_eas_rebuild_sd(void) { }; +#endif + struct cpufreq_governor schedutil_gov; static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy) @@ -710,6 +735,8 @@ static int sugov_init(struct cpufreq_policy *policy) if (ret) goto fail; + sugov_eas_rebuild_sd(); + out: mutex_unlock(&global_tunables_lock); return 0; @@ -751,6 +778,8 @@ static void sugov_exit(struct cpufreq_policy *policy) sugov_kthread_stop(sg_policy); sugov_policy_free(sg_policy); cpufreq_disable_fast_switch(policy); + + sugov_eas_rebuild_sd(); } static int sugov_start(struct cpufreq_policy *policy) @@ -768,14 +797,6 @@ static int sugov_start(struct cpufreq_policy *policy) sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); - for_each_cpu(cpu, policy->cpus) { - struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); - - memset(sg_cpu, 0, sizeof(*sg_cpu)); - sg_cpu->cpu = cpu; - sg_cpu->sg_policy = sg_policy; - } - if (policy_is_shared(policy)) uu = sugov_update_shared; else if (policy->fast_switch_enabled && cpufreq_driver_has_adjust_perf()) @@ -786,6 +807,9 @@ static int sugov_start(struct cpufreq_policy *policy) for_each_cpu(cpu, policy->cpus) { struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); + memset(sg_cpu, 0, sizeof(*sg_cpu)); + sg_cpu->cpu = cpu; + sg_cpu->sg_policy = sg_policy; cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, uu); } return 0; diff --git a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py index ec3323100e1a..38cfbdcdedb7 100755 --- a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py +++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-only # -*- coding: utf-8 -*- # @@ -11,11 +11,11 @@ then this utility enables and collects trace data for a user specified interval and generates performance plots. Prerequisites: - Python version 2.7.x or higher + Python version 3.6.x or higher gnuplot 5.0 or higher - gnuplot-py 1.8 or higher + python3-gnuplot 1.8 or higher (Most of the distributions have these required packages. They may be called - gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... ) + gnuplot-py, python-gnuplot or python3-gnuplot, gnuplot-nox, ... ) HWP (Hardware P-States are disabled) Kernel config for Linux trace is enabled @@ -23,7 +23,7 @@ Prerequisites: see print_help(): for Usage and Output details """ -from __future__ import print_function + from datetime import datetime import subprocess import os @@ -562,7 +562,7 @@ if __name__ == "__main__": # Temporary (or perhaps not) cur_version = sys.version_info - print('python version (should be >= 2.7):') + print('python version (should be >= 3.6):') print(cur_version) # Left as "cleanup" for potential future re-run ability.