diff options
290 files changed, 4444 insertions, 2412 deletions
diff --git a/Documentation/devicetree/bindings/extcon/maxim,max77843.yaml b/Documentation/devicetree/bindings/extcon/maxim,max77843.yaml new file mode 100644 index 000000000000..f9ffe3d6f957 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/maxim,max77843.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/extcon/maxim,max77843.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX77843 MicroUSB and Companion Power Management IC Extcon + +maintainers: + - Chanwoo Choi <cw00.choi@samsung.com> + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX77843 MicroUSB + Integrated Circuit (MUIC). + + See also Documentation/devicetree/bindings/mfd/maxim,max77843.yaml for + additional information and example. + +properties: + compatible: + const: maxim,max77843-muic + + connector: + $ref: /schemas/connector/usb-connector.yaml# + + ports: + $ref: /schemas/graph.yaml#/properties/port + description: + Any connector to the data bus of this controller should be modelled using + the OF graph bindings specified + properties: + port: + $ref: /schemas/graph.yaml#/properties/port + +required: + - compatible + - connector + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml index d1f53bd449f7..4caadf73fc4a 100644 --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml @@ -31,7 +31,7 @@ properties: controller-data: description: - SPI controller data, see bindings/spi/spi-samsung.txt + SPI controller data, see bindings/spi/samsung,spi-peripheral-props.yaml type: object google,cros-ec-spi-pre-delay: @@ -148,18 +148,21 @@ patternProperties: required: - compatible -if: - properties: - compatible: - contains: - enum: - - google,cros-ec-i2c - - google,cros-ec-rpmsg -then: - properties: - google,cros-ec-spi-pre-delay: false - google,cros-ec-spi-msg-delay: false - spi-max-frequency: false +allOf: + - if: + properties: + compatible: + contains: + enum: + - google,cros-ec-i2c + - google,cros-ec-rpmsg + then: + properties: + google,cros-ec-spi-pre-delay: false + google,cros-ec-spi-msg-delay: false + spi-max-frequency: false + else: + $ref: /schemas/spi/spi-peripheral-props.yaml additionalProperties: false @@ -200,7 +203,7 @@ examples: spi-max-frequency = <5000000>; proximity { - compatible = "google,cros-ec-mkbp-proximity"; + compatible = "google,cros-ec-mkbp-proximity"; }; cbas { diff --git a/Documentation/devicetree/bindings/mfd/max14577.txt b/Documentation/devicetree/bindings/mfd/max14577.txt deleted file mode 100644 index be11943a0560..000000000000 --- a/Documentation/devicetree/bindings/mfd/max14577.txt +++ /dev/null @@ -1,147 +0,0 @@ -Maxim MAX14577/77836 Multi-Function Device - -MAX14577 is a Multi-Function Device with Micro-USB Interface Circuit, Li+ -Battery Charger and SFOUT LDO output for powering USB devices. It is -interfaced to host controller using I2C. - -MAX77836 additionally contains PMIC (with two LDO regulators) and Fuel Gauge. -For the description of Fuel Gauge low SOC alert interrupt see: -../power/supply/max17040_battery.txt - - -Required properties: -- compatible : Must be "maxim,max14577" or "maxim,max77836". -- reg : I2C slave address for the max14577 chip (0x25 for max14577/max77836) -- interrupts : IRQ line for the chip. - - -Required nodes: - - charger : - Node for configuring the charger driver. - Required properties: - - compatible : "maxim,max14577-charger" - or "maxim,max77836-charger" - - maxim,fast-charge-uamp : Current in uA for Fast Charge; - Valid values: - - for max14577: 90000 - 950000; - - for max77836: 45000 - 475000; - - maxim,eoc-uamp : Current in uA for End-Of-Charge mode; - Valid values: - - for max14577: 50000 - 200000; - - for max77836: 5000 - 100000; - - maxim,ovp-uvolt : OverVoltage Protection Threshold in uV; - In an overvoltage condition, INT asserts and charging - stops. Valid values: - - 6000000, 6500000, 7000000, 7500000; - - maxim,constant-uvolt : Battery Constant Voltage in uV; - Valid values: - - 4000000 - 4280000 (step by 20000); - - 4350000; - - -Optional nodes: -- max14577-muic/max77836-muic : - Node used only by extcon consumers. - Required properties: - - compatible : "maxim,max14577-muic" or "maxim,max77836-muic" - -- regulators : - Required properties: - - compatible : "maxim,max14577-regulator" - or "maxim,max77836-regulator" - - May contain a sub-node per regulator from the list below. Each - sub-node should contain the constraints and initialization information - for that regulator. See regulator.txt for a description of standard - properties for these sub-nodes. - - List of valid regulator names: - - for max14577: CHARGER, SAFEOUT. - - for max77836: CHARGER, SAFEOUT, LDO1, LDO2. - - The SAFEOUT is a fixed voltage regulator so there is no need to specify - voltages for it. - - -Example: - -#include <dt-bindings/interrupt-controller/irq.h> - -max14577@25 { - compatible = "maxim,max14577"; - reg = <0x25>; - interrupt-parent = <&gpx1>; - interrupts = <5 IRQ_TYPE_LEVEL_LOW>; - - muic: max14577-muic { - compatible = "maxim,max14577-muic"; - }; - - regulators { - compatible = "maxim,max14577-regulator"; - - SAFEOUT { - regulator-name = "SAFEOUT"; - }; - CHARGER { - regulator-name = "CHARGER"; - regulator-min-microamp = <90000>; - regulator-max-microamp = <950000>; - regulator-boot-on; - }; - }; - - charger { - compatible = "maxim,max14577-charger"; - - maxim,constant-uvolt = <4350000>; - maxim,fast-charge-uamp = <450000>; - maxim,eoc-uamp = <50000>; - maxim,ovp-uvolt = <6500000>; - }; -}; - - -max77836@25 { - compatible = "maxim,max77836"; - reg = <0x25>; - interrupt-parent = <&gpx1>; - interrupts = <5 IRQ_TYPE_LEVEL_LOW>; - - muic: max77836-muic { - compatible = "maxim,max77836-muic"; - }; - - regulators { - compatible = "maxim,max77836-regulator"; - - SAFEOUT { - regulator-name = "SAFEOUT"; - }; - CHARGER { - regulator-name = "CHARGER"; - regulator-min-microamp = <90000>; - regulator-max-microamp = <950000>; - regulator-boot-on; - }; - LDO1 { - regulator-name = "LDO1"; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; - LDO2 { - regulator-name = "LDO2"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <3950000>; - }; - }; - - charger { - compatible = "maxim,max77836-charger"; - - maxim,constant-uvolt = <4350000>; - maxim,fast-charge-uamp = <225000>; - maxim,eoc-uamp = <7500>; - maxim,ovp-uvolt = <6500000>; - }; -}; diff --git a/Documentation/devicetree/bindings/mfd/max77802.txt b/Documentation/devicetree/bindings/mfd/max77802.txt deleted file mode 100644 index 09decac20d91..000000000000 --- a/Documentation/devicetree/bindings/mfd/max77802.txt +++ /dev/null @@ -1,25 +0,0 @@ -Maxim MAX77802 multi-function device - -The Maxim MAX77802 is a Power Management IC (PMIC) that contains 10 high -efficiency Buck regulators, 32 Low-DropOut (LDO) regulators used to power -up application processors and peripherals, a 2-channel 32kHz clock outputs, -a Real-Time-Clock (RTC) and a I2C interface to program the individual -regulators, clocks outputs and the RTC. - -Bindings for the built-in 32k clock generator block and -regulators are defined in ../clk/maxim,max77802.txt and -../regulator/max77802.txt respectively. - -Required properties: -- compatible : Must be "maxim,max77802" -- reg : Specifies the I2C slave address of PMIC block. -- interrupts : I2C device IRQ line connected to the main SoC. - -Example: - - max77802: pmic@9 { - compatible = "maxim,max77802"; - interrupt-parent = <&intc>; - interrupts = <26 IRQ_TYPE_NONE>; - reg = <0x09>; - }; diff --git a/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml b/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml new file mode 100644 index 000000000000..27870b8760a6 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml @@ -0,0 +1,195 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/maxim,max14577.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX14577/MAX77836 MicroUSB and Companion Power Management IC + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX14577/MAX77836 MicroUSB + Integrated Circuit (MUIC). + + The Maxim MAX14577 is a MicroUSB and Companion Power Management IC which + includes voltage safeout regulators, charger and MicroUSB management IC. + + The Maxim MAX77836 is a MicroUSB and Companion Power Management IC which + includes voltage safeout and LDO regulators, charger, fuel-gauge and MicroUSB + management IC. + +properties: + compatible: + enum: + - maxim,max14577 + - maxim,max77836 + + interrupts: + maxItems: 1 + + reg: + maxItems: 1 + + wakeup-source: true + + charger: + $ref: /schemas/power/supply/maxim,max14577.yaml + + extcon: + type: object + properties: + compatible: + enum: + - maxim,max14577-muic + - maxim,max77836-muic + + required: + - compatible + + regulators: + $ref: /schemas/regulator/maxim,max14577.yaml + +required: + - compatible + - interrupts + - reg + - charger + +allOf: + - if: + properties: + compatible: + contains: + const: maxim,max14577 + then: + properties: + charger: + properties: + compatible: + const: maxim,max14577-charger + extcon: + properties: + compatible: + const: maxim,max14577-muic + regulator: + properties: + compatible: + const: maxim,max14577-regulator + else: + properties: + charger: + properties: + compatible: + const: maxim,max77836-charger + extcon: + properties: + compatible: + const: maxim,max77836-muic + regulator: + properties: + compatible: + const: maxim,max77836-regulator + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@25 { + compatible = "maxim,max14577"; + reg = <0x25>; + interrupt-parent = <&gpx1>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + + extcon { + compatible = "maxim,max14577-muic"; + }; + + regulators { + compatible = "maxim,max14577-regulator"; + + SAFEOUT { + regulator-name = "SAFEOUT"; + }; + + CHARGER { + regulator-name = "CHARGER"; + regulator-min-microamp = <90000>; + regulator-max-microamp = <950000>; + regulator-boot-on; + }; + }; + + charger { + compatible = "maxim,max14577-charger"; + + maxim,constant-uvolt = <4350000>; + maxim,fast-charge-uamp = <450000>; + maxim,eoc-uamp = <50000>; + maxim,ovp-uvolt = <6500000>; + }; + }; + }; + + - | + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@25 { + compatible = "maxim,max77836"; + interrupt-parent = <&gpx1>; + interrupts = <5 IRQ_TYPE_NONE>; + reg = <0x25>; + wakeup-source; + + extcon { + compatible = "maxim,max77836-muic"; + }; + + regulators { + compatible = "maxim,max77836-regulator"; + + SAFEOUT { + regulator-name = "SAFEOUT"; + }; + + CHARGER { + regulator-name = "CHARGER"; + regulator-min-microamp = <45000>; + regulator-max-microamp = <475000>; + regulator-boot-on; + }; + + LDO1 { + regulator-name = "MOT_2.7V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <2700000>; + }; + + LDO2 { + regulator-name = "UNUSED_LDO2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + }; + + charger { + compatible = "maxim,max77836-charger"; + + maxim,constant-uvolt = <4350000>; + maxim,fast-charge-uamp = <225000>; + maxim,eoc-uamp = <7500>; + maxim,ovp-uvolt = <6500000>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77802.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77802.yaml new file mode 100644 index 000000000000..baa1346ac5d5 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/maxim,max77802.yaml @@ -0,0 +1,194 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/maxim,max77802.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX77802 Power Management IC + +maintainers: + - Javier Martinez Canillas <javier@dowhile0.org> + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX77802 Power Management + Integrated Circuit (PMIC). + + The Maxim MAX77802 is a Power Management IC which includes voltage and + current regulators (10 high efficiency Buck regulators and 32 Low-DropOut + (LDO)), RTC and clock outputs. + + The MAX77802 provides two 32.768khz clock outputs that can be controlled + (gated/ungated) over I2C. The clock IDs are defined as preprocessor macros + in dt-bindings/clock/maxim,max77802.h. + +properties: + compatible: + const: maxim,max77802 + + '#clock-cells': + const: 1 + + interrupts: + maxItems: 1 + + reg: + maxItems: 1 + + regulators: + $ref: /schemas/regulator/maxim,max77802.yaml + description: + List of child nodes that specify the regulators. + + inb1-supply: + description: Power supply for buck1 + inb2-supply: + description: Power supply for buck2 + inb3-supply: + description: Power supply for buck3 + inb4-supply: + description: Power supply for buck4 + inb5-supply: + description: Power supply for buck5 + inb6-supply: + description: Power supply for buck6 + inb7-supply: + description: Power supply for buck7 + inb8-supply: + description: Power supply for buck8 + inb9-supply: + description: Power supply for buck9 + inb10-supply: + description: Power supply for buck10 + + inl1-supply: + description: Power supply for LDO8, LDO15 + inl2-supply: + description: Power supply for LDO17, LDO27, LDO30, LDO35 + inl3-supply: + description: Power supply for LDO3, LDO5, LDO7, LDO7 + inl4-supply: + description: Power supply for LDO10, LDO11, LDO13, LDO14 + inl5-supply: + description: Power supply for LDO9, LDO19 + inl6-supply: + description: Power supply for LDO4, LDO21, LDO24, LDO33 + inl7-supply: + description: Power supply for LDO18, LDO20, LDO28, LDO29 + inl9-supply: + description: Power supply for LDO12, LDO23, LDO25, LDO26, LDO32, LDO34 + inl10-supply: + description: Power supply for LDO1, LDO2 + + wakeup-source: true + +required: + - compatible + - '#clock-cells' + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/regulator/maxim,max77802.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@9 { + compatible = "maxim,max77802"; + interrupt-parent = <&gpx3>; + interrupts = <1 IRQ_TYPE_NONE>; + pinctrl-names = "default"; + pinctrl-0 = <&max77802_irq>, <&pmic_selb>, + <&pmic_dvs_1>, <&pmic_dvs_2>, <&pmic_dvs_3>; + wakeup-source; + reg = <0x9>; + #clock-cells = <1>; + + inb1-supply = <&tps65090_dcdc2>; + inb2-supply = <&tps65090_dcdc1>; + inb3-supply = <&tps65090_dcdc2>; + inb4-supply = <&tps65090_dcdc2>; + inb5-supply = <&tps65090_dcdc1>; + inb6-supply = <&tps65090_dcdc2>; + inb7-supply = <&tps65090_dcdc1>; + inb8-supply = <&tps65090_dcdc1>; + inb9-supply = <&tps65090_dcdc1>; + inb10-supply = <&tps65090_dcdc1>; + + inl1-supply = <&buck5_reg>; + inl2-supply = <&buck7_reg>; + inl3-supply = <&buck9_reg>; + inl4-supply = <&buck9_reg>; + inl5-supply = <&buck9_reg>; + inl6-supply = <&tps65090_dcdc2>; + inl7-supply = <&buck9_reg>; + inl9-supply = <&tps65090_dcdc2>; + inl10-supply = <&buck7_reg>; + + regulators { + BUCK1 { + regulator-name = "vdd_mif"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + BUCK2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + regulator-ramp-delay = <12500>; + regulator-coupled-with = <&buck3_reg>; + regulator-coupled-max-spread = <300000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + // ... + + BUCK10 { + regulator-name = "vdd_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + LDO1 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-initial-mode = <MAX77802_OPMODE_NORMAL>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-mode = <MAX77802_OPMODE_LP>; + }; + }; + + // ... + + LDO35 { + regulator-name = "ldo_35"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml new file mode 100644 index 000000000000..61a0f9dcb983 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/maxim,max77843.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX77843 MicroUSB and Companion Power Management IC + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX77843 MicroUSB + Integrated Circuit (MUIC). + + The Maxim MAX77843 is a MicroUSB and Companion Power Management IC which + includes voltage current regulators, charger, fuel-gauge, haptic motor driver + and MicroUSB management IC. + +properties: + compatible: + const: maxim,max77843 + + interrupts: + maxItems: 1 + + reg: + maxItems: 1 + + extcon: + $ref: /schemas/extcon/maxim,max77843.yaml + + motor-driver: + type: object + properties: + compatible: + const: maxim,max77843-haptic + + haptic-supply: + description: Power supply to the haptic motor + + pwms: + maxItems: 1 + + required: + - compatible + - haptic-supply + - pwms + + regulators: + $ref: /schemas/regulator/maxim,max77843.yaml + +required: + - compatible + - interrupts + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@66 { + compatible = "maxim,max77843"; + interrupt-parent = <&gpa1>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + reg = <0x66>; + + extcon { + compatible = "maxim,max77843-muic"; + + connector { + compatible = "samsung,usb-connector-11pin", + "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + /* + * TODO: The DTS this is based on does not have + * port@0 which is a required property. The ports + * look incomplete and need fixing. + * Add a disabled port just to satisfy dtschema. + */ + reg = <0>; + status = "disabled"; + }; + + port@3 { + reg = <3>; + endpoint { + remote-endpoint = <&mhl_to_musb_con>; + }; + }; + }; + }; + + ports { + port { + endpoint { + remote-endpoint = <&usb_to_muic>; + }; + }; + }; + }; + + regulators { + compatible = "maxim,max77843-regulator"; + + SAFEOUT1 { + regulator-name = "SAFEOUT1"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <4950000>; + }; + + SAFEOUT2 { + regulator-name = "SAFEOUT2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <4950000>; + }; + + CHARGER { + regulator-name = "CHARGER"; + regulator-min-microamp = <100000>; + regulator-max-microamp = <3150000>; + }; + }; + + motor-driver { + compatible = "maxim,max77843-haptic"; + haptic-supply = <&ldo38_reg>; + pwms = <&pwm 0 33670 0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml index 39421f7233e4..4abfb4cfc157 100644 --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml @@ -47,7 +47,8 @@ properties: identified by the JEDEC READ ID opcode (0x9F). reg: - maxItems: 1 + minItems: 1 + maxItems: 2 spi-max-frequency: true spi-rx-bus-width: true diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml new file mode 100644 index 000000000000..3978b48299de --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/maxim,max14577.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX14577/MAX77836 MicroUSB and Companion Power Management IC Charger + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX14577/MAX77836 MicroUSB + Integrated Circuit (MUIC). + + See also Documentation/devicetree/bindings/mfd/maxim,max14577.yaml for + additional information and example. + +properties: + compatible: + enum: + - maxim,max14577-charger + - maxim,max77836-charger + + maxim,constant-uvolt: + description: + Battery Constant Voltage in uV + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 4000000 + maximum: 4350000 + + maxim,eoc-uamp: + description: | + Current in uA for End-Of-Charge mode. + MAX14577: 50000-20000 + MAX77836: 5000-100000 + $ref: /schemas/types.yaml#/definitions/uint32 + + maxim,fast-charge-uamp: + description: | + Current in uA for Fast Charge + MAX14577: 90000-950000 + MAX77836: 45000-475000 + $ref: /schemas/types.yaml#/definitions/uint32 + + maxim,ovp-uvolt: + description: + OverVoltage Protection Threshold in uV; In an overvoltage condition, INT + asserts and charging stops. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [6000000, 6500000, 7000000, 7500000] + +required: + - compatible + - maxim,constant-uvolt + - maxim,eoc-uamp + - maxim,fast-charge-uamp + - maxim,ovp-uvolt + +allOf: + - if: + properties: + compatible: + contains: + const: maxim,max14577-charger + then: + properties: + maxim,eoc-uamp: + minimum: 50000 + maximum: 200000 + maxim,fast-charge-uamp: + minimum: 90000 + maximum: 950000 + else: + # max77836 + properties: + maxim,eoc-uamp: + minimum: 5000 + maximum: 100000 + maxim,fast-charge-uamp: + minimum: 45000 + maximum: 475000 + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/max77802.txt b/Documentation/devicetree/bindings/regulator/max77802.txt deleted file mode 100644 index b82943d83677..000000000000 --- a/Documentation/devicetree/bindings/regulator/max77802.txt +++ /dev/null @@ -1,111 +0,0 @@ -Binding for Maxim MAX77802 regulators - -This is a part of device tree bindings of MAX77802 multi-function device. -More information can be found in bindings/mfd/max77802.txt file. - -The MAX77802 PMIC has 10 high-efficiency Buck and 32 Low-dropout (LDO) -regulators that can be controlled over I2C. - -Following properties should be present in main device node of the MFD chip. - -Optional properties: -- inb1-supply: The input supply for BUCK1 -- inb2-supply: The input supply for BUCK2 -- inb3-supply: The input supply for BUCK3 -- inb4-supply: The input supply for BUCK4 -- inb5-supply: The input supply for BUCK5 -- inb6-supply: The input supply for BUCK6 -- inb7-supply: The input supply for BUCK7 -- inb8-supply: The input supply for BUCK8 -- inb9-supply: The input supply for BUCK9 -- inb10-supply: The input supply for BUCK10 -- inl1-supply: The input supply for LDO8 and LDO15 -- inl2-supply: The input supply for LDO17, LDO27, LDO30 and LDO35 -- inl3-supply: The input supply for LDO3, LDO5, LDO6 and LDO7 -- inl4-supply: The input supply for LDO10, LDO11, LDO13 and LDO14 -- inl5-supply: The input supply for LDO9 and LDO19 -- inl6-supply: The input supply for LDO4, LDO21, LDO24 and LDO33 -- inl7-supply: The input supply for LDO18, LDO20, LDO28 and LDO29 -- inl9-supply: The input supply for LDO12, LDO23, LDO25, LDO26, LDO32 and LDO34 -- inl10-supply: The input supply for LDO1 and LDO2 - -Optional nodes: -- regulators : The regulators of max77802 have to be instantiated - under subnode named "regulators" using the following format. - - regulator-name { - standard regulator constraints.... - }; - refer Documentation/devicetree/bindings/regulator/regulator.txt - -The regulator node name should be initialized with a string to get matched -with their hardware counterparts as follow. The valid names are: - - -LDOn : for LDOs, where n can lie in ranges 1-15, 17-21, 23-30 - and 32-35. - example: LDO1, LDO2, LDO35. - -BUCKn : for BUCKs, where n can lie in range 1 to 10. - example: BUCK1, BUCK5, BUCK10. - -The max77802 regulator supports two different operating modes: Normal and Low -Power Mode. Some regulators support the modes to be changed at startup or by -the consumers during normal operation while others only support to change the -mode during system suspend. The standard regulator suspend states binding can -be used to configure the regulator operating mode. - -The regulators that support the standard "regulator-initial-mode" property, -changing their mode during normal operation are: LDOs 1, 3, 20 and 21. - -The possible values for "regulator-initial-mode" and "regulator-mode" are: - 1: Normal regulator voltage output mode. - 3: Low Power which reduces the quiescent current down to only 1uA - -The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h -header and can be included by device tree source files. - -The standard "regulator-mode" property can only be used for regulators that -support changing their mode to Low Power Mode during suspend. These regulators -are: BUCKs 2-4 and LDOs 1-35. Also, it only takes effect if the regulator has -been enabled for the given suspend state using "regulator-on-in-suspend" and -has not been disabled for that state using "regulator-off-in-suspend". - -Example: - - max77802@9 { - compatible = "maxim,max77802"; - interrupt-parent = <&wakeup_eint>; - interrupts = <26 0>; - reg = <0x09>; - #address-cells = <1>; - #size-cells = <0>; - - inb1-supply = <&parent_reg>; - - regulators { - ldo1_reg: LDO1 { - regulator-name = "vdd_1v0"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-always-on; - regulator-initial-mode = <MAX77802_OPMODE_LP>; - }; - - ldo11_reg: LDO11 { - regulator-name = "vdd_ldo11"; - regulator-min-microvolt = <1900000>; - regulator-max-microvolt = <1900000>; - regulator-always-on; - regulator-state-mem { - regulator-on-in-suspend; - regulator-mode = <MAX77802_OPMODE_LP>; - }; - }; - - buck1_reg: BUCK1 { - regulator-name = "vdd_mif"; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1300000>; - regulator-always-on; - regulator-boot-on; - }; - }; diff --git a/Documentation/devicetree/bindings/regulator/maxim,max14577.yaml b/Documentation/devicetree/bindings/regulator/maxim,max14577.yaml new file mode 100644 index 000000000000..16f01886a601 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/maxim,max14577.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/maxim,max14577.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX14577/MAX77836 MicroUSB and Companion Power Management IC regulators + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX14577/MAX77836 MicroUSB + Integrated Circuit (MUIC). + + See also Documentation/devicetree/bindings/mfd/maxim,max14577.yaml for + additional information and example. + +properties: + compatible: + enum: + - maxim,max14577-regulator + - maxim,max77836-regulator + + CHARGER: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: | + Current regulator. + + properties: + regulator-min-microvolt: false + regulator-max-microvolt: false + + SAFEOUT: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: | + Safeout LDO regulator (fixed voltage). + + properties: + regulator-min-microamp: false + regulator-max-microamp: false + regulator-min-microvolt: + const: 4900000 + regulator-max-microvolt: + const: 4900000 + +patternProperties: + "^LDO[12]$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: | + Current regulator. + + properties: + regulator-min-microamp: false + regulator-max-microamp: false + regulator-min-microvolt: + minimum: 800000 + regulator-max-microvolt: + maximum: 3950000 + +allOf: + - if: + properties: + compatible: + contains: + const: maxim,max14577-regulator + then: + properties: + LDO1: false + LDO2: false + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml new file mode 100644 index 000000000000..f2b4dd15a0f3 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/maxim,max77802.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX77802 Power Management IC regulators + +maintainers: + - Javier Martinez Canillas <javier@dowhile0.org> + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX77802 Power Management + Integrated Circuit (PMIC). + + The Maxim MAX77686 provides 10 high-efficiency Buck and 32 Low-DropOut (LDO) + regulators. + + See also Documentation/devicetree/bindings/mfd/maxim,max77802.yaml for + additional information and example. + + Certain regulators support "regulator-initial-mode" and "regulator-mode". + The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h + and their meaning is:: + 1 - Normal regulator voltage output mode. + 3 - Low Power which reduces the quiescent current down to only 1uA + + The standard "regulator-mode" property can only be used for regulators that + support changing their mode to Low Power Mode during suspend. These + regulators are:: bucks 2-4 and LDOs 1-35. Also, it only takes effect if the + regulator has been enabled for the given suspend state using + "regulator-on-in-suspend" and has not been disabled for that state using + "regulator-off-in-suspend". + +patternProperties: + # LDO1, LDO3, LDO20, LDO21 + "^LDO([13]|2[01])$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + LDOs supporting the regulator-initial-mode property and changing their + mode during normal operation. + + # LDO2, LDO4-15, LDO17-19, LDO23-30, LDO32-35 + "^LDO([24-9]|1[0-5789]|2[3-9]|3[02345])$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + LDOs supporting the regulator-mode property (changing mode to Low Power + Mode during suspend). + + properties: + regulator-initial-mode: false + + # buck2-4 + "^BUCK[2-4]$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + bucks supporting the regulator-mode property (changing mode to Low Power + Mode during suspend). + + properties: + regulator-initial-mode: false + + # buck1, buck5-10 + "^BUCK([15-9]|10)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + properties: + regulator-initial-mode: false + + patternProperties: + regulator-state-(standby|mem|disk): + type: object + properties: + regulator-mode: false + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77843.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77843.yaml new file mode 100644 index 000000000000..a963025e96c1 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/maxim,max77843.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/maxim,max77843.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX77843 MicroUSB and Companion Power Management IC regulators + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: | + This is a part of device tree bindings for Maxim MAX77843 MicroUSB Integrated + Circuit (MUIC). + + See also Documentation/devicetree/bindings/mfd/maxim,max77843.yaml for + additional information and example. + +properties: + compatible: + const: maxim,max77843-regulator + + CHARGER: + type: object + $ref: regulator.yaml# + additionalProperties: false + description: | + Current regulator. + + properties: + regulator-name: true + regulator-always-on: true + regulator-boot-on: true + regulator-min-microamp: + minimum: 100000 + regulator-max-microamp: + maximum: 3150000 + + required: + - regulator-name + +patternProperties: + "^SAFEOUT[12]$": + type: object + $ref: regulator.yaml# + additionalProperties: false + description: | + Safeout LDO regulator. + + properties: + regulator-name: true + regulator-always-on: true + regulator-boot-on: true + regulator-min-microvolt: + minimum: 3300000 + regulator-max-microvolt: + maximum: 4950000 + + required: + - regulator-name + +required: + - compatible + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml index 273f2d95a043..e72b6a3fae99 100644 --- a/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml +++ b/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml @@ -22,7 +22,7 @@ description: | [1] Documentation/devicetree/bindings/serial/samsung_uart.yaml [2] Documentation/devicetree/bindings/i2c/i2c-exynos5.txt - [3] Documentation/devicetree/bindings/spi/spi-samsung.txt + [3] Documentation/devicetree/bindings/spi/samsung,spi.yaml properties: $nodename: diff --git a/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml b/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml new file mode 100644 index 000000000000..818130b11bb9 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/mediatek,spi-mt65xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SPI Bus controller for MediaTek ARM SoCs + +maintainers: + - Leilk Liu <leilk.liu@mediatek.com> + +allOf: + - $ref: "/schemas/spi/spi-controller.yaml#" + +properties: + compatible: + oneOf: + - items: + - enum: + - mediatek,mt7629-spi + - const: mediatek,mt7622-spi + - items: + - enum: + - mediatek,mt8516-spi + - const: mediatek,mt2712-spi + - items: + - enum: + - mediatek,mt6779-spi + - mediatek,mt8186-spi + - mediatek,mt8192-spi + - mediatek,mt8195-spi + - const: mediatek,mt6765-spi + - items: + - enum: + - mediatek,mt7986-spi-ipm + - const: mediatek,spi-ipm + - items: + - enum: + - mediatek,mt2701-spi + - mediatek,mt2712-spi + - mediatek,mt6589-spi + - mediatek,mt6765-spi + - mediatek,mt6893-spi + - mediatek,mt7622-spi + - mediatek,mt8135-spi + - mediatek,mt8173-spi + - mediatek,mt8183-spi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: clock used for the parent clock + - description: clock used for the muxes clock + - description: clock used for the clock gate + + clock-names: + items: + - const: parent-clk + - const: sel-clk + - const: spi-clk + + mediatek,pad-select: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 4 + items: + enum: [0, 1, 2, 3] + description: + specify which pins group(ck/mi/mo/cs) spi controller used. + This is an array. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - '#address-cells' + - '#size-cells' + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/mt8173-clk.h> + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + spi@1100a000 { + compatible = "mediatek,mt8173-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1100a000 0x1000>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>; + clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&pericfg CLK_PERI_SPI0>; + clock-names = "parent-clk", "sel-clk", "spi-clk"; + cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>; + mediatek,pad-select = <1>, <0>; + }; diff --git a/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml b/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml index 4e4694e3d539..be3cc7faed53 100644 --- a/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml +++ b/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml @@ -30,6 +30,7 @@ properties: - mediatek,mt7622-nor - mediatek,mt7623-nor - mediatek,mt7629-nor + - mediatek,mt8186-nor - mediatek,mt8192-nor - mediatek,mt8195-nor - enum: @@ -49,6 +50,8 @@ properties: - description: clock used for controller - description: clock used for nor dma bus. this depends on hardware design, so this is optional. + - description: clock used for controller axi slave bus. + this depends on hardware design, so it is optional. clock-names: minItems: 2 @@ -56,6 +59,7 @@ properties: - const: spi - const: sf - const: axi + - const: axi_s required: - compatible diff --git a/Documentation/devicetree/bindings/spi/mediatek,spi-slave-mt27xx.yaml b/Documentation/devicetree/bindings/spi/mediatek,spi-slave-mt27xx.yaml new file mode 100644 index 000000000000..7977799a8ee1 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/mediatek,spi-slave-mt27xx.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/mediatek,spi-slave-mt27xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SPI Slave controller for MediaTek ARM SoCs + +maintainers: + - Leilk Liu <leilk.liu@mediatek.com> + +allOf: + - $ref: "/schemas/spi/spi-controller.yaml#" + +properties: + compatible: + enum: + - mediatek,mt2712-spi-slave + - mediatek,mt8195-spi-slave + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: spi + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/mt2712-clk.h> + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + spi@10013000 { + compatible = "mediatek,mt2712-spi-slave"; + reg = <0x10013000 0x100>; + interrupts = <GIC_SPI 283 IRQ_TYPE_LEVEL_LOW>; + clocks = <&infracfg CLK_INFRA_AO_SPI1>; + clock-names = "spi"; + assigned-clocks = <&topckgen CLK_TOP_SPISLV_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>; + }; diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml new file mode 100644 index 000000000000..ece261b8e963 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/microchip,mpfs-spi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip MPFS {Q,}SPI Controller Device Tree Bindings + +maintainers: + - Conor Dooley <conor.dooley@microchip.com> + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + enum: + - microchip,mpfs-spi + - microchip,mpfs-qspi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clock-names: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include "dt-bindings/clock/microchip,mpfs-clock.h" + spi@20108000 { + compatible = "microchip,mpfs-spi"; + reg = <0x20108000 0x1000>; + clocks = <&clkcfg CLK_SPI0>; + interrupt-parent = <&plic>; + interrupts = <54>; + spi-max-frequency = <25000000>; + }; +... diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml index 35a8045b2c70..0296edd1de22 100644 --- a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml +++ b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml @@ -19,6 +19,7 @@ properties: - nvidia,tegra210-qspi - nvidia,tegra186-qspi - nvidia,tegra194-qspi + - nvidia,tegra234-qspi reg: maxItems: 1 @@ -106,7 +107,7 @@ examples: dma-names = "rx", "tx"; flash@0 { - compatible = "spi-nor"; + compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <104000000>; spi-tx-bus-width = <2>; diff --git a/Documentation/devicetree/bindings/spi/renesas,rspi.yaml b/Documentation/devicetree/bindings/spi/renesas,rspi.yaml index 76e6d9e52fc7..2c3c6bd6ec45 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rspi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rspi.yaml @@ -22,7 +22,8 @@ properties: - renesas,rspi-r7s72100 # RZ/A1H - renesas,rspi-r7s9210 # RZ/A2 - renesas,r9a07g044-rspi # RZ/G2{L,LC} - - const: renesas,rspi-rz # RZ/A and RZ/G2{L,LC} + - renesas,r9a07g054-rspi # RZ/V2L + - const: renesas,rspi-rz - items: - enum: @@ -124,6 +125,7 @@ allOf: enum: - renesas,qspi - renesas,r9a07g044-rspi + - renesas,r9a07g054-rspi then: required: - resets diff --git a/Documentation/devicetree/bindings/spi/samsung,spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/samsung,spi-peripheral-props.yaml new file mode 100644 index 000000000000..f0db3fb3d688 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/samsung,spi-peripheral-props.yaml @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/samsung,spi-peripheral-props.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Peripheral-specific properties for Samsung S3C/S5P/Exynos SoC SPI controller + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: + See spi-peripheral-props.yaml for more info. + +properties: + controller-data: + type: object + additionalProperties: false + + properties: + samsung,spi-feedback-delay: + description: | + The sampling phase shift to be applied on the miso line (to account + for any lag in the miso line). Valid values: + - 0: No phase shift. + - 1: 90 degree phase shift sampling. + - 2: 180 degree phase shift sampling. + - 3: 270 degree phase shift sampling. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + default: 0 + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml new file mode 100644 index 000000000000..bf9a76d931d2 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml @@ -0,0 +1,188 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/samsung,spi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung S3C/S5P/Exynos SoC SPI controller + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +description: + All the SPI controller nodes should be represented in the aliases node using + the following format 'spi{n}' where n is a unique number for the alias. + +properties: + compatible: + oneOf: + - enum: + - samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450 + - samsung,s3c6410-spi + - samsung,s5pv210-spi # for S5PV210 and S5PC110 + - samsung,exynos5433-spi + - tesla,fsd-spi + - const: samsung,exynos7-spi + deprecated: true + + clocks: + minItems: 2 + maxItems: 3 + + clock-names: + minItems: 2 + maxItems: 3 + + cs-gpios: true + + dmas: + minItems: 2 + maxItems: 2 + + dma-names: + items: + - const: tx + - const: rx + + interrupts: + maxItems: 1 + + no-cs-readback: + description: + The CS line is disconnected, therefore the device should not operate + based on CS signalling. + type: boolean + + num-cs: + minimum: 1 + maximum: 4 + default: 1 + + samsung,spi-src-clk: + description: + If the spi controller includes a internal clock mux to select the clock + source for the spi bus clock, this property can be used to indicate the + clock to be used for driving the spi bus clock. If not specified, the + clock number 0 is used as default. + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + + reg: + maxItems: 1 + +required: + - compatible + - clocks + - clock-names + - dmas + - dma-names + - interrupts + - reg + +allOf: + - $ref: spi-controller.yaml# + - if: + properties: + compatible: + contains: + const: samsung,exynos5433-spi + then: + properties: + clocks: + minItems: 3 + maxItems: 3 + clock-names: + items: + - const: spi + - enum: + - spi_busclk0 + - spi_busclk1 + - spi_busclk2 + - spi_busclk3 + - const: spi_ioclk + else: + properties: + clocks: + minItems: 2 + maxItems: 2 + clock-names: + items: + - const: spi + - enum: + - spi_busclk0 + - spi_busclk1 + - spi_busclk2 + - spi_busclk3 + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/exynos5433.h> + #include <dt-bindings/clock/samsung,s2mps11.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/gpio/gpio.h> + + spi@14d30000 { + compatible = "samsung,exynos5433-spi"; + reg = <0x14d30000 0x100>; + interrupts = <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&pdma0 11>, <&pdma0 10>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_peric CLK_PCLK_SPI1>, + <&cmu_peric CLK_SCLK_SPI1>, + <&cmu_peric CLK_SCLK_IOCLK_SPI1>; + clock-names = "spi", + "spi_busclk0", + "spi_ioclk"; + samsung,spi-src-clk = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_bus>; + num-cs = <1>; + + cs-gpios = <&gpd6 3 GPIO_ACTIVE_HIGH>; + + audio-codec@0 { + compatible = "wlf,wm5110"; + reg = <0x0>; + spi-max-frequency = <20000000>; + interrupt-parent = <&gpa0>; + interrupts = <4 IRQ_TYPE_NONE>; + clocks = <&pmu_system_controller 0>, + <&s2mps13_osc S2MPS11_CLK_BT>; + clock-names = "mclk1", "mclk2"; + + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + + wlf,micd-detect-debounce = <300>; + wlf,micd-bias-start-time = <0x1>; + wlf,micd-rate = <0x7>; + wlf,micd-dbtime = <0x2>; + wlf,micd-force-micbias; + wlf,micd-configs = <0x0 1 0>; + wlf,hpdet-channel = <1>; + wlf,gpsw = <0x1>; + wlf,inmode = <2 0 2 0>; + + wlf,reset = <&gpc0 7 GPIO_ACTIVE_HIGH>; + wlf,ldoena = <&gpf0 0 GPIO_ACTIVE_HIGH>; + + /* core supplies */ + AVDD-supply = <&ldo18_reg>; + DBVDD1-supply = <&ldo18_reg>; + CPVDD-supply = <&ldo18_reg>; + DBVDD2-supply = <&ldo18_reg>; + DBVDD3-supply = <&ldo18_reg>; + SPKVDDL-supply = <&ldo18_reg>; + SPKVDDR-supply = <&ldo18_reg>; + + controller-data { + samsung,spi-feedback-delay = <0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml index 36b72518f565..0f4d40218400 100644 --- a/Documentation/devicetree/bindings/spi/spi-controller.yaml +++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml @@ -139,4 +139,11 @@ examples: spi-max-frequency = <100000>; reg = <1>; }; + + flash@2 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + reg = <2>, <3>; + stacked-memories = /bits/ 64 <0x10000000 0x10000000>; + }; }; diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt deleted file mode 100644 index 2a24969159cc..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt +++ /dev/null @@ -1,68 +0,0 @@ -Binding for MTK SPI controller - -Required properties: -- compatible: should be one of the following. - - mediatek,mt2701-spi: for mt2701 platforms - - mediatek,mt2712-spi: for mt2712 platforms - - mediatek,mt6589-spi: for mt6589 platforms - - mediatek,mt6765-spi: for mt6765 platforms - - mediatek,mt7622-spi: for mt7622 platforms - - "mediatek,mt7629-spi", "mediatek,mt7622-spi": for mt7629 platforms - - mediatek,mt8135-spi: for mt8135 platforms - - mediatek,mt8173-spi: for mt8173 platforms - - mediatek,mt8183-spi: for mt8183 platforms - - mediatek,mt6893-spi: for mt6893 platforms - - "mediatek,mt8192-spi", "mediatek,mt6765-spi": for mt8192 platforms - - "mediatek,mt8195-spi", "mediatek,mt6765-spi": for mt8195 platforms - - "mediatek,mt8516-spi", "mediatek,mt2712-spi": for mt8516 platforms - - "mediatek,mt6779-spi", "mediatek,mt6765-spi": for mt6779 platforms - -- #address-cells: should be 1. - -- #size-cells: should be 0. - -- reg: Address and length of the register set for the device - -- interrupts: Should contain spi interrupt - -- clocks: phandles to input clocks. - The first should be one of the following. It's PLL. - - <&clk26m>: specify parent clock 26MHZ. - - <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ. - It's the default one. - - <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ. - - <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ. - - <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ. - The second should be <&topckgen CLK_TOP_SPI_SEL>. It's clock mux. - The third is <&pericfg CLK_PERI_SPI0>. It's clock gate. - -- clock-names: shall be "parent-clk" for the parent clock, "sel-clk" for the - muxes clock, and "spi-clk" for the clock gate. - -Optional properties: --cs-gpios: see spi-bus.txt. - -- mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi - controller used. This is an array, the element value should be 0~3, - only required for MT8173. - 0: specify GPIO69,70,71,72 for spi pins. - 1: specify GPIO102,103,104,105 for spi pins. - 2: specify GPIO128,129,130,131 for spi pins. - 3: specify GPIO5,6,7,8 for spi pins. - -Example: - -- SoC Specific Portion: -spi: spi@1100a000 { - compatible = "mediatek,mt8173-spi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100a000 0 0x1000>; - interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>; - clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&pericfg CLK_PERI_SPI0>; - clock-names = "parent-clk", "sel-clk", "spi-clk"; - cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>; - mediatek,pad-select = <1>, <0>; -}; diff --git a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml index 283815d59e85..1b552c298277 100644 --- a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml +++ b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml @@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: NXP Flex Serial Peripheral Interface (FSPI) maintainers: - - Kuldeep Singh <kuldeep.singh@nxp.com> + - Han Xu <han.xu@nxp.com> + - Kuldeep Singh <singh.kuldeep87k@gmail.com> allOf: - $ref: "spi-controller.yaml#" diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml index 3ec2d7b83775..5e32928c4fc3 100644 --- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml +++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml @@ -83,8 +83,34 @@ properties: description: Delay, in microseconds, after a write transfer. + stacked-memories: + description: Several SPI memories can be wired in stacked mode. + This basically means that either a device features several chip + selects, or that different devices must be seen as a single + bigger chip. This basically doubles (or more) the total address + space with only a single additional wire, while still needing + to repeat the commands when crossing a chip boundary. The size of + each chip should be provided as members of the array. + $ref: /schemas/types.yaml#/definitions/uint64-array + minItems: 2 + maxItems: 4 + + parallel-memories: + description: Several SPI memories can be wired in parallel mode. + The devices are physically on a different buses but will always + act synchronously as each data word is spread across the + different memories (eg. even bits are stored in one memory, odd + bits in the other). This basically doubles the address space and + the throughput while greatly complexifying the wiring because as + many busses as devices must be wired. The size of each chip should + be provided as members of the array. + $ref: /schemas/types.yaml#/definitions/uint64-array + minItems: 2 + maxItems: 4 + # The controller specific properties go here. allOf: - $ref: cdns,qspi-nor-peripheral-props.yaml# + - $ref: samsung,spi-peripheral-props.yaml# additionalProperties: true diff --git a/Documentation/devicetree/bindings/spi/spi-pl022.yaml b/Documentation/devicetree/bindings/spi/spi-pl022.yaml index 6d633728fc2b..bda45ff3d294 100644 --- a/Documentation/devicetree/bindings/spi/spi-pl022.yaml +++ b/Documentation/devicetree/bindings/spi/spi-pl022.yaml @@ -38,9 +38,7 @@ properties: clock-names: items: - - enum: - - SSPCLK - - sspclk + - const: sspclk - const: apb_pclk pl022,autosuspend-delay: diff --git a/Documentation/devicetree/bindings/spi/spi-samsung.txt b/Documentation/devicetree/bindings/spi/spi-samsung.txt deleted file mode 100644 index 49028a4f5df1..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-samsung.txt +++ /dev/null @@ -1,122 +0,0 @@ -* Samsung SPI Controller - -The Samsung SPI controller is used to interface with various devices such as flash -and display controllers using the SPI communication interface. - -Required SoC Specific Properties: - -- compatible: should be one of the following. - - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms - - samsung,s3c6410-spi: for s3c6410 platforms - - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms - - samsung,exynos5433-spi: for exynos5433 compatible controllers - - samsung,exynos7-spi: for exynos7 platforms <DEPRECATED> - -- reg: physical base address of the controller and length of memory mapped - region. - -- interrupts: The interrupt number to the cpu. The interrupt specifier format - depends on the interrupt controller. - -- dmas : Two or more DMA channel specifiers following the convention outlined - in bindings/dma/dma.txt - -- dma-names: Names for the dma channels. There must be at least one channel - named "tx" for transmit and named "rx" for receive. - -- clocks: specifies the clock IDs provided to the SPI controller; they are - required for interacting with the controller itself, for synchronizing the bus - and as I/O clock (the latter is required by exynos5433 and exynos7). - -- clock-names: string names of the clocks in the 'clocks' property; for all the - the devices the names must be "spi", "spi_busclkN" (where N is determined by - "samsung,spi-src-clk"), while Exynos5433 should specify a third clock - "spi_ioclk" for the I/O clock. - -Required Board Specific Properties: - -- #address-cells: should be 1. -- #size-cells: should be 0. - -Optional Board Specific Properties: - -- samsung,spi-src-clk: If the spi controller includes a internal clock mux to - select the clock source for the spi bus clock, this property can be used to - indicate the clock to be used for driving the spi bus clock. If not specified, - the clock number 0 is used as default. - -- num-cs: Specifies the number of chip select lines supported. If - not specified, the default number of chip select lines is set to 1. - -- cs-gpios: should specify GPIOs used for chipselects (see spi-bus.txt) - -- no-cs-readback: the CS line is disconnected, therefore the device should not - operate based on CS signalling. - -SPI Controller specific data in SPI slave nodes: - -- The spi slave nodes should provide the following information which is required - by the spi controller. - - - samsung,spi-feedback-delay: The sampling phase shift to be applied on the - miso line (to account for any lag in the miso line). The following are the - valid values. - - - 0: No phase shift. - - 1: 90 degree phase shift sampling. - - 2: 180 degree phase shift sampling. - - 3: 270 degree phase shift sampling. - -Aliases: - -- All the SPI controller nodes should be represented in the aliases node using - the following format 'spi{n}' where n is a unique number for the alias. - - -Example: - -- SoC Specific Portion: - - spi_0: spi@12d20000 { - compatible = "samsung,exynos4210-spi"; - reg = <0x12d20000 0x100>; - interrupts = <0 66 0>; - dmas = <&pdma0 5 - &pdma0 4>; - dma-names = "tx", "rx"; - #address-cells = <1>; - #size-cells = <0>; - }; - -- Board Specific Portion: - - spi_0: spi@12d20000 { - #address-cells = <1>; - #size-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&spi0_bus>; - cs-gpios = <&gpa2 5 0>; - - w25q80bw@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "w25x80"; - reg = <0>; - spi-max-frequency = <10000>; - - controller-data { - samsung,spi-feedback-delay = <0>; - }; - - partition@0 { - label = "U-Boot"; - reg = <0x0 0x40000>; - read-only; - }; - - partition@40000 { - label = "Kernel"; - reg = <0x40000 0xc0000>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt b/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt deleted file mode 100644 index 9192724540fd..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt +++ /dev/null @@ -1,33 +0,0 @@ -Binding for MTK SPI Slave controller - -Required properties: -- compatible: should be one of the following. - - mediatek,mt2712-spi-slave: for mt2712 platforms - - mediatek,mt8195-spi-slave: for mt8195 platforms -- reg: Address and length of the register set for the device. -- interrupts: Should contain spi interrupt. -- clocks: phandles to input clocks. - It's clock gate, and should be <&infracfg CLK_INFRA_AO_SPI1>. -- clock-names: should be "spi" for the clock gate. - -Optional properties: -- assigned-clocks: it's mux clock, should be <&topckgen CLK_TOP_SPISLV_SEL>. -- assigned-clock-parents: parent of mux clock. - It's PLL, and should be one of the following. - - <&topckgen CLK_TOP_UNIVPLL1_D2>: specify parent clock 312MHZ. - It's the default one. - - <&topckgen CLK_TOP_UNIVPLL1_D4>: specify parent clock 156MHZ. - - <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ. - - <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ. - -Example: -- SoC Specific Portion: -spis1: spi@10013000 { - compatible = "mediatek,mt2712-spi-slave"; - reg = <0 0x10013000 0 0x100>; - interrupts = <GIC_SPI 283 IRQ_TYPE_LEVEL_LOW>; - clocks = <&infracfg CLK_INFRA_AO_SPI1>; - clock-names = "spi"; - assigned-clocks = <&topckgen CLK_TOP_SPISLV_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>; -}; diff --git a/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml b/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml new file mode 100644 index 000000000000..3a58cf0f1ec8 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright (C) Sunplus Co., Ltd. 2021 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/spi-sunplus-sp7021.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sunplus sp7021 SPI controller + +allOf: + - $ref: "spi-controller.yaml" + +maintainers: + - Li-hao Kuo <lhjeff911@gmail.com> + +properties: + compatible: + enum: + - sunplus,sp7021-spi + + reg: + items: + - description: the SPI master registers + - description: the SPI slave registers + + reg-names: + items: + - const: master + - const: slave + + interrupt-names: + items: + - const: dma_w + - const: master_risc + - const: slave_risc + + interrupts: + minItems: 3 + + clocks: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - clocks + - resets + - pinctrl-names + - pinctrl-0 + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + spi@9C002D80 { + compatible = "sunplus,sp7021-spi"; + reg = <0x9C002D80 0x80>, <0x9C002E00 0x80>; + reg-names = "master", "slave"; + interrupt-parent = <&intc>; + interrupt-names = "dma_w", + "master_risc", + "slave_risc"; + interrupts = <144 IRQ_TYPE_LEVEL_HIGH>, + <146 IRQ_TYPE_LEVEL_HIGH>, + <145 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 0x32>; + resets = <&rstc 0x22>; + pinctrl-names = "default"; + pinctrl-0 = <&pins_spi0>; + }; +... diff --git a/Documentation/driver-api/mtd/index.rst b/Documentation/driver-api/mtd/index.rst index 436ba5a851d7..6a4278f409d7 100644 --- a/Documentation/driver-api/mtd/index.rst +++ b/Documentation/driver-api/mtd/index.rst @@ -7,6 +7,6 @@ Memory Technology Device (MTD) .. toctree:: :maxdepth: 1 - intel-spi + spi-intel nand_ecc spi-nor diff --git a/Documentation/driver-api/mtd/intel-spi.rst b/Documentation/driver-api/mtd/spi-intel.rst index 0465f6879262..df854f20ead1 100644 --- a/Documentation/driver-api/mtd/intel-spi.rst +++ b/Documentation/driver-api/mtd/spi-intel.rst @@ -1,5 +1,5 @@ ============================== -Upgrading BIOS using intel-spi +Upgrading BIOS using spi-intel ============================== Many Intel CPUs like Baytrail and Braswell include SPI serial flash host @@ -11,12 +11,12 @@ avoid accidental (or on purpose) overwrite of the content. Not all manufacturers protect the SPI serial flash, mainly because it allows upgrading the BIOS image directly from an OS. -The intel-spi driver makes it possible to read and write the SPI serial +The spi-intel driver makes it possible to read and write the SPI serial flash, if certain protection bits are not set and locked. If it finds any of them set, the whole MTD device is made read-only to prevent partial overwrites. By default the driver exposes SPI serial flash contents as read-only but it can be changed from kernel command line, -passing "intel-spi.writeable=1". +passing "spi_intel.writeable=1". Please keep in mind that overwriting the BIOS image on SPI serial flash might render the machine unbootable and requires special equipment like @@ -32,7 +32,7 @@ Linux. serial flash. Distros like Debian and Fedora have this prepackaged with name "mtd-utils". - 3) Add "intel-spi.writeable=1" to the kernel command line and reboot + 3) Add "spi_intel.writeable=1" to the kernel command line and reboot the board (you can also reload the driver passing "writeable=1" as module parameter to modprobe). diff --git a/Documentation/spi/pxa2xx.rst b/Documentation/spi/pxa2xx.rst index 6347580826be..716f65d87d04 100644 --- a/Documentation/spi/pxa2xx.rst +++ b/Documentation/spi/pxa2xx.rst @@ -101,7 +101,6 @@ device. All fields are optional. u8 rx_threshold; u8 dma_burst_size; u32 timeout; - int gpio_cs; }; The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are @@ -146,7 +145,6 @@ field. Below is a sample configuration using the PXA255 NSSP. .rx_threshold = 8, /* SSP hardward FIFO threshold */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ .timeout = 235, /* See Intel documentation */ - .gpio_cs = 2, /* Use external chip select */ }; static struct pxa2xx_spi_chip cs8405a_chip_info = { @@ -154,7 +152,6 @@ field. Below is a sample configuration using the PXA255 NSSP. .rx_threshold = 8, /* SSP hardward FIFO threshold */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ .timeout = 235, /* See Intel documentation */ - .gpio_cs = 3, /* Use external chip select */ }; static struct spi_board_info streetracer_spi_board_info[] __initdata = { diff --git a/MAINTAINERS b/MAINTAINERS index b4688b0d04f2..b986a7b9bfef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11730,7 +11730,7 @@ MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER M: Javier Martinez Canillas <javier@dowhile0.org> L: linux-kernel@vger.kernel.org S: Supported -F: Documentation/devicetree/bindings/*/*max77802.txt +F: Documentation/devicetree/bindings/*/*max77802.yaml F: drivers/regulator/max77802-regulator.c F: include/dt-bindings/*/*max77802.h @@ -11745,6 +11745,7 @@ M: Krzysztof Kozlowski <krzk@kernel.org> M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> L: linux-pm@vger.kernel.org S: Supported +F: Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml F: drivers/power/supply/max14577_charger.c F: drivers/power/supply/max77693_charger.c @@ -11754,10 +11755,12 @@ M: Krzysztof Kozlowski <krzk@kernel.org> M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> L: linux-kernel@vger.kernel.org S: Supported +F: Documentation/devicetree/bindings/*/maxim,max14577.yaml F: Documentation/devicetree/bindings/*/maxim,max77686.yaml +F: Documentation/devicetree/bindings/*/maxim,max77843.yaml F: Documentation/devicetree/bindings/clock/maxim,max77686.txt -F: Documentation/devicetree/bindings/mfd/max14577.txt F: Documentation/devicetree/bindings/mfd/max77693.txt +F: drivers/*/*max77843.c F: drivers/*/max14577*.c F: drivers/*/max77686*.c F: drivers/*/max77693*.c @@ -17140,7 +17143,7 @@ M: Andi Shyti <andi@etezian.org> L: linux-spi@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/spi/spi-samsung.txt +F: Documentation/devicetree/bindings/spi/samsung,spi*.yaml F: drivers/spi/spi-s3c* F: include/linux/platform_data/spi-s3c64xx.h F: include/linux/spi/s3c24xx-fiq.h @@ -18560,6 +18563,13 @@ S: Maintained F: Documentation/devicetree/bindings/rtc/sunplus,sp7021-rtc.yaml F: drivers/rtc/rtc-sunplus.c +SUNPLUS SPI CONTROLLER INTERFACE DRIVER +M: Li-hao Kuo <lhjeff911@gmail.com> +L: linux-spi@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml +F: drivers/spi/spi-sunplus-sp7021.c + SUPERH M: Yoshinori Sato <ysato@users.sourceforge.jp> M: Rich Felker <dalias@libc.org> diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 593c7f793da5..44659fbc37ba 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -530,6 +530,16 @@ static struct pxa2xx_spi_controller corgi_spi_info = { .num_chipselect = 3, }; +static struct gpiod_lookup_table corgi_spi_gpio_table = { + .dev_id = "pxa2xx-spi.1", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_ADS7846_CS, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_LCDCON_CS, "cs", 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_MAX1111_CS, "cs", 2, GPIO_ACTIVE_LOW), + { }, + }, +}; + static void corgi_wait_for_hsync(void) { while (gpio_get_value(CORGI_GPIO_HSYNC)) @@ -548,10 +558,6 @@ static struct ads7846_platform_data corgi_ads7846_info = { .wait_for_sync = corgi_wait_for_hsync, }; -static struct pxa2xx_spi_chip corgi_ads7846_chip = { - .gpio_cs = CORGI_GPIO_ADS7846_CS, -}; - static void corgi_bl_kick_battery(void) { void (*kick_batt)(void); @@ -580,14 +586,6 @@ static struct corgi_lcd_platform_data corgi_lcdcon_info = { .kick_battery = corgi_bl_kick_battery, }; -static struct pxa2xx_spi_chip corgi_lcdcon_chip = { - .gpio_cs = CORGI_GPIO_LCDCON_CS, -}; - -static struct pxa2xx_spi_chip corgi_max1111_chip = { - .gpio_cs = CORGI_GPIO_MAX1111_CS, -}; - static struct spi_board_info corgi_spi_devices[] = { { .modalias = "ads7846", @@ -595,7 +593,6 @@ static struct spi_board_info corgi_spi_devices[] = { .bus_num = 1, .chip_select = 0, .platform_data = &corgi_ads7846_info, - .controller_data= &corgi_ads7846_chip, .irq = PXA_GPIO_TO_IRQ(CORGI_GPIO_TP_INT), }, { .modalias = "corgi-lcd", @@ -603,18 +600,17 @@ static struct spi_board_info corgi_spi_devices[] = { .bus_num = 1, .chip_select = 1, .platform_data = &corgi_lcdcon_info, - .controller_data= &corgi_lcdcon_chip, }, { .modalias = "max1111", .max_speed_hz = 450000, .bus_num = 1, .chip_select = 2, - .controller_data= &corgi_max1111_chip, }, }; static void __init corgi_init_spi(void) { + gpiod_add_lookup_table(&corgi_spi_gpio_table); pxa2xx_set_spi_info(1, &corgi_spi_info); gpiod_add_lookup_table(&corgi_lcdcon_gpio_table); spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices)); diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 1d4c5db54be2..e1870fbb19e7 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -616,7 +616,6 @@ static struct pxa2xx_spi_chip tsc2046_chip = { .tx_threshold = 1, .rx_threshold = 2, .timeout = 64, - .gpio_cs = GPIO88_HX4700_TSC2046_CS, }; static struct spi_board_info tsc2046_board_info[] __initdata = { @@ -635,6 +634,14 @@ static struct pxa2xx_spi_controller pxa_ssp2_master_info = { .enable_dma = 1, }; +static struct gpiod_lookup_table pxa_ssp2_gpio_table = { + .dev_id = "pxa2xx-spi.2", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", GPIO88_HX4700_TSC2046_CS, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + /* * External power */ @@ -896,6 +903,7 @@ static void __init hx4700_init(void) pxa_set_i2c_info(NULL); i2c_register_board_info(0, ARRAY_AND_SIZE(i2c_board_info)); i2c_register_board_info(1, ARRAY_AND_SIZE(pi2c_board_info)); + gpiod_add_lookup_table(&pxa_ssp2_gpio_table); pxa2xx_set_spi_info(2, &pxa_ssp2_master_info); spi_register_board_info(ARRAY_AND_SIZE(tsc2046_board_info)); diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index 04a12523cdee..753fe166ab68 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -13,7 +13,7 @@ #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/property.h> -#include <linux/gpio.h> +#include <linux/gpio/machine.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -42,7 +42,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info1 = { .rx_threshold = 128, .dma_burst_size = 8, .timeout = 235, - .gpio_cs = ICONTROL_MCP251x_nCS1 }; static struct pxa2xx_spi_chip mcp251x_chip_info2 = { @@ -50,7 +49,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info2 = { .rx_threshold = 128, .dma_burst_size = 8, .timeout = 235, - .gpio_cs = ICONTROL_MCP251x_nCS2 }; static struct pxa2xx_spi_chip mcp251x_chip_info3 = { @@ -58,7 +56,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info3 = { .rx_threshold = 128, .dma_burst_size = 8, .timeout = 235, - .gpio_cs = ICONTROL_MCP251x_nCS3 }; static struct pxa2xx_spi_chip mcp251x_chip_info4 = { @@ -66,7 +63,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = { .rx_threshold = 128, .dma_burst_size = 8, .timeout = 235, - .gpio_cs = ICONTROL_MCP251x_nCS4 }; static const struct property_entry mcp251x_properties[] = { @@ -143,6 +139,24 @@ struct platform_device pxa_spi_ssp4 = { } }; +static struct gpiod_lookup_table pxa_ssp3_gpio_table = { + .dev_id = "pxa2xx-spi.3", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS1, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS2, "cs", 1, GPIO_ACTIVE_LOW), + { }, + }, +}; + +static struct gpiod_lookup_table pxa_ssp4_gpio_table = { + .dev_id = "pxa2xx-spi.4", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS3, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS4, "cs", 1, GPIO_ACTIVE_LOW), + { }, + }, +}; + static struct platform_device *icontrol_spi_devices[] __initdata = { &pxa_spi_ssp3, &pxa_spi_ssp4, @@ -175,6 +189,8 @@ static mfp_cfg_t mfp_can_cfg[] __initdata = { static void __init icontrol_can_init(void) { pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_can_cfg)); + gpiod_add_lookup_table(&pxa_ssp3_gpio_table); + gpiod_add_lookup_table(&pxa_ssp4_gpio_table); platform_add_devices(ARRAY_AND_SIZE(icontrol_spi_devices)); spi_register_board_info(ARRAY_AND_SIZE(mcp251x_board_info)); } diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 793f61375ee8..73f5953b3bb6 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -195,7 +195,6 @@ static struct pxa2xx_spi_controller littleton_spi_info = { static struct pxa2xx_spi_chip littleton_tdo24m_chip = { .rx_threshold = 1, .tx_threshold = 1, - .gpio_cs = LITTLETON_GPIO_LCD_CS, }; static struct spi_board_info littleton_spi_devices[] __initdata = { @@ -208,8 +207,17 @@ static struct spi_board_info littleton_spi_devices[] __initdata = { }, }; +static struct gpiod_lookup_table littleton_spi_gpio_table = { + .dev_id = "pxa2xx-spi.2", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", LITTLETON_GPIO_LCD_CS, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + static void __init littleton_init_spi(void) { + gpiod_add_lookup_table(&littleton_spi_gpio_table); pxa2xx_set_spi_info(2, &littleton_spi_info); spi_register_board_info(ARRAY_AND_SIZE(littleton_spi_devices)); } diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index cd9fa465b9b2..200fd35168e0 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -938,8 +938,6 @@ struct pxa2xx_spi_chip tsc2046_chip_info = { .tx_threshold = 1, .rx_threshold = 2, .timeout = 64, - /* NOTICE must be GPIO, incompatibility with hw PXA SPI framing */ - .gpio_cs = GPIO14_MAGICIAN_TSC2046_CS, }; static struct pxa2xx_spi_controller magician_spi_info = { @@ -947,6 +945,15 @@ static struct pxa2xx_spi_controller magician_spi_info = { .enable_dma = 1, }; +static struct gpiod_lookup_table magician_spi_gpio_table = { + .dev_id = "pxa2xx-spi.2", + .table = { + /* NOTICE must be GPIO, incompatibility with hw PXA SPI framing */ + GPIO_LOOKUP_IDX("gpio-pxa", GPIO14_MAGICIAN_TSC2046_CS, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + static struct spi_board_info ads7846_spi_board_info[] __initdata = { { .modalias = "ads7846", @@ -1031,6 +1038,7 @@ static void __init magician_init(void) } else pr_err("LCD detection: CPLD mapping failed\n"); + gpiod_add_lookup_table(&magician_spi_gpio_table); pxa2xx_set_spi_info(2, &magician_spi_info); spi_register_board_info(ARRAY_AND_SIZE(ads7846_spi_board_info)); diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 3a4ecc3c8f8b..58cfa434afde 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -197,6 +197,14 @@ static struct pxa2xx_spi_controller poodle_spi_info = { .num_chipselect = 1, }; +static struct gpiod_lookup_table poodle_spi_gpio_table = { + .dev_id = "pxa2xx-spi.1", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", POODLE_GPIO_TP_CS, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + static struct ads7846_platform_data poodle_ads7846_info = { .model = 7846, .vref_delay_usecs = 100, @@ -205,23 +213,19 @@ static struct ads7846_platform_data poodle_ads7846_info = { .gpio_pendown = POODLE_GPIO_TP_INT, }; -static struct pxa2xx_spi_chip poodle_ads7846_chip = { - .gpio_cs = POODLE_GPIO_TP_CS, -}; - static struct spi_board_info poodle_spi_devices[] = { { .modalias = "ads7846", .max_speed_hz = 10000, .bus_num = 1, .platform_data = &poodle_ads7846_info, - .controller_data= &poodle_ads7846_chip, .irq = PXA_GPIO_TO_IRQ(POODLE_GPIO_TP_INT), }, }; static void __init poodle_init_spi(void) { + gpiod_add_lookup_table(&poodle_spi_gpio_table); pxa2xx_set_spi_info(1, &poodle_spi_info); spi_register_board_info(ARRAY_AND_SIZE(poodle_spi_devices)); } diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 371008e9bb02..a648e7094e84 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -510,10 +510,6 @@ static struct ads7846_platform_data spitz_ads7846_info = { .wait_for_sync = spitz_ads7846_wait_for_hsync, }; -static struct pxa2xx_spi_chip spitz_ads7846_chip = { - .gpio_cs = SPITZ_GPIO_ADS7846_CS, -}; - static void spitz_bl_kick_battery(void) { void (*kick_batt)(void); @@ -555,14 +551,6 @@ static struct corgi_lcd_platform_data spitz_lcdcon_info = { .kick_battery = spitz_bl_kick_battery, }; -static struct pxa2xx_spi_chip spitz_lcdcon_chip = { - .gpio_cs = SPITZ_GPIO_LCDCON_CS, -}; - -static struct pxa2xx_spi_chip spitz_max1111_chip = { - .gpio_cs = SPITZ_GPIO_MAX1111_CS, -}; - static struct spi_board_info spitz_spi_devices[] = { { .modalias = "ads7846", @@ -570,7 +558,6 @@ static struct spi_board_info spitz_spi_devices[] = { .bus_num = 2, .chip_select = 0, .platform_data = &spitz_ads7846_info, - .controller_data = &spitz_ads7846_chip, .irq = PXA_GPIO_TO_IRQ(SPITZ_GPIO_TP_INT), }, { .modalias = "corgi-lcd", @@ -578,13 +565,11 @@ static struct spi_board_info spitz_spi_devices[] = { .bus_num = 2, .chip_select = 1, .platform_data = &spitz_lcdcon_info, - .controller_data = &spitz_lcdcon_chip, }, { .modalias = "max1111", .max_speed_hz = 450000, .bus_num = 2, .chip_select = 2, - .controller_data = &spitz_max1111_chip, }, }; @@ -592,6 +577,16 @@ static struct pxa2xx_spi_controller spitz_spi_info = { .num_chipselect = 3, }; +static struct gpiod_lookup_table spitz_spi_gpio_table = { + .dev_id = "pxa2xx-spi.2", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_ADS7846_CS, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_LCDCON_CS, "cs", 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_MAX1111_CS, "cs", 2, GPIO_ACTIVE_LOW), + { }, + }, +}; + static void __init spitz_spi_init(void) { if (machine_is_akita()) @@ -599,6 +594,7 @@ static void __init spitz_spi_init(void) else gpiod_add_lookup_table(&spitz_lcdcon_gpio_table); + gpiod_add_lookup_table(&spitz_spi_gpio_table); pxa2xx_set_spi_info(2, &spitz_spi_info); spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices)); } diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index 8ca02ec1d44c..b43e2f4536a5 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -346,6 +346,22 @@ static struct pxa2xx_spi_controller pxa_ssp_master_2_info = { .num_chipselect = 1, }; +static struct gpiod_lookup_table pxa_ssp1_gpio_table = { + .dev_id = "pxa2xx-spi.1", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", 24, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + +static struct gpiod_lookup_table pxa_ssp3_gpio_table = { + .dev_id = "pxa2xx-spi.3", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", 39, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + /* An upcoming kernel change will scrap SFRM usage so these * drivers have been moved to use GPIOs */ static struct pxa2xx_spi_chip staccel_chip_info = { @@ -353,7 +369,6 @@ static struct pxa2xx_spi_chip staccel_chip_info = { .rx_threshold = 8, .dma_burst_size = 8, .timeout = 235, - .gpio_cs = 24, }; static struct pxa2xx_spi_chip cc2420_info = { @@ -361,7 +376,6 @@ static struct pxa2xx_spi_chip cc2420_info = { .rx_threshold = 8, .dma_burst_size = 8, .timeout = 235, - .gpio_cs = 39, }; static struct spi_board_info spi_board_info[] __initdata = { @@ -410,6 +424,8 @@ static void __init imote2_stargate2_init(void) pxa_set_btuart_info(NULL); pxa_set_stuart_info(NULL); + gpiod_add_lookup_table(&pxa_ssp1_gpio_table); + gpiod_add_lookup_table(&pxa_ssp3_gpio_table); pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info); pxa2xx_set_spi_info(2, &pxa_ssp_master_1_info); pxa2xx_set_spi_info(3, &pxa_ssp_master_2_info); diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index 8e74fbb0a96e..7eaeda269927 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -570,7 +570,6 @@ static struct pxa2xx_spi_chip z2_lbs_chip_info = { .rx_threshold = 8, .tx_threshold = 8, .timeout = 1000, - .gpio_cs = GPIO24_ZIPITZ2_WIFI_CS, }; static struct libertas_spi_platform_data z2_lbs_pdata = { @@ -584,7 +583,6 @@ static struct pxa2xx_spi_chip lms283_chip_info = { .rx_threshold = 1, .tx_threshold = 1, .timeout = 64, - .gpio_cs = GPIO88_ZIPITZ2_LCD_CS, }; static struct gpiod_lookup_table lms283_gpio_table = { @@ -624,8 +622,26 @@ static struct pxa2xx_spi_controller pxa_ssp2_master_info = { .num_chipselect = 1, }; +static struct gpiod_lookup_table pxa_ssp1_gpio_table = { + .dev_id = "pxa2xx-spi.1", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", GPIO24_ZIPITZ2_WIFI_CS, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + +static struct gpiod_lookup_table pxa_ssp2_gpio_table = { + .dev_id = "pxa2xx-spi.2", + .table = { + GPIO_LOOKUP_IDX("gpio-pxa", GPIO88_ZIPITZ2_LCD_CS, "cs", 0, GPIO_ACTIVE_LOW), + { }, + }, +}; + static void __init z2_spi_init(void) { + gpiod_add_lookup_table(&pxa_ssp1_gpio_table); + gpiod_add_lookup_table(&pxa_ssp2_gpio_table); pxa2xx_set_spi_info(1, &pxa_ssp1_master_info); pxa2xx_set_spi_info(2, &pxa_ssp2_master_info); gpiod_add_lookup_table(&lms283_gpio_table); diff --git a/arch/arm/mach-s3c/Kconfig b/arch/arm/mach-s3c/Kconfig index 25606e668cf9..1899fc3f44fd 100644 --- a/arch/arm/mach-s3c/Kconfig +++ b/arch/arm/mach-s3c/Kconfig @@ -191,18 +191,6 @@ config S3C64XX_DEV_SPI0 Compile in platform device definitions for S3C64XX's type SPI controller 0 -config S3C64XX_DEV_SPI1 - bool - help - Compile in platform device definitions for S3C64XX's type - SPI controller 1 - -config S3C64XX_DEV_SPI2 - bool - help - Compile in platform device definitions for S3C64XX's type - SPI controller 2 - config SAMSUNG_DEV_TS bool help diff --git a/arch/arm/mach-s3c/devs.c b/arch/arm/mach-s3c/devs.c index 06dec64848f9..1e266fc24f9b 100644 --- a/arch/arm/mach-s3c/devs.c +++ b/arch/arm/mach-s3c/devs.c @@ -1107,8 +1107,7 @@ struct platform_device s3c64xx_device_spi0 = { }, }; -void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, - int num_cs) +void __init s3c64xx_spi0_set_platdata(int src_clk_nr, int num_cs) { struct s3c64xx_spi_info pd; @@ -1120,80 +1119,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, pd.num_cs = num_cs; pd.src_clk_nr = src_clk_nr; - pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio; + pd.cfg_gpio = s3c64xx_spi0_cfg_gpio; s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0); } #endif /* CONFIG_S3C64XX_DEV_SPI0 */ - -#ifdef CONFIG_S3C64XX_DEV_SPI1 -static struct resource s3c64xx_spi1_resource[] = { - [0] = DEFINE_RES_MEM(S3C_PA_SPI1, SZ_256), - [1] = DEFINE_RES_IRQ(IRQ_SPI1), -}; - -struct platform_device s3c64xx_device_spi1 = { - .name = "s3c6410-spi", - .id = 1, - .num_resources = ARRAY_SIZE(s3c64xx_spi1_resource), - .resource = s3c64xx_spi1_resource, - .dev = { - .dma_mask = &samsung_device_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, - int num_cs) -{ - struct s3c64xx_spi_info pd; - - /* Reject invalid configuration */ - if (!num_cs || src_clk_nr < 0) { - pr_err("%s: Invalid SPI configuration\n", __func__); - return; - } - - pd.num_cs = num_cs; - pd.src_clk_nr = src_clk_nr; - pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio; - - s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1); -} -#endif /* CONFIG_S3C64XX_DEV_SPI1 */ - -#ifdef CONFIG_S3C64XX_DEV_SPI2 -static struct resource s3c64xx_spi2_resource[] = { - [0] = DEFINE_RES_MEM(S3C_PA_SPI2, SZ_256), - [1] = DEFINE_RES_IRQ(IRQ_SPI2), -}; - -struct platform_device s3c64xx_device_spi2 = { - .name = "s3c6410-spi", - .id = 2, - .num_resources = ARRAY_SIZE(s3c64xx_spi2_resource), - .resource = s3c64xx_spi2_resource, - .dev = { - .dma_mask = &samsung_device_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, - int num_cs) -{ - struct s3c64xx_spi_info pd; - - /* Reject invalid configuration */ - if (!num_cs || src_clk_nr < 0) { - pr_err("%s: Invalid SPI configuration\n", __func__); - return; - } - - pd.num_cs = num_cs; - pd.src_clk_nr = src_clk_nr; - pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio; - - s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2); -} -#endif /* CONFIG_S3C64XX_DEV_SPI2 */ diff --git a/arch/arm/mach-s3c/mach-crag6410-module.c b/arch/arm/mach-s3c/mach-crag6410-module.c index 407ad493493e..5d1d4b67a4b7 100644 --- a/arch/arm/mach-s3c/mach-crag6410-module.c +++ b/arch/arm/mach-s3c/mach-crag6410-module.c @@ -32,10 +32,6 @@ #include "crag6410.h" -static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = { - .line = S3C64XX_GPC(3), -}; - static struct wm0010_pdata wm0010_pdata = { .gpio_reset = S3C64XX_GPN(6), .reset_active_high = 1, /* Active high for Glenfarclas Rev 2 */ @@ -49,7 +45,6 @@ static struct spi_board_info wm1253_devs[] = { .chip_select = 0, .mode = SPI_MODE_0, .irq = S3C_EINT(4), - .controller_data = &wm0010_spi_csinfo, .platform_data = &wm0010_pdata, }, }; @@ -62,7 +57,6 @@ static struct spi_board_info balblair_devs[] = { .chip_select = 0, .mode = SPI_MODE_0, .irq = S3C_EINT(4), - .controller_data = &wm0010_spi_csinfo, .platform_data = &wm0010_pdata, }, }; @@ -229,10 +223,6 @@ static struct arizona_pdata wm5102_reva_pdata = { }, }; -static struct s3c64xx_spi_csinfo codec_spi_csinfo = { - .line = S3C64XX_GPN(5), -}; - static struct spi_board_info wm5102_reva_spi_devs[] = { [0] = { .modalias = "wm5102", @@ -242,7 +232,6 @@ static struct spi_board_info wm5102_reva_spi_devs[] = { .mode = SPI_MODE_0, .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, - .controller_data = &codec_spi_csinfo, .platform_data = &wm5102_reva_pdata, }, }; @@ -275,7 +264,6 @@ static struct spi_board_info wm5102_spi_devs[] = { .mode = SPI_MODE_0, .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, - .controller_data = &codec_spi_csinfo, .platform_data = &wm5102_pdata, }, }; @@ -298,7 +286,6 @@ static struct spi_board_info wm5110_spi_devs[] = { .mode = SPI_MODE_0, .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, - .controller_data = &codec_spi_csinfo, .platform_data = &wm5102_reva_pdata, }, }; diff --git a/arch/arm/mach-s3c/mach-crag6410.c b/arch/arm/mach-s3c/mach-crag6410.c index 4a12c75d407f..e3e0fe897bcc 100644 --- a/arch/arm/mach-s3c/mach-crag6410.c +++ b/arch/arm/mach-s3c/mach-crag6410.c @@ -825,6 +825,15 @@ static const struct gpio_led_platform_data gpio_leds_pdata = { static struct dwc2_hsotg_plat crag6410_hsotg_pdata; +static struct gpiod_lookup_table crag_spi0_gpiod_table = { + .dev_id = "s3c6410-spi.0", + .table = { + GPIO_LOOKUP_IDX("GPIOC", 3, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("GPION", 5, "cs", 1, GPIO_ACTIVE_LOW), + { }, + }, +}; + static void __init crag6410_machine_init(void) { /* Open drain IRQs need pullups */ @@ -856,7 +865,9 @@ static void __init crag6410_machine_init(void) i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1)); samsung_keypad_set_platdata(&crag6410_keypad_data); - s3c64xx_spi0_set_platdata(NULL, 0, 2); + + gpiod_add_lookup_table(&crag_spi0_gpiod_table); + s3c64xx_spi0_set_platdata(0, 2); pwm_add_table(crag6410_pwm_lookup, ARRAY_SIZE(crag6410_pwm_lookup)); platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices)); diff --git a/arch/arm/mach-s3c/setup-spi-s3c64xx.c b/arch/arm/mach-s3c/setup-spi-s3c64xx.c index efcf78d41585..497aff71c29c 100644 --- a/arch/arm/mach-s3c/setup-spi-s3c64xx.c +++ b/arch/arm/mach-s3c/setup-spi-s3c64xx.c @@ -16,12 +16,3 @@ int s3c64xx_spi0_cfg_gpio(void) return 0; } #endif - -#ifdef CONFIG_S3C64XX_DEV_SPI1 -int s3c64xx_spi1_cfg_gpio(void) -{ - s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3, - S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); - return 0; -} -#endif diff --git a/arch/arm/mach-s3c/spi-core-s3c24xx.h b/arch/arm/mach-s3c/spi-core-s3c24xx.h index 057667469cc3..919c5fd0c9af 100644 --- a/arch/arm/mach-s3c/spi-core-s3c24xx.h +++ b/arch/arm/mach-s3c/spi-core-s3c24xx.h @@ -16,12 +16,6 @@ static inline void s3c24xx_spi_setname(char *name) #ifdef CONFIG_S3C64XX_DEV_SPI0 s3c64xx_device_spi0.name = name; #endif -#ifdef CONFIG_S3C64XX_DEV_SPI1 - s3c64xx_device_spi1.name = name; -#endif -#ifdef CONFIG_S3C64XX_DEV_SPI2 - s3c64xx_device_spi2.name = name; -#endif } #endif /* __PLAT_S3C_SPI_CORE_S3C24XX_H */ diff --git a/drivers/bus/moxtet.c b/drivers/bus/moxtet.c index fd87a59837fa..5eb0fe73ddc4 100644 --- a/drivers/bus/moxtet.c +++ b/drivers/bus/moxtet.c @@ -815,7 +815,7 @@ static int moxtet_probe(struct spi_device *spi) return 0; } -static int moxtet_remove(struct spi_device *spi) +static void moxtet_remove(struct spi_device *spi) { struct moxtet *moxtet = spi_get_drvdata(spi); @@ -828,8 +828,6 @@ static int moxtet_remove(struct spi_device *spi) device_for_each_child(moxtet->dev, NULL, __unregister); mutex_destroy(&moxtet->lock); - - return 0; } static const struct of_device_id moxtet_dt_ids[] = { diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index 7c617edff4ca..3170d59d660c 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c @@ -267,11 +267,8 @@ static int st33zp24_i2c_probe(struct i2c_client *client, static int st33zp24_i2c_remove(struct i2c_client *client) { struct tpm_chip *chip = i2c_get_clientdata(client); - int ret; - ret = st33zp24_remove(chip); - if (ret) - return ret; + st33zp24_remove(chip); return 0; } diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index a75dafd39445..22d184884694 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c @@ -381,16 +381,11 @@ static int st33zp24_spi_probe(struct spi_device *dev) * @param: client, the spi_device description (TPM SPI description). * @return: 0 in case of success. */ -static int st33zp24_spi_remove(struct spi_device *dev) +static void st33zp24_spi_remove(struct spi_device *dev) { struct tpm_chip *chip = spi_get_drvdata(dev); - int ret; - ret = st33zp24_remove(chip); - if (ret) - return ret; - - return 0; + st33zp24_remove(chip); } static const struct spi_device_id st33zp24_spi_id[] = { diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index ce9efb73c144..15b393e92c8e 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -511,10 +511,9 @@ _tpm_clean_answer: } EXPORT_SYMBOL(st33zp24_probe); -int st33zp24_remove(struct tpm_chip *chip) +void st33zp24_remove(struct tpm_chip *chip) { tpm_chip_unregister(chip); - return 0; } EXPORT_SYMBOL(st33zp24_remove); diff --git a/drivers/char/tpm/st33zp24/st33zp24.h b/drivers/char/tpm/st33zp24/st33zp24.h index 6747be1e2502..b387a476c555 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.h +++ b/drivers/char/tpm/st33zp24/st33zp24.h @@ -34,5 +34,5 @@ int st33zp24_pm_resume(struct device *dev); int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, struct device *dev, int irq, int io_lpcpd); -int st33zp24_remove(struct tpm_chip *chip); +void st33zp24_remove(struct tpm_chip *chip); #endif /* __LOCAL_ST33ZP24_H__ */ diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c index aaa59a00eeae..184396b3af50 100644 --- a/drivers/char/tpm/tpm_tis_spi_main.c +++ b/drivers/char/tpm/tpm_tis_spi_main.c @@ -254,13 +254,12 @@ static int tpm_tis_spi_driver_probe(struct spi_device *spi) static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume); -static int tpm_tis_spi_remove(struct spi_device *dev) +static void tpm_tis_spi_remove(struct spi_device *dev) { struct tpm_chip *chip = spi_get_drvdata(dev); tpm_chip_unregister(chip); tpm_tis_remove(chip); - return 0; } static const struct spi_device_id tpm_tis_spi_id[] = { diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index 8f02c0b88000..f416f8bc2898 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -1544,14 +1544,12 @@ err_disable_oscin: return ret; } -static int lmk04832_remove(struct spi_device *spi) +static void lmk04832_remove(struct spi_device *spi) { struct lmk04832 *lmk = spi_get_drvdata(spi); clk_disable_unprepare(lmk->oscin); of_clk_del_provider(spi->dev.of_node); - - return 0; } static const struct spi_device_id lmk04832_id[] = { { "lmk04832", LMK04832 }, diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 4a55cdf089d6..e00c33310517 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -163,15 +163,13 @@ exit_destroy: return ret; } -static int gen_74x164_remove(struct spi_device *spi) +static void gen_74x164_remove(struct spi_device *spi) { struct gen_74x164_chip *chip = spi_get_drvdata(spi); gpiod_set_value_cansleep(chip->gpiod_oe, 0); gpiochip_remove(&chip->gpio_chip); mutex_destroy(&chip->lock); - - return 0; } static const struct spi_device_id gen_74x164_spi_ids[] = { diff --git a/drivers/gpio/gpio-max3191x.c b/drivers/gpio/gpio-max3191x.c index 51cd6f98d1c7..161c4751c5f7 100644 --- a/drivers/gpio/gpio-max3191x.c +++ b/drivers/gpio/gpio-max3191x.c @@ -443,14 +443,12 @@ static int max3191x_probe(struct spi_device *spi) return 0; } -static int max3191x_remove(struct spi_device *spi) +static void max3191x_remove(struct spi_device *spi) { struct max3191x_chip *max3191x = spi_get_drvdata(spi); gpiochip_remove(&max3191x->gpio); mutex_destroy(&max3191x->lock); - - return 0; } static int __init max3191x_register_driver(struct spi_driver *sdrv) diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c index 5862d73bf325..11813f41d460 100644 --- a/drivers/gpio/gpio-max7301.c +++ b/drivers/gpio/gpio-max7301.c @@ -64,11 +64,9 @@ static int max7301_probe(struct spi_device *spi) return ret; } -static int max7301_remove(struct spi_device *spi) +static void max7301_remove(struct spi_device *spi) { __max730x_remove(&spi->dev); - - return 0; } static const struct spi_device_id max7301_id[] = { diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c index 31d2be1bebc8..cd9b16dbe1a9 100644 --- a/drivers/gpio/gpio-mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -134,7 +134,7 @@ exit_destroy: return ret; } -static int mc33880_remove(struct spi_device *spi) +static void mc33880_remove(struct spi_device *spi) { struct mc33880 *mc; @@ -142,8 +142,6 @@ static int mc33880_remove(struct spi_device *spi) gpiochip_remove(&mc->chip); mutex_destroy(&mc->lock); - - return 0; } static struct spi_driver mc33880_driver = { diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c index 8e04054cf07e..81a47ae09ff8 100644 --- a/drivers/gpio/gpio-pisosr.c +++ b/drivers/gpio/gpio-pisosr.c @@ -163,15 +163,13 @@ static int pisosr_gpio_probe(struct spi_device *spi) return 0; } -static int pisosr_gpio_remove(struct spi_device *spi) +static void pisosr_gpio_remove(struct spi_device *spi) { struct pisosr_gpio *gpio = spi_get_drvdata(spi); gpiochip_remove(&gpio->chip); mutex_destroy(&gpio->lock); - - return 0; } static const struct spi_device_id pisosr_gpio_id_table[] = { diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c index f043b484055b..ed626fdc08e8 100644 --- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c +++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c @@ -293,15 +293,13 @@ static int y030xx067a_probe(struct spi_device *spi) return 0; } -static int y030xx067a_remove(struct spi_device *spi) +static void y030xx067a_remove(struct spi_device *spi) { struct y030xx067a *priv = spi_get_drvdata(spi); drm_panel_remove(&priv->panel); drm_panel_disable(&priv->panel); drm_panel_unprepare(&priv->panel); - - return 0; } static const struct drm_display_mode y030xx067a_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 8e84df9a0033..3dfafa585127 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -896,14 +896,12 @@ static int ili9322_probe(struct spi_device *spi) return 0; } -static int ili9322_remove(struct spi_device *spi) +static void ili9322_remove(struct spi_device *spi) { struct ili9322 *ili = spi_get_drvdata(spi); ili9322_power_off(ili); drm_panel_remove(&ili->panel); - - return 0; } /* diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 2c3378a259b1..a07ef26234e5 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -728,7 +728,7 @@ static int ili9341_probe(struct spi_device *spi) return -1; } -static int ili9341_remove(struct spi_device *spi) +static void ili9341_remove(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct ili9341 *ili = spi_get_drvdata(spi); @@ -741,7 +741,6 @@ static int ili9341_remove(struct spi_device *spi) drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); } - return 0; } static void ili9341_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c index c558de3f99be..e3b1daa0cb72 100644 --- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c +++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c @@ -219,15 +219,13 @@ static int ej030na_probe(struct spi_device *spi) return 0; } -static int ej030na_remove(struct spi_device *spi) +static void ej030na_remove(struct spi_device *spi) { struct ej030na *priv = spi_get_drvdata(spi); drm_panel_remove(&priv->panel); drm_panel_disable(&priv->panel); drm_panel_unprepare(&priv->panel); - - return 0; } static const struct drm_display_mode ej030na_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c index f3183b68704f..9d0d4faa3f58 100644 --- a/drivers/gpu/drm/panel/panel-lg-lb035q02.c +++ b/drivers/gpu/drm/panel/panel-lg-lb035q02.c @@ -203,14 +203,12 @@ static int lb035q02_probe(struct spi_device *spi) return 0; } -static int lb035q02_remove(struct spi_device *spi) +static void lb035q02_remove(struct spi_device *spi) { struct lb035q02_device *lcd = spi_get_drvdata(spi); drm_panel_remove(&lcd->panel); drm_panel_disable(&lcd->panel); - - return 0; } static const struct of_device_id lb035q02_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c index 8e5160af1de5..cf246d15b7b6 100644 --- a/drivers/gpu/drm/panel/panel-lg-lg4573.c +++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c @@ -266,14 +266,12 @@ static int lg4573_probe(struct spi_device *spi) return 0; } -static int lg4573_remove(struct spi_device *spi) +static void lg4573_remove(struct spi_device *spi) { struct lg4573 *ctx = spi_get_drvdata(spi); lg4573_display_off(ctx); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id lg4573_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c index 6e5ab1debc8b..81c5c541a351 100644 --- a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c @@ -212,15 +212,13 @@ static int nl8048_probe(struct spi_device *spi) return 0; } -static int nl8048_remove(struct spi_device *spi) +static void nl8048_remove(struct spi_device *spi) { struct nl8048_panel *lcd = spi_get_drvdata(spi); drm_panel_remove(&lcd->panel); drm_panel_disable(&lcd->panel); drm_panel_unprepare(&lcd->panel); - - return 0; } static const struct of_device_id nl8048_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index d036853db865..f58cfb10b58a 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -292,7 +292,7 @@ static int nt39016_probe(struct spi_device *spi) return 0; } -static int nt39016_remove(struct spi_device *spi) +static void nt39016_remove(struct spi_device *spi) { struct nt39016 *panel = spi_get_drvdata(spi); @@ -300,8 +300,6 @@ static int nt39016_remove(struct spi_device *spi) nt39016_disable(&panel->drm_panel); nt39016_unprepare(&panel->drm_panel); - - return 0; } static const struct drm_display_mode kd035g6_display_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-db7430.c b/drivers/gpu/drm/panel/panel-samsung-db7430.c index ead479719f00..04640c5256a8 100644 --- a/drivers/gpu/drm/panel/panel-samsung-db7430.c +++ b/drivers/gpu/drm/panel/panel-samsung-db7430.c @@ -314,12 +314,11 @@ static int db7430_probe(struct spi_device *spi) return 0; } -static int db7430_remove(struct spi_device *spi) +static void db7430_remove(struct spi_device *spi) { struct db7430 *db = spi_get_drvdata(spi); drm_panel_remove(&db->panel); - return 0; } /* diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c index c4b388850a13..01eb211f32f7 100644 --- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c +++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c @@ -358,14 +358,12 @@ static int ld9040_probe(struct spi_device *spi) return 0; } -static int ld9040_remove(struct spi_device *spi) +static void ld9040_remove(struct spi_device *spi) { struct ld9040 *ctx = spi_get_drvdata(spi); ld9040_power_off(ctx); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id ld9040_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c index 1696ceb36aa0..2adb223a895c 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c @@ -291,12 +291,11 @@ static int s6d27a1_probe(struct spi_device *spi) return 0; } -static int s6d27a1_remove(struct spi_device *spi) +static void s6d27a1_remove(struct spi_device *spi) { struct s6d27a1 *ctx = spi_get_drvdata(spi); drm_panel_remove(&ctx->panel); - return 0; } static const struct of_device_id s6d27a1_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c index c178d962b0d5..d99afcc672ca 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -62,10 +62,9 @@ static int s6e63m0_spi_probe(struct spi_device *spi) s6e63m0_spi_dcs_write, false); } -static int s6e63m0_spi_remove(struct spi_device *spi) +static void s6e63m0_spi_remove(struct spi_device *spi) { s6e63m0_remove(&spi->dev); - return 0; } static const struct of_device_id s6e63m0_spi_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c index 61e565524542..bbc4569cbcdc 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c @@ -387,13 +387,11 @@ static int st7789v_probe(struct spi_device *spi) return 0; } -static int st7789v_remove(struct spi_device *spi) +static void st7789v_remove(struct spi_device *spi) { struct st7789v *ctx = spi_get_drvdata(spi); drm_panel_remove(&ctx->panel); - - return 0; } static const struct of_device_id st7789v_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c index ba0b3ead150f..0d7541a33f87 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c @@ -655,7 +655,7 @@ static int acx565akm_probe(struct spi_device *spi) return 0; } -static int acx565akm_remove(struct spi_device *spi) +static void acx565akm_remove(struct spi_device *spi) { struct acx565akm_panel *lcd = spi_get_drvdata(spi); @@ -666,8 +666,6 @@ static int acx565akm_remove(struct spi_device *spi) drm_panel_disable(&lcd->panel); drm_panel_unprepare(&lcd->panel); - - return 0; } static const struct of_device_id acx565akm_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c index ba0c00d1a001..4dbf8b88f264 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c @@ -350,15 +350,13 @@ static int td028ttec1_probe(struct spi_device *spi) return 0; } -static int td028ttec1_remove(struct spi_device *spi) +static void td028ttec1_remove(struct spi_device *spi) { struct td028ttec1_panel *lcd = spi_get_drvdata(spi); drm_panel_remove(&lcd->panel); drm_panel_disable(&lcd->panel); drm_panel_unprepare(&lcd->panel); - - return 0; } static const struct of_device_id td028ttec1_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c index 1866cdb8f9c1..cf4609bb9b1d 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c @@ -463,7 +463,7 @@ static int td043mtea1_probe(struct spi_device *spi) return 0; } -static int td043mtea1_remove(struct spi_device *spi) +static void td043mtea1_remove(struct spi_device *spi) { struct td043mtea1_panel *lcd = spi_get_drvdata(spi); @@ -472,8 +472,6 @@ static int td043mtea1_remove(struct spi_device *spi) drm_panel_unprepare(&lcd->panel); sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group); - - return 0; } static const struct of_device_id td043mtea1_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c index e3791dad6830..0b1f5a11a055 100644 --- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c +++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c @@ -450,12 +450,11 @@ static int tpg110_probe(struct spi_device *spi) return 0; } -static int tpg110_remove(struct spi_device *spi) +static void tpg110_remove(struct spi_device *spi) { struct tpg110 *tpg = spi_get_drvdata(spi); drm_panel_remove(&tpg->panel); - return 0; } static const struct of_device_id tpg110_match[] = { diff --git a/drivers/gpu/drm/panel/panel-widechips-ws2401.c b/drivers/gpu/drm/panel/panel-widechips-ws2401.c index 8bc976f54b80..236f3cb2b594 100644 --- a/drivers/gpu/drm/panel/panel-widechips-ws2401.c +++ b/drivers/gpu/drm/panel/panel-widechips-ws2401.c @@ -407,12 +407,11 @@ static int ws2401_probe(struct spi_device *spi) return 0; } -static int ws2401_remove(struct spi_device *spi) +static void ws2401_remove(struct spi_device *spi) { struct ws2401 *ws = spi_get_drvdata(spi); drm_panel_remove(&ws->panel); - return 0; } /* diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 9b33c05732aa..ebb025543f8d 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -263,14 +263,12 @@ static int hx8357d_probe(struct spi_device *spi) return 0; } -static int hx8357d_remove(struct spi_device *spi) +static void hx8357d_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void hx8357d_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index bcc181351236..fc8ed245b0bc 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -193,14 +193,12 @@ static int ili9163_probe(struct spi_device *spi) return 0; } -static int ili9163_remove(struct spi_device *spi) +static void ili9163_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9163_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index 976d3209f164..cc92eb9f2a07 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -411,14 +411,12 @@ static int ili9225_probe(struct spi_device *spi) return 0; } -static int ili9225_remove(struct spi_device *spi) +static void ili9225_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9225_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 37e0c33399c8..5b8cc770ee7b 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -225,14 +225,12 @@ static int ili9341_probe(struct spi_device *spi) return 0; } -static int ili9341_remove(struct spi_device *spi) +static void ili9341_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9341_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index e9a63f4b2993..6d655e18e0aa 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -243,14 +243,12 @@ static int ili9486_probe(struct spi_device *spi) return 0; } -static int ili9486_remove(struct spi_device *spi) +static void ili9486_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void ili9486_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 023de49e7a8e..5e060f6910bb 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -233,14 +233,12 @@ static int mi0283qt_probe(struct spi_device *spi) return 0; } -static int mi0283qt_remove(struct spi_device *spi) +static void mi0283qt_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void mi0283qt_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 97a775c48cea..beeeb170d0b1 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -1140,14 +1140,12 @@ static int repaper_probe(struct spi_device *spi) return 0; } -static int repaper_remove(struct spi_device *spi) +static void repaper_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void repaper_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 51b9b9fb3ead..3f38faa1cd8c 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -360,14 +360,12 @@ static int st7586_probe(struct spi_device *spi) return 0; } -static int st7586_remove(struct spi_device *spi) +static void st7586_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void st7586_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index fc40dd10efa8..29d618093e94 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -247,14 +247,12 @@ static int st7735r_probe(struct spi_device *spi) return 0; } -static int st7735r_remove(struct spi_device *spi) +static void st7735r_remove(struct spi_device *spi) { struct drm_device *drm = spi_get_drvdata(spi); drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); - - return 0; } static void st7735r_shutdown(struct spi_device *spi) diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c index e5bc5ce09f4e..de37bce24fa6 100644 --- a/drivers/hwmon/adcxx.c +++ b/drivers/hwmon/adcxx.c @@ -194,7 +194,7 @@ out_err: return status; } -static int adcxx_remove(struct spi_device *spi) +static void adcxx_remove(struct spi_device *spi) { struct adcxx *adc = spi_get_drvdata(spi); int i; @@ -205,8 +205,6 @@ static int adcxx_remove(struct spi_device *spi) device_remove_file(&spi->dev, &ad_input[i].dev_attr); mutex_unlock(&adc->lock); - - return 0; } static const struct spi_device_id adcxx_ids[] = { diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 5fcfd57df61e..4c5487aeb3cf 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -254,7 +254,7 @@ err_remove: return err; } -static int max1111_remove(struct spi_device *spi) +static void max1111_remove(struct spi_device *spi) { struct max1111_data *data = spi_get_drvdata(spi); @@ -265,7 +265,6 @@ static int max1111_remove(struct spi_device *spi) sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); mutex_destroy(&data->drvdata_lock); - return 0; } static const struct spi_device_id max1111_ids[] = { diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c index 4cf4fe6809a3..93e048ee4955 100644 --- a/drivers/hwmon/max31722.c +++ b/drivers/hwmon/max31722.c @@ -100,7 +100,7 @@ static int max31722_probe(struct spi_device *spi) return 0; } -static int max31722_remove(struct spi_device *spi) +static void max31722_remove(struct spi_device *spi) { struct max31722_data *data = spi_get_drvdata(spi); int ret; @@ -111,8 +111,6 @@ static int max31722_remove(struct spi_device *spi) if (ret) /* There is nothing we can do about this ... */ dev_warn(&spi->dev, "Failed to put device in stand-by mode\n"); - - return 0; } static int __maybe_unused max31722_suspend(struct device *dev) diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c index 9f622e37477b..9040a717b247 100644 --- a/drivers/iio/accel/bma400_spi.c +++ b/drivers/iio/accel/bma400_spi.c @@ -87,11 +87,9 @@ static int bma400_spi_probe(struct spi_device *spi) return bma400_probe(&spi->dev, regmap, id->name); } -static int bma400_spi_remove(struct spi_device *spi) +static void bma400_spi_remove(struct spi_device *spi) { bma400_remove(&spi->dev); - - return 0; } static const struct spi_device_id bma400_spi_ids[] = { diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c index 11559567cb39..80007cc2d044 100644 --- a/drivers/iio/accel/bmc150-accel-spi.c +++ b/drivers/iio/accel/bmc150-accel-spi.c @@ -35,11 +35,9 @@ static int bmc150_accel_probe(struct spi_device *spi) true); } -static int bmc150_accel_remove(struct spi_device *spi) +static void bmc150_accel_remove(struct spi_device *spi) { bmc150_accel_core_remove(&spi->dev); - - return 0; } static const struct acpi_device_id bmc150_accel_acpi_match[] = { diff --git a/drivers/iio/accel/bmi088-accel-spi.c b/drivers/iio/accel/bmi088-accel-spi.c index 758ad2f12896..06d99d9949f3 100644 --- a/drivers/iio/accel/bmi088-accel-spi.c +++ b/drivers/iio/accel/bmi088-accel-spi.c @@ -56,11 +56,9 @@ static int bmi088_accel_probe(struct spi_device *spi) true); } -static int bmi088_accel_remove(struct spi_device *spi) +static void bmi088_accel_remove(struct spi_device *spi) { bmi088_accel_core_remove(&spi->dev); - - return 0; } static const struct spi_device_id bmi088_accel_id[] = { diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c index 441e6b764281..57c451cfb9e5 100644 --- a/drivers/iio/accel/kxsd9-spi.c +++ b/drivers/iio/accel/kxsd9-spi.c @@ -32,11 +32,9 @@ static int kxsd9_spi_probe(struct spi_device *spi) spi_get_device_id(spi)->name); } -static int kxsd9_spi_remove(struct spi_device *spi) +static void kxsd9_spi_remove(struct spi_device *spi) { kxsd9_common_remove(&spi->dev); - - return 0; } static const struct spi_device_id kxsd9_spi_id[] = { diff --git a/drivers/iio/accel/mma7455_spi.c b/drivers/iio/accel/mma7455_spi.c index ecf690692dcc..b746031551a3 100644 --- a/drivers/iio/accel/mma7455_spi.c +++ b/drivers/iio/accel/mma7455_spi.c @@ -22,11 +22,9 @@ static int mma7455_spi_probe(struct spi_device *spi) return mma7455_core_probe(&spi->dev, regmap, id->name); } -static int mma7455_spi_remove(struct spi_device *spi) +static void mma7455_spi_remove(struct spi_device *spi) { mma7455_core_remove(&spi->dev); - - return 0; } static const struct spi_device_id mma7455_spi_ids[] = { diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 43ecacbdc95a..83c81072511e 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -1524,7 +1524,7 @@ error_ret: return ret; } -static int sca3000_remove(struct spi_device *spi) +static void sca3000_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct sca3000_state *st = iio_priv(indio_dev); @@ -1535,8 +1535,6 @@ static int sca3000_remove(struct spi_device *spi) sca3000_stop_all_interrupts(st); if (spi->irq) free_irq(spi->irq, indio_dev); - - return 0; } static const struct spi_device_id sca3000_id[] = { diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 1d345d66742d..c17d9b5fbaf6 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -479,7 +479,7 @@ error_disable_reg: return ret; } -static int ad7266_remove(struct spi_device *spi) +static void ad7266_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7266_state *st = iio_priv(indio_dev); @@ -488,8 +488,6 @@ static int ad7266_remove(struct spi_device *spi) iio_triggered_buffer_cleanup(indio_dev); if (!IS_ERR(st->reg)) regulator_disable(st->reg); - - return 0; } static const struct spi_device_id ad7266_id[] = { diff --git a/drivers/iio/adc/ltc2496.c b/drivers/iio/adc/ltc2496.c index dd956a7c216e..5a55f79f2574 100644 --- a/drivers/iio/adc/ltc2496.c +++ b/drivers/iio/adc/ltc2496.c @@ -78,13 +78,11 @@ static int ltc2496_probe(struct spi_device *spi) return ltc2497core_probe(dev, indio_dev); } -static int ltc2496_remove(struct spi_device *spi) +static void ltc2496_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); ltc2497core_remove(indio_dev); - - return 0; } static const struct of_device_id ltc2496_of_match[] = { diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 8d1cff28cae0..b4c69acb33e3 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -459,15 +459,13 @@ reg_disable: return ret; } -static int mcp320x_remove(struct spi_device *spi) +static void mcp320x_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct mcp320x *adc = iio_priv(indio_dev); iio_device_unregister(indio_dev); regulator_disable(adc->reg); - - return 0; } static const struct of_device_id mcp320x_dt_ids[] = { diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index 13535f148c4c..1cb4590fe412 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -321,7 +321,7 @@ reg_disable: return ret; } -static int mcp3911_remove(struct spi_device *spi) +static void mcp3911_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct mcp3911 *adc = iio_priv(indio_dev); @@ -331,8 +331,6 @@ static int mcp3911_remove(struct spi_device *spi) clk_disable_unprepare(adc->clki); if (adc->vref) regulator_disable(adc->vref); - - return 0; } static const struct of_device_id mcp3911_dt_ids[] = { diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c index 6eb62b564dae..59d75d09604f 100644 --- a/drivers/iio/adc/ti-adc12138.c +++ b/drivers/iio/adc/ti-adc12138.c @@ -503,7 +503,7 @@ err_clk_disable: return ret; } -static int adc12138_remove(struct spi_device *spi) +static void adc12138_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct adc12138 *adc = iio_priv(indio_dev); @@ -514,8 +514,6 @@ static int adc12138_remove(struct spi_device *spi) regulator_disable(adc->vref_n); regulator_disable(adc->vref_p); clk_disable_unprepare(adc->cclk); - - return 0; } static const struct of_device_id adc12138_dt_ids[] = { diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index a7efa3eada2c..e3658b969c5b 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -662,7 +662,7 @@ error_destroy_mutex: return ret; } -static int ti_ads7950_remove(struct spi_device *spi) +static void ti_ads7950_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ti_ads7950_state *st = iio_priv(indio_dev); @@ -672,8 +672,6 @@ static int ti_ads7950_remove(struct spi_device *spi) iio_triggered_buffer_cleanup(indio_dev); regulator_disable(st->reg); mutex_destroy(&st->slock); - - return 0; } static const struct spi_device_id ti_ads7950_id[] = { diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 2e24717d7f55..22c2583eedd0 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -479,7 +479,7 @@ err_regulator_disable: return ret; } -static int ads8688_remove(struct spi_device *spi) +static void ads8688_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ads8688_state *st = iio_priv(indio_dev); @@ -489,8 +489,6 @@ static int ads8688_remove(struct spi_device *spi) if (!IS_ERR(st->reg)) regulator_disable(st->reg); - - return 0; } static const struct spi_device_id ads8688_id[] = { diff --git a/drivers/iio/adc/ti-tlc4541.c b/drivers/iio/adc/ti-tlc4541.c index 403b787f9f7e..2406eda9dfc6 100644 --- a/drivers/iio/adc/ti-tlc4541.c +++ b/drivers/iio/adc/ti-tlc4541.c @@ -224,7 +224,7 @@ error_disable_reg: return ret; } -static int tlc4541_remove(struct spi_device *spi) +static void tlc4541_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct tlc4541_state *st = iio_priv(indio_dev); @@ -232,8 +232,6 @@ static int tlc4541_remove(struct spi_device *spi) iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); regulator_disable(st->reg); - - return 0; } static const struct of_device_id tlc4541_dt_ids[] = { diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index cfcf18a0bce8..1134ae12e531 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -298,7 +298,7 @@ error_disable_reg: return ret; } -static int ad8366_remove(struct spi_device *spi) +static void ad8366_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad8366_state *st = iio_priv(indio_dev); @@ -308,8 +308,6 @@ static int ad8366_remove(struct spi_device *spi) if (!IS_ERR(reg)) regulator_disable(reg); - - return 0; } static const struct spi_device_id ad8366_id[] = { diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index 1aee87100038..eafaf4529df5 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -586,7 +586,7 @@ err_setup_irq: return ret; } -static int ssp_remove(struct spi_device *spi) +static void ssp_remove(struct spi_device *spi) { struct ssp_data *data = spi_get_drvdata(spi); @@ -608,8 +608,6 @@ static int ssp_remove(struct spi_device *spi) mutex_destroy(&data->pending_lock); mfd_remove_devices(&spi->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index 2d3b14c407d8..ecbc6a51d60f 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -521,7 +521,7 @@ error_free_channels: return ret; } -static int ad5360_remove(struct spi_device *spi) +static void ad5360_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5360_state *st = iio_priv(indio_dev); @@ -531,8 +531,6 @@ static int ad5360_remove(struct spi_device *spi) kfree(indio_dev->channels); regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); - - return 0; } static const struct spi_device_id ad5360_ids[] = { diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index e38860a6a9f3..82e1d9bd773e 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -488,11 +488,9 @@ static int ad5380_spi_probe(struct spi_device *spi) return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name); } -static int ad5380_spi_remove(struct spi_device *spi) +static void ad5380_spi_remove(struct spi_device *spi) { ad5380_remove(&spi->dev); - - return 0; } static const struct spi_device_id ad5380_spi_ids[] = { diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 1c9b54c012a7..14cfabacbea5 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -491,11 +491,9 @@ static int ad5446_spi_probe(struct spi_device *spi) &ad5446_spi_chip_info[id->driver_data]); } -static int ad5446_spi_remove(struct spi_device *spi) +static void ad5446_spi_remove(struct spi_device *spi) { ad5446_remove(&spi->dev); - - return 0; } static struct spi_driver ad5446_spi_driver = { diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c index f5e93c6acc9d..bad9bdaafa94 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -330,7 +330,7 @@ error_disable_reg: return ret; } -static int ad5449_spi_remove(struct spi_device *spi) +static void ad5449_spi_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5449 *st = iio_priv(indio_dev); @@ -338,8 +338,6 @@ static int ad5449_spi_remove(struct spi_device *spi) iio_device_unregister(indio_dev); regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); - - return 0; } static const struct spi_device_id ad5449_spi_ids[] = { diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index b631261efa97..8507573aa13e 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -336,7 +336,7 @@ error_disable_reg: return ret; } -static int ad5504_remove(struct spi_device *spi) +static void ad5504_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5504_state *st = iio_priv(indio_dev); @@ -345,8 +345,6 @@ static int ad5504_remove(struct spi_device *spi) if (!IS_ERR(st->reg)) regulator_disable(st->reg); - - return 0; } static const struct spi_device_id ad5504_id[] = { diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c index 6bfd7951e18c..0f7abfa75bec 100644 --- a/drivers/iio/dac/ad5592r.c +++ b/drivers/iio/dac/ad5592r.c @@ -130,11 +130,9 @@ static int ad5592r_spi_probe(struct spi_device *spi) return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops); } -static int ad5592r_spi_remove(struct spi_device *spi) +static void ad5592r_spi_remove(struct spi_device *spi) { ad5592r_remove(&spi->dev); - - return 0; } static const struct spi_device_id ad5592r_spi_ids[] = { diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 3c98941b9f99..371e812850eb 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -293,7 +293,7 @@ error_disable_reg: return ret; } -static int ad5624r_remove(struct spi_device *spi) +static void ad5624r_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5624r_state *st = iio_priv(indio_dev); @@ -301,8 +301,6 @@ static int ad5624r_remove(struct spi_device *spi) iio_device_unregister(indio_dev); if (!IS_ERR(st->reg)) regulator_disable(st->reg); - - return 0; } static const struct spi_device_id ad5624r_id[] = { diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index 2628810fdbb1..d26fb29b6b04 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -95,11 +95,9 @@ static int ad5686_spi_probe(struct spi_device *spi) ad5686_spi_write, ad5686_spi_read); } -static int ad5686_spi_remove(struct spi_device *spi) +static void ad5686_spi_remove(struct spi_device *spi) { ad5686_remove(&spi->dev); - - return 0; } static const struct spi_device_id ad5686_spi_id[] = { diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c index e37e095e94fc..4cb8471db81e 100644 --- a/drivers/iio/dac/ad5761.c +++ b/drivers/iio/dac/ad5761.c @@ -394,7 +394,7 @@ disable_regulator_err: return ret; } -static int ad5761_remove(struct spi_device *spi) +static void ad5761_remove(struct spi_device *spi) { struct iio_dev *iio_dev = spi_get_drvdata(spi); struct ad5761_state *st = iio_priv(iio_dev); @@ -403,8 +403,6 @@ static int ad5761_remove(struct spi_device *spi) if (!IS_ERR_OR_NULL(st->vref_reg)) regulator_disable(st->vref_reg); - - return 0; } static const struct spi_device_id ad5761_id[] = { diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index ae089b9145cb..d235a8047ba0 100644 --- a/drivers/iio/dac/ad5764.c +++ b/drivers/iio/dac/ad5764.c @@ -332,7 +332,7 @@ error_disable_reg: return ret; } -static int ad5764_remove(struct spi_device *spi) +static void ad5764_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5764_state *st = iio_priv(indio_dev); @@ -341,8 +341,6 @@ static int ad5764_remove(struct spi_device *spi) if (st->chip_info->int_vref == 0) regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg); - - return 0; } static const struct spi_device_id ad5764_ids[] = { diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 7b4579d73d18..2b14914b4050 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -428,7 +428,7 @@ error_disable_reg_pos: return ret; } -static int ad5791_remove(struct spi_device *spi) +static void ad5791_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad5791_state *st = iio_priv(indio_dev); @@ -439,8 +439,6 @@ static int ad5791_remove(struct spi_device *spi) if (!IS_ERR(st->reg_vss)) regulator_disable(st->reg_vss); - - return 0; } static const struct spi_device_id ad5791_id[] = { diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c index 5ecfdad54dec..6be35c92d435 100644 --- a/drivers/iio/dac/ad8801.c +++ b/drivers/iio/dac/ad8801.c @@ -193,7 +193,7 @@ error_disable_vrefh_reg: return ret; } -static int ad8801_remove(struct spi_device *spi) +static void ad8801_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad8801_state *state = iio_priv(indio_dev); @@ -202,8 +202,6 @@ static int ad8801_remove(struct spi_device *spi) if (state->vrefl_reg) regulator_disable(state->vrefl_reg); regulator_disable(state->vrefh_reg); - - return 0; } static const struct spi_device_id ad8801_ids[] = { diff --git a/drivers/iio/dac/ltc1660.c b/drivers/iio/dac/ltc1660.c index f6ec9bf5815e..c76233c9bb72 100644 --- a/drivers/iio/dac/ltc1660.c +++ b/drivers/iio/dac/ltc1660.c @@ -206,15 +206,13 @@ error_disable_reg: return ret; } -static int ltc1660_remove(struct spi_device *spi) +static void ltc1660_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ltc1660_priv *priv = iio_priv(indio_dev); iio_device_unregister(indio_dev); regulator_disable(priv->vref_reg); - - return 0; } static const struct of_device_id ltc1660_dt_ids[] = { diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index 53e4b887d372..aed46c80757e 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -372,7 +372,7 @@ static int ltc2632_probe(struct spi_device *spi) return iio_device_register(indio_dev); } -static int ltc2632_remove(struct spi_device *spi) +static void ltc2632_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ltc2632_state *st = iio_priv(indio_dev); @@ -381,8 +381,6 @@ static int ltc2632_remove(struct spi_device *spi) if (st->vref_reg) regulator_disable(st->vref_reg); - - return 0; } static const struct spi_device_id ltc2632_id[] = { diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c index 0ae414ee1716..cb9e60e71b91 100644 --- a/drivers/iio/dac/mcp4922.c +++ b/drivers/iio/dac/mcp4922.c @@ -172,7 +172,7 @@ error_disable_reg: return ret; } -static int mcp4922_remove(struct spi_device *spi) +static void mcp4922_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct mcp4922_state *state; @@ -180,8 +180,6 @@ static int mcp4922_remove(struct spi_device *spi) iio_device_unregister(indio_dev); state = iio_priv(indio_dev); regulator_disable(state->vref_reg); - - return 0; } static const struct spi_device_id mcp4922_id[] = { diff --git a/drivers/iio/dac/ti-dac082s085.c b/drivers/iio/dac/ti-dac082s085.c index 6beda2193683..4e1156e6deb2 100644 --- a/drivers/iio/dac/ti-dac082s085.c +++ b/drivers/iio/dac/ti-dac082s085.c @@ -313,7 +313,7 @@ err: return ret; } -static int ti_dac_remove(struct spi_device *spi) +static void ti_dac_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ti_dac_chip *ti_dac = iio_priv(indio_dev); @@ -321,8 +321,6 @@ static int ti_dac_remove(struct spi_device *spi) iio_device_unregister(indio_dev); mutex_destroy(&ti_dac->lock); regulator_disable(ti_dac->vref); - - return 0; } static const struct of_device_id ti_dac_of_id[] = { diff --git a/drivers/iio/dac/ti-dac7311.c b/drivers/iio/dac/ti-dac7311.c index 99f275829ec2..e10d17e60ed3 100644 --- a/drivers/iio/dac/ti-dac7311.c +++ b/drivers/iio/dac/ti-dac7311.c @@ -292,7 +292,7 @@ err: return ret; } -static int ti_dac_remove(struct spi_device *spi) +static void ti_dac_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ti_dac_chip *ti_dac = iio_priv(indio_dev); @@ -300,7 +300,6 @@ static int ti_dac_remove(struct spi_device *spi) iio_device_unregister(indio_dev); mutex_destroy(&ti_dac->lock); regulator_disable(ti_dac->vref); - return 0; } static const struct of_device_id ti_dac_of_id[] = { diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 3d9eba716b69..f3521330f6fb 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -589,7 +589,7 @@ error_disable_clk: return ret; } -static int adf4350_remove(struct spi_device *spi) +static void adf4350_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct adf4350_state *st = iio_priv(indio_dev); @@ -604,8 +604,6 @@ static int adf4350_remove(struct spi_device *spi) if (!IS_ERR(reg)) regulator_disable(reg); - - return 0; } static const struct of_device_id adf4350_of_match[] = { diff --git a/drivers/iio/gyro/bmg160_spi.c b/drivers/iio/gyro/bmg160_spi.c index 745962e1e423..fc2e453527b9 100644 --- a/drivers/iio/gyro/bmg160_spi.c +++ b/drivers/iio/gyro/bmg160_spi.c @@ -27,11 +27,9 @@ static int bmg160_spi_probe(struct spi_device *spi) return bmg160_core_probe(&spi->dev, regmap, spi->irq, id->name); } -static int bmg160_spi_remove(struct spi_device *spi) +static void bmg160_spi_remove(struct spi_device *spi) { bmg160_core_remove(&spi->dev); - - return 0; } static const struct spi_device_id bmg160_spi_id[] = { diff --git a/drivers/iio/gyro/fxas21002c_spi.c b/drivers/iio/gyro/fxas21002c_spi.c index 77ceebef4e34..c3ac169facf9 100644 --- a/drivers/iio/gyro/fxas21002c_spi.c +++ b/drivers/iio/gyro/fxas21002c_spi.c @@ -34,11 +34,9 @@ static int fxas21002c_spi_probe(struct spi_device *spi) return fxas21002c_core_probe(&spi->dev, regmap, spi->irq, id->name); } -static int fxas21002c_spi_remove(struct spi_device *spi) +static void fxas21002c_spi_remove(struct spi_device *spi) { fxas21002c_core_remove(&spi->dev); - - return 0; } static const struct spi_device_id fxas21002c_spi_id[] = { diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 273f16dcaff8..856ec901b091 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -570,7 +570,7 @@ err_disable_reg: return ret; } -static int afe4403_remove(struct spi_device *spi) +static void afe4403_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct afe4403_data *afe = iio_priv(indio_dev); @@ -586,8 +586,6 @@ static int afe4403_remove(struct spi_device *spi) ret = regulator_disable(afe->regulator); if (ret) dev_warn(afe->dev, "Unable to disable regulator\n"); - - return 0; } static const struct spi_device_id afe4403_ids[] = { diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c index c6ed3ea8460a..4c570412d65c 100644 --- a/drivers/iio/magnetometer/bmc150_magn_spi.c +++ b/drivers/iio/magnetometer/bmc150_magn_spi.c @@ -29,11 +29,9 @@ static int bmc150_magn_spi_probe(struct spi_device *spi) return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name); } -static int bmc150_magn_spi_remove(struct spi_device *spi) +static void bmc150_magn_spi_remove(struct spi_device *spi) { bmc150_magn_remove(&spi->dev); - - return 0; } static const struct spi_device_id bmc150_magn_spi_id[] = { diff --git a/drivers/iio/magnetometer/hmc5843_spi.c b/drivers/iio/magnetometer/hmc5843_spi.c index 89cf59a62c28..a99dd9b33e95 100644 --- a/drivers/iio/magnetometer/hmc5843_spi.c +++ b/drivers/iio/magnetometer/hmc5843_spi.c @@ -74,11 +74,9 @@ static int hmc5843_spi_probe(struct spi_device *spi) id->driver_data, id->name); } -static int hmc5843_spi_remove(struct spi_device *spi) +static void hmc5843_spi_remove(struct spi_device *spi) { hmc5843_common_remove(&spi->dev); - - return 0; } static const struct spi_device_id hmc5843_id[] = { diff --git a/drivers/iio/potentiometer/max5487.c b/drivers/iio/potentiometer/max5487.c index 007c2bd324cb..42723c996c9f 100644 --- a/drivers/iio/potentiometer/max5487.c +++ b/drivers/iio/potentiometer/max5487.c @@ -112,7 +112,7 @@ static int max5487_spi_probe(struct spi_device *spi) return iio_device_register(indio_dev); } -static int max5487_spi_remove(struct spi_device *spi) +static void max5487_spi_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); int ret; @@ -123,8 +123,6 @@ static int max5487_spi_remove(struct spi_device *spi) ret = max5487_write_cmd(spi, MAX5487_COPY_AB_TO_NV); if (ret) dev_warn(&spi->dev, "Failed to save wiper regs to NV regs\n"); - - return 0; } static const struct spi_device_id max5487_id[] = { diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 9fa2dcd71760..7ccd960ced5d 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -107,11 +107,9 @@ static int ms5611_spi_probe(struct spi_device *spi) spi_get_device_id(spi)->driver_data); } -static int ms5611_spi_remove(struct spi_device *spi) +static void ms5611_spi_remove(struct spi_device *spi) { ms5611_remove(spi_get_drvdata(spi)); - - return 0; } static const struct of_device_id ms5611_spi_matches[] = { diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c index 85201a4bae44..ee8ed77536ca 100644 --- a/drivers/iio/pressure/zpa2326_spi.c +++ b/drivers/iio/pressure/zpa2326_spi.c @@ -57,11 +57,9 @@ static int zpa2326_probe_spi(struct spi_device *spi) spi->irq, ZPA2326_DEVICE_ID, regmap); } -static int zpa2326_remove_spi(struct spi_device *spi) +static void zpa2326_remove_spi(struct spi_device *spi) { zpa2326_remove(&spi->dev); - - return 0; } static const struct spi_device_id zpa2326_spi_ids[] = { diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c index eda1b23002b5..d1f5354d5ea2 100644 --- a/drivers/input/keyboard/applespi.c +++ b/drivers/input/keyboard/applespi.c @@ -1858,7 +1858,7 @@ static void applespi_drain_reads(struct applespi_data *applespi) spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); } -static int applespi_remove(struct spi_device *spi) +static void applespi_remove(struct spi_device *spi) { struct applespi_data *applespi = spi_get_drvdata(spi); @@ -1871,8 +1871,6 @@ static int applespi_remove(struct spi_device *spi) applespi_drain_reads(applespi); debugfs_remove_recursive(applespi->debugfs_root); - - return 0; } static void applespi_shutdown(struct spi_device *spi) diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index 6e51c9bc619f..91e44d4c66f7 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -87,13 +87,11 @@ static int adxl34x_spi_probe(struct spi_device *spi) return 0; } -static int adxl34x_spi_remove(struct spi_device *spi) +static void adxl34x_spi_remove(struct spi_device *spi) { struct adxl34x *ac = spi_get_drvdata(spi); adxl34x_remove(ac); - - return 0; } static int __maybe_unused adxl34x_spi_suspend(struct device *dev) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index a25a77dd9a32..bed68a68f330 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1411,13 +1411,11 @@ static int ads7846_probe(struct spi_device *spi) return 0; } -static int ads7846_remove(struct spi_device *spi) +static void ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = spi_get_drvdata(spi); ads7846_stop(ts); - - return 0; } static struct spi_driver ads7846_driver = { diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c index 2aec41eb76b7..5d7db84f2749 100644 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ b/drivers/input/touchscreen/cyttsp4_spi.c @@ -164,12 +164,10 @@ static int cyttsp4_spi_probe(struct spi_device *spi) return PTR_ERR_OR_ZERO(ts); } -static int cyttsp4_spi_remove(struct spi_device *spi) +static void cyttsp4_spi_remove(struct spi_device *spi) { struct cyttsp4 *ts = spi_get_drvdata(spi); cyttsp4_remove(ts); - - return 0; } static struct spi_driver cyttsp4_spi_driver = { diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index a2f55920b9b2..555dfe98b3c4 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -64,11 +64,9 @@ static int tsc2005_probe(struct spi_device *spi) tsc2005_cmd); } -static int tsc2005_remove(struct spi_device *spi) +static void tsc2005_remove(struct spi_device *spi) { tsc200x_remove(&spi->dev); - - return 0; } #ifdef CONFIG_OF diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index d03cfd3c0bfb..c87686bd7c18 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -266,14 +266,12 @@ static int cr0014114_probe(struct spi_device *spi) return 0; } -static int cr0014114_remove(struct spi_device *spi) +static void cr0014114_remove(struct spi_device *spi) { struct cr0014114 *priv = spi_get_drvdata(spi); cancel_delayed_work_sync(&priv->work); mutex_destroy(&priv->lock); - - return 0; } static const struct of_device_id cr0014114_dt_ids[] = { diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c index 20dc9b9d7dea..cf5fb1195f87 100644 --- a/drivers/leds/leds-dac124s085.c +++ b/drivers/leds/leds-dac124s085.c @@ -85,15 +85,13 @@ eledcr: return ret; } -static int dac124s085_remove(struct spi_device *spi) +static void dac124s085_remove(struct spi_device *spi) { struct dac124s085 *dac = spi_get_drvdata(spi); int i; for (i = 0; i < ARRAY_SIZE(dac->leds); i++) led_classdev_unregister(&dac->leds[i].ldev); - - return 0; } static struct spi_driver dac124s085_driver = { diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c index f9eb59a25570..7e7b617bcd56 100644 --- a/drivers/leds/leds-el15203000.c +++ b/drivers/leds/leds-el15203000.c @@ -315,13 +315,11 @@ static int el15203000_probe(struct spi_device *spi) return el15203000_probe_dt(priv); } -static int el15203000_remove(struct spi_device *spi) +static void el15203000_remove(struct spi_device *spi) { struct el15203000 *priv = spi_get_drvdata(spi); mutex_destroy(&priv->lock); - - return 0; } static const struct of_device_id el15203000_dt_ids[] = { diff --git a/drivers/leds/leds-spi-byte.c b/drivers/leds/leds-spi-byte.c index f1964c96fb15..2bc5c99daf51 100644 --- a/drivers/leds/leds-spi-byte.c +++ b/drivers/leds/leds-spi-byte.c @@ -130,13 +130,11 @@ static int spi_byte_probe(struct spi_device *spi) return 0; } -static int spi_byte_remove(struct spi_device *spi) +static void spi_byte_remove(struct spi_device *spi) { struct spi_byte_led *led = spi_get_drvdata(spi); mutex_destroy(&led->mutex); - - return 0; } static struct spi_driver spi_byte_driver = { diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c index 6f2a66bc87fb..6be4e5528879 100644 --- a/drivers/media/spi/cxd2880-spi.c +++ b/drivers/media/spi/cxd2880-spi.c @@ -625,7 +625,7 @@ fail_regulator: return ret; } -static int +static void cxd2880_spi_remove(struct spi_device *spi) { struct cxd2880_dvb_spi *dvb_spi = spi_get_drvdata(spi); @@ -643,8 +643,6 @@ cxd2880_spi_remove(struct spi_device *spi) kfree(dvb_spi); pr_info("cxd2880_spi remove ok.\n"); - - return 0; } static const struct spi_device_id cxd2880_spi_id[] = { diff --git a/drivers/media/spi/gs1662.c b/drivers/media/spi/gs1662.c index f86ef1ca1288..75c21a93e6d0 100644 --- a/drivers/media/spi/gs1662.c +++ b/drivers/media/spi/gs1662.c @@ -458,13 +458,11 @@ static int gs_probe(struct spi_device *spi) return ret; } -static int gs_remove(struct spi_device *spi) +static void gs_remove(struct spi_device *spi) { struct v4l2_subdev *sd = spi_get_drvdata(spi); v4l2_device_unregister_subdev(sd); - - return 0; } static struct spi_driver gs_driver = { diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c index 44247049a319..ad6c72c1ed04 100644 --- a/drivers/media/tuners/msi001.c +++ b/drivers/media/tuners/msi001.c @@ -472,7 +472,7 @@ err: return ret; } -static int msi001_remove(struct spi_device *spi) +static void msi001_remove(struct spi_device *spi) { struct v4l2_subdev *sd = spi_get_drvdata(spi); struct msi001_dev *dev = sd_to_msi001_dev(sd); @@ -486,7 +486,6 @@ static int msi001_remove(struct spi_device *spi) v4l2_device_unregister_subdev(&dev->sd); v4l2_ctrl_handler_free(&dev->hdl); kfree(dev); - return 0; } static const struct spi_device_id msi001_id_table[] = { diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 9fe06dda3782..03620c8efe34 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -206,13 +206,11 @@ static int arizona_spi_probe(struct spi_device *spi) return arizona_dev_init(arizona); } -static int arizona_spi_remove(struct spi_device *spi) +static void arizona_spi_remove(struct spi_device *spi) { struct arizona *arizona = spi_get_drvdata(spi); arizona_dev_exit(arizona); - - return 0; } static const struct spi_device_id arizona_spi_ids[] = { diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index 5faf3766a5e2..b79a57b45c1e 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c @@ -55,12 +55,11 @@ static int da9052_spi_probe(struct spi_device *spi) return da9052_device_init(da9052, id->driver_data); } -static int da9052_spi_remove(struct spi_device *spi) +static void da9052_spi_remove(struct spi_device *spi) { struct da9052 *da9052 = spi_get_drvdata(spi); da9052_device_exit(da9052); - return 0; } static const struct spi_device_id da9052_spi_id[] = { diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index b14d3f98e1eb..3d5ce18aa9ae 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -390,7 +390,7 @@ static int pcap_add_subdev(struct pcap_chip *pcap, return ret; } -static int ezx_pcap_remove(struct spi_device *spi) +static void ezx_pcap_remove(struct spi_device *spi) { struct pcap_chip *pcap = spi_get_drvdata(spi); unsigned long flags; @@ -410,8 +410,6 @@ static int ezx_pcap_remove(struct spi_device *spi) irq_set_chip_and_handler(i, NULL, NULL); destroy_workqueue(pcap->workqueue); - - return 0; } static int ezx_pcap_probe(struct spi_device *spi) diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index f10e53187f67..9ffab9aafd81 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -63,6 +63,8 @@ #define SPIBASE_BYT 0x54 #define SPIBASE_BYT_SZ 512 #define SPIBASE_BYT_EN BIT(1) +#define BYT_BCR 0xfc +#define BYT_BCR_WPD BIT(0) #define SPIBASE_LPT 0x3800 #define SPIBASE_LPT_SZ 512 @@ -1084,12 +1086,57 @@ wdt_done: return ret; } +static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data) +{ + u32 val; + + val = readl(base + BYT_BCR); + if (!(val & BYT_BCR_WPD)) { + val |= BYT_BCR_WPD; + writel(val, base + BYT_BCR); + val = readl(base + BYT_BCR); + } + + return val & BYT_BCR_WPD; +} + +static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data) +{ + struct pci_dev *pdev = data; + u32 bcr; + + pci_read_config_dword(pdev, BCR, &bcr); + if (!(bcr & BCR_WPD)) { + bcr |= BCR_WPD; + pci_write_config_dword(pdev, BCR, bcr); + pci_read_config_dword(pdev, BCR, &bcr); + } + + return bcr & BCR_WPD; +} + +static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data) +{ + unsigned int spi = PCI_DEVFN(13, 2); + struct pci_bus *bus = data; + u32 bcr; + + pci_bus_read_config_dword(bus, spi, BCR, &bcr); + if (!(bcr & BCR_WPD)) { + bcr |= BCR_WPD; + pci_bus_write_config_dword(bus, spi, BCR, bcr); + pci_bus_read_config_dword(bus, spi, BCR, &bcr); + } + + return bcr & BCR_WPD; +} + static int lpc_ich_init_spi(struct pci_dev *dev) { struct lpc_ich_priv *priv = pci_get_drvdata(dev); struct resource *res = &intel_spi_res[0]; struct intel_spi_boardinfo *info; - u32 spi_base, rcba, bcr; + u32 spi_base, rcba; info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev) if (spi_base & SPIBASE_BYT_EN) { res->start = spi_base & ~(SPIBASE_BYT_SZ - 1); res->end = res->start + SPIBASE_BYT_SZ - 1; + + info->set_writeable = lpc_ich_byt_set_writeable; } break; @@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev) res->start = spi_base + SPIBASE_LPT; res->end = res->start + SPIBASE_LPT_SZ - 1; - pci_read_config_dword(dev, BCR, &bcr); - info->writeable = !!(bcr & BCR_WPD); + info->set_writeable = lpc_ich_lpt_set_writeable; + info->data = dev; } break; @@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev) res->start = spi_base & 0xfffffff0; res->end = res->start + SPIBASE_APL_SZ - 1; - pci_bus_read_config_dword(bus, spi, BCR, &bcr); - info->writeable = !!(bcr & BCR_WPD); + info->set_writeable = lpc_ich_bxt_set_writeable; + info->data = bus; } pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1); diff --git a/drivers/mfd/madera-spi.c b/drivers/mfd/madera-spi.c index e860f5ff0933..da84eb50e53a 100644 --- a/drivers/mfd/madera-spi.c +++ b/drivers/mfd/madera-spi.c @@ -112,13 +112,11 @@ static int madera_spi_probe(struct spi_device *spi) return madera_dev_init(madera); } -static int madera_spi_remove(struct spi_device *spi) +static void madera_spi_remove(struct spi_device *spi) { struct madera *madera = spi_get_drvdata(spi); madera_dev_exit(madera); - - return 0; } static const struct spi_device_id madera_spi_ids[] = { diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 4d8913d647e6..f803527e5819 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -166,10 +166,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi) return mc13xxx_common_init(&spi->dev); } -static int mc13xxx_spi_remove(struct spi_device *spi) +static void mc13xxx_spi_remove(struct spi_device *spi) { mc13xxx_common_exit(&spi->dev); - return 0; } static struct spi_driver mc13xxx_spi_driver = { diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c index fec2b4ec477c..d2f3d8f1e05a 100644 --- a/drivers/mfd/rsmu_spi.c +++ b/drivers/mfd/rsmu_spi.c @@ -220,13 +220,11 @@ static int rsmu_spi_probe(struct spi_device *client) return rsmu_core_init(rsmu); } -static int rsmu_spi_remove(struct spi_device *client) +static void rsmu_spi_remove(struct spi_device *client) { struct rsmu_ddata *rsmu = spi_get_drvdata(client); rsmu_core_exit(rsmu); - - return 0; } static const struct spi_device_id rsmu_spi_id[] = { diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index 6c5915016be5..ad8055a0e286 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c @@ -102,13 +102,11 @@ stmpe_spi_probe(struct spi_device *spi) return stmpe_probe(&spi_ci, id->driver_data); } -static int stmpe_spi_remove(struct spi_device *spi) +static void stmpe_spi_remove(struct spi_device *spi) { struct stmpe *stmpe = spi_get_drvdata(spi); stmpe_remove(stmpe); - - return 0; } static const struct of_device_id stmpe_spi_of_match[] = { diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index d701926aa46e..bba38fbc781d 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -50,13 +50,11 @@ static int tps65912_spi_probe(struct spi_device *spi) return tps65912_device_init(tps); } -static int tps65912_spi_remove(struct spi_device *spi) +static void tps65912_spi_remove(struct spi_device *spi) { struct tps65912 *tps = spi_get_drvdata(spi); tps65912_device_exit(tps); - - return 0; } static const struct spi_device_id tps65912_spi_id_table[] = { diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c index a9e75d80ad36..263055bda48b 100644 --- a/drivers/misc/ad525x_dpot-spi.c +++ b/drivers/misc/ad525x_dpot-spi.c @@ -90,10 +90,9 @@ static int ad_dpot_spi_probe(struct spi_device *spi) spi_get_device_id(spi)->name); } -static int ad_dpot_spi_remove(struct spi_device *spi) +static void ad_dpot_spi_remove(struct spi_device *spi) { ad_dpot_remove(&spi->dev); - return 0; } static const struct spi_device_id ad_dpot_spi_id[] = { diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 1f15399e5cb4..b630625b3024 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -555,14 +555,12 @@ static int eeprom_93xx46_probe(struct spi_device *spi) return 0; } -static int eeprom_93xx46_remove(struct spi_device *spi) +static void eeprom_93xx46_remove(struct spi_device *spi) { struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi); if (!(edev->pdata->flags & EE_READONLY)) device_remove_file(&spi->dev, &dev_attr_erase); - - return 0; } static struct spi_driver eeprom_93xx46_driver = { diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c index 98828030b5a4..bac4df2e5231 100644 --- a/drivers/misc/lattice-ecp3-config.c +++ b/drivers/misc/lattice-ecp3-config.c @@ -211,13 +211,11 @@ static int lattice_ecp3_probe(struct spi_device *spi) return 0; } -static int lattice_ecp3_remove(struct spi_device *spi) +static void lattice_ecp3_remove(struct spi_device *spi) { struct fpga_data *data = spi_get_drvdata(spi); wait_for_completion(&data->fw_loaded); - - return 0; } static const struct spi_device_id lattice_ecp3_id[] = { diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c index 9e40dfb60742..203a108b8883 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c @@ -96,15 +96,13 @@ static int lis302dl_spi_probe(struct spi_device *spi) return lis3lv02d_init_device(&lis3_dev); } -static int lis302dl_spi_remove(struct spi_device *spi) +static void lis302dl_spi_remove(struct spi_device *spi) { struct lis3lv02d *lis3 = spi_get_drvdata(spi); lis3lv02d_joystick_disable(lis3); lis3lv02d_poweroff(lis3); lis3lv02d_remove_fs(&lis3_dev); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index a576181e9db0..106dd204b1a7 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1489,7 +1489,7 @@ nomem: } -static int mmc_spi_remove(struct spi_device *spi) +static void mmc_spi_remove(struct spi_device *spi) { struct mmc_host *mmc = dev_get_drvdata(&spi->dev); struct mmc_spi_host *host = mmc_priv(mmc); @@ -1507,7 +1507,6 @@ static int mmc_spi_remove(struct spi_device *spi) spi->max_speed_hz = mmc->f_max; mmc_spi_put_pdata(spi); mmc_free_host(mmc); - return 0; } static const struct spi_device_id mmc_spi_dev_ids[] = { diff --git a/drivers/mtd/devices/mchp23k256.c b/drivers/mtd/devices/mchp23k256.c index a8b31bddf14b..008df9d8898d 100644 --- a/drivers/mtd/devices/mchp23k256.c +++ b/drivers/mtd/devices/mchp23k256.c @@ -209,13 +209,11 @@ static int mchp23k256_probe(struct spi_device *spi) return 0; } -static int mchp23k256_remove(struct spi_device *spi) +static void mchp23k256_remove(struct spi_device *spi) { struct mchp23k256_flash *flash = spi_get_drvdata(spi); WARN_ON(mtd_device_unregister(&flash->mtd)); - - return 0; } static const struct of_device_id mchp23k256_of_table[] = { diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c index 231a10790196..a3fd426df74b 100644 --- a/drivers/mtd/devices/mchp48l640.c +++ b/drivers/mtd/devices/mchp48l640.c @@ -341,13 +341,11 @@ static int mchp48l640_probe(struct spi_device *spi) return 0; } -static int mchp48l640_remove(struct spi_device *spi) +static void mchp48l640_remove(struct spi_device *spi) { struct mchp48l640_flash *flash = spi_get_drvdata(spi); WARN_ON(mtd_device_unregister(&flash->mtd)); - - return 0; } static const struct of_device_id mchp48l640_of_table[] = { diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 734878abaa23..134e27328597 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -916,7 +916,7 @@ static int dataflash_probe(struct spi_device *spi) return status; } -static int dataflash_remove(struct spi_device *spi) +static void dataflash_remove(struct spi_device *spi) { struct dataflash *flash = spi_get_drvdata(spi); @@ -925,8 +925,6 @@ static int dataflash_remove(struct spi_device *spi) WARN_ON(mtd_device_unregister(&flash->mtd)); kfree(flash); - - return 0; } static struct spi_driver dataflash_driver = { diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index 7f124c1bfa40..8813994ce9f4 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c @@ -398,13 +398,11 @@ static int sst25l_probe(struct spi_device *spi) return 0; } -static int sst25l_remove(struct spi_device *spi) +static void sst25l_remove(struct spi_device *spi) { struct sst25l_flash *flash = spi_get_drvdata(spi); WARN_ON(mtd_device_unregister(&flash->mtd)); - - return 0; } static struct spi_driver sst25l_driver = { diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig index 5c0e0ec2e6d1..50f4f3484d42 100644 --- a/drivers/mtd/spi-nor/controllers/Kconfig +++ b/drivers/mtd/spi-nor/controllers/Kconfig @@ -26,39 +26,3 @@ config SPI_NXP_SPIFI SPIFI is a specialized controller for connecting serial SPI Flash. Enable this option if you have a device with a SPIFI controller and want to access the Flash as a mtd device. - -config SPI_INTEL_SPI - tristate - -config SPI_INTEL_SPI_PCI - tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)" - depends on X86 && PCI - select SPI_INTEL_SPI - help - This enables PCI support for the Intel PCH/PCU SPI controller in - master mode. This controller is present in modern Intel hardware - and is used to hold BIOS and other persistent settings. Using - this driver it is possible to upgrade BIOS directly from Linux. - - Say N here unless you know what you are doing. Overwriting the - SPI flash may render the system unbootable. - - To compile this driver as a module, choose M here: the module - will be called intel-spi-pci. - -config SPI_INTEL_SPI_PLATFORM - tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)" - depends on X86 - select SPI_INTEL_SPI - help - This enables platform support for the Intel PCH/PCU SPI - controller in master mode. This controller is present in modern - Intel hardware and is used to hold BIOS and other persistent - settings. Using this driver it is possible to upgrade BIOS - directly from Linux. - - Say N here unless you know what you are doing. Overwriting the - SPI flash may render the system unbootable. - - To compile this driver as a module, choose M here: the module - will be called intel-spi-platform. diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile index e7abba491d98..6e2a1dc68466 100644 --- a/drivers/mtd/spi-nor/controllers/Makefile +++ b/drivers/mtd/spi-nor/controllers/Makefile @@ -2,6 +2,3 @@ obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o -obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o -obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o -obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h deleted file mode 100644 index f2871179fd34..000000000000 --- a/drivers/mtd/spi-nor/controllers/intel-spi.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Intel PCH/PCU SPI flash driver. - * - * Copyright (C) 2016, Intel Corporation - * Author: Mika Westerberg <mika.westerberg@linux.intel.com> - */ - -#ifndef INTEL_SPI_H -#define INTEL_SPI_H - -#include <linux/platform_data/x86/intel-spi.h> - -struct intel_spi; -struct resource; - -struct intel_spi *intel_spi_probe(struct device *dev, - struct resource *mem, const struct intel_spi_boardinfo *info); -int intel_spi_remove(struct intel_spi *ispi); - -#endif /* INTEL_SPI_H */ diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c index 04687b15b250..41645a24384c 100644 --- a/drivers/net/can/m_can/tcan4x5x-core.c +++ b/drivers/net/can/m_can/tcan4x5x-core.c @@ -388,7 +388,7 @@ out_power: return ret; } -static int tcan4x5x_can_remove(struct spi_device *spi) +static void tcan4x5x_can_remove(struct spi_device *spi) { struct tcan4x5x_priv *priv = spi_get_drvdata(spi); @@ -397,8 +397,6 @@ static int tcan4x5x_can_remove(struct spi_device *spi) tcan4x5x_power_enable(priv->power, 0); m_can_class_free_dev(priv->cdev.net); - - return 0; } static const struct of_device_id tcan4x5x_of_match[] = { diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index cfcc14fe3e42..664b8f14d7b0 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -948,7 +948,7 @@ static int hi3110_can_probe(struct spi_device *spi) return dev_err_probe(dev, ret, "Probe failed\n"); } -static int hi3110_can_remove(struct spi_device *spi) +static void hi3110_can_remove(struct spi_device *spi) { struct hi3110_priv *priv = spi_get_drvdata(spi); struct net_device *net = priv->net; @@ -960,8 +960,6 @@ static int hi3110_can_remove(struct spi_device *spi) clk_disable_unprepare(priv->clk); free_candev(net); - - return 0; } static int __maybe_unused hi3110_can_suspend(struct device *dev) diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 025e07cb7439..d23edaf22420 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1427,7 +1427,7 @@ out_free: return ret; } -static int mcp251x_can_remove(struct spi_device *spi) +static void mcp251x_can_remove(struct spi_device *spi) { struct mcp251x_priv *priv = spi_get_drvdata(spi); struct net_device *net = priv->net; @@ -1442,8 +1442,6 @@ static int mcp251x_can_remove(struct spi_device *spi) clk_disable_unprepare(priv->clk); free_candev(net); - - return 0; } static int __maybe_unused mcp251x_can_suspend(struct device *dev) diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index b5986df6eca0..65c9b31666a6 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -1966,7 +1966,7 @@ static int mcp251xfd_probe(struct spi_device *spi) return err; } -static int mcp251xfd_remove(struct spi_device *spi) +static void mcp251xfd_remove(struct spi_device *spi) { struct mcp251xfd_priv *priv = spi_get_drvdata(spi); struct net_device *ndev = priv->ndev; @@ -1975,8 +1975,6 @@ static int mcp251xfd_remove(struct spi_device *spi) mcp251xfd_unregister(priv); spi->max_speed_hz = priv->spi_max_speed_hz_orig; free_candev(ndev); - - return 0; } static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device) diff --git a/drivers/net/dsa/b53/b53_spi.c b/drivers/net/dsa/b53/b53_spi.c index 2b88f03e5252..0e54b2a0c211 100644 --- a/drivers/net/dsa/b53/b53_spi.c +++ b/drivers/net/dsa/b53/b53_spi.c @@ -314,7 +314,7 @@ static int b53_spi_probe(struct spi_device *spi) return 0; } -static int b53_spi_remove(struct spi_device *spi) +static void b53_spi_remove(struct spi_device *spi) { struct b53_device *dev = spi_get_drvdata(spi); @@ -322,8 +322,6 @@ static int b53_spi_remove(struct spi_device *spi) b53_switch_remove(dev); spi_set_drvdata(spi, NULL); - - return 0; } static void b53_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index b0a7dee27ffc..5f8d94aee774 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -87,7 +87,7 @@ static int ksz8795_spi_probe(struct spi_device *spi) return 0; } -static int ksz8795_spi_remove(struct spi_device *spi) +static void ksz8795_spi_remove(struct spi_device *spi) { struct ksz_device *dev = spi_get_drvdata(spi); @@ -95,8 +95,6 @@ static int ksz8795_spi_remove(struct spi_device *spi) ksz_switch_remove(dev); spi_set_drvdata(spi, NULL); - - return 0; } static void ksz8795_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index 43addeabfc25..87ca464dad32 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -65,7 +65,7 @@ static int ksz9477_spi_probe(struct spi_device *spi) return 0; } -static int ksz9477_spi_remove(struct spi_device *spi) +static void ksz9477_spi_remove(struct spi_device *spi) { struct ksz_device *dev = spi_get_drvdata(spi); @@ -73,8 +73,6 @@ static int ksz9477_spi_remove(struct spi_device *spi) ksz_switch_remove(dev); spi_set_drvdata(spi, NULL); - - return 0; } static void ksz9477_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index b513713be610..c2a47c6693b8 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3346,18 +3346,16 @@ static int sja1105_probe(struct spi_device *spi) return dsa_register_switch(priv->ds); } -static int sja1105_remove(struct spi_device *spi) +static void sja1105_remove(struct spi_device *spi) { struct sja1105_private *priv = spi_get_drvdata(spi); if (!priv) - return 0; + return; dsa_unregister_switch(priv->ds); spi_set_drvdata(spi, NULL); - - return 0; } static void sja1105_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/vitesse-vsc73xx-spi.c b/drivers/net/dsa/vitesse-vsc73xx-spi.c index 645398901e05..3110895358d8 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-spi.c +++ b/drivers/net/dsa/vitesse-vsc73xx-spi.c @@ -159,18 +159,16 @@ static int vsc73xx_spi_probe(struct spi_device *spi) return vsc73xx_probe(&vsc_spi->vsc); } -static int vsc73xx_spi_remove(struct spi_device *spi) +static void vsc73xx_spi_remove(struct spi_device *spi) { struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi); if (!vsc_spi) - return 0; + return; vsc73xx_remove(&vsc_spi->vsc); spi_set_drvdata(spi, NULL); - - return 0; } static void vsc73xx_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c index e7a9f9863258..bf70481bb1ca 100644 --- a/drivers/net/ethernet/asix/ax88796c_main.c +++ b/drivers/net/ethernet/asix/ax88796c_main.c @@ -1102,7 +1102,7 @@ err: return ret; } -static int ax88796c_remove(struct spi_device *spi) +static void ax88796c_remove(struct spi_device *spi) { struct ax88796c_device *ax_local = dev_get_drvdata(&spi->dev); struct net_device *ndev = ax_local->ndev; @@ -1112,8 +1112,6 @@ static int ax88796c_remove(struct spi_device *spi) netif_info(ax_local, probe, ndev, "removing network device %s %s\n", dev_driver_string(&spi->dev), dev_name(&spi->dev)); - - return 0; } #ifdef CONFIG_OF diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c index 0303e727e99f..d167d93e4c12 100644 --- a/drivers/net/ethernet/micrel/ks8851_spi.c +++ b/drivers/net/ethernet/micrel/ks8851_spi.c @@ -452,11 +452,9 @@ static int ks8851_probe_spi(struct spi_device *spi) return ks8851_probe_common(netdev, dev, msg_enable); } -static int ks8851_remove_spi(struct spi_device *spi) +static void ks8851_remove_spi(struct spi_device *spi) { ks8851_remove_common(&spi->dev); - - return 0; } static const struct of_device_id ks8851_match_table[] = { diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 634ac7649c43..db5a3edb4c3c 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -1612,15 +1612,13 @@ error_alloc: return ret; } -static int enc28j60_remove(struct spi_device *spi) +static void enc28j60_remove(struct spi_device *spi) { struct enc28j60_net *priv = spi_get_drvdata(spi); unregister_netdev(priv->netdev); free_irq(spi->irq, priv); free_netdev(priv->netdev); - - return 0; } static const struct of_device_id enc28j60_dt_ids[] = { diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index b90efc80fb59..dc1840cb5b10 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1093,7 +1093,7 @@ error_out: return ret; } -static int encx24j600_spi_remove(struct spi_device *spi) +static void encx24j600_spi_remove(struct spi_device *spi) { struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev); @@ -1101,8 +1101,6 @@ static int encx24j600_spi_remove(struct spi_device *spi) kthread_stop(priv->kworker_task); free_netdev(priv->ndev); - - return 0; } static const struct spi_device_id encx24j600_spi_id_table[] = { diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 955cce644392..3c5494afd3c0 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -1001,7 +1001,7 @@ qca_spi_probe(struct spi_device *spi) return 0; } -static int +static void qca_spi_remove(struct spi_device *spi) { struct net_device *qcaspi_devs = spi_get_drvdata(spi); @@ -1011,8 +1011,6 @@ qca_spi_remove(struct spi_device *spi) unregister_netdev(qcaspi_devs); free_netdev(qcaspi_devs); - - return 0; } static const struct spi_device_id qca_spi_id[] = { diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c index 89a31783fbb4..25739b182ac7 100644 --- a/drivers/net/ethernet/vertexcom/mse102x.c +++ b/drivers/net/ethernet/vertexcom/mse102x.c @@ -731,7 +731,7 @@ static int mse102x_probe_spi(struct spi_device *spi) return 0; } -static int mse102x_remove_spi(struct spi_device *spi) +static void mse102x_remove_spi(struct spi_device *spi) { struct mse102x_net *mse = dev_get_drvdata(&spi->dev); struct mse102x_net_spi *mses = to_mse102x_spi(mse); @@ -741,8 +741,6 @@ static int mse102x_remove_spi(struct spi_device *spi) mse102x_remove_device_debugfs(mses); unregister_netdev(mse->ndev); - - return 0; } static const struct of_device_id mse102x_match_table[] = { diff --git a/drivers/net/ethernet/wiznet/w5100-spi.c b/drivers/net/ethernet/wiznet/w5100-spi.c index 7779a36da3c8..7c52796273a4 100644 --- a/drivers/net/ethernet/wiznet/w5100-spi.c +++ b/drivers/net/ethernet/wiznet/w5100-spi.c @@ -461,11 +461,9 @@ static int w5100_spi_probe(struct spi_device *spi) return w5100_probe(&spi->dev, ops, priv_size, mac, spi->irq, -EINVAL); } -static int w5100_spi_remove(struct spi_device *spi) +static void w5100_spi_remove(struct spi_device *spi) { w5100_remove(&spi->dev); - - return 0; } static const struct spi_device_id w5100_spi_ids[] = { diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index 7db9cbd0f5de..6afdf1622944 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -1304,7 +1304,7 @@ err_alloc_wq: return ret; } -static int adf7242_remove(struct spi_device *spi) +static void adf7242_remove(struct spi_device *spi) { struct adf7242_local *lp = spi_get_drvdata(spi); @@ -1316,8 +1316,6 @@ static int adf7242_remove(struct spi_device *spi) ieee802154_unregister_hw(lp->hw); mutex_destroy(&lp->bmux); ieee802154_free_hw(lp->hw); - - return 0; } static const struct of_device_id adf7242_of_match[] = { diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 4f5ef8a9a9a8..549d04b5f3d4 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1768,7 +1768,7 @@ free_dev: return rc; } -static int at86rf230_remove(struct spi_device *spi) +static void at86rf230_remove(struct spi_device *spi) { struct at86rf230_local *lp = spi_get_drvdata(spi); @@ -1778,8 +1778,6 @@ static int at86rf230_remove(struct spi_device *spi) ieee802154_free_hw(lp->hw); at86rf230_debugfs_remove(); dev_dbg(&spi->dev, "unregistered at86rf230\n"); - - return 0; } static const struct of_device_id at86rf230_of_match[] = { diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 2bc730fd260e..187cbc634ce8 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -831,7 +831,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl) finish:; } -static int ca8210_remove(struct spi_device *spi_device); +static void ca8210_remove(struct spi_device *spi_device); /** * ca8210_spi_transfer_complete() - Called when a single spi transfer has @@ -3049,7 +3049,7 @@ static void ca8210_test_interface_clear(struct ca8210_priv *priv) * * Return: 0 or linux error code */ -static int ca8210_remove(struct spi_device *spi_device) +static void ca8210_remove(struct spi_device *spi_device) { struct ca8210_priv *priv; struct ca8210_platform_data *pdata; @@ -3089,8 +3089,6 @@ static int ca8210_remove(struct spi_device *spi_device) if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS)) ca8210_test_interface_clear(priv); } - - return 0; } /** diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index 89c046b204e0..1e1f40f628a0 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -1213,7 +1213,7 @@ err_hw_init: return ret; } -static int cc2520_remove(struct spi_device *spi) +static void cc2520_remove(struct spi_device *spi) { struct cc2520_private *priv = spi_get_drvdata(spi); @@ -1222,8 +1222,6 @@ static int cc2520_remove(struct spi_device *spi) ieee802154_unregister_hw(priv->hw); ieee802154_free_hw(priv->hw); - - return 0; } static const struct spi_device_id cc2520_ids[] = { diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index 383231b85464..c927a5ae0d05 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -1335,7 +1335,7 @@ free_dev: return ret; } -static int mcr20a_remove(struct spi_device *spi) +static void mcr20a_remove(struct spi_device *spi) { struct mcr20a_local *lp = spi_get_drvdata(spi); @@ -1343,8 +1343,6 @@ static int mcr20a_remove(struct spi_device *spi) ieee802154_unregister_hw(lp->hw); ieee802154_free_hw(lp->hw); - - return 0; } static const struct of_device_id mcr20a_of_match[] = { diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index ff83e00b77af..ee4cfbf2c5cc 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -1356,7 +1356,7 @@ err_ret: return ret; } -static int mrf24j40_remove(struct spi_device *spi) +static void mrf24j40_remove(struct spi_device *spi) { struct mrf24j40 *devrec = spi_get_drvdata(spi); @@ -1366,8 +1366,6 @@ static int mrf24j40_remove(struct spi_device *spi) ieee802154_free_hw(devrec->hw); /* TODO: Will ieee802154_free_device() wait until ->xmit() is * complete? */ - - return 0; } static const struct of_device_id mrf24j40_of_match[] = { diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index 8b5445a724ce..ff37f8ba6758 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -517,7 +517,7 @@ static int ks8995_probe(struct spi_device *spi) return 0; } -static int ks8995_remove(struct spi_device *spi) +static void ks8995_remove(struct spi_device *spi) { struct ks8995_switch *ks = spi_get_drvdata(spi); @@ -526,8 +526,6 @@ static int ks8995_remove(struct spi_device *spi) /* assert reset */ if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio)) gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 1); - - return 0; } /* ------------------------------------------------------------------------ */ diff --git a/drivers/net/wan/slic_ds26522.c b/drivers/net/wan/slic_ds26522.c index 8e3b1c717c10..6063552cea9b 100644 --- a/drivers/net/wan/slic_ds26522.c +++ b/drivers/net/wan/slic_ds26522.c @@ -194,10 +194,9 @@ static int slic_ds26522_init_configure(struct spi_device *spi) return 0; } -static int slic_ds26522_remove(struct spi_device *spi) +static void slic_ds26522_remove(struct spi_device *spi) { pr_info("DS26522 module uninstalled\n"); - return 0; } static int slic_ds26522_probe(struct spi_device *spi) diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c index ab0fe8565851..f99b7ba69fc3 100644 --- a/drivers/net/wireless/intersil/p54/p54spi.c +++ b/drivers/net/wireless/intersil/p54/p54spi.c @@ -669,7 +669,7 @@ err_free: return ret; } -static int p54spi_remove(struct spi_device *spi) +static void p54spi_remove(struct spi_device *spi) { struct p54s_priv *priv = spi_get_drvdata(spi); @@ -684,8 +684,6 @@ static int p54spi_remove(struct spi_device *spi) mutex_destroy(&priv->mutex); p54_free_common(priv->hw); - - return 0; } diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index cd9f8ecf171f..ff1c7ec8c450 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -1195,7 +1195,7 @@ out: return err; } -static int libertas_spi_remove(struct spi_device *spi) +static void libertas_spi_remove(struct spi_device *spi) { struct if_spi_card *card = spi_get_drvdata(spi); struct lbs_private *priv = card->priv; @@ -1212,8 +1212,6 @@ static int libertas_spi_remove(struct spi_device *spi) if (card->pdata->teardown) card->pdata->teardown(spi); free_if_spi_card(card); - - return 0; } static int if_spi_suspend(struct device *dev) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 2c2ed4b09efd..d2db52289399 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -240,7 +240,7 @@ free: return ret; } -static int wilc_bus_remove(struct spi_device *spi) +static void wilc_bus_remove(struct spi_device *spi) { struct wilc *wilc = spi_get_drvdata(spi); struct wilc_spi *spi_priv = wilc->bus_data; @@ -248,8 +248,6 @@ static int wilc_bus_remove(struct spi_device *spi) clk_disable_unprepare(wilc->rtc_clk); wilc_netdev_cleanup(wilc); kfree(spi_priv); - - return 0; } static const struct of_device_id wilc_of_match[] = { diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c index 271ed2ce2d7f..fe0d220da44d 100644 --- a/drivers/net/wireless/st/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c @@ -423,7 +423,7 @@ static int cw1200_spi_probe(struct spi_device *func) } /* Disconnect Function to be called by SPI stack when device is disconnected */ -static int cw1200_spi_disconnect(struct spi_device *func) +static void cw1200_spi_disconnect(struct spi_device *func) { struct hwbus_priv *self = spi_get_drvdata(func); @@ -435,8 +435,6 @@ static int cw1200_spi_disconnect(struct spi_device *func) } } cw1200_spi_off(dev_get_platdata(&func->dev)); - - return 0; } static int __maybe_unused cw1200_spi_suspend(struct device *dev) diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 5b894bd6237e..9df38726e8b0 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c @@ -327,14 +327,12 @@ out_free: return ret; } -static int wl1251_spi_remove(struct spi_device *spi) +static void wl1251_spi_remove(struct spi_device *spi) { struct wl1251 *wl = spi_get_drvdata(spi); wl1251_free_hw(wl); regulator_disable(wl->vio); - - return 0; } static struct spi_driver wl1251_spi_driver = { diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 354a7e1c3315..7eae1ec2eb2b 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -546,13 +546,11 @@ out_dev_put: return ret; } -static int wl1271_remove(struct spi_device *spi) +static void wl1271_remove(struct spi_device *spi) { struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); platform_device_unregister(glue->core); - - return 0; } static struct spi_driver wl1271_spi_driver = { diff --git a/drivers/nfc/nfcmrvl/spi.c b/drivers/nfc/nfcmrvl/spi.c index 5b833a9a83f8..a38e2fcdfd39 100644 --- a/drivers/nfc/nfcmrvl/spi.c +++ b/drivers/nfc/nfcmrvl/spi.c @@ -174,12 +174,11 @@ static int nfcmrvl_spi_probe(struct spi_device *spi) return 0; } -static int nfcmrvl_spi_remove(struct spi_device *spi) +static void nfcmrvl_spi_remove(struct spi_device *spi) { struct nfcmrvl_spi_drv_data *drv_data = spi_get_drvdata(spi); nfcmrvl_nci_unregister_dev(drv_data->priv); - return 0; } static const struct of_device_id of_nfcmrvl_spi_match[] __maybe_unused = { diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c index 4e723992e74c..169eacc0a32a 100644 --- a/drivers/nfc/st-nci/spi.c +++ b/drivers/nfc/st-nci/spi.c @@ -263,13 +263,11 @@ static int st_nci_spi_probe(struct spi_device *dev) return r; } -static int st_nci_spi_remove(struct spi_device *dev) +static void st_nci_spi_remove(struct spi_device *dev) { struct st_nci_spi_phy *phy = spi_get_drvdata(dev); ndlc_remove(phy->ndlc); - - return 0; } static struct spi_device_id st_nci_spi_id_table[] = { diff --git a/drivers/nfc/st95hf/core.c b/drivers/nfc/st95hf/core.c index b23f47936473..ed704bb77226 100644 --- a/drivers/nfc/st95hf/core.c +++ b/drivers/nfc/st95hf/core.c @@ -1198,7 +1198,7 @@ err_disable_regulator: return ret; } -static int st95hf_remove(struct spi_device *nfc_spi_dev) +static void st95hf_remove(struct spi_device *nfc_spi_dev) { int result = 0; unsigned char reset_cmd = ST95HF_COMMAND_RESET; @@ -1236,8 +1236,6 @@ static int st95hf_remove(struct spi_device *nfc_spi_dev) /* disable regulator */ if (stcontext->st95hf_supply) regulator_disable(stcontext->st95hf_supply); - - return 0; } /* Register as SPI protocol driver */ diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 29ca9c328df2..21d68664fe08 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -2144,7 +2144,7 @@ err_destroy_lock: return ret; } -static int trf7970a_remove(struct spi_device *spi) +static void trf7970a_remove(struct spi_device *spi) { struct trf7970a *trf = spi_get_drvdata(spi); @@ -2160,8 +2160,6 @@ static int trf7970a_remove(struct spi_device *spi) regulator_disable(trf->regulator); mutex_destroy(&trf->lock); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index fc5aa1525d13..d49a4efe46c8 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -302,13 +302,11 @@ EXPORT_SYMBOL(cros_ec_register); * * Return: 0 on success or negative error code. */ -int cros_ec_unregister(struct cros_ec_device *ec_dev) +void cros_ec_unregister(struct cros_ec_device *ec_dev) { if (ec_dev->pd) platform_device_unregister(ec_dev->pd); platform_device_unregister(ec_dev->ec); - - return 0; } EXPORT_SYMBOL(cros_ec_unregister); diff --git a/drivers/platform/chrome/cros_ec.h b/drivers/platform/chrome/cros_ec.h index 78363dcfdf23..bbca0096868a 100644 --- a/drivers/platform/chrome/cros_ec.h +++ b/drivers/platform/chrome/cros_ec.h @@ -11,7 +11,7 @@ #include <linux/interrupt.h> int cros_ec_register(struct cros_ec_device *ec_dev); -int cros_ec_unregister(struct cros_ec_device *ec_dev); +void cros_ec_unregister(struct cros_ec_device *ec_dev); int cros_ec_suspend(struct cros_ec_device *ec_dev); int cros_ec_resume(struct cros_ec_device *ec_dev); diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c index 30c8938c27d5..22feb0fd4ce7 100644 --- a/drivers/platform/chrome/cros_ec_i2c.c +++ b/drivers/platform/chrome/cros_ec_i2c.c @@ -313,7 +313,9 @@ static int cros_ec_i2c_remove(struct i2c_client *client) { struct cros_ec_device *ec_dev = i2c_get_clientdata(client); - return cros_ec_unregister(ec_dev); + cros_ec_unregister(ec_dev); + + return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index d6306d2a096f..7651417b4a25 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -439,7 +439,9 @@ static int cros_ec_lpc_remove(struct platform_device *pdev) acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY, cros_ec_lpc_acpi_notify); - return cros_ec_unregister(ec_dev); + cros_ec_unregister(ec_dev); + + return 0; } static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = { diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 14c4046fa04d..8493af0f680e 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -786,11 +786,11 @@ static int cros_ec_spi_probe(struct spi_device *spi) return 0; } -static int cros_ec_spi_remove(struct spi_device *spi) +static void cros_ec_spi_remove(struct spi_device *spi) { struct cros_ec_device *ec_dev = spi_get_drvdata(spi); - return cros_ec_unregister(ec_dev); + cros_ec_unregister(ec_dev); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c index 0d46706afd2d..4823bd2819f6 100644 --- a/drivers/platform/olpc/olpc-xo175-ec.c +++ b/drivers/platform/olpc/olpc-xo175-ec.c @@ -648,7 +648,7 @@ static struct olpc_ec_driver olpc_xo175_ec_driver = { .ec_cmd = olpc_xo175_ec_cmd, }; -static int olpc_xo175_ec_remove(struct spi_device *spi) +static void olpc_xo175_ec_remove(struct spi_device *spi) { if (pm_power_off == olpc_xo175_ec_power_off) pm_power_off = NULL; @@ -657,8 +657,6 @@ static int olpc_xo175_ec_remove(struct spi_device *spi) platform_device_unregister(olpc_ec); olpc_ec = NULL; - - return 0; } static int olpc_xo175_ec_probe(struct spi_device *spi) diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 2f83adef966e..6d66ab5a8b17 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -185,10 +185,9 @@ static int ds1302_probe(struct spi_device *spi) return 0; } -static int ds1302_remove(struct spi_device *spi) +static void ds1302_remove(struct spi_device *spi) { spi_set_drvdata(spi, NULL); - return 0; } #ifdef CONFIG_OF diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 9ef107b99b65..ed9360486953 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -720,7 +720,7 @@ static int ds1305_probe(struct spi_device *spi) return 0; } -static int ds1305_remove(struct spi_device *spi) +static void ds1305_remove(struct spi_device *spi) { struct ds1305 *ds1305 = spi_get_drvdata(spi); @@ -730,8 +730,6 @@ static int ds1305_remove(struct spi_device *spi) devm_free_irq(&spi->dev, spi->irq, ds1305); cancel_work_sync(&ds1305->work); } - - return 0; } static struct spi_driver ds1305_driver = { diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index f14ed6c96437..ed5a6ba89a3e 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -434,11 +434,9 @@ static int ds1343_probe(struct spi_device *spi) return 0; } -static int ds1343_remove(struct spi_device *spi) +static void ds1343_remove(struct spi_device *spi) { dev_pm_clear_wake_irq(&spi->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b2a8821971e1..31a2cef3790c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -427,6 +427,45 @@ config SPI_INGENIC To compile this driver as a module, choose M here: the module will be called spi-ingenic. +config SPI_INTEL + tristate + +config SPI_INTEL_PCI + tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)" + depends on PCI + depends on X86 || COMPILE_TEST + depends on SPI_MEM + select SPI_INTEL + help + This enables PCI support for the Intel PCH/PCU SPI controller in + master mode. This controller is present in modern Intel hardware + and is used to hold BIOS and other persistent settings. Using + this driver it is possible to upgrade BIOS directly from Linux. + + Say N here unless you know what you are doing. Overwriting the + SPI flash may render the system unbootable. + + To compile this driver as a module, choose M here: the module + will be called spi-intel-pci. + +config SPI_INTEL_PLATFORM + tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)" + depends on X86 || COMPILE_TEST + depends on SPI_MEM + select SPI_INTEL + help + This enables platform support for the Intel PCH/PCU SPI + controller in master mode. This controller is present in modern + Intel hardware and is used to hold BIOS and other persistent + settings. Using this driver it is possible to upgrade BIOS + directly from Linux. + + Say N here unless you know what you are doing. Overwriting the + SPI flash may render the system unbootable. + + To compile this driver as a module, choose M here: the module + will be called spi-intel-platform. + config SPI_JCORE tristate "J-Core SPI Master" depends on OF && (SUPERH || COMPILE_TEST) @@ -866,6 +905,17 @@ config SPI_SUN6I help This enables using the SPI controller on the Allwinner A31 SoCs. +config SPI_SUNPLUS_SP7021 + tristate "Sunplus SP7021 SPI controller" + depends on SOC_SP7021 || COMPILE_TEST + help + This enables Sunplus SP7021 SPI controller driver on the SP7021 SoCs. + This driver can also be built as a module. If so, the module will be + called as spi-sunplus-sp7021. + + If you have a Sunplus SP7021 platform say Y here. + If unsure, say N. + config SPI_SYNQUACER tristate "Socionext's SynQuacer HighSpeed SPI controller" depends on ARCH_SYNQUACER || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index dd7393a6046f..3aa28ed3f761 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -61,6 +61,9 @@ obj-$(CONFIG_SPI_HISI_SFC_V3XX) += spi-hisi-sfc-v3xx.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMX) += spi-imx.o obj-$(CONFIG_SPI_INGENIC) += spi-ingenic.o +obj-$(CONFIG_SPI_INTEL) += spi-intel.o +obj-$(CONFIG_SPI_INTEL_PCI) += spi-intel-pci.o +obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o obj-$(CONFIG_SPI_JCORE) += spi-jcore.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o @@ -119,6 +122,7 @@ obj-$(CONFIG_SPI_STM32_QSPI) += spi-stm32-qspi.o obj-$(CONFIG_SPI_ST_SSC4) += spi-st-ssc4.o obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o +obj-$(CONFIG_SPI_SUNPLUS_SP7021) += spi-sunplus-sp7021.o obj-$(CONFIG_SPI_SYNQUACER) += spi-synquacer.o obj-$(CONFIG_SPI_TEGRA210_QUAD) += spi-tegra210-quad.o obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c index 4b3ac7aceaf6..cba6a4486c24 100644 --- a/drivers/spi/spi-amd.c +++ b/drivers/spi/spi-amd.c @@ -12,12 +12,17 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/spi/spi.h> +#include <linux/iopoll.h> #define AMD_SPI_CTRL0_REG 0x00 #define AMD_SPI_EXEC_CMD BIT(16) #define AMD_SPI_FIFO_CLEAR BIT(20) #define AMD_SPI_BUSY BIT(31) +#define AMD_SPI_OPCODE_REG 0x45 +#define AMD_SPI_CMD_TRIGGER_REG 0x47 +#define AMD_SPI_TRIGGER_CMD BIT(7) + #define AMD_SPI_OPCODE_MASK 0xFF #define AMD_SPI_ALT_CS_REG 0x1D @@ -34,10 +39,15 @@ #define AMD_SPI_XFER_TX 1 #define AMD_SPI_XFER_RX 2 +enum amd_spi_versions { + AMD_SPI_V1 = 1, /* AMDI0061 */ + AMD_SPI_V2, /* AMDI0062 */ +}; + struct amd_spi { void __iomem *io_remap_addr; unsigned long io_base_addr; - u32 rom_addr; + enum amd_spi_versions version; }; static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx) @@ -81,14 +91,29 @@ static void amd_spi_select_chip(struct amd_spi *amd_spi, u8 cs) amd_spi_setclear_reg8(amd_spi, AMD_SPI_ALT_CS_REG, cs, AMD_SPI_ALT_CS_MASK); } +static inline void amd_spi_clear_chip(struct amd_spi *amd_spi, u8 chip_select) +{ + amd_spi_writereg8(amd_spi, AMD_SPI_ALT_CS_REG, chip_select & ~AMD_SPI_ALT_CS_MASK); +} + static void amd_spi_clear_fifo_ptr(struct amd_spi *amd_spi) { amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR, AMD_SPI_FIFO_CLEAR); } -static void amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode) +static int amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode) { - amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, AMD_SPI_OPCODE_MASK); + switch (amd_spi->version) { + case AMD_SPI_V1: + amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, + AMD_SPI_OPCODE_MASK); + return 0; + case AMD_SPI_V2: + amd_spi_writereg8(amd_spi, AMD_SPI_OPCODE_REG, cmd_opcode); + return 0; + default: + return -ENODEV; + } } static inline void amd_spi_set_rx_count(struct amd_spi *amd_spi, u8 rx_count) @@ -103,16 +128,22 @@ static inline void amd_spi_set_tx_count(struct amd_spi *amd_spi, u8 tx_count) static int amd_spi_busy_wait(struct amd_spi *amd_spi) { - int timeout = 100000; - - /* poll for SPI bus to become idle */ - while (amd_spi_readreg32(amd_spi, AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) { - usleep_range(10, 20); - if (timeout-- < 0) - return -ETIMEDOUT; + u32 val; + int reg; + + switch (amd_spi->version) { + case AMD_SPI_V1: + reg = AMD_SPI_CTRL0_REG; + break; + case AMD_SPI_V2: + reg = AMD_SPI_STATUS_REG; + break; + default: + return -ENODEV; } - return 0; + return readl_poll_timeout(amd_spi->io_remap_addr + reg, val, + !(val & AMD_SPI_BUSY), 20, 2000000); } static int amd_spi_execute_opcode(struct amd_spi *amd_spi) @@ -123,10 +154,20 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi) if (ret) return ret; - /* Set ExecuteOpCode bit in the CTRL0 register */ - amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, AMD_SPI_EXEC_CMD); - - return 0; + switch (amd_spi->version) { + case AMD_SPI_V1: + /* Set ExecuteOpCode bit in the CTRL0 register */ + amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, + AMD_SPI_EXEC_CMD); + return 0; + case AMD_SPI_V2: + /* Trigger the command execution */ + amd_spi_setclear_reg8(amd_spi, AMD_SPI_CMD_TRIGGER_REG, + AMD_SPI_TRIGGER_CMD, AMD_SPI_TRIGGER_CMD); + return 0; + default: + return -ENODEV; + } } static int amd_spi_master_setup(struct spi_device *spi) @@ -196,6 +237,17 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi, message->actual_length = tx_len + rx_len + 1; /* complete the transaction */ message->status = 0; + + switch (amd_spi->version) { + case AMD_SPI_V1: + break; + case AMD_SPI_V2: + amd_spi_clear_chip(amd_spi, message->spi->chip_select); + break; + default: + return -ENODEV; + } + spi_finalize_current_message(master); return 0; @@ -241,6 +293,8 @@ static int amd_spi_probe(struct platform_device *pdev) } dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr); + amd_spi->version = (enum amd_spi_versions) device_get_match_data(dev); + /* Initialize the spi_master fields */ master->bus_num = 0; master->num_chipselect = 4; @@ -266,7 +320,8 @@ err_free_master: #ifdef CONFIG_ACPI static const struct acpi_device_id spi_acpi_match[] = { - { "AMDI0061", 0 }, + { "AMDI0061", AMD_SPI_V1 }, + { "AMDI0062", AMD_SPI_V2 }, {}, }; MODULE_DEVICE_TABLE(acpi, spi_acpi_match); diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index d1e287d2d9cd..607e7a49fb89 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> #include <linux/spi/spi_bitbang.h> #include <linux/bitops.h> #include <linux/clk.h> @@ -133,6 +134,38 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); } +static int ath79_exec_mem_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct ath79_spi *sp = ath79_spidev_to_sp(mem->spi); + + /* Ensures that reading is performed on device connected to hardware cs0 */ + if (mem->spi->chip_select || mem->spi->cs_gpiod) + return -ENOTSUPP; + + /* Only use for fast-read op. */ + if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN || + op->addr.nbytes != 3 || op->dummy.nbytes != 1) + return -ENOTSUPP; + + /* disable GPIO mode */ + ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); + + memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes); + + /* enable GPIO mode */ + ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); + + /* restore IOC register */ + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); + + return 0; +} + +static const struct spi_controller_mem_ops ath79_mem_ops = { + .exec_op = ath79_exec_mem_op, +}; + static int ath79_spi_probe(struct platform_device *pdev) { struct spi_master *master; @@ -154,6 +187,7 @@ static int ath79_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->flags = SPI_MASTER_GPIO_SS; master->num_chipselect = 3; + master->mem_ops = &ath79_mem_ops; sp->bitbang.master = master; sp->bitbang.chipselect = ath79_spi_chipselect; diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 7d709a8c833b..e28521922330 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -22,7 +22,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/spi/spi.h> @@ -445,25 +444,12 @@ static void bcm2835aux_spi_handle_err(struct spi_master *master, static int bcm2835aux_spi_setup(struct spi_device *spi) { - int ret; - /* sanity check for native cs */ if (spi->mode & SPI_NO_CS) return 0; - if (gpio_is_valid(spi->cs_gpio)) { - /* with gpio-cs set the GPIO to the correct level - * and as output (in case the dt has the gpio not configured - * as output but native cs) - */ - ret = gpio_direction_output(spi->cs_gpio, - (spi->mode & SPI_CS_HIGH) ? 0 : 1); - if (ret) - dev_err(&spi->dev, - "could not set gpio %i as output: %i\n", - spi->cs_gpio, ret); - - return ret; - } + + if (spi->cs_gpiod) + return 0; /* for dt-backwards compatibility: only support native on CS0 * known things not supported with broken native CS: @@ -519,6 +505,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) master->prepare_message = bcm2835aux_spi_prepare_message; master->unprepare_message = bcm2835aux_spi_unprepare_message; master->dev.of_node = pdev->dev.of_node; + master->use_gpio_descriptors = true; bs = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h index ae61d72c7d28..267342dfa738 100644 --- a/drivers/spi/spi-bitbang-txrx.h +++ b/drivers/spi/spi-bitbang-txrx.h @@ -41,6 +41,8 @@ * chips need ... there may be several reasons you'd need to tweak timings * in these routines, not just to make it faster or slower to match a * particular CPU clock rate. + * + * ToDo: Maybe the bitrev macros can be used to improve the code? */ static inline u32 @@ -106,3 +108,67 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, } return word; } + +static inline u32 +bitbang_txrx_le_cpha0(struct spi_device *spi, + unsigned int nsecs, unsigned int cpol, unsigned int flags, + u32 word, u8 bits) +{ + /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ + + u32 oldbit = !(word & 1); + /* clock starts at inactive polarity */ + for (; likely(bits); bits--) { + + /* setup LSB (to slave) on trailing edge */ + if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((word & 1) != oldbit) { + setmosi(spi, word & 1); + oldbit = word & 1; + } + } + spidelay(nsecs); /* T(setup) */ + + setsck(spi, !cpol); + spidelay(nsecs); + + /* sample LSB (from slave) on leading edge */ + word >>= 1; + if ((flags & SPI_MASTER_NO_RX) == 0) + word |= getmiso(spi) << (bits - 1); + setsck(spi, cpol); + } + return word; +} + +static inline u32 +bitbang_txrx_le_cpha1(struct spi_device *spi, + unsigned int nsecs, unsigned int cpol, unsigned int flags, + u32 word, u8 bits) +{ + /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ + + u32 oldbit = !(word & 1); + /* clock starts at inactive polarity */ + for (; likely(bits); bits--) { + + /* setup LSB (to slave) on leading edge */ + setsck(spi, !cpol); + if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((word & 1) != oldbit) { + setmosi(spi, word & 1); + oldbit = word & 1; + } + } + spidelay(nsecs); /* T(setup) */ + + setsck(spi, cpol); + spidelay(nsecs); + + /* sample LSB (from slave) on trailing edge */ + word >>= 1; + if ((flags & SPI_MASTER_NO_RX) == 0) + word |= getmiso(spi) << (bits - 1); + } + return word; +} diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index 4bc1b93fc276..3ab19be83095 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -578,10 +578,8 @@ static int cdns_xspi_probe(struct platform_device *pdev) } cdns_xspi->irq = platform_get_irq(pdev, 0); - if (cdns_xspi->irq < 0) { - dev_err(dev, "Failed to get IRQ\n"); + if (cdns_xspi->irq < 0) return -ENXIO; - } ret = devm_request_irq(dev, cdns_xspi->irq, cdns_xspi_irq_handler, IRQF_SHARED, pdev->name, cdns_xspi); diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c index b6c7467f0b59..d403a7a3021d 100644 --- a/drivers/spi/spi-fsi.c +++ b/drivers/spi/spi-fsi.c @@ -25,6 +25,7 @@ #define SPI_FSI_BASE 0x70000 #define SPI_FSI_INIT_TIMEOUT_MS 1000 +#define SPI_FSI_STATUS_TIMEOUT_MS 100 #define SPI_FSI_MAX_RX_SIZE 8 #define SPI_FSI_MAX_TX_SIZE 40 @@ -299,6 +300,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx, struct spi_transfer *transfer) { int rc = 0; + unsigned long end; u64 status = 0ULL; if (transfer->tx_buf) { @@ -315,10 +317,14 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx, if (rc) return rc; + end = jiffies + msecs_to_jiffies(SPI_FSI_STATUS_TIMEOUT_MS); do { rc = fsi_spi_status(ctx, &status, "TX"); if (rc) return rc; + + if (time_after(jiffies, end)) + return -ETIMEDOUT; } while (status & SPI_FSI_STATUS_TDR_FULL); sent += nb; @@ -329,10 +335,14 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx, u8 *rx = transfer->rx_buf; while (transfer->len > recv) { + end = jiffies + msecs_to_jiffies(SPI_FSI_STATUS_TIMEOUT_MS); do { rc = fsi_spi_status(ctx, &status, "RX"); if (rc) return rc; + + if (time_after(jiffies, end)) + return -ETIMEDOUT; } while (!(status & SPI_FSI_STATUS_RDR_FULL)); rc = fsi_spi_read_reg(ctx, SPI_FSI_DATA_RX, &in); diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0584f4d2fde2..4b12c4964a66 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -135,25 +135,37 @@ static inline int getmiso(const struct spi_device *spi) static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits); + else + return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); } static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits); + else + return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); } static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits); + else + return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); } static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits); + else + return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); } /* @@ -170,28 +182,40 @@ static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { flags = spi->master->flags; - return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits); + else + return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); } static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { flags = spi->master->flags; - return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits); + else + return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); } static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { flags = spi->master->flags; - return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits); + else + return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); } static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { flags = spi->master->flags; - return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); + if (unlikely(spi->mode & SPI_LSB_FIRST)) + return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits); + else + return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); } /*----------------------------------------------------------------------*/ @@ -378,7 +402,7 @@ static int spi_gpio_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | - SPI_CS_HIGH; + SPI_CS_HIGH | SPI_LSB_FIRST; if (!spi_gpio->mosi) { /* HW configuration without MOSI pin * diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/spi/spi-intel-pci.c index 1bc53b8bb88a..a5ef7a526a7f 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c +++ b/drivers/spi/spi-intel-pci.c @@ -2,34 +2,48 @@ /* * Intel PCH/PCU SPI flash PCI driver. * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 - 2022, Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ -#include <linux/ioport.h> -#include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> -#include "intel-spi.h" +#include "spi-intel.h" #define BCR 0xdc #define BCR_WPD BIT(0) +static bool intel_spi_pci_set_writeable(void __iomem *base, void *data) +{ + struct pci_dev *pdev = data; + u32 bcr; + + /* Try to make the chip read/write */ + pci_read_config_dword(pdev, BCR, &bcr); + if (!(bcr & BCR_WPD)) { + bcr |= BCR_WPD; + pci_write_config_dword(pdev, BCR, bcr); + pci_read_config_dword(pdev, BCR, &bcr); + } + + return bcr & BCR_WPD; +} + static const struct intel_spi_boardinfo bxt_info = { .type = INTEL_SPI_BXT, + .set_writeable = intel_spi_pci_set_writeable, }; static const struct intel_spi_boardinfo cnl_info = { .type = INTEL_SPI_CNL, + .set_writeable = intel_spi_pci_set_writeable, }; static int intel_spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct intel_spi_boardinfo *info; - struct intel_spi *ispi; - u32 bcr; int ret; ret = pcim_enable_device(pdev); @@ -41,26 +55,8 @@ static int intel_spi_pci_probe(struct pci_dev *pdev, if (!info) return -ENOMEM; - /* Try to make the chip read/write */ - pci_read_config_dword(pdev, BCR, &bcr); - if (!(bcr & BCR_WPD)) { - bcr |= BCR_WPD; - pci_write_config_dword(pdev, BCR, bcr); - pci_read_config_dword(pdev, BCR, &bcr); - } - info->writeable = !!(bcr & BCR_WPD); - - ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info); - if (IS_ERR(ispi)) - return PTR_ERR(ispi); - - pci_set_drvdata(pdev, ispi); - return 0; -} - -static void intel_spi_pci_remove(struct pci_dev *pdev) -{ - intel_spi_remove(pci_get_drvdata(pdev)); + info->data = pdev; + return intel_spi_probe(&pdev->dev, &pdev->resource[0], info); } static const struct pci_device_id intel_spi_pci_ids[] = { @@ -70,6 +66,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info }, { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, @@ -89,7 +86,6 @@ static struct pci_driver intel_spi_pci_driver = { .name = "intel-spi", .id_table = intel_spi_pci_ids, .probe = intel_spi_pci_probe, - .remove = intel_spi_pci_remove, }; module_pci_driver(intel_spi_pci_driver); diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c b/drivers/spi/spi-intel-platform.c index f80f1086f928..2ef09fa35661 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c +++ b/drivers/spi/spi-intel-platform.c @@ -2,20 +2,18 @@ /* * Intel PCH/PCU SPI flash platform driver. * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 - 2022, Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ -#include <linux/ioport.h> #include <linux/module.h> #include <linux/platform_device.h> -#include "intel-spi.h" +#include "spi-intel.h" static int intel_spi_platform_probe(struct platform_device *pdev) { struct intel_spi_boardinfo *info; - struct intel_spi *ispi; struct resource *mem; info = dev_get_platdata(&pdev->dev); @@ -23,24 +21,11 @@ static int intel_spi_platform_probe(struct platform_device *pdev) return -EINVAL; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ispi = intel_spi_probe(&pdev->dev, mem, info); - if (IS_ERR(ispi)) - return PTR_ERR(ispi); - - platform_set_drvdata(pdev, ispi); - return 0; -} - -static int intel_spi_platform_remove(struct platform_device *pdev) -{ - struct intel_spi *ispi = platform_get_drvdata(pdev); - - return intel_spi_remove(ispi); + return intel_spi_probe(&pdev->dev, mem, info); } static struct platform_driver intel_spi_platform_driver = { .probe = intel_spi_platform_probe, - .remove = intel_spi_platform_remove, .driver = { .name = "intel-spi", }, diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/spi/spi-intel.c index a413892ff449..e937cfe85559 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi.c +++ b/drivers/spi/spi-intel.c @@ -2,21 +2,21 @@ /* * Intel PCH/PCU SPI flash driver. * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 - 2022, Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ -#include <linux/err.h> -#include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/sched.h> -#include <linux/sizes.h> -#include <linux/mtd/mtd.h> + #include <linux/mtd/partitions.h> #include <linux/mtd/spi-nor.h> -#include "intel-spi.h" +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> + +#include "spi-intel.h" /* Offsets are from @ispi->base */ #define BFPREG 0x00 @@ -92,8 +92,6 @@ /* CPU specifics */ #define BYT_PR 0x74 #define BYT_SSFSTS_CTL 0x90 -#define BYT_BCR 0xfc -#define BYT_BCR_WPD BIT(0) #define BYT_FREG_NUM 5 #define BYT_PR_NUM 5 @@ -125,37 +123,43 @@ * struct intel_spi - Driver private data * @dev: Device pointer * @info: Pointer to board specific info - * @nor: SPI NOR layer structure * @base: Beginning of MMIO space * @pregs: Start of protection registers * @sregs: Start of software sequencer registers + * @master: Pointer to the SPI controller structure * @nregions: Maximum number of regions * @pr_num: Maximum number of protected range registers - * @writeable: Is the chip writeable * @locked: Is SPI setting locked * @swseq_reg: Use SW sequencer in register reads/writes * @swseq_erase: Use SW sequencer in erase operation - * @erase_64k: 64k erase supported * @atomic_preopcode: Holds preopcode when atomic sequence is requested * @opcodes: Opcodes which are supported. This are programmed by BIOS * before it locks down the controller. + * @mem_ops: Pointer to SPI MEM ops supported by the controller */ struct intel_spi { struct device *dev; const struct intel_spi_boardinfo *info; - struct spi_nor nor; void __iomem *base; void __iomem *pregs; void __iomem *sregs; + struct spi_controller *master; size_t nregions; size_t pr_num; - bool writeable; bool locked; bool swseq_reg; bool swseq_erase; - bool erase_64k; u8 atomic_preopcode; u8 opcodes[8]; + const struct intel_spi_mem_op *mem_ops; +}; + +struct intel_spi_mem_op { + struct spi_mem_op mem_op; + u32 replacement_op; + int (*exec_op)(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op); }; static bool writeable; @@ -201,9 +205,6 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) readl(ispi->sregs + OPMENU1)); } - if (ispi->info->type == INTEL_SPI_BYT) - dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR)); - dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC)); dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC)); @@ -219,9 +220,8 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) base = value & PR_BASE_MASK; dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x [%c%c]\n", - i, base << 12, (limit << 12) | 0xfff, - value & PR_WPE ? 'W' : '.', - value & PR_RPE ? 'R' : '.'); + i, base << 12, (limit << 12) | 0xfff, + value & PR_WPE ? 'W' : '.', value & PR_RPE ? 'R' : '.'); } dev_dbg(ispi->dev, "Flash regions:\n"); @@ -236,7 +236,7 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) dev_dbg(ispi->dev, " %02d disabled\n", i); else dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x\n", - i, base << 12, (limit << 12) | 0xfff); + i, base << 12, (limit << 12) | 0xfff); } dev_dbg(ispi->dev, "Using %cW sequencer for register access\n", @@ -304,124 +304,12 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi) INTEL_SPI_TIMEOUT * 1000); } -static int intel_spi_init(struct intel_spi *ispi) +static bool intel_spi_set_writeable(struct intel_spi *ispi) { - u32 opmenu0, opmenu1, lvscc, uvscc, val; - int i; - - switch (ispi->info->type) { - case INTEL_SPI_BYT: - ispi->sregs = ispi->base + BYT_SSFSTS_CTL; - ispi->pregs = ispi->base + BYT_PR; - ispi->nregions = BYT_FREG_NUM; - ispi->pr_num = BYT_PR_NUM; - ispi->swseq_reg = true; - - if (writeable) { - /* Disable write protection */ - val = readl(ispi->base + BYT_BCR); - if (!(val & BYT_BCR_WPD)) { - val |= BYT_BCR_WPD; - writel(val, ispi->base + BYT_BCR); - val = readl(ispi->base + BYT_BCR); - } - - ispi->writeable = !!(val & BYT_BCR_WPD); - } - - break; - - case INTEL_SPI_LPT: - ispi->sregs = ispi->base + LPT_SSFSTS_CTL; - ispi->pregs = ispi->base + LPT_PR; - ispi->nregions = LPT_FREG_NUM; - ispi->pr_num = LPT_PR_NUM; - ispi->swseq_reg = true; - break; - - case INTEL_SPI_BXT: - ispi->sregs = ispi->base + BXT_SSFSTS_CTL; - ispi->pregs = ispi->base + BXT_PR; - ispi->nregions = BXT_FREG_NUM; - ispi->pr_num = BXT_PR_NUM; - ispi->erase_64k = true; - break; - - case INTEL_SPI_CNL: - ispi->sregs = NULL; - ispi->pregs = ispi->base + CNL_PR; - ispi->nregions = CNL_FREG_NUM; - ispi->pr_num = CNL_PR_NUM; - break; + if (!ispi->info->set_writeable) + return false; - default: - return -EINVAL; - } - - /* Disable #SMI generation from HW sequencer */ - val = readl(ispi->base + HSFSTS_CTL); - val &= ~HSFSTS_CTL_FSMIE; - writel(val, ispi->base + HSFSTS_CTL); - - /* - * Determine whether erase operation should use HW or SW sequencer. - * - * The HW sequencer has a predefined list of opcodes, with only the - * erase opcode being programmable in LVSCC and UVSCC registers. - * If these registers don't contain a valid erase opcode, erase - * cannot be done using HW sequencer. - */ - lvscc = readl(ispi->base + LVSCC); - uvscc = readl(ispi->base + UVSCC); - if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK)) - ispi->swseq_erase = true; - /* SPI controller on Intel BXT supports 64K erase opcode */ - if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase) - if (!(lvscc & ERASE_64K_OPCODE_MASK) || - !(uvscc & ERASE_64K_OPCODE_MASK)) - ispi->erase_64k = false; - - if (ispi->sregs == NULL && (ispi->swseq_reg || ispi->swseq_erase)) { - dev_err(ispi->dev, "software sequencer not supported, but required\n"); - return -EINVAL; - } - - /* - * Some controllers can only do basic operations using hardware - * sequencer. All other operations are supposed to be carried out - * using software sequencer. - */ - if (ispi->swseq_reg) { - /* Disable #SMI generation from SW sequencer */ - val = readl(ispi->sregs + SSFSTS_CTL); - val &= ~SSFSTS_CTL_FSMIE; - writel(val, ispi->sregs + SSFSTS_CTL); - } - - /* Check controller's lock status */ - val = readl(ispi->base + HSFSTS_CTL); - ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN); - - if (ispi->locked && ispi->sregs) { - /* - * BIOS programs allowed opcodes and then locks down the - * register. So read back what opcodes it decided to support. - * That's the set we are going to support as well. - */ - opmenu0 = readl(ispi->sregs + OPMENU0); - opmenu1 = readl(ispi->sregs + OPMENU1); - - if (opmenu0 && opmenu1) { - for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { - ispi->opcodes[i] = opmenu0 >> i * 8; - ispi->opcodes[i + 4] = opmenu1 >> i * 8; - } - } - } - - intel_spi_dump_regs(ispi); - - return 0; + return ispi->info->set_writeable(ispi->base, ispi->info->data); } static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype) @@ -537,7 +425,6 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len, default: return -EINVAL; } - } writel(val, ispi->sregs + SSFSTS_CTL); @@ -554,31 +441,35 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len, return 0; } -static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, - size_t len) +static int intel_spi_read_reg(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op) { - struct intel_spi *ispi = nor->priv; + size_t nbytes = op->data.nbytes; + u8 opcode = op->cmd.opcode; int ret; /* Address of the first chip */ writel(0, ispi->base + FADDR); if (ispi->swseq_reg) - ret = intel_spi_sw_cycle(ispi, opcode, len, + ret = intel_spi_sw_cycle(ispi, opcode, nbytes, OPTYPE_READ_NO_ADDR); else - ret = intel_spi_hw_cycle(ispi, opcode, len); + ret = intel_spi_hw_cycle(ispi, opcode, nbytes); if (ret) return ret; - return intel_spi_read_block(ispi, buf, len); + return intel_spi_read_block(ispi, op->data.buf.in, nbytes); } -static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf, - size_t len) +static int intel_spi_write_reg(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op) { - struct intel_spi *ispi = nor->priv; + size_t nbytes = op->data.nbytes; + u8 opcode = op->cmd.opcode; int ret; /* @@ -623,23 +514,25 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf, writel(0, ispi->base + FADDR); /* Write the value beforehand */ - ret = intel_spi_write_block(ispi, buf, len); + ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes); if (ret) return ret; if (ispi->swseq_reg) - return intel_spi_sw_cycle(ispi, opcode, len, + return intel_spi_sw_cycle(ispi, opcode, nbytes, OPTYPE_WRITE_NO_ADDR); - return intel_spi_hw_cycle(ispi, opcode, len); + return intel_spi_hw_cycle(ispi, opcode, nbytes); } -static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, - u_char *read_buf) +static int intel_spi_read(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op) { - struct intel_spi *ispi = nor->priv; - size_t block_size, retlen = 0; + void *read_buf = op->data.buf.in; + size_t block_size, nbytes = op->data.nbytes; + u32 addr = op->addr.val; u32 val, status; - ssize_t ret; + int ret; /* * Atomic sequence is not expected with HW sequencer reads. Make @@ -648,24 +541,14 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, if (WARN_ON_ONCE(ispi->atomic_preopcode)) ispi->atomic_preopcode = 0; - switch (nor->read_opcode) { - case SPINOR_OP_READ: - case SPINOR_OP_READ_FAST: - case SPINOR_OP_READ_4B: - case SPINOR_OP_READ_FAST_4B: - break; - default: - return -EINVAL; - } - - while (len > 0) { - block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); + while (nbytes > 0) { + block_size = min_t(size_t, nbytes, INTEL_SPI_FIFO_SZ); /* Read cannot cross 4K boundary */ - block_size = min_t(loff_t, from + block_size, - round_up(from + 1, SZ_4K)) - from; + block_size = min_t(loff_t, addr + block_size, + round_up(addr + 1, SZ_4K)) - addr; - writel(from, ispi->base + FADDR); + writel(addr, ispi->base + FADDR); val = readl(ispi->base + HSFSTS_CTL); val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); @@ -686,8 +569,7 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, ret = -EACCES; if (ret < 0) { - dev_err(ispi->dev, "read error: %llx: %#x\n", from, - status); + dev_err(ispi->dev, "read error: %x: %#x\n", addr, status); return ret; } @@ -695,34 +577,35 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, if (ret) return ret; - len -= block_size; - from += block_size; - retlen += block_size; + nbytes -= block_size; + addr += block_size; read_buf += block_size; } - return retlen; + return 0; } -static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, - const u_char *write_buf) +static int intel_spi_write(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op) { - struct intel_spi *ispi = nor->priv; - size_t block_size, retlen = 0; + size_t block_size, nbytes = op->data.nbytes; + const void *write_buf = op->data.buf.out; + u32 addr = op->addr.val; u32 val, status; - ssize_t ret; + int ret; /* Not needed with HW sequencer write, make sure it is cleared */ ispi->atomic_preopcode = 0; - while (len > 0) { - block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); + while (nbytes > 0) { + block_size = min_t(size_t, nbytes, INTEL_SPI_FIFO_SZ); /* Write cannot cross 4K boundary */ - block_size = min_t(loff_t, to + block_size, - round_up(to + 1, SZ_4K)) - to; + block_size = min_t(loff_t, addr + block_size, + round_up(addr + 1, SZ_4K)) - addr; - writel(to, ispi->base + FADDR); + writel(addr, ispi->base + FADDR); val = readl(ispi->base + HSFSTS_CTL); val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); @@ -753,79 +636,476 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, ret = -EACCES; if (ret < 0) { - dev_err(ispi->dev, "write error: %llx: %#x\n", to, - status); + dev_err(ispi->dev, "write error: %x: %#x\n", addr, status); return ret; } - len -= block_size; - to += block_size; - retlen += block_size; + nbytes -= block_size; + addr += block_size; write_buf += block_size; } - return retlen; + return 0; } -static int intel_spi_erase(struct spi_nor *nor, loff_t offs) +static int intel_spi_erase(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op) { - size_t erase_size, len = nor->mtd.erasesize; - struct intel_spi *ispi = nor->priv; - u32 val, status, cmd; + u8 opcode = op->cmd.opcode; + u32 addr = op->addr.val; + u32 val, status; int ret; - /* If the hardware can do 64k erase use that when possible */ - if (len >= SZ_64K && ispi->erase_64k) { - cmd = HSFSTS_CTL_FCYCLE_ERASE_64K; - erase_size = SZ_64K; - } else { - cmd = HSFSTS_CTL_FCYCLE_ERASE; - erase_size = SZ_4K; + writel(addr, ispi->base + FADDR); + + if (ispi->swseq_erase) + return intel_spi_sw_cycle(ispi, opcode, 0, + OPTYPE_WRITE_WITH_ADDR); + + /* Not needed with HW sequencer erase, make sure it is cleared */ + ispi->atomic_preopcode = 0; + + val = readl(ispi->base + HSFSTS_CTL); + val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); + val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; + val |= HSFSTS_CTL_FGO; + val |= iop->replacement_op; + writel(val, ispi->base + HSFSTS_CTL); + + ret = intel_spi_wait_hw_busy(ispi); + if (ret) + return ret; + + status = readl(ispi->base + HSFSTS_CTL); + if (status & HSFSTS_CTL_FCERR) + return -EIO; + if (status & HSFSTS_CTL_AEL) + return -EACCES; + + return 0; +} + +static bool intel_spi_cmp_mem_op(const struct intel_spi_mem_op *iop, + const struct spi_mem_op *op) +{ + if (iop->mem_op.cmd.nbytes != op->cmd.nbytes || + iop->mem_op.cmd.buswidth != op->cmd.buswidth || + iop->mem_op.cmd.dtr != op->cmd.dtr || + iop->mem_op.cmd.opcode != op->cmd.opcode) + return false; + + if (iop->mem_op.addr.nbytes != op->addr.nbytes || + iop->mem_op.addr.dtr != op->addr.dtr) + return false; + + if (iop->mem_op.data.dir != op->data.dir || + iop->mem_op.data.dtr != op->data.dtr) + return false; + + if (iop->mem_op.data.dir != SPI_MEM_NO_DATA) { + if (iop->mem_op.data.buswidth != op->data.buswidth) + return false; + } + + return true; +} + +static const struct intel_spi_mem_op * +intel_spi_match_mem_op(struct intel_spi *ispi, const struct spi_mem_op *op) +{ + const struct intel_spi_mem_op *iop; + + for (iop = ispi->mem_ops; iop->mem_op.cmd.opcode; iop++) { + if (intel_spi_cmp_mem_op(iop, op)) + break; } - if (ispi->swseq_erase) { - while (len > 0) { - writel(offs, ispi->base + FADDR); + return iop->mem_op.cmd.opcode ? iop : NULL; +} + +static bool intel_spi_supports_mem_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + const struct intel_spi_mem_op *iop; + + iop = intel_spi_match_mem_op(ispi, op); + if (!iop) { + dev_dbg(ispi->dev, "%#x not supported\n", op->cmd.opcode); + return false; + } - ret = intel_spi_sw_cycle(ispi, nor->erase_opcode, - 0, OPTYPE_WRITE_WITH_ADDR); - if (ret) - return ret; + /* + * For software sequencer check that the opcode is actually + * present in the opmenu if it is locked. + */ + if (ispi->swseq_reg && ispi->locked) { + int i; - offs += erase_size; - len -= erase_size; + /* Check if it is in the locked opcodes list */ + for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) { + if (ispi->opcodes[i] == op->cmd.opcode) + return true; } - return 0; + dev_dbg(ispi->dev, "%#x not supported\n", op->cmd.opcode); + return false; } - /* Not needed with HW sequencer erase, make sure it is cleared */ - ispi->atomic_preopcode = 0; + return true; +} - while (len > 0) { - writel(offs, ispi->base + FADDR); +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + const struct intel_spi_mem_op *iop; - val = readl(ispi->base + HSFSTS_CTL); - val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); - val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; - val |= cmd; - val |= HSFSTS_CTL_FGO; - writel(val, ispi->base + HSFSTS_CTL); + iop = intel_spi_match_mem_op(ispi, op); + if (!iop) + return -EOPNOTSUPP; - ret = intel_spi_wait_hw_busy(ispi); - if (ret) - return ret; + return iop->exec_op(ispi, iop, op); +} - status = readl(ispi->base + HSFSTS_CTL); - if (status & HSFSTS_CTL_FCERR) - return -EIO; - else if (status & HSFSTS_CTL_AEL) - return -EACCES; +static const char *intel_spi_get_name(struct spi_mem *mem) +{ + const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + + /* + * Return name of the flash controller device to be compatible + * with the MTD version. + */ + return dev_name(ispi->dev); +} + +static const struct spi_controller_mem_ops intel_spi_mem_ops = { + .supports_op = intel_spi_supports_mem_op, + .exec_op = intel_spi_exec_mem_op, + .get_name = intel_spi_get_name, +}; + +#define INTEL_SPI_OP_ADDR(__nbytes) \ + { \ + .nbytes = __nbytes, \ + } + +#define INTEL_SPI_OP_NO_DATA \ + { \ + .dir = SPI_MEM_NO_DATA, \ + } + +#define INTEL_SPI_OP_DATA_IN(__buswidth) \ + { \ + .dir = SPI_MEM_DATA_IN, \ + .buswidth = __buswidth, \ + } + +#define INTEL_SPI_OP_DATA_OUT(__buswidth) \ + { \ + .dir = SPI_MEM_DATA_OUT, \ + .buswidth = __buswidth, \ + } + +#define INTEL_SPI_MEM_OP(__cmd, __addr, __data, __exec_op) \ + { \ + .mem_op = { \ + .cmd = __cmd, \ + .addr = __addr, \ + .data = __data, \ + }, \ + .exec_op = __exec_op, \ + } + +#define INTEL_SPI_MEM_OP_REPL(__cmd, __addr, __data, __exec_op, __repl) \ + { \ + .mem_op = { \ + .cmd = __cmd, \ + .addr = __addr, \ + .data = __data, \ + }, \ + .exec_op = __exec_op, \ + .replacement_op = __repl, \ + } + +/* + * The controller handles pretty much everything internally based on the + * SFDP data but we want to make sure we only support the operations + * actually possible. Only check buswidth and transfer direction, the + * core validates data. + */ +#define INTEL_SPI_GENERIC_OPS \ + /* Status register operations */ \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), \ + SPI_MEM_OP_NO_ADDR, \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read_reg), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), \ + SPI_MEM_OP_NO_ADDR, \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read_reg), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), \ + SPI_MEM_OP_NO_ADDR, \ + INTEL_SPI_OP_DATA_OUT(1), \ + intel_spi_write_reg), \ + /* Normal read */ \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(2), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(4), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(2), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(4), \ + intel_spi_read), \ + /* Fast read */ \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(2), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(4), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(2), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(4), \ + intel_spi_read), \ + /* Read with 4-byte address opcode */ \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(2), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(4), \ + intel_spi_read), \ + /* Fast read with 4-byte address opcode */ \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(2), \ + intel_spi_read), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_IN(4), \ + intel_spi_read), \ + /* Write operations */ \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_OUT(1), \ + intel_spi_write), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_OUT(1), \ + intel_spi_write), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + INTEL_SPI_OP_DATA_OUT(1), \ + intel_spi_write), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 1), \ + SPI_MEM_OP_NO_ADDR, \ + SPI_MEM_OP_NO_DATA, \ + intel_spi_write_reg), \ + INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 1), \ + SPI_MEM_OP_NO_ADDR, \ + SPI_MEM_OP_NO_DATA, \ + intel_spi_write_reg), \ + /* Erase operations */ \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K, 1), \ + INTEL_SPI_OP_ADDR(3), \ + SPI_MEM_OP_NO_DATA, \ + intel_spi_erase, \ + HSFSTS_CTL_FCYCLE_ERASE), \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K, 1), \ + INTEL_SPI_OP_ADDR(4), \ + SPI_MEM_OP_NO_DATA, \ + intel_spi_erase, \ + HSFSTS_CTL_FCYCLE_ERASE), \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K_4B, 1), \ + INTEL_SPI_OP_ADDR(4), \ + SPI_MEM_OP_NO_DATA, \ + intel_spi_erase, \ + HSFSTS_CTL_FCYCLE_ERASE) \ + +static const struct intel_spi_mem_op generic_mem_ops[] = { + INTEL_SPI_GENERIC_OPS, + { }, +}; + +static const struct intel_spi_mem_op erase_64k_mem_ops[] = { + INTEL_SPI_GENERIC_OPS, + /* 64k sector erase operations */ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE, 1), + INTEL_SPI_OP_ADDR(3), + SPI_MEM_OP_NO_DATA, + intel_spi_erase, + HSFSTS_CTL_FCYCLE_ERASE_64K), + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE, 1), + INTEL_SPI_OP_ADDR(4), + SPI_MEM_OP_NO_DATA, + intel_spi_erase, + HSFSTS_CTL_FCYCLE_ERASE_64K), + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE_4B, 1), + INTEL_SPI_OP_ADDR(4), + SPI_MEM_OP_NO_DATA, + intel_spi_erase, + HSFSTS_CTL_FCYCLE_ERASE_64K), + { }, +}; + +static int intel_spi_init(struct intel_spi *ispi) +{ + u32 opmenu0, opmenu1, lvscc, uvscc, val; + bool erase_64k = false; + int i; + + switch (ispi->info->type) { + case INTEL_SPI_BYT: + ispi->sregs = ispi->base + BYT_SSFSTS_CTL; + ispi->pregs = ispi->base + BYT_PR; + ispi->nregions = BYT_FREG_NUM; + ispi->pr_num = BYT_PR_NUM; + ispi->swseq_reg = true; + break; + + case INTEL_SPI_LPT: + ispi->sregs = ispi->base + LPT_SSFSTS_CTL; + ispi->pregs = ispi->base + LPT_PR; + ispi->nregions = LPT_FREG_NUM; + ispi->pr_num = LPT_PR_NUM; + ispi->swseq_reg = true; + break; + + case INTEL_SPI_BXT: + ispi->sregs = ispi->base + BXT_SSFSTS_CTL; + ispi->pregs = ispi->base + BXT_PR; + ispi->nregions = BXT_FREG_NUM; + ispi->pr_num = BXT_PR_NUM; + erase_64k = true; + break; + + case INTEL_SPI_CNL: + ispi->sregs = NULL; + ispi->pregs = ispi->base + CNL_PR; + ispi->nregions = CNL_FREG_NUM; + ispi->pr_num = CNL_PR_NUM; + break; + + default: + return -EINVAL; + } + + /* Try to disable write protection if user asked to do so */ + if (writeable && !intel_spi_set_writeable(ispi)) { + dev_warn(ispi->dev, "can't disable chip write protection\n"); + writeable = false; + } + + /* Disable #SMI generation from HW sequencer */ + val = readl(ispi->base + HSFSTS_CTL); + val &= ~HSFSTS_CTL_FSMIE; + writel(val, ispi->base + HSFSTS_CTL); - offs += erase_size; - len -= erase_size; + /* + * Determine whether erase operation should use HW or SW sequencer. + * + * The HW sequencer has a predefined list of opcodes, with only the + * erase opcode being programmable in LVSCC and UVSCC registers. + * If these registers don't contain a valid erase opcode, erase + * cannot be done using HW sequencer. + */ + lvscc = readl(ispi->base + LVSCC); + uvscc = readl(ispi->base + UVSCC); + if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK)) + ispi->swseq_erase = true; + /* SPI controller on Intel BXT supports 64K erase opcode */ + if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase) + if (!(lvscc & ERASE_64K_OPCODE_MASK) || + !(uvscc & ERASE_64K_OPCODE_MASK)) + erase_64k = false; + + if (!ispi->sregs && (ispi->swseq_reg || ispi->swseq_erase)) { + dev_err(ispi->dev, "software sequencer not supported, but required\n"); + return -EINVAL; + } + + /* + * Some controllers can only do basic operations using hardware + * sequencer. All other operations are supposed to be carried out + * using software sequencer. + */ + if (ispi->swseq_reg) { + /* Disable #SMI generation from SW sequencer */ + val = readl(ispi->sregs + SSFSTS_CTL); + val &= ~SSFSTS_CTL_FSMIE; + writel(val, ispi->sregs + SSFSTS_CTL); } + /* Check controller's lock status */ + val = readl(ispi->base + HSFSTS_CTL); + ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN); + + if (ispi->locked && ispi->sregs) { + /* + * BIOS programs allowed opcodes and then locks down the + * register. So read back what opcodes it decided to support. + * That's the set we are going to support as well. + */ + opmenu0 = readl(ispi->sregs + OPMENU0); + opmenu1 = readl(ispi->sregs + OPMENU1); + + if (opmenu0 && opmenu1) { + for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { + ispi->opcodes[i] = opmenu0 >> i * 8; + ispi->opcodes[i + 4] = opmenu1 >> i * 8; + } + } + } + + if (erase_64k) { + dev_dbg(ispi->dev, "Using erase_64k memory operations"); + ispi->mem_ops = erase_64k_mem_ops; + } else { + dev_dbg(ispi->dev, "Using generic memory operations"); + ispi->mem_ops = generic_mem_ops; + } + + intel_spi_dump_regs(ispi); return 0; } @@ -884,9 +1164,12 @@ static void intel_spi_fill_partition(struct intel_spi *ispi, /* * If any of the regions have protection bits set, make the * whole partition read-only to be on the safe side. + * + * Also if the user did not ask the chip to be writeable + * mask the bit too. */ - if (intel_spi_is_protected(ispi, base, limit)) - ispi->writeable = false; + if (!writeable || intel_spi_is_protected(ispi, base, limit)) + part->mask_flags |= MTD_WRITEABLE; end = (limit << 12) + 4096; if (end > part->size) @@ -894,75 +1177,74 @@ static void intel_spi_fill_partition(struct intel_spi *ispi, } } -static const struct spi_nor_controller_ops intel_spi_controller_ops = { - .read_reg = intel_spi_read_reg, - .write_reg = intel_spi_write_reg, - .read = intel_spi_read, - .write = intel_spi_write, - .erase = intel_spi_erase, -}; +static int intel_spi_populate_chip(struct intel_spi *ispi) +{ + struct flash_platform_data *pdata; + struct spi_board_info chip; -struct intel_spi *intel_spi_probe(struct device *dev, - struct resource *mem, const struct intel_spi_boardinfo *info) + pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->nr_parts = 1; + pdata->parts = devm_kcalloc(ispi->dev, sizeof(*pdata->parts), + pdata->nr_parts, GFP_KERNEL); + if (!pdata->parts) + return -ENOMEM; + + intel_spi_fill_partition(ispi, pdata->parts); + + memset(&chip, 0, sizeof(chip)); + snprintf(chip.modalias, 8, "spi-nor"); + chip.platform_data = pdata; + + return spi_new_device(ispi->master, &chip) ? 0 : -ENODEV; +} + +/** + * intel_spi_probe() - Probe the Intel SPI flash controller + * @dev: Pointer to the parent device + * @mem: MMIO resource + * @info: Platform spefific information + * + * Probes Intel SPI flash controller and creates the flash chip device. + * Returns %0 on success and negative errno in case of failure. + */ +int intel_spi_probe(struct device *dev, struct resource *mem, + const struct intel_spi_boardinfo *info) { - const struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ | - SNOR_HWCAPS_READ_FAST | - SNOR_HWCAPS_PP, - }; - struct mtd_partition part; + struct spi_controller *master; struct intel_spi *ispi; int ret; - if (!info || !mem) - return ERR_PTR(-EINVAL); + master = devm_spi_alloc_master(dev, sizeof(*ispi)); + if (!master) + return -ENOMEM; + + master->mem_ops = &intel_spi_mem_ops; - ispi = devm_kzalloc(dev, sizeof(*ispi), GFP_KERNEL); - if (!ispi) - return ERR_PTR(-ENOMEM); + ispi = spi_master_get_devdata(master); ispi->base = devm_ioremap_resource(dev, mem); if (IS_ERR(ispi->base)) - return ERR_CAST(ispi->base); + return PTR_ERR(ispi->base); ispi->dev = dev; + ispi->master = master; ispi->info = info; - ispi->writeable = info->writeable; ret = intel_spi_init(ispi); if (ret) - return ERR_PTR(ret); - - ispi->nor.dev = ispi->dev; - ispi->nor.priv = ispi; - ispi->nor.controller_ops = &intel_spi_controller_ops; - - ret = spi_nor_scan(&ispi->nor, NULL, &hwcaps); - if (ret) { - dev_info(dev, "failed to locate the chip\n"); - return ERR_PTR(ret); - } - - intel_spi_fill_partition(ispi, &part); - - /* Prevent writes if not explicitly enabled */ - if (!ispi->writeable || !writeable) - ispi->nor.mtd.flags &= ~MTD_WRITEABLE; + return ret; - ret = mtd_device_register(&ispi->nor.mtd, &part, 1); + ret = devm_spi_register_master(dev, master); if (ret) - return ERR_PTR(ret); + return ret; - return ispi; + return intel_spi_populate_chip(ispi); } EXPORT_SYMBOL_GPL(intel_spi_probe); -int intel_spi_remove(struct intel_spi *ispi) -{ - return mtd_device_unregister(&ispi->nor.mtd); -} -EXPORT_SYMBOL_GPL(intel_spi_remove); - MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-intel.h b/drivers/spi/spi-intel.h new file mode 100644 index 000000000000..a4f0327a46ff --- /dev/null +++ b/drivers/spi/spi-intel.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Intel PCH/PCU SPI flash driver. + * + * Copyright (C) 2016 - 2022, Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> + */ + +#ifndef SPI_INTEL_H +#define SPI_INTEL_H + +#include <linux/platform_data/x86/spi-intel.h> + +struct resource; + +int intel_spi_probe(struct device *dev, struct resource *mem, + const struct intel_spi_boardinfo *info); + +#endif /* SPI_INTEL_H */ diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index bcb52601804a..aae26f62ea87 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -906,17 +906,11 @@ static int lantiq_ssc_probe(struct platform_device *pdev) struct spi_master *master; struct lantiq_ssc_spi *spi; const struct lantiq_ssc_hwcfg *hwcfg; - const struct of_device_id *match; u32 id, supports_dma, revision; unsigned int num_cs; int err; - match = of_match_device(lantiq_ssc_match, dev); - if (!match) { - dev_err(dev, "no device match\n"); - return -EINVAL; - } - hwcfg = match->data; + hwcfg = of_device_get_match_data(dev); master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi)); if (!master) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 37f4443ce9a0..e9d83d65873b 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -854,15 +854,13 @@ static int spi_mem_probe(struct spi_device *spi) return memdrv->probe(mem); } -static int spi_mem_remove(struct spi_device *spi) +static void spi_mem_remove(struct spi_device *spi) { struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver); struct spi_mem *mem = spi_get_drvdata(spi); if (memdrv->remove) - return memdrv->remove(mem); - - return 0; + memdrv->remove(mem); } static void spi_mem_shutdown(struct spi_device *spi) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 78a9bca8cc68..03630359ce70 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -23,7 +23,6 @@ #include <linux/clk.h> #include <linux/spi/spi.h> #include <linux/fsl_devices.h> -#include <linux/gpio.h> #include <asm/mpc52xx_psc.h> enum { @@ -128,17 +127,28 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) out_be32(psc_addr(mps, ccr), ccr); mps->bits_per_word = cs->bits_per_word; - if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) - mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0); + if (spi->cs_gpiod) { + if (mps->cs_control) + /* boardfile override */ + mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0); + else + /* gpiolib will deal with the inversion */ + gpiod_set_value(spi->cs_gpiod, 1); + } } static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi) { struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); - if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) - mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1); - + if (spi->cs_gpiod) { + if (mps->cs_control) + /* boardfile override */ + mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1); + else + /* gpiolib will deal with the inversion */ + gpiod_set_value(spi->cs_gpiod, 0); + } } /* extract and scale size field in txsz or rxsz */ @@ -363,7 +373,6 @@ static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master) static int mpc512x_psc_spi_setup(struct spi_device *spi) { struct mpc512x_psc_spi_cs *cs = spi->controller_state; - int ret; if (spi->bits_per_word % 8) return -EINVAL; @@ -373,18 +382,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi) if (!cs) return -ENOMEM; - if (gpio_is_valid(spi->cs_gpio)) { - ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev)); - if (ret) { - dev_err(&spi->dev, "can't get CS gpio: %d\n", - ret); - kfree(cs); - return ret; - } - gpio_direction_output(spi->cs_gpio, - spi->mode & SPI_CS_HIGH ? 0 : 1); - } - spi->controller_state = cs; } @@ -396,8 +393,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi) static void mpc512x_psc_spi_cleanup(struct spi_device *spi) { - if (gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); kfree(spi->controller_state); } @@ -476,11 +471,6 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id) return IRQ_NONE; } -static void mpc512x_spi_cs_control(struct spi_device *spi, bool onoff) -{ - gpio_set_value(spi->cs_gpio, onoff); -} - static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, u32 size, unsigned int irq) { @@ -500,9 +490,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, mps->type = (int)of_device_get_match_data(dev); mps->irq = irq; - if (pdata == NULL) { - mps->cs_control = mpc512x_spi_cs_control; - } else { + if (pdata) { mps->cs_control = pdata->cs_control; master->bus_num = pdata->bus_num; master->num_chipselect = pdata->max_chipselect; @@ -513,6 +501,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, 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; master->dev.of_node = dev->of_node; diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 753bd313e6fd..1a0b3208dfca 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -12,7 +12,7 @@ #include <linux/ioport.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/platform_data/spi-mt65xx.h> #include <linux/pm_runtime.h> @@ -31,6 +31,7 @@ #define SPI_CFG2_REG 0x0028 #define SPI_TX_SRC_REG_64 0x002c #define SPI_RX_DST_REG_64 0x0030 +#define SPI_CFG3_IPM_REG 0x0040 #define SPI_CFG0_SCK_HIGH_OFFSET 0 #define SPI_CFG0_SCK_LOW_OFFSET 8 @@ -43,11 +44,15 @@ #define SPI_CFG1_PACKET_LOOP_OFFSET 8 #define SPI_CFG1_PACKET_LENGTH_OFFSET 16 #define SPI_CFG1_GET_TICK_DLY_OFFSET 29 +#define SPI_CFG1_GET_TICK_DLY_OFFSET_V1 30 #define SPI_CFG1_GET_TICK_DLY_MASK 0xe0000000 +#define SPI_CFG1_GET_TICK_DLY_MASK_V1 0xc0000000 + #define SPI_CFG1_CS_IDLE_MASK 0xff #define SPI_CFG1_PACKET_LOOP_MASK 0xff00 #define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 +#define SPI_CFG1_IPM_PACKET_LENGTH_MASK GENMASK(31, 16) #define SPI_CFG2_SCK_HIGH_OFFSET 0 #define SPI_CFG2_SCK_LOW_OFFSET 16 @@ -68,7 +73,13 @@ #define SPI_CMD_TX_ENDIAN BIT(15) #define SPI_CMD_FINISH_IE BIT(16) #define SPI_CMD_PAUSE_IE BIT(17) +#define SPI_CMD_IPM_NONIDLE_MODE BIT(19) +#define SPI_CMD_IPM_SPIM_LOOP BIT(21) +#define SPI_CMD_IPM_GET_TICKDLY_OFFSET 22 +#define SPI_CMD_IPM_GET_TICKDLY_MASK GENMASK(24, 22) +#define SPI_CFG3_IPM_HALF_DUPLEX_DIR BIT(2) +#define SPI_CFG3_IPM_HALF_DUPLEX_EN BIT(3) #define MT8173_SPI_MAX_PAD_SEL 3 #define MTK_SPI_PAUSE_INT_STATUS 0x2 @@ -78,6 +89,7 @@ #define MTK_SPI_MAX_FIFO_SIZE 32U #define MTK_SPI_PACKET_SIZE 1024 +#define MTK_SPI_IPM_PACKET_SIZE SZ_64K #define MTK_SPI_32BITS_MASK (0xffffffff) #define DMA_ADDR_EXT_BITS (36) @@ -93,6 +105,9 @@ struct mtk_spi_compatible { bool dma_ext; /* some IC no need unprepare SPI clk */ bool no_need_unprepare; + /* IPM design adjust and extend register to support more features */ + bool ipm_design; + }; struct mtk_spi { @@ -116,6 +131,12 @@ static const struct mtk_spi_compatible mt2712_compat = { .must_tx = true, }; +static const struct mtk_spi_compatible mtk_ipm_compat = { + .enhance_timing = true, + .dma_ext = true, + .ipm_design = true, +}; + static const struct mtk_spi_compatible mt6765_compat = { .need_pad_sel = true, .must_tx = true, @@ -157,6 +178,9 @@ static const struct mtk_chip_config mtk_default_chip_info = { }; static const struct of_device_id mtk_spi_of_match[] = { + { .compatible = "mediatek,spi-ipm", + .data = (void *)&mtk_ipm_compat, + }, { .compatible = "mediatek,mt2701-spi", .data = (void *)&mtk_common_compat, }, @@ -275,12 +299,11 @@ static int mtk_spi_set_hw_cs_timing(struct spi_device *spi) return 0; } -static int mtk_spi_prepare_message(struct spi_master *master, - struct spi_message *msg) +static int mtk_spi_hw_init(struct spi_master *master, + struct spi_device *spi) { u16 cpha, cpol; u32 reg_val; - struct spi_device *spi = msg->spi; struct mtk_chip_config *chip_config = spi->controller_data; struct mtk_spi *mdata = spi_master_get_devdata(master); @@ -288,6 +311,15 @@ static int mtk_spi_prepare_message(struct spi_master *master, cpol = spi->mode & SPI_CPOL ? 1 : 0; reg_val = readl(mdata->base + SPI_CMD_REG); + if (mdata->dev_comp->ipm_design) { + /* SPI transfer without idle time until packet length done */ + reg_val |= SPI_CMD_IPM_NONIDLE_MODE; + if (spi->mode & SPI_LOOP) + reg_val |= SPI_CMD_IPM_SPIM_LOOP; + else + reg_val &= ~SPI_CMD_IPM_SPIM_LOOP; + } + if (cpha) reg_val |= SPI_CMD_CPHA; else @@ -345,17 +377,39 @@ static int mtk_spi_prepare_message(struct spi_master *master, mdata->base + SPI_PAD_SEL_REG); /* tick delay */ - reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; - reg_val |= ((chip_config->tick_delay & 0x7) - << SPI_CFG1_GET_TICK_DLY_OFFSET); - writel(reg_val, mdata->base + SPI_CFG1_REG); + if (mdata->dev_comp->enhance_timing) { + if (mdata->dev_comp->ipm_design) { + reg_val = readl(mdata->base + SPI_CMD_REG); + reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; + reg_val |= ((chip_config->tick_delay & 0x7) + << SPI_CMD_IPM_GET_TICKDLY_OFFSET); + writel(reg_val, mdata->base + SPI_CMD_REG); + } else { + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; + reg_val |= ((chip_config->tick_delay & 0x7) + << SPI_CFG1_GET_TICK_DLY_OFFSET); + writel(reg_val, mdata->base + SPI_CFG1_REG); + } + } else { + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; + reg_val |= ((chip_config->tick_delay & 0x3) + << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); + writel(reg_val, mdata->base + SPI_CFG1_REG); + } /* set hw cs timing */ mtk_spi_set_hw_cs_timing(spi); return 0; } +static int mtk_spi_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + return mtk_spi_hw_init(master, msg->spi); +} + static void mtk_spi_set_cs(struct spi_device *spi, bool enable) { u32 reg_val; @@ -377,13 +431,13 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) } static void mtk_spi_prepare_transfer(struct spi_master *master, - struct spi_transfer *xfer) + u32 speed_hz) { u32 div, sck_time, reg_val; struct mtk_spi *mdata = spi_master_get_devdata(master); - if (xfer->speed_hz < mdata->spi_clk_hz / 2) - div = DIV_ROUND_UP(mdata->spi_clk_hz, xfer->speed_hz); + if (speed_hz < mdata->spi_clk_hz / 2) + div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz); else div = 1; @@ -414,12 +468,24 @@ static void mtk_spi_setup_packet(struct spi_master *master) u32 packet_size, packet_loop, reg_val; struct mtk_spi *mdata = spi_master_get_devdata(master); - packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE); + if (mdata->dev_comp->ipm_design) + packet_size = min_t(u32, + mdata->xfer_len, + MTK_SPI_IPM_PACKET_SIZE); + else + packet_size = min_t(u32, + mdata->xfer_len, + MTK_SPI_PACKET_SIZE); + packet_loop = mdata->xfer_len / packet_size; reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK); + if (mdata->dev_comp->ipm_design) + reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK; + else + reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK; reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; + reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK; reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; writel(reg_val, mdata->base + SPI_CFG1_REG); } @@ -514,7 +580,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, 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); + mtk_spi_prepare_transfer(master, xfer->speed_hz); mtk_spi_setup_packet(master); if (xfer->tx_buf) { @@ -547,7 +613,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); + mtk_spi_prepare_transfer(master, xfer->speed_hz); cmd = readl(mdata->base + SPI_CMD_REG); if (xfer->tx_buf) @@ -582,6 +648,19 @@ static int mtk_spi_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { + struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + u32 reg_val = 0; + + /* prepare xfer direction and duplex mode */ + if (mdata->dev_comp->ipm_design) { + if (!xfer->tx_buf || !xfer->rx_buf) { + reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; + if (xfer->rx_buf) + reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; + } + writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); + } + if (master->can_dma(master, spi, xfer)) return mtk_spi_dma_transfer(master, spi, xfer); else @@ -605,8 +684,9 @@ static int mtk_spi_setup(struct spi_device *spi) if (!spi->controller_data) spi->controller_data = (void *)&mtk_default_chip_info; - if (mdata->dev_comp->need_pad_sel && gpio_is_valid(spi->cs_gpio)) - gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) + /* CS de-asserted, gpiolib will handle inversion */ + gpiod_direction_output(spi->cs_gpiod, 0); return 0; } @@ -730,6 +810,7 @@ static int mtk_spi_probe(struct platform_device *pdev) 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; of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node); if (!of_id) { @@ -746,6 +827,8 @@ static int mtk_spi_probe(struct platform_device *pdev) if (mdata->dev_comp->must_tx) master->flags = SPI_MASTER_MUST_TX; + if (mdata->dev_comp->ipm_design) + master->mode_bits |= SPI_LOOP; if (mdata->dev_comp->need_pad_sel) { mdata->pad_num = of_property_count_u32_elems( @@ -853,25 +936,12 @@ static int mtk_spi_probe(struct platform_device *pdev) goto err_disable_runtime_pm; } - if (!master->cs_gpios && master->num_chipselect > 1) { + if (!master->cs_gpiods && master->num_chipselect > 1) { dev_err(&pdev->dev, "cs_gpios not specified and num_chipselect > 1\n"); ret = -EINVAL; goto err_disable_runtime_pm; } - - if (master->cs_gpios) { - for (i = 0; i < master->num_chipselect; i++) { - ret = devm_gpio_request(&pdev->dev, - master->cs_gpios[i], - dev_name(&pdev->dev)); - if (ret) { - dev_err(&pdev->dev, - "can't get CS GPIO %i\n", i); - goto err_disable_runtime_pm; - } - } - } } if (mdata->dev_comp->dma_ext) diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 5c93730615f8..94fb09696677 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -95,6 +95,17 @@ #define CLK_TO_US(sp, clkcnt) DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000) +struct mtk_nor_caps { + u8 dma_bits; + + /* extra_dummy_bit is adding for the IP of new SoCs. + * Some new SoCs modify the timing of fetching registers' values + * and IDs of nor flash, they need a extra_dummy_bit which can add + * more clock cycles for fetching data. + */ + u8 extra_dummy_bit; +}; + struct mtk_nor { struct spi_controller *ctlr; struct device *dev; @@ -104,11 +115,13 @@ struct mtk_nor { struct clk *spi_clk; struct clk *ctlr_clk; struct clk *axi_clk; + struct clk *axi_s_clk; unsigned int spi_freq; bool wbuf_en; bool has_irq; bool high_dma; struct completion op_done; + const struct mtk_nor_caps *caps; }; static inline void mtk_nor_rmw(struct mtk_nor *sp, u32 reg, u32 set, u32 clr) @@ -554,7 +567,12 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op) } // trigger op - writel(prg_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT); + if (rx_len) + writel(prg_len * BITS_PER_BYTE + sp->caps->extra_dummy_bit, + sp->base + MTK_NOR_REG_PRG_CNT); + else + writel(prg_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT); + ret = mtk_nor_cmd_exec(sp, MTK_NOR_CMD_PROGRAM, prg_len * BITS_PER_BYTE); if (ret) @@ -674,6 +692,7 @@ static void mtk_nor_disable_clk(struct mtk_nor *sp) clk_disable_unprepare(sp->spi_clk); clk_disable_unprepare(sp->ctlr_clk); clk_disable_unprepare(sp->axi_clk); + clk_disable_unprepare(sp->axi_s_clk); } static int mtk_nor_enable_clk(struct mtk_nor *sp) @@ -697,6 +716,14 @@ static int mtk_nor_enable_clk(struct mtk_nor *sp) return ret; } + ret = clk_prepare_enable(sp->axi_s_clk); + if (ret) { + clk_disable_unprepare(sp->spi_clk); + clk_disable_unprepare(sp->ctlr_clk); + clk_disable_unprepare(sp->axi_clk); + return ret; + } + return 0; } @@ -743,9 +770,25 @@ static const struct spi_controller_mem_ops mtk_nor_mem_ops = { .exec_op = mtk_nor_exec_op }; +static const struct mtk_nor_caps mtk_nor_caps_mt8173 = { + .dma_bits = 32, + .extra_dummy_bit = 0, +}; + +static const struct mtk_nor_caps mtk_nor_caps_mt8186 = { + .dma_bits = 32, + .extra_dummy_bit = 1, +}; + +static const struct mtk_nor_caps mtk_nor_caps_mt8192 = { + .dma_bits = 36, + .extra_dummy_bit = 0, +}; + static const struct of_device_id mtk_nor_match[] = { - { .compatible = "mediatek,mt8192-nor", .data = (void *)36 }, - { .compatible = "mediatek,mt8173-nor", .data = (void *)32 }, + { .compatible = "mediatek,mt8173-nor", .data = &mtk_nor_caps_mt8173 }, + { .compatible = "mediatek,mt8186-nor", .data = &mtk_nor_caps_mt8186 }, + { .compatible = "mediatek,mt8192-nor", .data = &mtk_nor_caps_mt8192 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mtk_nor_match); @@ -754,10 +797,10 @@ static int mtk_nor_probe(struct platform_device *pdev) { struct spi_controller *ctlr; struct mtk_nor *sp; + struct mtk_nor_caps *caps; void __iomem *base; - struct clk *spi_clk, *ctlr_clk, *axi_clk; + struct clk *spi_clk, *ctlr_clk, *axi_clk, *axi_s_clk; int ret, irq; - unsigned long dma_bits; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) @@ -775,10 +818,16 @@ static int mtk_nor_probe(struct platform_device *pdev) if (IS_ERR(axi_clk)) return PTR_ERR(axi_clk); - dma_bits = (unsigned long)of_device_get_match_data(&pdev->dev); - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits))) { - dev_err(&pdev->dev, "failed to set dma mask(%lu)\n", dma_bits); - return -EINVAL; + axi_s_clk = devm_clk_get_optional(&pdev->dev, "axi_s"); + if (IS_ERR(axi_s_clk)) + return PTR_ERR(axi_s_clk); + + caps = (struct mtk_nor_caps *)of_device_get_match_data(&pdev->dev); + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(caps->dma_bits)); + if (ret) { + dev_err(&pdev->dev, "failed to set dma mask(%u)\n", caps->dma_bits); + return ret; } ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp)); @@ -808,7 +857,9 @@ static int mtk_nor_probe(struct platform_device *pdev) sp->spi_clk = spi_clk; sp->ctlr_clk = ctlr_clk; sp->axi_clk = axi_clk; - sp->high_dma = (dma_bits > 32); + sp->axi_s_clk = axi_s_clk; + sp->caps = caps; + sp->high_dma = caps->dma_bits > 32; sp->buffer = dmam_alloc_coherent(&pdev->dev, MTK_NOR_BOUNCE_BUF_SIZE + MTK_NOR_DMA_ALIGN, &sp->buffer_dma, GFP_KERNEL); diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index b62471ab6d7f..ba67dbed9fb8 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -201,7 +201,7 @@ struct fiu_data { int fiu_max; }; -static const struct npcm_fiu_info npxm7xx_fiu_info[] = { +static const struct npcm_fiu_info npcm7xx_fiu_info[] = { {.name = "FIU0", .fiu_id = FIU0, .max_map_size = MAP_SIZE_128MB, .max_cs = 2}, {.name = "FIU3", .fiu_id = FIU3, @@ -209,8 +209,8 @@ static const struct npcm_fiu_info npxm7xx_fiu_info[] = { {.name = "FIUX", .fiu_id = FIUX, .max_map_size = MAP_SIZE_16MB, .max_cs = 2} }; -static const struct fiu_data npxm7xx_fiu_data = { - .npcm_fiu_data_info = npxm7xx_fiu_info, +static const struct fiu_data npcm7xx_fiu_data = { + .npcm_fiu_data_info = npcm7xx_fiu_info, .fiu_max = 3, }; @@ -664,14 +664,13 @@ static const struct spi_controller_mem_ops npcm_fiu_mem_ops = { }; static const struct of_device_id npcm_fiu_dt_ids[] = { - { .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data }, + { .compatible = "nuvoton,npcm750-fiu", .data = &npcm7xx_fiu_data }, { /* sentinel */ } }; static int npcm_fiu_probe(struct platform_device *pdev) { const struct fiu_data *fiu_data_match; - const struct of_device_id *match; struct device *dev = &pdev->dev; struct spi_controller *ctrl; struct npcm_fiu_spi *fiu; @@ -685,13 +684,12 @@ static int npcm_fiu_probe(struct platform_device *pdev) fiu = spi_controller_get_devdata(ctrl); - match = of_match_device(npcm_fiu_dt_ids, dev); - if (!match || !match->data) { + fiu_data_match = of_device_get_match_data(dev); + if (!fiu_data_match) { dev_err(dev, "No compatible OF match\n"); return -ENODEV; } - fiu_data_match = match->data; id = of_alias_get_id(dev->of_node, "fiu"); if (id < 0 || id >= fiu_data_match->fiu_max) { dev_err(dev, "Invalid platform device id: %d\n", id); diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index f86433b29260..7e5c09a7d489 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -591,18 +591,16 @@ static int pic32_spi_setup(struct spi_device *spi) * unreliable/erroneous SPI transactions. * To avoid that we will always handle /CS by toggling GPIO. */ - if (!gpio_is_valid(spi->cs_gpio)) + if (!spi->cs_gpiod) return -EINVAL; - gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); - return 0; } static void pic32_spi_cleanup(struct spi_device *spi) { - /* de-activate cs-gpio */ - gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + /* de-activate cs-gpio, gpiolib will handle inversion */ + gpiod_direction_output(spi->cs_gpiod, 0); } static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) @@ -784,6 +782,7 @@ static int pic32_spi_probe(struct platform_device *pdev) master->unprepare_message = pic32_spi_unprepare_message; master->prepare_transfer_hardware = pic32_spi_prepare_hardware; master->unprepare_transfer_hardware = pic32_spi_unprepare_hardware; + master->use_gpio_descriptors = true; /* optional DMA support */ ret = pic32_spi_dma_prep(pic32s, &pdev->dev); diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 2e134eb4bd2c..861b21c63504 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -15,32 +15,20 @@ #include <linux/dmaengine.h> #include <linux/platform_data/dma-dw.h> -enum { - PORT_QUARK_X1000, - PORT_BYT, - PORT_MRFLD, - PORT_BSW0, - PORT_BSW1, - PORT_BSW2, - PORT_CE4100, - PORT_LPT0, - PORT_LPT1, -}; +#define PCI_DEVICE_ID_INTEL_QUARK_X1000 0x0935 +#define PCI_DEVICE_ID_INTEL_BYT 0x0f0e +#define PCI_DEVICE_ID_INTEL_MRFLD 0x1194 +#define PCI_DEVICE_ID_INTEL_BSW0 0x228e +#define PCI_DEVICE_ID_INTEL_BSW1 0x2290 +#define PCI_DEVICE_ID_INTEL_BSW2 0x22ac +#define PCI_DEVICE_ID_INTEL_CE4100 0x2e6a +#define PCI_DEVICE_ID_INTEL_LPT0_0 0x9c65 +#define PCI_DEVICE_ID_INTEL_LPT0_1 0x9c66 +#define PCI_DEVICE_ID_INTEL_LPT1_0 0x9ce5 +#define PCI_DEVICE_ID_INTEL_LPT1_1 0x9ce6 struct pxa_spi_info { - enum pxa_ssp_type type; - int port_id; - int num_chipselect; - unsigned long max_clk_rate; - - /* DMA channel request parameters */ - bool (*dma_filter)(struct dma_chan *chan, void *param); - void *tx_param; - void *rx_param; - - int dma_burst_size; - - int (*setup)(struct pci_dev *pdev, struct pxa_spi_info *c); + int (*setup)(struct pci_dev *pdev, struct pxa2xx_spi_controller *c); }; static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; @@ -65,6 +53,24 @@ static struct dw_dma_slave lpt1_rx_param = { .src_id = 1 }; static struct dw_dma_slave lpt0_tx_param = { .dst_id = 2 }; static struct dw_dma_slave lpt0_rx_param = { .src_id = 3 }; +static void pxa2xx_spi_pci_clk_unregister(void *clk) +{ + clk_unregister(clk); +} + +static int pxa2xx_spi_pci_clk_register(struct pci_dev *dev, struct ssp_device *ssp, + unsigned long rate) +{ + char buf[40]; + + snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); + ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, rate); + if (IS_ERR(ssp->clk)) + return PTR_ERR(ssp->clk); + + return devm_add_action_or_reset(&dev->dev, pxa2xx_spi_pci_clk_unregister, ssp->clk); +} + static bool lpss_dma_filter(struct dma_chan *chan, void *param) { struct dw_dma_slave *dws = param; @@ -76,55 +82,131 @@ static bool lpss_dma_filter(struct dma_chan *chan, void *param) return true; } -static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) +static void lpss_dma_put_device(void *dma_dev) { + pci_dev_put(dma_dev); +} + +static int lpss_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) +{ + struct ssp_device *ssp = &c->ssp; + struct dw_dma_slave *tx, *rx; struct pci_dev *dma_dev; + int ret; - c->num_chipselect = 1; - c->max_clk_rate = 50000000; + switch (dev->device) { + case PCI_DEVICE_ID_INTEL_BYT: + ssp->type = LPSS_BYT_SSP; + ssp->port_id = 0; + c->tx_param = &byt_tx_param; + c->rx_param = &byt_rx_param; + break; + case PCI_DEVICE_ID_INTEL_BSW0: + ssp->type = LPSS_BSW_SSP; + ssp->port_id = 0; + c->tx_param = &bsw0_tx_param; + c->rx_param = &bsw0_rx_param; + break; + case PCI_DEVICE_ID_INTEL_BSW1: + ssp->type = LPSS_BSW_SSP; + ssp->port_id = 1; + c->tx_param = &bsw1_tx_param; + c->rx_param = &bsw1_rx_param; + break; + case PCI_DEVICE_ID_INTEL_BSW2: + ssp->type = LPSS_BSW_SSP; + ssp->port_id = 2; + c->tx_param = &bsw2_tx_param; + c->rx_param = &bsw2_rx_param; + break; + case PCI_DEVICE_ID_INTEL_LPT0_0: + case PCI_DEVICE_ID_INTEL_LPT1_0: + ssp->type = LPSS_LPT_SSP; + ssp->port_id = 0; + c->tx_param = &lpt0_tx_param; + c->rx_param = &lpt0_rx_param; + break; + case PCI_DEVICE_ID_INTEL_LPT0_1: + case PCI_DEVICE_ID_INTEL_LPT1_1: + ssp->type = LPSS_LPT_SSP; + ssp->port_id = 1; + c->tx_param = &lpt1_tx_param; + c->rx_param = &lpt1_rx_param; + break; + default: + return -ENODEV; + } - dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + c->num_chipselect = 1; - if (c->tx_param) { - struct dw_dma_slave *slave = c->tx_param; + ret = pxa2xx_spi_pci_clk_register(dev, ssp, 50000000); + if (ret) + return ret; - slave->dma_dev = &dma_dev->dev; - slave->m_master = 0; - slave->p_master = 1; - } + dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev); + if (ret) + return ret; - if (c->rx_param) { - struct dw_dma_slave *slave = c->rx_param; + tx = c->tx_param; + tx->dma_dev = &dma_dev->dev; + tx->m_master = 0; + tx->p_master = 1; - slave->dma_dev = &dma_dev->dev; - slave->m_master = 0; - slave->p_master = 1; - } + rx = c->rx_param; + rx->dma_dev = &dma_dev->dev; + rx->m_master = 0; + rx->p_master = 1; c->dma_filter = lpss_dma_filter; + c->dma_burst_size = 1; + c->enable_dma = 1; return 0; } -static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) +static const struct pxa_spi_info lpss_info_config = { + .setup = lpss_spi_setup, +}; + +static int ce4100_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) { - struct pci_dev *dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0)); + struct ssp_device *ssp = &c->ssp; + + ssp->type = PXA25x_SSP; + ssp->port_id = dev->devfn; + c->num_chipselect = dev->devfn; + + return pxa2xx_spi_pci_clk_register(dev, ssp, 3686400); +} + +static const struct pxa_spi_info ce4100_info_config = { + .setup = ce4100_spi_setup, +}; + +static int mrfld_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) +{ + struct ssp_device *ssp = &c->ssp; struct dw_dma_slave *tx, *rx; + struct pci_dev *dma_dev; + int ret; + + ssp->type = MRFLD_SSP; switch (PCI_FUNC(dev->devfn)) { case 0: - c->port_id = 3; + ssp->port_id = 3; c->num_chipselect = 1; c->tx_param = &mrfld3_tx_param; c->rx_param = &mrfld3_rx_param; break; case 1: - c->port_id = 5; + ssp->port_id = 5; c->num_chipselect = 4; c->tx_param = &mrfld5_tx_param; c->rx_param = &mrfld5_rx_param; break; case 2: - c->port_id = 6; + ssp->port_id = 6; c->num_chipselect = 1; c->tx_param = &mrfld6_tx_param; c->rx_param = &mrfld6_rx_param; @@ -133,6 +215,15 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) return -ENODEV; } + ret = pxa2xx_spi_pci_clk_register(dev, ssp, 25000000); + if (ret) + return ret; + + dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0)); + ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev); + if (ret) + return ret; + tx = c->tx_param; tx->dma_dev = &dma_dev->dev; @@ -141,81 +232,38 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) c->dma_filter = lpss_dma_filter; c->dma_burst_size = 8; + c->enable_dma = 1; return 0; } -static struct pxa_spi_info spi_info_configs[] = { - [PORT_CE4100] = { - .type = PXA25x_SSP, - .port_id = -1, - .num_chipselect = -1, - .max_clk_rate = 3686400, - }, - [PORT_BYT] = { - .type = LPSS_BYT_SSP, - .port_id = 0, - .setup = lpss_spi_setup, - .tx_param = &byt_tx_param, - .rx_param = &byt_rx_param, - }, - [PORT_BSW0] = { - .type = LPSS_BSW_SSP, - .port_id = 0, - .setup = lpss_spi_setup, - .tx_param = &bsw0_tx_param, - .rx_param = &bsw0_rx_param, - }, - [PORT_BSW1] = { - .type = LPSS_BSW_SSP, - .port_id = 1, - .setup = lpss_spi_setup, - .tx_param = &bsw1_tx_param, - .rx_param = &bsw1_rx_param, - }, - [PORT_BSW2] = { - .type = LPSS_BSW_SSP, - .port_id = 2, - .setup = lpss_spi_setup, - .tx_param = &bsw2_tx_param, - .rx_param = &bsw2_rx_param, - }, - [PORT_MRFLD] = { - .type = MRFLD_SSP, - .max_clk_rate = 25000000, - .setup = mrfld_spi_setup, - }, - [PORT_QUARK_X1000] = { - .type = QUARK_X1000_SSP, - .port_id = -1, - .num_chipselect = 1, - .max_clk_rate = 50000000, - }, - [PORT_LPT0] = { - .type = LPSS_LPT_SSP, - .port_id = 0, - .setup = lpss_spi_setup, - .tx_param = &lpt0_tx_param, - .rx_param = &lpt0_rx_param, - }, - [PORT_LPT1] = { - .type = LPSS_LPT_SSP, - .port_id = 1, - .setup = lpss_spi_setup, - .tx_param = &lpt1_tx_param, - .rx_param = &lpt1_rx_param, - }, +static const struct pxa_spi_info mrfld_info_config = { + .setup = mrfld_spi_setup, +}; + +static int qrk_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) +{ + struct ssp_device *ssp = &c->ssp; + + ssp->type = QUARK_X1000_SSP; + ssp->port_id = dev->devfn; + c->num_chipselect = 1; + + return pxa2xx_spi_pci_clk_register(dev, ssp, 50000000); +} + +static const struct pxa_spi_info qrk_info_config = { + .setup = qrk_spi_setup, }; static int pxa2xx_spi_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { + const struct pxa_spi_info *info; struct platform_device_info pi; int ret; struct platform_device *pdev; struct pxa2xx_spi_controller spi_pdata; struct ssp_device *ssp; - struct pxa_spi_info *c; - char buf[40]; ret = pcim_enable_device(dev); if (ret) @@ -225,27 +273,17 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, if (ret) return ret; - c = &spi_info_configs[ent->driver_data]; - if (c->setup) { - ret = c->setup(dev, c); - if (ret) - return ret; - } - memset(&spi_pdata, 0, sizeof(spi_pdata)); - spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn; - spi_pdata.dma_filter = c->dma_filter; - spi_pdata.tx_param = c->tx_param; - spi_pdata.rx_param = c->rx_param; - spi_pdata.enable_dma = c->rx_param && c->tx_param; - spi_pdata.dma_burst_size = c->dma_burst_size ? c->dma_burst_size : 1; ssp = &spi_pdata.ssp; ssp->dev = &dev->dev; ssp->phys_base = pci_resource_start(dev, 0); ssp->mmio_base = pcim_iomap_table(dev)[0]; - ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn; - ssp->type = c->type; + + info = (struct pxa_spi_info *)ent->driver_data; + ret = info->setup(dev, &spi_pdata); + if (ret) + return ret; pci_set_master(dev); @@ -254,14 +292,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, return ret; ssp->irq = pci_irq_vector(dev, 0); - snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); - ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, - c->max_clk_rate); - if (IS_ERR(ssp->clk)) - return PTR_ERR(ssp->clk); - memset(&pi, 0, sizeof(pi)); - pi.fwnode = dev->dev.fwnode; + pi.fwnode = dev_fwnode(&dev->dev); pi.parent = &dev->dev; pi.name = "pxa2xx-spi"; pi.id = ssp->port_id; @@ -269,10 +301,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, pi.size_data = sizeof(spi_pdata); pdev = platform_device_register_full(&pi); - if (IS_ERR(pdev)) { - clk_unregister(ssp->clk); + if (IS_ERR(pdev)) return PTR_ERR(pdev); - } pci_set_drvdata(dev, pdev); @@ -282,26 +312,22 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, static void pxa2xx_spi_pci_remove(struct pci_dev *dev) { struct platform_device *pdev = pci_get_drvdata(dev); - struct pxa2xx_spi_controller *spi_pdata; - - spi_pdata = dev_get_platdata(&pdev->dev); platform_device_unregister(pdev); - clk_unregister(spi_pdata->ssp.clk); } static const struct pci_device_id pxa2xx_spi_pci_devices[] = { - { PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 }, - { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, - { PCI_VDEVICE(INTEL, 0x1194), PORT_MRFLD }, - { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, - { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, - { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 }, - { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, - { PCI_VDEVICE(INTEL, 0x9c65), PORT_LPT0 }, - { PCI_VDEVICE(INTEL, 0x9c66), PORT_LPT1 }, - { PCI_VDEVICE(INTEL, 0x9ce5), PORT_LPT0 }, - { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT1 }, + { PCI_DEVICE_DATA(INTEL, QUARK_X1000, &qrk_info_config) }, + { PCI_DEVICE_DATA(INTEL, BYT, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, MRFLD, &mrfld_info_config) }, + { PCI_DEVICE_DATA(INTEL, BSW0, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, BSW1, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, BSW2, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, CE4100, &ce4100_info_config) }, + { PCI_DEVICE_DATA(INTEL, LPT0_0, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, LPT0_1, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, LPT1_0, &lpss_info_config) }, + { PCI_DEVICE_DATA(INTEL, LPT1_1, &lpss_info_config) }, { } }; MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index e88f86274eeb..edb42d08857d 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -13,7 +13,6 @@ #include <linux/err.h> #include <linux/errno.h> #include <linux/gpio/consumer.h> -#include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/ioport.h> @@ -1163,57 +1162,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller) return 0; } -static void cleanup_cs(struct spi_device *spi) -{ - if (!gpio_is_valid(spi->cs_gpio)) - return; - - gpio_free(spi->cs_gpio); - spi->cs_gpio = -ENOENT; -} - -static int setup_cs(struct spi_device *spi, struct chip_data *chip, - struct pxa2xx_spi_chip *chip_info) -{ - struct driver_data *drv_data = spi_controller_get_devdata(spi->controller); - - if (chip == NULL) - return 0; - - if (chip_info == NULL) - return 0; - - if (drv_data->ssp_type == CE4100_SSP) - return 0; - - /* - * NOTE: setup() can be called multiple times, possibly with - * different chip_info, release previously requested GPIO. - */ - cleanup_cs(spi); - - if (gpio_is_valid(chip_info->gpio_cs)) { - int gpio = chip_info->gpio_cs; - int err; - - err = gpio_request(gpio, "SPI_CS"); - if (err) { - dev_err(&spi->dev, "failed to request chip select GPIO%d\n", gpio); - return err; - } - - err = gpio_direction_output(gpio, !(spi->mode & SPI_CS_HIGH)); - if (err) { - gpio_free(gpio); - return err; - } - - spi->cs_gpio = gpio; - } - - return 0; -} - static int setup(struct spi_device *spi) { struct pxa2xx_spi_chip *chip_info; @@ -1222,7 +1170,6 @@ static int setup(struct spi_device *spi) struct driver_data *drv_data = spi_controller_get_devdata(spi->controller); uint tx_thres, tx_hi_thres, rx_thres; - int err; switch (drv_data->ssp_type) { case QUARK_X1000_SSP: @@ -1365,21 +1312,13 @@ static int setup(struct spi_device *spi) spi_set_ctldata(spi, chip); - if (drv_data->ssp_type == CE4100_SSP) - return 0; - - err = setup_cs(spi, chip, chip_info); - if (err) - kfree(chip); - - return err; + return 0; } static void cleanup(struct spi_device *spi) { struct chip_data *chip = spi_get_ctldata(spi); - cleanup_cs(spi); kfree(chip); } @@ -1455,6 +1394,11 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP }, + /* RPL-S */ + { PCI_VDEVICE(INTEL, 0x7a2a), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x7a2b), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x7a79), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x7a7b), LPSS_CNL_SSP }, /* ADL-S */ { PCI_VDEVICE(INTEL, 0x7aaa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x7aab), LPSS_CNL_SSP }, diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index d39dec6d1c91..00d6084306b4 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -593,7 +593,6 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) { struct spi_qup *controller = dev_id; u32 opflags, qup_err, spi_err; - unsigned long flags; int error = 0; qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS); @@ -625,10 +624,10 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) error = -EIO; } - spin_lock_irqsave(&controller->lock, flags); + spin_lock(&controller->lock); if (!controller->error) controller->error = error; - spin_unlock_irqrestore(&controller->lock, flags); + spin_unlock(&controller->lock); if (spi_qup_is_dma_xfer(controller->mode)) { writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c index a46b38544027..bd87d3c92dd3 100644 --- a/drivers/spi/spi-rockchip-sfc.c +++ b/drivers/spi/spi-rockchip-sfc.c @@ -624,10 +624,8 @@ static int rockchip_sfc_probe(struct platform_device *pdev) /* Find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Failed to get the irq\n"); + if (ret < 0) goto err_irq; - } ret = devm_request_irq(dev, ret, rockchip_sfc_irq_handler, 0, pdev->name, sfc); diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index c6a1bb09be05..cdc16eecaf6b 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -133,7 +133,8 @@ #define INT_TF_OVERFLOW (1 << 1) #define INT_RF_UNDERFLOW (1 << 2) #define INT_RF_OVERFLOW (1 << 3) -#define INT_RF_FULL (1 << 4) +#define INT_RF_FULL (1 << 4) +#define INT_CS_INACTIVE (1 << 6) /* Bit fields in ICR, 4bit */ #define ICR_MASK 0x0f @@ -194,6 +195,8 @@ struct rockchip_spi { bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; bool slave_abort; + bool cs_inactive; /* spi slave tansmition stop when cs inactive */ + struct spi_transfer *xfer; /* Store xfer temporarily */ }; static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable) @@ -275,8 +278,9 @@ static void rockchip_spi_handle_err(struct spi_controller *ctlr, */ spi_enable_chip(rs, false); - /* make sure all interrupts are masked */ + /* make sure all interrupts are masked and status cleared */ writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); + writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); if (atomic_read(&rs->state) & TXDMA) dmaengine_terminate_async(ctlr->dma_tx); @@ -343,6 +347,15 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id) struct spi_controller *ctlr = dev_id; struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + /* When int_cs_inactive comes, spi slave abort */ + if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_IMR) & INT_CS_INACTIVE) { + ctlr->slave_abort(ctlr); + writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); + writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); + + return IRQ_HANDLED; + } + if (rs->tx_left) rockchip_spi_pio_writer(rs); @@ -350,6 +363,7 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id) if (!rs->rx_left) { spi_enable_chip(rs, false); writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); + writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); spi_finalize_current_transfer(ctlr); } @@ -357,14 +371,18 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id) } static int rockchip_spi_prepare_irq(struct rockchip_spi *rs, - struct spi_transfer *xfer) + struct spi_controller *ctlr, + struct spi_transfer *xfer) { rs->tx = xfer->tx_buf; rs->rx = xfer->rx_buf; rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0; rs->rx_left = xfer->len / rs->n_bytes; - writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR); + if (rs->cs_inactive) + writel_relaxed(INT_RF_FULL | INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR); + else + writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR); spi_enable_chip(rs, true); if (rs->tx_left) @@ -383,6 +401,9 @@ static void rockchip_spi_dma_rxcb(void *data) if (state & TXDMA && !rs->slave_abort) return; + if (rs->cs_inactive) + writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); + spi_enable_chip(rs, false); spi_finalize_current_transfer(ctlr); } @@ -423,14 +444,16 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs, atomic_set(&rs->state, 0); + rs->tx = xfer->tx_buf; + rs->rx = xfer->rx_buf; + rxdesc = NULL; if (xfer->rx_buf) { struct dma_slave_config rxconf = { .direction = DMA_DEV_TO_MEM, .src_addr = rs->dma_addr_rx, .src_addr_width = rs->n_bytes, - .src_maxburst = rockchip_spi_calc_burst_size(xfer->len / - rs->n_bytes), + .src_maxburst = rockchip_spi_calc_burst_size(xfer->len / rs->n_bytes), }; dmaengine_slave_config(ctlr->dma_rx, &rxconf); @@ -474,10 +497,13 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs, /* rx must be started before tx due to spi instinct */ if (rxdesc) { atomic_or(RXDMA, &rs->state); - dmaengine_submit(rxdesc); + ctlr->dma_rx->cookie = dmaengine_submit(rxdesc); dma_async_issue_pending(ctlr->dma_rx); } + if (rs->cs_inactive) + writel_relaxed(INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR); + spi_enable_chip(rs, true); if (txdesc) { @@ -584,7 +610,42 @@ static size_t rockchip_spi_max_transfer_size(struct spi_device *spi) static int rockchip_spi_slave_abort(struct spi_controller *ctlr) { struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + u32 rx_fifo_left; + struct dma_tx_state state; + enum dma_status status; + + /* Get current dma rx point */ + if (atomic_read(&rs->state) & RXDMA) { + dmaengine_pause(ctlr->dma_rx); + status = dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state); + if (status == DMA_ERROR) { + rs->rx = rs->xfer->rx_buf; + rs->xfer->len = 0; + rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR); + for (; rx_fifo_left; rx_fifo_left--) + readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR); + goto out; + } else { + rs->rx += rs->xfer->len - rs->n_bytes * state.residue; + } + } + + /* Get the valid data left in rx fifo and set rs->xfer->len real rx size */ + if (rs->rx) { + rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR); + for (; rx_fifo_left; rx_fifo_left--) { + u32 rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR); + + if (rs->n_bytes == 1) + *(u8 *)rs->rx = (u8)rxw; + else + *(u16 *)rs->rx = (u16)rxw; + rs->rx += rs->n_bytes; + } + rs->xfer->len = (unsigned int)(rs->rx - rs->xfer->rx_buf); + } +out: if (atomic_read(&rs->state) & RXDMA) dmaengine_terminate_sync(ctlr->dma_rx); if (atomic_read(&rs->state) & TXDMA) @@ -626,7 +687,7 @@ static int rockchip_spi_transfer_one( } rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2; - + rs->xfer = xfer; use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false; ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave); @@ -636,7 +697,7 @@ static int rockchip_spi_transfer_one( if (use_dma) return rockchip_spi_prepare_dma(rs, ctlr, xfer); - return rockchip_spi_prepare_irq(rs, xfer); + return rockchip_spi_prepare_irq(rs, ctlr, xfer); } static bool rockchip_spi_can_dma(struct spi_controller *ctlr, @@ -653,6 +714,29 @@ static bool rockchip_spi_can_dma(struct spi_controller *ctlr, return xfer->len / bytes_per_word >= rs->fifo_len; } +static int rockchip_spi_setup(struct spi_device *spi) +{ + struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller); + u32 cr0; + + pm_runtime_get_sync(rs->dev); + + cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0); + + cr0 &= ~(0x3 << CR0_SCPH_OFFSET); + cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET); + if (spi->mode & SPI_CS_HIGH && spi->chip_select <= 1) + cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET; + else if (spi->chip_select <= 1) + cr0 &= ~(BIT(spi->chip_select) << CR0_SOI_OFFSET); + + writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); + + pm_runtime_put(rs->dev); + + return 0; +} + static int rockchip_spi_probe(struct platform_device *pdev) { int ret; @@ -780,6 +864,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) ctlr->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX; ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT); + ctlr->setup = rockchip_spi_setup; ctlr->set_cs = rockchip_spi_set_cs; ctlr->transfer_one = rockchip_spi_transfer_one; ctlr->max_transfer_size = rockchip_spi_max_transfer_size; @@ -815,8 +900,13 @@ static int rockchip_spi_probe(struct platform_device *pdev) switch (readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION)) { case ROCKCHIP_SPI_VER2_TYPE2: ctlr->mode_bits |= SPI_CS_HIGH; + if (ctlr->can_dma && slave_mode) + rs->cs_inactive = true; + else + rs->cs_inactive = false; break; default: + rs->cs_inactive = false; break; } @@ -875,14 +965,14 @@ static int rockchip_spi_suspend(struct device *dev) { int ret; struct spi_controller *ctlr = dev_get_drvdata(dev); + struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); ret = spi_controller_suspend(ctlr); if (ret < 0) return ret; - ret = pm_runtime_force_suspend(dev); - if (ret < 0) - return ret; + clk_disable_unprepare(rs->spiclk); + clk_disable_unprepare(rs->apb_pclk); pinctrl_pm_select_sleep_state(dev); @@ -897,10 +987,14 @@ static int rockchip_spi_resume(struct device *dev) pinctrl_pm_select_default_state(dev); - ret = pm_runtime_force_resume(dev); + ret = clk_prepare_enable(rs->apb_pclk); if (ret < 0) return ret; + ret = clk_prepare_enable(rs->spiclk); + if (ret < 0) + clk_disable_unprepare(rs->apb_pclk); + ret = spi_controller_resume(ctlr); if (ret < 0) { clk_disable_unprepare(rs->spiclk); @@ -942,7 +1036,7 @@ static int rockchip_spi_runtime_resume(struct device *dev) #endif /* CONFIG_PM */ static const struct dev_pm_ops rockchip_spi_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume) SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend, rockchip_spi_runtime_resume, NULL) }; diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index d6f51695ca5b..660aa866af06 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -12,7 +12,6 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/platform_device.h> -#include <linux/gpio.h> #include <linux/io.h> #include <linux/slab.h> @@ -62,9 +61,6 @@ struct s3c24xx_spi { unsigned char fiq_inuse; unsigned char fiq_claimed; - void (*set_cs)(struct s3c2410_spi_info *spi, - int cs, int pol); - /* data buffers */ const unsigned char *tx; unsigned char *rx; @@ -84,29 +80,21 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev) return spi_master_get_devdata(sdev->master); } -static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol) -{ - gpio_set_value(spi->pin_cs, pol); -} - static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) { struct s3c24xx_spi_devstate *cs = spi->controller_state; struct s3c24xx_spi *hw = to_hw(spi); - unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; /* change the chipselect state and the state of the spi engine clock */ switch (value) { case BITBANG_CS_INACTIVE: - hw->set_cs(hw->pdata, spi->chip_select, cspol^1); writeb(cs->spcon, hw->regs + S3C2410_SPCON); break; case BITBANG_CS_ACTIVE: writeb(cs->spcon | S3C2410_SPCON_ENSCK, hw->regs + S3C2410_SPCON); - hw->set_cs(hw->pdata, spi->chip_select, cspol); break; } } @@ -452,14 +440,6 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw) writeb(0xff, hw->regs + S3C2410_SPPRE); writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); - - if (hw->pdata) { - if (hw->set_cs == s3c24xx_spi_gpiocs) - gpio_direction_output(hw->pdata->pin_cs, 1); - - if (hw->pdata->gpio_setup) - hw->pdata->gpio_setup(hw->pdata, 1); - } } static int s3c24xx_spi_probe(struct platform_device *pdev) @@ -502,6 +482,9 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) master->num_chipselect = hw->pdata->num_cs; master->bus_num = pdata->bus_num; master->bits_per_word_mask = SPI_BPW_MASK(8); + /* we need to call the local chipselect callback */ + master->flags = SPI_MASTER_GPIO_SS; + master->use_gpio_descriptors = true; /* setup the state for the bitbang driver */ @@ -541,27 +524,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) goto err_no_pdata; } - /* setup any gpio we can */ - - if (!pdata->set_cs) { - if (pdata->pin_cs < 0) { - dev_err(&pdev->dev, "No chipselect pin\n"); - err = -EINVAL; - goto err_register; - } - - err = devm_gpio_request(&pdev->dev, pdata->pin_cs, - dev_name(&pdev->dev)); - if (err) { - dev_err(&pdev->dev, "Failed to get gpio for cs\n"); - goto err_register; - } - - hw->set_cs = s3c24xx_spi_gpiocs; - gpio_direction_output(pdata->pin_cs, 1); - } else - hw->set_cs = pdata->set_cs; - s3c24xx_spi_initialsetup(hw); /* register our spi controller */ @@ -604,9 +566,6 @@ static int s3c24xx_spi_suspend(struct device *dev) if (ret) return ret; - if (hw->pdata && hw->pdata->gpio_setup) - hw->pdata->gpio_setup(hw->pdata, 0); - clk_disable(hw->clk); return 0; } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8755cd85e83c..c26440e9058d 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -13,10 +13,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> -#include <linux/gpio.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/platform_data/spi-s3c64xx.h> @@ -656,7 +654,11 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master, struct s3c64xx_spi_csinfo *cs = spi->controller_data; /* Configure feedback delay */ - writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); + if (!cs) + /* No delay if not defined */ + writel(0, sdd->regs + S3C64XX_SPI_FB_CLK); + else + writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); return 0; } @@ -796,16 +798,14 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( return ERR_PTR(-EINVAL); } - data_np = of_get_child_by_name(slave_np, "controller-data"); - if (!data_np) { - dev_err(&spi->dev, "child node 'controller-data' not found\n"); - return ERR_PTR(-EINVAL); - } - cs = kzalloc(sizeof(*cs), GFP_KERNEL); - if (!cs) { - of_node_put(data_np); + if (!cs) return ERR_PTR(-ENOMEM); + + data_np = of_get_child_by_name(slave_np, "controller-data"); + if (!data_np) { + dev_info(&spi->dev, "feedback delay set to default (0)\n"); + return cs; } of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay); @@ -830,34 +830,16 @@ static int s3c64xx_spi_setup(struct spi_device *spi) if (spi->dev.of_node) { cs = s3c64xx_get_slave_ctrldata(spi); spi->controller_data = cs; - } else if (cs) { - /* On non-DT platforms the SPI core will set spi->cs_gpio - * to -ENOENT. The GPIO pin used to drive the chip select - * is defined by using platform data so spi->cs_gpio value - * has to be override to have the proper GPIO pin number. - */ - spi->cs_gpio = cs->line; } - if (IS_ERR_OR_NULL(cs)) { + /* NULL is fine, we just avoid using the FB delay (=0) */ + if (IS_ERR(cs)) { dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select); return -ENODEV; } - if (!spi_get_ctldata(spi)) { - if (gpio_is_valid(spi->cs_gpio)) { - err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH, - dev_name(&spi->dev)); - if (err) { - dev_err(&spi->dev, - "Failed to get /CS gpio [%d]: %d\n", - spi->cs_gpio, err); - goto err_gpio_req; - } - } - + if (!spi_get_ctldata(spi)) spi_set_ctldata(spi, cs); - } pm_runtime_get_sync(&sdd->pdev->dev); @@ -909,11 +891,9 @@ setup_exit: /* setup() returns with device de-selected */ s3c64xx_spi_set_cs(spi, false); - if (gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); spi_set_ctldata(spi, NULL); -err_gpio_req: + /* This was dynamically allocated on the DT path */ if (spi->dev.of_node) kfree(cs); @@ -924,19 +904,9 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); - if (gpio_is_valid(spi->cs_gpio)) { - gpio_free(spi->cs_gpio); - if (spi->dev.of_node) - kfree(cs); - else { - /* On non-DT platforms, the SPI core sets - * spi->cs_gpio to -ENOENT and .setup() - * overrides it with the GPIO pin value - * passed using platform data. - */ - spi->cs_gpio = -ENOENT; - } - } + /* This was dynamically allocated on the DT path */ + if (spi->dev.of_node) + kfree(cs); spi_set_ctldata(spi, NULL); } @@ -1131,6 +1101,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->prepare_message = s3c64xx_spi_prepare_message; master->transfer_one = s3c64xx_spi_transfer_one; master->num_chipselect = sci->num_cs; + master->use_gpio_descriptors = true; master->dma_alignment = 8; master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | SPI_BPW_MASK(8); @@ -1442,6 +1413,16 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; +static struct s3c64xx_spi_port_config fsd_spi_port_config = { + .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, + .rx_lvl_offset = 15, + .tx_st_done = 25, + .high_speed = true, + .clk_from_cmu = true, + .clk_ioclk = false, + .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, +}; + static const struct platform_device_id s3c64xx_spi_driver_ids[] = { { .name = "s3c2443-spi", @@ -1472,6 +1453,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "samsung,exynos5433-spi", .data = (void *)&exynos5433_spi_port_config, }, + { .compatible = "tesla,fsd-spi", + .data = (void *)&fsd_spi_port_config, + }, { }, }; MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); diff --git a/drivers/spi/spi-slave-system-control.c b/drivers/spi/spi-slave-system-control.c index 169f3d595f60..d37cfe995a63 100644 --- a/drivers/spi/spi-slave-system-control.c +++ b/drivers/spi/spi-slave-system-control.c @@ -132,13 +132,12 @@ static int spi_slave_system_control_probe(struct spi_device *spi) return 0; } -static int spi_slave_system_control_remove(struct spi_device *spi) +static void spi_slave_system_control_remove(struct spi_device *spi) { struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi); spi_slave_abort(spi); wait_for_completion(&priv->finished); - return 0; } static struct spi_driver spi_slave_system_control_driver = { diff --git a/drivers/spi/spi-slave-time.c b/drivers/spi/spi-slave-time.c index f2e07a392d68..f56c1afb8534 100644 --- a/drivers/spi/spi-slave-time.c +++ b/drivers/spi/spi-slave-time.c @@ -106,13 +106,12 @@ static int spi_slave_time_probe(struct spi_device *spi) return 0; } -static int spi_slave_time_remove(struct spi_device *spi) +static void spi_slave_time_remove(struct spi_device *spi) { struct spi_slave_time_priv *priv = spi_get_drvdata(spi); spi_slave_abort(spi); wait_for_completion(&priv->finished); - return 0; } static struct spi_driver spi_slave_time_driver = { diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index 6c44dda9ee8c..843be803696b 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -17,7 +17,6 @@ #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -171,11 +170,6 @@ static int spi_st_transfer_one(struct spi_master *master, return t->len; } -static void spi_st_cleanup(struct spi_device *spi) -{ - gpio_free(spi->cs_gpio); -} - /* the spi->mode bits understood by this driver: */ #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH) static int spi_st_setup(struct spi_device *spi) @@ -183,29 +177,17 @@ static int spi_st_setup(struct spi_device *spi) struct spi_st *spi_st = spi_master_get_devdata(spi->master); u32 spi_st_clk, sscbrg, var; u32 hz = spi->max_speed_hz; - int cs = spi->cs_gpio; - int ret; if (!hz) { dev_err(&spi->dev, "max_speed_hz unspecified\n"); return -EINVAL; } - if (!gpio_is_valid(cs)) { - dev_err(&spi->dev, "%d is not a valid gpio\n", cs); + if (!spi->cs_gpiod) { + dev_err(&spi->dev, "no valid gpio assigned\n"); return -EINVAL; } - ret = gpio_request(cs, dev_name(&spi->dev)); - if (ret) { - dev_err(&spi->dev, "could not request gpio:%d\n", cs); - return ret; - } - - ret = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); - if (ret) - goto out_free_gpio; - spi_st_clk = clk_get_rate(spi_st->clk); /* Set SSC_BRF */ @@ -213,8 +195,7 @@ static int spi_st_setup(struct spi_device *spi) if (sscbrg < 0x07 || sscbrg > BIT(16)) { dev_err(&spi->dev, "baudrate %d outside valid range %d\n", sscbrg, hz); - ret = -EINVAL; - goto out_free_gpio; + return -EINVAL; } spi_st->baud = spi_st_clk / (2 * sscbrg); @@ -263,10 +244,6 @@ static int spi_st_setup(struct spi_device *spi) readl_relaxed(spi_st->base + SSC_RBUF); return 0; - -out_free_gpio: - gpio_free(cs); - return ret; } /* Interrupt fired when TX shift register becomes empty */ @@ -309,11 +286,11 @@ static int spi_st_probe(struct platform_device *pdev) master->dev.of_node = np; master->mode_bits = MODEBITS; master->setup = spi_st_setup; - master->cleanup = spi_st_cleanup; master->transfer_one = spi_st_transfer_one; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->auto_runtime_pm = true; master->bus_num = pdev->id; + master->use_gpio_descriptors = true; spi_st = spi_master_get_devdata(master); spi_st->clk = devm_clk_get(&pdev->dev, "ssc"); diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 7fc24505a72c..a6adc20f6862 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -763,7 +763,7 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX)) { /* OVR flag shouldn't be handled for TX only mode */ - sr &= ~STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE; + sr &= ~(STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE); mask |= STM32F4_SPI_SR_TXE; } diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 1fdfc6e6691d..6000d0761206 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -280,7 +280,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master, * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) * Or we can use CDR2, which is calculated with the formula: * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) - * Wether we use the former or the latter is set through the + * Whether we use the former or the latter is set through the * DRS bit. * * First try CDR2, and if we can't reach the expected diff --git a/drivers/spi/spi-sunplus-sp7021.c b/drivers/spi/spi-sunplus-sp7021.c new file mode 100644 index 000000000000..f989f7b99296 --- /dev/null +++ b/drivers/spi/spi-sunplus-sp7021.c @@ -0,0 +1,584 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2021 Sunplus Inc. +// Author: Li-hao Kuo <lhjeff911@gmail.com> + +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <linux/spi/spi.h> + +#define SP7021_DATA_RDY_REG 0x0044 +#define SP7021_SLAVE_DMA_CTRL_REG 0x0048 +#define SP7021_SLAVE_DMA_LENGTH_REG 0x004c +#define SP7021_SLAVE_DMA_ADDR_REG 0x004c + +#define SP7021_SLAVE_DATA_RDY BIT(0) +#define SP7021_SLAVE_SW_RST BIT(1) +#define SP7021_SLA_DMA_W_INT BIT(8) +#define SP7021_SLAVE_CLR_INT BIT(8) +#define SP7021_SLAVE_DMA_EN BIT(0) +#define SP7021_SLAVE_DMA_RW BIT(6) +#define SP7021_SLAVE_DMA_CMD GENMASK(3, 2) + +#define SP7021_FIFO_REG 0x0034 +#define SP7021_SPI_STATUS_REG 0x0038 +#define SP7021_SPI_CONFIG_REG 0x003c +#define SP7021_INT_BUSY_REG 0x004c +#define SP7021_DMA_CTRL_REG 0x0050 + +#define SP7021_SPI_START_FD BIT(0) +#define SP7021_FD_SW_RST BIT(1) +#define SP7021_TX_EMP_FLAG BIT(2) +#define SP7021_RX_EMP_FLAG BIT(4) +#define SP7021_RX_FULL_FLAG BIT(5) +#define SP7021_FINISH_FLAG BIT(6) + +#define SP7021_TX_CNT_MASK GENMASK(11, 8) +#define SP7021_RX_CNT_MASK GENMASK(15, 12) +#define SP7021_TX_LEN_MASK GENMASK(23, 16) +#define SP7021_GET_LEN_MASK GENMASK(31, 24) +#define SP7021_SET_TX_LEN GENMASK(23, 16) +#define SP7021_SET_XFER_LEN GENMASK(31, 24) + +#define SP7021_CPOL_FD BIT(0) +#define SP7021_CPHA_R BIT(1) +#define SP7021_CPHA_W BIT(2) +#define SP7021_LSB_SEL BIT(4) +#define SP7021_CS_POR BIT(5) +#define SP7021_FD_SEL BIT(6) + +#define SP7021_RX_UNIT GENMASK(8, 7) +#define SP7021_TX_UNIT GENMASK(10, 9) +#define SP7021_TX_EMP_FLAG_MASK BIT(11) +#define SP7021_RX_FULL_FLAG_MASK BIT(14) +#define SP7021_FINISH_FLAG_MASK BIT(15) +#define SP7021_CLEAN_RW_BYTE GENMASK(10, 7) +#define SP7021_CLEAN_FLUG_MASK GENMASK(15, 11) +#define SP7021_CLK_MASK GENMASK(31, 16) + +#define SP7021_INT_BYPASS BIT(3) +#define SP7021_CLR_MASTER_INT BIT(6) + +#define SP7021_SPI_DATA_SIZE (255) +#define SP7021_FIFO_DATA_LEN (16) + +enum { + SP7021_MASTER_MODE = 0, + SP7021_SLAVE_MODE = 1, +}; + +struct sp7021_spi_ctlr { + struct device *dev; + struct spi_controller *ctlr; + void __iomem *m_base; + void __iomem *s_base; + u32 xfer_conf; + int mode; + int m_irq; + int s_irq; + struct clk *spi_clk; + struct reset_control *rstc; + // irq spin lock + spinlock_t lock; + // data xfer lock + struct mutex buf_lock; + struct completion isr_done; + struct completion slave_isr; + unsigned int rx_cur_len; + unsigned int tx_cur_len; + unsigned int data_unit; + const u8 *tx_buf; + u8 *rx_buf; +}; + +static irqreturn_t sp7021_spi_slave_irq(int irq, void *dev) +{ + struct sp7021_spi_ctlr *pspim = dev; + unsigned int data_status; + + data_status = readl(pspim->s_base + SP7021_DATA_RDY_REG); + data_status |= SP7021_SLAVE_CLR_INT; + writel(data_status , pspim->s_base + SP7021_DATA_RDY_REG); + complete(&pspim->slave_isr); + return IRQ_HANDLED; +} + +static int sp7021_spi_slave_abort(struct spi_controller *ctlr) +{ + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + + complete(&pspim->slave_isr); + complete(&pspim->isr_done); + return 0; +} + +static int sp7021_spi_slave_tx(struct spi_device *spi, struct spi_transfer *xfer) +{ + struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller); + u32 value; + + reinit_completion(&pspim->slave_isr); + value = SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3); + writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); + writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG); + writel(xfer->tx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG); + value = readl(pspim->s_base + SP7021_DATA_RDY_REG); + value |= SP7021_SLAVE_DATA_RDY; + writel(value, pspim->s_base + SP7021_DATA_RDY_REG); + if (wait_for_completion_interruptible(&pspim->isr_done)) { + dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__); + return -EINTR; + } + return 0; +} + +static int sp7021_spi_slave_rx(struct spi_device *spi, struct spi_transfer *xfer) +{ + struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller); + u32 value; + + reinit_completion(&pspim->isr_done); + value = SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3); + writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); + writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG); + writel(xfer->rx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG); + if (wait_for_completion_interruptible(&pspim->isr_done)) { + dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__); + return -EINTR; + } + writel(SP7021_SLAVE_SW_RST, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); + return 0; +} + +static void sp7021_spi_master_rb(struct sp7021_spi_ctlr *pspim, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++) { + pspim->rx_buf[pspim->rx_cur_len] = + readl(pspim->m_base + SP7021_FIFO_REG); + pspim->rx_cur_len++; + } +} + +static void sp7021_spi_master_wb(struct sp7021_spi_ctlr *pspim, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++) { + writel(pspim->tx_buf[pspim->tx_cur_len], + pspim->m_base + SP7021_FIFO_REG); + pspim->tx_cur_len++; + } +} + +static irqreturn_t sp7021_spi_master_irq(int irq, void *dev) +{ + struct sp7021_spi_ctlr *pspim = dev; + unsigned int tx_cnt, total_len; + unsigned int tx_len, rx_cnt; + unsigned int fd_status; + bool isrdone = false; + u32 value; + + fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); + tx_cnt = FIELD_GET(SP7021_TX_CNT_MASK, fd_status); + tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status); + total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); + + if ((fd_status & SP7021_TX_EMP_FLAG) && (fd_status & SP7021_RX_EMP_FLAG) && total_len == 0) + return IRQ_NONE; + + if (tx_len == 0 && total_len == 0) + return IRQ_NONE; + + spin_lock_irq(&pspim->lock); + + rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status); + if (fd_status & SP7021_RX_FULL_FLAG) + rx_cnt = pspim->data_unit; + + tx_cnt = min(tx_len - pspim->tx_cur_len, pspim->data_unit - tx_cnt); + dev_dbg(pspim->dev, "fd_st=0x%x rx_c:%d tx_c:%d tx_l:%d", + fd_status, rx_cnt, tx_cnt, tx_len); + + if (rx_cnt > 0) + sp7021_spi_master_rb(pspim, rx_cnt); + if (tx_cnt > 0) + sp7021_spi_master_wb(pspim, tx_cnt); + + fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); + tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status); + total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); + + if (fd_status & SP7021_FINISH_FLAG || tx_len == pspim->tx_cur_len) { + while (total_len != pspim->rx_cur_len) { + fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); + total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); + if (fd_status & SP7021_RX_FULL_FLAG) + rx_cnt = pspim->data_unit; + else + rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status); + + if (rx_cnt > 0) + sp7021_spi_master_rb(pspim, rx_cnt); + } + value = readl(pspim->m_base + SP7021_INT_BUSY_REG); + value |= SP7021_CLR_MASTER_INT; + writel(value, pspim->m_base + SP7021_INT_BUSY_REG); + writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG); + isrdone = true; + } + + if (isrdone) + complete(&pspim->isr_done); + spin_unlock_irq(&pspim->lock); + return IRQ_HANDLED; +} + +static void sp7021_prep_transfer(struct spi_controller *ctlr, struct spi_device *spi) +{ + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + + pspim->tx_cur_len = 0; + pspim->rx_cur_len = 0; + pspim->data_unit = SP7021_FIFO_DATA_LEN; +} + +// preliminary set CS, CPOL, CPHA and LSB +static int sp7021_spi_controller_prepare_message(struct spi_controller *ctlr, + struct spi_message *msg) +{ + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + struct spi_device *s = msg->spi; + u32 valus, rs = 0; + + valus = readl(pspim->m_base + SP7021_SPI_STATUS_REG); + valus |= SP7021_FD_SW_RST; + writel(valus, pspim->m_base + SP7021_SPI_STATUS_REG); + rs |= SP7021_FD_SEL; + if (s->mode & SPI_CPOL) + rs |= SP7021_CPOL_FD; + + if (s->mode & SPI_LSB_FIRST) + rs |= SP7021_LSB_SEL; + + if (s->mode & SPI_CS_HIGH) + rs |= SP7021_CS_POR; + + if (s->mode & SPI_CPHA) + rs |= SP7021_CPHA_R; + else + rs |= SP7021_CPHA_W; + + rs |= FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0); + pspim->xfer_conf = rs; + if (pspim->xfer_conf & SP7021_CPOL_FD) + writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); + + return 0; +} + +static void sp7021_spi_setup_clk(struct spi_controller *ctlr, struct spi_transfer *xfer) +{ + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + u32 clk_rate, clk_sel, div; + + clk_rate = clk_get_rate(pspim->spi_clk); + div = max(2U, clk_rate / xfer->speed_hz); + + clk_sel = (div / 2) - 1; + pspim->xfer_conf &= ~SP7021_CLK_MASK; + pspim->xfer_conf |= FIELD_PREP(SP7021_CLK_MASK, clk_sel); + writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); +} + +static int sp7021_spi_master_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + unsigned long timeout = msecs_to_jiffies(1000); + unsigned int xfer_cnt, xfer_len, last_len; + unsigned int i, len_temp; + u32 reg_temp; + + xfer_cnt = xfer->len / SP7021_SPI_DATA_SIZE; + last_len = xfer->len % SP7021_SPI_DATA_SIZE; + + for (i = 0; i <= xfer_cnt; i++) { + mutex_lock(&pspim->buf_lock); + sp7021_prep_transfer(ctlr, spi); + sp7021_spi_setup_clk(ctlr, xfer); + reinit_completion(&pspim->isr_done); + + if (i == xfer_cnt) + xfer_len = last_len; + else + xfer_len = SP7021_SPI_DATA_SIZE; + + pspim->tx_buf = xfer->tx_buf + i * SP7021_SPI_DATA_SIZE; + pspim->rx_buf = xfer->rx_buf + i * SP7021_SPI_DATA_SIZE; + + if (pspim->tx_cur_len < xfer_len) { + len_temp = min(pspim->data_unit, xfer_len); + sp7021_spi_master_wb(pspim, len_temp); + } + reg_temp = readl(pspim->m_base + SP7021_SPI_CONFIG_REG); + reg_temp &= ~SP7021_CLEAN_RW_BYTE; + reg_temp &= ~SP7021_CLEAN_FLUG_MASK; + reg_temp |= SP7021_FD_SEL | SP7021_FINISH_FLAG_MASK | + SP7021_TX_EMP_FLAG_MASK | SP7021_RX_FULL_FLAG_MASK | + FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0); + writel(reg_temp, pspim->m_base + SP7021_SPI_CONFIG_REG); + + reg_temp = FIELD_PREP(SP7021_SET_TX_LEN, xfer_len) | + FIELD_PREP(SP7021_SET_XFER_LEN, xfer_len) | + SP7021_SPI_START_FD; + writel(reg_temp, pspim->m_base + SP7021_SPI_STATUS_REG); + + if (!wait_for_completion_interruptible_timeout(&pspim->isr_done, timeout)) { + dev_err(&spi->dev, "wait_for_completion err\n"); + mutex_unlock(&pspim->buf_lock); + return -ETIMEDOUT; + } + + reg_temp = readl(pspim->m_base + SP7021_SPI_STATUS_REG); + if (reg_temp & SP7021_FINISH_FLAG) { + writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG); + writel(readl(pspim->m_base + SP7021_SPI_CONFIG_REG) & + SP7021_CLEAN_FLUG_MASK, pspim->m_base + SP7021_SPI_CONFIG_REG); + } + + if (pspim->xfer_conf & SP7021_CPOL_FD) + writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); + + mutex_unlock(&pspim->buf_lock); + } + return 0; +} + +static int sp7021_spi_slave_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + struct device *dev = pspim->dev; + int ret; + + if (xfer->tx_buf && !xfer->rx_buf) { + xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf, + xfer->len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, xfer->tx_dma)) + return -ENOMEM; + ret = sp7021_spi_slave_tx(spi, xfer); + dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); + } else if (xfer->rx_buf && !xfer->tx_buf) { + xfer->rx_dma = dma_map_single(dev, xfer->rx_buf, xfer->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, xfer->rx_dma)) + return -ENOMEM; + ret = sp7021_spi_slave_rx(spi, xfer); + dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); + } else { + dev_dbg(&ctlr->dev, "%s() wrong command\n", __func__); + return -EINVAL; + } + + spi_finalize_current_transfer(ctlr); + return ret; +} + +static void sp7021_spi_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + +static void sp7021_spi_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + +static int sp7021_spi_controller_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sp7021_spi_ctlr *pspim; + struct spi_controller *ctlr; + int mode, ret; + + pdev->id = of_alias_get_id(pdev->dev.of_node, "sp_spi"); + + if (device_property_read_bool(dev, "spi-slave")) + mode = SP7021_SLAVE_MODE; + else + mode = SP7021_MASTER_MODE; + + if (mode == SP7021_SLAVE_MODE) + ctlr = devm_spi_alloc_slave(dev, sizeof(*pspim)); + else + ctlr = devm_spi_alloc_master(dev, sizeof(*pspim)); + if (!ctlr) + return -ENOMEM; + device_set_node(&ctlr->dev, dev_fwnode(dev)); + ctlr->bus_num = pdev->id; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + ctlr->auto_runtime_pm = true; + ctlr->prepare_message = sp7021_spi_controller_prepare_message; + if (mode == SP7021_SLAVE_MODE) { + ctlr->transfer_one = sp7021_spi_slave_transfer_one; + ctlr->slave_abort = sp7021_spi_slave_abort; + ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; + } else { + ctlr->bits_per_word_mask = SPI_BPW_MASK(8); + ctlr->min_speed_hz = 40000; + ctlr->max_speed_hz = 25000000; + ctlr->use_gpio_descriptors = true; + ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; + ctlr->transfer_one = sp7021_spi_master_transfer_one; + } + platform_set_drvdata(pdev, ctlr); + pspim = spi_controller_get_devdata(ctlr); + pspim->mode = mode; + pspim->ctlr = ctlr; + pspim->dev = dev; + spin_lock_init(&pspim->lock); + mutex_init(&pspim->buf_lock); + init_completion(&pspim->isr_done); + init_completion(&pspim->slave_isr); + + pspim->m_base = devm_platform_ioremap_resource_byname(pdev, "master"); + if (IS_ERR(pspim->m_base)) + return dev_err_probe(dev, PTR_ERR(pspim->m_base), "m_base get fail\n"); + + pspim->s_base = devm_platform_ioremap_resource_byname(pdev, "slave"); + if (IS_ERR(pspim->s_base)) + return dev_err_probe(dev, PTR_ERR(pspim->s_base), "s_base get fail\n"); + + pspim->m_irq = platform_get_irq_byname(pdev, "master_risc"); + if (pspim->m_irq < 0) + return pspim->m_irq; + + pspim->s_irq = platform_get_irq_byname(pdev, "slave_risc"); + if (pspim->s_irq < 0) + return pspim->s_irq; + + pspim->spi_clk = devm_clk_get(dev, NULL); + if (IS_ERR(pspim->spi_clk)) + return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n"); + + pspim->rstc = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(pspim->rstc)) + return dev_err_probe(dev, PTR_ERR(pspim->rstc), "rst get fail\n"); + + ret = clk_prepare_enable(pspim->spi_clk); + if (ret) + return dev_err_probe(dev, ret, "failed to enable clk\n"); + + ret = devm_add_action_or_reset(dev, sp7021_spi_disable_unprepare, pspim->spi_clk); + if (ret) + return ret; + + ret = reset_control_deassert(pspim->rstc); + if (ret) + return dev_err_probe(dev, ret, "failed to deassert reset\n"); + + ret = devm_add_action_or_reset(dev, sp7021_spi_reset_control_assert, pspim->rstc); + if (ret) + return ret; + + ret = devm_request_irq(dev, pspim->m_irq, sp7021_spi_master_irq, + IRQF_TRIGGER_RISING, pdev->name, pspim); + if (ret) + return ret; + + ret = devm_request_irq(dev, pspim->s_irq, sp7021_spi_slave_irq, + IRQF_TRIGGER_RISING, pdev->name, pspim); + if (ret) + return ret; + + pm_runtime_enable(dev); + ret = spi_register_controller(ctlr); + if (ret) { + pm_runtime_disable(dev); + return dev_err_probe(dev, ret, "spi_register_master fail\n"); + } + return 0; +} + +static int sp7021_spi_controller_remove(struct platform_device *pdev) +{ + struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); + + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + return 0; +} + +static int __maybe_unused sp7021_spi_controller_suspend(struct device *dev) +{ + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + + return reset_control_assert(pspim->rstc); +} + +static int __maybe_unused sp7021_spi_controller_resume(struct device *dev) +{ + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + + reset_control_deassert(pspim->rstc); + return clk_prepare_enable(pspim->spi_clk); +} + +#ifdef CONFIG_PM +static int sp7021_spi_runtime_suspend(struct device *dev) +{ + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + + return reset_control_assert(pspim->rstc); +} + +static int sp7021_spi_runtime_resume(struct device *dev) +{ + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + + return reset_control_deassert(pspim->rstc); +} +#endif + +static const struct dev_pm_ops sp7021_spi_pm_ops = { + SET_RUNTIME_PM_OPS(sp7021_spi_runtime_suspend, + sp7021_spi_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(sp7021_spi_controller_suspend, + sp7021_spi_controller_resume) +}; + +static const struct of_device_id sp7021_spi_controller_ids[] = { + { .compatible = "sunplus,sp7021-spi" }, + {} +}; +MODULE_DEVICE_TABLE(of, sp7021_spi_controller_ids); + +static struct platform_driver sp7021_spi_controller_driver = { + .probe = sp7021_spi_controller_probe, + .remove = sp7021_spi_controller_remove, + .driver = { + .name = "sunplus,sp7021-spi-controller", + .of_match_table = sp7021_spi_controller_ids, + .pm = &sp7021_spi_pm_ops, + }, +}; +module_platform_driver(sp7021_spi_controller_driver); + +MODULE_AUTHOR("Li-hao Kuo <lhjeff911@gmail.com>"); +MODULE_DESCRIPTION("Sunplus SPI controller driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index e9de1d958bbd..8f345247a8c3 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1352,6 +1352,10 @@ static int tegra_spi_probe(struct platform_device *pdev) tspi->phys = r->start; spi_irq = platform_get_irq(pdev, 0); + if (spi_irq < 0) { + ret = spi_irq; + goto exit_free_master; + } tspi->irq = spi_irq; tspi->clk = devm_clk_get(&pdev->dev, "spi"); diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 2a03739a0c60..80c3787deea9 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1006,14 +1006,8 @@ static int tegra_slink_probe(struct platform_device *pdev) struct resource *r; int ret, spi_irq; const struct tegra_slink_chip_data *cdata = NULL; - const struct of_device_id *match; - match = of_match_device(tegra_slink_of_match, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "Error: No device match found\n"); - return -ENODEV; - } - cdata = match->data; + cdata = of_device_get_match_data(&pdev->dev); master = spi_alloc_master(&pdev->dev, sizeof(*tspi)); if (!master) { diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index ce1bdb4767ea..66f647f32876 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -21,6 +21,8 @@ #include <linux/of_device.h> #include <linux/reset.h> #include <linux/spi/spi.h> +#include <linux/acpi.h> +#include <linux/property.h> #define QSPI_COMMAND1 0x000 #define QSPI_BIT_LENGTH(x) (((x) & 0x1f) << 0) @@ -119,11 +121,40 @@ #define QSPI_NUM_DUMMY_CYCLE(x) (((x) & 0xff) << 0) #define QSPI_DUMMY_CYCLES_MAX 0xff +#define QSPI_CMB_SEQ_CMD 0x19c +#define QSPI_COMMAND_VALUE_SET(X) (((x) & 0xFF) << 0) + +#define QSPI_CMB_SEQ_CMD_CFG 0x1a0 +#define QSPI_COMMAND_X1_X2_X4(x) (((x) & 0x3) << 13) +#define QSPI_COMMAND_X1_X2_X4_MASK (0x03 << 13) +#define QSPI_COMMAND_SDR_DDR BIT(12) +#define QSPI_COMMAND_SIZE_SET(x) (((x) & 0xFF) << 0) + +#define QSPI_GLOBAL_CONFIG 0X1a4 +#define QSPI_CMB_SEQ_EN BIT(0) + +#define QSPI_CMB_SEQ_ADDR 0x1a8 +#define QSPI_ADDRESS_VALUE_SET(X) (((x) & 0xFFFF) << 0) + +#define QSPI_CMB_SEQ_ADDR_CFG 0x1ac +#define QSPI_ADDRESS_X1_X2_X4(x) (((x) & 0x3) << 13) +#define QSPI_ADDRESS_X1_X2_X4_MASK (0x03 << 13) +#define QSPI_ADDRESS_SDR_DDR BIT(12) +#define QSPI_ADDRESS_SIZE_SET(x) (((x) & 0xFF) << 0) + #define DATA_DIR_TX BIT(0) #define DATA_DIR_RX BIT(1) #define QSPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) #define DEFAULT_QSPI_DMA_BUF_LEN (64 * 1024) +#define CMD_TRANSFER 0 +#define ADDR_TRANSFER 1 +#define DATA_TRANSFER 2 + +struct tegra_qspi_soc_data { + bool has_dma; + bool cmb_xfer_capable; +}; struct tegra_qspi_client_data { int tx_clk_tap_delay; @@ -137,7 +168,6 @@ struct tegra_qspi { spinlock_t lock; struct clk *clk; - struct reset_control *rst; void __iomem *base; phys_addr_t phys; unsigned int irq; @@ -185,6 +215,7 @@ struct tegra_qspi { u32 *tx_dma_buf; dma_addr_t tx_dma_phys; struct dma_async_tx_descriptor *tx_dma_desc; + const struct tegra_qspi_soc_data *soc_data; }; static inline u32 tegra_qspi_readl(struct tegra_qspi *tqspi, unsigned long offset) @@ -767,7 +798,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran u32 tx_tap = 0, rx_tap = 0; int req_mode; - if (speed != tqspi->cur_speed) { + if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) { clk_set_rate(tqspi->clk, speed); tqspi->cur_speed = speed; } @@ -875,16 +906,16 @@ static int tegra_qspi_start_transfer_one(struct spi_device *spi, static struct tegra_qspi_client_data *tegra_qspi_parse_cdata_dt(struct spi_device *spi) { struct tegra_qspi_client_data *cdata; - struct device_node *slave_np = spi->dev.of_node; cdata = devm_kzalloc(&spi->dev, sizeof(*cdata), GFP_KERNEL); if (!cdata) return NULL; - of_property_read_u32(slave_np, "nvidia,tx-clk-tap-delay", - &cdata->tx_clk_tap_delay); - of_property_read_u32(slave_np, "nvidia,rx-clk-tap-delay", - &cdata->rx_clk_tap_delay); + device_property_read_u32(&spi->dev, "nvidia,tx-clk-tap-delay", + &cdata->tx_clk_tap_delay); + device_property_read_u32(&spi->dev, "nvidia,rx-clk-tap-delay", + &cdata->rx_clk_tap_delay); + return cdata; } @@ -906,7 +937,6 @@ static int tegra_qspi_setup(struct spi_device *spi) cdata = tegra_qspi_parse_cdata_dt(spi); spi->controller_data = cdata; } - spin_lock_irqsave(&tqspi->lock, flags); /* keep default cs state to inactive */ @@ -948,9 +978,8 @@ static void tegra_qspi_handle_error(struct tegra_qspi *tqspi) dev_err(tqspi->dev, "error in transfer, fifo status 0x%08x\n", tqspi->status_reg); tegra_qspi_dump_regs(tqspi); tegra_qspi_flush_fifos(tqspi, true); - reset_control_assert(tqspi->rst); - udelay(2); - reset_control_deassert(tqspi->rst); + if (device_reset(tqspi->dev) < 0) + dev_warn_once(tqspi->dev, "device reset failed\n"); } static void tegra_qspi_transfer_end(struct spi_device *spi) @@ -966,19 +995,179 @@ static void tegra_qspi_transfer_end(struct spi_device *spi) tegra_qspi_writel(tqspi, tqspi->def_command1_reg, QSPI_COMMAND1); } -static int tegra_qspi_transfer_one_message(struct spi_master *master, struct spi_message *msg) +static u32 tegra_qspi_cmd_config(bool is_ddr, u8 bus_width, u8 len) +{ + u32 cmd_config = 0; + + /* Extract Command configuration and value */ + if (is_ddr) + cmd_config |= QSPI_COMMAND_SDR_DDR; + else + cmd_config &= ~QSPI_COMMAND_SDR_DDR; + + cmd_config |= QSPI_COMMAND_X1_X2_X4(bus_width); + cmd_config |= QSPI_COMMAND_SIZE_SET((len * 8) - 1); + + return cmd_config; +} + +static u32 tegra_qspi_addr_config(bool is_ddr, u8 bus_width, u8 len) +{ + u32 addr_config = 0; + + /* Extract Address configuration and value */ + is_ddr = 0; //Only SDR mode supported + bus_width = 0; //X1 mode + + if (is_ddr) + addr_config |= QSPI_ADDRESS_SDR_DDR; + else + addr_config &= ~QSPI_ADDRESS_SDR_DDR; + + addr_config |= QSPI_ADDRESS_X1_X2_X4(bus_width); + addr_config |= QSPI_ADDRESS_SIZE_SET((len * 8) - 1); + + return addr_config; +} + +static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_message *msg) +{ + bool is_first_msg = true; + struct spi_transfer *xfer; + struct spi_device *spi = msg->spi; + u8 transfer_phase = 0; + u32 cmd1 = 0, dma_ctl = 0; + int ret = 0; + u32 address_value = 0; + u32 cmd_config = 0, addr_config = 0; + u8 cmd_value = 0, val = 0; + + /* Enable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); + val |= QSPI_CMB_SEQ_EN; + tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG); + /* Process individual transfer list */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + switch (transfer_phase) { + case CMD_TRANSFER: + /* X1 SDR mode */ + cmd_config = tegra_qspi_cmd_config(false, 0, + xfer->len); + cmd_value = *((const u8 *)(xfer->tx_buf)); + break; + case ADDR_TRANSFER: + /* X1 SDR mode */ + addr_config = tegra_qspi_addr_config(false, 0, + xfer->len); + address_value = *((const u32 *)(xfer->tx_buf)); + break; + case DATA_TRANSFER: + /* Program Command, Address value in register */ + tegra_qspi_writel(tqspi, cmd_value, QSPI_CMB_SEQ_CMD); + tegra_qspi_writel(tqspi, address_value, + QSPI_CMB_SEQ_ADDR); + /* Program Command and Address config in register */ + tegra_qspi_writel(tqspi, cmd_config, + QSPI_CMB_SEQ_CMD_CFG); + tegra_qspi_writel(tqspi, addr_config, + QSPI_CMB_SEQ_ADDR_CFG); + + reinit_completion(&tqspi->xfer_completion); + cmd1 = tegra_qspi_setup_transfer_one(spi, xfer, + is_first_msg); + ret = tegra_qspi_start_transfer_one(spi, xfer, + cmd1); + + if (ret < 0) { + dev_err(tqspi->dev, "Failed to start transfer-one: %d\n", + ret); + return ret; + } + + is_first_msg = false; + ret = wait_for_completion_timeout + (&tqspi->xfer_completion, + QSPI_DMA_TIMEOUT); + + if (WARN_ON(ret == 0)) { + dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n", + ret); + if (tqspi->is_curr_dma_xfer && + (tqspi->cur_direction & DATA_DIR_TX)) + dmaengine_terminate_all + (tqspi->tx_dma_chan); + + if (tqspi->is_curr_dma_xfer && + (tqspi->cur_direction & DATA_DIR_RX)) + dmaengine_terminate_all + (tqspi->rx_dma_chan); + + /* Abort transfer by resetting pio/dma bit */ + if (!tqspi->is_curr_dma_xfer) { + cmd1 = tegra_qspi_readl + (tqspi, + QSPI_COMMAND1); + cmd1 &= ~QSPI_PIO; + tegra_qspi_writel + (tqspi, cmd1, + QSPI_COMMAND1); + } else { + dma_ctl = tegra_qspi_readl + (tqspi, + QSPI_DMA_CTL); + dma_ctl &= ~QSPI_DMA_EN; + tegra_qspi_writel(tqspi, dma_ctl, + QSPI_DMA_CTL); + } + + /* Reset controller if timeout happens */ + if (device_reset(tqspi->dev) < 0) + dev_warn_once(tqspi->dev, + "device reset failed\n"); + ret = -EIO; + goto exit; + } + + if (tqspi->tx_status || tqspi->rx_status) { + dev_err(tqspi->dev, "QSPI Transfer failed\n"); + tqspi->tx_status = 0; + tqspi->rx_status = 0; + ret = -EIO; + goto exit; + } + break; + default: + ret = -EINVAL; + goto exit; + } + msg->actual_length += xfer->len; + transfer_phase++; + } + +exit: + msg->status = ret; + + return ret; +} + +static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, + struct spi_message *msg) { - struct tegra_qspi *tqspi = spi_master_get_devdata(master); struct spi_device *spi = msg->spi; struct spi_transfer *transfer; bool is_first_msg = true; - int ret; + int ret = 0, val = 0; msg->status = 0; msg->actual_length = 0; tqspi->tx_status = 0; tqspi->rx_status = 0; + /* Disable Combined sequence mode */ + val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); + val &= ~QSPI_CMB_SEQ_EN; + tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG); list_for_each_entry(transfer, &msg->transfers, transfer_list) { struct spi_transfer *xfer = transfer; u8 dummy_bytes = 0; @@ -1016,7 +1205,6 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, struct spi goto complete_xfer; } - is_first_msg = false; ret = wait_for_completion_timeout(&tqspi->xfer_completion, QSPI_DMA_TIMEOUT); if (WARN_ON(ret == 0)) { @@ -1061,7 +1249,48 @@ complete_xfer: ret = 0; exit: msg->status = ret; + + return ret; +} + +static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi, + struct spi_message *msg) +{ + int transfer_count = 0; + struct spi_transfer *xfer; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + transfer_count++; + } + if (!tqspi->soc_data->cmb_xfer_capable || transfer_count != 3) + return false; + xfer = list_first_entry(&msg->transfers, typeof(*xfer), + transfer_list); + if (xfer->len > 2) + return false; + xfer = list_next_entry(xfer, transfer_list); + if (xfer->len > 4 || xfer->len < 3) + return false; + xfer = list_next_entry(xfer, transfer_list); + if (!tqspi->soc_data->has_dma || xfer->len > (QSPI_FIFO_DEPTH << 2)) + return false; + + return true; +} + +static int tegra_qspi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct tegra_qspi *tqspi = spi_master_get_devdata(master); + int ret; + + if (tegra_qspi_validate_cmb_seq(tqspi, msg)) + ret = tegra_qspi_combined_seq_xfer(tqspi, msg); + else + ret = tegra_qspi_non_combined_seq_xfer(tqspi, msg); + spi_finalize_current_message(master); + return ret; } @@ -1193,15 +1422,58 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) return handle_dma_based_xfer(tqspi); } +static struct tegra_qspi_soc_data tegra210_qspi_soc_data = { + .has_dma = true, + .cmb_xfer_capable = false, +}; + +static struct tegra_qspi_soc_data tegra186_qspi_soc_data = { + .has_dma = true, + .cmb_xfer_capable = true, +}; + +static struct tegra_qspi_soc_data tegra234_qspi_soc_data = { + .has_dma = false, + .cmb_xfer_capable = true, +}; + static const struct of_device_id tegra_qspi_of_match[] = { - { .compatible = "nvidia,tegra210-qspi", }, - { .compatible = "nvidia,tegra186-qspi", }, - { .compatible = "nvidia,tegra194-qspi", }, + { + .compatible = "nvidia,tegra210-qspi", + .data = &tegra210_qspi_soc_data, + }, { + .compatible = "nvidia,tegra186-qspi", + .data = &tegra186_qspi_soc_data, + }, { + .compatible = "nvidia,tegra194-qspi", + .data = &tegra186_qspi_soc_data, + }, { + .compatible = "nvidia,tegra234-qspi", + .data = &tegra234_qspi_soc_data, + }, {} }; MODULE_DEVICE_TABLE(of, tegra_qspi_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id tegra_qspi_acpi_match[] = { + { + .id = "NVDA1213", + .driver_data = (kernel_ulong_t)&tegra210_qspi_soc_data, + }, { + .id = "NVDA1313", + .driver_data = (kernel_ulong_t)&tegra186_qspi_soc_data, + }, { + .id = "NVDA1413", + .driver_data = (kernel_ulong_t)&tegra234_qspi_soc_data, + }, + {} +}; + +MODULE_DEVICE_TABLE(acpi, tegra_qspi_acpi_match); +#endif + static int tegra_qspi_probe(struct platform_device *pdev) { struct spi_master *master; @@ -1233,6 +1505,7 @@ static int tegra_qspi_probe(struct platform_device *pdev) tqspi->dev = &pdev->dev; spin_lock_init(&tqspi->lock); + tqspi->soc_data = device_get_match_data(&pdev->dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); tqspi->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(tqspi->base)) @@ -1240,20 +1513,18 @@ static int tegra_qspi_probe(struct platform_device *pdev) tqspi->phys = r->start; qspi_irq = platform_get_irq(pdev, 0); + if (qspi_irq < 0) + return qspi_irq; tqspi->irq = qspi_irq; - tqspi->clk = devm_clk_get(&pdev->dev, "qspi"); - if (IS_ERR(tqspi->clk)) { - ret = PTR_ERR(tqspi->clk); - dev_err(&pdev->dev, "failed to get clock: %d\n", ret); - return ret; - } + if (!has_acpi_companion(tqspi->dev)) { + tqspi->clk = devm_clk_get(&pdev->dev, "qspi"); + if (IS_ERR(tqspi->clk)) { + ret = PTR_ERR(tqspi->clk); + dev_err(&pdev->dev, "failed to get clock: %d\n", ret); + return ret; + } - tqspi->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(tqspi->rst)) { - ret = PTR_ERR(tqspi->rst); - dev_err(&pdev->dev, "failed to get reset control: %d\n", ret); - return ret; } tqspi->max_buf_size = QSPI_FIFO_DEPTH << 2; @@ -1277,9 +1548,8 @@ static int tegra_qspi_probe(struct platform_device *pdev) goto exit_pm_disable; } - reset_control_assert(tqspi->rst); - udelay(2); - reset_control_deassert(tqspi->rst); + if (device_reset(tqspi->dev) < 0) + dev_warn_once(tqspi->dev, "device reset failed\n"); tqspi->def_command1_reg = QSPI_M_S | QSPI_CS_SW_HW | QSPI_CS_SW_VAL; tegra_qspi_writel(tqspi, tqspi->def_command1_reg, QSPI_COMMAND1); @@ -1358,6 +1628,9 @@ static int __maybe_unused tegra_qspi_runtime_suspend(struct device *dev) struct spi_master *master = dev_get_drvdata(dev); struct tegra_qspi *tqspi = spi_master_get_devdata(master); + /* Runtime pm disabled with ACPI */ + if (has_acpi_companion(tqspi->dev)) + return 0; /* flush all write which are in PPSB queue by reading back */ tegra_qspi_readl(tqspi, QSPI_COMMAND1); @@ -1372,6 +1645,9 @@ static int __maybe_unused tegra_qspi_runtime_resume(struct device *dev) struct tegra_qspi *tqspi = spi_master_get_devdata(master); int ret; + /* Runtime pm disabled with ACPI */ + if (has_acpi_companion(tqspi->dev)) + return 0; ret = clk_prepare_enable(tqspi->clk); if (ret < 0) dev_err(tqspi->dev, "failed to enable clock: %d\n", ret); @@ -1389,6 +1665,7 @@ static struct platform_driver tegra_qspi_driver = { .name = "tegra-qspi", .pm = &tegra_qspi_pm_ops, .of_match_table = tegra_qspi_of_match, + .acpi_match_table = ACPI_PTR(tegra_qspi_acpi_match), }, .probe = tegra_qspi_probe, .remove = tegra_qspi_remove, diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c index f8ad0709d015..a565352f6381 100644 --- a/drivers/spi/spi-tle62x0.c +++ b/drivers/spi/spi-tle62x0.c @@ -288,7 +288,7 @@ static int tle62x0_probe(struct spi_device *spi) return ret; } -static int tle62x0_remove(struct spi_device *spi) +static void tle62x0_remove(struct spi_device *spi) { struct tle62x0_state *st = spi_get_drvdata(spi); int ptr; @@ -298,7 +298,6 @@ static int tle62x0_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_status_show); kfree(st); - return 0; } static struct spi_driver tle62x0_driver = { diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 8c4615b76339..dfaa1d79a78b 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -103,6 +103,7 @@ static int use_dma = 1; struct pch_spi_dma_ctrl { + struct pci_dev *dma_dev; struct dma_async_tx_descriptor *desc_tx; struct dma_async_tx_descriptor *desc_rx; struct pch_dma_slave param_tx; @@ -876,8 +877,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) if (!chan) { dev_err(&data->master->dev, "ERROR: dma_request_channel FAILS(Tx)\n"); - data->use_dma = 0; - return; + goto out; } dma->chan_tx = chan; @@ -893,10 +893,15 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) "ERROR: dma_request_channel FAILS(Rx)\n"); dma_release_channel(dma->chan_tx); dma->chan_tx = NULL; - data->use_dma = 0; - return; + goto out; } dma->chan_rx = chan; + + dma->dma_dev = dma_dev; + return; +out: + pci_dev_put(dma_dev); + data->use_dma = 0; } static void pch_spi_release_dma(struct pch_spi_data *data) @@ -912,6 +917,8 @@ static void pch_spi_release_dma(struct pch_spi_data *data) dma_release_channel(dma->chan_rx); dma->chan_rx = NULL; } + + pci_dev_put(dma->dma_dev); } static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 328b6559bb19..2b5afae8ff7f 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1172,7 +1172,10 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto clk_dis_all; } - dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); + if (ret) + goto clk_dis_all; + ctlr->bits_per_word_mask = SPI_BPW_MASK(8); ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS; ctlr->mem_ops = &zynqmp_qspi_mem_ops; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d96082dc3340..c4dd1200fe99 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -18,7 +18,6 @@ #include <linux/mod_devicetable.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> -#include <linux/of_gpio.h> #include <linux/gpio/consumer.h> #include <linux/pm_runtime.h> #include <linux/pm_domain.h> @@ -144,7 +143,7 @@ static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \ unsigned long flags; \ ssize_t len; \ spin_lock_irqsave(&stat->lock, flags); \ - len = sprintf(buf, format_string, stat->field); \ + len = sysfs_emit(buf, format_string "\n", stat->field); \ spin_unlock_irqrestore(&stat->lock, flags); \ return len; \ } \ @@ -404,15 +403,8 @@ static void spi_remove(struct device *dev) { const struct spi_driver *sdrv = to_spi_driver(dev->driver); - if (sdrv->remove) { - int ret; - - ret = sdrv->remove(to_spi_device(dev)); - if (ret) - dev_warn(dev, - "Failed to unbind driver (%pe), ignoring\n", - ERR_PTR(ret)); - } + if (sdrv->remove) + sdrv->remove(to_spi_device(dev)); dev_pm_domain_detach(dev, true); } @@ -532,7 +524,7 @@ static DEFINE_MUTEX(board_lock); * * Return: a pointer to the new device, or NULL. */ -static struct spi_device *spi_alloc_device(struct spi_controller *ctlr) +struct spi_device *spi_alloc_device(struct spi_controller *ctlr) { struct spi_device *spi; @@ -549,7 +541,6 @@ static struct spi_device *spi_alloc_device(struct spi_controller *ctlr) spi->dev.parent = &ctlr->dev; spi->dev.bus = &spi_bus_type; spi->dev.release = spidev_release; - spi->cs_gpio = -ENOENT; spi->mode = ctlr->buswidth_override_bits; spin_lock_init(&spi->statistics.lock); @@ -557,6 +548,7 @@ static struct spi_device *spi_alloc_device(struct spi_controller *ctlr) device_initialize(&spi->dev); return spi; } +EXPORT_SYMBOL_GPL(spi_alloc_device); static void spi_dev_set_name(struct spi_device *spi) { @@ -612,11 +604,8 @@ static int __spi_add_device(struct spi_device *spi) return -ENODEV; } - /* Descriptors take precedence */ if (ctlr->cs_gpiods) spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select]; - else if (ctlr->cs_gpios) - spi->cs_gpio = ctlr->cs_gpios[spi->chip_select]; /* * Drivers may modify this initial i/o setup, but will @@ -652,7 +641,7 @@ static int __spi_add_device(struct spi_device *spi) * * Return: 0 on success; negative errno on failure */ -static int spi_add_device(struct spi_device *spi) +int spi_add_device(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; @@ -673,6 +662,7 @@ static int spi_add_device(struct spi_device *spi) mutex_unlock(&ctlr->add_lock); return status; } +EXPORT_SYMBOL_GPL(spi_add_device); static int spi_add_device_locked(struct spi_device *spi) { @@ -936,48 +926,40 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) * Avoid calling into the driver (or doing delays) if the chip select * isn't actually changing from the last time this was called. */ - if (!force && (spi->controller->last_cs_enable == enable) && + if (!force && ((enable && spi->controller->last_cs == spi->chip_select) || + (!enable && spi->controller->last_cs != spi->chip_select)) && (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH))) return; trace_spi_set_cs(spi, activate); - spi->controller->last_cs_enable = enable; + spi->controller->last_cs = enable ? spi->chip_select : -1; spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; - if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || - !spi->controller->set_cs_timing) && !activate) { + if ((spi->cs_gpiod || !spi->controller->set_cs_timing) && !activate) { spi_delay_exec(&spi->cs_hold, NULL); } if (spi->mode & SPI_CS_HIGH) enable = !enable; - if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) { + if (spi->cs_gpiod) { if (!(spi->mode & SPI_NO_CS)) { - if (spi->cs_gpiod) { - /* - * Historically ACPI has no means of the GPIO polarity and - * thus the SPISerialBus() resource defines it on the per-chip - * basis. In order to avoid a chain of negations, the GPIO - * polarity is considered being Active High. Even for the cases - * when _DSD() is involved (in the updated versions of ACPI) - * the GPIO CS polarity must be defined Active High to avoid - * ambiguity. That's why we use enable, that takes SPI_CS_HIGH - * into account. - */ - if (has_acpi_companion(&spi->dev)) - gpiod_set_value_cansleep(spi->cs_gpiod, !enable); - else - /* Polarity handled by GPIO library */ - gpiod_set_value_cansleep(spi->cs_gpiod, activate); - } else { - /* - * Invert the enable line, as active low is - * default for SPI. - */ - gpio_set_value_cansleep(spi->cs_gpio, !enable); - } + /* + * Historically ACPI has no means of the GPIO polarity and + * thus the SPISerialBus() resource defines it on the per-chip + * basis. In order to avoid a chain of negations, the GPIO + * polarity is considered being Active High. Even for the cases + * when _DSD() is involved (in the updated versions of ACPI) + * the GPIO CS polarity must be defined Active High to avoid + * ambiguity. That's why we use enable, that takes SPI_CS_HIGH + * into account. + */ + if (has_acpi_companion(&spi->dev)) + gpiod_set_value_cansleep(spi->cs_gpiod, !enable); + else + /* Polarity handled by GPIO library */ + gpiod_set_value_cansleep(spi->cs_gpiod, activate); } /* Some SPI masters need both GPIO CS & slave_select */ if ((spi->controller->flags & SPI_MASTER_GPIO_SS) && @@ -987,8 +969,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) spi->controller->set_cs(spi, !enable); } - if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || - !spi->controller->set_cs_timing) { + if (spi->cs_gpiod || !spi->controller->set_cs_timing) { if (activate) spi_delay_exec(&spi->cs_setup, NULL); else @@ -1019,10 +1000,10 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev, int i, ret; if (vmalloced_buf || kmap_buf) { - desc_len = min_t(unsigned int, max_seg_size, PAGE_SIZE); + desc_len = min_t(unsigned long, max_seg_size, PAGE_SIZE); sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); } else if (virt_addr_valid(buf)) { - desc_len = min_t(unsigned int, max_seg_size, ctlr->max_dma_len); + desc_len = min_t(size_t, max_seg_size, ctlr->max_dma_len); sgs = DIV_ROUND_UP(len, desc_len); } else { return -EINVAL; @@ -2318,8 +2299,50 @@ struct acpi_spi_lookup { int irq; u8 bits_per_word; u8 chip_select; + int n; + int index; }; +static int acpi_spi_count(struct acpi_resource *ares, void *data) +{ + struct acpi_resource_spi_serialbus *sb; + int *count = data; + + if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) + return 1; + + sb = &ares->data.spi_serial_bus; + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_SPI) + return 1; + + *count = *count + 1; + + return 1; +} + +/** + * acpi_spi_count_resources - Count the number of SpiSerialBus resources + * @adev: ACPI device + * + * Returns the number of SpiSerialBus resources in the ACPI-device's + * resource-list; or a negative error code. + */ +int acpi_spi_count_resources(struct acpi_device *adev) +{ + LIST_HEAD(r); + int count = 0; + int ret; + + ret = acpi_dev_get_resources(adev, &r, acpi_spi_count, &count); + if (ret < 0) + return ret; + + acpi_dev_free_resource_list(&r); + + return count; +} +EXPORT_SYMBOL_GPL(acpi_spi_count_resources); + static void acpi_spi_parse_apple_properties(struct acpi_device *dev, struct acpi_spi_lookup *lookup) { @@ -2349,6 +2372,8 @@ 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; @@ -2362,14 +2387,35 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) sb = &ares->data.spi_serial_bus; if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) { + if (lookup->index != -1 && lookup->n++ != lookup->index) + return 1; + + if (lookup->index == -1 && !ctlr) + return -ENODEV; + status = acpi_get_handle(NULL, sb->resource_source.string_ptr, &parent_handle); - if (ACPI_FAILURE(status) || - ACPI_HANDLE(ctlr->dev.parent) != parent_handle) + if (ACPI_FAILURE(status)) return -ENODEV; + if (ctlr) { + if (ACPI_HANDLE(ctlr->dev.parent) != parent_handle) + return -ENODEV; + } else { + struct acpi_device *adev; + + if (acpi_bus_get_device(parent_handle, &adev)) + return -ENODEV; + + ctlr = acpi_spi_find_controller_by_adev(adev); + if (!ctlr) + return -ENODEV; + + lookup->ctlr = ctlr; + } + /* * ACPI DeviceSelection numbering is handled by the * host controller driver in Windows and can vary @@ -2408,8 +2454,25 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) return 1; } -static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, - struct acpi_device *adev) +/** + * acpi_spi_device_alloc - Allocate a spi device, and fill it in with ACPI information + * @ctlr: controller to which the spi device belongs + * @adev: ACPI Device for the spi device + * @index: Index of the spi resource inside the ACPI Node + * + * This should be used to allocate a new spi device from and ACPI Node. + * The caller is responsible for calling spi_add_device to register the spi device. + * + * If ctlr is set to NULL, the Controller for the spi device will be looked up + * using the resource. + * If index is set to -1, index is not used. + * Note: If index is -1, ctlr must be set. + * + * Return: a pointer to the new device, or ERR_PTR on error. + */ +struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, + struct acpi_device *adev, + int index) { acpi_handle parent_handle = NULL; struct list_head resource_list; @@ -2417,12 +2480,13 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, struct spi_device *spi; int ret; - if (acpi_bus_get_status(adev) || !adev->status.present || - acpi_device_enumerated(adev)) - return AE_OK; + if (!ctlr && index == -1) + return ERR_PTR(-EINVAL); lookup.ctlr = ctlr; lookup.irq = -1; + lookup.index = index; + lookup.n = 0; INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, @@ -2431,26 +2495,25 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, if (ret < 0) /* found SPI in _CRS but it points to another controller */ - return AE_OK; + return ERR_PTR(-ENODEV); if (!lookup.max_speed_hz && ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) && - ACPI_HANDLE(ctlr->dev.parent) == parent_handle) { + ACPI_HANDLE(lookup.ctlr->dev.parent) == parent_handle) { /* Apple does not use _CRS but nested devices for SPI slaves */ acpi_spi_parse_apple_properties(adev, &lookup); } if (!lookup.max_speed_hz) - return AE_OK; + return ERR_PTR(-ENODEV); - spi = spi_alloc_device(ctlr); + spi = spi_alloc_device(lookup.ctlr); if (!spi) { - dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n", + dev_err(&lookup.ctlr->dev, "failed to allocate SPI device for %s\n", dev_name(&adev->dev)); - return AE_NO_MEMORY; + return ERR_PTR(-ENOMEM); } - ACPI_COMPANION_SET(&spi->dev, adev); spi->max_speed_hz = lookup.max_speed_hz; spi->mode |= lookup.mode; @@ -2458,6 +2521,27 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, spi->bits_per_word = lookup.bits_per_word; spi->chip_select = lookup.chip_select; + return spi; +} +EXPORT_SYMBOL_GPL(acpi_spi_device_alloc); + +static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, + struct acpi_device *adev) +{ + struct spi_device *spi; + + if (acpi_bus_get_status(adev) || !adev->status.present || + acpi_device_enumerated(adev)) + return AE_OK; + + spi = acpi_spi_device_alloc(ctlr, adev, -1); + if (IS_ERR(spi)) { + if (PTR_ERR(spi) == -ENOMEM) + return AE_NO_MEMORY; + else + return AE_OK; + } + acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias, sizeof(spi->modalias)); @@ -2480,10 +2564,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, void *data, void **return_value) { + struct acpi_device *adev = acpi_fetch_acpi_dev(handle); struct spi_controller *ctlr = data; - struct acpi_device *adev; - if (acpi_bus_get_device(handle, &adev)) + if (!adev) return AE_OK; return acpi_register_spi_device(ctlr, adev); @@ -2729,46 +2813,6 @@ struct spi_controller *__devm_spi_alloc_controller(struct device *dev, } EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller); -#ifdef CONFIG_OF -static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) -{ - int nb, i, *cs; - struct device_node *np = ctlr->dev.of_node; - - if (!np) - return 0; - - nb = of_gpio_named_count(np, "cs-gpios"); - ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); - - /* Return error only for an incorrectly formed cs-gpios property */ - if (nb == 0 || nb == -ENOENT) - return 0; - else if (nb < 0) - return nb; - - cs = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect, sizeof(int), - GFP_KERNEL); - ctlr->cs_gpios = cs; - - if (!ctlr->cs_gpios) - return -ENOMEM; - - for (i = 0; i < ctlr->num_chipselect; i++) - cs[i] = -ENOENT; - - for (i = 0; i < nb; i++) - cs[i] = of_get_named_gpio(np, "cs-gpios", i); - - return 0; -} -#else -static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) -{ - return 0; -} -#endif - /** * spi_get_gpio_descs() - grab chip select GPIOs for the master * @ctlr: The SPI master to grab GPIO descriptors for @@ -2953,22 +2997,15 @@ int spi_register_controller(struct spi_controller *ctlr) */ dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num); - if (!spi_controller_is_slave(ctlr)) { - if (ctlr->use_gpio_descriptors) { - status = spi_get_gpio_descs(ctlr); - if (status) - goto free_bus_id; - /* - * A controller using GPIO descriptors always - * supports SPI_CS_HIGH if need be. - */ - ctlr->mode_bits |= SPI_CS_HIGH; - } else { - /* Legacy code path for GPIOs from DT */ - status = of_spi_get_gpio_numbers(ctlr); - if (status) - goto free_bus_id; - } + if (!spi_controller_is_slave(ctlr) && ctlr->use_gpio_descriptors) { + status = spi_get_gpio_descs(ctlr); + if (status) + goto free_bus_id; + /* + * A controller using GPIO descriptors always + * supports SPI_CS_HIGH if need be. + */ + ctlr->mode_bits |= SPI_CS_HIGH; } /* @@ -2980,6 +3017,9 @@ int spi_register_controller(struct spi_controller *ctlr) goto free_bus_id; } + /* setting last_cs to -1 means no chip selected */ + ctlr->last_cs = -1; + status = device_add(&ctlr->dev); if (status < 0) goto free_bus_id; @@ -3457,12 +3497,6 @@ int spi_setup(struct spi_device *spi) */ bad_bits = spi->mode & ~(spi->controller->mode_bits | SPI_CS_WORD | SPI_NO_TX | SPI_NO_RX); - /* - * Nothing prevents from working with active-high CS in case if it - * is driven by GPIO. - */ - if (gpio_is_valid(spi->cs_gpio)) - bad_bits &= ~SPI_CS_HIGH; ugly_bits = bad_bits & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL); @@ -3588,8 +3622,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) * cs_change is set for each transfer. */ if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || - spi->cs_gpiod || - gpio_is_valid(spi->cs_gpio))) { + spi->cs_gpiod)) { size_t maxsize; int ret; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index a5cceca8b82b..53a551714265 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -453,22 +453,29 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) dev_dbg(&spi->dev, "%d bits per word\n", tmp); } break; - case SPI_IOC_WR_MAX_SPEED_HZ: + case SPI_IOC_WR_MAX_SPEED_HZ: { + u32 save; + retval = get_user(tmp, (__u32 __user *)arg); - if (retval == 0) { - u32 save = spi->max_speed_hz; + if (retval) + break; + if (tmp == 0) { + retval = -EINVAL; + break; + } - spi->max_speed_hz = tmp; - retval = spi_setup(spi); - if (retval == 0) { - spidev->speed_hz = tmp; - dev_dbg(&spi->dev, "%d Hz (max)\n", - spidev->speed_hz); - } - spi->max_speed_hz = save; + save = spi->max_speed_hz; + + spi->max_speed_hz = tmp; + retval = spi_setup(spi); + if (retval == 0) { + spidev->speed_hz = tmp; + dev_dbg(&spi->dev, "%d Hz (max)\n", spidev->speed_hz); } - break; + spi->max_speed_hz = save; + break; + } default: /* segmented and/or full-duplex I/O request */ /* Check message and copy into scratch area */ @@ -803,7 +810,7 @@ static int spidev_probe(struct spi_device *spi) return status; } -static int spidev_remove(struct spi_device *spi) +static void spidev_remove(struct spi_device *spi) { struct spidev_data *spidev = spi_get_drvdata(spi); @@ -820,8 +827,6 @@ static int spidev_remove(struct spi_device *spi) if (spidev->users == 0) kfree(spidev); mutex_unlock(&device_list_lock); - - return 0; } static struct spi_driver spidev_spi_driver = { diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index 55677efc0138..b68f5f9b7c78 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -272,21 +272,39 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...); void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...); void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...); +#define FBTFT_DT_TABLE(_compatible) \ +static const struct of_device_id dt_ids[] = { \ + { .compatible = _compatible }, \ + {}, \ +}; \ +MODULE_DEVICE_TABLE(of, dt_ids); + +#define FBTFT_SPI_DRIVER(_name, _compatible, _display, _spi_ids) \ + \ +static int fbtft_driver_probe_spi(struct spi_device *spi) \ +{ \ + return fbtft_probe_common(_display, spi, NULL); \ +} \ + \ +static void fbtft_driver_remove_spi(struct spi_device *spi) \ +{ \ + struct fb_info *info = spi_get_drvdata(spi); \ + \ + fbtft_remove_common(&spi->dev, info); \ +} \ + \ +static struct spi_driver fbtft_driver_spi_driver = { \ + .driver = { \ + .name = _name, \ + .of_match_table = dt_ids, \ + }, \ + .id_table = _spi_ids, \ + .probe = fbtft_driver_probe_spi, \ + .remove = fbtft_driver_remove_spi, \ +}; + #define FBTFT_REGISTER_DRIVER(_name, _compatible, _display) \ \ -static int fbtft_driver_probe_spi(struct spi_device *spi) \ -{ \ - return fbtft_probe_common(_display, spi, NULL); \ -} \ - \ -static int fbtft_driver_remove_spi(struct spi_device *spi) \ -{ \ - struct fb_info *info = spi_get_drvdata(spi); \ - \ - fbtft_remove_common(&spi->dev, info); \ - return 0; \ -} \ - \ static int fbtft_driver_probe_pdev(struct platform_device *pdev) \ { \ return fbtft_probe_common(_display, NULL, pdev); \ @@ -300,22 +318,9 @@ static int fbtft_driver_remove_pdev(struct platform_device *pdev) \ return 0; \ } \ \ -static const struct of_device_id dt_ids[] = { \ - { .compatible = _compatible }, \ - {}, \ -}; \ - \ -MODULE_DEVICE_TABLE(of, dt_ids); \ +FBTFT_DT_TABLE(_compatible) \ \ - \ -static struct spi_driver fbtft_driver_spi_driver = { \ - .driver = { \ - .name = _name, \ - .of_match_table = dt_ids, \ - }, \ - .probe = fbtft_driver_probe_spi, \ - .remove = fbtft_driver_remove_spi, \ -}; \ +FBTFT_SPI_DRIVER(_name, _compatible, _display, NULL) \ \ static struct platform_driver fbtft_driver_platform_driver = { \ .driver = { \ @@ -351,42 +356,15 @@ module_exit(fbtft_driver_module_exit); #define FBTFT_REGISTER_SPI_DRIVER(_name, _comp_vend, _comp_dev, _display) \ \ -static int fbtft_driver_probe_spi(struct spi_device *spi) \ -{ \ - return fbtft_probe_common(_display, spi, NULL); \ -} \ - \ -static int fbtft_driver_remove_spi(struct spi_device *spi) \ -{ \ - struct fb_info *info = spi_get_drvdata(spi); \ - \ - fbtft_remove_common(&spi->dev, info); \ - return 0; \ -} \ - \ -static const struct of_device_id dt_ids[] = { \ - { .compatible = _comp_vend "," _comp_dev }, \ - {}, \ -}; \ - \ -MODULE_DEVICE_TABLE(of, dt_ids); \ +FBTFT_DT_TABLE(_comp_vend "," _comp_dev) \ \ static const struct spi_device_id spi_ids[] = { \ { .name = _comp_dev }, \ {}, \ }; \ - \ MODULE_DEVICE_TABLE(spi, spi_ids); \ \ -static struct spi_driver fbtft_driver_spi_driver = { \ - .driver = { \ - .name = _name, \ - .of_match_table = dt_ids, \ - }, \ - .id_table = spi_ids, \ - .probe = fbtft_driver_probe_spi, \ - .remove = fbtft_driver_remove_spi, \ -}; \ +FBTFT_SPI_DRIVER(_name, _comp_vend "," _comp_dev, _display, spi_ids) \ \ module_spi_driver(fbtft_driver_spi_driver); diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 68c09fa016ed..1d31c35875e3 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -1264,7 +1264,7 @@ RX_failed: return retval; } -static int pi433_remove(struct spi_device *spi) +static void pi433_remove(struct spi_device *spi) { struct pi433_device *device = spi_get_drvdata(spi); @@ -1284,8 +1284,6 @@ static int pi433_remove(struct spi_device *spi) kfree(device->rx_buffer); kfree(device); - - return 0; } static const struct of_device_id pi433_dt_ids[] = { diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index 55ffcd7c42e2..fa0ff66a457d 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -232,12 +232,11 @@ static int wfx_spi_probe(struct spi_device *func) return wfx_probe(bus->core); } -static int wfx_spi_remove(struct spi_device *func) +static void wfx_spi_remove(struct spi_device *func) { struct wfx_spi_priv *bus = spi_get_drvdata(func); wfx_release(bus->core); - return 0; } /* For dynamic driver binding, kernel does not use OF to match driver. It only diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 3c92d4e01488..516cff362434 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -805,7 +805,7 @@ static int max3100_probe(struct spi_device *spi) return 0; } -static int max3100_remove(struct spi_device *spi) +static void max3100_remove(struct spi_device *spi) { struct max3100_port *s = spi_get_drvdata(spi); int i; @@ -828,13 +828,12 @@ static int max3100_remove(struct spi_device *spi) for (i = 0; i < MAX_MAX3100; i++) if (max3100s[i]) { mutex_unlock(&max3100s_lock); - return 0; + return; } pr_debug("removing max3100 driver\n"); uart_unregister_driver(&max3100_uart_driver); mutex_unlock(&max3100s_lock); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index dde0824b2fa5..3112b4a05448 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1487,10 +1487,9 @@ static int max310x_spi_probe(struct spi_device *spi) return max310x_probe(&spi->dev, devtype, regmap, spi->irq); } -static int max310x_spi_remove(struct spi_device *spi) +static void max310x_spi_remove(struct spi_device *spi) { max310x_remove(&spi->dev); - return 0; } static const struct spi_device_id max310x_id_table[] = { diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 38d1c0748533..3a6c68e19c80 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1443,11 +1443,9 @@ static int sc16is7xx_spi_probe(struct spi_device *spi) return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq); } -static int sc16is7xx_spi_remove(struct spi_device *spi) +static void sc16is7xx_spi_remove(struct spi_device *spi) { sc16is7xx_remove(&spi->dev); - - return 0; } static const struct spi_device_id sc16is7xx_spi_id_table[] = { diff --git a/drivers/usb/gadget/udc/max3420_udc.c b/drivers/usb/gadget/udc/max3420_udc.c index d2a2b20cc1ad..7d9bd16190c0 100644 --- a/drivers/usb/gadget/udc/max3420_udc.c +++ b/drivers/usb/gadget/udc/max3420_udc.c @@ -1292,7 +1292,7 @@ del_gadget: return err; } -static int max3420_remove(struct spi_device *spi) +static void max3420_remove(struct spi_device *spi) { struct max3420_udc *udc = spi_get_drvdata(spi); unsigned long flags; @@ -1304,8 +1304,6 @@ static int max3420_remove(struct spi_device *spi) kthread_stop(udc->thread_task); spin_unlock_irqrestore(&udc->lock, flags); - - return 0; } static const struct of_device_id max3420_udc_of_match[] = { diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 30de85a707fe..99a5523a79fb 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1926,7 +1926,7 @@ error: return retval; } -static int +static void max3421_remove(struct spi_device *spi) { struct max3421_hcd *max3421_hcd; @@ -1947,7 +1947,6 @@ max3421_remove(struct spi_device *spi) free_irq(spi->irq, hcd); usb_put_hcd(hcd); - return 0; } static const struct of_device_id max3421_of_match_table[] = { diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index 8a4361e95a11..522dd81110b8 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -506,12 +506,11 @@ static int ams369fg06_probe(struct spi_device *spi) return 0; } -static int ams369fg06_remove(struct spi_device *spi) +static void ams369fg06_remove(struct spi_device *spi) { struct ams369fg06 *lcd = spi_get_drvdata(spi); ams369fg06_power(lcd, FB_BLANK_POWERDOWN); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index 33f5d80495e6..0a57033ae31d 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -542,7 +542,7 @@ static int corgi_lcd_probe(struct spi_device *spi) return 0; } -static int corgi_lcd_remove(struct spi_device *spi) +static void corgi_lcd_remove(struct spi_device *spi) { struct corgi_lcd *lcd = spi_get_drvdata(spi); @@ -550,7 +550,6 @@ static int corgi_lcd_remove(struct spi_device *spi) lcd->bl_dev->props.brightness = 0; backlight_update_status(lcd->bl_dev); corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); - return 0; } static struct spi_driver corgi_lcd_driver = { diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index 328aba9cddad..e7b6bd827986 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -526,10 +526,9 @@ static int ili922x_probe(struct spi_device *spi) return 0; } -static int ili922x_remove(struct spi_device *spi) +static void ili922x_remove(struct spi_device *spi) { ili922x_poweroff(spi); - return 0; } static struct spi_driver ili922x_driver = { diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index 46f97d1c3d21..cc763cf15f53 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -223,12 +223,11 @@ static int l4f00242t03_probe(struct spi_device *spi) return 0; } -static int l4f00242t03_remove(struct spi_device *spi) +static void l4f00242t03_remove(struct spi_device *spi) { struct l4f00242t03_priv *priv = spi_get_drvdata(spi); l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); - return 0; } static void l4f00242t03_shutdown(struct spi_device *spi) diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index f949b66dce1b..5c46df8022bf 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -364,12 +364,11 @@ static int lms501kf03_probe(struct spi_device *spi) return 0; } -static int lms501kf03_remove(struct spi_device *spi) +static void lms501kf03_remove(struct spi_device *spi) { struct lms501kf03 *lcd = spi_get_drvdata(spi); lms501kf03_power(lcd, FB_BLANK_POWERDOWN); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index 5cbf621e48bd..b6d373af6e3f 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c @@ -255,12 +255,11 @@ static int ltv350qv_probe(struct spi_device *spi) return 0; } -static int ltv350qv_remove(struct spi_device *spi) +static void ltv350qv_remove(struct spi_device *spi) { struct ltv350qv *lcd = spi_get_drvdata(spi); ltv350qv_power(lcd, FB_BLANK_POWERDOWN); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 0de044dcafd5..fc6fbaf85594 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -397,12 +397,11 @@ static int tdo24m_probe(struct spi_device *spi) return 0; } -static int tdo24m_remove(struct spi_device *spi) +static void tdo24m_remove(struct spi_device *spi) { struct tdo24m *lcd = spi_get_drvdata(spi); tdo24m_power(lcd, FB_BLANK_POWERDOWN); - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 38765544345b..23d6c6bf0f54 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -232,15 +232,13 @@ err_register: return ret; } -static int tosa_lcd_remove(struct spi_device *spi) +static void tosa_lcd_remove(struct spi_device *spi) { struct tosa_lcd_data *data = spi_get_drvdata(spi); i2c_unregister_device(data->i2c); tosa_lcd_tg_off(data); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 3567b45f9ba9..bfc1913e8b55 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c @@ -233,11 +233,9 @@ static int vgg2432a4_probe(struct spi_device *spi) return 0; } -static int vgg2432a4_remove(struct spi_device *spi) +static void vgg2432a4_remove(struct spi_device *spi) { ili9320_remove(spi_get_drvdata(spi)); - - return 0; } static void vgg2432a4_shutdown(struct spi_device *spi) diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c index a75ae0c9b14c..03cff39d392d 100644 --- a/drivers/video/fbdev/omap/lcd_mipid.c +++ b/drivers/video/fbdev/omap/lcd_mipid.c @@ -570,14 +570,12 @@ static int mipid_spi_probe(struct spi_device *spi) return 0; } -static int mipid_spi_remove(struct spi_device *spi) +static void mipid_spi_remove(struct spi_device *spi) { struct mipid_device *md = dev_get_drvdata(&spi->dev); mipid_disable(&md->panel); kfree(md); - - return 0; } static struct spi_driver mipid_spi_driver = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c index 1bec7a4422e8..aab67721263d 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c @@ -316,7 +316,7 @@ err_gpio: return r; } -static int lb035q02_panel_spi_remove(struct spi_device *spi) +static void lb035q02_panel_spi_remove(struct spi_device *spi) { struct panel_drv_data *ddata = spi_get_drvdata(spi); struct omap_dss_device *dssdev = &ddata->dssdev; @@ -328,8 +328,6 @@ static int lb035q02_panel_spi_remove(struct spi_device *spi) lb035q02_disconnect(dssdev); omap_dss_put_device(in); - - return 0; } static const struct of_device_id lb035q02_of_match[] = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c index dff9ebbadfc0..be9910ff6e62 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c @@ -327,7 +327,7 @@ err_gpio: return r; } -static int nec_8048_remove(struct spi_device *spi) +static void nec_8048_remove(struct spi_device *spi) { struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); struct omap_dss_device *dssdev = &ddata->dssdev; @@ -341,8 +341,6 @@ static int nec_8048_remove(struct spi_device *spi) nec_8048_disconnect(dssdev); omap_dss_put_device(in); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c index 8d8b5ff7d43c..a909b5385ca5 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c @@ -857,7 +857,7 @@ err_gpio: return r; } -static int acx565akm_remove(struct spi_device *spi) +static void acx565akm_remove(struct spi_device *spi) { struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); struct omap_dss_device *dssdev = &ddata->dssdev; @@ -874,8 +874,6 @@ static int acx565akm_remove(struct spi_device *spi) acx565akm_disconnect(dssdev); omap_dss_put_device(in); - - return 0; } static const struct of_device_id acx565akm_of_match[] = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c index 595ebd8bd5dc..3c0f887d3092 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c @@ -425,7 +425,7 @@ err_reg: return r; } -static int td028ttec1_panel_remove(struct spi_device *spi) +static void td028ttec1_panel_remove(struct spi_device *spi) { struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); struct omap_dss_device *dssdev = &ddata->dssdev; @@ -439,8 +439,6 @@ static int td028ttec1_panel_remove(struct spi_device *spi) td028ttec1_panel_disconnect(dssdev); omap_dss_put_device(in); - - return 0; } static const struct of_device_id td028ttec1_of_match[] = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c index afac1d9445aa..58bbba7c037f 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c @@ -564,7 +564,7 @@ err_regulator: return r; } -static int tpo_td043_remove(struct spi_device *spi) +static void tpo_td043_remove(struct spi_device *spi) { struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); struct omap_dss_device *dssdev = &ddata->dssdev; @@ -580,8 +580,6 @@ static int tpo_td043_remove(struct spi_device *spi) omap_dss_put_device(in); sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group); - - return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/include/linux/mfd/lpc_ich.h b/include/linux/mfd/lpc_ich.h index 39967a5eca6d..ea4a4b1b246a 100644 --- a/include/linux/mfd/lpc_ich.h +++ b/include/linux/mfd/lpc_ich.h @@ -8,7 +8,7 @@ #ifndef LPC_ICH_H #define LPC_ICH_H -#include <linux/platform_data/x86/intel-spi.h> +#include <linux/platform_data/x86/spi-intel.h> /* GPIO resources */ #define ICH_RES_GPIO 0 diff --git a/include/linux/platform_data/spi-s3c64xx.h b/include/linux/platform_data/spi-s3c64xx.h index 773daf7915a3..5df1ace6d2c9 100644 --- a/include/linux/platform_data/spi-s3c64xx.h +++ b/include/linux/platform_data/spi-s3c64xx.h @@ -16,7 +16,6 @@ struct platform_device; * struct s3c64xx_spi_csinfo - ChipSelect description * @fb_delay: Slave specific feedback delay. * Refer to FB_CLK_SEL register definition in SPI chapter. - * @line: Custom 'identity' of the CS line. * * This is per SPI-Slave Chipselect information. * Allocate and initialize one in machine init code and make the @@ -24,7 +23,6 @@ struct platform_device; */ struct s3c64xx_spi_csinfo { u8 fb_delay; - unsigned line; }; /** @@ -43,26 +41,16 @@ struct s3c64xx_spi_info { /** * s3c64xx_spi_set_platdata - SPI Controller configure callback by the board * initialization code. - * @cfg_gpio: Pointer to gpio setup function. * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks. * @num_cs: Number of elements in the 'cs' array. * * Call this from machine init code for each SPI Controller that * has some chips attached to it. */ -extern void s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, - int num_cs); -extern void s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, - int num_cs); -extern void s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr, - int num_cs); +extern void s3c64xx_spi0_set_platdata(int src_clk_nr, int num_cs); /* defined by architecture to configure gpio */ extern int s3c64xx_spi0_cfg_gpio(void); -extern int s3c64xx_spi1_cfg_gpio(void); -extern int s3c64xx_spi2_cfg_gpio(void); extern struct s3c64xx_spi_info s3c64xx_spi0_pdata; -extern struct s3c64xx_spi_info s3c64xx_spi1_pdata; -extern struct s3c64xx_spi_info s3c64xx_spi2_pdata; #endif /*__SPI_S3C64XX_H */ diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/spi-intel.h index 7f53a5c6f35e..a512ec37abbb 100644 --- a/include/linux/platform_data/x86/intel-spi.h +++ b/include/linux/platform_data/x86/spi-intel.h @@ -6,8 +6,8 @@ * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ -#ifndef INTEL_SPI_PDATA_H -#define INTEL_SPI_PDATA_H +#ifndef SPI_INTEL_PDATA_H +#define SPI_INTEL_PDATA_H enum intel_spi_type { INTEL_SPI_BYT = 1, @@ -19,11 +19,13 @@ enum intel_spi_type { /** * struct intel_spi_boardinfo - Board specific data for Intel SPI driver * @type: Type which this controller is compatible with - * @writeable: The chip is writeable + * @set_writeable: Try to make the chip writeable (optional) + * @data: Data to be passed to @set_writeable can be %NULL */ struct intel_spi_boardinfo { enum intel_spi_type type; - bool writeable; + bool (*set_writeable)(void __iomem *base, void *data); + void *data; }; -#endif /* INTEL_SPI_PDATA_H */ +#endif /* SPI_INTEL_PDATA_H */ diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index ca74dce36706..4658e7801b42 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h @@ -42,7 +42,6 @@ struct pxa2xx_spi_chip { u8 rx_threshold; u8 dma_burst_size; u32 timeout; - int gpio_cs; }; #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) diff --git a/include/linux/spi/s3c24xx.h b/include/linux/spi/s3c24xx.h index 440a71593162..9b8bb22d5b0c 100644 --- a/include/linux/spi/s3c24xx.h +++ b/include/linux/spi/s3c24xx.h @@ -10,14 +10,9 @@ #define __LINUX_SPI_S3C24XX_H __FILE__ struct s3c2410_spi_info { - int pin_cs; /* simple gpio cs */ unsigned int num_cs; /* total chipselects */ int bus_num; /* bus number to use. */ - unsigned int use_fiq:1; /* use fiq */ - - void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable); - void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol); }; extern int s3c24xx_set_fiq(unsigned int irq, u32 *ack_ptr, bool on); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 7ab3fed7b804..7d005fa4631c 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -16,6 +16,7 @@ #include <linux/gpio/consumer.h> #include <uapi/linux/spi/spi.h> +#include <linux/acpi.h> struct dma_chan; struct software_node; @@ -136,9 +137,6 @@ extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer); * for driver coldplugging, and in uevents used for hotplugging * @driver_override: If the name of a driver is written to this attribute, then * the device will bind to the named driver and only the named driver. - * @cs_gpio: LEGACY: gpio number of the chipselect line (optional, -ENOENT when - * not using a GPIO line) use cs_gpiod in new drivers by opting in on - * the spi_master. * @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when * not using a GPIO line) * @word_delay: delay to be inserted between consecutive @@ -185,7 +183,6 @@ struct spi_device { void *controller_data; char modalias[SPI_NAME_SIZE]; const char *driver_override; - int cs_gpio; /* LEGACY: chip select gpio */ struct gpio_desc *cs_gpiod; /* chip select gpio desc */ struct spi_delay word_delay; /* inter-word delay */ /* CS delays */ @@ -280,7 +277,7 @@ struct spi_message; struct spi_driver { const struct spi_device_id *id_table; int (*probe)(struct spi_device *spi); - int (*remove)(struct spi_device *spi); + void (*remove)(struct spi_device *spi); void (*shutdown)(struct spi_device *spi); struct device_driver driver; }; @@ -373,7 +370,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * @cur_msg_prepared: spi_prepare_message was called for the currently * in-flight message * @cur_msg_mapped: message has been mapped for DMA - * @last_cs_enable: was enable true on the last call to set_cs. + * @last_cs: the last chip_select that is recorded by set_cs, -1 on non chip + * selected * @last_cs_mode_high: was (mode & SPI_CS_HIGH) true on the last call to set_cs. * @xfer_completion: used by core transfer_one_message() * @busy: message pump is busy @@ -417,17 +415,12 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * controller has native support for memory like operations. * @unprepare_message: undo any work done by prepare_message(). * @slave_abort: abort the ongoing transfer request on an SPI slave controller - * @cs_gpios: LEGACY: array of GPIO descs to use as chip select lines; one per - * CS number. Any individual value may be -ENOENT for CS lines that - * are not GPIOs (driven by the SPI controller itself). Use the cs_gpiods - * in new drivers. * @cs_gpiods: Array of GPIO descs to use as chip select lines; one per CS * number. Any individual value may be NULL for CS lines that * are not GPIOs (driven by the SPI controller itself). * @use_gpio_descriptors: Turns on the code in the SPI core to parse and grab - * GPIO descriptors rather than using global GPIO numbers grabbed by the - * driver. This will fill in @cs_gpiods and @cs_gpios should not be used, - * and SPI devices will have the cs_gpiod assigned rather than cs_gpio. + * GPIO descriptors. This will fill in @cs_gpiods and SPI devices will have + * the cs_gpiod assigned if a GPIO line is found for the chipselect. * @unused_native_cs: When cs_gpiods is used, spi_register_controller() will * fill in this field with the first unused native CS, to be used by SPI * controller drivers that need to drive a native CS when using GPIO CS. @@ -611,7 +604,7 @@ struct spi_controller { bool auto_runtime_pm; bool cur_msg_prepared; bool cur_msg_mapped; - bool last_cs_enable; + char last_cs; bool last_cs_mode_high; bool fallback; struct completion xfer_completion; @@ -641,7 +634,6 @@ struct spi_controller { const struct spi_controller_mem_ops *mem_ops; /* gpio chip select */ - int *cs_gpios; struct gpio_desc **cs_gpiods; bool use_gpio_descriptors; s8 unused_native_cs; @@ -759,6 +751,13 @@ extern int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr); extern void spi_unregister_controller(struct spi_controller *ctlr); +#if IS_ENABLED(CONFIG_ACPI) +extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, + struct acpi_device *adev, + int index); +int acpi_spi_count_resources(struct acpi_device *adev); +#endif + /* * SPI resource management while processing a SPI message */ @@ -1452,8 +1451,20 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) * use spi_new_device() to describe each device. You can also call * spi_unregister_device() to start making that device vanish, but * normally that would be handled by spi_unregister_controller(). + * + * You can also use spi_alloc_device() and spi_add_device() to use a two + * stage registration sequence for each spi_device. This gives the caller + * some more control over the spi_device structure before it is registered, + * but requires that caller to initialize fields that would otherwise + * be defined using the board info. */ extern struct spi_device * +spi_alloc_device(struct spi_controller *ctlr); + +extern int +spi_add_device(struct spi_device *spi); + +extern struct spi_device * spi_new_device(struct spi_controller *, struct spi_board_info *); extern void spi_unregister_device(struct spi_device *spi); diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c index 9f8123893cc8..50eb6c0e6658 100644 --- a/sound/pci/hda/cs35l41_hda_spi.c +++ b/sound/pci/hda/cs35l41_hda_spi.c @@ -28,11 +28,9 @@ static int cs35l41_hda_spi_probe(struct spi_device *spi) devm_regmap_init_spi(spi, &cs35l41_regmap_spi)); } -static int cs35l41_hda_spi_remove(struct spi_device *spi) +static void cs35l41_hda_spi_remove(struct spi_device *spi) { cs35l41_hda_remove(&spi->dev); - - return 0; } static const struct spi_device_id cs35l41_hda_spi_id[] = { diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c index 655689c9778a..7c9242c2ff94 100644 --- a/sound/soc/codecs/adau1761-spi.c +++ b/sound/soc/codecs/adau1761-spi.c @@ -45,10 +45,9 @@ static int adau1761_spi_probe(struct spi_device *spi) id->driver_data, adau1761_spi_switch_mode); } -static int adau1761_spi_remove(struct spi_device *spi) +static void adau1761_spi_remove(struct spi_device *spi) { adau17x1_remove(&spi->dev); - return 0; } static const struct spi_device_id adau1761_spi_id[] = { diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c index bb5613574786..1a09633d5a88 100644 --- a/sound/soc/codecs/adau1781-spi.c +++ b/sound/soc/codecs/adau1781-spi.c @@ -45,10 +45,9 @@ static int adau1781_spi_probe(struct spi_device *spi) id->driver_data, adau1781_spi_switch_mode); } -static int adau1781_spi_remove(struct spi_device *spi) +static void adau1781_spi_remove(struct spi_device *spi) { adau17x1_remove(&spi->dev); - return 0; } static const struct spi_device_id adau1781_spi_id[] = { diff --git a/sound/soc/codecs/cs35l41-spi.c b/sound/soc/codecs/cs35l41-spi.c index 6dfd5459aa20..169221a5b09f 100644 --- a/sound/soc/codecs/cs35l41-spi.c +++ b/sound/soc/codecs/cs35l41-spi.c @@ -55,13 +55,11 @@ static int cs35l41_spi_probe(struct spi_device *spi) return cs35l41_probe(cs35l41, pdata); } -static int cs35l41_spi_remove(struct spi_device *spi) +static void cs35l41_spi_remove(struct spi_device *spi) { struct cs35l41_private *cs35l41 = spi_get_drvdata(spi); cs35l41_remove(cs35l41); - - return 0; } #ifdef CONFIG_OF diff --git a/sound/soc/codecs/pcm3168a-spi.c b/sound/soc/codecs/pcm3168a-spi.c index ecd379f308e6..b5b08046f545 100644 --- a/sound/soc/codecs/pcm3168a-spi.c +++ b/sound/soc/codecs/pcm3168a-spi.c @@ -26,11 +26,9 @@ static int pcm3168a_spi_probe(struct spi_device *spi) return pcm3168a_probe(&spi->dev, regmap); } -static int pcm3168a_spi_remove(struct spi_device *spi) +static void pcm3168a_spi_remove(struct spi_device *spi) { pcm3168a_remove(&spi->dev); - - return 0; } static const struct spi_device_id pcm3168a_spi_id[] = { diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c index 7cf559b47e1c..4d29e7196380 100644 --- a/sound/soc/codecs/pcm512x-spi.c +++ b/sound/soc/codecs/pcm512x-spi.c @@ -26,10 +26,9 @@ static int pcm512x_spi_probe(struct spi_device *spi) return pcm512x_probe(&spi->dev, regmap); } -static int pcm512x_spi_remove(struct spi_device *spi) +static void pcm512x_spi_remove(struct spi_device *spi) { pcm512x_remove(&spi->dev); - return 0; } static const struct spi_device_id pcm512x_spi_id[] = { diff --git a/sound/soc/codecs/tlv320aic32x4-spi.c b/sound/soc/codecs/tlv320aic32x4-spi.c index a8958cd1c692..03cce8d6404f 100644 --- a/sound/soc/codecs/tlv320aic32x4-spi.c +++ b/sound/soc/codecs/tlv320aic32x4-spi.c @@ -46,11 +46,9 @@ static int aic32x4_spi_probe(struct spi_device *spi) return aic32x4_probe(&spi->dev, regmap); } -static int aic32x4_spi_remove(struct spi_device *spi) +static void aic32x4_spi_remove(struct spi_device *spi) { aic32x4_remove(&spi->dev); - - return 0; } static const struct spi_device_id aic32x4_spi_id[] = { diff --git a/sound/soc/codecs/tlv320aic3x-spi.c b/sound/soc/codecs/tlv320aic3x-spi.c index 494e84402232..deed6ec7e081 100644 --- a/sound/soc/codecs/tlv320aic3x-spi.c +++ b/sound/soc/codecs/tlv320aic3x-spi.c @@ -35,11 +35,9 @@ static int aic3x_spi_probe(struct spi_device *spi) return aic3x_probe(&spi->dev, regmap, id->driver_data); } -static int aic3x_spi_remove(struct spi_device *spi) +static void aic3x_spi_remove(struct spi_device *spi) { aic3x_remove(&spi->dev); - - return 0; } static const struct spi_device_id aic3x_spi_id[] = { diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 28b4656c4e14..1bef1c500c8e 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -969,7 +969,7 @@ static int wm0010_spi_probe(struct spi_device *spi) return 0; } -static int wm0010_spi_remove(struct spi_device *spi) +static void wm0010_spi_remove(struct spi_device *spi) { struct wm0010_priv *wm0010 = spi_get_drvdata(spi); @@ -980,8 +980,6 @@ static int wm0010_spi_remove(struct spi_device *spi) if (wm0010->irq) free_irq(wm0010->irq, wm0010); - - return 0; } static struct spi_driver wm0010_spi_driver = { diff --git a/sound/soc/codecs/wm8804-spi.c b/sound/soc/codecs/wm8804-spi.c index 9a8da1511c34..628568724c20 100644 --- a/sound/soc/codecs/wm8804-spi.c +++ b/sound/soc/codecs/wm8804-spi.c @@ -24,10 +24,9 @@ static int wm8804_spi_probe(struct spi_device *spi) return wm8804_probe(&spi->dev, regmap); } -static int wm8804_spi_remove(struct spi_device *spi) +static void wm8804_spi_remove(struct spi_device *spi) { wm8804_remove(&spi->dev); - return 0; } static const struct of_device_id wm8804_of_match[] = { diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 76c0e37a838c..56d2c712e257 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -1001,7 +1001,7 @@ out: return retval; } -static int snd_at73c213_remove(struct spi_device *spi) +static void snd_at73c213_remove(struct spi_device *spi) { struct snd_card *card = dev_get_drvdata(&spi->dev); struct snd_at73c213 *chip = card->private_data; @@ -1066,8 +1066,6 @@ out: ssc_free(chip->ssc); snd_card_free(card); - - return 0; } #ifdef CONFIG_PM_SLEEP |