Merge 34aac0a33d ("Merge tag 'spi-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi") into android-mainline
Steps on the way to 6.7-rc1 Change-Id: Iad41a9ce20c9cfa886cd5b19bbfbaac78ea27e79 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -23,6 +23,7 @@ properties:
|
||||
- enum:
|
||||
- qcom,qcm2290-cpufreq-hw
|
||||
- qcom,sc7180-cpufreq-hw
|
||||
- qcom,sdm670-cpufreq-hw
|
||||
- qcom,sdm845-cpufreq-hw
|
||||
- qcom,sm6115-cpufreq-hw
|
||||
- qcom,sm6350-cpufreq-hw
|
||||
@@ -36,11 +37,13 @@ properties:
|
||||
- qcom,sa8775p-cpufreq-epss
|
||||
- qcom,sc7280-cpufreq-epss
|
||||
- qcom,sc8280xp-cpufreq-epss
|
||||
- qcom,sdx75-cpufreq-epss
|
||||
- qcom,sm6375-cpufreq-epss
|
||||
- qcom,sm8250-cpufreq-epss
|
||||
- qcom,sm8350-cpufreq-epss
|
||||
- qcom,sm8450-cpufreq-epss
|
||||
- qcom,sm8550-cpufreq-epss
|
||||
- qcom,sm8650-cpufreq-epss
|
||||
- const: qcom,cpufreq-epss
|
||||
|
||||
reg:
|
||||
@@ -128,6 +131,7 @@ allOf:
|
||||
- qcom,qdu1000-cpufreq-epss
|
||||
- qcom,sc7180-cpufreq-hw
|
||||
- qcom,sc8280xp-cpufreq-epss
|
||||
- qcom,sdm670-cpufreq-hw
|
||||
- qcom,sdm845-cpufreq-hw
|
||||
- qcom,sm6115-cpufreq-hw
|
||||
- qcom,sm6350-cpufreq-hw
|
||||
|
||||
@@ -27,8 +27,12 @@ select:
|
||||
enum:
|
||||
- qcom,apq8064
|
||||
- qcom,apq8096
|
||||
- qcom,ipq5332
|
||||
- qcom,ipq6018
|
||||
- qcom,ipq8064
|
||||
- qcom,ipq8074
|
||||
- qcom,ipq9574
|
||||
- qcom,msm8909
|
||||
- qcom,msm8939
|
||||
- qcom,msm8960
|
||||
- qcom,msm8974
|
||||
@@ -43,7 +47,9 @@ patternProperties:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
const: operating-points-v2-kryo-cpu
|
||||
enum:
|
||||
- operating-points-v2-krait-cpu
|
||||
- operating-points-v2-kryo-cpu
|
||||
then:
|
||||
$ref: /schemas/opp/opp-v2-kryo-cpu.yaml#
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/devfreq/event/rockchip,dfi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip DFI
|
||||
|
||||
maintainers:
|
||||
- Sascha Hauer <s.hauer@pengutronix.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,rk3399-dfi
|
||||
- rockchip,rk3568-dfi
|
||||
- rockchip,rk3588-dfi
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk_ddr_mon
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
rockchip,pmu:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the syscon managing the "PMU general register files".
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- reg
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3399-dfi
|
||||
|
||||
then:
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/rk3308-cru.h>
|
||||
|
||||
bus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
dfi: dfi@ff630000 {
|
||||
compatible = "rockchip,rk3399-dfi";
|
||||
reg = <0x00 0xff630000 0x00 0x4000>;
|
||||
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
rockchip,pmu = <&pmugrf>;
|
||||
clocks = <&cru PCLK_DDR_MON>;
|
||||
clock-names = "pclk_ddr_mon";
|
||||
};
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
* Rockchip rk3399 DFI device
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "rockchip,rk3399-dfi".
|
||||
- reg: physical base address of each DFI and length of memory mapped region
|
||||
- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
|
||||
- clocks: phandles for clock specified in "clock-names" property
|
||||
- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
|
||||
|
||||
Example:
|
||||
dfi: dfi@ff630000 {
|
||||
compatible = "rockchip,rk3399-dfi";
|
||||
reg = <0x00 0xff630000 0x00 0x4000>;
|
||||
rockchip,pmu = <&pmugrf>;
|
||||
clocks = <&cru PCLK_DDR_MON>;
|
||||
clock-names = "pclk_ddr_mon";
|
||||
};
|
||||
@@ -18,9 +18,17 @@ properties:
|
||||
- fsl,imx31-gpio
|
||||
- fsl,imx35-gpio
|
||||
- fsl,imx7d-gpio
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx27-gpio
|
||||
- const: fsl,imx21-gpio
|
||||
- items:
|
||||
- const: fsl,imx35-gpio
|
||||
- const: fsl,imx31-gpio
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx25-gpio
|
||||
- const: fsl,imx35-gpio
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx50-gpio
|
||||
|
||||
@@ -20,6 +20,7 @@ description: |
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: fsl,imx8ulp-gpio
|
||||
- const: fsl,vf610-gpio
|
||||
- items:
|
||||
- const: fsl,imx7ulp-gpio
|
||||
@@ -27,16 +28,18 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx93-gpio
|
||||
- fsl,imx8ulp-gpio
|
||||
- const: fsl,imx7ulp-gpio
|
||||
- fsl,imx95-gpio
|
||||
- const: fsl,imx8ulp-gpio
|
||||
|
||||
reg:
|
||||
description: The first reg tuple represents the PORT module, the second tuple
|
||||
represents the GPIO module.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
items:
|
||||
- description: GPIO Trustzone non-secure interrupt number
|
||||
- description: GPIO Trustzone secure interrupt number
|
||||
minItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
@@ -59,7 +62,8 @@ properties:
|
||||
- const: port
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
patternProperties:
|
||||
"^.+-hog(-[0-9]+)?$":
|
||||
@@ -77,6 +81,30 @@ required:
|
||||
- "#gpio-cells"
|
||||
- gpio-controller
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- fsl,vf610-gpio
|
||||
- fsl,imx7ulp-gpio
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
reg:
|
||||
items:
|
||||
- description: PORT register base address
|
||||
- description: GPIO register base address
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 2
|
||||
reg:
|
||||
items:
|
||||
- description: GPIO register base address
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
Intel IXP4xx XScale Networking Processors GPIO
|
||||
|
||||
This GPIO controller is found in the Intel IXP4xx processors.
|
||||
It supports 16 GPIO lines.
|
||||
|
||||
The interrupt portions of the GPIO controller is hierarchical:
|
||||
the synchronous edge detector is part of the GPIO block, but the
|
||||
actual enabling/disabling of the interrupt line is done in the
|
||||
main IXP4xx interrupt controller which has a 1:1 mapping for
|
||||
the first 12 GPIO lines to 12 system interrupts.
|
||||
|
||||
The remaining 4 GPIO lines can not be used for receiving
|
||||
interrupts.
|
||||
|
||||
The interrupt parent of this GPIO controller must be the
|
||||
IXP4xx interrupt controller.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Should be
|
||||
"intel,ixp4xx-gpio"
|
||||
- reg : Should contain registers location and length
|
||||
- gpio-controller : marks this as a GPIO controller
|
||||
- #gpio-cells : Should be 2, see gpio/gpio.txt
|
||||
- interrupt-controller : marks this as an interrupt controller
|
||||
- #interrupt-cells : a standard two-cell interrupt, see
|
||||
interrupt-controller/interrupts.txt
|
||||
|
||||
Example:
|
||||
|
||||
gpio0: gpio@c8004000 {
|
||||
compatible = "intel,ixp4xx-gpio";
|
||||
reg = <0xc8004000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/gpio/intel,ixp4xx-gpio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel IXP4xx XScale Networking Processors GPIO Controller
|
||||
|
||||
description: |
|
||||
This GPIO controller is found in the Intel IXP4xx
|
||||
processors. It supports 16 GPIO lines.
|
||||
The interrupt portions of the GPIO controller is hierarchical.
|
||||
The synchronous edge detector is part of the GPIO block, but the
|
||||
actual enabling/disabling of the interrupt line is done in the
|
||||
main IXP4xx interrupt controller which has a 1-to-1 mapping for
|
||||
the first 12 GPIO lines to 12 system interrupts.
|
||||
The remaining 4 GPIO lines can not be used for receiving
|
||||
interrupts.
|
||||
The interrupt parent of this GPIO controller must be the
|
||||
IXP4xx interrupt controller.
|
||||
GPIO 14 and 15 can be used as clock outputs rather than GPIO,
|
||||
and this can be enabled by a special flag.
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,ixp4xx-gpio
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
intel,ixp4xx-gpio14-clkout:
|
||||
description: If defined, enables clock output on GPIO 14
|
||||
instead of GPIO.
|
||||
type: boolean
|
||||
|
||||
intel,ixp4xx-gpio15-clkout:
|
||||
description: If defined, enables clock output on GPIO 15
|
||||
instead of GPIO.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#gpio-cells"
|
||||
- interrupt-controller
|
||||
- "#interrupt-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
gpio@c8004000 {
|
||||
compatible = "intel,ixp4xx-gpio";
|
||||
reg = <0xc8004000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
@@ -11,9 +11,22 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- loongson,ls2k-gpio
|
||||
- loongson,ls7a-gpio
|
||||
oneOf:
|
||||
- enum:
|
||||
- loongson,ls2k-gpio
|
||||
- loongson,ls2k0500-gpio0
|
||||
- loongson,ls2k0500-gpio1
|
||||
- loongson,ls2k2000-gpio0
|
||||
- loongson,ls2k2000-gpio1
|
||||
- loongson,ls2k2000-gpio2
|
||||
- loongson,ls3a5000-gpio
|
||||
- loongson,ls7a-gpio
|
||||
- items:
|
||||
- const: loongson,ls2k1000-gpio
|
||||
- const: loongson,ls2k-gpio
|
||||
- items:
|
||||
- const: loongson,ls7a1000-gpio
|
||||
- const: loongson,ls7a-gpio
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -49,7 +62,7 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
gpio0: gpio@1fe00500 {
|
||||
compatible = "loongson,ls2k-gpio";
|
||||
compatible = "loongson,ls2k1000-gpio", "loongson,ls2k-gpio";
|
||||
reg = <0x1fe00500 0x38>;
|
||||
ngpios = <64>;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
@@ -18,7 +18,7 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Node to get DDR loading. Refer to
|
||||
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt.
|
||||
Documentation/devicetree/bindings/devfreq/event/rockchip,dfi.yaml.
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
@@ -26,7 +26,9 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: operating-points-v2-kryo-cpu
|
||||
enum:
|
||||
- operating-points-v2-krait-cpu
|
||||
- operating-points-v2-kryo-cpu
|
||||
|
||||
nvmem-cells:
|
||||
description: |
|
||||
@@ -47,6 +49,8 @@ patternProperties:
|
||||
|
||||
opp-microvolt: true
|
||||
|
||||
opp-peak-kBps: true
|
||||
|
||||
opp-supported-hw:
|
||||
description: |
|
||||
A single 32 bit bitmap value, representing compatible HW.
|
||||
@@ -63,14 +67,22 @@ patternProperties:
|
||||
5: MSM8996SG, speedbin 1
|
||||
6: MSM8996SG, speedbin 2
|
||||
7-31: unused
|
||||
enum: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x9, 0xd, 0xe, 0xf,
|
||||
0x10, 0x20, 0x30, 0x70]
|
||||
|
||||
Bitmap for IPQ806x SoC:
|
||||
0: IPQ8062
|
||||
1: IPQ8064/IPQ8066/IPQ8068
|
||||
2: IPQ8065/IPQ8069
|
||||
3-31: unused
|
||||
|
||||
Other platforms use bits directly corresponding to speedbin index.
|
||||
|
||||
clock-latency-ns: true
|
||||
|
||||
required-opps: true
|
||||
|
||||
patternProperties:
|
||||
'^opp-microvolt-speed[0-9]+-pvs[0-9]+$': true
|
||||
|
||||
required:
|
||||
- opp-hz
|
||||
|
||||
@@ -256,6 +268,22 @@ examples:
|
||||
};
|
||||
};
|
||||
|
||||
/* Dummy opp table to give example for named opp-microvolt */
|
||||
opp-table-2 {
|
||||
compatible = "operating-points-v2-krait-cpu";
|
||||
nvmem-cells = <&speedbin_efuse>;
|
||||
|
||||
opp-384000000 {
|
||||
opp-hz = /bits/ 64 <384000000>;
|
||||
opp-microvolt-speed0-pvs0 = <1000000 950000 1050000>;
|
||||
opp-microvolt-speed0-pvs1 = <925000 878750 971250>;
|
||||
opp-microvolt-speed0-pvs2 = <875000 831250 918750>;
|
||||
opp-microvolt-speed0-pvs3 = <800000 760000 840000>;
|
||||
opp-supported-hw = <0x7>;
|
||||
clock-latency-ns = <100000>;
|
||||
};
|
||||
};
|
||||
|
||||
smem {
|
||||
compatible = "qcom,smem";
|
||||
memory-region = <&smem_mem>;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright (c) 2023 Analog Devices, Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/adi,max77503-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices MAX77503 Buck Converter
|
||||
|
||||
maintainers:
|
||||
- Gokhan Celik <Gokhan.Celik@analog.com>
|
||||
|
||||
description: |
|
||||
The Analog Devices MAX77503 is a single channel 14V input, 1.5A
|
||||
high-efficiency buck converter. This converter has 94% efficiency
|
||||
for 2-Cell/3-Cell battery applications.
|
||||
|
||||
allOf:
|
||||
- $ref: regulator.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,max77503
|
||||
|
||||
reg:
|
||||
description: I2C address of the device
|
||||
items:
|
||||
- enum: [0x1e, 0x24, 0x37]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
regulator@1e {
|
||||
compatible = "adi,max77503";
|
||||
reg = <0x1e>;
|
||||
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
};
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
* Dialog Semiconductor DA9210 Multi-phase 12A DCDC BUCK Converter
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: must be "dlg,da9210"
|
||||
- reg: the i2c slave address of the regulator. It should be 0x68.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- interrupts: a reference to the DA9210 interrupt, if available.
|
||||
|
||||
Any standard regulator properties can be used to configure the single da9210
|
||||
DCDC.
|
||||
|
||||
Example:
|
||||
|
||||
da9210@68 {
|
||||
compatible = "dlg,da9210";
|
||||
reg = <0x68>;
|
||||
|
||||
interrupt-parent = <...>;
|
||||
interrupts = <...>;
|
||||
|
||||
regulator-min-microvolt = <300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <1600000>;
|
||||
regulator-max-microamp = <4600000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/dlg,da9210.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Dialog Semiconductor DA9210 Multi-Phase 12A DC-DC Buck Converter
|
||||
|
||||
maintainers:
|
||||
- Support Opensource <support.opensource@diasemi.com>
|
||||
|
||||
allOf:
|
||||
- $ref: regulator.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: dlg,da9210
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
regulator@68 {
|
||||
compatible = "dlg,da9210";
|
||||
reg = <0x68>;
|
||||
|
||||
interrupt-parent = <&irqc0>;
|
||||
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
regulator-min-microvolt = <300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <1600000>;
|
||||
regulator-max-microamp = <4600000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
@@ -100,6 +100,11 @@ properties:
|
||||
vin-supply:
|
||||
description: Input supply phandle.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description:
|
||||
Interrupt signaling a critical under-voltage event.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- regulator-name
|
||||
|
||||
@@ -43,6 +43,7 @@ properties:
|
||||
"^OUT[1-4]$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
||||
@@ -30,10 +30,12 @@ properties:
|
||||
"^LDO([1-9]|1[0-5])$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^BUCK|BUCKBOOST$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/mediatek,mt6358-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6358 Regulator
|
||||
|
||||
maintainers:
|
||||
- Zhiyong Tao <zhiyong.tao@mediatek.com>
|
||||
|
||||
description:
|
||||
Regulator node of the PMIC. This node should under the PMIC's device node.
|
||||
All voltage regulators provided by the PMIC are described as sub-nodes of
|
||||
this node.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: mediatek,mt6358-regulator
|
||||
- items:
|
||||
- const: mediatek,mt6366-regulator
|
||||
- const: mediatek,mt6358-regulator
|
||||
|
||||
vsys-ldo1-supply:
|
||||
description: Supply for LDOs vfe28, vxo22, vcn28, vaux18, vaud28, vsim1, vusb, vbif28
|
||||
vsys-ldo2-supply:
|
||||
description: Supply for LDOs vldo28 (MT6358 only), vio28, vmc, vmch, vsim2
|
||||
vsys-ldo3-supply:
|
||||
description: Supply for LDOs vcn33, vcama[12] (MT6358 only), vemc, vibr
|
||||
vsys-vcore-supply:
|
||||
description: Supply for buck regulator vcore
|
||||
vsys-vdram1-supply:
|
||||
description: Supply for buck regulator vdram1
|
||||
vsys-vgpu-supply:
|
||||
description: Supply for buck regulator vgpu
|
||||
vsys-vmodem-supply:
|
||||
description: Supply for buck regulator vmodem
|
||||
vsys-vpa-supply:
|
||||
description: Supply for buck regulator vpa
|
||||
vsys-vproc11-supply:
|
||||
description: Supply for buck regulator vproc11
|
||||
vsys-vproc12-supply:
|
||||
description: Supply for buck regulator vproc12
|
||||
vsys-vs1-supply:
|
||||
description: Supply for buck regulator vs1
|
||||
vsys-vs2-supply:
|
||||
description: Supply for buck regulator vs2
|
||||
vs1-ldo1-supply:
|
||||
description:
|
||||
Supply for LDOs vrf18, vefuse, vcn18, vcamio (MT6358 only), vio18, vm18 (MT6366 only)
|
||||
vs2-ldo1-supply:
|
||||
description: Supply for LDOs vdram2, vmddr (MT6366 only)
|
||||
vs2-ldo2-supply:
|
||||
description: Supply for LDOs vrf12, va12
|
||||
vs2-ldo3-supply:
|
||||
description:
|
||||
Supply for LDOs vsram-core (MT6366 only), vsram-gpu, vsram-others, vsram-proc11, vsram-proc12
|
||||
vs2-ldo4-supply:
|
||||
description: Supply for LDO vcamd
|
||||
|
||||
patternProperties:
|
||||
"^(buck_)?v(core|dram1|gpu|modem|pa|proc1[12]|s[12])$":
|
||||
description: Buck regulators
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Buck regulatpr operating modes allowed. Valid values below.
|
||||
Users should use the macros from dt-bindings/regulator/mediatek,mt6397-regulator.h
|
||||
0 (MT6397_BUCK_MODE_AUTO): Auto PFM/PWM mode
|
||||
1 (MT6397_BUCK_MODE_FORCE_PWM): Forced PWM mode
|
||||
items:
|
||||
enum: [0, 1]
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?v(a|rf)12$":
|
||||
description: LDOs with fixed 1.2V output and 0~100/10mV tuning
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?v((aux|cn|io|rf)18|camio)$":
|
||||
description:
|
||||
LDOs with fixed 1.8V output and 0~100/10mV tuning (vcn18 on MT6366 has variable output)
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?vxo22$":
|
||||
description: LDOs with fixed 2.2V output and 0~100/10mV tuning
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?v(aud|bif|cn|fe|io)28$":
|
||||
description: LDOs with fixed 2.8V output and 0~100/10mV tuning
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?vusb$":
|
||||
description: LDOs with fixed 3.0V output and 0~100/10mV tuning
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?vsram[_-](core|gpu|others|proc1[12])$":
|
||||
description: LDOs with variable output
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^(ldo_)?v(cama[12]|camd|cn33|dram2|efuse|emc|ibr|ldo28|m18|mc|mch|mddr|sim[12])$":
|
||||
description: LDOs with variable output and 0~100/10mV tuning
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
properties:
|
||||
regulator-allowed-modes: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6358-regulator
|
||||
then:
|
||||
patternProperties:
|
||||
# Old regulator node name scheme (with prefix and underscores) only
|
||||
# ([^y-] is used to avoid matching -supply
|
||||
"^(?<!buck_)(?<!ldo_)v.*[^y-](?!-supply)$": false
|
||||
"^ldo_vsram-": false
|
||||
# vsram_core regulator doesn't exist on MT6358
|
||||
"^ldo_vsram[-_]core$": false
|
||||
|
||||
properties:
|
||||
# vm18 and vmddr regulators don't exist on MT6358
|
||||
ldo_vm18: false
|
||||
ldo_vmddr: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: mediatek,mt6366-regulator
|
||||
then:
|
||||
patternProperties:
|
||||
# Prefer cleaned up regulator node names
|
||||
"^(buck|ldo)_": false
|
||||
# Don't allow underscores
|
||||
"^vsram_": false
|
||||
# vcam* regulators don't exist on MT6366
|
||||
"^vcam": false
|
||||
|
||||
properties:
|
||||
# vldo28 regulator doesn't exist on MT6366
|
||||
vldo28: false
|
||||
# vs2_ldo4 supply pin doesn't exist on MT6366
|
||||
vs2-ldo4-supply: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/regulator/mediatek,mt6397-regulator.h>
|
||||
|
||||
regulator {
|
||||
compatible = "mediatek,mt6358-regulator";
|
||||
|
||||
buck_vgpu {
|
||||
regulator-name = "vgpu";
|
||||
regulator-min-microvolt = <625000>;
|
||||
regulator-max-microvolt = <900000>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
|
||||
MT6397_BUCK_MODE_FORCE_PWM>;
|
||||
};
|
||||
|
||||
ldo_vsram_gpu {
|
||||
regulator-name = "vsram_gpu";
|
||||
regulator-min-microvolt = <850000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/regulator/mediatek,mt6397-regulator.h>
|
||||
|
||||
regulator {
|
||||
compatible = "mediatek,mt6366-regulator", "mediatek,mt6358-regulator";
|
||||
|
||||
vdram1 {
|
||||
regulator-name = "pp1125_emi_vdd2";
|
||||
regulator-min-microvolt = <1125000>;
|
||||
regulator-max-microvolt = <1125000>;
|
||||
regulator-ramp-delay = <12500>;
|
||||
regulator-enable-ramp-delay = <0>;
|
||||
regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
|
||||
MT6397_BUCK_MODE_FORCE_PWM>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vproc11 {
|
||||
regulator-name = "ppvar_dvdd_proc_bc_mt6366";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
|
||||
MT6397_BUCK_MODE_FORCE_PWM>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vmddr {
|
||||
regulator-name = "pm0750_emi_vmddr";
|
||||
regulator-min-microvolt = <700000>;
|
||||
regulator-max-microvolt = <750000>;
|
||||
regulator-enable-ramp-delay = <325>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vsram-proc11 {
|
||||
regulator-name = "pp0900_dvdd_sram_bc";
|
||||
regulator-min-microvolt = <850000>;
|
||||
regulator-max-microvolt = <1120000>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -1,350 +0,0 @@
|
||||
MediaTek MT6358 Regulator
|
||||
|
||||
All voltage regulators provided by the MT6358 PMIC are described as the
|
||||
subnodes of the MT6358 regulators node. Each regulator is named according
|
||||
to its regulator type, buck_<name> and ldo_<name>. The definition for each
|
||||
of these nodes is defined using the standard binding for regulators at
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
|
||||
The valid names for regulators are::
|
||||
BUCK:
|
||||
buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu,
|
||||
buck_vs2, buck_vmodem, buck_vs1
|
||||
LDO:
|
||||
ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio,
|
||||
ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others,
|
||||
ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28,
|
||||
ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18,
|
||||
ldo_vcn33, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28, ldo_vsim2
|
||||
|
||||
Example:
|
||||
|
||||
pmic {
|
||||
compatible = "mediatek,mt6358";
|
||||
|
||||
mt6358regulator: mt6358regulator {
|
||||
compatible = "mediatek,mt6358-regulator";
|
||||
|
||||
mt6358_vdram1_reg: buck_vdram1 {
|
||||
regulator-compatible = "buck_vdram1";
|
||||
regulator-name = "vdram1";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <2087500>;
|
||||
regulator-ramp-delay = <12500>;
|
||||
regulator-enable-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vcore_reg: buck_vcore {
|
||||
regulator-name = "vcore";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vpa_reg: buck_vpa {
|
||||
regulator-name = "vpa";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <3650000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
regulator-enable-ramp-delay = <250>;
|
||||
};
|
||||
|
||||
mt6358_vproc11_reg: buck_vproc11 {
|
||||
regulator-name = "vproc11";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vproc12_reg: buck_vproc12 {
|
||||
regulator-name = "vproc12";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vgpu_reg: buck_vgpu {
|
||||
regulator-name = "vgpu";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <200>;
|
||||
};
|
||||
|
||||
mt6358_vs2_reg: buck_vs2 {
|
||||
regulator-name = "vs2";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <2087500>;
|
||||
regulator-ramp-delay = <12500>;
|
||||
regulator-enable-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vmodem_reg: buck_vmodem {
|
||||
regulator-name = "vmodem";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <900>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vs1_reg: buck_vs1 {
|
||||
regulator-name = "vs1";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <2587500>;
|
||||
regulator-ramp-delay = <12500>;
|
||||
regulator-enable-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vdram2_reg: ldo_vdram2 {
|
||||
regulator-name = "vdram2";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <3300>;
|
||||
};
|
||||
|
||||
mt6358_vsim1_reg: ldo_vsim1 {
|
||||
regulator-name = "vsim1";
|
||||
regulator-min-microvolt = <1700000>;
|
||||
regulator-max-microvolt = <3100000>;
|
||||
regulator-enable-ramp-delay = <540>;
|
||||
};
|
||||
|
||||
mt6358_vibr_reg: ldo_vibr {
|
||||
regulator-name = "vibr";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-enable-ramp-delay = <60>;
|
||||
};
|
||||
|
||||
mt6358_vrf12_reg: ldo_vrf12 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vrf12";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-enable-ramp-delay = <120>;
|
||||
};
|
||||
|
||||
mt6358_vio18_reg: ldo_vio18 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vio18";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <2700>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vusb_reg: ldo_vusb {
|
||||
regulator-name = "vusb";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3100000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vcamio_reg: ldo_vcamio {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcamio";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vcamd_reg: ldo_vcamd {
|
||||
regulator-name = "vcamd";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vcn18_reg: ldo_vcn18 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcn18";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vfe28_reg: ldo_vfe28 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vfe28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vsram_proc11_reg: ldo_vsram_proc11 {
|
||||
regulator-name = "vsram_proc11";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vcn28_reg: ldo_vcn28 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcn28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vsram_others_reg: ldo_vsram_others {
|
||||
regulator-name = "vsram_others";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vsram_gpu_reg: ldo_vsram_gpu {
|
||||
regulator-name = "vsram_gpu";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
};
|
||||
|
||||
mt6358_vxo22_reg: ldo_vxo22 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vxo22";
|
||||
regulator-min-microvolt = <2200000>;
|
||||
regulator-max-microvolt = <2200000>;
|
||||
regulator-enable-ramp-delay = <120>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vefuse_reg: ldo_vefuse {
|
||||
regulator-name = "vefuse";
|
||||
regulator-min-microvolt = <1700000>;
|
||||
regulator-max-microvolt = <1900000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vaux18_reg: ldo_vaux18 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vaux18";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vmch_reg: ldo_vmch {
|
||||
regulator-name = "vmch";
|
||||
regulator-min-microvolt = <2900000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-enable-ramp-delay = <60>;
|
||||
};
|
||||
|
||||
mt6358_vbif28_reg: ldo_vbif28 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbif28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vsram_proc12_reg: ldo_vsram_proc12 {
|
||||
regulator-name = "vsram_proc12";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1293750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vcama1_reg: ldo_vcama1 {
|
||||
regulator-name = "vcama1";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vemc_reg: ldo_vemc {
|
||||
regulator-name = "vemc";
|
||||
regulator-min-microvolt = <2900000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-enable-ramp-delay = <60>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vio28_reg: ldo_vio28 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vio28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_va12_reg: ldo_va12 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "va12";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mt6358_vrf18_reg: ldo_vrf18 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vrf18";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-enable-ramp-delay = <120>;
|
||||
};
|
||||
|
||||
mt6358_vcn33_reg: ldo_vcn33 {
|
||||
regulator-name = "vcn33";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3500000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vcama2_reg: ldo_vcama2 {
|
||||
regulator-name = "vcama2";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vmc_reg: ldo_vmc {
|
||||
regulator-name = "vmc";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-enable-ramp-delay = <60>;
|
||||
};
|
||||
|
||||
mt6358_vldo28_reg: ldo_vldo28 {
|
||||
regulator-name = "vldo28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vaud28_reg: ldo_vaud28 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vaud28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-enable-ramp-delay = <270>;
|
||||
};
|
||||
|
||||
mt6358_vsim2_reg: ldo_vsim2 {
|
||||
regulator-name = "vsim2";
|
||||
regulator-min-microvolt = <1700000>;
|
||||
regulator-max-microvolt = <3100000>;
|
||||
regulator-enable-ramp-delay = <540>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -48,10 +48,12 @@ properties:
|
||||
"^LDO[1-4]$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^BUCK|BOOST$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ description: |
|
||||
For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2
|
||||
For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
|
||||
For PMI8998, bob
|
||||
For PMC8380, smps1 - smps8, ldo1 - lodo3
|
||||
For PMR735A, smps1 - smps3, ldo1 - ldo7
|
||||
For PMX55, smps1 - smps7, ldo1 - ldo16
|
||||
For PMX65, smps1 - smps8, ldo1 - ldo21
|
||||
@@ -78,6 +79,7 @@ properties:
|
||||
- qcom,pm8998-rpmh-regulators
|
||||
- qcom,pmc8180-rpmh-regulators
|
||||
- qcom,pmc8180c-rpmh-regulators
|
||||
- qcom,pmc8380-rpmh-regulators
|
||||
- qcom,pmg1110-rpmh-regulators
|
||||
- qcom,pmi8998-rpmh-regulators
|
||||
- qcom,pmm8155au-rpmh-regulators
|
||||
@@ -364,6 +366,16 @@ allOf:
|
||||
patternProperties:
|
||||
"^vdd-s([1-9]|1[0-3])-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pmc8380-rpmh-regulators
|
||||
then:
|
||||
patternProperties:
|
||||
"^vdd-l[1-3]-supply$": true
|
||||
"^vdd-s[1-8]-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -17,12 +17,15 @@ properties:
|
||||
- qcom,pm660l-regulators
|
||||
- qcom,pm8004-regulators
|
||||
- qcom,pm8005-regulators
|
||||
- qcom,pm8019-regulators
|
||||
- qcom,pm8226-regulators
|
||||
- qcom,pm8841-regulators
|
||||
- qcom,pm8909-regulators
|
||||
- qcom,pm8916-regulators
|
||||
- qcom,pm8941-regulators
|
||||
- qcom,pm8950-regulators
|
||||
- qcom,pm8994-regulators
|
||||
- qcom,pma8084-regulators
|
||||
- qcom,pmi8994-regulators
|
||||
- qcom,pmp8074-regulators
|
||||
- qcom,pms405-regulators
|
||||
@@ -32,7 +35,7 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
patternProperties:
|
||||
"^(5vs[1-2]|(l|s)[1-9][0-9]?|lvs[1-3])$":
|
||||
"^(5vs[1-2]|(l|s)[1-9][0-9]?|lvs[1-4])$":
|
||||
description: List of regulators and its properties
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
@@ -176,6 +179,25 @@ allOf:
|
||||
patternProperties:
|
||||
"^vdd_s[1-4]-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pm8019-regulators
|
||||
then:
|
||||
properties:
|
||||
vdd_l1-supply: true
|
||||
vdd_l2_l3-supply: true
|
||||
vdd_l4_l5_l6-supply: true
|
||||
vdd_l7_l8_l11-supply: true
|
||||
vdd_l9-supply: true
|
||||
vdd_l10-supply: true
|
||||
vdd_l12-supply: true
|
||||
vdd_l13_l14-supply: true
|
||||
patternProperties:
|
||||
"^vdd_s[1-4]-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@@ -206,6 +228,24 @@ allOf:
|
||||
patternProperties:
|
||||
"^vdd_s[1-8]-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pm8909-regulators
|
||||
then:
|
||||
properties:
|
||||
vdd_s1-supply: true
|
||||
vdd_s2-supply: true
|
||||
vdd_l1-supply: true
|
||||
vdd_l2_l5-supply: true
|
||||
vdd_l3_l6_l10-supply: true
|
||||
vdd_l4_l7-supply: true
|
||||
vdd_l8_l11_l15_l18-supply: true
|
||||
vdd_l9_l12_l14_l17-supply: true
|
||||
vdd_l13-supply: true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@@ -295,6 +335,32 @@ allOf:
|
||||
patternProperties:
|
||||
"^vdd_s[1-9][0-2]?-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pma8084-regulators
|
||||
then:
|
||||
properties:
|
||||
vdd_l1_l11-supply: true
|
||||
vdd_l2_l3_l4_l27-supply: true
|
||||
vdd_l5_l7-supply: true
|
||||
vdd_l6_l12_l14_l15_l26-supply: true
|
||||
vdd_l8-supply: true
|
||||
vdd_l9_l10_l13_l20_l23_l24-supply: true
|
||||
vdd_l16_l25-supply: true
|
||||
vdd_l17-supply: true
|
||||
vdd_l18-supply: true
|
||||
vdd_l19-supply: true
|
||||
vdd_l21-supply: true
|
||||
vdd_l22-supply: true
|
||||
vdd_lvs1_2-supply: true
|
||||
vdd_lvs3_4-supply: true
|
||||
vdd_5vs1-supply: true
|
||||
patternProperties:
|
||||
"^vdd_s([1-9]|1[0-2])-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -46,6 +46,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
|
||||
@@ -68,6 +68,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/arm,pl022-peripheral-props.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Peripheral-specific properties for Arm PL022 SPI controller
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
select: false
|
||||
|
||||
properties:
|
||||
pl022,interface:
|
||||
description: SPI interface type
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # SPI
|
||||
- 1 # Texas Instruments Synchronous Serial Frame Format
|
||||
- 2 # Microwire (Half Duplex)
|
||||
|
||||
pl022,com-mode:
|
||||
description: Specifies the transfer mode
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # interrupt mode
|
||||
- 1 # polling mode
|
||||
- 2 # DMA mode
|
||||
default: 1
|
||||
|
||||
pl022,rx-level-trig:
|
||||
description: Rx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,tx-level-trig:
|
||||
description: Tx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,ctrl-len:
|
||||
description: Microwire interface - Control length
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0x03
|
||||
maximum: 0x1f
|
||||
|
||||
pl022,wait-state:
|
||||
description: Microwire interface - Wait state
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
pl022,duplex:
|
||||
description: Microwire interface - Full/Half duplex
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
additionalProperties: true
|
||||
...
|
||||
@@ -50,6 +50,7 @@ properties:
|
||||
patternProperties:
|
||||
"@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
spi-rx-bus-width:
|
||||
|
||||
@@ -44,9 +44,17 @@ properties:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
interconnects:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
operating-points-v2: true
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -62,7 +70,9 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8996.h>
|
||||
#include <dt-bindings/interconnect/qcom,msm8996.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
spi@7575000 {
|
||||
compatible = "qcom,spi-qup-v2.2.1";
|
||||
@@ -76,6 +86,9 @@ examples:
|
||||
pinctrl-1 = <&blsp1_spi1_sleep>;
|
||||
dmas = <&blsp1_dma 12>, <&blsp1_dma 13>;
|
||||
dma-names = "tx", "rx";
|
||||
power-domains = <&rpmpd MSM8996_VDDCX>;
|
||||
operating-points-v2 = <&spi_opp_table>;
|
||||
interconnects = <&pnoc MASTER_BLSP_1 &bimc SLAVE_EBI_CH0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
@@ -39,6 +39,12 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
renesas,csi-no-ss:
|
||||
type: boolean
|
||||
description:
|
||||
The CSI Slave Selection (SS) pin won't be used to enable transmission and
|
||||
reception. Only available when in target mode.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -50,6 +56,9 @@ required:
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
dependencies:
|
||||
renesas,csi-no-ss: [ spi-slave ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
||||
@@ -47,6 +47,8 @@ properties:
|
||||
patternProperties:
|
||||
"^flash@[0-3]$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
|
||||
@@ -160,6 +160,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
|
||||
@@ -113,8 +113,14 @@ properties:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
|
||||
st,spi-midi-ns:
|
||||
description: |
|
||||
Only for STM32H7, (Master Inter-Data Idleness) minimum time
|
||||
delay in nanoseconds inserted between two consecutive data frames.
|
||||
|
||||
# The controller specific properties go here.
|
||||
allOf:
|
||||
- $ref: arm,pl022-peripheral-props.yaml#
|
||||
- $ref: cdns,qspi-nor-peripheral-props.yaml#
|
||||
- $ref: samsung,spi-peripheral-props.yaml#
|
||||
- $ref: nvidia,tegra210-quad-peripheral-props.yaml#
|
||||
|
||||
@@ -74,57 +74,6 @@ properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
|
||||
type: object
|
||||
# SPI slave nodes must be children of the SPI master node and can
|
||||
# contain the following properties.
|
||||
properties:
|
||||
pl022,interface:
|
||||
description: SPI interface type
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # SPI
|
||||
- 1 # Texas Instruments Synchronous Serial Frame Format
|
||||
- 2 # Microwire (Half Duplex)
|
||||
|
||||
pl022,com-mode:
|
||||
description: Specifies the transfer mode
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 0 # interrupt mode
|
||||
- 1 # polling mode
|
||||
- 2 # DMA mode
|
||||
default: 1
|
||||
|
||||
pl022,rx-level-trig:
|
||||
description: Rx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,tx-level-trig:
|
||||
description: Tx FIFO watermark level
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
|
||||
pl022,ctrl-len:
|
||||
description: Microwire interface - Control length
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0x03
|
||||
maximum: 0x1f
|
||||
|
||||
pl022,wait-state:
|
||||
description: Microwire interface - Wait state
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
pl022,duplex:
|
||||
description: Microwire interface - Full/Half duplex
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -18,15 +18,6 @@ maintainers:
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: st,stm32f4-spi
|
||||
|
||||
then:
|
||||
properties:
|
||||
st,spi-midi-ns: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -59,17 +50,6 @@ properties:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
patternProperties:
|
||||
"^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
|
||||
type: object
|
||||
# SPI slave nodes must be children of the SPI master node and can
|
||||
# contain the following properties.
|
||||
properties:
|
||||
st,spi-midi-ns:
|
||||
description: |
|
||||
Only for STM32H7, (Master Inter-Data Idleness) minimum time
|
||||
delay in nanoseconds inserted between two consecutive data frames.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -29,6 +29,10 @@ warnings. These stubs are used for two use cases:
|
||||
will use it under other compile-time configurations. In this case the
|
||||
consumer must make sure not to call into these functions, or the user will
|
||||
be met with console warnings that may be perceived as intimidating.
|
||||
Combining truly optional GPIOLIB usage with calls to
|
||||
``[devm_]gpiod_get_optional()`` is a *bad idea*, and will result in weird
|
||||
error messages. Use the ordinary getter functions with optional GPIOLIB:
|
||||
some open coding of error handling should be expected when you do this.
|
||||
|
||||
All the functions that work with the descriptor-based GPIO interface are
|
||||
prefixed with ``gpiod_``. The ``gpio_`` prefix is used for the legacy
|
||||
|
||||
@@ -64,6 +64,49 @@ If the driver needs to perform more complex initialization like getting and
|
||||
configuring GPIOs it can get its ACPI handle and extract this information
|
||||
from ACPI tables.
|
||||
|
||||
ACPI device objects
|
||||
===================
|
||||
|
||||
Generally speaking, there are two categories of devices in a system in which
|
||||
ACPI is used as an interface between the platform firmware and the OS: Devices
|
||||
that can be discovered and enumerated natively, through a protocol defined for
|
||||
the specific bus that they are on (for example, configuration space in PCI),
|
||||
without the platform firmware assistance, and devices that need to be described
|
||||
by the platform firmware so that they can be discovered. Still, for any device
|
||||
known to the platform firmware, regardless of which category it falls into,
|
||||
there can be a corresponding ACPI device object in the ACPI Namespace in which
|
||||
case the Linux kernel will create a struct acpi_device object based on it for
|
||||
that device.
|
||||
|
||||
Those struct acpi_device objects are never used for binding drivers to natively
|
||||
discoverable devices, because they are represented by other types of device
|
||||
objects (for example, struct pci_dev for PCI devices) that are bound to by
|
||||
device drivers (the corresponding struct acpi_device object is then used as
|
||||
an additional source of information on the configuration of the given device).
|
||||
Moreover, the core ACPI device enumeration code creates struct platform_device
|
||||
objects for the majority of devices that are discovered and enumerated with the
|
||||
help of the platform firmware and those platform device objects can be bound to
|
||||
by platform drivers in direct analogy with the natively enumerable devices
|
||||
case. Therefore it is logically inconsistent and so generally invalid to bind
|
||||
drivers to struct acpi_device objects, including drivers for devices that are
|
||||
discovered with the help of the platform firmware.
|
||||
|
||||
Historically, ACPI drivers that bound directly to struct acpi_device objects
|
||||
were implemented for some devices enumerated with the help of the platform
|
||||
firmware, but this is not recommended for any new drivers. As explained above,
|
||||
platform device objects are created for those devices as a rule (with a few
|
||||
exceptions that are not relevant here) and so platform drivers should be used
|
||||
for handling them, even though the corresponding ACPI device objects are the
|
||||
only source of device configuration information in that case.
|
||||
|
||||
For every device having a corresponding struct acpi_device object, the pointer
|
||||
to it is returned by the ACPI_COMPANION() macro, so it is always possible to
|
||||
get to the device configuration information stored in the ACPI device object
|
||||
this way. Accordingly, struct acpi_device can be regarded as a part of the
|
||||
interface between the kernel and the ACPI Namespace, whereas device objects of
|
||||
other types (for example, struct pci_dev or struct platform_device) are used
|
||||
for interacting with the rest of the system.
|
||||
|
||||
DMA support
|
||||
===========
|
||||
|
||||
|
||||
+1
-1
@@ -2224,7 +2224,7 @@ M: Imre Kaloz <kaloz@openwrt.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
|
||||
F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
|
||||
F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
|
||||
F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion*
|
||||
F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
|
||||
|
||||
@@ -561,22 +561,6 @@ static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
|
||||
&ams_delta_nand_gpio_table,
|
||||
};
|
||||
|
||||
/*
|
||||
* Some drivers may not use GPIO lookup tables but need to be provided
|
||||
* with GPIO numbers. The same applies to GPIO based IRQ lines - some
|
||||
* drivers may even not use GPIO layer but expect just IRQ numbers.
|
||||
* We could either define GPIO lookup tables then use them on behalf
|
||||
* of those devices, or we can use GPIO driver level methods for
|
||||
* identification of GPIO and IRQ numbers. For the purpose of the latter,
|
||||
* defina a helper function which identifies GPIO chips by their labels.
|
||||
*/
|
||||
static int gpiochip_match_by_label(struct gpio_chip *chip, void *data)
|
||||
{
|
||||
char *label = data;
|
||||
|
||||
return !strcmp(label, chip->label);
|
||||
}
|
||||
|
||||
static struct gpiod_hog ams_delta_gpio_hogs[] = {
|
||||
GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
|
||||
GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
|
||||
@@ -616,14 +600,28 @@ static void __init modem_assign_irq(struct gpio_chip *chip)
|
||||
*/
|
||||
static void __init omap_gpio_deps_init(void)
|
||||
{
|
||||
struct gpio_device *gdev;
|
||||
struct gpio_chip *chip;
|
||||
|
||||
chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
|
||||
if (!chip) {
|
||||
pr_err("%s: OMAP GPIO chip not found\n", __func__);
|
||||
/*
|
||||
* Some drivers may not use GPIO lookup tables but need to be provided
|
||||
* with GPIO numbers. The same applies to GPIO based IRQ lines - some
|
||||
* drivers may even not use GPIO layer but expect just IRQ numbers.
|
||||
* We could either define GPIO lookup tables then use them on behalf
|
||||
* of those devices, or we can use GPIO driver level methods for
|
||||
* identification of GPIO and IRQ numbers.
|
||||
*
|
||||
* This reference will be leaked but that's alright as this device
|
||||
* never goes down.
|
||||
*/
|
||||
gdev = gpio_device_find_by_label(OMAP_GPIO_LABEL);
|
||||
if (!gdev) {
|
||||
pr_err("%s: OMAP GPIO device not found\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
chip = gpio_device_get_chip(gdev);
|
||||
|
||||
/*
|
||||
* Start with FIQ initialization as it may have to request
|
||||
* and release successfully each OMAP GPIO pin in turn.
|
||||
|
||||
@@ -51,11 +51,6 @@
|
||||
#define PALMTE_HDQ_GPIO 11
|
||||
#define PALMTE_HEADPHONES_GPIO 14
|
||||
#define PALMTE_SPEAKER_GPIO 15
|
||||
#define PALMTE_DC_GPIO OMAP_MPUIO(2)
|
||||
#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4)
|
||||
#define PALMTE_MMC1_GPIO OMAP_MPUIO(6)
|
||||
#define PALMTE_MMC2_GPIO OMAP_MPUIO(7)
|
||||
#define PALMTE_MMC3_GPIO OMAP_MPUIO(11)
|
||||
|
||||
static const unsigned int palmte_keymap[] = {
|
||||
KEY(0, 0, KEY_F1), /* Calendar */
|
||||
|
||||
+41
-57
@@ -17,6 +17,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/string_choices.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/battery.h>
|
||||
|
||||
@@ -32,8 +33,9 @@ MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int acpi_ac_add(struct acpi_device *device);
|
||||
static void acpi_ac_remove(struct acpi_device *device);
|
||||
static int acpi_ac_probe(struct platform_device *pdev);
|
||||
static void acpi_ac_remove(struct platform_device *pdev);
|
||||
|
||||
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data);
|
||||
|
||||
static const struct acpi_device_id ac_device_ids[] = {
|
||||
@@ -50,17 +52,6 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
|
||||
static int ac_sleep_before_get_state_ms;
|
||||
static int ac_only;
|
||||
|
||||
static struct acpi_driver acpi_ac_driver = {
|
||||
.name = "ac",
|
||||
.class = ACPI_AC_CLASS,
|
||||
.ids = ac_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_ac_add,
|
||||
.remove = acpi_ac_remove,
|
||||
},
|
||||
.drv.pm = &acpi_ac_pm,
|
||||
};
|
||||
|
||||
struct acpi_ac {
|
||||
struct power_supply *charger;
|
||||
struct power_supply_desc charger_desc;
|
||||
@@ -128,15 +119,12 @@ static enum power_supply_property ac_props[] = {
|
||||
/* Driver Model */
|
||||
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_device *device = data;
|
||||
struct acpi_ac *ac = acpi_driver_data(device);
|
||||
|
||||
if (!ac)
|
||||
return;
|
||||
struct acpi_ac *ac = data;
|
||||
struct acpi_device *adev = ac->device;
|
||||
|
||||
switch (event) {
|
||||
default:
|
||||
acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
|
||||
acpi_handle_debug(adev->handle, "Unsupported event [0x%x]\n",
|
||||
event);
|
||||
fallthrough;
|
||||
case ACPI_AC_NOTIFY_STATUS:
|
||||
@@ -153,10 +141,10 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
|
||||
msleep(ac_sleep_before_get_state_ms);
|
||||
|
||||
acpi_ac_get_state(ac);
|
||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||
dev_name(&device->dev), event,
|
||||
acpi_bus_generate_netlink_event(adev->pnp.device_class,
|
||||
dev_name(&adev->dev), event,
|
||||
(u32) ac->state);
|
||||
acpi_notifier_call_chain(device, event, (u32) ac->state);
|
||||
acpi_notifier_call_chain(adev, event, (u32) ac->state);
|
||||
kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
|
||||
}
|
||||
}
|
||||
@@ -213,24 +201,22 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = {
|
||||
{},
|
||||
};
|
||||
|
||||
static int acpi_ac_add(struct acpi_device *device)
|
||||
static int acpi_ac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
|
||||
struct power_supply_config psy_cfg = {};
|
||||
int result = 0;
|
||||
struct acpi_ac *ac = NULL;
|
||||
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
struct acpi_ac *ac;
|
||||
int result;
|
||||
|
||||
ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
|
||||
if (!ac)
|
||||
return -ENOMEM;
|
||||
|
||||
ac->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_AC_CLASS);
|
||||
device->driver_data = ac;
|
||||
ac->device = adev;
|
||||
strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
|
||||
|
||||
platform_set_drvdata(pdev, ac);
|
||||
|
||||
result = acpi_ac_get_state(ac);
|
||||
if (result)
|
||||
@@ -238,26 +224,26 @@ static int acpi_ac_add(struct acpi_device *device)
|
||||
|
||||
psy_cfg.drv_data = ac;
|
||||
|
||||
ac->charger_desc.name = acpi_device_bid(device);
|
||||
ac->charger_desc.name = acpi_device_bid(adev);
|
||||
ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS;
|
||||
ac->charger_desc.properties = ac_props;
|
||||
ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
|
||||
ac->charger_desc.get_property = get_ac_property;
|
||||
ac->charger = power_supply_register(&ac->device->dev,
|
||||
ac->charger = power_supply_register(&pdev->dev,
|
||||
&ac->charger_desc, &psy_cfg);
|
||||
if (IS_ERR(ac->charger)) {
|
||||
result = PTR_ERR(ac->charger);
|
||||
goto err_release_ac;
|
||||
}
|
||||
|
||||
pr_info("%s [%s] (%s)\n", acpi_device_name(device),
|
||||
acpi_device_bid(device), ac->state ? "on-line" : "off-line");
|
||||
pr_info("%s [%s] (%s-line)\n", acpi_device_name(adev),
|
||||
acpi_device_bid(adev), str_on_off(ac->state));
|
||||
|
||||
ac->battery_nb.notifier_call = acpi_ac_battery_notify;
|
||||
register_acpi_notifier(&ac->battery_nb);
|
||||
|
||||
result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
|
||||
acpi_ac_notify);
|
||||
result = acpi_dev_install_notify_handler(adev, ACPI_ALL_NOTIFY,
|
||||
acpi_ac_notify, ac);
|
||||
if (result)
|
||||
goto err_unregister;
|
||||
|
||||
@@ -275,16 +261,9 @@ err_release_ac:
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int acpi_ac_resume(struct device *dev)
|
||||
{
|
||||
struct acpi_ac *ac;
|
||||
struct acpi_ac *ac = dev_get_drvdata(dev);
|
||||
unsigned int old_state;
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
ac = acpi_driver_data(to_acpi_device(dev));
|
||||
if (!ac)
|
||||
return -EINVAL;
|
||||
|
||||
old_state = ac->state;
|
||||
if (acpi_ac_get_state(ac))
|
||||
return 0;
|
||||
@@ -297,16 +276,11 @@ static int acpi_ac_resume(struct device *dev)
|
||||
#define acpi_ac_resume NULL
|
||||
#endif
|
||||
|
||||
static void acpi_ac_remove(struct acpi_device *device)
|
||||
static void acpi_ac_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_ac *ac = NULL;
|
||||
struct acpi_ac *ac = platform_get_drvdata(pdev);
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return;
|
||||
|
||||
ac = acpi_driver_data(device);
|
||||
|
||||
acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY,
|
||||
acpi_dev_remove_notify_handler(ac->device, ACPI_ALL_NOTIFY,
|
||||
acpi_ac_notify);
|
||||
power_supply_unregister(ac->charger);
|
||||
unregister_acpi_notifier(&ac->battery_nb);
|
||||
@@ -314,6 +288,16 @@ static void acpi_ac_remove(struct acpi_device *device)
|
||||
kfree(ac);
|
||||
}
|
||||
|
||||
static struct platform_driver acpi_ac_driver = {
|
||||
.probe = acpi_ac_probe,
|
||||
.remove_new = acpi_ac_remove,
|
||||
.driver = {
|
||||
.name = "ac",
|
||||
.acpi_match_table = ac_device_ids,
|
||||
.pm = &acpi_ac_pm,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init acpi_ac_init(void)
|
||||
{
|
||||
int result;
|
||||
@@ -326,7 +310,7 @@ static int __init acpi_ac_init(void)
|
||||
|
||||
dmi_check_system(ac_dmi_table);
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_ac_driver);
|
||||
result = platform_driver_register(&acpi_ac_driver);
|
||||
if (result < 0)
|
||||
return -ENODEV;
|
||||
|
||||
@@ -335,7 +319,7 @@ static int __init acpi_ac_init(void)
|
||||
|
||||
static void __exit acpi_ac_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&acpi_ac_driver);
|
||||
platform_driver_unregister(&acpi_ac_driver);
|
||||
}
|
||||
module_init(acpi_ac_init);
|
||||
module_exit(acpi_ac_exit);
|
||||
|
||||
@@ -194,12 +194,19 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
||||
record_header = (void *)subtable_header + offset;
|
||||
offset += record_header->length;
|
||||
|
||||
if (!record_header->length) {
|
||||
pr_err(FW_BUG "Zero-length record found in FPTD.\n");
|
||||
result = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (record_header->type) {
|
||||
case RECORD_S3_RESUME:
|
||||
if (subtable_type != SUBTABLE_S3PT) {
|
||||
pr_err(FW_BUG "Invalid record %d for subtable %s\n",
|
||||
record_header->type, signature);
|
||||
return -EINVAL;
|
||||
result = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (record_resume) {
|
||||
pr_err("Duplicate resume performance record found.\n");
|
||||
@@ -208,7 +215,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
||||
record_resume = (struct resume_performance_record *)record_header;
|
||||
result = sysfs_create_group(fpdt_kobj, &resume_attr_group);
|
||||
if (result)
|
||||
return result;
|
||||
goto err;
|
||||
break;
|
||||
case RECORD_S3_SUSPEND:
|
||||
if (subtable_type != SUBTABLE_S3PT) {
|
||||
@@ -223,13 +230,14 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
||||
record_suspend = (struct suspend_performance_record *)record_header;
|
||||
result = sysfs_create_group(fpdt_kobj, &suspend_attr_group);
|
||||
if (result)
|
||||
return result;
|
||||
goto err;
|
||||
break;
|
||||
case RECORD_BOOT:
|
||||
if (subtable_type != SUBTABLE_FBPT) {
|
||||
pr_err(FW_BUG "Invalid %d for subtable %s\n",
|
||||
record_header->type, signature);
|
||||
return -EINVAL;
|
||||
result = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (record_boot) {
|
||||
pr_err("Duplicate boot performance record found.\n");
|
||||
@@ -238,7 +246,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
||||
record_boot = (struct boot_performance_record *)record_header;
|
||||
result = sysfs_create_group(fpdt_kobj, &boot_attr_group);
|
||||
if (result)
|
||||
return result;
|
||||
goto err;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -247,6 +255,18 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (record_boot)
|
||||
sysfs_remove_group(fpdt_kobj, &boot_attr_group);
|
||||
|
||||
if (record_suspend)
|
||||
sysfs_remove_group(fpdt_kobj, &suspend_attr_group);
|
||||
|
||||
if (record_resume)
|
||||
sysfs_remove_group(fpdt_kobj, &resume_attr_group);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int __init acpi_init_fpdt(void)
|
||||
@@ -255,6 +275,7 @@ static int __init acpi_init_fpdt(void)
|
||||
struct acpi_table_header *header;
|
||||
struct fpdt_subtable_entry *subtable;
|
||||
u32 offset = sizeof(*header);
|
||||
int result;
|
||||
|
||||
status = acpi_get_table(ACPI_SIG_FPDT, 0, &header);
|
||||
|
||||
@@ -263,8 +284,8 @@ static int __init acpi_init_fpdt(void)
|
||||
|
||||
fpdt_kobj = kobject_create_and_add("fpdt", acpi_kobj);
|
||||
if (!fpdt_kobj) {
|
||||
acpi_put_table(header);
|
||||
return -ENOMEM;
|
||||
result = -ENOMEM;
|
||||
goto err_nomem;
|
||||
}
|
||||
|
||||
while (offset < header->length) {
|
||||
@@ -272,8 +293,10 @@ static int __init acpi_init_fpdt(void)
|
||||
switch (subtable->type) {
|
||||
case SUBTABLE_FBPT:
|
||||
case SUBTABLE_S3PT:
|
||||
fpdt_process_subtable(subtable->address,
|
||||
result = fpdt_process_subtable(subtable->address,
|
||||
subtable->type);
|
||||
if (result)
|
||||
goto err_subtable;
|
||||
break;
|
||||
default:
|
||||
/* Other types are reserved in ACPI 6.4 spec. */
|
||||
@@ -282,6 +305,12 @@ static int __init acpi_init_fpdt(void)
|
||||
offset += sizeof(*subtable);
|
||||
}
|
||||
return 0;
|
||||
err_subtable:
|
||||
kobject_put(fpdt_kobj);
|
||||
|
||||
err_nomem:
|
||||
acpi_put_table(header);
|
||||
return result;
|
||||
}
|
||||
|
||||
fs_initcall(acpi_init_fpdt);
|
||||
|
||||
+10
-11
@@ -368,7 +368,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
||||
{ "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) },
|
||||
{ "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) },
|
||||
{ "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) },
|
||||
{ "INT33C7", },
|
||||
|
||||
/* BayTrail LPSS devices */
|
||||
{ "80860F09", LPSS_ADDR(byt_pwm_dev_desc) },
|
||||
@@ -376,8 +375,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
||||
{ "80860F0E", LPSS_ADDR(byt_spi_dev_desc) },
|
||||
{ "80860F14", LPSS_ADDR(byt_sdio_dev_desc) },
|
||||
{ "80860F41", LPSS_ADDR(byt_i2c_dev_desc) },
|
||||
{ "INT33B2", },
|
||||
{ "INT33FC", },
|
||||
|
||||
/* Braswell LPSS devices */
|
||||
{ "80862286", LPSS_ADDR(lpss_dma_desc) },
|
||||
@@ -396,7 +393,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
||||
{ "INT3434", LPSS_ADDR(lpt_uart_dev_desc) },
|
||||
{ "INT3435", LPSS_ADDR(lpt_uart_dev_desc) },
|
||||
{ "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
|
||||
{ "INT3437", },
|
||||
|
||||
/* Wildcat Point LPSS devices */
|
||||
{ "INT3438", LPSS_ADDR(lpt_spi_dev_desc) },
|
||||
@@ -578,6 +574,7 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
|
||||
{
|
||||
struct acpi_handle_list dep_devices;
|
||||
acpi_status status;
|
||||
bool ret = false;
|
||||
int i;
|
||||
|
||||
if (!acpi_has_method(adev->handle, "_DEP"))
|
||||
@@ -591,11 +588,14 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
|
||||
}
|
||||
|
||||
for (i = 0; i < dep_devices.count; i++) {
|
||||
if (dep_devices.handles[i] == handle)
|
||||
return true;
|
||||
if (dep_devices.handles[i] == handle) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
acpi_handle_list_free(&dep_devices);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void acpi_lpss_link_consumer(struct device *dev1,
|
||||
@@ -657,10 +657,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
|
||||
int ret;
|
||||
|
||||
dev_desc = (const struct lpss_device_desc *)id->driver_data;
|
||||
if (!dev_desc) {
|
||||
pdev = acpi_create_platform_device(adev, NULL);
|
||||
return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1;
|
||||
}
|
||||
if (!dev_desc)
|
||||
return -EINVAL;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
+31
-51
@@ -18,6 +18,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/mwait.h>
|
||||
#include <xen/xen.h>
|
||||
|
||||
@@ -336,33 +337,14 @@ static ssize_t idlecpus_show(struct device *dev,
|
||||
|
||||
static DEVICE_ATTR_RW(idlecpus);
|
||||
|
||||
static int acpi_pad_add_sysfs(struct acpi_device *device)
|
||||
{
|
||||
int result;
|
||||
static struct attribute *acpi_pad_attrs[] = {
|
||||
&dev_attr_idlecpus.attr,
|
||||
&dev_attr_idlepct.attr,
|
||||
&dev_attr_rrtime.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
result = device_create_file(&device->dev, &dev_attr_idlecpus);
|
||||
if (result)
|
||||
return -ENODEV;
|
||||
result = device_create_file(&device->dev, &dev_attr_idlepct);
|
||||
if (result) {
|
||||
device_remove_file(&device->dev, &dev_attr_idlecpus);
|
||||
return -ENODEV;
|
||||
}
|
||||
result = device_create_file(&device->dev, &dev_attr_rrtime);
|
||||
if (result) {
|
||||
device_remove_file(&device->dev, &dev_attr_idlecpus);
|
||||
device_remove_file(&device->dev, &dev_attr_idlepct);
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_pad_remove_sysfs(struct acpi_device *device)
|
||||
{
|
||||
device_remove_file(&device->dev, &dev_attr_idlecpus);
|
||||
device_remove_file(&device->dev, &dev_attr_idlepct);
|
||||
device_remove_file(&device->dev, &dev_attr_rrtime);
|
||||
}
|
||||
ATTRIBUTE_GROUPS(acpi_pad);
|
||||
|
||||
/*
|
||||
* Query firmware how many CPUs should be idle
|
||||
@@ -416,13 +398,13 @@ static void acpi_pad_handle_notify(acpi_handle handle)
|
||||
static void acpi_pad_notify(acpi_handle handle, u32 event,
|
||||
void *data)
|
||||
{
|
||||
struct acpi_device *device = data;
|
||||
struct acpi_device *adev = data;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
|
||||
acpi_pad_handle_notify(handle);
|
||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||
dev_name(&device->dev), event, 0);
|
||||
acpi_bus_generate_netlink_event(adev->pnp.device_class,
|
||||
dev_name(&adev->dev), event, 0);
|
||||
break;
|
||||
default:
|
||||
pr_warn("Unsupported event [0x%x]\n", event);
|
||||
@@ -430,35 +412,33 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_pad_add(struct acpi_device *device)
|
||||
static int acpi_pad_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
|
||||
acpi_status status;
|
||||
|
||||
strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS);
|
||||
strcpy(acpi_device_name(adev), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(adev), ACPI_PROCESSOR_AGGREGATOR_CLASS);
|
||||
|
||||
if (acpi_pad_add_sysfs(device))
|
||||
return -ENODEV;
|
||||
status = acpi_install_notify_handler(adev->handle,
|
||||
ACPI_DEVICE_NOTIFY, acpi_pad_notify, adev);
|
||||
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY, acpi_pad_notify, device);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_pad_remove_sysfs(device);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_pad_remove(struct acpi_device *device)
|
||||
static void acpi_pad_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
|
||||
|
||||
mutex_lock(&isolated_cpus_lock);
|
||||
acpi_pad_idle_cpus(0);
|
||||
mutex_unlock(&isolated_cpus_lock);
|
||||
|
||||
acpi_remove_notify_handler(device->handle,
|
||||
acpi_remove_notify_handler(adev->handle,
|
||||
ACPI_DEVICE_NOTIFY, acpi_pad_notify);
|
||||
acpi_pad_remove_sysfs(device);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id pad_device_ids[] = {
|
||||
@@ -467,13 +447,13 @@ static const struct acpi_device_id pad_device_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, pad_device_ids);
|
||||
|
||||
static struct acpi_driver acpi_pad_driver = {
|
||||
.name = "processor_aggregator",
|
||||
.class = ACPI_PROCESSOR_AGGREGATOR_CLASS,
|
||||
.ids = pad_device_ids,
|
||||
.ops = {
|
||||
.add = acpi_pad_add,
|
||||
.remove = acpi_pad_remove,
|
||||
static struct platform_driver acpi_pad_driver = {
|
||||
.probe = acpi_pad_probe,
|
||||
.remove_new = acpi_pad_remove,
|
||||
.driver = {
|
||||
.dev_groups = acpi_pad_groups,
|
||||
.name = "processor_aggregator",
|
||||
.acpi_match_table = pad_device_ids,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -487,12 +467,12 @@ static int __init acpi_pad_init(void)
|
||||
if (power_saving_mwait_eax == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return acpi_bus_register_driver(&acpi_pad_driver);
|
||||
return platform_driver_register(&acpi_pad_driver);
|
||||
}
|
||||
|
||||
static void __exit acpi_pad_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&acpi_pad_driver);
|
||||
platform_driver_unregister(&acpi_pad_driver);
|
||||
}
|
||||
|
||||
module_init(acpi_pad_init);
|
||||
|
||||
@@ -2062,7 +2062,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
goto err_del;
|
||||
|
||||
error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify);
|
||||
acpi_video_bus_notify, device);
|
||||
if (error)
|
||||
goto err_remove;
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ static struct acpi_table_erst *erst_tab;
|
||||
#define ERST_RANGE_NVRAM 0x0002
|
||||
#define ERST_RANGE_SLOW 0x0004
|
||||
|
||||
/* ERST Exec max timings */
|
||||
#define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000
|
||||
#define ERST_EXEC_TIMING_MAX_SHIFT 32
|
||||
|
||||
/*
|
||||
* ERST Error Log Address Range, used as buffer for reading/writing
|
||||
* error records.
|
||||
@@ -68,6 +72,7 @@ static struct erst_erange {
|
||||
u64 size;
|
||||
void __iomem *vaddr;
|
||||
u32 attr;
|
||||
u64 timings;
|
||||
} erst_erange;
|
||||
|
||||
/*
|
||||
@@ -97,6 +102,19 @@ static inline int erst_errno(int command_status)
|
||||
}
|
||||
}
|
||||
|
||||
static inline u64 erst_get_timeout(void)
|
||||
{
|
||||
u64 timeout = FIRMWARE_TIMEOUT;
|
||||
|
||||
if (erst_erange.attr & ERST_RANGE_SLOW) {
|
||||
timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >>
|
||||
ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC;
|
||||
if (timeout < FIRMWARE_TIMEOUT)
|
||||
timeout = FIRMWARE_TIMEOUT;
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
static int erst_timedout(u64 *t, u64 spin_unit)
|
||||
{
|
||||
if ((s64)*t < spin_unit) {
|
||||
@@ -191,9 +209,11 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
|
||||
{
|
||||
int rc;
|
||||
u64 val;
|
||||
u64 timeout = FIRMWARE_TIMEOUT;
|
||||
u64 timeout;
|
||||
u64 stall_time;
|
||||
|
||||
timeout = erst_get_timeout();
|
||||
|
||||
if (ctx->var1 > FIRMWARE_MAX_STALL) {
|
||||
if (!in_nmi())
|
||||
pr_warn(FW_WARN
|
||||
@@ -389,6 +409,13 @@ static int erst_get_erange(struct erst_erange *range)
|
||||
if (rc)
|
||||
return rc;
|
||||
range->attr = apei_exec_ctx_get_output(&ctx);
|
||||
rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_TIMINGS);
|
||||
if (rc == 0)
|
||||
range->timings = apei_exec_ctx_get_output(&ctx);
|
||||
else if (rc == -ENOENT)
|
||||
range->timings = 0;
|
||||
else
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -621,10 +648,12 @@ EXPORT_SYMBOL_GPL(erst_get_record_id_end);
|
||||
static int __erst_write_to_storage(u64 offset)
|
||||
{
|
||||
struct apei_exec_context ctx;
|
||||
u64 timeout = FIRMWARE_TIMEOUT;
|
||||
u64 timeout;
|
||||
u64 val;
|
||||
int rc;
|
||||
|
||||
timeout = erst_get_timeout();
|
||||
|
||||
erst_exec_ctx_init(&ctx);
|
||||
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE);
|
||||
if (rc)
|
||||
@@ -660,10 +689,12 @@ static int __erst_write_to_storage(u64 offset)
|
||||
static int __erst_read_from_storage(u64 record_id, u64 offset)
|
||||
{
|
||||
struct apei_exec_context ctx;
|
||||
u64 timeout = FIRMWARE_TIMEOUT;
|
||||
u64 timeout;
|
||||
u64 val;
|
||||
int rc;
|
||||
|
||||
timeout = erst_get_timeout();
|
||||
|
||||
erst_exec_ctx_init(&ctx);
|
||||
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ);
|
||||
if (rc)
|
||||
@@ -703,10 +734,12 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
|
||||
static int __erst_clear_from_storage(u64 record_id)
|
||||
{
|
||||
struct apei_exec_context ctx;
|
||||
u64 timeout = FIRMWARE_TIMEOUT;
|
||||
u64 timeout;
|
||||
u64 val;
|
||||
int rc;
|
||||
|
||||
timeout = erst_get_timeout();
|
||||
|
||||
erst_exec_ctx_init(&ctx);
|
||||
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR);
|
||||
if (rc)
|
||||
|
||||
@@ -209,6 +209,20 @@ err_pool_alloc:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* ghes_estatus_pool_region_free - free previously allocated memory
|
||||
* from the ghes_estatus_pool.
|
||||
* @addr: address of memory to free.
|
||||
* @size: size of memory to free.
|
||||
*
|
||||
* Returns none.
|
||||
*/
|
||||
void ghes_estatus_pool_region_free(unsigned long addr, u32 size)
|
||||
{
|
||||
gen_pool_free(ghes_estatus_pool, addr, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ghes_estatus_pool_region_free);
|
||||
|
||||
static int map_gen_v2(struct ghes *ghes)
|
||||
{
|
||||
return apei_map_generic_address(&ghes->generic_v2->read_ack_register);
|
||||
@@ -564,6 +578,7 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
|
||||
pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
|
||||
unsigned int devfn;
|
||||
int aer_severity;
|
||||
u8 *aer_info;
|
||||
|
||||
devfn = PCI_DEVFN(pcie_err->device_id.device,
|
||||
pcie_err->device_id.function);
|
||||
@@ -577,11 +592,17 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
|
||||
if (gdata->flags & CPER_SEC_RESET)
|
||||
aer_severity = AER_FATAL;
|
||||
|
||||
aer_info = (void *)gen_pool_alloc(ghes_estatus_pool,
|
||||
sizeof(struct aer_capability_regs));
|
||||
if (!aer_info)
|
||||
return;
|
||||
memcpy(aer_info, pcie_err->aer_info, sizeof(struct aer_capability_regs));
|
||||
|
||||
aer_recover_queue(pcie_err->device_id.segment,
|
||||
pcie_err->device_id.bus,
|
||||
devfn, aer_severity,
|
||||
(struct aer_capability_regs *)
|
||||
pcie_err->aer_info);
|
||||
aer_info);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1214,7 +1214,7 @@ static int acpi_battery_add(struct acpi_device *device)
|
||||
device_init_wakeup(&device->dev, 1);
|
||||
|
||||
result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
|
||||
acpi_battery_notify);
|
||||
acpi_battery_notify, device);
|
||||
if (result)
|
||||
goto fail_pm;
|
||||
|
||||
|
||||
+2
-2
@@ -556,12 +556,12 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device,
|
||||
|
||||
int acpi_dev_install_notify_handler(struct acpi_device *adev,
|
||||
u32 handler_type,
|
||||
acpi_notify_handler handler)
|
||||
acpi_notify_handler handler, void *context)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_install_notify_handler(adev->handle, handler_type,
|
||||
handler, adev);
|
||||
handler, context);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
+11
-13
@@ -158,8 +158,8 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia
|
||||
return 0;
|
||||
|
||||
len = snprintf(modalias, size, "acpi:");
|
||||
if (len <= 0)
|
||||
return len;
|
||||
if (len >= size)
|
||||
return -ENOMEM;
|
||||
|
||||
size -= len;
|
||||
|
||||
@@ -168,8 +168,6 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia
|
||||
continue;
|
||||
|
||||
count = snprintf(&modalias[len], size, "%s:", id->id);
|
||||
if (count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (count >= size)
|
||||
return -ENOMEM;
|
||||
@@ -177,7 +175,7 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia
|
||||
len += count;
|
||||
size -= count;
|
||||
}
|
||||
modalias[len] = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -212,8 +210,10 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias
|
||||
len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
|
||||
ACPI_FREE(buf.pointer);
|
||||
|
||||
if (len <= 0)
|
||||
return len;
|
||||
if (len >= size)
|
||||
return -ENOMEM;
|
||||
|
||||
size -= len;
|
||||
|
||||
of_compatible = acpi_dev->data.of_compatible;
|
||||
if (of_compatible->type == ACPI_TYPE_PACKAGE) {
|
||||
@@ -226,8 +226,6 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias
|
||||
for (i = 0; i < nval; i++, obj++) {
|
||||
count = snprintf(&modalias[len], size, "C%s",
|
||||
obj->string.pointer);
|
||||
if (count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (count >= size)
|
||||
return -ENOMEM;
|
||||
@@ -235,7 +233,7 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias
|
||||
len += count;
|
||||
size -= count;
|
||||
}
|
||||
modalias[len] = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -410,7 +408,7 @@ static ssize_t uid_show(struct device *dev,
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
|
||||
return sprintf(buf, "%s\n", acpi_device_uid(acpi_dev));
|
||||
}
|
||||
static DEVICE_ATTR_RO(uid);
|
||||
|
||||
@@ -554,7 +552,7 @@ int acpi_device_setup_files(struct acpi_device *dev)
|
||||
|
||||
if (dev->pnp.type.bus_address)
|
||||
result = device_create_file(&dev->dev, &dev_attr_adr);
|
||||
if (dev->pnp.unique_id)
|
||||
if (acpi_device_uid(dev))
|
||||
result = device_create_file(&dev->dev, &dev_attr_uid);
|
||||
|
||||
if (acpi_has_method(dev->handle, "_SUN")) {
|
||||
@@ -635,7 +633,7 @@ void acpi_device_remove_files(struct acpi_device *dev)
|
||||
if (acpi_has_method(dev->handle, "_HRV"))
|
||||
device_remove_file(&dev->dev, &dev_attr_hrv);
|
||||
|
||||
if (dev->pnp.unique_id)
|
||||
if (acpi_device_uid(dev))
|
||||
device_remove_file(&dev->dev, &dev_attr_uid);
|
||||
if (dev->pnp.type.bus_address)
|
||||
device_remove_file(&dev->dev, &dev_attr_adr);
|
||||
|
||||
@@ -1924,6 +1924,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-dk1xxx"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* HP 250 G7 Notebook PC
|
||||
*/
|
||||
.callback = ec_honor_dsdt_gpe,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G7 Notebook PC"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Samsung hardware
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ static int acpi_hed_add(struct acpi_device *device)
|
||||
hed_handle = device->handle;
|
||||
|
||||
err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_hed_notify);
|
||||
acpi_hed_notify, device);
|
||||
if (err)
|
||||
hed_handle = NULL;
|
||||
|
||||
|
||||
@@ -3340,7 +3340,7 @@ static int acpi_nfit_add(struct acpi_device *adev)
|
||||
int rc = 0;
|
||||
|
||||
rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_nfit_notify);
|
||||
acpi_nfit_notify, adev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ void __init acpi_osi_setup(char *str)
|
||||
break;
|
||||
} else if (osi->string[0] == '\0') {
|
||||
osi->enable = enable;
|
||||
strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
|
||||
strscpy(osi->string, str, OSI_STRING_LENGTH_MAX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-12
@@ -149,7 +149,7 @@ void acpi_os_printf(const char *fmt, ...)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_os_printf);
|
||||
|
||||
void acpi_os_vprintf(const char *fmt, va_list args)
|
||||
void __printf(1, 0) acpi_os_vprintf(const char *fmt, va_list args)
|
||||
{
|
||||
static char buffer[512];
|
||||
|
||||
@@ -493,7 +493,7 @@ EXPORT_SYMBOL(acpi_os_unmap_generic_address);
|
||||
|
||||
#ifdef ACPI_FUTURE_USAGE
|
||||
acpi_status
|
||||
acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
|
||||
acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
|
||||
{
|
||||
if (!phys || !virt)
|
||||
return AE_BAD_PARAMETER;
|
||||
@@ -784,7 +784,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
acpi_status
|
||||
acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
|
||||
acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, u32 reg,
|
||||
u64 *value, u32 width)
|
||||
{
|
||||
int result, size;
|
||||
@@ -816,7 +816,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
|
||||
}
|
||||
|
||||
acpi_status
|
||||
acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
|
||||
acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, u32 reg,
|
||||
u64 value, u32 width)
|
||||
{
|
||||
int result, size;
|
||||
@@ -1067,6 +1067,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
|
||||
struct acpi_os_dpc *dpc;
|
||||
struct workqueue_struct *queue;
|
||||
int ret;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
|
||||
"Scheduling function [%p(%p)] for deferred execution.\n",
|
||||
function, context));
|
||||
@@ -1197,7 +1198,7 @@ bool acpi_queue_hotplug_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
acpi_status
|
||||
acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
|
||||
acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle *handle)
|
||||
{
|
||||
struct semaphore *sem = NULL;
|
||||
|
||||
@@ -1522,6 +1523,7 @@ acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
|
||||
__acquires(lockp)
|
||||
{
|
||||
acpi_cpu_flags flags;
|
||||
|
||||
spin_lock_irqsave(lockp, flags);
|
||||
return flags;
|
||||
}
|
||||
@@ -1554,7 +1556,7 @@ void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
|
||||
acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t **cache)
|
||||
{
|
||||
*cache = kmem_cache_create(name, size, 0, 0, NULL);
|
||||
if (*cache == NULL)
|
||||
@@ -1575,10 +1577,10 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
|
||||
acpi_status acpi_os_purge_cache(acpi_cache_t *cache)
|
||||
{
|
||||
kmem_cache_shrink(cache);
|
||||
return (AE_OK);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -1594,10 +1596,10 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
|
||||
acpi_status acpi_os_delete_cache(acpi_cache_t *cache)
|
||||
{
|
||||
kmem_cache_destroy(cache);
|
||||
return (AE_OK);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -1614,10 +1616,10 @@ acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
|
||||
acpi_status acpi_os_release_object(acpi_cache_t *cache, void *object)
|
||||
{
|
||||
kmem_cache_free(cache, object);
|
||||
return (AE_OK);
|
||||
return AE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1708,6 +1710,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
|
||||
u32 pm1b_control)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (__acpi_os_prepare_sleep)
|
||||
rc = __acpi_os_prepare_sleep(sleep_state,
|
||||
pm1a_control, pm1b_control);
|
||||
@@ -1730,6 +1733,7 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
|
||||
u32 val_b)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (__acpi_os_prepare_extended_sleep)
|
||||
rc = __acpi_os_prepare_extended_sleep(sleep_state,
|
||||
val_a, val_b);
|
||||
|
||||
@@ -1055,9 +1055,9 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
||||
* exists and returns 0, we must preserve any PCI resource
|
||||
* assignments made by firmware for this host bridge.
|
||||
*/
|
||||
obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1,
|
||||
DSM_PCI_PRESERVE_BOOT_CONFIG, NULL);
|
||||
if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0)
|
||||
obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1,
|
||||
DSM_PCI_PRESERVE_BOOT_CONFIG, NULL, ACPI_TYPE_INTEGER);
|
||||
if (obj && obj->integer.value == 0)
|
||||
host_bridge->preserve_config = 1;
|
||||
ACPI_FREE(obj);
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ struct prm_module_info {
|
||||
bool updatable;
|
||||
|
||||
struct list_head module_list;
|
||||
struct prm_handler_info handlers[];
|
||||
struct prm_handler_info handlers[] __counted_by(handler_count);
|
||||
};
|
||||
|
||||
static u64 efi_pa_va_lookup(u64 pa)
|
||||
|
||||
+11
-9
@@ -55,6 +55,7 @@ static const guid_t ads_guid =
|
||||
GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
|
||||
0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
|
||||
|
||||
/* ACPI _DSD data buffer GUID: edb12dd0-363d-4085-a3d2-49522ca160c4 */
|
||||
static const guid_t buffer_prop_guid =
|
||||
GUID_INIT(0xedb12dd0, 0x363d, 0x4085,
|
||||
0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4);
|
||||
@@ -1102,25 +1103,26 @@ static int acpi_data_prop_read(const struct acpi_device_data *data,
|
||||
switch (proptype) {
|
||||
case DEV_PROP_STRING:
|
||||
break;
|
||||
case DEV_PROP_U8 ... DEV_PROP_U64:
|
||||
default:
|
||||
if (obj->type == ACPI_TYPE_BUFFER) {
|
||||
if (nval > obj->buffer.length)
|
||||
return -EOVERFLOW;
|
||||
break;
|
||||
} else {
|
||||
if (nval > obj->package.count)
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
fallthrough;
|
||||
default:
|
||||
if (nval > obj->package.count)
|
||||
return -EOVERFLOW;
|
||||
break;
|
||||
}
|
||||
if (nval == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (obj->type != ACPI_TYPE_BUFFER)
|
||||
items = obj->package.elements;
|
||||
else
|
||||
if (obj->type == ACPI_TYPE_BUFFER) {
|
||||
if (proptype != DEV_PROP_U8)
|
||||
return -EPROTO;
|
||||
items = obj;
|
||||
} else {
|
||||
items = obj->package.elements;
|
||||
}
|
||||
|
||||
switch (proptype) {
|
||||
case DEV_PROP_U8:
|
||||
|
||||
+49
-47
@@ -385,127 +385,144 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
|
||||
|
||||
static const struct dmi_system_id medion_laptop[] = {
|
||||
/*
|
||||
* DMI matches for boards where the DSDT specifies the kbd IRQ as
|
||||
* level active-low and using the override changes this to rising edge,
|
||||
* stopping the keyboard from working.
|
||||
*/
|
||||
static const struct dmi_system_id irq1_level_low_skip_override[] = {
|
||||
{
|
||||
.ident = "MEDION P15651",
|
||||
/* MEDION P15651 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "M15T"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "MEDION S17405",
|
||||
/* MEDION S17405 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "M17T"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "MEDION S17413",
|
||||
/* MEDION S17413 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "M1xA"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id asus_laptop[] = {
|
||||
{
|
||||
.ident = "Asus Vivobook K3402ZA",
|
||||
/* Asus Vivobook K3402ZA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus Vivobook K3502ZA",
|
||||
/* Asus Vivobook K3502ZA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus Vivobook S5402ZA",
|
||||
/* Asus Vivobook S5402ZA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus Vivobook S5602ZA",
|
||||
/* Asus Vivobook S5602ZA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus ExpertBook B1402CBA",
|
||||
/* Asus ExpertBook B1402CBA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus ExpertBook B1502CBA",
|
||||
/* Asus ExpertBook B1502CBA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus ExpertBook B2402CBA",
|
||||
/* Asus ExpertBook B2402CBA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus ExpertBook B2402FBA",
|
||||
/* Asus ExpertBook B2402FBA */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "B2402FBA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus ExpertBook B2502",
|
||||
/* Asus ExpertBook B2502 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id tongfang_gm_rg[] = {
|
||||
{
|
||||
.ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
|
||||
/* LG Electronics 17U70P */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "17U70P"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id maingear_laptop[] = {
|
||||
/*
|
||||
* DMI matches for AMD Zen boards where the DSDT specifies the kbd IRQ
|
||||
* as falling edge and this must be overridden to rising edge,
|
||||
* to have a working keyboard.
|
||||
*/
|
||||
static const struct dmi_system_id irq1_edge_low_force_override[] = {
|
||||
{
|
||||
.ident = "MAINGEAR Vector Pro 2 15",
|
||||
/* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* MAINGEAR Vector Pro 2 15 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "MAINGEAR Vector Pro 2 17",
|
||||
/* MAINGEAR Vector Pro 2 17 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id pcspecialist_laptop[] = {
|
||||
{
|
||||
/* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */
|
||||
.matches = {
|
||||
@@ -527,17 +544,6 @@ static const struct dmi_system_id pcspecialist_laptop[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id lg_laptop[] = {
|
||||
{
|
||||
.ident = "LG Electronics 17U70P",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "17U70P"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
struct irq_override_cmp {
|
||||
const struct dmi_system_id *system;
|
||||
unsigned char irq;
|
||||
@@ -548,12 +554,8 @@ struct irq_override_cmp {
|
||||
};
|
||||
|
||||
static const struct irq_override_cmp override_table[] = {
|
||||
{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
|
||||
{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
|
||||
{ tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
|
||||
{ maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
|
||||
{ pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
|
||||
{ lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
|
||||
{ irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
|
||||
{ irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
|
||||
};
|
||||
|
||||
static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
|
||||
|
||||
+7
-6
@@ -289,10 +289,10 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_scan_device_not_present(struct acpi_device *adev)
|
||||
static int acpi_scan_device_not_enumerated(struct acpi_device *adev)
|
||||
{
|
||||
if (!acpi_device_enumerated(adev)) {
|
||||
dev_warn(&adev->dev, "Still not present\n");
|
||||
dev_warn(&adev->dev, "Still not enumerated\n");
|
||||
return -EALREADY;
|
||||
}
|
||||
acpi_bus_trim(adev);
|
||||
@@ -304,7 +304,7 @@ static int acpi_scan_device_check(struct acpi_device *adev)
|
||||
int error;
|
||||
|
||||
acpi_bus_get_status(adev);
|
||||
if (adev->status.present || adev->status.functional) {
|
||||
if (acpi_device_is_present(adev)) {
|
||||
/*
|
||||
* This function is only called for device objects for which
|
||||
* matching scan handlers exist. The only situation in which
|
||||
@@ -327,7 +327,7 @@ static int acpi_scan_device_check(struct acpi_device *adev)
|
||||
error = -ENODEV;
|
||||
}
|
||||
} else {
|
||||
error = acpi_scan_device_not_present(adev);
|
||||
error = acpi_scan_device_not_enumerated(adev);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@@ -338,8 +338,8 @@ static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
|
||||
int error;
|
||||
|
||||
acpi_bus_get_status(adev);
|
||||
if (!(adev->status.present || adev->status.functional)) {
|
||||
acpi_scan_device_not_present(adev);
|
||||
if (!acpi_device_is_present(adev)) {
|
||||
acpi_scan_device_not_enumerated(adev);
|
||||
return 0;
|
||||
}
|
||||
if (handler && handler->hotplug.scan_dependent)
|
||||
@@ -2032,6 +2032,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
|
||||
mutex_unlock(&acpi_dep_list_lock);
|
||||
}
|
||||
|
||||
acpi_handle_list_free(&dep_devices);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
+22
-8
@@ -245,7 +245,7 @@ static bool update_trip_devices(struct acpi_thermal *tz,
|
||||
struct acpi_thermal_trip *acpi_trip,
|
||||
int index, bool compare)
|
||||
{
|
||||
struct acpi_handle_list devices;
|
||||
struct acpi_handle_list devices = { 0 };
|
||||
char method[] = "_PSL";
|
||||
acpi_status status;
|
||||
|
||||
@@ -255,18 +255,21 @@ static bool update_trip_devices(struct acpi_thermal *tz,
|
||||
method[3] = '0' + index;
|
||||
}
|
||||
|
||||
memset(&devices, 0, sizeof(devices));
|
||||
|
||||
status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_handle_info(tz->device->handle, "%s evaluation failure\n", method);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices)))
|
||||
if (acpi_handle_list_equal(&acpi_trip->devices, &devices)) {
|
||||
acpi_handle_list_free(&devices);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (compare)
|
||||
ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device");
|
||||
|
||||
memcpy(&acpi_trip->devices, &devices, sizeof(devices));
|
||||
acpi_handle_list_replace(&acpi_trip->devices, &devices);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -808,6 +811,17 @@ static void acpi_thermal_check_fn(struct work_struct *work)
|
||||
mutex_unlock(&tz->thermal_check_lock);
|
||||
}
|
||||
|
||||
static void acpi_thermal_free_thermal_zone(struct acpi_thermal *tz)
|
||||
{
|
||||
int i;
|
||||
|
||||
acpi_handle_list_free(&tz->trips.passive.trip.devices);
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
|
||||
acpi_handle_list_free(&tz->trips.active[i].trip.devices);
|
||||
|
||||
kfree(tz);
|
||||
}
|
||||
|
||||
static int acpi_thermal_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_thermal_trip *acpi_trip;
|
||||
@@ -922,7 +936,7 @@ static int acpi_thermal_add(struct acpi_device *device)
|
||||
acpi_device_bid(device), deci_kelvin_to_celsius(tz->temp_dk));
|
||||
|
||||
result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_thermal_notify);
|
||||
acpi_thermal_notify, device);
|
||||
if (result)
|
||||
goto flush_wq;
|
||||
|
||||
@@ -934,7 +948,7 @@ flush_wq:
|
||||
free_trips:
|
||||
kfree(tz->trip_table);
|
||||
free_memory:
|
||||
kfree(tz);
|
||||
acpi_thermal_free_thermal_zone(tz);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -954,7 +968,7 @@ static void acpi_thermal_remove(struct acpi_device *device)
|
||||
flush_workqueue(acpi_thermal_pm_queue);
|
||||
acpi_thermal_unregister_thermal_zone(tz);
|
||||
|
||||
kfree(tz);
|
||||
acpi_thermal_free_thermal_zone(tz);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
+90
-12
@@ -342,9 +342,8 @@ acpi_evaluate_reference(acpi_handle handle,
|
||||
u32 i = 0;
|
||||
|
||||
|
||||
if (!list) {
|
||||
if (!list)
|
||||
return AE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* Evaluate object. */
|
||||
|
||||
@@ -370,7 +369,8 @@ acpi_evaluate_reference(acpi_handle handle,
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (package->package.count > ACPI_MAX_HANDLES) {
|
||||
list->handles = kcalloc(package->package.count, sizeof(*list->handles), GFP_KERNEL);
|
||||
if (!list->handles) {
|
||||
kfree(package);
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
@@ -399,10 +399,11 @@ acpi_evaluate_reference(acpi_handle handle,
|
||||
acpi_handle_debug(list->handles[i], "Found in reference list\n");
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
if (ACPI_FAILURE(status)) {
|
||||
list->count = 0;
|
||||
//kfree(list->handles);
|
||||
kfree(list->handles);
|
||||
list->handles = NULL;
|
||||
}
|
||||
|
||||
kfree(buffer.pointer);
|
||||
@@ -412,6 +413,61 @@ acpi_evaluate_reference(acpi_handle handle,
|
||||
|
||||
EXPORT_SYMBOL(acpi_evaluate_reference);
|
||||
|
||||
/**
|
||||
* acpi_handle_list_equal - Check if two ACPI handle lists are the same
|
||||
* @list1: First list to compare.
|
||||
* @list2: Second list to compare.
|
||||
*
|
||||
* Return true if the given ACPI handle lists are of the same size and
|
||||
* contain the same ACPI handles in the same order. Otherwise, return false.
|
||||
*/
|
||||
bool acpi_handle_list_equal(struct acpi_handle_list *list1,
|
||||
struct acpi_handle_list *list2)
|
||||
{
|
||||
return list1->count == list2->count &&
|
||||
!memcmp(list1->handles, list2->handles,
|
||||
list1->count * sizeof(acpi_handle));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_handle_list_equal);
|
||||
|
||||
/**
|
||||
* acpi_handle_list_replace - Replace one ACPI handle list with another
|
||||
* @dst: ACPI handle list to replace.
|
||||
* @src: Source ACPI handle list.
|
||||
*
|
||||
* Free the handles table in @dst, move the handles table from @src to @dst,
|
||||
* copy count from @src to @dst and clear @src.
|
||||
*/
|
||||
void acpi_handle_list_replace(struct acpi_handle_list *dst,
|
||||
struct acpi_handle_list *src)
|
||||
{
|
||||
if (dst->count)
|
||||
kfree(dst->handles);
|
||||
|
||||
dst->count = src->count;
|
||||
dst->handles = src->handles;
|
||||
|
||||
src->handles = NULL;
|
||||
src->count = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_handle_list_replace);
|
||||
|
||||
/**
|
||||
* acpi_handle_list_free - Free the handles table in an ACPI handle list
|
||||
* @list: ACPI handle list to free.
|
||||
*
|
||||
* Free the handles table in @list and clear its count field.
|
||||
*/
|
||||
void acpi_handle_list_free(struct acpi_handle_list *list)
|
||||
{
|
||||
if (!list->count)
|
||||
return;
|
||||
|
||||
kfree(list->handles);
|
||||
list->count = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_handle_list_free);
|
||||
|
||||
acpi_status
|
||||
acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
|
||||
{
|
||||
@@ -523,7 +579,7 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
|
||||
vaf.va = &args;
|
||||
|
||||
path = acpi_handle_path(handle);
|
||||
printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf);
|
||||
printk("%sACPI: %s: %pV", level, path ? path : "<n/a>", &vaf);
|
||||
|
||||
va_end(args);
|
||||
kfree(path);
|
||||
@@ -768,20 +824,43 @@ bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_check_dsm);
|
||||
|
||||
/**
|
||||
* acpi_dev_uid_match - Match device by supplied UID
|
||||
* @adev: ACPI device to match.
|
||||
* @uid2: Unique ID of the device.
|
||||
*
|
||||
* Matches UID in @adev with given @uid2.
|
||||
*
|
||||
* Returns:
|
||||
* - %true if matches.
|
||||
* - %false otherwise.
|
||||
*/
|
||||
bool acpi_dev_uid_match(struct acpi_device *adev, const char *uid2)
|
||||
{
|
||||
const char *uid1 = acpi_device_uid(adev);
|
||||
|
||||
return uid1 && uid2 && !strcmp(uid1, uid2);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_uid_match);
|
||||
|
||||
/**
|
||||
* acpi_dev_hid_uid_match - Match device by supplied HID and UID
|
||||
* @adev: ACPI device to match.
|
||||
* @hid2: Hardware ID of the device.
|
||||
* @uid2: Unique ID of the device, pass NULL to not check _UID.
|
||||
*
|
||||
* Matches HID and UID in @adev with given @hid2 and @uid2.
|
||||
* Returns true if matches.
|
||||
* Matches HID and UID in @adev with given @hid2 and @uid2. Absence of @uid2
|
||||
* will be treated as a match. If user wants to validate @uid2, it should be
|
||||
* done before calling this function.
|
||||
*
|
||||
* Returns:
|
||||
* - %true if matches or @uid2 is NULL.
|
||||
* - %false otherwise.
|
||||
*/
|
||||
bool acpi_dev_hid_uid_match(struct acpi_device *adev,
|
||||
const char *hid2, const char *uid2)
|
||||
{
|
||||
const char *hid1 = acpi_device_hid(adev);
|
||||
const char *uid1 = acpi_device_uid(adev);
|
||||
|
||||
if (strcmp(hid1, hid2))
|
||||
return false;
|
||||
@@ -789,7 +868,7 @@ bool acpi_dev_hid_uid_match(struct acpi_device *adev,
|
||||
if (!uid2)
|
||||
return true;
|
||||
|
||||
return uid1 && !strcmp(uid1, uid2);
|
||||
return acpi_dev_uid_match(adev, uid2);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_dev_hid_uid_match);
|
||||
|
||||
@@ -863,8 +942,7 @@ static int acpi_dev_match_cb(struct device *dev, const void *data)
|
||||
if (acpi_match_device_ids(adev, match->hid))
|
||||
return 0;
|
||||
|
||||
if (match->uid && (!adev->pnp.unique_id ||
|
||||
strcmp(adev->pnp.unique_id, match->uid)))
|
||||
if (match->uid && !acpi_dev_uid_match(adev, match->uid))
|
||||
return 0;
|
||||
|
||||
if (match->hrv == -1)
|
||||
|
||||
@@ -130,6 +130,16 @@ static int video_detect_force_native(const struct dmi_system_id *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_detect_portege_r100(const struct dmi_system_id *d)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
/* Search for Trident CyberBlade XP4m32 to confirm Portégé R100 */
|
||||
dev = pci_get_device(PCI_VENDOR_ID_TRIDENT, 0x2100, NULL);
|
||||
if (dev)
|
||||
acpi_backlight_dmi = acpi_backlight_vendor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
/*
|
||||
* Models which should use the vendor backlight interface,
|
||||
@@ -229,14 +239,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Xiaomi Mi Pad 2 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Models which should use the vendor backlight interface,
|
||||
@@ -270,6 +272,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Toshiba Portégé R100 has working both acpi_video and toshiba_acpi
|
||||
* vendor driver. But none of them gets activated as it has a VGA with
|
||||
* no kernel driver (Trident CyberBlade XP4m32).
|
||||
* The DMI strings are generic so check for the VGA chip in callback.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_portege_r100,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Portable PC")
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Models which need acpi_video backlight control where the GPU drivers
|
||||
* do not call acpi_video_register_backlight() because no internal panel
|
||||
@@ -799,6 +817,56 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* x86 android tablets which directly control the backlight through
|
||||
* an external backlight controller, typically TI's LP8557.
|
||||
* The backlight is directly controlled by the lp855x driver on these.
|
||||
* This setup means that neither i915's native nor acpi_video backlight
|
||||
* control works. Add a "vendor" quirk to disable both. Note these
|
||||
* devices do not use vendor control in the typical meaning of
|
||||
* vendor specific SMBIOS or ACPI calls being used.
|
||||
*/
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Lenovo Yoga Book X90F / X90L */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/*
|
||||
* Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10"
|
||||
* Lenovo Yoga Tablet 2 use the same mainboard)
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
|
||||
/* Partial match on beginning of BIOS version */
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Lenovo Yoga Tab 3 Pro YT3-X90F */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
/* Xiaomi Mi Pad 2 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
|
||||
},
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
|
||||
@@ -417,11 +417,10 @@ static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *d
|
||||
int ret = -EINVAL;
|
||||
|
||||
guid_parse(uuid, dsm_guid);
|
||||
obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL);
|
||||
|
||||
/* Check if the _DSM is present and as expected. */
|
||||
if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 ||
|
||||
obj->buffer.length > sizeof(u32)) {
|
||||
obj = acpi_evaluate_dsm_typed(handle, dsm_guid, rev, 0, NULL, ACPI_TYPE_BUFFER);
|
||||
if (!obj || obj->buffer.length == 0 || obj->buffer.length > sizeof(u32)) {
|
||||
acpi_handle_debug(handle,
|
||||
"_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
|
||||
goto out;
|
||||
|
||||
@@ -184,8 +184,7 @@ bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *s
|
||||
if (acpi_match_device_ids(adev, override_status_ids[i].hid))
|
||||
continue;
|
||||
|
||||
if (!adev->pnp.unique_id ||
|
||||
strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
|
||||
if (!acpi_dev_uid_match(adev, override_status_ids[i].uid))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -228,3 +228,24 @@ void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd)
|
||||
device_pm_check_callbacks(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_domain_set);
|
||||
|
||||
/**
|
||||
* dev_pm_domain_set_performance_state - Request a new performance state.
|
||||
* @dev: The device to make the request for.
|
||||
* @state: Target performance state for the device.
|
||||
*
|
||||
* This function should be called when a new performance state needs to be
|
||||
* requested for a device that is attached to a PM domain. Note that, the
|
||||
* support for performance scaling for PM domains is optional.
|
||||
*
|
||||
* Returns 0 on success and when performance scaling isn't supported, negative
|
||||
* error code on failure.
|
||||
*/
|
||||
int dev_pm_domain_set_performance_state(struct device *dev, unsigned int state)
|
||||
{
|
||||
if (dev->pm_domain && dev->pm_domain->set_performance_state)
|
||||
return dev->pm_domain->set_performance_state(dev, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_domain_set_performance_state);
|
||||
|
||||
+21
-12
@@ -419,6 +419,25 @@ static void genpd_restore_performance_state(struct device *dev,
|
||||
genpd_set_performance_state(dev, state);
|
||||
}
|
||||
|
||||
static int genpd_dev_pm_set_performance_state(struct device *dev,
|
||||
unsigned int state)
|
||||
{
|
||||
struct generic_pm_domain *genpd = dev_to_genpd(dev);
|
||||
int ret = 0;
|
||||
|
||||
genpd_lock(genpd);
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
dev_gpd_data(dev)->rpm_pstate = state;
|
||||
} else {
|
||||
ret = genpd_set_performance_state(dev, state);
|
||||
if (!ret)
|
||||
dev_gpd_data(dev)->rpm_pstate = 0;
|
||||
}
|
||||
genpd_unlock(genpd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_pm_genpd_set_performance_state- Set performance state of device's power
|
||||
* domain.
|
||||
@@ -437,7 +456,6 @@ static void genpd_restore_performance_state(struct device *dev,
|
||||
int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
int ret = 0;
|
||||
|
||||
genpd = dev_to_genpd_safe(dev);
|
||||
if (!genpd)
|
||||
@@ -447,17 +465,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
|
||||
!dev->power.subsys_data->domain_data))
|
||||
return -EINVAL;
|
||||
|
||||
genpd_lock(genpd);
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
dev_gpd_data(dev)->rpm_pstate = state;
|
||||
} else {
|
||||
ret = genpd_set_performance_state(dev, state);
|
||||
if (!ret)
|
||||
dev_gpd_data(dev)->rpm_pstate = 0;
|
||||
}
|
||||
genpd_unlock(genpd);
|
||||
|
||||
return ret;
|
||||
return genpd_dev_pm_set_performance_state(dev, state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_genpd_set_performance_state);
|
||||
|
||||
@@ -2079,6 +2087,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||
genpd->domain.ops.restore_noirq = genpd_restore_noirq;
|
||||
genpd->domain.ops.complete = genpd_complete;
|
||||
genpd->domain.start = genpd_dev_pm_start;
|
||||
genpd->domain.set_performance_state = genpd_dev_pm_set_performance_state;
|
||||
|
||||
if (genpd->flags & GENPD_FLAG_PM_CLK) {
|
||||
genpd->dev_ops.stop = pm_clk_suspend;
|
||||
|
||||
@@ -334,6 +334,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rbtree_all(const void *key, const struct rb_node *node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* regcache_sync - Sync the register cache with the hardware.
|
||||
*
|
||||
@@ -351,6 +356,7 @@ int regcache_sync(struct regmap *map)
|
||||
unsigned int i;
|
||||
const char *name;
|
||||
bool bypass;
|
||||
struct rb_node *node;
|
||||
|
||||
if (WARN_ON(map->cache_type == REGCACHE_NONE))
|
||||
return -EINVAL;
|
||||
@@ -392,6 +398,30 @@ out:
|
||||
/* Restore the bypass state */
|
||||
map->cache_bypass = bypass;
|
||||
map->no_sync_defaults = false;
|
||||
|
||||
/*
|
||||
* If we did any paging with cache bypassed and a cached
|
||||
* paging register then the register and cache state might
|
||||
* have gone out of sync, force writes of all the paging
|
||||
* registers.
|
||||
*/
|
||||
rb_for_each(node, 0, &map->range_tree, rbtree_all) {
|
||||
struct regmap_range_node *this =
|
||||
rb_entry(node, struct regmap_range_node, node);
|
||||
|
||||
/* If there's nothing in the cache there's nothing to sync */
|
||||
ret = regcache_read(map, this->selector_reg, &i);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
|
||||
ret = _regmap_write(map, this->selector_reg, i);
|
||||
if (ret != 0) {
|
||||
dev_err(map->dev, "Failed to write %x = %x: %d\n",
|
||||
this->selector_reg, i, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
regmap_async_complete(map);
|
||||
|
||||
@@ -48,7 +48,7 @@ static ssize_t regmap_name_read_file(struct file *file,
|
||||
name = map->dev->driver->name;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
|
||||
if (ret < 0) {
|
||||
if (ret >= PAGE_SIZE) {
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -442,10 +442,18 @@ static struct regmap_range_cfg test_range = {
|
||||
.range_max = 40,
|
||||
};
|
||||
|
||||
static bool test_range_volatile(struct device *dev, unsigned int reg)
|
||||
static bool test_range_window_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (reg >= test_range.window_start &&
|
||||
reg <= test_range.selector_reg + test_range.window_len)
|
||||
reg <= test_range.window_start + test_range.window_len)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool test_range_all_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (test_range_window_volatile(dev, reg))
|
||||
return true;
|
||||
|
||||
if (reg >= test_range.range_min && reg <= test_range.range_max)
|
||||
@@ -465,7 +473,7 @@ static void basic_ranges(struct kunit *test)
|
||||
|
||||
config = test_regmap_config;
|
||||
config.cache_type = t->type;
|
||||
config.volatile_reg = test_range_volatile;
|
||||
config.volatile_reg = test_range_all_volatile;
|
||||
config.ranges = &test_range;
|
||||
config.num_ranges = 1;
|
||||
config.max_register = test_range.range_max;
|
||||
@@ -875,6 +883,59 @@ static void cache_present(struct kunit *test)
|
||||
regmap_exit(map);
|
||||
}
|
||||
|
||||
/* Check that caching the window register works with sync */
|
||||
static void cache_range_window_reg(struct kunit *test)
|
||||
{
|
||||
struct regcache_types *t = (struct regcache_types *)test->param_value;
|
||||
struct regmap *map;
|
||||
struct regmap_config config;
|
||||
struct regmap_ram_data *data;
|
||||
unsigned int val;
|
||||
int i;
|
||||
|
||||
config = test_regmap_config;
|
||||
config.cache_type = t->type;
|
||||
config.volatile_reg = test_range_window_volatile;
|
||||
config.ranges = &test_range;
|
||||
config.num_ranges = 1;
|
||||
config.max_register = test_range.range_max;
|
||||
|
||||
map = gen_regmap(&config, &data);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
|
||||
if (IS_ERR(map))
|
||||
return;
|
||||
|
||||
/* Write new values to the entire range */
|
||||
for (i = test_range.range_min; i <= test_range.range_max; i++)
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, i, 0));
|
||||
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 2);
|
||||
|
||||
/* Write to the first register in the range to reset the page */
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 0);
|
||||
|
||||
/* Trigger a cache sync */
|
||||
regcache_mark_dirty(map);
|
||||
KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
|
||||
|
||||
/* Write to the first register again, the page should be reset */
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 0);
|
||||
|
||||
/* Trigger another cache sync */
|
||||
regcache_mark_dirty(map);
|
||||
KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
|
||||
|
||||
/* Write to the last register again, the page should be reset */
|
||||
KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_max, 0));
|
||||
val = data->vals[test_range.selector_reg] & test_range.selector_mask;
|
||||
KUNIT_ASSERT_EQ(test, val, 2);
|
||||
}
|
||||
|
||||
struct raw_test_types {
|
||||
const char *name;
|
||||
|
||||
@@ -1217,6 +1278,7 @@ static struct kunit_case regmap_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_gen_params),
|
||||
|
||||
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
|
||||
KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
|
||||
|
||||
@@ -90,7 +90,7 @@ config ARM_VEXPRESS_SPC_CPUFREQ
|
||||
|
||||
config ARM_BRCMSTB_AVS_CPUFREQ
|
||||
tristate "Broadcom STB AVS CPUfreq driver"
|
||||
depends on ARCH_BRCMSTB || COMPILE_TEST
|
||||
depends on (ARCH_BRCMSTB && !ARM_SCMI_CPUFREQ) || COMPILE_TEST
|
||||
default y
|
||||
help
|
||||
Some Broadcom STB SoCs use a co-processor running proprietary firmware
|
||||
@@ -124,8 +124,8 @@ config ARM_IMX_CPUFREQ_DT
|
||||
tristate "Freescale i.MX8M cpufreq support"
|
||||
depends on ARCH_MXC && CPUFREQ_DT
|
||||
help
|
||||
This adds cpufreq driver support for Freescale i.MX8M series SoCs,
|
||||
based on cpufreq-dt.
|
||||
This adds cpufreq driver support for Freescale i.MX7/i.MX8M
|
||||
series SoCs, based on cpufreq-dt.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
|
||||
@@ -142,9 +142,11 @@ static const struct of_device_id blocklist[] __initconst = {
|
||||
{ .compatible = "nvidia,tegra234", },
|
||||
|
||||
{ .compatible = "qcom,apq8096", },
|
||||
{ .compatible = "qcom,msm8909", },
|
||||
{ .compatible = "qcom,msm8996", },
|
||||
{ .compatible = "qcom,msm8998", },
|
||||
{ .compatible = "qcom,qcm2290", },
|
||||
{ .compatible = "qcom,qcm6490", },
|
||||
{ .compatible = "qcom,qcs404", },
|
||||
{ .compatible = "qcom,qdu1000", },
|
||||
{ .compatible = "qcom,sa8155p" },
|
||||
@@ -176,7 +178,9 @@ static const struct of_device_id blocklist[] __initconst = {
|
||||
{ .compatible = "ti,omap3", },
|
||||
{ .compatible = "ti,am625", },
|
||||
{ .compatible = "ti,am62a7", },
|
||||
{ .compatible = "ti,am62p5", },
|
||||
|
||||
{ .compatible = "qcom,ipq6018", },
|
||||
{ .compatible = "qcom,ipq8064", },
|
||||
{ .compatible = "qcom,apq8064", },
|
||||
{ .compatible = "qcom,msm8974", },
|
||||
|
||||
@@ -1555,7 +1555,7 @@ static int cpufreq_online(unsigned int cpu)
|
||||
|
||||
/*
|
||||
* Register with the energy model before
|
||||
* sched_cpufreq_governor_change() is called, which will result
|
||||
* sugov_eas_rebuild_sd() is called, which will result
|
||||
* in rebuilding of the sched domains, which should only be done
|
||||
* once the energy model is properly initialized for the policy
|
||||
* first.
|
||||
|
||||
@@ -187,8 +187,7 @@ static ssize_t down_threshold_store(struct gov_attr_set *attr_set,
|
||||
ret = sscanf(buf, "%u", &input);
|
||||
|
||||
/* cannot be lower than 1 otherwise freq will not fall */
|
||||
if (ret != 1 || input < 1 || input > 100 ||
|
||||
input >= dbs_data->up_threshold)
|
||||
if (ret != 1 || input < 1 || input >= dbs_data->up_threshold)
|
||||
return -EINVAL;
|
||||
|
||||
cs_tuners->down_threshold = input;
|
||||
|
||||
@@ -131,23 +131,23 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
||||
len += sysfs_emit_at(buf, len, " From : To\n");
|
||||
len += sysfs_emit_at(buf, len, " : ");
|
||||
for (i = 0; i < stats->state_num; i++) {
|
||||
if (len >= PAGE_SIZE)
|
||||
if (len >= PAGE_SIZE - 1)
|
||||
break;
|
||||
len += sysfs_emit_at(buf, len, "%9u ", stats->freq_table[i]);
|
||||
}
|
||||
if (len >= PAGE_SIZE)
|
||||
return PAGE_SIZE;
|
||||
if (len >= PAGE_SIZE - 1)
|
||||
return PAGE_SIZE - 1;
|
||||
|
||||
len += sysfs_emit_at(buf, len, "\n");
|
||||
|
||||
for (i = 0; i < stats->state_num; i++) {
|
||||
if (len >= PAGE_SIZE)
|
||||
if (len >= PAGE_SIZE - 1)
|
||||
break;
|
||||
|
||||
len += sysfs_emit_at(buf, len, "%9u: ", stats->freq_table[i]);
|
||||
|
||||
for (j = 0; j < stats->state_num; j++) {
|
||||
if (len >= PAGE_SIZE)
|
||||
if (len >= PAGE_SIZE - 1)
|
||||
break;
|
||||
|
||||
if (pending)
|
||||
@@ -157,12 +157,12 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
||||
|
||||
len += sysfs_emit_at(buf, len, "%9u ", count);
|
||||
}
|
||||
if (len >= PAGE_SIZE)
|
||||
if (len >= PAGE_SIZE - 1)
|
||||
break;
|
||||
len += sysfs_emit_at(buf, len, "\n");
|
||||
}
|
||||
|
||||
if (len >= PAGE_SIZE) {
|
||||
if (len >= PAGE_SIZE - 1) {
|
||||
pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n");
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
|
||||
static DEFINE_MUTEX(userspace_mutex);
|
||||
struct userspace_policy {
|
||||
unsigned int is_managed;
|
||||
unsigned int setspeed;
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* cpufreq_set - set the CPU frequency
|
||||
@@ -28,19 +31,19 @@ static DEFINE_MUTEX(userspace_mutex);
|
||||
static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
struct userspace_policy *userspace = policy->governor_data;
|
||||
|
||||
pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
if (!per_cpu(cpu_is_managed, policy->cpu))
|
||||
mutex_lock(&userspace->mutex);
|
||||
if (!userspace->is_managed)
|
||||
goto err;
|
||||
|
||||
*setspeed = freq;
|
||||
userspace->setspeed = freq;
|
||||
|
||||
ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
|
||||
err:
|
||||
mutex_unlock(&userspace_mutex);
|
||||
mutex_unlock(&userspace->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -51,67 +54,74 @@ static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
|
||||
|
||||
static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed;
|
||||
struct userspace_policy *userspace;
|
||||
|
||||
setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL);
|
||||
if (!setspeed)
|
||||
userspace = kzalloc(sizeof(*userspace), GFP_KERNEL);
|
||||
if (!userspace)
|
||||
return -ENOMEM;
|
||||
|
||||
policy->governor_data = setspeed;
|
||||
mutex_init(&userspace->mutex);
|
||||
|
||||
policy->governor_data = userspace;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any routine that writes to the policy struct will hold the "rwsem" of
|
||||
* policy struct that means it is free to free "governor_data" here.
|
||||
*/
|
||||
static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
mutex_lock(&userspace_mutex);
|
||||
kfree(policy->governor_data);
|
||||
policy->governor_data = NULL;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
}
|
||||
|
||||
static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
struct userspace_policy *userspace = policy->governor_data;
|
||||
|
||||
BUG_ON(!policy->cur);
|
||||
pr_debug("started managing cpu %u\n", policy->cpu);
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
per_cpu(cpu_is_managed, policy->cpu) = 1;
|
||||
*setspeed = policy->cur;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
mutex_lock(&userspace->mutex);
|
||||
userspace->is_managed = 1;
|
||||
userspace->setspeed = policy->cur;
|
||||
mutex_unlock(&userspace->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
struct userspace_policy *userspace = policy->governor_data;
|
||||
|
||||
pr_debug("managing cpu %u stopped\n", policy->cpu);
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
per_cpu(cpu_is_managed, policy->cpu) = 0;
|
||||
*setspeed = 0;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
mutex_lock(&userspace->mutex);
|
||||
userspace->is_managed = 0;
|
||||
userspace->setspeed = 0;
|
||||
mutex_unlock(&userspace->mutex);
|
||||
}
|
||||
|
||||
static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
struct userspace_policy *userspace = policy->governor_data;
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
mutex_lock(&userspace->mutex);
|
||||
|
||||
pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
|
||||
policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
|
||||
policy->cpu, policy->min, policy->max, policy->cur, userspace->setspeed);
|
||||
|
||||
if (policy->max < *setspeed)
|
||||
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
|
||||
else if (policy->min > *setspeed)
|
||||
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
|
||||
if (policy->max < userspace->setspeed)
|
||||
__cpufreq_driver_target(policy, policy->max,
|
||||
CPUFREQ_RELATION_H);
|
||||
else if (policy->min > userspace->setspeed)
|
||||
__cpufreq_driver_target(policy, policy->min,
|
||||
CPUFREQ_RELATION_L);
|
||||
else
|
||||
__cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
|
||||
__cpufreq_driver_target(policy, userspace->setspeed,
|
||||
CPUFREQ_RELATION_L);
|
||||
|
||||
mutex_unlock(&userspace_mutex);
|
||||
mutex_unlock(&userspace->mutex);
|
||||
}
|
||||
|
||||
static struct cpufreq_governor cpufreq_gov_userspace = {
|
||||
|
||||
@@ -571,13 +571,9 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
|
||||
static inline void update_turbo_state(void)
|
||||
{
|
||||
u64 misc_en;
|
||||
struct cpudata *cpu;
|
||||
|
||||
cpu = all_cpu_data[0];
|
||||
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
|
||||
global.turbo_disabled =
|
||||
(misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
|
||||
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
|
||||
global.turbo_disabled = misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
|
||||
}
|
||||
|
||||
static int min_perf_pct_min(void)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/irq.h>
|
||||
@@ -378,10 +379,9 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
static u32 read_gpio(struct device_node *np)
|
||||
{
|
||||
const u32 *reg = of_get_property(np, "reg", NULL);
|
||||
u32 offset;
|
||||
u64 offset;
|
||||
|
||||
if (reg == NULL)
|
||||
if (of_property_read_reg(np, 0, &offset, NULL) < 0)
|
||||
return 0;
|
||||
/* That works for all keylargos but shall be fixed properly
|
||||
* some day... The problem is that it seems we can't rely
|
||||
@@ -389,7 +389,6 @@ static u32 read_gpio(struct device_node *np)
|
||||
* relative to the base of KeyLargo or to the base of the
|
||||
* GPIO space, and the device-tree doesn't help.
|
||||
*/
|
||||
offset = *reg;
|
||||
if (offset < KEYLARGO_GPIO_LEVELS0)
|
||||
offset += KEYLARGO_GPIO_LEVELS0;
|
||||
return offset;
|
||||
|
||||
@@ -30,6 +30,14 @@
|
||||
|
||||
#include <dt-bindings/arm/qcom,ids.h>
|
||||
|
||||
enum ipq806x_versions {
|
||||
IPQ8062_VERSION = 0,
|
||||
IPQ8064_VERSION,
|
||||
IPQ8065_VERSION,
|
||||
};
|
||||
|
||||
#define IPQ6000_VERSION BIT(2)
|
||||
|
||||
struct qcom_cpufreq_drv;
|
||||
|
||||
struct qcom_cpufreq_match_data {
|
||||
@@ -40,16 +48,38 @@ struct qcom_cpufreq_match_data {
|
||||
const char **genpd_names;
|
||||
};
|
||||
|
||||
struct qcom_cpufreq_drv_cpu {
|
||||
int opp_token;
|
||||
};
|
||||
|
||||
struct qcom_cpufreq_drv {
|
||||
int *opp_tokens;
|
||||
u32 versions;
|
||||
const struct qcom_cpufreq_match_data *data;
|
||||
struct qcom_cpufreq_drv_cpu cpus[];
|
||||
};
|
||||
|
||||
static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
|
||||
|
||||
static int qcom_cpufreq_simple_get_version(struct device *cpu_dev,
|
||||
struct nvmem_cell *speedbin_nvmem,
|
||||
char **pvs_name,
|
||||
struct qcom_cpufreq_drv *drv)
|
||||
{
|
||||
u8 *speedbin;
|
||||
|
||||
*pvs_name = NULL;
|
||||
speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
|
||||
if (IS_ERR(speedbin))
|
||||
return PTR_ERR(speedbin);
|
||||
|
||||
dev_dbg(cpu_dev, "speedbin: %d\n", *speedbin);
|
||||
drv->versions = 1 << *speedbin;
|
||||
kfree(speedbin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void get_krait_bin_format_a(struct device *cpu_dev,
|
||||
int *speed, int *pvs, int *pvs_ver,
|
||||
int *speed, int *pvs,
|
||||
u8 *buf)
|
||||
{
|
||||
u32 pte_efuse;
|
||||
@@ -180,8 +210,7 @@ static int qcom_cpufreq_krait_name_version(struct device *cpu_dev,
|
||||
|
||||
switch (len) {
|
||||
case 4:
|
||||
get_krait_bin_format_a(cpu_dev, &speed, &pvs, &pvs_ver,
|
||||
speedbin);
|
||||
get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin);
|
||||
break;
|
||||
case 8:
|
||||
get_krait_bin_format_b(cpu_dev, &speed, &pvs, &pvs_ver,
|
||||
@@ -203,6 +232,114 @@ len_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_cpufreq_ipq8064_name_version(struct device *cpu_dev,
|
||||
struct nvmem_cell *speedbin_nvmem,
|
||||
char **pvs_name,
|
||||
struct qcom_cpufreq_drv *drv)
|
||||
{
|
||||
int speed = 0, pvs = 0;
|
||||
int msm_id, ret = 0;
|
||||
u8 *speedbin;
|
||||
size_t len;
|
||||
|
||||
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
|
||||
if (IS_ERR(speedbin))
|
||||
return PTR_ERR(speedbin);
|
||||
|
||||
if (len != 4) {
|
||||
dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n");
|
||||
ret = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
get_krait_bin_format_a(cpu_dev, &speed, &pvs, speedbin);
|
||||
|
||||
ret = qcom_smem_get_soc_id(&msm_id);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
switch (msm_id) {
|
||||
case QCOM_ID_IPQ8062:
|
||||
drv->versions = BIT(IPQ8062_VERSION);
|
||||
break;
|
||||
case QCOM_ID_IPQ8064:
|
||||
case QCOM_ID_IPQ8066:
|
||||
case QCOM_ID_IPQ8068:
|
||||
drv->versions = BIT(IPQ8064_VERSION);
|
||||
break;
|
||||
case QCOM_ID_IPQ8065:
|
||||
case QCOM_ID_IPQ8069:
|
||||
drv->versions = BIT(IPQ8065_VERSION);
|
||||
break;
|
||||
default:
|
||||
dev_err(cpu_dev,
|
||||
"SoC ID %u is not part of IPQ8064 family, limiting to 1.0GHz!\n",
|
||||
msm_id);
|
||||
drv->versions = BIT(IPQ8062_VERSION);
|
||||
break;
|
||||
}
|
||||
|
||||
/* IPQ8064 speed is never fused. Only pvs values are fused. */
|
||||
snprintf(*pvs_name, sizeof("speed0-pvsXX"), "speed0-pvs%d", pvs);
|
||||
|
||||
exit:
|
||||
kfree(speedbin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_cpufreq_ipq6018_name_version(struct device *cpu_dev,
|
||||
struct nvmem_cell *speedbin_nvmem,
|
||||
char **pvs_name,
|
||||
struct qcom_cpufreq_drv *drv)
|
||||
{
|
||||
u32 msm_id;
|
||||
int ret;
|
||||
u8 *speedbin;
|
||||
*pvs_name = NULL;
|
||||
|
||||
ret = qcom_smem_get_soc_id(&msm_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
|
||||
if (IS_ERR(speedbin))
|
||||
return PTR_ERR(speedbin);
|
||||
|
||||
switch (msm_id) {
|
||||
case QCOM_ID_IPQ6005:
|
||||
case QCOM_ID_IPQ6010:
|
||||
case QCOM_ID_IPQ6018:
|
||||
case QCOM_ID_IPQ6028:
|
||||
/* Fuse Value Freq BIT to set
|
||||
* ---------------------------------
|
||||
* 2’b0 No Limit BIT(0)
|
||||
* 2’b1 1.5 GHz BIT(1)
|
||||
*/
|
||||
drv->versions = 1 << (unsigned int)(*speedbin);
|
||||
break;
|
||||
case QCOM_ID_IPQ6000:
|
||||
/*
|
||||
* IPQ6018 family only has one bit to advertise the CPU
|
||||
* speed-bin, but that is not enough for IPQ6000 which
|
||||
* is only rated up to 1.2GHz.
|
||||
* So for IPQ6000 manually set BIT(2) based on SMEM ID.
|
||||
*/
|
||||
drv->versions = IPQ6000_VERSION;
|
||||
break;
|
||||
default:
|
||||
dev_err(cpu_dev,
|
||||
"SoC ID %u is not part of IPQ6018 family, limiting to 1.2GHz!\n",
|
||||
msm_id);
|
||||
drv->versions = IPQ6000_VERSION;
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(speedbin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *generic_genpd_names[] = { "perf", NULL };
|
||||
|
||||
static const struct qcom_cpufreq_match_data match_data_kryo = {
|
||||
.get_version = qcom_cpufreq_kryo_name_version,
|
||||
};
|
||||
@@ -211,12 +348,25 @@ static const struct qcom_cpufreq_match_data match_data_krait = {
|
||||
.get_version = qcom_cpufreq_krait_name_version,
|
||||
};
|
||||
|
||||
static const struct qcom_cpufreq_match_data match_data_msm8909 = {
|
||||
.get_version = qcom_cpufreq_simple_get_version,
|
||||
.genpd_names = generic_genpd_names,
|
||||
};
|
||||
|
||||
static const char *qcs404_genpd_names[] = { "cpr", NULL };
|
||||
|
||||
static const struct qcom_cpufreq_match_data match_data_qcs404 = {
|
||||
.genpd_names = qcs404_genpd_names,
|
||||
};
|
||||
|
||||
static const struct qcom_cpufreq_match_data match_data_ipq6018 = {
|
||||
.get_version = qcom_cpufreq_ipq6018_name_version,
|
||||
};
|
||||
|
||||
static const struct qcom_cpufreq_match_data match_data_ipq8064 = {
|
||||
.get_version = qcom_cpufreq_ipq8064_name_version,
|
||||
};
|
||||
|
||||
static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_cpufreq_drv *drv;
|
||||
@@ -237,48 +387,39 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
if (!np)
|
||||
return -ENOENT;
|
||||
|
||||
ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu");
|
||||
ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu") ||
|
||||
of_device_is_compatible(np, "operating-points-v2-krait-cpu");
|
||||
if (!ret) {
|
||||
of_node_put(np);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
drv = kzalloc(sizeof(*drv), GFP_KERNEL);
|
||||
drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()),
|
||||
GFP_KERNEL);
|
||||
if (!drv)
|
||||
return -ENOMEM;
|
||||
|
||||
match = pdev->dev.platform_data;
|
||||
drv->data = match->data;
|
||||
if (!drv->data) {
|
||||
ret = -ENODEV;
|
||||
goto free_drv;
|
||||
}
|
||||
if (!drv->data)
|
||||
return -ENODEV;
|
||||
|
||||
if (drv->data->get_version) {
|
||||
speedbin_nvmem = of_nvmem_cell_get(np, NULL);
|
||||
if (IS_ERR(speedbin_nvmem)) {
|
||||
ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
|
||||
"Could not get nvmem cell\n");
|
||||
goto free_drv;
|
||||
}
|
||||
if (IS_ERR(speedbin_nvmem))
|
||||
return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
|
||||
"Could not get nvmem cell\n");
|
||||
|
||||
ret = drv->data->get_version(cpu_dev,
|
||||
speedbin_nvmem, &pvs_name, drv);
|
||||
if (ret) {
|
||||
nvmem_cell_put(speedbin_nvmem);
|
||||
goto free_drv;
|
||||
return ret;
|
||||
}
|
||||
nvmem_cell_put(speedbin_nvmem);
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens),
|
||||
GFP_KERNEL);
|
||||
if (!drv->opp_tokens) {
|
||||
ret = -ENOMEM;
|
||||
goto free_drv;
|
||||
}
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct dev_pm_opp_config config = {
|
||||
.supported_hw = NULL,
|
||||
@@ -304,9 +445,9 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (config.supported_hw || config.genpd_names) {
|
||||
drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config);
|
||||
if (drv->opp_tokens[cpu] < 0) {
|
||||
ret = drv->opp_tokens[cpu];
|
||||
drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
|
||||
if (drv->cpus[cpu].opp_token < 0) {
|
||||
ret = drv->cpus[cpu].opp_token;
|
||||
dev_err(cpu_dev, "Failed to set OPP config\n");
|
||||
goto free_opp;
|
||||
}
|
||||
@@ -325,11 +466,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
||||
|
||||
free_opp:
|
||||
for_each_possible_cpu(cpu)
|
||||
dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
|
||||
kfree(drv->opp_tokens);
|
||||
free_drv:
|
||||
kfree(drv);
|
||||
|
||||
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -341,10 +478,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
|
||||
platform_device_unregister(cpufreq_dt_pdev);
|
||||
|
||||
for_each_possible_cpu(cpu)
|
||||
dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
|
||||
|
||||
kfree(drv->opp_tokens);
|
||||
kfree(drv);
|
||||
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
|
||||
}
|
||||
|
||||
static struct platform_driver qcom_cpufreq_driver = {
|
||||
@@ -357,9 +491,11 @@ static struct platform_driver qcom_cpufreq_driver = {
|
||||
|
||||
static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
|
||||
{ .compatible = "qcom,apq8096", .data = &match_data_kryo },
|
||||
{ .compatible = "qcom,msm8909", .data = &match_data_msm8909 },
|
||||
{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
|
||||
{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
|
||||
{ .compatible = "qcom,ipq8064", .data = &match_data_krait },
|
||||
{ .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 },
|
||||
{ .compatible = "qcom,ipq8064", .data = &match_data_ipq8064 },
|
||||
{ .compatible = "qcom,apq8064", .data = &match_data_krait },
|
||||
{ .compatible = "qcom,msm8974", .data = &match_data_krait },
|
||||
{ .compatible = "qcom,msm8960", .data = &match_data_krait },
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
@@ -21,10 +20,11 @@
|
||||
|
||||
#define KHZ 1000
|
||||
#define REF_CLK_MHZ 408 /* 408 MHz */
|
||||
#define US_DELAY 500
|
||||
#define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ)
|
||||
#define MAX_CNT ~0U
|
||||
|
||||
#define MAX_DELTA_KHZ 115200
|
||||
|
||||
#define NDIV_MASK 0x1FF
|
||||
|
||||
#define CORE_OFFSET(cpu) (cpu * 8)
|
||||
@@ -39,6 +39,12 @@
|
||||
/* cpufreq transisition latency */
|
||||
#define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */
|
||||
|
||||
struct tegra_cpu_data {
|
||||
u32 cpuid;
|
||||
u32 clusterid;
|
||||
void __iomem *freq_core_reg;
|
||||
};
|
||||
|
||||
struct tegra_cpu_ctr {
|
||||
u32 cpu;
|
||||
u32 coreclk_cnt, last_coreclk_cnt;
|
||||
@@ -62,6 +68,7 @@ struct tegra_cpufreq_soc {
|
||||
int maxcpus_per_cluster;
|
||||
unsigned int num_clusters;
|
||||
phys_addr_t actmon_cntr_base;
|
||||
u32 refclk_delta_min;
|
||||
};
|
||||
|
||||
struct tegra194_cpufreq_data {
|
||||
@@ -69,6 +76,7 @@ struct tegra194_cpufreq_data {
|
||||
struct cpufreq_frequency_table **bpmp_luts;
|
||||
const struct tegra_cpufreq_soc *soc;
|
||||
bool icc_dram_bw_scaling;
|
||||
struct tegra_cpu_data *cpu_data;
|
||||
};
|
||||
|
||||
static struct workqueue_struct *read_counters_wq;
|
||||
@@ -116,14 +124,8 @@ static void tegra234_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid)
|
||||
static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
|
||||
{
|
||||
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
void __iomem *freq_core_reg;
|
||||
u64 mpidr_id;
|
||||
|
||||
/* use physical id to get address of per core frequency register */
|
||||
mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
|
||||
freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
|
||||
|
||||
*ndiv = readl(freq_core_reg) & NDIV_MASK;
|
||||
*ndiv = readl(data->cpu_data[cpu].freq_core_reg) & NDIV_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -131,19 +133,10 @@ static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
|
||||
static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
|
||||
{
|
||||
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
void __iomem *freq_core_reg;
|
||||
u32 cpu, cpuid, clusterid;
|
||||
u64 mpidr_id;
|
||||
u32 cpu;
|
||||
|
||||
for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) {
|
||||
data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
|
||||
|
||||
/* use physical id to get address of per core frequency register */
|
||||
mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
|
||||
freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
|
||||
|
||||
writel(ndiv, freq_core_reg);
|
||||
}
|
||||
for_each_cpu(cpu, policy->cpus)
|
||||
writel(ndiv, data->cpu_data[cpu].freq_core_reg);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -157,19 +150,35 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c)
|
||||
{
|
||||
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
void __iomem *actmon_reg;
|
||||
u32 cpuid, clusterid;
|
||||
u32 delta_refcnt;
|
||||
int cnt = 0;
|
||||
u64 val;
|
||||
|
||||
data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid);
|
||||
actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid);
|
||||
actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid,
|
||||
data->cpu_data[c->cpu].cpuid);
|
||||
|
||||
val = readq(actmon_reg);
|
||||
c->last_refclk_cnt = upper_32_bits(val);
|
||||
c->last_coreclk_cnt = lower_32_bits(val);
|
||||
udelay(US_DELAY);
|
||||
val = readq(actmon_reg);
|
||||
c->refclk_cnt = upper_32_bits(val);
|
||||
c->coreclk_cnt = lower_32_bits(val);
|
||||
|
||||
/*
|
||||
* The sampling window is based on the minimum number of reference
|
||||
* clock cycles which is known to give a stable value of CPU frequency.
|
||||
*/
|
||||
do {
|
||||
val = readq(actmon_reg);
|
||||
c->refclk_cnt = upper_32_bits(val);
|
||||
c->coreclk_cnt = lower_32_bits(val);
|
||||
if (c->refclk_cnt < c->last_refclk_cnt)
|
||||
delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt);
|
||||
else
|
||||
delta_refcnt = c->refclk_cnt - c->last_refclk_cnt;
|
||||
if (++cnt >= 0xFFFF) {
|
||||
pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n",
|
||||
c->cpu, delta_refcnt, cnt);
|
||||
break;
|
||||
}
|
||||
} while (delta_refcnt < data->soc->refclk_delta_min);
|
||||
}
|
||||
|
||||
static struct tegra_cpufreq_ops tegra234_cpufreq_ops = {
|
||||
@@ -184,6 +193,7 @@ static const struct tegra_cpufreq_soc tegra234_cpufreq_soc = {
|
||||
.actmon_cntr_base = 0x9000,
|
||||
.maxcpus_per_cluster = 4,
|
||||
.num_clusters = 3,
|
||||
.refclk_delta_min = 16000,
|
||||
};
|
||||
|
||||
static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = {
|
||||
@@ -191,6 +201,7 @@ static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = {
|
||||
.actmon_cntr_base = 0x4000,
|
||||
.maxcpus_per_cluster = 8,
|
||||
.num_clusters = 1,
|
||||
.refclk_delta_min = 16000,
|
||||
};
|
||||
|
||||
static void tegra194_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid)
|
||||
@@ -231,15 +242,33 @@ static inline u32 map_ndiv_to_freq(struct mrq_cpu_ndiv_limits_response
|
||||
|
||||
static void tegra194_read_counters(struct tegra_cpu_ctr *c)
|
||||
{
|
||||
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
u32 delta_refcnt;
|
||||
int cnt = 0;
|
||||
u64 val;
|
||||
|
||||
val = read_freq_feedback();
|
||||
c->last_refclk_cnt = lower_32_bits(val);
|
||||
c->last_coreclk_cnt = upper_32_bits(val);
|
||||
udelay(US_DELAY);
|
||||
val = read_freq_feedback();
|
||||
c->refclk_cnt = lower_32_bits(val);
|
||||
c->coreclk_cnt = upper_32_bits(val);
|
||||
|
||||
/*
|
||||
* The sampling window is based on the minimum number of reference
|
||||
* clock cycles which is known to give a stable value of CPU frequency.
|
||||
*/
|
||||
do {
|
||||
val = read_freq_feedback();
|
||||
c->refclk_cnt = lower_32_bits(val);
|
||||
c->coreclk_cnt = upper_32_bits(val);
|
||||
if (c->refclk_cnt < c->last_refclk_cnt)
|
||||
delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt);
|
||||
else
|
||||
delta_refcnt = c->refclk_cnt - c->last_refclk_cnt;
|
||||
if (++cnt >= 0xFFFF) {
|
||||
pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n",
|
||||
c->cpu, delta_refcnt, cnt);
|
||||
break;
|
||||
}
|
||||
} while (delta_refcnt < data->soc->refclk_delta_min);
|
||||
}
|
||||
|
||||
static void tegra_read_counters(struct work_struct *work)
|
||||
@@ -297,9 +326,8 @@ static unsigned int tegra194_calculate_speed(u32 cpu)
|
||||
u32 rate_mhz;
|
||||
|
||||
/*
|
||||
* udelay() is required to reconstruct cpu frequency over an
|
||||
* observation window. Using workqueue to call udelay() with
|
||||
* interrupts enabled.
|
||||
* Reconstruct cpu frequency over an observation/sampling window.
|
||||
* Using workqueue to keep interrupts enabled during the interval.
|
||||
*/
|
||||
read_counters_work.c.cpu = cpu;
|
||||
INIT_WORK_ONSTACK(&read_counters_work.work, tegra_read_counters);
|
||||
@@ -357,19 +385,17 @@ static void tegra194_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
|
||||
static unsigned int tegra194_get_speed(u32 cpu)
|
||||
{
|
||||
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
u32 clusterid = data->cpu_data[cpu].clusterid;
|
||||
struct cpufreq_frequency_table *pos;
|
||||
u32 cpuid, clusterid;
|
||||
unsigned int rate;
|
||||
u64 ndiv;
|
||||
int ret;
|
||||
|
||||
data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
|
||||
|
||||
/* reconstruct actual cpu freq using counters */
|
||||
rate = tegra194_calculate_speed(cpu);
|
||||
|
||||
/* get last written ndiv value */
|
||||
ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv);
|
||||
ret = data->soc->ops->get_cpu_ndiv(cpu, data->cpu_data[cpu].cpuid, clusterid, &ndiv);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
return rate;
|
||||
|
||||
@@ -383,9 +409,9 @@ static unsigned int tegra194_get_speed(u32 cpu)
|
||||
if (pos->driver_data != ndiv)
|
||||
continue;
|
||||
|
||||
if (abs(pos->frequency - rate) > 115200) {
|
||||
pr_warn("cpufreq: cpu%d,cur:%u,set:%u,set ndiv:%llu\n",
|
||||
cpu, rate, pos->frequency, ndiv);
|
||||
if (abs(pos->frequency - rate) > MAX_DELTA_KHZ) {
|
||||
pr_warn("cpufreq: cpu%d,cur:%u,set:%u,delta:%d,set ndiv:%llu\n",
|
||||
cpu, rate, pos->frequency, abs(rate - pos->frequency), ndiv);
|
||||
} else {
|
||||
rate = pos->frequency;
|
||||
}
|
||||
@@ -450,6 +476,8 @@ static int tegra_cpufreq_init_cpufreq_table(struct cpufreq_policy *policy,
|
||||
if (IS_ERR(opp))
|
||||
continue;
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
ret = dev_pm_opp_enable(cpu_dev, pos->frequency * KHZ);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -473,13 +501,12 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
int maxcpus_per_cluster = data->soc->maxcpus_per_cluster;
|
||||
u32 clusterid = data->cpu_data[policy->cpu].clusterid;
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
struct cpufreq_frequency_table *bpmp_lut;
|
||||
u32 start_cpu, cpu;
|
||||
u32 clusterid;
|
||||
int ret;
|
||||
|
||||
data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid);
|
||||
if (clusterid >= data->soc->num_clusters || !data->bpmp_luts[clusterid])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -578,6 +605,7 @@ static const struct tegra_cpufreq_soc tegra194_cpufreq_soc = {
|
||||
.ops = &tegra194_cpufreq_ops,
|
||||
.maxcpus_per_cluster = 2,
|
||||
.num_clusters = 4,
|
||||
.refclk_delta_min = 16000,
|
||||
};
|
||||
|
||||
static void tegra194_cpufreq_free_resources(void)
|
||||
@@ -657,6 +685,28 @@ tegra_cpufreq_bpmp_read_lut(struct platform_device *pdev, struct tegra_bpmp *bpm
|
||||
return freq_table;
|
||||
}
|
||||
|
||||
static int tegra194_cpufreq_store_physids(unsigned int cpu, struct tegra194_cpufreq_data *data)
|
||||
{
|
||||
int num_cpus = data->soc->maxcpus_per_cluster * data->soc->num_clusters;
|
||||
u32 cpuid, clusterid;
|
||||
u64 mpidr_id;
|
||||
|
||||
if (cpu > (num_cpus - 1)) {
|
||||
pr_err("cpufreq: wrong num of cpus or clusters in soc data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
|
||||
|
||||
mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
|
||||
|
||||
data->cpu_data[cpu].cpuid = cpuid;
|
||||
data->cpu_data[cpu].clusterid = clusterid;
|
||||
data->cpu_data[cpu].freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra194_cpufreq_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct tegra_cpufreq_soc *soc;
|
||||
@@ -664,6 +714,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
|
||||
struct tegra_bpmp *bpmp;
|
||||
struct device *cpu_dev;
|
||||
int err, i;
|
||||
u32 cpu;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
@@ -671,7 +722,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
|
||||
|
||||
soc = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters) {
|
||||
if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters && soc->refclk_delta_min) {
|
||||
data->soc = soc;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "soc data missing\n");
|
||||
@@ -690,6 +741,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(data->regs);
|
||||
}
|
||||
|
||||
data->cpu_data = devm_kcalloc(&pdev->dev, data->soc->num_clusters *
|
||||
data->soc->maxcpus_per_cluster,
|
||||
sizeof(*data->cpu_data), GFP_KERNEL);
|
||||
if (!data->cpu_data)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
bpmp = tegra_bpmp_get(&pdev->dev);
|
||||
@@ -711,6 +768,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
err = tegra194_cpufreq_store_physids(cpu, data);
|
||||
if (err)
|
||||
goto err_free_res;
|
||||
}
|
||||
|
||||
tegra194_cpufreq_driver.driver_data = data;
|
||||
|
||||
/* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */
|
||||
|
||||
@@ -338,6 +338,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
|
||||
{ .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
|
||||
{ .compatible = "ti,am625", .data = &am625_soc_data, },
|
||||
{ .compatible = "ti,am62a7", .data = &am625_soc_data, },
|
||||
{ .compatible = "ti,am62p5", .data = &am625_soc_data, },
|
||||
/* legacy */
|
||||
{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
|
||||
{ .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
|
||||
|
||||
@@ -88,7 +88,7 @@ static unsigned long find_available_min_freq(struct devfreq *devfreq)
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long min_freq = 0;
|
||||
|
||||
opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq);
|
||||
opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &min_freq, 0);
|
||||
if (IS_ERR(opp))
|
||||
min_freq = 0;
|
||||
else
|
||||
@@ -102,7 +102,7 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long max_freq = ULONG_MAX;
|
||||
|
||||
opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq);
|
||||
opp = dev_pm_opp_find_freq_floor_indexed(devfreq->dev.parent, &max_freq, 0);
|
||||
if (IS_ERR(opp))
|
||||
max_freq = 0;
|
||||
else
|
||||
@@ -196,7 +196,7 @@ static int set_freq_table(struct devfreq *devfreq)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
|
||||
opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
|
||||
opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &freq, 0);
|
||||
if (IS_ERR(opp)) {
|
||||
devm_kfree(devfreq->dev.parent, devfreq->freq_table);
|
||||
return PTR_ERR(opp);
|
||||
@@ -2036,18 +2036,18 @@ struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
|
||||
|
||||
if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
|
||||
/* The freq is an upper bound. opp should be lower */
|
||||
opp = dev_pm_opp_find_freq_floor(dev, freq);
|
||||
opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0);
|
||||
|
||||
/* If not available, use the closest opp */
|
||||
if (opp == ERR_PTR(-ERANGE))
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, freq);
|
||||
opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0);
|
||||
} else {
|
||||
/* The freq is an lower bound. opp should be higher */
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, freq);
|
||||
opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0);
|
||||
|
||||
/* If not available, use the closest opp */
|
||||
if (opp == ERR_PTR(-ERANGE))
|
||||
opp = dev_pm_opp_find_freq_floor(dev, freq);
|
||||
opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0);
|
||||
}
|
||||
|
||||
return opp;
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/devfreq-event.h>
|
||||
@@ -507,7 +507,6 @@ static int of_get_devfreq_events(struct device_node *np,
|
||||
struct device *dev = info->dev;
|
||||
struct device_node *events_np, *node;
|
||||
int i, j, count;
|
||||
const struct of_device_id *of_id;
|
||||
int ret;
|
||||
|
||||
events_np = of_get_child_by_name(np, "events");
|
||||
@@ -525,13 +524,7 @@ static int of_get_devfreq_events(struct device_node *np,
|
||||
}
|
||||
info->num_events = count;
|
||||
|
||||
of_id = of_match_device(exynos_ppmu_id_match, dev);
|
||||
if (of_id)
|
||||
info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
|
||||
else {
|
||||
of_node_put(events_np);
|
||||
return -EINVAL;
|
||||
}
|
||||
info->ppmu_type = (enum exynos_ppmu_type)device_get_match_data(dev);
|
||||
|
||||
j = 0;
|
||||
for_each_child_of_node(events_np, node) {
|
||||
|
||||
@@ -16,30 +16,71 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/seqlock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <soc/rockchip/rockchip_grf.h>
|
||||
#include <soc/rockchip/rk3399_grf.h>
|
||||
#include <soc/rockchip/rk3568_grf.h>
|
||||
#include <soc/rockchip/rk3588_grf.h>
|
||||
|
||||
#define RK3399_DMC_NUM_CH 2
|
||||
#define DMC_MAX_CHANNELS 4
|
||||
|
||||
#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16)
|
||||
|
||||
/* DDRMON_CTRL */
|
||||
#define DDRMON_CTRL 0x04
|
||||
#define CLR_DDRMON_CTRL (0x1f0000 << 0)
|
||||
#define LPDDR4_EN (0x10001 << 4)
|
||||
#define HARDWARE_EN (0x10001 << 3)
|
||||
#define LPDDR3_EN (0x10001 << 2)
|
||||
#define SOFTWARE_EN (0x10001 << 1)
|
||||
#define SOFTWARE_DIS (0x10000 << 1)
|
||||
#define TIME_CNT_EN (0x10001 << 0)
|
||||
#define DDRMON_CTRL_DDR4 BIT(5)
|
||||
#define DDRMON_CTRL_LPDDR4 BIT(4)
|
||||
#define DDRMON_CTRL_HARDWARE_EN BIT(3)
|
||||
#define DDRMON_CTRL_LPDDR23 BIT(2)
|
||||
#define DDRMON_CTRL_SOFTWARE_EN BIT(1)
|
||||
#define DDRMON_CTRL_TIMER_CNT_EN BIT(0)
|
||||
#define DDRMON_CTRL_DDR_TYPE_MASK (DDRMON_CTRL_DDR4 | \
|
||||
DDRMON_CTRL_LPDDR4 | \
|
||||
DDRMON_CTRL_LPDDR23)
|
||||
|
||||
#define DDRMON_CH0_WR_NUM 0x20
|
||||
#define DDRMON_CH0_RD_NUM 0x24
|
||||
#define DDRMON_CH0_COUNT_NUM 0x28
|
||||
#define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
|
||||
#define DDRMON_CH1_COUNT_NUM 0x3c
|
||||
#define DDRMON_CH1_DFI_ACCESS_NUM 0x40
|
||||
|
||||
struct dmc_usage {
|
||||
u32 access;
|
||||
u32 total;
|
||||
#define PERF_EVENT_CYCLES 0x0
|
||||
#define PERF_EVENT_READ_BYTES 0x1
|
||||
#define PERF_EVENT_WRITE_BYTES 0x2
|
||||
#define PERF_EVENT_READ_BYTES0 0x3
|
||||
#define PERF_EVENT_WRITE_BYTES0 0x4
|
||||
#define PERF_EVENT_READ_BYTES1 0x5
|
||||
#define PERF_EVENT_WRITE_BYTES1 0x6
|
||||
#define PERF_EVENT_READ_BYTES2 0x7
|
||||
#define PERF_EVENT_WRITE_BYTES2 0x8
|
||||
#define PERF_EVENT_READ_BYTES3 0x9
|
||||
#define PERF_EVENT_WRITE_BYTES3 0xa
|
||||
#define PERF_EVENT_BYTES 0xb
|
||||
#define PERF_ACCESS_TYPE_MAX 0xc
|
||||
|
||||
/**
|
||||
* struct dmc_count_channel - structure to hold counter values from the DDR controller
|
||||
* @access: Number of read and write accesses
|
||||
* @clock_cycles: DDR clock cycles
|
||||
* @read_access: number of read accesses
|
||||
* @write_access: number of write accesses
|
||||
*/
|
||||
struct dmc_count_channel {
|
||||
u64 access;
|
||||
u64 clock_cycles;
|
||||
u64 read_access;
|
||||
u64 write_access;
|
||||
};
|
||||
|
||||
struct dmc_count {
|
||||
struct dmc_count_channel c[DMC_MAX_CHANNELS];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -49,98 +90,157 @@ struct dmc_usage {
|
||||
*/
|
||||
struct rockchip_dfi {
|
||||
struct devfreq_event_dev *edev;
|
||||
struct devfreq_event_desc *desc;
|
||||
struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
|
||||
struct devfreq_event_desc desc;
|
||||
struct dmc_count last_event_count;
|
||||
|
||||
struct dmc_count last_perf_count;
|
||||
struct dmc_count total_count;
|
||||
seqlock_t count_seqlock; /* protects last_perf_count and total_count */
|
||||
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
struct regmap *regmap_pmu;
|
||||
struct clk *clk;
|
||||
int usecount;
|
||||
struct mutex mutex;
|
||||
u32 ddr_type;
|
||||
unsigned int channel_mask;
|
||||
unsigned int max_channels;
|
||||
enum cpuhp_state cpuhp_state;
|
||||
struct hlist_node node;
|
||||
struct pmu pmu;
|
||||
struct hrtimer timer;
|
||||
unsigned int cpu;
|
||||
int active_events;
|
||||
int burst_len;
|
||||
int buswidth[DMC_MAX_CHANNELS];
|
||||
int ddrmon_stride;
|
||||
bool ddrmon_ctrl_single;
|
||||
};
|
||||
|
||||
static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
|
||||
static int rockchip_dfi_enable(struct rockchip_dfi *dfi)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
void __iomem *dfi_regs = info->regs;
|
||||
u32 val;
|
||||
u32 ddr_type;
|
||||
void __iomem *dfi_regs = dfi->regs;
|
||||
int i, ret = 0;
|
||||
|
||||
/* get ddr type */
|
||||
regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
|
||||
ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
|
||||
RK3399_PMUGRF_DDRTYPE_MASK;
|
||||
mutex_lock(&dfi->mutex);
|
||||
|
||||
/* clear DDRMON_CTRL setting */
|
||||
writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
|
||||
dfi->usecount++;
|
||||
if (dfi->usecount > 1)
|
||||
goto out;
|
||||
|
||||
/* set ddr type to dfi */
|
||||
if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3)
|
||||
writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
|
||||
else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4)
|
||||
writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
|
||||
|
||||
/* enable count, use software mode */
|
||||
writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
|
||||
}
|
||||
|
||||
static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
void __iomem *dfi_regs = info->regs;
|
||||
|
||||
writel_relaxed(SOFTWARE_DIS, dfi_regs + DDRMON_CTRL);
|
||||
}
|
||||
|
||||
static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
u32 tmp, max = 0;
|
||||
u32 i, busier_ch = 0;
|
||||
void __iomem *dfi_regs = info->regs;
|
||||
|
||||
rockchip_dfi_stop_hardware_counter(edev);
|
||||
|
||||
/* Find out which channel is busier */
|
||||
for (i = 0; i < RK3399_DMC_NUM_CH; i++) {
|
||||
info->ch_usage[i].access = readl_relaxed(dfi_regs +
|
||||
DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4;
|
||||
info->ch_usage[i].total = readl_relaxed(dfi_regs +
|
||||
DDRMON_CH0_COUNT_NUM + i * 20);
|
||||
tmp = info->ch_usage[i].access;
|
||||
if (tmp > max) {
|
||||
busier_ch = i;
|
||||
max = tmp;
|
||||
}
|
||||
}
|
||||
rockchip_dfi_start_hardware_counter(edev);
|
||||
|
||||
return busier_ch;
|
||||
}
|
||||
|
||||
static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
|
||||
rockchip_dfi_stop_hardware_counter(edev);
|
||||
clk_disable_unprepare(info->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(info->clk);
|
||||
ret = clk_prepare_enable(dfi->clk);
|
||||
if (ret) {
|
||||
dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
|
||||
return ret;
|
||||
dev_err(&dfi->edev->dev, "failed to enable dfi clk: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rockchip_dfi_start_hardware_counter(edev);
|
||||
for (i = 0; i < dfi->max_channels; i++) {
|
||||
u32 ctrl = 0;
|
||||
|
||||
if (!(dfi->channel_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
/* clear DDRMON_CTRL setting */
|
||||
writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_TIMER_CNT_EN |
|
||||
DDRMON_CTRL_SOFTWARE_EN | DDRMON_CTRL_HARDWARE_EN),
|
||||
dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
|
||||
|
||||
/* set ddr type to dfi */
|
||||
switch (dfi->ddr_type) {
|
||||
case ROCKCHIP_DDRTYPE_LPDDR2:
|
||||
case ROCKCHIP_DDRTYPE_LPDDR3:
|
||||
ctrl = DDRMON_CTRL_LPDDR23;
|
||||
break;
|
||||
case ROCKCHIP_DDRTYPE_LPDDR4:
|
||||
case ROCKCHIP_DDRTYPE_LPDDR4X:
|
||||
ctrl = DDRMON_CTRL_LPDDR4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writel_relaxed(HIWORD_UPDATE(ctrl, DDRMON_CTRL_DDR_TYPE_MASK),
|
||||
dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
|
||||
|
||||
/* enable count, use software mode */
|
||||
writel_relaxed(HIWORD_UPDATE(DDRMON_CTRL_SOFTWARE_EN, DDRMON_CTRL_SOFTWARE_EN),
|
||||
dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
|
||||
|
||||
if (dfi->ddrmon_ctrl_single)
|
||||
break;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&dfi->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_dfi_disable(struct rockchip_dfi *dfi)
|
||||
{
|
||||
void __iomem *dfi_regs = dfi->regs;
|
||||
int i;
|
||||
|
||||
mutex_lock(&dfi->mutex);
|
||||
|
||||
dfi->usecount--;
|
||||
|
||||
WARN_ON_ONCE(dfi->usecount < 0);
|
||||
|
||||
if (dfi->usecount > 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < dfi->max_channels; i++) {
|
||||
if (!(dfi->channel_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
writel_relaxed(HIWORD_UPDATE(0, DDRMON_CTRL_SOFTWARE_EN),
|
||||
dfi_regs + i * dfi->ddrmon_stride + DDRMON_CTRL);
|
||||
|
||||
if (dfi->ddrmon_ctrl_single)
|
||||
break;
|
||||
}
|
||||
|
||||
clk_disable_unprepare(dfi->clk);
|
||||
out:
|
||||
mutex_unlock(&dfi->mutex);
|
||||
}
|
||||
|
||||
static void rockchip_dfi_read_counters(struct rockchip_dfi *dfi, struct dmc_count *res)
|
||||
{
|
||||
u32 i;
|
||||
void __iomem *dfi_regs = dfi->regs;
|
||||
|
||||
for (i = 0; i < dfi->max_channels; i++) {
|
||||
if (!(dfi->channel_mask & BIT(i)))
|
||||
continue;
|
||||
res->c[i].read_access = readl_relaxed(dfi_regs +
|
||||
DDRMON_CH0_RD_NUM + i * dfi->ddrmon_stride);
|
||||
res->c[i].write_access = readl_relaxed(dfi_regs +
|
||||
DDRMON_CH0_WR_NUM + i * dfi->ddrmon_stride);
|
||||
res->c[i].access = readl_relaxed(dfi_regs +
|
||||
DDRMON_CH0_DFI_ACCESS_NUM + i * dfi->ddrmon_stride);
|
||||
res->c[i].clock_cycles = readl_relaxed(dfi_regs +
|
||||
DDRMON_CH0_COUNT_NUM + i * dfi->ddrmon_stride);
|
||||
}
|
||||
}
|
||||
|
||||
static int rockchip_dfi_event_disable(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
|
||||
|
||||
rockchip_dfi_disable(dfi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dfi_event_enable(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
|
||||
|
||||
return rockchip_dfi_enable(dfi);
|
||||
}
|
||||
|
||||
static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
|
||||
{
|
||||
return 0;
|
||||
@@ -149,77 +249,576 @@ static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
|
||||
static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
|
||||
struct devfreq_event_data *edata)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
int busier_ch;
|
||||
struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev);
|
||||
struct dmc_count count;
|
||||
struct dmc_count *last = &dfi->last_event_count;
|
||||
u32 access = 0, clock_cycles = 0;
|
||||
int i;
|
||||
|
||||
busier_ch = rockchip_dfi_get_busier_ch(edev);
|
||||
rockchip_dfi_read_counters(dfi, &count);
|
||||
|
||||
edata->load_count = info->ch_usage[busier_ch].access;
|
||||
edata->total_count = info->ch_usage[busier_ch].total;
|
||||
/* We can only report one channel, so find the busiest one */
|
||||
for (i = 0; i < dfi->max_channels; i++) {
|
||||
u32 a, c;
|
||||
|
||||
if (!(dfi->channel_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
a = count.c[i].access - last->c[i].access;
|
||||
c = count.c[i].clock_cycles - last->c[i].clock_cycles;
|
||||
|
||||
if (a > access) {
|
||||
access = a;
|
||||
clock_cycles = c;
|
||||
}
|
||||
}
|
||||
|
||||
edata->load_count = access * 4;
|
||||
edata->total_count = clock_cycles;
|
||||
|
||||
dfi->last_event_count = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devfreq_event_ops rockchip_dfi_ops = {
|
||||
.disable = rockchip_dfi_disable,
|
||||
.enable = rockchip_dfi_enable,
|
||||
.disable = rockchip_dfi_event_disable,
|
||||
.enable = rockchip_dfi_event_enable,
|
||||
.get_event = rockchip_dfi_get_event,
|
||||
.set_event = rockchip_dfi_set_event,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
|
||||
static void rockchip_ddr_perf_counters_add(struct rockchip_dfi *dfi,
|
||||
const struct dmc_count *now,
|
||||
struct dmc_count *res)
|
||||
{
|
||||
const struct dmc_count *last = &dfi->last_perf_count;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dfi->max_channels; i++) {
|
||||
res->c[i].read_access = dfi->total_count.c[i].read_access +
|
||||
(u32)(now->c[i].read_access - last->c[i].read_access);
|
||||
res->c[i].write_access = dfi->total_count.c[i].write_access +
|
||||
(u32)(now->c[i].write_access - last->c[i].write_access);
|
||||
res->c[i].access = dfi->total_count.c[i].access +
|
||||
(u32)(now->c[i].access - last->c[i].access);
|
||||
res->c[i].clock_cycles = dfi->total_count.c[i].clock_cycles +
|
||||
(u32)(now->c[i].clock_cycles - last->c[i].clock_cycles);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t ddr_perf_cpumask_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pmu *pmu = dev_get_drvdata(dev);
|
||||
struct rockchip_dfi *dfi = container_of(pmu, struct rockchip_dfi, pmu);
|
||||
|
||||
return cpumap_print_to_pagebuf(true, buf, cpumask_of(dfi->cpu));
|
||||
}
|
||||
|
||||
static struct device_attribute ddr_perf_cpumask_attr =
|
||||
__ATTR(cpumask, 0444, ddr_perf_cpumask_show, NULL);
|
||||
|
||||
static struct attribute *ddr_perf_cpumask_attrs[] = {
|
||||
&ddr_perf_cpumask_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ddr_perf_cpumask_attr_group = {
|
||||
.attrs = ddr_perf_cpumask_attrs,
|
||||
};
|
||||
|
||||
PMU_EVENT_ATTR_STRING(cycles, ddr_pmu_cycles, "event="__stringify(PERF_EVENT_CYCLES))
|
||||
|
||||
#define DFI_PMU_EVENT_ATTR(_name, _var, _str) \
|
||||
PMU_EVENT_ATTR_STRING(_name, _var, _str); \
|
||||
PMU_EVENT_ATTR_STRING(_name.unit, _var##_unit, "MB"); \
|
||||
PMU_EVENT_ATTR_STRING(_name.scale, _var##_scale, "9.536743164e-07")
|
||||
|
||||
DFI_PMU_EVENT_ATTR(read-bytes0, ddr_pmu_read_bytes0, "event="__stringify(PERF_EVENT_READ_BYTES0));
|
||||
DFI_PMU_EVENT_ATTR(write-bytes0, ddr_pmu_write_bytes0, "event="__stringify(PERF_EVENT_WRITE_BYTES0));
|
||||
|
||||
DFI_PMU_EVENT_ATTR(read-bytes1, ddr_pmu_read_bytes1, "event="__stringify(PERF_EVENT_READ_BYTES1));
|
||||
DFI_PMU_EVENT_ATTR(write-bytes1, ddr_pmu_write_bytes1, "event="__stringify(PERF_EVENT_WRITE_BYTES1));
|
||||
|
||||
DFI_PMU_EVENT_ATTR(read-bytes2, ddr_pmu_read_bytes2, "event="__stringify(PERF_EVENT_READ_BYTES2));
|
||||
DFI_PMU_EVENT_ATTR(write-bytes2, ddr_pmu_write_bytes2, "event="__stringify(PERF_EVENT_WRITE_BYTES2));
|
||||
|
||||
DFI_PMU_EVENT_ATTR(read-bytes3, ddr_pmu_read_bytes3, "event="__stringify(PERF_EVENT_READ_BYTES3));
|
||||
DFI_PMU_EVENT_ATTR(write-bytes3, ddr_pmu_write_bytes3, "event="__stringify(PERF_EVENT_WRITE_BYTES3));
|
||||
|
||||
DFI_PMU_EVENT_ATTR(read-bytes, ddr_pmu_read_bytes, "event="__stringify(PERF_EVENT_READ_BYTES));
|
||||
DFI_PMU_EVENT_ATTR(write-bytes, ddr_pmu_write_bytes, "event="__stringify(PERF_EVENT_WRITE_BYTES));
|
||||
|
||||
DFI_PMU_EVENT_ATTR(bytes, ddr_pmu_bytes, "event="__stringify(PERF_EVENT_BYTES));
|
||||
|
||||
#define DFI_ATTR_MB(_name) \
|
||||
&_name.attr.attr, \
|
||||
&_name##_unit.attr.attr, \
|
||||
&_name##_scale.attr.attr
|
||||
|
||||
static struct attribute *ddr_perf_events_attrs[] = {
|
||||
&ddr_pmu_cycles.attr.attr,
|
||||
DFI_ATTR_MB(ddr_pmu_read_bytes),
|
||||
DFI_ATTR_MB(ddr_pmu_write_bytes),
|
||||
DFI_ATTR_MB(ddr_pmu_read_bytes0),
|
||||
DFI_ATTR_MB(ddr_pmu_write_bytes0),
|
||||
DFI_ATTR_MB(ddr_pmu_read_bytes1),
|
||||
DFI_ATTR_MB(ddr_pmu_write_bytes1),
|
||||
DFI_ATTR_MB(ddr_pmu_read_bytes2),
|
||||
DFI_ATTR_MB(ddr_pmu_write_bytes2),
|
||||
DFI_ATTR_MB(ddr_pmu_read_bytes3),
|
||||
DFI_ATTR_MB(ddr_pmu_write_bytes3),
|
||||
DFI_ATTR_MB(ddr_pmu_bytes),
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ddr_perf_events_attr_group = {
|
||||
.name = "events",
|
||||
.attrs = ddr_perf_events_attrs,
|
||||
};
|
||||
|
||||
PMU_FORMAT_ATTR(event, "config:0-7");
|
||||
|
||||
static struct attribute *ddr_perf_format_attrs[] = {
|
||||
&format_attr_event.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ddr_perf_format_attr_group = {
|
||||
.name = "format",
|
||||
.attrs = ddr_perf_format_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *attr_groups[] = {
|
||||
&ddr_perf_events_attr_group,
|
||||
&ddr_perf_cpumask_attr_group,
|
||||
&ddr_perf_format_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int rockchip_ddr_perf_event_init(struct perf_event *event)
|
||||
{
|
||||
struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
|
||||
|
||||
if (event->attr.type != event->pmu->type)
|
||||
return -ENOENT;
|
||||
|
||||
if (event->attach_state & PERF_ATTACH_TASK)
|
||||
return -EINVAL;
|
||||
|
||||
if (event->cpu < 0) {
|
||||
dev_warn(dfi->dev, "Can't provide per-task data!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 rockchip_ddr_perf_event_get_count(struct perf_event *event)
|
||||
{
|
||||
struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
|
||||
int blen = dfi->burst_len;
|
||||
struct dmc_count total, now;
|
||||
unsigned int seq;
|
||||
u64 count = 0;
|
||||
int i;
|
||||
|
||||
rockchip_dfi_read_counters(dfi, &now);
|
||||
|
||||
do {
|
||||
seq = read_seqbegin(&dfi->count_seqlock);
|
||||
rockchip_ddr_perf_counters_add(dfi, &now, &total);
|
||||
} while (read_seqretry(&dfi->count_seqlock, seq));
|
||||
|
||||
switch (event->attr.config) {
|
||||
case PERF_EVENT_CYCLES:
|
||||
count = total.c[0].clock_cycles;
|
||||
break;
|
||||
case PERF_EVENT_READ_BYTES:
|
||||
for (i = 0; i < dfi->max_channels; i++)
|
||||
count += total.c[i].read_access * blen * dfi->buswidth[i];
|
||||
break;
|
||||
case PERF_EVENT_WRITE_BYTES:
|
||||
for (i = 0; i < dfi->max_channels; i++)
|
||||
count += total.c[i].write_access * blen * dfi->buswidth[i];
|
||||
break;
|
||||
case PERF_EVENT_READ_BYTES0:
|
||||
count = total.c[0].read_access * blen * dfi->buswidth[0];
|
||||
break;
|
||||
case PERF_EVENT_WRITE_BYTES0:
|
||||
count = total.c[0].write_access * blen * dfi->buswidth[0];
|
||||
break;
|
||||
case PERF_EVENT_READ_BYTES1:
|
||||
count = total.c[1].read_access * blen * dfi->buswidth[1];
|
||||
break;
|
||||
case PERF_EVENT_WRITE_BYTES1:
|
||||
count = total.c[1].write_access * blen * dfi->buswidth[1];
|
||||
break;
|
||||
case PERF_EVENT_READ_BYTES2:
|
||||
count = total.c[2].read_access * blen * dfi->buswidth[2];
|
||||
break;
|
||||
case PERF_EVENT_WRITE_BYTES2:
|
||||
count = total.c[2].write_access * blen * dfi->buswidth[2];
|
||||
break;
|
||||
case PERF_EVENT_READ_BYTES3:
|
||||
count = total.c[3].read_access * blen * dfi->buswidth[3];
|
||||
break;
|
||||
case PERF_EVENT_WRITE_BYTES3:
|
||||
count = total.c[3].write_access * blen * dfi->buswidth[3];
|
||||
break;
|
||||
case PERF_EVENT_BYTES:
|
||||
for (i = 0; i < dfi->max_channels; i++)
|
||||
count += total.c[i].access * blen * dfi->buswidth[i];
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void rockchip_ddr_perf_event_update(struct perf_event *event)
|
||||
{
|
||||
u64 now;
|
||||
s64 prev;
|
||||
|
||||
if (event->attr.config >= PERF_ACCESS_TYPE_MAX)
|
||||
return;
|
||||
|
||||
now = rockchip_ddr_perf_event_get_count(event);
|
||||
prev = local64_xchg(&event->hw.prev_count, now);
|
||||
local64_add(now - prev, &event->count);
|
||||
}
|
||||
|
||||
static void rockchip_ddr_perf_event_start(struct perf_event *event, int flags)
|
||||
{
|
||||
u64 now = rockchip_ddr_perf_event_get_count(event);
|
||||
|
||||
local64_set(&event->hw.prev_count, now);
|
||||
}
|
||||
|
||||
static int rockchip_ddr_perf_event_add(struct perf_event *event, int flags)
|
||||
{
|
||||
struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
|
||||
|
||||
dfi->active_events++;
|
||||
|
||||
if (dfi->active_events == 1) {
|
||||
dfi->total_count = (struct dmc_count){};
|
||||
rockchip_dfi_read_counters(dfi, &dfi->last_perf_count);
|
||||
hrtimer_start(&dfi->timer, ns_to_ktime(NSEC_PER_SEC), HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
if (flags & PERF_EF_START)
|
||||
rockchip_ddr_perf_event_start(event, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_ddr_perf_event_stop(struct perf_event *event, int flags)
|
||||
{
|
||||
rockchip_ddr_perf_event_update(event);
|
||||
}
|
||||
|
||||
static void rockchip_ddr_perf_event_del(struct perf_event *event, int flags)
|
||||
{
|
||||
struct rockchip_dfi *dfi = container_of(event->pmu, struct rockchip_dfi, pmu);
|
||||
|
||||
rockchip_ddr_perf_event_stop(event, PERF_EF_UPDATE);
|
||||
|
||||
dfi->active_events--;
|
||||
|
||||
if (dfi->active_events == 0)
|
||||
hrtimer_cancel(&dfi->timer);
|
||||
}
|
||||
|
||||
static enum hrtimer_restart rockchip_dfi_timer(struct hrtimer *timer)
|
||||
{
|
||||
struct rockchip_dfi *dfi = container_of(timer, struct rockchip_dfi, timer);
|
||||
struct dmc_count now, total;
|
||||
|
||||
rockchip_dfi_read_counters(dfi, &now);
|
||||
|
||||
write_seqlock(&dfi->count_seqlock);
|
||||
|
||||
rockchip_ddr_perf_counters_add(dfi, &now, &total);
|
||||
dfi->total_count = total;
|
||||
dfi->last_perf_count = now;
|
||||
|
||||
write_sequnlock(&dfi->count_seqlock);
|
||||
|
||||
hrtimer_forward_now(&dfi->timer, ns_to_ktime(NSEC_PER_SEC));
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
};
|
||||
|
||||
static int ddr_perf_offline_cpu(unsigned int cpu, struct hlist_node *node)
|
||||
{
|
||||
struct rockchip_dfi *dfi = hlist_entry_safe(node, struct rockchip_dfi, node);
|
||||
int target;
|
||||
|
||||
if (cpu != dfi->cpu)
|
||||
return 0;
|
||||
|
||||
target = cpumask_any_but(cpu_online_mask, cpu);
|
||||
if (target >= nr_cpu_ids)
|
||||
return 0;
|
||||
|
||||
perf_pmu_migrate_context(&dfi->pmu, cpu, target);
|
||||
dfi->cpu = target;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_ddr_cpuhp_remove_state(void *data)
|
||||
{
|
||||
struct rockchip_dfi *dfi = data;
|
||||
|
||||
cpuhp_remove_multi_state(dfi->cpuhp_state);
|
||||
|
||||
rockchip_dfi_disable(dfi);
|
||||
}
|
||||
|
||||
static void rockchip_ddr_cpuhp_remove_instance(void *data)
|
||||
{
|
||||
struct rockchip_dfi *dfi = data;
|
||||
|
||||
cpuhp_state_remove_instance_nocalls(dfi->cpuhp_state, &dfi->node);
|
||||
}
|
||||
|
||||
static void rockchip_ddr_perf_remove(void *data)
|
||||
{
|
||||
struct rockchip_dfi *dfi = data;
|
||||
|
||||
perf_pmu_unregister(&dfi->pmu);
|
||||
}
|
||||
|
||||
static int rockchip_ddr_perf_init(struct rockchip_dfi *dfi)
|
||||
{
|
||||
struct pmu *pmu = &dfi->pmu;
|
||||
int ret;
|
||||
|
||||
seqlock_init(&dfi->count_seqlock);
|
||||
|
||||
pmu->module = THIS_MODULE;
|
||||
pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE;
|
||||
pmu->task_ctx_nr = perf_invalid_context;
|
||||
pmu->attr_groups = attr_groups;
|
||||
pmu->event_init = rockchip_ddr_perf_event_init;
|
||||
pmu->add = rockchip_ddr_perf_event_add;
|
||||
pmu->del = rockchip_ddr_perf_event_del;
|
||||
pmu->start = rockchip_ddr_perf_event_start;
|
||||
pmu->stop = rockchip_ddr_perf_event_stop;
|
||||
pmu->read = rockchip_ddr_perf_event_update;
|
||||
|
||||
dfi->cpu = raw_smp_processor_id();
|
||||
|
||||
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
|
||||
"rockchip_ddr_perf_pmu",
|
||||
NULL,
|
||||
ddr_perf_offline_cpu);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dfi->dev, "cpuhp_setup_state_multi failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dfi->cpuhp_state = ret;
|
||||
|
||||
rockchip_dfi_enable(dfi);
|
||||
|
||||
ret = devm_add_action_or_reset(dfi->dev, rockchip_ddr_cpuhp_remove_state, dfi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cpuhp_state_add_instance_nocalls(dfi->cpuhp_state, &dfi->node);
|
||||
if (ret) {
|
||||
dev_err(dfi->dev, "Error %d registering hotplug\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(dfi->dev, rockchip_ddr_cpuhp_remove_instance, dfi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hrtimer_init(&dfi->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
dfi->timer.function = rockchip_dfi_timer;
|
||||
|
||||
switch (dfi->ddr_type) {
|
||||
case ROCKCHIP_DDRTYPE_LPDDR2:
|
||||
case ROCKCHIP_DDRTYPE_LPDDR3:
|
||||
dfi->burst_len = 8;
|
||||
break;
|
||||
case ROCKCHIP_DDRTYPE_LPDDR4:
|
||||
case ROCKCHIP_DDRTYPE_LPDDR4X:
|
||||
dfi->burst_len = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = perf_pmu_register(pmu, "rockchip_ddr", -1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dfi->dev, rockchip_ddr_perf_remove, dfi);
|
||||
}
|
||||
#else
|
||||
static int rockchip_ddr_perf_init(struct rockchip_dfi *dfi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rk3399_dfi_init(struct rockchip_dfi *dfi)
|
||||
{
|
||||
struct regmap *regmap_pmu = dfi->regmap_pmu;
|
||||
u32 val;
|
||||
|
||||
dfi->clk = devm_clk_get(dfi->dev, "pclk_ddr_mon");
|
||||
if (IS_ERR(dfi->clk))
|
||||
return dev_err_probe(dfi->dev, PTR_ERR(dfi->clk),
|
||||
"Cannot get the clk pclk_ddr_mon\n");
|
||||
|
||||
/* get ddr type */
|
||||
regmap_read(regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
|
||||
dfi->ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val);
|
||||
|
||||
dfi->channel_mask = GENMASK(1, 0);
|
||||
dfi->max_channels = 2;
|
||||
|
||||
dfi->buswidth[0] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH0, val) == 0 ? 4 : 2;
|
||||
dfi->buswidth[1] = FIELD_GET(RK3399_PMUGRF_OS_REG2_BW_CH1, val) == 0 ? 4 : 2;
|
||||
|
||||
dfi->ddrmon_stride = 0x14;
|
||||
dfi->ddrmon_ctrl_single = true;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int rk3568_dfi_init(struct rockchip_dfi *dfi)
|
||||
{
|
||||
struct regmap *regmap_pmu = dfi->regmap_pmu;
|
||||
u32 reg2, reg3;
|
||||
|
||||
regmap_read(regmap_pmu, RK3568_PMUGRF_OS_REG2, ®2);
|
||||
regmap_read(regmap_pmu, RK3568_PMUGRF_OS_REG3, ®3);
|
||||
|
||||
/* lower 3 bits of the DDR type */
|
||||
dfi->ddr_type = FIELD_GET(RK3568_PMUGRF_OS_REG2_DRAMTYPE_INFO, reg2);
|
||||
|
||||
/*
|
||||
* For version three and higher the upper two bits of the DDR type are
|
||||
* in RK3568_PMUGRF_OS_REG3
|
||||
*/
|
||||
if (FIELD_GET(RK3568_PMUGRF_OS_REG3_SYSREG_VERSION, reg3) >= 0x3)
|
||||
dfi->ddr_type |= FIELD_GET(RK3568_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3;
|
||||
|
||||
dfi->channel_mask = BIT(0);
|
||||
dfi->max_channels = 1;
|
||||
|
||||
dfi->buswidth[0] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2;
|
||||
|
||||
dfi->ddrmon_stride = 0x0; /* not relevant, we only have a single channel on this SoC */
|
||||
dfi->ddrmon_ctrl_single = true;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int rk3588_dfi_init(struct rockchip_dfi *dfi)
|
||||
{
|
||||
struct regmap *regmap_pmu = dfi->regmap_pmu;
|
||||
u32 reg2, reg3, reg4;
|
||||
|
||||
regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG2, ®2);
|
||||
regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG3, ®3);
|
||||
regmap_read(regmap_pmu, RK3588_PMUGRF_OS_REG4, ®4);
|
||||
|
||||
/* lower 3 bits of the DDR type */
|
||||
dfi->ddr_type = FIELD_GET(RK3588_PMUGRF_OS_REG2_DRAMTYPE_INFO, reg2);
|
||||
|
||||
/*
|
||||
* For version three and higher the upper two bits of the DDR type are
|
||||
* in RK3588_PMUGRF_OS_REG3
|
||||
*/
|
||||
if (FIELD_GET(RK3588_PMUGRF_OS_REG3_SYSREG_VERSION, reg3) >= 0x3)
|
||||
dfi->ddr_type |= FIELD_GET(RK3588_PMUGRF_OS_REG3_DRAMTYPE_INFO_V3, reg3) << 3;
|
||||
|
||||
dfi->buswidth[0] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH0, reg2) == 0 ? 4 : 2;
|
||||
dfi->buswidth[1] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg2) == 0 ? 4 : 2;
|
||||
dfi->buswidth[2] = FIELD_GET(RK3568_PMUGRF_OS_REG2_BW_CH0, reg4) == 0 ? 4 : 2;
|
||||
dfi->buswidth[3] = FIELD_GET(RK3588_PMUGRF_OS_REG2_BW_CH1, reg4) == 0 ? 4 : 2;
|
||||
dfi->channel_mask = FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg2) |
|
||||
FIELD_GET(RK3588_PMUGRF_OS_REG2_CH_INFO, reg4) << 2;
|
||||
dfi->max_channels = 4;
|
||||
|
||||
dfi->ddrmon_stride = 0x4000;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_dfi_id_match[] = {
|
||||
{ .compatible = "rockchip,rk3399-dfi" },
|
||||
{ .compatible = "rockchip,rk3399-dfi", .data = rk3399_dfi_init },
|
||||
{ .compatible = "rockchip,rk3568-dfi", .data = rk3568_dfi_init },
|
||||
{ .compatible = "rockchip,rk3588-dfi", .data = rk3588_dfi_init },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
|
||||
|
||||
static int rockchip_dfi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rockchip_dfi *data;
|
||||
struct rockchip_dfi *dfi;
|
||||
struct devfreq_event_desc *desc;
|
||||
struct device_node *np = pdev->dev.of_node, *node;
|
||||
int (*soc_init)(struct rockchip_dfi *dfi);
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
|
||||
if (!data)
|
||||
soc_init = of_device_get_match_data(&pdev->dev);
|
||||
if (!soc_init)
|
||||
return -EINVAL;
|
||||
|
||||
dfi = devm_kzalloc(dev, sizeof(*dfi), GFP_KERNEL);
|
||||
if (!dfi)
|
||||
return -ENOMEM;
|
||||
|
||||
data->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(data->regs))
|
||||
return PTR_ERR(data->regs);
|
||||
dfi->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(dfi->regs))
|
||||
return PTR_ERR(dfi->regs);
|
||||
|
||||
data->clk = devm_clk_get(dev, "pclk_ddr_mon");
|
||||
if (IS_ERR(data->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(data->clk),
|
||||
"Cannot get the clk pclk_ddr_mon\n");
|
||||
|
||||
/* try to find the optional reference to the pmu syscon */
|
||||
node = of_parse_phandle(np, "rockchip,pmu", 0);
|
||||
if (node) {
|
||||
data->regmap_pmu = syscon_node_to_regmap(node);
|
||||
of_node_put(node);
|
||||
if (IS_ERR(data->regmap_pmu))
|
||||
return PTR_ERR(data->regmap_pmu);
|
||||
}
|
||||
data->dev = dev;
|
||||
if (!node)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV, "Can't find pmu_grf registers\n");
|
||||
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
dfi->regmap_pmu = syscon_node_to_regmap(node);
|
||||
of_node_put(node);
|
||||
if (IS_ERR(dfi->regmap_pmu))
|
||||
return PTR_ERR(dfi->regmap_pmu);
|
||||
|
||||
dfi->dev = dev;
|
||||
mutex_init(&dfi->mutex);
|
||||
|
||||
desc = &dfi->desc;
|
||||
desc->ops = &rockchip_dfi_ops;
|
||||
desc->driver_data = data;
|
||||
desc->driver_data = dfi;
|
||||
desc->name = np->name;
|
||||
data->desc = desc;
|
||||
|
||||
data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
|
||||
if (IS_ERR(data->edev)) {
|
||||
ret = soc_init(dfi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dfi->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
|
||||
if (IS_ERR(dfi->edev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to add devfreq-event device\n");
|
||||
return PTR_ERR(data->edev);
|
||||
return PTR_ERR(dfi->edev);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
ret = rockchip_ddr_perf_init(dfi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, dfi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -229,6 +828,7 @@ static struct platform_driver rockchip_dfi_driver = {
|
||||
.driver = {
|
||||
.name = "rockchip-dfi",
|
||||
.of_match_table = rockchip_dfi_id_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
module_platform_driver(rockchip_dfi_driver);
|
||||
|
||||
@@ -137,6 +137,8 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
|
||||
if (drv->pre_freq == *freq)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&drv->reg_lock);
|
||||
|
||||
inter_voltage = drv->inter_voltage;
|
||||
cci_pll = clk_get_parent(drv->cci_clk);
|
||||
|
||||
@@ -144,11 +146,10 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
|
||||
opp = devfreq_recommended_opp(dev, &opp_rate, 1);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(dev, "failed to find opp for freq: %ld\n", opp_rate);
|
||||
return PTR_ERR(opp);
|
||||
ret = PTR_ERR(opp);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
mutex_lock(&drv->reg_lock);
|
||||
|
||||
voltage = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
@@ -227,9 +228,9 @@ static int mtk_ccifreq_opp_notifier(struct notifier_block *nb,
|
||||
drv = container_of(nb, struct mtk_ccifreq_drv, opp_nb);
|
||||
|
||||
if (event == OPP_EVENT_ADJUST_VOLTAGE) {
|
||||
mutex_lock(&drv->reg_lock);
|
||||
freq = dev_pm_opp_get_freq(opp);
|
||||
|
||||
mutex_lock(&drv->reg_lock);
|
||||
/* current opp item is changed */
|
||||
if (freq == drv->pre_freq) {
|
||||
volt = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <soc/rockchip/pm_domains.h>
|
||||
#include <soc/rockchip/rockchip_grf.h>
|
||||
#include <soc/rockchip/rk3399_grf.h>
|
||||
#include <soc/rockchip/rockchip_sip.h>
|
||||
|
||||
@@ -381,17 +382,16 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
|
||||
ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
|
||||
RK3399_PMUGRF_DDRTYPE_MASK;
|
||||
ddr_type = FIELD_GET(RK3399_PMUGRF_OS_REG2_DDRTYPE, val);
|
||||
|
||||
switch (ddr_type) {
|
||||
case RK3399_PMUGRF_DDRTYPE_DDR3:
|
||||
case ROCKCHIP_DDRTYPE_DDR3:
|
||||
data->odt_dis_freq = data->ddr3_odt_dis_freq;
|
||||
break;
|
||||
case RK3399_PMUGRF_DDRTYPE_LPDDR3:
|
||||
case ROCKCHIP_DDRTYPE_LPDDR3:
|
||||
data->odt_dis_freq = data->lpddr3_odt_dis_freq;
|
||||
break;
|
||||
case RK3399_PMUGRF_DDRTYPE_LPDDR4:
|
||||
case ROCKCHIP_DDRTYPE_LPDDR4:
|
||||
data->odt_dis_freq = data->lpddr4_odt_dis_freq;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1790,9 +1790,11 @@ config GPIO_LATCH
|
||||
connected to other GPIOs.
|
||||
|
||||
config GPIO_MOCKUP
|
||||
tristate "GPIO Testing Driver"
|
||||
tristate "GPIO Testing Driver (DEPRECATED)"
|
||||
select IRQ_SIM
|
||||
help
|
||||
This module is DEPRECATED. Please consider using gpio-sim instead.
|
||||
|
||||
This enables GPIO Testing driver, which provides a way to test GPIO
|
||||
subsystem through sysfs (or char device) and debugfs.
|
||||
User could use it through the script in
|
||||
|
||||
@@ -317,13 +317,11 @@ skip_irq:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_gpio_remove(struct platform_device *pdev)
|
||||
static void altera_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev);
|
||||
|
||||
of_mm_gpiochip_remove(&altera_gc->mmchip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id altera_gpio_of_match[] = {
|
||||
@@ -338,7 +336,7 @@ static struct platform_driver altera_gpio_driver = {
|
||||
.of_match_table = altera_gpio_of_match,
|
||||
},
|
||||
.probe = altera_gpio_probe,
|
||||
.remove = altera_gpio_remove,
|
||||
.remove_new = altera_gpio_remove,
|
||||
};
|
||||
|
||||
static int __init altera_gpio_init(void)
|
||||
|
||||
@@ -122,13 +122,11 @@ static int pt_gpio_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pt_gpio_remove(struct platform_device *pdev)
|
||||
static void pt_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev);
|
||||
|
||||
gpiochip_remove(&pt_gpio->gc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id pt_gpio_acpi_match[] = {
|
||||
@@ -145,7 +143,7 @@ static struct platform_driver pt_gpio_driver = {
|
||||
.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
|
||||
},
|
||||
.probe = pt_gpio_probe,
|
||||
.remove = pt_gpio_remove,
|
||||
.remove_new = pt_gpio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(pt_gpio_driver);
|
||||
|
||||
@@ -371,7 +371,7 @@ static int brcmstb_gpio_sanity_check_banks(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
static int brcmstb_gpio_remove(struct platform_device *pdev)
|
||||
static void brcmstb_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev);
|
||||
struct brcmstb_gpio_bank *bank;
|
||||
@@ -395,8 +395,6 @@ static int brcmstb_gpio_remove(struct platform_device *pdev)
|
||||
*/
|
||||
list_for_each_entry(bank, &priv->bank_list, node)
|
||||
gpiochip_remove(&bank->gc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
|
||||
@@ -757,7 +755,7 @@ static struct platform_driver brcmstb_gpio_driver = {
|
||||
.pm = &brcmstb_gpio_pm_ops,
|
||||
},
|
||||
.probe = brcmstb_gpio_probe,
|
||||
.remove = brcmstb_gpio_remove,
|
||||
.remove_new = brcmstb_gpio_remove,
|
||||
.shutdown = brcmstb_gpio_shutdown,
|
||||
};
|
||||
module_platform_driver(brcmstb_gpio_driver);
|
||||
|
||||
@@ -268,14 +268,12 @@ err_revert_dir:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdns_gpio_remove(struct platform_device *pdev)
|
||||
static void cdns_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cdns_gpio_chip *cgpio = platform_get_drvdata(pdev);
|
||||
|
||||
iowrite32(cgpio->bypass_orig, cgpio->regs + CDNS_GPIO_BYPASS_MODE);
|
||||
clk_disable_unprepare(cgpio->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cdns_of_ids[] = {
|
||||
@@ -290,7 +288,7 @@ static struct platform_driver cdns_gpio_driver = {
|
||||
.of_match_table = cdns_of_ids,
|
||||
},
|
||||
.probe = cdns_gpio_probe,
|
||||
.remove = cdns_gpio_remove,
|
||||
.remove_new = cdns_gpio_remove,
|
||||
};
|
||||
module_platform_driver(cdns_gpio_driver);
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/gpio-davinci.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@@ -486,7 +486,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
struct davinci_gpio_platform_data *pdata = dev->platform_data;
|
||||
struct davinci_gpio_regs __iomem *g;
|
||||
struct irq_domain *irq_domain = NULL;
|
||||
const struct of_device_id *match;
|
||||
struct irq_chip *irq_chip;
|
||||
struct davinci_gpio_irq_data *irqdata;
|
||||
gpio_get_irq_chip_cb_t gpio_get_irq_chip;
|
||||
@@ -495,10 +494,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
* Use davinci_gpio_get_irq_chip by default to handle non DT cases
|
||||
*/
|
||||
gpio_get_irq_chip = davinci_gpio_get_irq_chip;
|
||||
match = of_match_device(of_match_ptr(davinci_gpio_ids),
|
||||
dev);
|
||||
if (match)
|
||||
gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data;
|
||||
if (dev->of_node)
|
||||
gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)device_get_match_data(dev);
|
||||
|
||||
ngpio = pdata->ngpio;
|
||||
|
||||
|
||||
@@ -504,17 +504,15 @@ static int dln2_gpio_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dln2_gpio_remove(struct platform_device *pdev)
|
||||
static void dln2_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
dln2_unregister_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver dln2_gpio_driver = {
|
||||
.driver.name = "dln2-gpio",
|
||||
.probe = dln2_gpio_probe,
|
||||
.remove = dln2_gpio_remove,
|
||||
.remove_new = dln2_gpio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(dln2_gpio_driver);
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "gpiolib.h"
|
||||
#include "gpiolib-acpi.h"
|
||||
|
||||
#define GPIO_SWPORTA_DR 0x00
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
@@ -91,12 +92,20 @@ enum sprd_eic_type {
|
||||
|
||||
struct sprd_eic {
|
||||
struct gpio_chip chip;
|
||||
struct notifier_block irq_nb;
|
||||
void __iomem *base[SPRD_EIC_MAX_BANK];
|
||||
enum sprd_eic_type type;
|
||||
spinlock_t lock;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static ATOMIC_NOTIFIER_HEAD(sprd_eic_irq_notifier);
|
||||
|
||||
static struct sprd_eic *to_sprd_eic(struct notifier_block *nb)
|
||||
{
|
||||
return container_of(nb, struct sprd_eic, irq_nb);
|
||||
}
|
||||
|
||||
struct sprd_eic_variant_data {
|
||||
enum sprd_eic_type type;
|
||||
u32 num_eics;
|
||||
@@ -494,13 +503,6 @@ retry:
|
||||
sprd_eic_irq_unmask(data);
|
||||
}
|
||||
|
||||
static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data)
|
||||
{
|
||||
enum sprd_eic_type type = *(enum sprd_eic_type *)data;
|
||||
|
||||
return !strcmp(chip->label, sprd_eic_label_name[type]);
|
||||
}
|
||||
|
||||
static void sprd_eic_handle_one_type(struct gpio_chip *chip)
|
||||
{
|
||||
struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
|
||||
@@ -546,27 +548,29 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip)
|
||||
static void sprd_eic_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *ic = irq_desc_get_chip(desc);
|
||||
struct gpio_chip *chip;
|
||||
enum sprd_eic_type type;
|
||||
|
||||
chained_irq_enter(ic, desc);
|
||||
|
||||
/*
|
||||
* Since the digital-chip EIC 4 sub-modules (debounce, latch, async
|
||||
* and sync) share one same interrupt line, we should iterate each
|
||||
* EIC module to check if there are EIC interrupts were triggered.
|
||||
* and sync) share one same interrupt line, we should notify all of
|
||||
* them to let them check if there are EIC interrupts were triggered.
|
||||
*/
|
||||
for (type = SPRD_EIC_DEBOUNCE; type < SPRD_EIC_MAX; type++) {
|
||||
chip = gpiochip_find(&type, sprd_eic_match_chip_by_type);
|
||||
if (!chip)
|
||||
continue;
|
||||
|
||||
sprd_eic_handle_one_type(chip);
|
||||
}
|
||||
atomic_notifier_call_chain(&sprd_eic_irq_notifier, 0, NULL);
|
||||
|
||||
chained_irq_exit(ic, desc);
|
||||
}
|
||||
|
||||
static int sprd_eic_irq_notify(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct sprd_eic *sprd_eic = to_sprd_eic(nb);
|
||||
|
||||
sprd_eic_handle_one_type(&sprd_eic->chip);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static const struct irq_chip sprd_eic_irq = {
|
||||
.name = "sprd-eic",
|
||||
.irq_ack = sprd_eic_irq_ack,
|
||||
@@ -576,21 +580,30 @@ static const struct irq_chip sprd_eic_irq = {
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE,
|
||||
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
||||
};
|
||||
|
||||
static void sprd_eic_unregister_notifier(void *data)
|
||||
{
|
||||
struct notifier_block *nb = data;
|
||||
|
||||
atomic_notifier_chain_unregister(&sprd_eic_irq_notifier, nb);
|
||||
}
|
||||
|
||||
static int sprd_eic_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct sprd_eic_variant_data *pdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_irq_chip *irq;
|
||||
struct sprd_eic *sprd_eic;
|
||||
struct resource *res;
|
||||
int ret, i;
|
||||
|
||||
pdata = of_device_get_match_data(&pdev->dev);
|
||||
pdata = of_device_get_match_data(dev);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "No matching driver data found.\n");
|
||||
dev_err(dev, "No matching driver data found.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sprd_eic = devm_kzalloc(&pdev->dev, sizeof(*sprd_eic), GFP_KERNEL);
|
||||
sprd_eic = devm_kzalloc(dev, sizeof(*sprd_eic), GFP_KERNEL);
|
||||
if (!sprd_eic)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -612,7 +625,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
sprd_eic->base[i] = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(sprd_eic->base[i]))
|
||||
return PTR_ERR(sprd_eic->base[i]);
|
||||
}
|
||||
@@ -620,7 +633,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
|
||||
sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type];
|
||||
sprd_eic->chip.ngpio = pdata->num_eics;
|
||||
sprd_eic->chip.base = -1;
|
||||
sprd_eic->chip.parent = &pdev->dev;
|
||||
sprd_eic->chip.parent = dev;
|
||||
sprd_eic->chip.direction_input = sprd_eic_direction_input;
|
||||
switch (sprd_eic->type) {
|
||||
case SPRD_EIC_DEBOUNCE:
|
||||
@@ -647,13 +660,21 @@ static int sprd_eic_probe(struct platform_device *pdev)
|
||||
irq->num_parents = 1;
|
||||
irq->parents = &sprd_eic->irq;
|
||||
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &sprd_eic->chip, sprd_eic);
|
||||
ret = devm_gpiochip_add_data(dev, &sprd_eic->chip, sprd_eic);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret);
|
||||
dev_err(dev, "Could not register gpiochip %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
sprd_eic->irq_nb.notifier_call = sprd_eic_irq_notify;
|
||||
ret = atomic_notifier_chain_register(&sprd_eic_irq_notifier,
|
||||
&sprd_eic->irq_nb);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to register with the interrupt notifier");
|
||||
|
||||
return devm_add_action_or_reset(dev, sprd_eic_unregister_notifier,
|
||||
&sprd_eic->irq_nb);
|
||||
}
|
||||
|
||||
static const struct of_device_id sprd_eic_of_match[] = {
|
||||
|
||||
+69
-69
@@ -163,7 +163,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
|
||||
static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
unsigned long config);
|
||||
|
||||
#define F7188X_GPIO_BANK(_base, _ngpio, _regbase, _label) \
|
||||
#define F7188X_GPIO_BANK(_ngpio, _regbase, _label) \
|
||||
{ \
|
||||
.chip = { \
|
||||
.label = _label, \
|
||||
@@ -174,7 +174,7 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
.direction_output = f7188x_gpio_direction_out, \
|
||||
.set = f7188x_gpio_set, \
|
||||
.set_config = f7188x_gpio_set_config, \
|
||||
.base = _base, \
|
||||
.base = -1, \
|
||||
.ngpio = _ngpio, \
|
||||
.can_sleep = true, \
|
||||
}, \
|
||||
@@ -191,98 +191,98 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
#define f7188x_gpio_data_single(type) ((type) == nct6126d)
|
||||
|
||||
static struct f7188x_gpio_bank f71869_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 6, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(6, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(6, 0x90, DRVNAME "-6"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71869a_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(6, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71882_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 4, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 4, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(4, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(4, 0xB0, DRVNAME "-4"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71889a_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(7, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(7, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71889_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(7, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(7, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f81866_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(80, 8, 0x88, DRVNAME "-8"),
|
||||
F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0x80, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(8, 0x88, DRVNAME "-8"),
|
||||
};
|
||||
|
||||
|
||||
static struct f7188x_gpio_bank f81804_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(90, 8, 0x98, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0x90, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(8, 0x80, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(8, 0x98, DRVNAME "-6"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f81865_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(8, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(5, 0x90, DRVNAME "-6"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank nct6126d_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xEC, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(8, 0xE0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(8, 0xE4, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(8, 0xE8, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(8, 0xEC, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(8, 0xF0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(8, 0xF4, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(8, 0xF8, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(8, 0xFC, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
@@ -324,13 +324,11 @@ dis_clk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ftgpio_gpio_remove(struct platform_device *pdev)
|
||||
static void ftgpio_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ftgpio_gpio *g = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(g->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ftgpio_gpio_of_match[] = {
|
||||
@@ -352,6 +350,6 @@ static struct platform_driver ftgpio_gpio_driver = {
|
||||
.of_match_table = ftgpio_gpio_of_match,
|
||||
},
|
||||
.probe = ftgpio_gpio_probe,
|
||||
.remove = ftgpio_gpio_remove,
|
||||
.remove_new = ftgpio_gpio_remove,
|
||||
};
|
||||
builtin_platform_driver(ftgpio_gpio_driver);
|
||||
|
||||
@@ -84,7 +84,7 @@ static const struct regmap_config regmap = {
|
||||
.rd_table = &rd_table,
|
||||
.volatile_table = &volatile_table,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.num_reg_defaults_raw = FXL6408_REG_INT_STS + 1,
|
||||
};
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ static int grgpio_probe(struct platform_device *ofdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int grgpio_remove(struct platform_device *ofdev)
|
||||
static void grgpio_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct grgpio_priv *priv = platform_get_drvdata(ofdev);
|
||||
|
||||
@@ -439,8 +439,6 @@ static int grgpio_remove(struct platform_device *ofdev)
|
||||
|
||||
if (priv->domain)
|
||||
irq_domain_remove(priv->domain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id grgpio_match[] = {
|
||||
@@ -457,7 +455,7 @@ static struct platform_driver grgpio_driver = {
|
||||
.of_match_table = grgpio_match,
|
||||
},
|
||||
.probe = grgpio_probe,
|
||||
.remove = grgpio_remove,
|
||||
.remove_new = grgpio_remove,
|
||||
};
|
||||
module_platform_driver(grgpio_driver);
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ static void hisi_gpio_get_pdata(struct device *dev,
|
||||
hisi_gpio->irq = platform_get_irq(pdev, idx);
|
||||
|
||||
dev_info(dev,
|
||||
"get hisi_gpio[%d] with %d lines\n", idx,
|
||||
"get hisi_gpio[%d] with %u lines\n", idx,
|
||||
hisi_gpio->line_num);
|
||||
|
||||
idx++;
|
||||
|
||||
@@ -421,7 +421,7 @@ static int ljca_gpio_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ljca_gpio_remove(struct platform_device *pdev)
|
||||
static void ljca_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ljca_gpio_dev *ljca_gpio = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -429,7 +429,6 @@ static int ljca_gpio_remove(struct platform_device *pdev)
|
||||
ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
|
||||
mutex_destroy(&ljca_gpio->irq_lock);
|
||||
mutex_destroy(&ljca_gpio->trans_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LJCA_GPIO_DRV_NAME "ljca-gpio"
|
||||
@@ -442,7 +441,7 @@ MODULE_DEVICE_TABLE(platform, ljca_gpio_id);
|
||||
static struct platform_driver ljca_gpio_driver = {
|
||||
.driver.name = LJCA_GPIO_DRV_NAME,
|
||||
.probe = ljca_gpio_probe,
|
||||
.remove = ljca_gpio_remove,
|
||||
.remove_new = ljca_gpio_remove,
|
||||
};
|
||||
module_platform_driver(ljca_gpio_driver);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ struct loongson_gpio_chip_data {
|
||||
unsigned int conf_offset;
|
||||
unsigned int out_offset;
|
||||
unsigned int in_offset;
|
||||
unsigned int inten_offset;
|
||||
};
|
||||
|
||||
struct loongson_gpio_chip {
|
||||
@@ -117,19 +118,29 @@ static void loongson_gpio_set(struct gpio_chip *chip, unsigned int pin, int valu
|
||||
|
||||
static int loongson_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
unsigned int u;
|
||||
struct platform_device *pdev = to_platform_device(chip->parent);
|
||||
struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip);
|
||||
|
||||
if (lgpio->chip_data->mode == BIT_CTRL_MODE) {
|
||||
/* Get the register index from offset then multiply by bytes per register */
|
||||
u = readl(lgpio->reg_base + lgpio->chip_data->inten_offset + (offset / 32) * 4);
|
||||
u |= BIT(offset % 32);
|
||||
writel(u, lgpio->reg_base + lgpio->chip_data->inten_offset + (offset / 32) * 4);
|
||||
} else {
|
||||
writeb(1, lgpio->reg_base + lgpio->chip_data->inten_offset + offset);
|
||||
}
|
||||
|
||||
return platform_get_irq(pdev, offset);
|
||||
}
|
||||
|
||||
static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgpio,
|
||||
struct device_node *np, void __iomem *reg_base)
|
||||
void __iomem *reg_base)
|
||||
{
|
||||
int ret;
|
||||
u32 ngpios;
|
||||
|
||||
lgpio->reg_base = reg_base;
|
||||
|
||||
if (lgpio->chip_data->mode == BIT_CTRL_MODE) {
|
||||
ret = bgpio_init(&lgpio->chip, dev, 8,
|
||||
lgpio->reg_base + lgpio->chip_data->in_offset,
|
||||
@@ -148,15 +159,15 @@ static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgp
|
||||
lgpio->chip.direction_output = loongson_gpio_direction_output;
|
||||
lgpio->chip.set = loongson_gpio_set;
|
||||
lgpio->chip.parent = dev;
|
||||
device_property_read_u32(dev, "ngpios", &ngpios);
|
||||
lgpio->chip.ngpio = ngpios;
|
||||
spin_lock_init(&lgpio->lock);
|
||||
}
|
||||
|
||||
device_property_read_u32(dev, "ngpios", &ngpios);
|
||||
|
||||
lgpio->chip.can_sleep = 0;
|
||||
lgpio->chip.ngpio = ngpios;
|
||||
lgpio->chip.label = lgpio->chip_data->label;
|
||||
lgpio->chip.to_irq = loongson_gpio_to_irq;
|
||||
lgpio->chip.can_sleep = false;
|
||||
if (lgpio->chip_data->inten_offset)
|
||||
lgpio->chip.to_irq = loongson_gpio_to_irq;
|
||||
|
||||
return devm_gpiochip_add_data(dev, &lgpio->chip, lgpio);
|
||||
}
|
||||
@@ -165,7 +176,6 @@ static int loongson_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
struct loongson_gpio_chip *lgpio;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
lgpio = devm_kzalloc(dev, sizeof(*lgpio), GFP_KERNEL);
|
||||
@@ -178,7 +188,7 @@ static int loongson_gpio_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(reg_base))
|
||||
return PTR_ERR(reg_base);
|
||||
|
||||
return loongson_gpio_init(dev, lgpio, np, reg_base);
|
||||
return loongson_gpio_init(dev, lgpio, reg_base);
|
||||
}
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = {
|
||||
@@ -187,6 +197,57 @@ static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = {
|
||||
.conf_offset = 0x0,
|
||||
.in_offset = 0x20,
|
||||
.out_offset = 0x10,
|
||||
.inten_offset = 0x30,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k0500_data0 = {
|
||||
.label = "ls2k0500_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x0,
|
||||
.in_offset = 0x8,
|
||||
.out_offset = 0x10,
|
||||
.inten_offset = 0xb0,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k0500_data1 = {
|
||||
.label = "ls2k0500_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x0,
|
||||
.in_offset = 0x8,
|
||||
.out_offset = 0x10,
|
||||
.inten_offset = 0x98,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data0 = {
|
||||
.label = "ls2k2000_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x0,
|
||||
.in_offset = 0xc,
|
||||
.out_offset = 0x8,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data1 = {
|
||||
.label = "ls2k2000_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x0,
|
||||
.in_offset = 0x20,
|
||||
.out_offset = 0x10,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data2 = {
|
||||
.label = "ls2k2000_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x84,
|
||||
.in_offset = 0x88,
|
||||
.out_offset = 0x80,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls3a5000_data = {
|
||||
.label = "ls3a5000_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x0,
|
||||
.in_offset = 0xc,
|
||||
.out_offset = 0x8,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls7a_data = {
|
||||
@@ -202,6 +263,30 @@ static const struct of_device_id loongson_gpio_of_match[] = {
|
||||
.compatible = "loongson,ls2k-gpio",
|
||||
.data = &loongson_gpio_ls2k_data,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls2k0500-gpio0",
|
||||
.data = &loongson_gpio_ls2k0500_data0,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls2k0500-gpio1",
|
||||
.data = &loongson_gpio_ls2k0500_data1,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls2k2000-gpio0",
|
||||
.data = &loongson_gpio_ls2k2000_data0,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls2k2000-gpio1",
|
||||
.data = &loongson_gpio_ls2k2000_data1,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls2k2000-gpio2",
|
||||
.data = &loongson_gpio_ls2k2000_data2,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls3a5000-gpio",
|
||||
.data = &loongson_gpio_ls3a5000_data,
|
||||
},
|
||||
{
|
||||
.compatible = "loongson,ls7a-gpio",
|
||||
.data = &loongson_gpio_ls7a_data,
|
||||
@@ -215,6 +300,22 @@ static const struct acpi_device_id loongson_gpio_acpi_match[] = {
|
||||
.id = "LOON0002",
|
||||
.driver_data = (kernel_ulong_t)&loongson_gpio_ls7a_data,
|
||||
},
|
||||
{
|
||||
.id = "LOON0007",
|
||||
.driver_data = (kernel_ulong_t)&loongson_gpio_ls3a5000_data,
|
||||
},
|
||||
{
|
||||
.id = "LOON000A",
|
||||
.driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data0,
|
||||
},
|
||||
{
|
||||
.id = "LOON000B",
|
||||
.driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data1,
|
||||
},
|
||||
{
|
||||
.id = "LOON000C",
|
||||
.driver_data = (kernel_ulong_t)&loongson_gpio_ls2k2000_data2,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, loongson_gpio_acpi_match);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user