mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
Merge tag 'soc-drivers-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull SoC driver updates from Arnd Bergmann:
"There are lots of minor updates for driver subsystems managed through
the soc tree (turris-omnia platform, cache driver, tee drivers,
arm-cci, bus, memory) as well as soc vendor specific drivers
(starfive, xilinx, microchip, nxp, amlogic, imx, renesas, samsung, ti,
nvidia).
The more notable changes are:
- Larger updates for Qualcomm SoCs including support for SM8950
(Maili) SM8975 (Hawi), Glymur, Shikra, and IPQ5424
- Added SoC support for Exynos5515, Tegra264, Tegra410, R8A774A3, and
MT8167 in existing drivers
- Arm SCMI firmware driver support for ACPI PCC transport and module
autoloading of protocol specific drivers
- Apple crash log support for CrgA embedded controller"
* tag 'soc-drivers-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (176 commits)
platform: cznic: turris-omnia-mcu: stop button emulation producers
cache: Make cpu_cache_invalidate_memregion() error out if there are no handlers
soc: mpfs: use kref cleanup on probe failure
arm64: enable HAVE_SHARED_GPIOS for all ARM64 platforms
bus: arm-cci: Drop cci-control-port node reference in __cci_ace_get_port()
bus: arm-cci: Drop CPU node reference in cci_ace_init_ports()
soc: fsl: dpio: Free the IRQ before releasing the I/O object
soc: fsl: dpio: Fix cleanup on IRQ registration failure
bus: fsl-mc: Annotate fsl_mc_io.portal_virt_addr with __counted_by_ptr
bus: fsl-mc: drop the fwnode links of the dpmacs nodes
soc: fsl: cpm1: tsa: Fix clock leak in tsa_of_parse_tdms()
soc: qcom: geni-se: Drop unused icc_ddr parameter from geni_icc_get()
firmware: qcom: scm: Allow QSEECOM on ThinkPad T14s Gen 7
dt-bindings: mailbox: qcom: Document Maili CPUCP mailbox controller
dt-bindings: spmi: glymur-spmi-pmic-arb: Add compatible for Qualcomm Maili SoC
soc: qcom: pmic_pdcharger_ulog: prevent work requeue during remove
ASoC: dt-bindings: qcom,apr: Add modem_apps GLINK channel for shikra
firmware: qcom: tzmem: disable SHM bridge for SM7125 platform
soc: qcom: ubwc: Add Kalambo UBWC config
firmware: qcom: scm: Allow QSEECOM on Kalambo CRD
...
This commit is contained in:
commit
2e51c645fe
140 files changed
+5839
-1058
No files matched your search
@@ -32,6 +32,7 @@ properties:
|
||||
- qcom,glymur-ctcu
|
||||
- qcom,kaanapali-ctcu
|
||||
- qcom,qcs8300-ctcu
|
||||
- qcom,shikra-ctcu
|
||||
- qcom,sm8750-ctcu
|
||||
- qcom,x1e80100-ctcu
|
||||
- const: qcom,sa8775p-ctcu
|
||||
|
||||
+53
-2
@@ -26,6 +26,7 @@ properties:
|
||||
- qcom,hawi-llcc
|
||||
- qcom,ipq5424-llcc
|
||||
- qcom,kaanapali-llcc
|
||||
- qcom,nord-llcc
|
||||
- qcom,qcs615-llcc
|
||||
- qcom,qcs8300-llcc
|
||||
- qcom,qdu1000-llcc
|
||||
@@ -56,11 +57,11 @@ properties:
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 14
|
||||
maxItems: 18
|
||||
|
||||
reg-names:
|
||||
minItems: 1
|
||||
maxItems: 14
|
||||
maxItems: 18
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
@@ -355,6 +356,56 @@ allOf:
|
||||
- const: llcc3_base
|
||||
- const: llcc_broadcast_base
|
||||
- const: llcc_broadcast_and_base
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,nord-llcc
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: LLCC0 base register region
|
||||
- description: LLCC1 base register region
|
||||
- description: LLCC2 base register region
|
||||
- description: LLCC3 base register region
|
||||
- description: LLCC4 base register region
|
||||
- description: LLCC5 base register region
|
||||
- description: LLCC6 base register region
|
||||
- description: LLCC7 base register region
|
||||
- description: LLCC8 base register region
|
||||
- description: LLCC9 base register region
|
||||
- description: LLCC10 base register region
|
||||
- description: LLCC11 base register region
|
||||
- description: LLCC12 base register region
|
||||
- description: LLCC13 base register region
|
||||
- description: LLCC14 base register region
|
||||
- description: LLCC15 base register region
|
||||
- description: LLCC broadcast OR register region
|
||||
- description: LLCC broadcast AND register region
|
||||
reg-names:
|
||||
items:
|
||||
- const: llcc0_base
|
||||
- const: llcc1_base
|
||||
- const: llcc2_base
|
||||
- const: llcc3_base
|
||||
- const: llcc4_base
|
||||
- const: llcc5_base
|
||||
- const: llcc6_base
|
||||
- const: llcc7_base
|
||||
- const: llcc8_base
|
||||
- const: llcc9_base
|
||||
- const: llcc10_base
|
||||
- const: llcc11_base
|
||||
- const: llcc12_base
|
||||
- const: llcc13_base
|
||||
- const: llcc14_base
|
||||
- const: llcc15_base
|
||||
- const: llcc_broadcast_base
|
||||
- const: llcc_broadcast_and_base
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-per0crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 Peripheral-0 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-per0crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Main Oscillator (25 MHz)
|
||||
- description: PLL6
|
||||
- description: Configure 400MHz
|
||||
- description: Configure 800MHZ
|
||||
- description: Non Coherent NOC Initiator
|
||||
- description: Non Coherent NOC Target
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: osc
|
||||
- const: pll6
|
||||
- const: cfg_400
|
||||
- const: cfg_800
|
||||
- const: ncnoc_init
|
||||
- const: ncnoc_targ
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@11a08000 {
|
||||
compatible = "starfive,jhb100-per0crg";
|
||||
reg = <0x11a08000 0x1000>;
|
||||
clocks = <&osc>, <&pll6>, <&sys0crg 71>,
|
||||
<&sys0crg 72>, <&sys0crg 70>,
|
||||
<&sys2crg 23>;
|
||||
clock-names = "osc", "pll6", "cfg_400",
|
||||
"cfg_800", "ncnoc_init",
|
||||
"ncnoc_targ";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-per1crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 Peripheral-1 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-per1crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PLL7
|
||||
- description: Non Coherent NOC Initiator
|
||||
- description: Configure 800MHz
|
||||
- description: Non Coherent NOC Target
|
||||
- description: Configure 143MHz
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pll7
|
||||
- const: ncnoc_init
|
||||
- const: cfg_800
|
||||
- const: ncnoc_targ
|
||||
- const: cfg_143
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@11b40000 {
|
||||
compatible = "starfive,jhb100-per1crg";
|
||||
reg = <0x11b40000 0x1000>;
|
||||
clocks = <&pll7>,
|
||||
<&sys0crg 68>,
|
||||
<&sys0crg 69>,
|
||||
<&sys2crg 19>,
|
||||
<&sys2crg 22>;
|
||||
clock-names = "pll7", "ncnoc_init",
|
||||
"cfg_800", "ncnoc_targ",
|
||||
"cfg_143";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-per2crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 Peripheral-2 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-per2crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Non Coherent NOC Initiator
|
||||
- description: Configure 400MHz
|
||||
- description: Configure 125MHz
|
||||
- description: GMAC2 RGMII RX
|
||||
- description: GMAC2 RMII Reference
|
||||
- description: GMAC3 SGMII TX
|
||||
- description: GMAC3 SGMII RX
|
||||
- description: Main Oscillator (25 MHz)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ncnoc_init
|
||||
- const: cfg_400
|
||||
- const: cfg_125
|
||||
- const: gmac2_rgmii_rx
|
||||
- const: gmac2_rmii_ref
|
||||
- const: gmac3_sgmii_tx
|
||||
- const: gmac3_sgmii_rx
|
||||
- const: osc
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@11bc0000 {
|
||||
compatible = "starfive,jhb100-per2crg";
|
||||
reg = <0x11bc0000 0x1000>;
|
||||
clocks = <&sys0crg 52>, <&sys0crg 54>, <&sys0crg 55>,
|
||||
<&per2_gmac2_rgmii_rx>, <&per2_gmac2_rmii_ref>,
|
||||
<&per2_gmac3_sgmii_tx>, <&per2_gmac3_sgmii_rx>,
|
||||
<&osc>;
|
||||
clock-names = "ncnoc_init", "cfg_400", "cfg_125",
|
||||
"gmac2_rgmii_rx", "gmac2_rmii_ref",
|
||||
"gmac3_sgmii_tx", "gmac3_sgmii_rx",
|
||||
"osc";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-per3crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 Peripheral-3 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-per3crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Non Coherent NOC Initiator
|
||||
- description: Non Coherent NOC Target
|
||||
- description: Configure 125MHz
|
||||
- description: GMAC0 RMII Reference clock
|
||||
- description: GMAC1 SGMII TX
|
||||
- description: GMAC1 SGMII RX
|
||||
- description: Main Oscillator (25 MHz)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ncnoc_init
|
||||
- const: ncnoc_targ
|
||||
- const: cfg_125
|
||||
- const: gmac0_rmii_rclki
|
||||
- const: gmac1_sgmii_tx
|
||||
- const: gmac1_sgmii_rx
|
||||
- const: osc
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@11c40000 {
|
||||
compatible = "starfive,jhb100-per3crg";
|
||||
reg = <0x11c40000 0x1000>;
|
||||
clocks = <&sys0crg 65>,
|
||||
<&sys1crg 18>,
|
||||
<&sys1crg 19>,
|
||||
<&per3_gmac0_rmii_rclki>,
|
||||
<&per3_gmac1_sgmii_tx>,
|
||||
<&per3_gmac1_sgmii_rx>,
|
||||
<&osc>;
|
||||
clock-names = "ncnoc_init", "ncnoc_targ", "cfg_125",
|
||||
"gmac0_rmii_rclki", "gmac1_sgmii_tx",
|
||||
"gmac1_sgmii_rx", "osc";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-sys0crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 System-0 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-sys0crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Main Oscillator (25 MHz)
|
||||
- description: PLL0
|
||||
- description: PLL1
|
||||
- description: PLL2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: osc
|
||||
- const: pll0
|
||||
- const: pll1
|
||||
- const: pll2
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@13000000 {
|
||||
compatible = "starfive,jhb100-sys0crg";
|
||||
reg = <0x13000000 0x4000>;
|
||||
clocks = <&osc>, <&pll0>, <&pll1>,
|
||||
<&syspll 0>;
|
||||
clock-names = "osc", "pll0", "pll1", "pll2";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-sys1crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 System-1 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-sys1crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Main Oscillator (25 MHz)
|
||||
- description: PLL0
|
||||
- description: PLL1
|
||||
- description: PLL2
|
||||
- description: PLL4
|
||||
- description: PLL5
|
||||
- description: NPU Non Coherent NOC Initiator
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: osc
|
||||
- const: pll0
|
||||
- const: pll1
|
||||
- const: pll2
|
||||
- const: pll4
|
||||
- const: pll5
|
||||
- const: npu_ncnoc_init
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@13004000 {
|
||||
compatible = "starfive,jhb100-sys1crg";
|
||||
reg = <0x13004000 0x4000>;
|
||||
clocks = <&osc>, <&pll0>, <&pll1>,
|
||||
<&syspll 0>, <&syspll 2>,
|
||||
<&syspll 3>, <&sys0crg 61>;
|
||||
clock-names = "osc", "pll0", "pll1", "pll2",
|
||||
"pll4", "pll5", "npu_ncnoc_init";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/starfive,jhb100-sys2crg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 System-2 Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: starfive,jhb100-sys2crg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Main Oscillator (25 MHz)
|
||||
- description: PLL1
|
||||
- description: GPU0 Non Coherent NOC Initiator
|
||||
- description: GPU1 Non Coherent NOC Initiator
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: osc
|
||||
- const: pll1
|
||||
- const: gpu0_ncnoc_init
|
||||
- const: gpu1_ncnoc_init
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/starfive,jhb100-crg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@13008000 {
|
||||
compatible = "starfive,jhb100-sys2crg";
|
||||
reg = <0x13008000 0x4000>;
|
||||
clocks = <&osc>, <&pll1>, <&sys0crg 73>,
|
||||
<&sys0crg 74>;
|
||||
clock-names = "osc", "pll1", "gpu0_ncnoc_init",
|
||||
"gpu1_ncnoc_init";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -37,6 +37,7 @@ properties:
|
||||
- qcom,scm-ipq9574
|
||||
- qcom,scm-ipq9650
|
||||
- qcom,scm-kaanapali
|
||||
- qcom,scm-kuno
|
||||
- qcom,scm-maili
|
||||
- qcom,scm-mdm9607
|
||||
- qcom,scm-milos
|
||||
@@ -44,6 +45,7 @@ properties:
|
||||
- qcom,scm-msm8660
|
||||
- qcom,scm-msm8916
|
||||
- qcom,scm-msm8937
|
||||
- qcom,scm-msm8952
|
||||
- qcom,scm-msm8953
|
||||
- qcom,scm-msm8960
|
||||
- qcom,scm-msm8974
|
||||
@@ -152,6 +154,7 @@ allOf:
|
||||
- qcom,scm-msm8660
|
||||
- qcom,scm-msm8916
|
||||
- qcom,scm-msm8937
|
||||
- qcom,scm-msm8952
|
||||
- qcom,scm-msm8953
|
||||
- qcom,scm-msm8960
|
||||
- qcom,scm-msm8974
|
||||
@@ -198,6 +201,7 @@ allOf:
|
||||
- qcom,scm-msm8226
|
||||
- qcom,scm-msm8916
|
||||
- qcom,scm-msm8937
|
||||
- qcom,scm-msm8952
|
||||
- qcom,scm-msm8953
|
||||
- qcom,scm-msm8974
|
||||
- qcom,scm-msm8976
|
||||
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- samsung,exynos2200-chipid
|
||||
- samsung,exynos5515-chipid
|
||||
- samsung,exynos7885-chipid
|
||||
- samsung,exynos8895-chipid
|
||||
- samsung,exynos9610-chipid
|
||||
|
||||
@@ -50,6 +50,7 @@ properties:
|
||||
- enum:
|
||||
- qcom,eliza-llcc-bwmon
|
||||
- qcom,hawi-llcc-bwmon
|
||||
- qcom,milos-cpu-bwmon
|
||||
- qcom,qcs615-llcc-bwmon
|
||||
- qcom,qcs8300-llcc-bwmon
|
||||
- qcom,sa8775p-llcc-bwmon
|
||||
|
||||
@@ -21,6 +21,7 @@ properties:
|
||||
- qcom,glymur-cpucp-mbox
|
||||
- qcom,hawi-cpucp-mbox
|
||||
- qcom,kaanapali-cpucp-mbox
|
||||
- qcom,maili-cpucp-mbox
|
||||
- qcom,nord-cpucp-mbox
|
||||
- qcom,sm8750-cpucp-mbox
|
||||
- const: qcom,x1e80100-cpucp-mbox
|
||||
|
||||
@@ -16,7 +16,7 @@ description: |
|
||||
MediaTek SMI have two generations of HW architecture, here is the list
|
||||
which generation the SoCs use:
|
||||
generation 1: mt2701 and mt7623.
|
||||
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192 and mt8195.
|
||||
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8189, mt8192 and mt8195.
|
||||
|
||||
There's slight differences between the two SMI, for generation 2, the
|
||||
register which control the iommu port is at each larb's register base. But
|
||||
@@ -25,6 +25,21 @@ description: |
|
||||
SMI generation 1 to transform the smi clock into emi clock domain, but that is
|
||||
not needed for SMI generation 2.
|
||||
|
||||
The smi-common connects with smi-larb and IOMMU. The maximum inputs number of
|
||||
a smi-common is 8. In SMI generation 2, the engines number may be over 8.
|
||||
In this case, we use a smi-sub-common to merge some larbs.
|
||||
The block diagram something is like:
|
||||
|
||||
IOMMU
|
||||
| |
|
||||
smi-common
|
||||
---------------------------
|
||||
| | ...
|
||||
larb0 sub-common ... <-max number is 8
|
||||
----------------
|
||||
| | ...
|
||||
larb1 larbX ... <-max number is 8
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
@@ -40,6 +55,8 @@ properties:
|
||||
- mediatek,mt8186-smi-common
|
||||
- mediatek,mt8188-smi-common-vdo
|
||||
- mediatek,mt8188-smi-common-vpp
|
||||
- mediatek,mt8189-smi-common
|
||||
- mediatek,mt8189-smi-sub-common
|
||||
- mediatek,mt8192-smi-common
|
||||
- mediatek,mt8195-smi-common-vdo
|
||||
- mediatek,mt8195-smi-common-vpp
|
||||
@@ -108,6 +125,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- mediatek,mt8189-smi-sub-common
|
||||
- mediatek,mt8195-smi-sub-common
|
||||
then:
|
||||
required:
|
||||
@@ -157,6 +175,7 @@ allOf:
|
||||
- mediatek,mt6795-smi-common
|
||||
- mediatek,mt8167-smi-common
|
||||
- mediatek,mt8173-smi-common
|
||||
- mediatek,mt8189-smi-common
|
||||
|
||||
then:
|
||||
properties:
|
||||
|
||||
@@ -27,6 +27,7 @@ properties:
|
||||
- mediatek,mt8183-smi-larb
|
||||
- mediatek,mt8186-smi-larb
|
||||
- mediatek,mt8188-smi-larb
|
||||
- mediatek,mt8189-smi-larb
|
||||
- mediatek,mt8192-smi-larb
|
||||
- mediatek,mt8195-smi-larb
|
||||
|
||||
@@ -85,6 +86,7 @@ allOf:
|
||||
- mediatek,mt8183-smi-larb
|
||||
- mediatek,mt8186-smi-larb
|
||||
- mediatek,mt8188-smi-larb
|
||||
- mediatek,mt8189-smi-larb
|
||||
- mediatek,mt8195-smi-larb
|
||||
|
||||
then:
|
||||
@@ -119,6 +121,7 @@ allOf:
|
||||
- mediatek,mt6779-smi-larb
|
||||
- mediatek,mt8186-smi-larb
|
||||
- mediatek,mt8188-smi-larb
|
||||
- mediatek,mt8189-smi-larb
|
||||
- mediatek,mt8192-smi-larb
|
||||
- mediatek,mt8195-smi-larb
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ properties:
|
||||
- nxp,s32g3-gpr
|
||||
- qcom,apq8064-mmss-sfpb
|
||||
- qcom,apq8064-sps-sic
|
||||
- qcom,msm8960-sps-sic
|
||||
- rockchip,px30-qos
|
||||
- rockchip,rk3036-qos
|
||||
- rockchip,rk3066-qos
|
||||
|
||||
@@ -16,15 +16,21 @@ maintainers:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amlogic,meson-gx-clk-measure
|
||||
- amlogic,meson8-clk-measure
|
||||
- amlogic,meson8b-clk-measure
|
||||
- amlogic,a1-clk-measure
|
||||
- amlogic,a4-clk-measure
|
||||
- amlogic,a5-clk-measure
|
||||
- amlogic,a9-clk-measure
|
||||
- amlogic,c3-clk-measure
|
||||
- amlogic,meson-axg-clk-measure
|
||||
- amlogic,meson-g12a-clk-measure
|
||||
- amlogic,meson-gx-clk-measure
|
||||
- amlogic,meson-sm1-clk-measure
|
||||
- amlogic,c3-clk-measure
|
||||
- amlogic,meson8-clk-measure
|
||||
- amlogic,meson8b-clk-measure
|
||||
- amlogic,s4-clk-measure
|
||||
- amlogic,a1-clk-measure
|
||||
- amlogic,s6-clk-measure
|
||||
- amlogic,s7-clk-measure
|
||||
- amlogic,s7d-clk-measure
|
||||
- amlogic,t7-clk-measure
|
||||
|
||||
reg:
|
||||
|
||||
@@ -120,7 +120,9 @@ allOf:
|
||||
properties:
|
||||
qcom,glink-channels:
|
||||
items:
|
||||
- const: adsp_apps
|
||||
- enum:
|
||||
- adsp_apps
|
||||
- modem_apps
|
||||
power-domains: false
|
||||
else:
|
||||
properties:
|
||||
|
||||
@@ -18,15 +18,22 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,rpmh-stats
|
||||
- qcom,sdm845-rpmh-stats
|
||||
- qcom,rpm-stats
|
||||
# For older RPM firmware versions with fixed offset for the sleep stats
|
||||
- qcom,apq8084-rpm-stats
|
||||
- qcom,msm8226-rpm-stats
|
||||
- qcom,msm8916-rpm-stats
|
||||
- qcom,msm8974-rpm-stats
|
||||
oneOf:
|
||||
- enum:
|
||||
- qcom,rpmh-stats
|
||||
- qcom,sdm845-rpmh-stats
|
||||
- qcom,rpm-stats
|
||||
# For older RPM firmware versions with fixed offset for the sleep stats
|
||||
- qcom,apq8084-rpm-stats
|
||||
- qcom,msm8226-rpm-stats
|
||||
- qcom,msm8916-rpm-stats
|
||||
- qcom,msm8974-rpm-stats
|
||||
# SoC-specific compatibles that also read subsystem-level stats,
|
||||
# falling back to "qcom,rpm-stats" for SoC-level stats only
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,shikra-rpm-stats
|
||||
- const: qcom,rpm-stats
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/starfive/starfive,jhb100-syscon.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive JHB100 SoC system controller
|
||||
|
||||
maintainers:
|
||||
- Kevin Xie <kevin.xie@starfivetech.com>
|
||||
- Changhuang Liang <changhuang.liang@starfivetech.com>
|
||||
|
||||
description:
|
||||
The StarFive JHB100 SoC system controller contains MMIO registers used by
|
||||
other hardware modules (e.g., PLL, eMMC, PCIe). These modules access
|
||||
specific register offsets, bit masks, and shifts within the system
|
||||
controller region for configuration and status.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- starfive,jhb100-b2h-syscon
|
||||
- starfive,jhb100-gpu-syscon
|
||||
- starfive,jhb100-h2b-syscon
|
||||
- starfive,jhb100-host-syscon
|
||||
- starfive,jhb100-husb-syscon
|
||||
- starfive,jhb100-husbcmn-syscon
|
||||
- starfive,jhb100-husbd-syscon
|
||||
- starfive,jhb100-npu-syscon
|
||||
- starfive,jhb100-pcieep-ecsr-syscon
|
||||
- starfive,jhb100-pcierp-ecsr-syscon
|
||||
- starfive,jhb100-pcierp-syscon
|
||||
- starfive,jhb100-per0-syscon
|
||||
- starfive,jhb100-per1-syscon
|
||||
- starfive,jhb100-per2-syscon
|
||||
- starfive,jhb100-per3-syscon
|
||||
- starfive,jhb100-sfc-filter-syscon
|
||||
- starfive,jhb100-strap-syscon
|
||||
- starfive,jhb100-sys0-syscon
|
||||
- starfive,jhb100-sys1-syscon
|
||||
- starfive,jhb100-sys2-syscon
|
||||
- starfive,jhb100-usb-syscon
|
||||
- starfive,jhb100-vout-syscon
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- starfive,jhb100-per0-syscon
|
||||
- starfive,jhb100-per1-syscon
|
||||
- starfive,jhb100-sys0-syscon
|
||||
then:
|
||||
required:
|
||||
- clocks
|
||||
- '#clock-cells'
|
||||
else:
|
||||
properties:
|
||||
clocks: false
|
||||
'#clock-cells': false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: starfive,jhb100-pcierp-syscon
|
||||
then:
|
||||
required:
|
||||
- '#reset-cells'
|
||||
else:
|
||||
properties:
|
||||
'#reset-cells': false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
syscon@13010000 {
|
||||
compatible = "starfive,jhb100-sys0-syscon", "syscon";
|
||||
reg = <0x13010000 0x2000>;
|
||||
clocks = <&osc>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
syscon@13014000 {
|
||||
compatible = "starfive,jhb100-sys1-syscon", "syscon";
|
||||
reg = <0x13014000 0x4000>;
|
||||
};
|
||||
|
||||
syscon@11719000 {
|
||||
compatible = "starfive,jhb100-pcierp-syscon", "syscon";
|
||||
reg = <0x11719000 0x1000>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
...
|
||||
@@ -27,6 +27,7 @@ properties:
|
||||
- enum:
|
||||
- qcom,hawi-spmi-pmic-arb
|
||||
- qcom,kaanapali-spmi-pmic-arb
|
||||
- qcom,maili-spmi-pmic-arb
|
||||
- const: qcom,glymur-spmi-pmic-arb
|
||||
- enum:
|
||||
- qcom,glymur-spmi-pmic-arb
|
||||
|
||||
@@ -18,7 +18,6 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,apq8064-imem
|
||||
- qcom,ipq5424-imem
|
||||
- qcom,msm8226-imem
|
||||
- qcom,msm8974-imem
|
||||
- qcom,msm8976-imem
|
||||
|
||||
@@ -37,12 +37,14 @@ properties:
|
||||
- qcom,eliza-imem
|
||||
- qcom,glymur-imem
|
||||
- qcom,hawi-imem
|
||||
- qcom,ipq5424-imem
|
||||
- qcom,kaanapali-imem
|
||||
- qcom,maili-imem
|
||||
- qcom,milos-imem
|
||||
- qcom,rpm-msg-ram
|
||||
- qcom,shikra-imem
|
||||
- rockchip,rk3288-pmu-sram
|
||||
- samsung,exynos850-acpm-sram
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -159,6 +161,7 @@ if:
|
||||
enum:
|
||||
- qcom,rpm-msg-ram
|
||||
- rockchip,rk3288-pmu-sram
|
||||
- samsung,exynos850-acpm-sram
|
||||
then:
|
||||
required:
|
||||
- "#address-cells"
|
||||
|
||||
@@ -3444,6 +3444,7 @@ F: include/linux/soc/qcom/
|
||||
ARM/QUALCOMM SUPPORT
|
||||
M: Bjorn Andersson <andersson@kernel.org>
|
||||
M: Konrad Dybcio <konradybcio@kernel.org>
|
||||
R: Abel Vesa <abelvesa@kernel.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
C: irc://irc.oftc.net/linux-msm
|
||||
@@ -26774,6 +26775,7 @@ F: drivers/pmdomain/arm/
|
||||
F: drivers/powercap/arm_scmi_powercap.c
|
||||
F: drivers/regulator/scmi-regulator.c
|
||||
F: drivers/reset/reset-scmi.c
|
||||
F: include/linux/device-id/scmi.h
|
||||
F: include/linux/sc[mp]i_protocol.h
|
||||
F: include/trace/events/scmi.h
|
||||
F: include/uapi/linux/virtio_scmi.h
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#define AT91_PM_ULP1 0x03
|
||||
#define AT91_PM_BACKUP 0x04
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
struct at91_pm_data {
|
||||
void __iomem *pmc;
|
||||
void __iomem *ramc[2];
|
||||
|
||||
@@ -197,6 +197,7 @@ config ARM64
|
||||
if DYNAMIC_FTRACE_WITH_ARGS
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
|
||||
select HAVE_SHARED_GPIOS
|
||||
select HAVE_BUILDTIME_MCOUNT_SORT
|
||||
select HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
select HAVE_GUP_FAST
|
||||
|
||||
@@ -336,7 +336,6 @@ config ARCH_QCOM
|
||||
select GPIOLIB
|
||||
select PINCTRL
|
||||
select HAVE_PWRCTRL if PCI
|
||||
select HAVE_SHARED_GPIOS
|
||||
help
|
||||
This enables support for the ARMv8 based Qualcomm chipsets.
|
||||
|
||||
|
||||
@@ -167,9 +167,12 @@ static int __cci_ace_get_port(struct device_node *dn, int type)
|
||||
cci_portn = of_parse_phandle(dn, "cci-control-port", 0);
|
||||
for (i = 0; i < nb_cci_ports; i++) {
|
||||
ace_match = ports[i].type == type;
|
||||
if (ace_match && cci_portn == ports[i].dn)
|
||||
if (ace_match && cci_portn == ports[i].dn) {
|
||||
of_node_put(cci_portn);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
of_node_put(cci_portn);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -199,6 +202,7 @@ static void cci_ace_init_ports(void)
|
||||
continue;
|
||||
|
||||
port = __cci_ace_get_port(cpun, ACE_PORT);
|
||||
of_node_put(cpun);
|
||||
if (port < 0)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define pr_fmt(fmt) "fsl-mc: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/ioport.h>
|
||||
@@ -797,6 +798,10 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
|
||||
}
|
||||
dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
|
||||
|
||||
mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
|
||||
mc_dev->dev.dma_mask = &mc_dev->dma_mask;
|
||||
mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask;
|
||||
|
||||
if (strcmp(obj_desc->type, "dprc") == 0) {
|
||||
struct fsl_mc_io *mc_io2;
|
||||
|
||||
@@ -838,9 +843,6 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
|
||||
* parent's ICID.
|
||||
*/
|
||||
mc_dev->icid = parent_mc_dev->icid;
|
||||
mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
|
||||
mc_dev->dev.dma_mask = &mc_dev->dma_mask;
|
||||
mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1032,6 +1034,20 @@ static int fsl_mc_firmware_check(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fsl_mc_purge_dpmac_fwnode_links(struct device *dev)
|
||||
{
|
||||
struct device_node *dpmacs, *child;
|
||||
|
||||
dpmacs = of_get_child_by_name(dev->of_node, "dpmacs");
|
||||
if (!dpmacs)
|
||||
return;
|
||||
|
||||
for_each_child_of_node(dpmacs, child)
|
||||
fwnode_links_purge(of_fwnode_handle(child));
|
||||
|
||||
of_node_put(dpmacs);
|
||||
}
|
||||
|
||||
/*
|
||||
* fsl_mc_bus_probe - callback invoked when the root MC bus is being
|
||||
* added
|
||||
@@ -1133,6 +1149,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
|
||||
&mc->num_translation_ranges);
|
||||
if (error < 0)
|
||||
goto error_cleanup_mc_io;
|
||||
|
||||
fsl_mc_purge_dpmac_fwnode_links(&pdev->dev);
|
||||
}
|
||||
|
||||
error = dprc_get_container_id(mc_io, 0, &container_id);
|
||||
@@ -1264,35 +1282,43 @@ static int __init fsl_mc_bus_driver_init(void)
|
||||
error = bus_register(&fsl_mc_bus_type);
|
||||
if (error < 0) {
|
||||
pr_err("bus type registration failed: %d\n", error);
|
||||
goto error_cleanup_cache;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = platform_driver_register(&fsl_mc_bus_driver);
|
||||
if (error < 0) {
|
||||
pr_err("platform_driver_register() failed: %d\n", error);
|
||||
error = bus_register_notifier(&platform_bus_type, &fsl_mc_nb);
|
||||
if (error < 0)
|
||||
goto error_cleanup_bus;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup_bus:
|
||||
bus_unregister(&fsl_mc_bus_type);
|
||||
return error;
|
||||
}
|
||||
postcore_initcall(fsl_mc_bus_driver_init);
|
||||
|
||||
static int __init fsl_mc_bus_drivers_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = dprc_driver_init();
|
||||
if (error < 0)
|
||||
goto error_cleanup_driver;
|
||||
return error;
|
||||
|
||||
error = fsl_mc_allocator_driver_init();
|
||||
if (error < 0)
|
||||
goto error_cleanup_dprc_driver;
|
||||
|
||||
return bus_register_notifier(&platform_bus_type, &fsl_mc_nb);
|
||||
error = platform_driver_register(&fsl_mc_bus_driver);
|
||||
if (error < 0) {
|
||||
pr_err("platform_driver_register() failed: %d\n", error);
|
||||
goto error_cleanup_dprc_driver;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup_dprc_driver:
|
||||
dprc_driver_exit();
|
||||
|
||||
error_cleanup_driver:
|
||||
platform_driver_unregister(&fsl_mc_bus_driver);
|
||||
|
||||
error_cleanup_bus:
|
||||
bus_unregister(&fsl_mc_bus_type);
|
||||
|
||||
error_cleanup_cache:
|
||||
return error;
|
||||
}
|
||||
postcore_initcall(fsl_mc_bus_driver_init);
|
||||
subsys_initcall_sync(fsl_mc_bus_drivers_init);
|
||||
@@ -57,7 +57,7 @@ static void fsl_mc_write_msi_msg(struct msi_desc *msi_desc, struct msi_msg *msg)
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* IRQ is for for a child device of mc_bus_dev
|
||||
* IRQ is for a child device of mc_bus_dev
|
||||
*/
|
||||
error = dprc_set_obj_irq(mc_bus_dev->mc_io,
|
||||
MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
|
||||
|
||||
Vendored
+1
-1
@@ -170,7 +170,7 @@ static void hisi_soc_hha_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct acpi_device_id hisi_soc_hha_ids[] = {
|
||||
{ "HISI0511", },
|
||||
{ .id = "HISI0511" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, hisi_soc_hha_ids);
|
||||
|
||||
Vendored
+1
-1
@@ -275,7 +275,7 @@ static int sifive_ccache_probe(struct platform_device *pdev)
|
||||
|
||||
rc = devm_request_irq(dev, g_irq[i], ccache_int_handler, 0, "ccache_ecc", NULL);
|
||||
if (rc)
|
||||
return dev_err_probe(dev, rc, "Could not request IRQ %d\n", g_irq[i]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define SCMI_UEVENT_MODALIAS_FMT "%s:%02x:%s"
|
||||
#define SCMI_UEVENT_MODALIAS_FMT SCMI_MODULE_PREFIX "%02x:%s"
|
||||
|
||||
BLOCKING_NOTIFIER_HEAD(scmi_requested_devices_nh);
|
||||
EXPORT_SYMBOL_GPL(scmi_requested_devices_nh);
|
||||
@@ -185,7 +186,7 @@ static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
|
||||
const struct scmi_device_id *entry;
|
||||
int ret;
|
||||
|
||||
for (entry = id_table; entry->name; entry++) {
|
||||
for (entry = id_table; entry->name[0]; entry++) {
|
||||
ret = scmi_protocol_device_request(entry);
|
||||
if (ret)
|
||||
goto err_unrequest;
|
||||
@@ -205,7 +206,7 @@ scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
|
||||
{
|
||||
const struct scmi_device_id *entry;
|
||||
|
||||
for (entry = id_table; entry->name; entry++)
|
||||
for (entry = id_table; entry->name[0]; entry++)
|
||||
scmi_protocol_device_unrequest(entry);
|
||||
}
|
||||
|
||||
@@ -219,10 +220,10 @@ static int __scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
|
||||
const struct scmi_device_id *id_table,
|
||||
bool skip_transport)
|
||||
{
|
||||
if (!id_table || !id_table->name)
|
||||
if (!id_table || !id_table->name[0])
|
||||
return 0;
|
||||
|
||||
for (; id_table->protocol_id && id_table->name; id_table++)
|
||||
for (; id_table->protocol_id && id_table->name[0]; id_table++)
|
||||
if (id_table->protocol_id == scmi_dev->protocol_id &&
|
||||
!(skip_transport && scmi_device_is_transport(scmi_dev)) &&
|
||||
!strcmp(id_table->name, scmi_dev->name))
|
||||
@@ -266,7 +267,7 @@ scmi_child_dev_find_get(struct device *parent, int prot_id, const char *name)
|
||||
struct device *dev;
|
||||
|
||||
id_table[0].protocol_id = prot_id;
|
||||
id_table[0].name = name;
|
||||
strscpy(id_table[0].name, name, sizeof(id_table[0].name));
|
||||
|
||||
dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
|
||||
if (!dev)
|
||||
@@ -300,8 +301,7 @@ static int scmi_device_uevent(const struct device *dev, struct kobj_uevent_env *
|
||||
const struct scmi_device *scmi_dev = to_scmi_dev(dev);
|
||||
|
||||
return add_uevent_var(env, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT,
|
||||
dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
|
||||
scmi_dev->name);
|
||||
scmi_dev->protocol_id, scmi_dev->name);
|
||||
}
|
||||
|
||||
static ssize_t modalias_show(struct device *dev,
|
||||
@@ -309,9 +309,8 @@ static ssize_t modalias_show(struct device *dev,
|
||||
{
|
||||
struct scmi_device *scmi_dev = to_scmi_dev(dev);
|
||||
|
||||
return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT,
|
||||
dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
|
||||
scmi_dev->name);
|
||||
return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT "\n",
|
||||
scmi_dev->protocol_id, scmi_dev->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
@@ -429,17 +428,16 @@ static void scmi_device_release(struct device *dev)
|
||||
struct scmi_device *scmi_dev = to_scmi_dev(dev);
|
||||
|
||||
scmi_device_release_resources(scmi_dev);
|
||||
of_node_put(dev->of_node);
|
||||
fwnode_handle_put(dev_fwnode(dev));
|
||||
kfree_const(scmi_dev->name);
|
||||
kfree(scmi_dev);
|
||||
}
|
||||
|
||||
static void __scmi_device_destroy(struct scmi_device *scmi_dev)
|
||||
{
|
||||
pr_debug("(%pOF) Destroying SCMI device '%s' for protocol 0x%x (%s)\n",
|
||||
scmi_dev->dev.parent->of_node,
|
||||
dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
|
||||
scmi_dev->name);
|
||||
pr_debug("(%pfwf) Destroying SCMI device '%s' for protocol 0x%x (%s)\n",
|
||||
dev_fwnode(&scmi_dev->dev), dev_name(&scmi_dev->dev),
|
||||
scmi_dev->protocol_id, scmi_dev->name);
|
||||
|
||||
device_del(&scmi_dev->dev);
|
||||
scmi_device_release_resources(scmi_dev);
|
||||
@@ -447,7 +445,7 @@ static void __scmi_device_destroy(struct scmi_device *scmi_dev)
|
||||
}
|
||||
|
||||
static struct scmi_device *
|
||||
__scmi_device_create(struct device_node *np, struct device *parent,
|
||||
__scmi_device_create(struct fwnode_handle *fwnode, struct device *parent,
|
||||
int protocol, const char *name)
|
||||
{
|
||||
int id, retval;
|
||||
@@ -458,7 +456,7 @@ __scmi_device_create(struct device_node *np, struct device *parent,
|
||||
* If the same protocol/name device already exist under the same parent
|
||||
* (i.e. SCMI instance) just return the existent device.
|
||||
* This avoids any race between the SCMI driver, creating devices for
|
||||
* each DT defined protocol at probe time, and the concurrent
|
||||
* each fwnode defined protocol at probe time, and the concurrent
|
||||
* registration of SCMI drivers.
|
||||
*/
|
||||
scmi_dev = scmi_child_dev_find_get(parent, protocol, name);
|
||||
@@ -495,7 +493,7 @@ __scmi_device_create(struct device_node *np, struct device *parent,
|
||||
|
||||
scmi_dev->id = id;
|
||||
scmi_dev->dev.parent = parent;
|
||||
device_set_node(&scmi_dev->dev, of_fwnode_handle(of_node_get(np)));
|
||||
device_set_node(&scmi_dev->dev, fwnode_handle_get(fwnode));
|
||||
scmi_dev->dev.bus = &scmi_bus_type;
|
||||
scmi_dev->dev.release = scmi_device_release;
|
||||
dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
|
||||
@@ -504,8 +502,8 @@ __scmi_device_create(struct device_node *np, struct device *parent,
|
||||
if (retval)
|
||||
goto put_dev;
|
||||
|
||||
pr_debug("(%pOF) Created SCMI device '%s' for protocol 0x%x (%s)\n",
|
||||
parent->of_node, dev_name(&scmi_dev->dev), protocol, name);
|
||||
pr_debug("(%pfwf) Created SCMI device '%s' - protocol 0x%x (%s)\n",
|
||||
fwnode, dev_name(&scmi_dev->dev), protocol, name);
|
||||
|
||||
return scmi_dev;
|
||||
put_dev:
|
||||
@@ -521,23 +519,51 @@ free_dev:
|
||||
}
|
||||
|
||||
static struct scmi_device *
|
||||
_scmi_device_create(struct device_node *np, struct device *parent,
|
||||
_scmi_device_create(struct fwnode_handle *fwnode, struct device *parent,
|
||||
int protocol, const char *name)
|
||||
{
|
||||
struct scmi_device *sdev;
|
||||
|
||||
sdev = __scmi_device_create(np, parent, protocol, name);
|
||||
sdev = __scmi_device_create(fwnode, parent, protocol, name);
|
||||
if (!sdev)
|
||||
pr_err("(%pOF) Failed to create device for protocol 0x%x (%s)\n",
|
||||
parent->of_node, protocol, name);
|
||||
pr_err("(%pfwf) Failed to create device - protocol 0x%x (%s)\n",
|
||||
fwnode, protocol, name);
|
||||
|
||||
return sdev;
|
||||
}
|
||||
|
||||
/* Standard protocols table */
|
||||
static const struct scmi_device_id scmi_std_id_table[] = {
|
||||
{ SCMI_PROTOCOL_POWER, "genpd" },
|
||||
{ SCMI_PROTOCOL_SYSTEM, "syspower" },
|
||||
{ SCMI_PROTOCOL_PERF, "perf" },
|
||||
{ SCMI_PROTOCOL_PERF, "cpufreq" },
|
||||
{ SCMI_PROTOCOL_CLOCK, "clocks" },
|
||||
{ SCMI_PROTOCOL_SENSOR, "hwmon" },
|
||||
{ SCMI_PROTOCOL_SENSOR, "iiodev" },
|
||||
{ SCMI_PROTOCOL_RESET, "reset" },
|
||||
{ SCMI_PROTOCOL_VOLTAGE, "regulator" },
|
||||
{ SCMI_PROTOCOL_POWERCAP, "powercap" },
|
||||
{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
|
||||
{ SCMI_PROTOCOL_PINCTRL, "pinctrl-imx" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static bool scmi_device_id_in_std_id_table(const struct scmi_device_id *id)
|
||||
{
|
||||
for (int i = 0; scmi_std_id_table[i].name[0]; i++) {
|
||||
if (scmi_std_id_table[i].protocol_id == id->protocol_id &&
|
||||
!strcmp(scmi_std_id_table[i].name, id->name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_device_create - A method to create one or more SCMI devices
|
||||
*
|
||||
* @np: A reference to the device node to use for the new device(s)
|
||||
* @fwnode: A reference to the device node to use for the new device(s)
|
||||
* @parent: The parent device to use identifying a specific SCMI instance
|
||||
* @protocol: The SCMI protocol to be associated with this device
|
||||
* @name: The requested-name of the device to be created; this is optional
|
||||
@@ -557,30 +583,47 @@ _scmi_device_create(struct device_node *np, struct device *parent,
|
||||
* could have been potentially created for a whole protocol, unless no
|
||||
* device was found to have been requested for that specific protocol.
|
||||
*/
|
||||
struct scmi_device *scmi_device_create(struct device_node *np,
|
||||
struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode,
|
||||
struct device *parent, int protocol,
|
||||
const char *name)
|
||||
{
|
||||
struct list_head *phead;
|
||||
struct scmi_requested_dev *rdev;
|
||||
struct scmi_device *scmi_dev = NULL;
|
||||
struct scmi_device *sdev, *scmi_dev = NULL;
|
||||
|
||||
if (name)
|
||||
return _scmi_device_create(np, parent, protocol, name);
|
||||
return _scmi_device_create(fwnode, parent, protocol, name);
|
||||
|
||||
/*
|
||||
* Always create devices for standard protocols, even if the device-ids
|
||||
* have not been registered into scmi_requested_devices yet. This allows
|
||||
* auto-loading of SCMI protocol driver modules for standard protocols.
|
||||
*/
|
||||
for (int i = 0; scmi_std_id_table[i].name[0]; i++) {
|
||||
if (scmi_std_id_table[i].protocol_id != protocol)
|
||||
continue;
|
||||
|
||||
sdev = _scmi_device_create(fwnode, parent, protocol,
|
||||
scmi_std_id_table[i].name);
|
||||
if (sdev)
|
||||
scmi_dev = sdev;
|
||||
}
|
||||
|
||||
mutex_lock(&scmi_requested_devices_mtx);
|
||||
phead = idr_find(&scmi_requested_devices, protocol);
|
||||
/* Nothing to do. */
|
||||
if (!phead) {
|
||||
mutex_unlock(&scmi_requested_devices_mtx);
|
||||
return NULL;
|
||||
return scmi_dev;
|
||||
}
|
||||
|
||||
/* Walk the list of requested devices for protocol and create them */
|
||||
list_for_each_entry(rdev, phead, node) {
|
||||
struct scmi_device *sdev;
|
||||
/* Standard proto matches already have their dev created above */
|
||||
if (scmi_device_id_in_std_id_table(rdev->id_table))
|
||||
continue;
|
||||
|
||||
sdev = _scmi_device_create(np, parent,
|
||||
sdev = _scmi_device_create(fwnode, parent,
|
||||
rdev->id_table->protocol_id,
|
||||
rdev->id_table->name);
|
||||
if (sdev)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef _SCMI_COMMON_H
|
||||
#define _SCMI_COMMON_H
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/device.h>
|
||||
@@ -152,7 +153,7 @@ extern const struct bus_type scmi_bus_type;
|
||||
#define SCMI_BUS_NOTIFY_DEVICE_UNREQUEST 1
|
||||
extern struct blocking_notifier_head scmi_requested_devices_nh;
|
||||
|
||||
struct scmi_device *scmi_device_create(struct device_node *np,
|
||||
struct scmi_device *scmi_device_create(struct fwnode_handle *fwnode,
|
||||
struct device *parent, int protocol,
|
||||
const char *name);
|
||||
void scmi_device_destroy(struct device *parent, int protocol, const char *name);
|
||||
@@ -206,7 +207,8 @@ struct scmi_chan_info {
|
||||
* @poll_done: Callback to poll transfer status
|
||||
*/
|
||||
struct scmi_transport_ops {
|
||||
bool (*chan_available)(struct device_node *of_node, int idx);
|
||||
bool (*chan_available)(struct fwnode_handle *fwnode, int prot_id,
|
||||
int idx);
|
||||
int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
bool tx);
|
||||
int (*chan_free)(int id, void *p, void *data);
|
||||
@@ -232,7 +234,7 @@ struct scmi_transport_ops {
|
||||
* be pending simultaneously in the system. May be overridden by the
|
||||
* get_max_msg op.
|
||||
* @max_msg_size: Maximum size of data payload per message that can be handled.
|
||||
* @atomic_threshold: Optional system wide DT-configured threshold, expressed
|
||||
* @atomic_threshold: Optional system wide fwnode-configured threshold, expressed
|
||||
* in microseconds, for atomic operations.
|
||||
* Only SCMI synchronous commands reported by the platform
|
||||
* to have an execution latency lesser-equal to the threshold
|
||||
@@ -240,7 +242,8 @@ struct scmi_transport_ops {
|
||||
* decision is finally left up to the SCMI drivers.
|
||||
* @no_completion_irq: Flag to indicate that this transport has no completion
|
||||
* interrupt and has to be polled. This is similar to the
|
||||
* force_polling below, except this is set via DT property.
|
||||
* force_polling below, except this is set via fwnode
|
||||
* property.
|
||||
* @force_polling: Flag to force this whole transport to use SCMI core polling
|
||||
* mechanism instead of completion interrupts even if available.
|
||||
* @sync_cmds_completed_on_ret: Flag to indicate that the transport assures
|
||||
@@ -284,6 +287,28 @@ static inline bool is_polling_enabled(struct scmi_chan_info *cinfo,
|
||||
is_transport_polling_capable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_xfer_async_response_arm - Arm the delayed response completion
|
||||
*
|
||||
* @xfer: A reference to the xfer to arm
|
||||
* @async_done: The completion to signal upon reception of a delayed response,
|
||||
* or NULL to disarm @xfer.
|
||||
*/
|
||||
static inline void scmi_xfer_async_response_arm(struct scmi_xfer *xfer,
|
||||
struct completion *async_done)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&xfer->lock, flags);
|
||||
xfer->async_done = async_done;
|
||||
spin_unlock_irqrestore(&xfer->lock, flags);
|
||||
}
|
||||
|
||||
static inline void scmi_xfer_async_response_disarm(struct scmi_xfer *xfer)
|
||||
{
|
||||
scmi_xfer_async_response_arm(xfer, NULL);
|
||||
}
|
||||
|
||||
void scmi_xfer_raw_put(const struct scmi_handle *handle,
|
||||
struct scmi_xfer *xfer);
|
||||
struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle);
|
||||
@@ -465,6 +490,17 @@ struct scmi_transport_core_operations {
|
||||
const struct scmi_message_operations *msg;
|
||||
};
|
||||
|
||||
struct scmi_dsd_info {
|
||||
u32 protocol_id;
|
||||
const char *const property_name;
|
||||
};
|
||||
|
||||
static const struct scmi_dsd_info scmi_dsd_info_list[] __maybe_unused = {
|
||||
{ SCMI_PROTOCOL_BASE, "arm-arml0001-transport-pcc" },
|
||||
{ SCMI_PROTOCOL_POWERCAP, "arm-arml0001-protocol-pcap" },
|
||||
{ SCMI_PROTOCOL_TELEMETRY, "arm-arml0001-protocol-telemetry" },
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scmi_transport_handle - Transport instance handle
|
||||
* @supplier_get: A helper to retrieve the device descriptor, identifying the
|
||||
@@ -615,7 +651,8 @@ struct scmi_transport_supplier __supplier = { \
|
||||
.th.supplier_put = scmi_transport_supplier_put, \
|
||||
}
|
||||
|
||||
#define DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core_ops)\
|
||||
#define __DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __of_match, \
|
||||
__acpi_match, __core_ops) \
|
||||
static void __tag##_dev_free(void *data) \
|
||||
{ \
|
||||
struct platform_device *spdev = data; \
|
||||
@@ -649,7 +686,10 @@ static int __tag##_probe(struct platform_device *pdev) \
|
||||
goto err_mem; \
|
||||
} \
|
||||
\
|
||||
device_set_of_node_from_dev(&spdev->dev, dev); \
|
||||
if (dev_of_node(dev)) \
|
||||
platform_device_set_of_node_from_dev(spdev, dev); \
|
||||
else \
|
||||
platform_device_set_fwnode(spdev, dev_fwnode(dev)); \
|
||||
\
|
||||
strans.supplier = supplier; \
|
||||
memcpy(&strans.desc, &(__desc), sizeof(strans.desc)); \
|
||||
@@ -678,11 +718,18 @@ err_mem: \
|
||||
static struct platform_driver __drv = { \
|
||||
.driver = { \
|
||||
.name = #__tag "_transport", \
|
||||
.of_match_table = __match, \
|
||||
.of_match_table = __of_match, \
|
||||
.acpi_match_table = ACPI_PTR(__acpi_match), \
|
||||
}, \
|
||||
.probe = __tag##_probe, \
|
||||
}
|
||||
|
||||
#define DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core_ops)\
|
||||
__DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, NULL, __core_ops)
|
||||
|
||||
#define DEFINE_SCMI_ACPI_TRANSPORT_DRIVER(__tag, __drv, __desc, __match, __core_ops)\
|
||||
__DEFINE_SCMI_TRANSPORT_DRIVER(__tag, __drv, __desc, NULL, __match, __core_ops)
|
||||
|
||||
void scmi_notification_instance_data_set(const struct scmi_handle *handle,
|
||||
void *priv);
|
||||
void *scmi_notification_instance_data_get(const struct scmi_handle *handle);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/debugfs.h>
|
||||
@@ -30,7 +31,7 @@
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/processor.h>
|
||||
#include <linux/rcupdate.h>
|
||||
@@ -102,7 +103,7 @@ struct scmi_xfers_info {
|
||||
* initialization code to identify this instance.
|
||||
*
|
||||
* Each protocol is initialized independently once for each SCMI platform in
|
||||
* which is defined by DT and implemented by the SCMI server fw.
|
||||
* which is defined by fwnode and implemented by the SCMI server fw.
|
||||
*/
|
||||
struct scmi_protocol_instance {
|
||||
const struct scmi_handle *handle;
|
||||
@@ -137,8 +138,9 @@ struct scmi_protocol_instance {
|
||||
* @protocols_imp: List of protocols implemented, currently maximum of
|
||||
* scmi_base_info.num_protocols elements allocated by the
|
||||
* base protocol
|
||||
* @active_protocols: IDR storing device_nodes for protocols actually defined
|
||||
* in the DT and confirmed as implemented by fw.
|
||||
* @active_protocols: IDR storing fwnodes for protocols actually defined
|
||||
* in the firmware description and confirmed as implemented
|
||||
* by fw.
|
||||
* @notify_priv: Pointer to private data structure specific to notifications.
|
||||
* @node: List head
|
||||
* @users: Number of users of this instance
|
||||
@@ -416,19 +418,19 @@ EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
|
||||
* scmi_create_protocol_devices - Create devices for all pending requests for
|
||||
* this SCMI instance.
|
||||
*
|
||||
* @np: The device node describing the protocol
|
||||
* @fwnode: The firmware node describing the protocol
|
||||
* @info: The SCMI instance descriptor
|
||||
* @prot_id: The protocol ID
|
||||
* @name: The optional name of the device to be created: if not provided this
|
||||
* call will lead to the creation of all the devices currently requested
|
||||
* for the specified protocol.
|
||||
*/
|
||||
static void scmi_create_protocol_devices(struct device_node *np,
|
||||
static void scmi_create_protocol_devices(struct fwnode_handle *fwnode,
|
||||
struct scmi_info *info,
|
||||
int prot_id, const char *name)
|
||||
{
|
||||
mutex_lock(&info->devreq_mtx);
|
||||
scmi_device_create(np, info->dev, prot_id, name);
|
||||
scmi_device_create(fwnode, info->dev, prot_id, name);
|
||||
mutex_unlock(&info->devreq_mtx);
|
||||
}
|
||||
|
||||
@@ -718,6 +720,7 @@ static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle,
|
||||
|
||||
refcount_set(&xfer->users, 1);
|
||||
atomic_set(&xfer->busy, SCMI_XFER_FREE);
|
||||
xfer->async_done = NULL;
|
||||
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
|
||||
|
||||
return xfer;
|
||||
@@ -752,9 +755,10 @@ struct scmi_xfer *scmi_xfer_raw_get(const struct scmi_handle *handle)
|
||||
* @protocol_id: Identifier of the protocol
|
||||
*
|
||||
* Note that in a regular SCMI stack, usually, a protocol has to be defined in
|
||||
* the DT to have an associated channel and be usable; but in Raw mode any
|
||||
* protocol in range is allowed, re-using the Base channel, so as to enable
|
||||
* fuzzing on any protocol without the need of a fully compiled DT.
|
||||
* the firmware description to have an associated channel and be usable; but in
|
||||
* Raw mode any protocol in range is allowed, re-using the Base channel, so as
|
||||
* to enable fuzzing on any protocol without the need of a fully compiled
|
||||
* firmware description.
|
||||
*
|
||||
* Return: A reference to the channel to use, or an ERR_PTR
|
||||
*/
|
||||
@@ -768,7 +772,7 @@ scmi_xfer_raw_channel_get(const struct scmi_handle *handle, u8 protocol_id)
|
||||
if (!cinfo) {
|
||||
if (protocol_id == SCMI_PROTOCOL_BASE)
|
||||
return ERR_PTR(-EINVAL);
|
||||
/* Use Base channel for protocols not defined for DT */
|
||||
/* Use Base channel for protocols not defined for fwnode */
|
||||
cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE);
|
||||
if (!cinfo)
|
||||
return ERR_PTR(-EINVAL);
|
||||
@@ -1064,6 +1068,29 @@ static inline void scmi_xfer_command_release(struct scmi_info *info,
|
||||
__scmi_xfer_put(&info->tx_minfo, xfer);
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_xfer_async_response_complete - Signal a received delayed response
|
||||
*
|
||||
* @xfer: A reference to the xfer whose delayed response was received
|
||||
*
|
||||
* Return: True if a completion was still armed on @xfer and has been
|
||||
* signalled, false if a waiter has already disarmed it due to
|
||||
* timeout or other error.
|
||||
*/
|
||||
static bool scmi_xfer_async_response_complete(struct scmi_xfer *xfer)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct completion *async_done;
|
||||
|
||||
spin_lock_irqsave(&xfer->lock, flags);
|
||||
async_done = xfer->async_done;
|
||||
if (async_done)
|
||||
complete(async_done);
|
||||
spin_unlock_irqrestore(&xfer->lock, flags);
|
||||
|
||||
return !!async_done;
|
||||
}
|
||||
|
||||
static inline void scmi_clear_channel(struct scmi_info *info,
|
||||
struct scmi_chan_info *cinfo)
|
||||
{
|
||||
@@ -1167,8 +1194,12 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
|
||||
|
||||
if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP) {
|
||||
scmi_clear_channel(info, cinfo);
|
||||
complete(xfer->async_done);
|
||||
scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK);
|
||||
if (scmi_xfer_async_response_complete(xfer))
|
||||
scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK);
|
||||
else
|
||||
dev_err(cinfo->dev,
|
||||
"Delayed Response for %d (protocol 0x%X msg 0x%X) received after waiter was disarmed, dropping\n",
|
||||
xfer->hdr.seq, xfer->hdr.protocol_id, xfer->hdr.id);
|
||||
} else {
|
||||
complete(&xfer->done);
|
||||
scmi_inc_count(info->dbg, RESPONSE_OK);
|
||||
@@ -1510,7 +1541,7 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph,
|
||||
int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT);
|
||||
DECLARE_COMPLETION_ONSTACK(async_response);
|
||||
|
||||
xfer->async_done = &async_response;
|
||||
scmi_xfer_async_response_arm(xfer, &async_response);
|
||||
|
||||
/*
|
||||
* Delayed responses should not be polled, so an async command should
|
||||
@@ -1522,7 +1553,7 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph,
|
||||
|
||||
ret = do_xfer(ph, xfer);
|
||||
if (!ret) {
|
||||
if (!wait_for_completion_timeout(xfer->async_done, timeout)) {
|
||||
if (!wait_for_completion_timeout(&async_response, timeout)) {
|
||||
dev_err(ph->dev,
|
||||
"timed out in delayed resp(caller: %pS)\n",
|
||||
(void *)_RET_IP_);
|
||||
@@ -1532,7 +1563,7 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph,
|
||||
}
|
||||
}
|
||||
|
||||
xfer->async_done = NULL;
|
||||
scmi_xfer_async_response_disarm(xfer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2749,7 +2780,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
|
||||
static int scmi_chan_setup(struct scmi_info *info, struct fwnode_handle *fwnode,
|
||||
int prot_id, bool tx)
|
||||
{
|
||||
int ret, idx;
|
||||
@@ -2765,7 +2796,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
|
||||
if (idr_find(idr, prot_id))
|
||||
return -EEXIST;
|
||||
|
||||
if (!info->desc->ops->chan_available(of_node, idx)) {
|
||||
if (!info->desc->ops->chan_available(fwnode, prot_id, idx)) {
|
||||
cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);
|
||||
if (unlikely(!cinfo)) /* Possible only if platform has no Rx */
|
||||
return -EINVAL;
|
||||
@@ -2785,7 +2816,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
|
||||
snprintf(name, sizeof(name), SCMI_TRANSPORT_DEVNAME_PREFIX "_%s_%02X",
|
||||
idx ? "rx" : "tx", prot_id);
|
||||
/* Create a uniquely named, dedicated transport device for this chan */
|
||||
tdev = scmi_device_create(of_node, info->dev, prot_id, name);
|
||||
tdev = scmi_device_create(fwnode, info->dev, prot_id, name);
|
||||
if (!tdev) {
|
||||
dev_err(info->dev,
|
||||
"failed to create transport device (%s)\n", name);
|
||||
@@ -2831,14 +2862,14 @@ idr_alloc:
|
||||
}
|
||||
|
||||
static inline int
|
||||
scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node,
|
||||
scmi_txrx_setup(struct scmi_info *info, struct fwnode_handle *fwnode,
|
||||
int prot_id)
|
||||
{
|
||||
int ret = scmi_chan_setup(info, of_node, prot_id, true);
|
||||
int ret = scmi_chan_setup(info, fwnode, prot_id, true);
|
||||
|
||||
if (!ret) {
|
||||
/* Rx is optional, report only memory errors */
|
||||
ret = scmi_chan_setup(info, of_node, prot_id, false);
|
||||
ret = scmi_chan_setup(info, fwnode, prot_id, false);
|
||||
if (ret && ret != -ENOMEM)
|
||||
ret = 0;
|
||||
}
|
||||
@@ -2855,44 +2886,57 @@ scmi_txrx_setup(struct scmi_info *info, struct device_node *of_node,
|
||||
*
|
||||
* @info: The SCMI instance descriptor.
|
||||
*
|
||||
* Initialize all the channels found described in the DT against the underlying
|
||||
* configured transport using custom defined dedicated devices instead of
|
||||
* borrowing devices from the SCMI drivers; this way channels are initialized
|
||||
* Initialize all the channels found described in the fwnode against the
|
||||
* underlying configured transport using custom defined dedicated devices instead
|
||||
* of borrowing devices from the SCMI drivers; this way channels are initialized
|
||||
* upfront during core SCMI stack probing and are no more coupled with SCMI
|
||||
* devices used by SCMI drivers.
|
||||
*
|
||||
* Note that, even though a pair of TX/RX channels is associated to each
|
||||
* protocol defined in the DT, a distinct freshly initialized channel is
|
||||
* created only if the DT node for the protocol at hand describes a dedicated
|
||||
* protocol defined in the fwnode, a distinct freshly initialized channel is
|
||||
* created only if the fwnode for the protocol at hand describes a dedicated
|
||||
* channel: in all the other cases the common BASE protocol channel is reused.
|
||||
*
|
||||
* Return: 0 on Success
|
||||
*/
|
||||
static int scmi_channels_setup(struct scmi_info *info)
|
||||
{
|
||||
int ret;
|
||||
struct device_node *top_np = info->dev->of_node;
|
||||
int ret, idx;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(info->dev);
|
||||
|
||||
/* Initialize a common generic channel at first */
|
||||
ret = scmi_txrx_setup(info, top_np, SCMI_PROTOCOL_BASE);
|
||||
ret = scmi_txrx_setup(info, fwnode, SCMI_PROTOCOL_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_available_child_of_node_scoped(top_np, child) {
|
||||
u32 prot_id;
|
||||
if (!is_acpi_node(fwnode)) {
|
||||
fwnode_for_each_available_child_node_scoped(fwnode, child) {
|
||||
u32 prot_id;
|
||||
|
||||
if (of_property_read_u32(child, "reg", &prot_id))
|
||||
continue;
|
||||
if (fwnode_property_read_u32(child, "reg", &prot_id))
|
||||
continue;
|
||||
|
||||
if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) {
|
||||
dev_err(info->dev,
|
||||
"Out of range protocol %d\n", prot_id);
|
||||
continue;
|
||||
if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) {
|
||||
dev_err(info->dev,
|
||||
"Out of range protocol %d\n", prot_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = scmi_txrx_setup(info, child, prot_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
for (idx = 0; idx < ARRAY_SIZE(scmi_dsd_info_list); idx++) {
|
||||
int prot_id = scmi_dsd_info_list[idx].protocol_id;
|
||||
|
||||
ret = scmi_txrx_setup(info, child, prot_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (prot_id == SCMI_PROTOCOL_BASE)
|
||||
continue;
|
||||
|
||||
ret = scmi_txrx_setup(info, fwnode, prot_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2969,14 +3013,14 @@ static int scmi_bus_notifier(struct notifier_block *nb,
|
||||
static int scmi_device_request_notifier(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct fwnode_handle *fwnode;
|
||||
struct scmi_device_id *id_table = data;
|
||||
struct scmi_info *info = req_nb_to_scmi_info(nb);
|
||||
|
||||
rcu_read_lock();
|
||||
np = idr_find(&info->active_protocols, id_table->protocol_id);
|
||||
fwnode = idr_find(&info->active_protocols, id_table->protocol_id);
|
||||
rcu_read_unlock();
|
||||
if (!np)
|
||||
if (!fwnode)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
dev_dbg(info->dev, "%sRequested device (%s) for protocol 0x%x\n",
|
||||
@@ -2985,7 +3029,7 @@ static int scmi_device_request_notifier(struct notifier_block *nb,
|
||||
|
||||
switch (action) {
|
||||
case SCMI_BUS_NOTIFY_DEVICE_REQUEST:
|
||||
scmi_create_protocol_devices(np, info, id_table->protocol_id,
|
||||
scmi_create_protocol_devices(fwnode, info, id_table->protocol_id,
|
||||
id_table->name);
|
||||
break;
|
||||
case SCMI_BUS_NOTIFY_DEVICE_UNREQUEST:
|
||||
@@ -3061,6 +3105,15 @@ static void scmi_debugfs_common_cleanup(void *d)
|
||||
kfree(dbg->type);
|
||||
}
|
||||
|
||||
static const char *scmi_acpi_device_hid(struct acpi_device *adev)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
return adev ? acpi_device_hid(adev) : "unknown";
|
||||
#else
|
||||
return "unknown";
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
|
||||
{
|
||||
char top_dir[16];
|
||||
@@ -3072,13 +3125,16 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
|
||||
if (!dbg)
|
||||
return NULL;
|
||||
|
||||
dbg->name = kstrdup(of_node_full_name(info->dev->of_node), GFP_KERNEL);
|
||||
dbg->name = kstrdup(fwnode_get_name(dev_fwnode(info->dev)), GFP_KERNEL);
|
||||
if (!dbg->name) {
|
||||
devm_kfree(info->dev, dbg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
of_property_read_string(info->dev->of_node, "compatible", &c_ptr);
|
||||
if (fwnode_property_read_string(dev_fwnode(info->dev), "compatible",
|
||||
&c_ptr))
|
||||
c_ptr = scmi_acpi_device_hid(ACPI_COMPANION(info->dev));
|
||||
|
||||
dbg->type = kstrdup(c_ptr, GFP_KERNEL);
|
||||
if (!dbg->type) {
|
||||
kfree(dbg->name);
|
||||
@@ -3184,23 +3240,23 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
|
||||
|
||||
dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier));
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms",
|
||||
&trans->desc.max_rx_timeout_ms);
|
||||
ret = fwnode_property_read_u32(dev_fwnode(dev), "arm,max-rx-timeout-ms",
|
||||
&trans->desc.max_rx_timeout_ms);
|
||||
if (ret && ret != -EINVAL)
|
||||
dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n");
|
||||
dev_err(dev, "Malformed arm,max-rx-timeout-ms property.\n");
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "arm,max-msg-size",
|
||||
&trans->desc.max_msg_size);
|
||||
ret = fwnode_property_read_u32(dev_fwnode(dev), "arm,max-msg-size",
|
||||
&trans->desc.max_msg_size);
|
||||
if (ret && ret != -EINVAL)
|
||||
dev_err(dev, "Malformed arm,max-msg-size DT property.\n");
|
||||
dev_err(dev, "Malformed arm,max-msg-size property.\n");
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "arm,max-msg",
|
||||
&trans->desc.max_msg);
|
||||
ret = fwnode_property_read_u32(dev_fwnode(dev), "arm,max-msg",
|
||||
&trans->desc.max_msg);
|
||||
if (ret && ret != -EINVAL)
|
||||
dev_err(dev, "Malformed arm,max-msg DT property.\n");
|
||||
dev_err(dev, "Malformed arm,max-msg property.\n");
|
||||
|
||||
trans->desc.no_completion_irq = of_property_read_bool(dev->of_node,
|
||||
"arm,no-completion-irq");
|
||||
trans->desc.no_completion_irq =
|
||||
fwnode_property_read_bool(dev_fwnode(dev), "arm,no-completion-irq");
|
||||
|
||||
dev_info(dev,
|
||||
"SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n",
|
||||
@@ -3208,8 +3264,8 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
|
||||
trans->desc.max_msg);
|
||||
|
||||
/* System wide atomic threshold for atomic ops .. if any */
|
||||
if (!of_property_read_u32(dev->of_node, "atomic-threshold-us",
|
||||
&trans->desc.atomic_threshold))
|
||||
if (!fwnode_property_read_u32(dev_fwnode(dev), "atomic-threshold-us",
|
||||
&trans->desc.atomic_threshold))
|
||||
dev_info(dev,
|
||||
"SCMI System wide atomic threshold set to %u us\n",
|
||||
trans->desc.atomic_threshold);
|
||||
@@ -3229,16 +3285,52 @@ static void scmi_enable_matching_quirks(struct scmi_info *info)
|
||||
rev->sub_vendor_id, rev->impl_ver);
|
||||
}
|
||||
|
||||
static int scmi_probe(struct platform_device *pdev)
|
||||
static void scmi_device_check_create(struct fwnode_handle *fwnode, int prot_id,
|
||||
struct scmi_info *info, bool report_missing)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = info->dev;
|
||||
struct scmi_handle *handle = &info->handle;
|
||||
|
||||
if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) {
|
||||
dev_err(dev, "Out of range protocol %d\n", prot_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scmi_is_protocol_implemented(handle, prot_id)) {
|
||||
if (!report_missing)
|
||||
return;
|
||||
|
||||
dev_err(dev, "SCMI protocol %d not implemented\n", prot_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save this valid fwnode protocol descriptor amongst
|
||||
* @active_protocols for this SCMI instance.
|
||||
*/
|
||||
ret = idr_alloc(&info->active_protocols, fwnode,
|
||||
prot_id, prot_id + 1, GFP_KERNEL);
|
||||
if (ret != prot_id) {
|
||||
dev_err(dev, "SCMI protocol %d already activated. Skip\n",
|
||||
prot_id);
|
||||
return;
|
||||
}
|
||||
|
||||
scmi_create_protocol_devices(fwnode_handle_get(fwnode), info, prot_id,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int scmi_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret, idx;
|
||||
char *err_str = "probe failure\n";
|
||||
struct scmi_handle *handle;
|
||||
const struct scmi_desc *desc;
|
||||
struct scmi_info *info;
|
||||
bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *child, *np = dev->of_node;
|
||||
struct fwnode_handle *child;
|
||||
|
||||
desc = scmi_transport_setup(dev);
|
||||
if (!desc) {
|
||||
@@ -3277,7 +3369,7 @@ static int scmi_probe(struct platform_device *pdev)
|
||||
handle->devm_protocol_put = scmi_devm_protocol_put;
|
||||
handle->is_transport_atomic = scmi_is_transport_atomic;
|
||||
|
||||
/* Setup all channels described in the DT at first */
|
||||
/* Setup all channels described in the fwnode at first */
|
||||
ret = scmi_channels_setup(info);
|
||||
if (ret) {
|
||||
err_str = "failed to setup channels\n";
|
||||
@@ -3352,37 +3444,25 @@ static int scmi_probe(struct platform_device *pdev)
|
||||
|
||||
scmi_enable_matching_quirks(info);
|
||||
|
||||
for_each_available_child_of_node(np, child) {
|
||||
u32 prot_id;
|
||||
if (!is_acpi_node(dev_fwnode(dev))) {
|
||||
fwnode_for_each_available_child_node(dev_fwnode(dev), child) {
|
||||
u32 prot_id;
|
||||
|
||||
if (of_property_read_u32(child, "reg", &prot_id))
|
||||
continue;
|
||||
if (fwnode_property_read_u32(child, "reg", &prot_id))
|
||||
continue;
|
||||
|
||||
if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id)) {
|
||||
dev_err(dev, "Out of range protocol %d\n", prot_id);
|
||||
continue;
|
||||
scmi_device_check_create(child, prot_id, info, true);
|
||||
}
|
||||
} else {
|
||||
for (idx = 0; idx < ARRAY_SIZE(scmi_dsd_info_list); idx++) {
|
||||
int prot_id = scmi_dsd_info_list[idx].protocol_id;
|
||||
|
||||
if (!scmi_is_protocol_implemented(handle, prot_id)) {
|
||||
dev_err(dev, "SCMI protocol %d not implemented\n",
|
||||
prot_id);
|
||||
continue;
|
||||
if (prot_id == SCMI_PROTOCOL_BASE)
|
||||
continue;
|
||||
|
||||
scmi_device_check_create(dev_fwnode(dev), prot_id,
|
||||
info, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save this valid DT protocol descriptor amongst
|
||||
* @active_protocols for this SCMI instance/
|
||||
*/
|
||||
ret = idr_alloc(&info->active_protocols, child,
|
||||
prot_id, prot_id + 1, GFP_KERNEL);
|
||||
if (ret != prot_id) {
|
||||
dev_err(dev, "SCMI protocol %d already activated. Skip\n",
|
||||
prot_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
of_node_get(child);
|
||||
scmi_create_protocol_devices(child, info, prot_id, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3409,7 +3489,7 @@ static void scmi_remove(struct platform_device *pdev)
|
||||
{
|
||||
int id;
|
||||
struct scmi_info *info = platform_get_drvdata(pdev);
|
||||
struct device_node *child;
|
||||
struct fwnode_handle *child;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT))
|
||||
scmi_raw_mode_cleanup(info->raw);
|
||||
@@ -3434,7 +3514,7 @@ static void scmi_remove(struct platform_device *pdev)
|
||||
mutex_unlock(&info->protocols_mtx);
|
||||
|
||||
idr_for_each_entry(&info->active_protocols, child, id)
|
||||
of_node_put(child);
|
||||
fwnode_handle_put(child);
|
||||
idr_destroy(&info->active_protocols);
|
||||
|
||||
bus_unregister_notifier(&scmi_bus_type, &info->bus_nb);
|
||||
|
||||
@@ -100,7 +100,10 @@ struct scmi_msg_hdr {
|
||||
* message. If request-ACK protocol is used, we can reuse the same
|
||||
* buffer for the rx path as we use for the tx path.
|
||||
* @done: command message transmit completion event
|
||||
* @async_done: pointer to delayed response message received event completion
|
||||
* @async_done: pointer to delayed response message received event completion,
|
||||
* or NULL when no delayed response is expected. Protected by
|
||||
* @lock, since the completion is owned by the waiter and can
|
||||
* vanish once the wait times out.
|
||||
* @pending: True for xfers added to @pending_xfers hashtable
|
||||
* @node: An hlist_node reference used to store this xfer, alternatively, on
|
||||
* the free list @free_xfers or in the @pending_xfers hashtable
|
||||
@@ -121,7 +124,7 @@ struct scmi_msg_hdr {
|
||||
* - SCMI_XFER_SENT_OK -> SCMI_XFER_DRESP_OK
|
||||
* (Missing synchronous response is assumed OK and ignored)
|
||||
* @flags: Optional flags associated to this xfer.
|
||||
* @lock: A spinlock to protect state and busy fields.
|
||||
* @lock: A spinlock to protect state, busy and async_done fields.
|
||||
* @priv: A pointer for transport private usage.
|
||||
*/
|
||||
struct scmi_xfer {
|
||||
@@ -147,7 +150,7 @@ struct scmi_xfer {
|
||||
#define SCMI_XFER_IS_CHAN_SET(x) \
|
||||
((x)->flags & SCMI_XFER_FLAG_CHAN_SET)
|
||||
int flags;
|
||||
/* A lock to protect state and busy fields */
|
||||
/* A lock to protect state, busy and async_done fields */
|
||||
spinlock_t lock;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
@@ -198,6 +198,8 @@ struct scmi_raw_mode_info {
|
||||
* @async_response: A completion to be, optionally, used for async waits: it
|
||||
* will be setup by @scmi_do_xfer_raw_start, if needed, to be
|
||||
* pointed at by xfer->async_done.
|
||||
* @async: True if @async_response was armed on @xfer, i.e. if a delayed
|
||||
* response has to be waited for.
|
||||
* @node: A list node.
|
||||
*/
|
||||
struct scmi_xfer_raw_waiter {
|
||||
@@ -205,6 +207,7 @@ struct scmi_xfer_raw_waiter {
|
||||
struct scmi_chan_info *cinfo;
|
||||
struct scmi_xfer *xfer;
|
||||
struct completion async_response;
|
||||
bool async;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
@@ -346,9 +349,10 @@ scmi_xfer_raw_waiter_get(struct scmi_raw_mode_info *raw, struct scmi_xfer *xfer,
|
||||
|
||||
if (async) {
|
||||
reinit_completion(&rw->async_response);
|
||||
xfer->async_done = &rw->async_response;
|
||||
scmi_xfer_async_response_arm(xfer, &rw->async_response);
|
||||
}
|
||||
|
||||
rw->async = async;
|
||||
rw->cinfo = cinfo;
|
||||
rw->xfer = xfer;
|
||||
}
|
||||
@@ -361,8 +365,16 @@ static void scmi_xfer_raw_waiter_put(struct scmi_raw_mode_info *raw,
|
||||
struct scmi_xfer_raw_waiter *rw)
|
||||
{
|
||||
if (rw->xfer) {
|
||||
rw->xfer->async_done = NULL;
|
||||
/*
|
||||
* Disarm the delayed response before this waiter, and its
|
||||
* embedded completion, can be picked up again for a new
|
||||
* transaction: a delayed response received late, after the
|
||||
* related wait timed out, must not signal a completion which
|
||||
* has been in the meantime re-armed on a different xfer.
|
||||
*/
|
||||
scmi_xfer_async_response_disarm(rw->xfer);
|
||||
rw->xfer = NULL;
|
||||
rw->async = false;
|
||||
}
|
||||
|
||||
mutex_lock(&raw->free_mtx);
|
||||
@@ -479,18 +491,23 @@ static void scmi_xfer_raw_worker(struct work_struct *work)
|
||||
ret, scmi_inflight_count(raw->handle));
|
||||
|
||||
/* Wait also for an async delayed response if needed */
|
||||
if (!ret && xfer->async_done) {
|
||||
if (!ret && rw->async) {
|
||||
unsigned long tmo = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT);
|
||||
|
||||
if (!wait_for_completion_timeout(xfer->async_done, tmo))
|
||||
if (!wait_for_completion_timeout(&rw->async_response, tmo))
|
||||
dev_err(dev,
|
||||
"timed out in RAW delayed resp - HDR:%08X\n",
|
||||
pack_scmi_header(&xfer->hdr));
|
||||
}
|
||||
|
||||
/* Release waiter and xfer */
|
||||
scmi_xfer_raw_put(raw->handle, xfer);
|
||||
/*
|
||||
* Release the waiter first: this disarms the delayed response
|
||||
* while we still hold a reference on the xfer, so that the xfer
|
||||
* cannot be recycled by a new transaction while it still points
|
||||
* at this waiter's completion.
|
||||
*/
|
||||
scmi_xfer_raw_waiter_put(raw, rw);
|
||||
scmi_xfer_raw_put(raw->handle, xfer);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
@@ -694,6 +711,7 @@ static int scmi_raw_message_send(struct scmi_raw_mode_info *raw,
|
||||
} else {
|
||||
dev_err(raw->handle->dev,
|
||||
"Failed to send RAW message - Polling NOT supported\n");
|
||||
scmi_xfer_raw_put(raw->handle, xfer);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,7 @@ struct scmi_reset_issued_notify_payld {
|
||||
struct reset_dom_info {
|
||||
bool async_reset;
|
||||
bool reset_notify;
|
||||
u32 latency_us;
|
||||
char name[SCMI_MAX_STR_SIZE];
|
||||
struct scmi_reset_domain_info info;
|
||||
};
|
||||
|
||||
struct scmi_reset_info {
|
||||
@@ -134,10 +133,10 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
|
||||
if (pinfo->notify_reset_cmd)
|
||||
dom_info->reset_notify =
|
||||
SUPPORTS_NOTIFY_RESET(attributes);
|
||||
dom_info->latency_us = le32_to_cpu(attr->latency);
|
||||
if (dom_info->latency_us == U32_MAX)
|
||||
dom_info->latency_us = 0;
|
||||
strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
|
||||
dom_info->info.latency_us = le32_to_cpu(attr->latency);
|
||||
if (dom_info->info.latency_us == U32_MAX)
|
||||
dom_info->info.latency_us = 0;
|
||||
strscpy(dom_info->info.name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
|
||||
}
|
||||
|
||||
ph->xops->xfer_put(ph, t);
|
||||
@@ -149,7 +148,7 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
|
||||
if (!ret && PROTOCOL_REV_MAJOR(ph->version) >= 0x3 &&
|
||||
SUPPORTS_EXTENDED_NAMES(attributes))
|
||||
ph->hops->extended_name_get(ph, RESET_DOMAIN_NAME_GET, domain,
|
||||
NULL, dom_info->name,
|
||||
NULL, dom_info->info.name,
|
||||
SCMI_MAX_STR_SIZE);
|
||||
|
||||
return ret;
|
||||
@@ -162,28 +161,16 @@ static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph)
|
||||
return pi->num_domains;
|
||||
}
|
||||
|
||||
static const char *
|
||||
scmi_reset_name_get(const struct scmi_protocol_handle *ph, u32 domain)
|
||||
static const struct scmi_reset_domain_info *
|
||||
scmi_reset_info_get(const struct scmi_protocol_handle *ph, u32 domain)
|
||||
{
|
||||
struct reset_dom_info *dom_info;
|
||||
|
||||
dom_info = scmi_reset_domain_lookup(ph, domain);
|
||||
if (IS_ERR(dom_info))
|
||||
return "unknown";
|
||||
return NULL;
|
||||
|
||||
return dom_info->name;
|
||||
}
|
||||
|
||||
static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
|
||||
u32 domain)
|
||||
{
|
||||
struct reset_dom_info *dom_info;
|
||||
|
||||
dom_info = scmi_reset_domain_lookup(ph, domain);
|
||||
if (IS_ERR(dom_info))
|
||||
return PTR_ERR(dom_info);
|
||||
|
||||
return dom_info->latency_us;
|
||||
return &dom_info->info;
|
||||
}
|
||||
|
||||
static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
|
||||
@@ -241,8 +228,7 @@ scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
|
||||
|
||||
static const struct scmi_reset_proto_ops reset_proto_ops = {
|
||||
.num_domains_get = scmi_reset_num_domains_get,
|
||||
.name_get = scmi_reset_name_get,
|
||||
.latency_get = scmi_reset_latency_get,
|
||||
.info_get = scmi_reset_info_get,
|
||||
.reset = scmi_reset_domain_reset,
|
||||
.assert = scmi_reset_domain_assert,
|
||||
.deassert = scmi_reset_domain_deassert,
|
||||
|
||||
@@ -77,6 +77,18 @@ config ARM_SCMI_TRANSPORT_OPTEE
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called scmi_transport_optee.
|
||||
|
||||
config ARM_SCMI_TRANSPORT_PCC
|
||||
tristate "SCMI transport based on ACPI PCC"
|
||||
depends on PCC
|
||||
select ARM_SCMI_HAVE_TRANSPORT
|
||||
help
|
||||
This enables the ACPI PCC mailbox based transport for SCMI.
|
||||
|
||||
If you want the ARM SCMI PROTOCOL stack to include support for a
|
||||
transport based on ACPI PCC mailboxes, answer Y.
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called scmi_transport_pcc.
|
||||
|
||||
config ARM_SCMI_TRANSPORT_VIRTIO
|
||||
tristate "SCMI transport based on VirtIO"
|
||||
depends on VIRTIO
|
||||
|
||||
@@ -7,6 +7,8 @@ scmi_transport_mailbox-objs := mailbox.o
|
||||
obj-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += scmi_transport_mailbox.o
|
||||
scmi_transport_optee-objs := optee.o
|
||||
obj-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += scmi_transport_optee.o
|
||||
scmi_transport_pcc-objs := pcc.o
|
||||
obj-$(CONFIG_ARM_SCMI_TRANSPORT_PCC) += scmi_transport_pcc.o
|
||||
scmi_transport_virtio-objs := virtio.o
|
||||
obj-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += scmi_transport_virtio.o
|
||||
|
||||
|
||||
@@ -77,9 +77,14 @@ static void rx_callback(struct mbox_client *cl, void *m)
|
||||
core->shmem->read_header(smbox->shmem), NULL);
|
||||
}
|
||||
|
||||
static bool mailbox_chan_available(struct device_node *of_node, int idx)
|
||||
static bool
|
||||
mailbox_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx)
|
||||
{
|
||||
int num_mb;
|
||||
struct device_node *of_node = to_of_node(fwnode);
|
||||
|
||||
if (!of_node)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Just check if bidirrectional channels are involved, and check the
|
||||
|
||||
@@ -314,9 +314,14 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool scmi_optee_chan_available(struct device_node *of_node, int idx)
|
||||
static bool
|
||||
scmi_optee_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx)
|
||||
{
|
||||
u32 channel_id;
|
||||
struct device_node *of_node = to_of_node(fwnode);
|
||||
|
||||
if (!of_node)
|
||||
return false;
|
||||
|
||||
return !of_property_read_u32_index(of_node, "linaro,optee-channel-id",
|
||||
idx, &channel_id);
|
||||
|
||||
@@ -0,0 +1,875 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* System Control and Management Interface (SCMI) Message ACPI PCC
|
||||
* Transport Driver
|
||||
*
|
||||
* This transport uses ACPI PCC (PCCT Type 3/4) subspaces via the Linux
|
||||
* PCC mailbox controller to exchange SCMI messages over the standard
|
||||
* SCMI Shared Memory Transport (SMT) layout.
|
||||
*
|
||||
* PCC subspace selection is conveyed via ACPI SCMI namespace device.
|
||||
* described in ACPI for System Control and Management Interface Platform
|
||||
* Design Document[1]
|
||||
*
|
||||
* [1] https://support.arm.com/documentation/111115/latest
|
||||
*
|
||||
* Copyright (C) 2026
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <acpi/pcc.h>
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#define SCMI_TRANSPORT_PACKAGE_MAX_VERSION (1)
|
||||
#define SCMI_PROTOCOL_PACKAGE_MAX_VERSION (1)
|
||||
#define SCMI_TRANSPORT_SHARED_CHANNEL BIT_ULL(0)
|
||||
#define SCMI_TRANSPORT_P2A_CHANNEL BIT_ULL(1)
|
||||
#define SCMI_TRANSPORT_FLAGS_MASK (SCMI_TRANSPORT_SHARED_CHANNEL | \
|
||||
SCMI_TRANSPORT_P2A_CHANNEL)
|
||||
|
||||
#define SCMI_DSD_GUID_ENTRY_COUNT 2
|
||||
#define SCMI_PROTOCOL_MAX_TRANSPORTS 2
|
||||
|
||||
enum scmi_dsd_property_index {
|
||||
SCMI_DSD_PROPERTY_NAME,
|
||||
SCMI_DSD_PROPERTY_VALUE,
|
||||
SCMI_DSD_PROPERTY_COUNT,
|
||||
};
|
||||
|
||||
enum scmi_pcc_transport_index {
|
||||
SCMI_PCC_TRANSPORT_REVISION,
|
||||
SCMI_PCC_TRANSPORT_COUNT,
|
||||
SCMI_PCC_TRANSPORT_DESCRIPTORS,
|
||||
};
|
||||
|
||||
enum scmi_pcc_descriptor_index {
|
||||
SCMI_PCC_DESCRIPTOR_PCCT_INDEX,
|
||||
SCMI_PCC_DESCRIPTOR_TRANSPORT_UID,
|
||||
SCMI_PCC_DESCRIPTOR_FLAGS,
|
||||
SCMI_PCC_DESCRIPTOR_COUNT,
|
||||
};
|
||||
|
||||
enum scmi_protocol_property_index {
|
||||
SCMI_PROTOCOL_PROPERTY_REVISION,
|
||||
SCMI_PROTOCOL_PROPERTY_TRANSPORTS,
|
||||
SCMI_PROTOCOL_PROPERTY_ASSOCIATIONS,
|
||||
SCMI_PROTOCOL_PROPERTY_COUNT,
|
||||
};
|
||||
|
||||
enum scmi_protocol_transport_index {
|
||||
SCMI_PROTOCOL_TRANSPORT_UID,
|
||||
SCMI_PROTOCOL_TRANSPORT_FLAGS,
|
||||
SCMI_PROTOCOL_TRANSPORT_COUNT,
|
||||
};
|
||||
|
||||
/*
|
||||
* SCMI specification requires all parameters, message headers, return
|
||||
* arguments or any protocol data to be expressed in little endian
|
||||
* format only.
|
||||
*/
|
||||
struct pcc_shared_mem {
|
||||
struct acpi_pcct_ext_pcc_shared_memory header;
|
||||
u8 msg_payload[];
|
||||
};
|
||||
|
||||
#define SCMI_PCC_MSG_HEADER_SIZE sizeof(u32)
|
||||
#define SCMI_PCC_STATUS_SIZE sizeof(u32)
|
||||
#define SCMI_PCC_RESPONSE_OVERHEAD (SCMI_PCC_MSG_HEADER_SIZE + \
|
||||
SCMI_PCC_STATUS_SIZE)
|
||||
#define SCMI_PCC_SHMEM_OVERHEAD (sizeof(struct pcc_shared_mem) + \
|
||||
SCMI_PCC_STATUS_SIZE)
|
||||
|
||||
/**
|
||||
* struct scmi_pcc - Structure representing a SCMI mailbox transport
|
||||
*
|
||||
* @cl: Mailbox Client
|
||||
* @pchan: Transmit/Receive PCC/mailbox channel
|
||||
* @cinfo: SCMI channel info
|
||||
*/
|
||||
struct scmi_pcc {
|
||||
struct mbox_client cl;
|
||||
struct pcc_mbox_chan *pchan;
|
||||
struct scmi_chan_info *cinfo;
|
||||
};
|
||||
|
||||
struct pcc_transport {
|
||||
u64 uid;
|
||||
u64 flags;
|
||||
u32 pcc_ss_id;
|
||||
u32 protocol_id;
|
||||
struct hlist_node hnode;
|
||||
};
|
||||
|
||||
struct pcc_transport_map {
|
||||
struct fwnode_handle *fwnode;
|
||||
struct device *dev;
|
||||
struct list_head node;
|
||||
DECLARE_HASHTABLE(table, ilog2(MAX_PCC_SUBSPACES / 8));
|
||||
};
|
||||
|
||||
#define client_to_scmi_pcc(c) container_of(c, struct scmi_pcc, cl)
|
||||
|
||||
static struct scmi_transport_core_operations *core;
|
||||
static LIST_HEAD(pcc_transport_maps);
|
||||
static DEFINE_MUTEX(pcc_transport_maps_lock);
|
||||
|
||||
static void acpi_scmi_clear_transport_map(struct pcc_transport_map *map)
|
||||
{
|
||||
struct pcc_transport *p;
|
||||
struct hlist_node *tmp;
|
||||
int idx;
|
||||
|
||||
hash_for_each_safe(map->table, idx, tmp, p, hnode) {
|
||||
hash_del(&p->hnode);
|
||||
kfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_scmi_destroy_transport_map(struct pcc_transport_map *map)
|
||||
{
|
||||
acpi_scmi_clear_transport_map(map);
|
||||
if (map->fwnode)
|
||||
fwnode_handle_put(map->fwnode);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static void pcc_transport_map_release(void *data)
|
||||
{
|
||||
struct pcc_transport_map *map = data;
|
||||
|
||||
guard(mutex)(&pcc_transport_maps_lock);
|
||||
list_del(&map->node);
|
||||
acpi_scmi_destroy_transport_map(map);
|
||||
}
|
||||
|
||||
static void acpi_scmi_clear_transport_maps(void)
|
||||
{
|
||||
struct pcc_transport_map *map, *tmp;
|
||||
|
||||
guard(mutex)(&pcc_transport_maps_lock);
|
||||
list_for_each_entry_safe(map, tmp, &pcc_transport_maps, node) {
|
||||
list_del(&map->node);
|
||||
acpi_scmi_destroy_transport_map(map);
|
||||
}
|
||||
}
|
||||
|
||||
static const union acpi_object *
|
||||
acpi_scmi_pkg_elements(const union acpi_object *obj, unsigned int count)
|
||||
{
|
||||
if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != count)
|
||||
return NULL;
|
||||
|
||||
return obj->package.elements;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_scmi_pkg_u64(const union acpi_object *pkg, unsigned int idx, u64 *val)
|
||||
{
|
||||
const union acpi_object *elem = &pkg->package.elements[idx];
|
||||
|
||||
if (elem->type != ACPI_TYPE_INTEGER)
|
||||
return -EINVAL;
|
||||
|
||||
*val = elem->integer.value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_scmi_property(const union acpi_object *properties,
|
||||
unsigned int idx, const char **name,
|
||||
const union acpi_object **value)
|
||||
{
|
||||
const union acpi_object *property;
|
||||
const union acpi_object *elems;
|
||||
|
||||
property = &properties->package.elements[idx];
|
||||
elems = acpi_scmi_pkg_elements(property, SCMI_DSD_PROPERTY_COUNT);
|
||||
if (!elems)
|
||||
return -EINVAL;
|
||||
if (elems[SCMI_DSD_PROPERTY_NAME].type != ACPI_TYPE_STRING ||
|
||||
!elems[SCMI_DSD_PROPERTY_NAME].string.pointer)
|
||||
return -EINVAL;
|
||||
|
||||
*name = elems[SCMI_DSD_PROPERTY_NAME].string.pointer;
|
||||
*value = &elems[SCMI_DSD_PROPERTY_VALUE];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_scmi_dsd_parse_transport_package(struct pcc_transport_map *map,
|
||||
const union acpi_object *obj)
|
||||
{
|
||||
u64 revision, pkg_cnt;
|
||||
bool common_a2p = false, common_p2a = false;
|
||||
|
||||
if (obj->type != ACPI_TYPE_PACKAGE ||
|
||||
obj->package.count < SCMI_PCC_TRANSPORT_DESCRIPTORS ||
|
||||
acpi_scmi_pkg_u64(obj, SCMI_PCC_TRANSPORT_REVISION, &revision) ||
|
||||
acpi_scmi_pkg_u64(obj, SCMI_PCC_TRANSPORT_COUNT, &pkg_cnt))
|
||||
return -EINVAL;
|
||||
if (revision != SCMI_TRANSPORT_PACKAGE_MAX_VERSION)
|
||||
return -EINVAL;
|
||||
if (pkg_cnt != obj->package.count - SCMI_PCC_TRANSPORT_DESCRIPTORS)
|
||||
return -EINVAL;
|
||||
|
||||
for (u32 idx = 0; idx < pkg_cnt; idx++) {
|
||||
struct pcc_transport *p, *tmp;
|
||||
union acpi_object *pack;
|
||||
u64 pcc_ss_id, uid, flags;
|
||||
|
||||
pack = &obj->package.elements[idx +
|
||||
SCMI_PCC_TRANSPORT_DESCRIPTORS];
|
||||
if (!acpi_scmi_pkg_elements(pack, SCMI_PCC_DESCRIPTOR_COUNT)) {
|
||||
pr_info("Invalid transport properties pkg %u\n", idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (acpi_scmi_pkg_u64(pack, SCMI_PCC_DESCRIPTOR_PCCT_INDEX,
|
||||
&pcc_ss_id) ||
|
||||
acpi_scmi_pkg_u64(pack, SCMI_PCC_DESCRIPTOR_TRANSPORT_UID,
|
||||
&uid) ||
|
||||
acpi_scmi_pkg_u64(pack, SCMI_PCC_DESCRIPTOR_FLAGS, &flags))
|
||||
return -EINVAL;
|
||||
if (pcc_ss_id > INT_MAX ||
|
||||
flags & ~SCMI_TRANSPORT_FLAGS_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
hash_for_each_possible(map->table, tmp, hnode, uid) {
|
||||
if (tmp->uid == uid) {
|
||||
pr_info("Duplicate UID %llu\n", uid);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SCMI_TRANSPORT_SHARED_CHANNEL) {
|
||||
if (flags & SCMI_TRANSPORT_P2A_CHANNEL) {
|
||||
if (common_p2a)
|
||||
return -EINVAL;
|
||||
common_p2a = true;
|
||||
} else {
|
||||
if (common_a2p)
|
||||
return -EINVAL;
|
||||
common_a2p = true;
|
||||
}
|
||||
}
|
||||
|
||||
p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
p->uid = uid;
|
||||
p->pcc_ss_id = pcc_ss_id;
|
||||
p->flags = flags;
|
||||
if (p->flags & SCMI_TRANSPORT_SHARED_CHANNEL)
|
||||
p->protocol_id = SCMI_PROTOCOL_BASE;
|
||||
|
||||
hash_add(map->table, &p->hnode, uid);
|
||||
}
|
||||
|
||||
if (!common_a2p)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_scmi_dsd_parse_protocol_subpackage(struct pcc_transport_map *map,
|
||||
const union acpi_object *obj,
|
||||
int prot_id)
|
||||
{
|
||||
struct pcc_transport *p;
|
||||
unsigned int pkg_cnt = obj->package.count;
|
||||
bool found, tx_found = false, rx_found = false;
|
||||
u64 uid;
|
||||
|
||||
if (pkg_cnt > SCMI_PROTOCOL_MAX_TRANSPORTS) {
|
||||
pr_warn("Found %u protocol channels, at most %u allowed\n",
|
||||
pkg_cnt, SCMI_PROTOCOL_MAX_TRANSPORTS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (u32 idx = 0; idx < pkg_cnt; idx++) {
|
||||
union acpi_object *pack = &obj->package.elements[idx];
|
||||
u64 flags;
|
||||
|
||||
if (!acpi_scmi_pkg_elements(pack, SCMI_PROTOCOL_TRANSPORT_COUNT) ||
|
||||
acpi_scmi_pkg_u64(pack, SCMI_PROTOCOL_TRANSPORT_UID, &uid) ||
|
||||
acpi_scmi_pkg_u64(pack, SCMI_PROTOCOL_TRANSPORT_FLAGS,
|
||||
&flags))
|
||||
return -EINVAL;
|
||||
if (flags)
|
||||
return -EINVAL;
|
||||
|
||||
found = false;
|
||||
hash_for_each_possible(map->table, p, hnode, uid) {
|
||||
if (p->uid != uid)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
if (p->flags & SCMI_TRANSPORT_SHARED_CHANNEL) {
|
||||
pr_info("Protocol package references common PCC subspace %u\n",
|
||||
p->pcc_ss_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (p->protocol_id && p->protocol_id != prot_id)
|
||||
return -EINVAL;
|
||||
|
||||
if (p->flags & SCMI_TRANSPORT_P2A_CHANNEL) {
|
||||
if (rx_found)
|
||||
return -EINVAL;
|
||||
rx_found = true;
|
||||
} else {
|
||||
if (tx_found)
|
||||
return -EINVAL;
|
||||
tx_found = true;
|
||||
}
|
||||
p->protocol_id = prot_id;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_scmi_dsd_parse_protocol_package(struct pcc_transport_map *map,
|
||||
const union acpi_object *obj, int prot_id)
|
||||
{
|
||||
const union acpi_object *elems;
|
||||
const union acpi_object *pack;
|
||||
u64 revision;
|
||||
int ret;
|
||||
|
||||
elems = acpi_scmi_pkg_elements(obj, SCMI_PROTOCOL_PROPERTY_COUNT);
|
||||
if (!elems ||
|
||||
acpi_scmi_pkg_u64(obj, SCMI_PROTOCOL_PROPERTY_REVISION, &revision))
|
||||
return -EINVAL;
|
||||
|
||||
pack = &elems[SCMI_PROTOCOL_PROPERTY_TRANSPORTS];
|
||||
|
||||
if (revision != SCMI_PROTOCOL_PACKAGE_MAX_VERSION)
|
||||
return -EINVAL;
|
||||
|
||||
if (pack->type != ACPI_TYPE_PACKAGE) {
|
||||
pr_info("Invalid protocol transport package\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Document 111115A v1.0, Sections 2.2.2.1 and 2.2.3 permit an empty
|
||||
* protocol transport package when common transport channels exist.
|
||||
*/
|
||||
if (pack->package.count != 0) {
|
||||
ret = acpi_scmi_dsd_parse_protocol_subpackage(map, pack, prot_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pack = &elems[SCMI_PROTOCOL_PROPERTY_ASSOCIATIONS];
|
||||
if (pack->type != ACPI_TYPE_PACKAGE) {
|
||||
pr_info("Invalid protocol transport association package\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pack->package.count != 0) {
|
||||
pr_info("Non-empty association package not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ACPI SCMI _DSD UUID: "84a2d1c6-86b6-4199-8dac-9c17449d5e03" */
|
||||
static const guid_t acpi_scmi_uuid = GUID_INIT(0x84a2d1c6, 0x86b6, 0x4199,
|
||||
0x8d, 0xac, 0x9c, 0x17,
|
||||
0x44, 0x9d, 0x5e, 0x03);
|
||||
|
||||
static int acpi_scmi_lookup_protocol_id(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(scmi_dsd_info_list); i++) {
|
||||
if (!strcmp(name, scmi_dsd_info_list[i].property_name))
|
||||
return scmi_dsd_info_list[i].protocol_id;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int acpi_scmi_parse_properties(struct pcc_transport_map *map,
|
||||
const union acpi_object *properties)
|
||||
{
|
||||
bool transport_found = false;
|
||||
|
||||
if (properties->type != ACPI_TYPE_PACKAGE)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Protocol properties reference TransportUIDs declared by the transport
|
||||
* property. Parse the transport first because _DSD property ordering is
|
||||
* not defined.
|
||||
*/
|
||||
for (u32 i = 0; i < properties->package.count; i++) {
|
||||
const union acpi_object *v;
|
||||
const char *name;
|
||||
int prot_id, ret;
|
||||
|
||||
ret = acpi_scmi_property(properties, i, &name, &v);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
prot_id = acpi_scmi_lookup_protocol_id(name);
|
||||
if (prot_id < 0)
|
||||
continue;
|
||||
if (prot_id != SCMI_PROTOCOL_BASE)
|
||||
continue;
|
||||
if (v->type != ACPI_TYPE_PACKAGE)
|
||||
return -EINVAL;
|
||||
if (transport_found)
|
||||
return -EEXIST;
|
||||
|
||||
ret = acpi_scmi_dsd_parse_transport_package(map, v);
|
||||
if (ret)
|
||||
return ret;
|
||||
transport_found = true;
|
||||
}
|
||||
|
||||
if (!transport_found)
|
||||
return -ENOENT;
|
||||
|
||||
for (u32 i = 0; i < properties->package.count; i++) {
|
||||
const union acpi_object *v;
|
||||
const char *name;
|
||||
int prot_id, ret;
|
||||
|
||||
ret = acpi_scmi_property(properties, i, &name, &v);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
prot_id = acpi_scmi_lookup_protocol_id(name);
|
||||
if (prot_id < 0 || prot_id == SCMI_PROTOCOL_BASE)
|
||||
continue;
|
||||
if (v->type != ACPI_TYPE_PACKAGE)
|
||||
return -EINVAL;
|
||||
|
||||
ret = acpi_scmi_dsd_parse_protocol_package(map, v, prot_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_scmi_namespace_fwnode_parse(struct fwnode_handle *fwnode,
|
||||
struct pcc_transport_map *map)
|
||||
{
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_device *adev = to_acpi_device_node(fwnode);
|
||||
union acpi_object *desc;
|
||||
acpi_status status;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (!adev || !adev->handle)
|
||||
return -EINVAL;
|
||||
|
||||
status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
|
||||
ACPI_TYPE_PACKAGE);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EINVAL;
|
||||
|
||||
desc = buf.pointer;
|
||||
if (desc->package.count % SCMI_DSD_GUID_ENTRY_COUNT) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Look for the device properties GUID. */
|
||||
for (u32 i = 0; i < desc->package.count;
|
||||
i += SCMI_DSD_GUID_ENTRY_COUNT) {
|
||||
const union acpi_object *guid;
|
||||
const union acpi_object *properties;
|
||||
|
||||
guid = &desc->package.elements[i];
|
||||
properties = &desc->package.elements[i + 1];
|
||||
|
||||
/*
|
||||
* The first element must be a GUID and the second one must be
|
||||
* a package.
|
||||
*/
|
||||
if (guid->type != ACPI_TYPE_BUFFER ||
|
||||
guid->buffer.length != UUID_SIZE ||
|
||||
properties->type != ACPI_TYPE_PACKAGE)
|
||||
continue;
|
||||
|
||||
if (!guid_equal((guid_t *)guid->buffer.pointer,
|
||||
&acpi_scmi_uuid))
|
||||
continue;
|
||||
|
||||
ret = acpi_scmi_parse_properties(map, properties);
|
||||
break;
|
||||
}
|
||||
|
||||
out_free:
|
||||
ACPI_FREE(buf.pointer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
pcc_transport_map_has_ss_id(struct pcc_transport_map *map, u32 pcc_ss_id)
|
||||
{
|
||||
struct pcc_transport *p;
|
||||
int idx;
|
||||
|
||||
hash_for_each(map->table, idx, p, hnode) {
|
||||
if (p->pcc_ss_id == pcc_ss_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int pcc_transport_map_validate(struct pcc_transport_map *map)
|
||||
{
|
||||
struct pcc_transport_map *iter;
|
||||
struct pcc_transport *p;
|
||||
int idx;
|
||||
|
||||
list_for_each_entry(iter, &pcc_transport_maps, node) {
|
||||
hash_for_each(map->table, idx, p, hnode) {
|
||||
if (pcc_transport_map_has_ss_id(iter, p->pcc_ss_id))
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct pcc_transport_map *pcc_transport_map_find(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct pcc_transport_map *map;
|
||||
|
||||
list_for_each_entry(map, &pcc_transport_maps, node) {
|
||||
if (map->fwnode == fwnode)
|
||||
return map;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
struct pcc_transport_map *pcc_transport_map_get(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct pcc_transport_map *map;
|
||||
int ret;
|
||||
|
||||
map = pcc_transport_map_find(fwnode);
|
||||
if (map)
|
||||
return map;
|
||||
|
||||
map = kzalloc_obj(*map, GFP_KERNEL);
|
||||
if (!map)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hash_init(map->table);
|
||||
ret = acpi_scmi_namespace_fwnode_parse(fwnode, map);
|
||||
if (ret)
|
||||
goto err_free_map;
|
||||
|
||||
ret = pcc_transport_map_validate(map);
|
||||
if (ret)
|
||||
goto err_free_map;
|
||||
|
||||
map->fwnode = fwnode_handle_get(fwnode);
|
||||
list_add_tail(&map->node, &pcc_transport_maps);
|
||||
|
||||
return map;
|
||||
|
||||
err_free_map:
|
||||
acpi_scmi_clear_transport_map(map);
|
||||
kfree(map);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int pcc_transport_map_manage(struct pcc_transport_map *map,
|
||||
struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev || map->dev == dev)
|
||||
return 0;
|
||||
if (map->dev)
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* Release the cached map after the SCMI remove path tears down channels.
|
||||
*/
|
||||
ret = devm_add_action(dev, pcc_transport_map_release, map);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
map->dev = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcc_lookup_ss_id(struct pcc_transport_map *map, u32 prot_id, bool tx)
|
||||
{
|
||||
struct pcc_transport *p;
|
||||
int idx;
|
||||
|
||||
hash_for_each(map->table, idx, p, hnode) {
|
||||
if (p->protocol_id != prot_id)
|
||||
continue;
|
||||
|
||||
if ((!tx && (p->flags & SCMI_TRANSPORT_P2A_CHANNEL)) ||
|
||||
(tx && !(p->flags & SCMI_TRANSPORT_P2A_CHANNEL)))
|
||||
return p->pcc_ss_id;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int pcc_get_ss_id(struct fwnode_handle *fwnode, u32 prot_id, bool tx,
|
||||
struct device *dev)
|
||||
{
|
||||
struct pcc_transport_map *map;
|
||||
int ret;
|
||||
|
||||
if (!fwnode)
|
||||
return -EINVAL;
|
||||
|
||||
guard(mutex)(&pcc_transport_maps_lock);
|
||||
map = pcc_transport_map_get(fwnode);
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
ret = pcc_transport_map_manage(map, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return pcc_lookup_ss_id(map, prot_id, tx);
|
||||
}
|
||||
|
||||
static bool
|
||||
pcc_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx)
|
||||
{
|
||||
return pcc_get_ss_id(fwnode, prot_id, !idx, NULL) >= 0;
|
||||
}
|
||||
|
||||
static void tx_prepare(struct mbox_client *cl, void *m)
|
||||
{
|
||||
struct scmi_pcc *smbox = client_to_scmi_pcc(cl);
|
||||
struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem;
|
||||
struct scmi_xfer *xfer = m;
|
||||
|
||||
/*
|
||||
* PCC take cares not to call tx_prepare until last transmit is done.
|
||||
* Request platform interrupt notification if available.
|
||||
*/
|
||||
if (xfer->tx.buf)
|
||||
memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len);
|
||||
iowrite32(SCMI_PCC_MSG_HEADER_SIZE + xfer->tx.len,
|
||||
&shmem->header.length);
|
||||
iowrite32(pack_scmi_header(&xfer->hdr), &shmem->header.command);
|
||||
iowrite32(smbox->pchan->mchan->mbox->txdone_irq ?
|
||||
PCC_CMD_COMPLETION_NOTIFY : 0, &shmem->header.flags);
|
||||
}
|
||||
|
||||
static void rx_callback(struct mbox_client *cl, void *m)
|
||||
{
|
||||
struct scmi_pcc *smbox = client_to_scmi_pcc(cl);
|
||||
struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem;
|
||||
|
||||
core->rx_callback(smbox->cinfo, ioread32(&shmem->header.command), NULL);
|
||||
}
|
||||
|
||||
static int pcc_chan_validate_shmem(struct scmi_chan_info *cinfo,
|
||||
struct scmi_pcc *smbox, int ss_id)
|
||||
{
|
||||
struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem;
|
||||
u32 valid_signature = ss_id + PCC_SIGNATURE;
|
||||
|
||||
if (smbox->pchan->shmem_size < SCMI_PCC_SHMEM_OVERHEAD ||
|
||||
smbox->pchan->shmem_size - SCMI_PCC_SHMEM_OVERHEAD <
|
||||
cinfo->max_msg_size) {
|
||||
dev_err(cinfo->dev, "misconfigured SCMI PCC shared memory\n");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (ioread32(&shmem->header.signature) != valid_signature) {
|
||||
dev_err(cinfo->dev, "invalid PCC shared memory signature\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
bool tx)
|
||||
{
|
||||
const char *desc = tx ? "Tx" : "Rx";
|
||||
struct device *cdev = cinfo->dev;
|
||||
struct scmi_pcc *smbox;
|
||||
struct mbox_client *cl;
|
||||
int ret, ss_id;
|
||||
|
||||
smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
|
||||
if (!smbox)
|
||||
return -ENOMEM;
|
||||
|
||||
cl = &smbox->cl;
|
||||
cl->dev = cdev;
|
||||
cl->tx_prepare = tx ? tx_prepare : NULL;
|
||||
cl->rx_callback = rx_callback;
|
||||
cl->tx_block = false;
|
||||
|
||||
ss_id = pcc_get_ss_id(dev_fwnode(cinfo->dev), cinfo->id, tx, dev);
|
||||
if (ss_id < 0)
|
||||
return ss_id;
|
||||
|
||||
smbox->pchan = pcc_mbox_request_channel(cl, ss_id);
|
||||
if (IS_ERR(smbox->pchan)) {
|
||||
ret = PTR_ERR(smbox->pchan);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(cdev,
|
||||
"failed to request SCMI %s mailbox\n", desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pcc_chan_validate_shmem(cinfo, smbox, ss_id);
|
||||
if (ret) {
|
||||
pcc_mbox_free_channel(smbox->pchan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cinfo->transport_info = smbox;
|
||||
smbox->cinfo = cinfo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcc_chan_free(int id, void *p, void *data)
|
||||
{
|
||||
struct scmi_chan_info *cinfo = p;
|
||||
struct scmi_pcc *smbox = cinfo->transport_info;
|
||||
|
||||
if (!smbox || IS_ERR_OR_NULL(smbox->pchan))
|
||||
return 0;
|
||||
|
||||
pcc_mbox_free_channel(smbox->pchan);
|
||||
cinfo->transport_info = NULL;
|
||||
smbox->pchan = NULL;
|
||||
smbox->cinfo = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pcc_send_message(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
|
||||
{
|
||||
struct scmi_pcc *smbox = cinfo->transport_info;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The mailbox layer has its own queue. However the mailbox queue
|
||||
* confuses the per message SCMI timeouts since the clock starts when
|
||||
* the message is submitted into the mailbox queue. So when multiple
|
||||
* messages are queued up the clock starts on all messages instead of
|
||||
* only the one inflight.
|
||||
*/
|
||||
ret = mbox_send_message(smbox->pchan->mchan, xfer);
|
||||
/* mbox_send_message returns non-negative value on success */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcc_fetch_response(struct scmi_chan_info *cinfo,
|
||||
struct scmi_xfer *xfer)
|
||||
{
|
||||
struct scmi_pcc *smbox = cinfo->transport_info;
|
||||
struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem;
|
||||
size_t len = ioread32(&shmem->header.length);
|
||||
size_t payload_len;
|
||||
|
||||
xfer->hdr.status = ioread32(shmem->msg_payload);
|
||||
payload_len = len > SCMI_PCC_RESPONSE_OVERHEAD ?
|
||||
len - SCMI_PCC_RESPONSE_OVERHEAD : 0;
|
||||
xfer->rx.len = min(xfer->rx.len, payload_len);
|
||||
|
||||
/* msg_payload starts after the header, so skip only the status here. */
|
||||
memcpy_fromio(xfer->rx.buf, shmem->msg_payload + SCMI_PCC_STATUS_SIZE,
|
||||
xfer->rx.len);
|
||||
}
|
||||
|
||||
static void pcc_fetch_notification(struct scmi_chan_info *cinfo, size_t max_len,
|
||||
struct scmi_xfer *xfer)
|
||||
{
|
||||
struct scmi_pcc *smbox = cinfo->transport_info;
|
||||
struct pcc_shared_mem __iomem *shmem = smbox->pchan->shmem;
|
||||
size_t len = ioread32(&shmem->header.length);
|
||||
size_t payload_len;
|
||||
|
||||
payload_len = len > SCMI_PCC_MSG_HEADER_SIZE ?
|
||||
len - SCMI_PCC_MSG_HEADER_SIZE : 0;
|
||||
xfer->rx.len = min(max_len, payload_len);
|
||||
memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len);
|
||||
}
|
||||
|
||||
static const struct scmi_transport_ops scmi_pcc_ops = {
|
||||
.chan_available = pcc_chan_available,
|
||||
.chan_setup = pcc_chan_setup,
|
||||
.chan_free = pcc_chan_free,
|
||||
.send_message = pcc_send_message,
|
||||
.fetch_response = pcc_fetch_response,
|
||||
.fetch_notification = pcc_fetch_notification,
|
||||
};
|
||||
|
||||
static struct scmi_desc scmi_pcc_desc = {
|
||||
.ops = &scmi_pcc_ops,
|
||||
.max_rx_timeout_ms = 30,
|
||||
.max_msg = MBOX_TX_QUEUE_LEN,
|
||||
.max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id scmi_acpi_ids[] = {
|
||||
{ .id = "ARML0001" },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, scmi_acpi_ids);
|
||||
|
||||
DEFINE_SCMI_ACPI_TRANSPORT_DRIVER(scmi_pcc, scmi_pcc_driver,
|
||||
scmi_pcc_desc, scmi_acpi_ids, core);
|
||||
|
||||
static int __init scmi_pcc_init(void)
|
||||
{
|
||||
return platform_driver_register(&scmi_pcc_driver);
|
||||
}
|
||||
|
||||
static void __exit scmi_pcc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&scmi_pcc_driver);
|
||||
acpi_scmi_clear_transport_maps();
|
||||
}
|
||||
module_init(scmi_pcc_init);
|
||||
module_exit(scmi_pcc_exit);
|
||||
|
||||
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@kernel.org>");
|
||||
MODULE_DESCRIPTION("SCMI ACPI PCC Transport driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -84,10 +84,16 @@ static irqreturn_t smc_msg_done_isr(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static bool smc_chan_available(struct device_node *of_node, int idx)
|
||||
static bool
|
||||
smc_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx)
|
||||
{
|
||||
struct device_node *of_node = to_of_node(fwnode);
|
||||
|
||||
if (!of_node)
|
||||
return false;
|
||||
|
||||
struct device_node *np __free(device_node) =
|
||||
of_parse_phandle(of_node, "shmem", 0);
|
||||
of_parse_phandle(of_node, "shmem", 0);
|
||||
if (!np)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -375,7 +375,8 @@ static unsigned int virtio_get_max_msg(struct scmi_chan_info *base_cinfo)
|
||||
return vioch->max_msg;
|
||||
}
|
||||
|
||||
static bool virtio_chan_available(struct device_node *of_node, int idx)
|
||||
static bool
|
||||
virtio_chan_available(struct fwnode_handle *fwnode, int prot_id, int idx)
|
||||
{
|
||||
struct scmi_vio_channel *channels, *vioch = NULL;
|
||||
|
||||
|
||||
@@ -99,8 +99,10 @@ static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc)
|
||||
else
|
||||
chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
|
||||
|
||||
if (!chan_name)
|
||||
return -ENOMEM;
|
||||
if (!chan_name) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dsp_chan = &dsp_ipc->chans[i];
|
||||
dsp_chan->name = chan_name;
|
||||
|
||||
@@ -156,7 +156,7 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
|
||||
{
|
||||
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
|
||||
u32 *response_msg __free(kfree) =
|
||||
kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
|
||||
kzalloc_objs(*response_msg, AUTO_UPDATE_FEATURE_RESP_SIZE);
|
||||
struct mpfs_mss_response *response __free(kfree) =
|
||||
kzalloc_obj(struct mpfs_mss_response);
|
||||
struct mpfs_mss_msg *message __free(kfree) =
|
||||
@@ -358,7 +358,7 @@ static const struct fw_upload_ops mpfs_auto_update_ops = {
|
||||
static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv)
|
||||
{
|
||||
u32 *response_msg __free(kfree) =
|
||||
kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
|
||||
kzalloc_objs(*response_msg, AUTO_UPDATE_FEATURE_RESP_SIZE);
|
||||
struct mpfs_mss_response *response __free(kfree) =
|
||||
kzalloc_obj(struct mpfs_mss_response);
|
||||
struct mpfs_mss_msg *message __free(kfree) =
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
menu "Qualcomm firmware drivers"
|
||||
|
||||
config QCOM_PAS
|
||||
tristate "Qualcomm generic PAS interface driver"
|
||||
tristate "Qualcomm generic PAS interface driver" if COMPILE_TEST
|
||||
help
|
||||
Enable the generic Peripheral Authentication Service (PAS) provided
|
||||
by the firmware. It acts as the common layer with different TZ
|
||||
@@ -16,6 +16,7 @@ config QCOM_PAS
|
||||
|
||||
config QCOM_PAS_TEE
|
||||
tristate "Qualcomm PAS TEE interface driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
select QCOM_PAS
|
||||
depends on TEE
|
||||
depends on !CPU_BIG_ENDIAN
|
||||
@@ -25,7 +26,7 @@ config QCOM_PAS_TEE
|
||||
by the firmware TEE implementation as the backend.
|
||||
|
||||
config QCOM_SCM
|
||||
tristate "Qualcomm PAS SCM interface driver"
|
||||
tristate "Qualcomm PAS SCM interface driver" if ARCH_QCOM || COMPILE_TEST
|
||||
select QCOM_PAS
|
||||
select QCOM_TZMEM
|
||||
default y if ARCH_QCOM
|
||||
|
||||
@@ -219,7 +219,7 @@ out:
|
||||
* @res: SCM call return values
|
||||
*
|
||||
* This shall only be used with commands that are guaranteed to be
|
||||
* uninterruptable, atomic and SMP safe.
|
||||
* uninterruptible, atomic and SMP safe.
|
||||
*/
|
||||
int scm_legacy_call_atomic(struct device *unused,
|
||||
const struct qcom_scm_desc *desc,
|
||||
|
||||
@@ -576,26 +576,6 @@ static void qcom_scm_set_download_mode(struct qcom_scm *scm, u32 dload_mode)
|
||||
writel_relaxed(minidump_dest, scm->minidump_sram);
|
||||
}
|
||||
|
||||
struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev,
|
||||
u32 pas_id,
|
||||
phys_addr_t mem_phys,
|
||||
size_t mem_size)
|
||||
{
|
||||
struct qcom_pas_context *ctx;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ctx->dev = dev;
|
||||
ctx->pas_id = pas_id;
|
||||
ctx->mem_phys = mem_phys;
|
||||
ctx->mem_size = mem_size;
|
||||
|
||||
return (struct qcom_scm_pas_context *)ctx;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_qcom_scm_pas_context_alloc);
|
||||
|
||||
static int __qcom_scm_pas_init_image(struct device *dev, u32 pas_id,
|
||||
dma_addr_t mdata_phys,
|
||||
struct qcom_scm_res *res)
|
||||
@@ -653,9 +633,9 @@ static int qcom_scm_pas_prep_and_init_image(struct device *dev,
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
static int __qcom_scm_pas_init_image2(struct device *dev, u32 pas_id,
|
||||
const void *metadata, size_t size,
|
||||
struct qcom_pas_context *ctx)
|
||||
static int qcom_scm_pas_init_image(struct device *dev, u32 pas_id,
|
||||
const void *metadata, size_t size,
|
||||
struct qcom_pas_context *ctx)
|
||||
{
|
||||
struct qcom_scm_res res;
|
||||
dma_addr_t mdata_phys;
|
||||
@@ -695,16 +675,8 @@ static int __qcom_scm_pas_init_image2(struct device *dev, u32 pas_id,
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int qcom_scm_pas_init_image(u32 pas_id, const void *metadata, size_t size,
|
||||
struct qcom_scm_pas_context *ctx)
|
||||
{
|
||||
return __qcom_scm_pas_init_image2(__scm->dev, pas_id, metadata, size,
|
||||
(struct qcom_pas_context *)ctx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_init_image);
|
||||
|
||||
static void __qcom_scm_pas_metadata_release(struct device *dev,
|
||||
struct qcom_pas_context *ctx)
|
||||
static void qcom_scm_pas_metadata_release(struct device *dev,
|
||||
struct qcom_pas_context *ctx)
|
||||
{
|
||||
if (ctx->use_tzmem)
|
||||
qcom_tzmem_free(ctx->ptr);
|
||||
@@ -714,15 +686,8 @@ static void __qcom_scm_pas_metadata_release(struct device *dev,
|
||||
ctx->ptr = NULL;
|
||||
}
|
||||
|
||||
void qcom_scm_pas_metadata_release(struct qcom_scm_pas_context *ctx)
|
||||
{
|
||||
__qcom_scm_pas_metadata_release(__scm->dev,
|
||||
(struct qcom_pas_context *)ctx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_metadata_release);
|
||||
|
||||
static int __qcom_scm_pas_mem_setup(struct device *dev, u32 pas_id,
|
||||
phys_addr_t addr, phys_addr_t size)
|
||||
static int qcom_scm_pas_mem_setup(struct device *dev, u32 pas_id,
|
||||
phys_addr_t addr, phys_addr_t size)
|
||||
{
|
||||
int ret;
|
||||
struct qcom_scm_desc desc = {
|
||||
@@ -753,12 +718,6 @@ disable_clk:
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int qcom_scm_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size)
|
||||
{
|
||||
return __qcom_scm_pas_mem_setup(__scm->dev, pas_id, addr, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_mem_setup);
|
||||
|
||||
static void *__qcom_scm_pas_get_rsc_table(struct device *dev, u32 pas_id,
|
||||
void *input_rt_tzm,
|
||||
size_t input_rt_size,
|
||||
@@ -812,11 +771,10 @@ free_output_rt:
|
||||
return ret ? ERR_PTR(ret) : output_rt_tzm;
|
||||
}
|
||||
|
||||
static void *__qcom_scm_pas_get_rsc_table2(struct device *dev,
|
||||
struct qcom_pas_context *ctx,
|
||||
void *input_rt,
|
||||
size_t input_rt_size,
|
||||
size_t *output_rt_size)
|
||||
static void *qcom_scm_pas_get_rsc_table(struct device *dev,
|
||||
struct qcom_pas_context *ctx,
|
||||
void *input_rt, size_t input_rt_size,
|
||||
size_t *output_rt_size)
|
||||
{
|
||||
struct resource_table empty_rsc = {};
|
||||
size_t size = SZ_16K;
|
||||
@@ -854,17 +812,27 @@ static void *__qcom_scm_pas_get_rsc_table2(struct device *dev,
|
||||
output_rt_tzm = __qcom_scm_pas_get_rsc_table(dev, ctx->pas_id,
|
||||
input_rt_tzm,
|
||||
input_rt_size, &size);
|
||||
if (PTR_ERR(output_rt_tzm) == -EOVERFLOW)
|
||||
/* Try again with the size requested by the TZ */
|
||||
if (PTR_ERR(output_rt_tzm) == -EOVERFLOW) {
|
||||
/* Try again with a page-aligned size requested by the TZ. */
|
||||
size = PAGE_ALIGN(size);
|
||||
output_rt_tzm = __qcom_scm_pas_get_rsc_table(dev, ctx->pas_id,
|
||||
input_rt_tzm,
|
||||
input_rt_size,
|
||||
&size);
|
||||
}
|
||||
if (IS_ERR(output_rt_tzm)) {
|
||||
ret = PTR_ERR(output_rt_tzm);
|
||||
goto free_input_rt;
|
||||
}
|
||||
|
||||
*output_rt_size = size;
|
||||
|
||||
/* A zero-sized table means that TrustZone has no resource table. */
|
||||
if (!size) {
|
||||
tbl_ptr = NULL;
|
||||
goto free_output_rt;
|
||||
}
|
||||
|
||||
tbl_ptr = kmemdup(output_rt_tzm, size, GFP_KERNEL);
|
||||
if (!tbl_ptr) {
|
||||
qcom_tzmem_free(output_rt_tzm);
|
||||
@@ -872,7 +840,7 @@ static void *__qcom_scm_pas_get_rsc_table2(struct device *dev,
|
||||
goto free_input_rt;
|
||||
}
|
||||
|
||||
*output_rt_size = size;
|
||||
free_output_rt:
|
||||
qcom_tzmem_free(output_rt_tzm);
|
||||
|
||||
free_input_rt:
|
||||
@@ -887,19 +855,7 @@ disable_clk:
|
||||
return ret ? ERR_PTR(ret) : tbl_ptr;
|
||||
}
|
||||
|
||||
struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx,
|
||||
void *input_rt,
|
||||
size_t input_rt_size,
|
||||
size_t *output_rt_size)
|
||||
{
|
||||
return __qcom_scm_pas_get_rsc_table2(__scm->dev,
|
||||
(struct qcom_pas_context *)ctx,
|
||||
input_rt, input_rt_size,
|
||||
output_rt_size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_get_rsc_table);
|
||||
|
||||
static int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 pas_id)
|
||||
static int qcom_scm_pas_auth_and_reset(struct device *dev, u32 pas_id)
|
||||
{
|
||||
int ret;
|
||||
struct qcom_scm_desc desc = {
|
||||
@@ -928,14 +884,8 @@ disable_clk:
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int qcom_scm_pas_auth_and_reset(u32 pas_id)
|
||||
{
|
||||
return __qcom_scm_pas_auth_and_reset(__scm->dev, pas_id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_auth_and_reset);
|
||||
|
||||
static int __qcom_scm_pas_prepare_and_auth_reset(struct device *dev,
|
||||
struct qcom_pas_context *ctx)
|
||||
static int qcom_scm_pas_prepare_and_auth_reset(struct device *dev,
|
||||
struct qcom_pas_context *ctx)
|
||||
{
|
||||
u64 handle;
|
||||
int ret;
|
||||
@@ -946,7 +896,7 @@ static int __qcom_scm_pas_prepare_and_auth_reset(struct device *dev,
|
||||
* memory region and then invokes a call to TrustZone to authenticate.
|
||||
*/
|
||||
if (!ctx->use_tzmem)
|
||||
return __qcom_scm_pas_auth_and_reset(dev, ctx->pas_id);
|
||||
return qcom_scm_pas_auth_and_reset(dev, ctx->pas_id);
|
||||
|
||||
/*
|
||||
* When Linux runs @ EL2 Linux must create the shmbridge itself and then
|
||||
@@ -956,21 +906,14 @@ static int __qcom_scm_pas_prepare_and_auth_reset(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = __qcom_scm_pas_auth_and_reset(dev, ctx->pas_id);
|
||||
ret = qcom_scm_pas_auth_and_reset(dev, ctx->pas_id);
|
||||
qcom_tzmem_shm_bridge_delete(handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx)
|
||||
{
|
||||
return __qcom_scm_pas_prepare_and_auth_reset(__scm->dev,
|
||||
(struct qcom_pas_context *)ctx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_prepare_and_auth_reset);
|
||||
|
||||
static int __qcom_scm_pas_set_remote_state(struct device *dev, u32 state,
|
||||
u32 pas_id)
|
||||
static int qcom_scm_pas_set_remote_state(struct device *dev, u32 state,
|
||||
u32 pas_id)
|
||||
{
|
||||
struct qcom_scm_desc desc = {
|
||||
.svc = QCOM_SCM_SVC_BOOT,
|
||||
@@ -988,13 +931,7 @@ static int __qcom_scm_pas_set_remote_state(struct device *dev, u32 state,
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int qcom_scm_set_remote_state(u32 state, u32 id)
|
||||
{
|
||||
return __qcom_scm_pas_set_remote_state(__scm->dev, state, id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_set_remote_state);
|
||||
|
||||
static int __qcom_scm_pas_shutdown(struct device *dev, u32 pas_id)
|
||||
static int qcom_scm_pas_shutdown(struct device *dev, u32 pas_id)
|
||||
{
|
||||
int ret;
|
||||
struct qcom_scm_desc desc = {
|
||||
@@ -1023,13 +960,7 @@ disable_clk:
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int qcom_scm_pas_shutdown(u32 pas_id)
|
||||
{
|
||||
return __qcom_scm_pas_shutdown(__scm->dev, pas_id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_shutdown);
|
||||
|
||||
static bool __qcom_scm_pas_supported(struct device *dev, u32 pas_id)
|
||||
static bool qcom_scm_pas_supported(struct device *dev, u32 pas_id)
|
||||
{
|
||||
int ret;
|
||||
struct qcom_scm_desc desc = {
|
||||
@@ -1050,23 +981,17 @@ static bool __qcom_scm_pas_supported(struct device *dev, u32 pas_id)
|
||||
return ret ? false : !!res.result[0];
|
||||
}
|
||||
|
||||
bool qcom_scm_pas_supported(u32 pas_id)
|
||||
{
|
||||
return __qcom_scm_pas_supported(__scm->dev, pas_id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_pas_supported);
|
||||
|
||||
static struct qcom_pas_ops qcom_pas_ops_scm = {
|
||||
.drv_name = "qcom_scm",
|
||||
.supported = __qcom_scm_pas_supported,
|
||||
.init_image = __qcom_scm_pas_init_image2,
|
||||
.mem_setup = __qcom_scm_pas_mem_setup,
|
||||
.get_rsc_table = __qcom_scm_pas_get_rsc_table2,
|
||||
.auth_and_reset = __qcom_scm_pas_auth_and_reset,
|
||||
.prepare_and_auth_reset = __qcom_scm_pas_prepare_and_auth_reset,
|
||||
.set_remote_state = __qcom_scm_pas_set_remote_state,
|
||||
.shutdown = __qcom_scm_pas_shutdown,
|
||||
.metadata_release = __qcom_scm_pas_metadata_release,
|
||||
.supported = qcom_scm_pas_supported,
|
||||
.init_image = qcom_scm_pas_init_image,
|
||||
.mem_setup = qcom_scm_pas_mem_setup,
|
||||
.get_rsc_table = qcom_scm_pas_get_rsc_table,
|
||||
.auth_and_reset = qcom_scm_pas_auth_and_reset,
|
||||
.prepare_and_auth_reset = qcom_scm_pas_prepare_and_auth_reset,
|
||||
.set_remote_state = qcom_scm_pas_set_remote_state,
|
||||
.shutdown = qcom_scm_pas_shutdown,
|
||||
.metadata_release = qcom_scm_pas_metadata_release,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2302,6 +2227,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
|
||||
static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
|
||||
{ .compatible = "asus,vivobook-s15" },
|
||||
{ .compatible = "asus,vivobook-s15-x1p4" },
|
||||
{ .compatible = "asus,zenbook-a14-ux3407na" },
|
||||
{ .compatible = "asus,zenbook-a14-ux3407qa" },
|
||||
{ .compatible = "asus,zenbook-a14-ux3407ra" },
|
||||
{ .compatible = "asus,zenbook-a16-ux3607oa" },
|
||||
@@ -2311,14 +2237,17 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
|
||||
{ .compatible = "ecs,liva-qc710" },
|
||||
{ .compatible = "honor,magicbook-art-14-snapdragon" },
|
||||
{ .compatible = "hp,elitebook-ultra-g1q" },
|
||||
{ .compatible = "hp,elitebook-x-g2q" },
|
||||
{ .compatible = "hp,omnibook-x14" },
|
||||
{ .compatible = "huawei,gaokun3" },
|
||||
{ .compatible = "lenovo,flex-5g" },
|
||||
{ .compatible = "lenovo,ideacentre-mini-01q8x10" },
|
||||
{ .compatible = "lenovo,thinkbook-16" },
|
||||
{ .compatible = "lenovo,thinkpad-t14s" },
|
||||
{ .compatible = "lenovo,thinkpad-t14s-gen7" },
|
||||
{ .compatible = "lenovo,thinkpad-x13s", },
|
||||
{ .compatible = "lenovo,yoga-slim7x" },
|
||||
{ .compatible = "lenovo,yoga-slim7x-gen11" },
|
||||
{ .compatible = "medion,sprchrgd14s1" },
|
||||
{ .compatible = "microsoft,arcata", },
|
||||
{ .compatible = "microsoft,surface-pro-12in", },
|
||||
@@ -2327,7 +2256,9 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
|
||||
{ .compatible = "microsoft,romulus13", },
|
||||
{ .compatible = "microsoft,romulus15", },
|
||||
{ .compatible = "qcom,glymur-crd" },
|
||||
{ .compatible = "qcom,glymur-qcb" },
|
||||
{ .compatible = "qcom,hamoa-iot-evk" },
|
||||
{ .compatible = "qcom,kalambo-crd" },
|
||||
{ .compatible = "qcom,mahua-crd" },
|
||||
{ .compatible = "qcom,purwa-iot-evk" },
|
||||
{ .compatible = "qcom,sc8180x-primus" },
|
||||
@@ -2844,17 +2775,15 @@ static int qcom_scm_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_reserved_mem_device_init(scm->dev);
|
||||
ret = devm_of_reserved_mem_device_init(scm->dev);
|
||||
if (ret && ret != -ENODEV)
|
||||
return dev_err_probe(scm->dev, ret,
|
||||
"Failed to setup the reserved memory region for TZ mem\n");
|
||||
|
||||
ret = qcom_tzmem_enable(scm->dev);
|
||||
if (ret) {
|
||||
ret = dev_err_probe(scm->dev, ret,
|
||||
"Failed to enable the TrustZone memory allocator\n");
|
||||
goto err_rmem;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(scm->dev, ret,
|
||||
"Failed to enable the TrustZone memory allocator\n");
|
||||
|
||||
memset(&pool_config, 0, sizeof(pool_config));
|
||||
pool_config.initial_size = 0;
|
||||
@@ -2862,11 +2791,9 @@ static int qcom_scm_probe(struct platform_device *pdev)
|
||||
pool_config.max_size = SZ_256K;
|
||||
|
||||
scm->mempool = devm_qcom_tzmem_pool_new(scm->dev, &pool_config);
|
||||
if (IS_ERR(scm->mempool)) {
|
||||
ret = dev_err_probe(scm->dev, PTR_ERR(scm->mempool),
|
||||
"Failed to create the SCM memory pool\n");
|
||||
goto err_rmem;
|
||||
}
|
||||
if (IS_ERR(scm->mempool))
|
||||
return dev_err_probe(scm->dev, PTR_ERR(scm->mempool),
|
||||
"Failed to create the SCM memory pool\n");
|
||||
|
||||
ret = qcom_scm_query_waitq_count(scm);
|
||||
scm->wq_cnt = ret < 0 ? QCOM_SCM_DEFAULT_WAITQ_COUNT : ret;
|
||||
@@ -2942,10 +2869,6 @@ static int qcom_scm_probe(struct platform_device *pdev)
|
||||
qcom_scm_gunyah_wdt_init(scm);
|
||||
|
||||
return 0;
|
||||
|
||||
err_rmem:
|
||||
of_reserved_mem_device_release(scm->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qcom_scm_shutdown(struct platform_device *pdev)
|
||||
|
||||
@@ -82,6 +82,7 @@ static const char *const qcom_tzmem_blacklist[] = {
|
||||
"qcom,sc8180x",
|
||||
"qcom,sdm670", /* failure in GPU firmware loading */
|
||||
"qcom,sdm845", /* reset in rmtfs memory assignment */
|
||||
"qcom,sm7125", /* hang in rmtfs memory assignment */
|
||||
"qcom,sm7150", /* reset in rmtfs memory assignment */
|
||||
"qcom,sm8150", /* reset in rmtfs memory assignment */
|
||||
NULL
|
||||
@@ -516,7 +517,7 @@ int qcom_tzmem_enable(struct device *dev)
|
||||
static int result;
|
||||
|
||||
qcom_tzmem_dev = dev;
|
||||
DO_ONCE(qcom_tzmem_do_init, &result);
|
||||
DO_ONCE_SLEEPABLE(qcom_tzmem_do_init, &result);
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_tzmem_enable);
|
||||
|
||||
@@ -4050,7 +4050,7 @@ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
|
||||
.default_host_id = 2,
|
||||
/* Conservative duration */
|
||||
.max_rx_timeout_ms = 1000,
|
||||
/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
|
||||
/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle up to 128 messages! */
|
||||
.max_msgs = 20,
|
||||
.max_msg_size = 64,
|
||||
};
|
||||
@@ -4060,7 +4060,7 @@ static const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
|
||||
.default_host_id = 12,
|
||||
/* Conservative duration */
|
||||
.max_rx_timeout_ms = 10000,
|
||||
/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
|
||||
/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle up to 128 messages! */
|
||||
.max_msgs = 20,
|
||||
.max_msg_size = 60,
|
||||
};
|
||||
@@ -4132,7 +4132,7 @@ static int ti_sci_probe(struct platform_device *pdev)
|
||||
|
||||
/* Pre-initialize the buffer pointer to pre-allocated buffers */
|
||||
for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) {
|
||||
xfer->xfer_buf = devm_kcalloc(dev, 1, desc->max_msg_size,
|
||||
xfer->xfer_buf = devm_kzalloc(dev, desc->max_msg_size,
|
||||
GFP_KERNEL);
|
||||
if (!xfer->xfer_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2025 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware/xlnx-zynqmp.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -33,7 +34,7 @@
|
||||
*
|
||||
* Return: Returns 0 on success or error value on failure.
|
||||
*/
|
||||
int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
|
||||
static int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
|
||||
{
|
||||
u32 regval;
|
||||
int ret;
|
||||
@@ -53,7 +54,6 @@ int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_is_sram_init_done - check SRAM initialization
|
||||
@@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready);
|
||||
*
|
||||
* Return: Returns 0 on success or error value on failure.
|
||||
*/
|
||||
int zynqmp_pm_is_sram_init_done(bool *is_done)
|
||||
static int zynqmp_pm_is_sram_init_done(bool *is_done)
|
||||
{
|
||||
u32 regval;
|
||||
int ret;
|
||||
@@ -81,7 +81,69 @@ int zynqmp_pm_is_sram_init_done(bool *is_done)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_is_sram_init_done);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_wait_mphy_tx_rx_config_ready - wait for M-PHY TX-RX config ready
|
||||
* @timeout_us: Caller-supplied timeout budget in microseconds
|
||||
*
|
||||
* Poll the M-PHY TX-RX configuration-ready status until it settles or the
|
||||
* timeout elapses. The poll loop is EEMI-specific (legacy firmware only offers
|
||||
* the per-read status primitive), so it lives here in the firmware driver
|
||||
* rather than in the UFS controller driver; an SCMI-based backend can instead
|
||||
* offload the wait to the platform in a single call. The timeout budget is
|
||||
* owned by the caller (UFS driver), keeping the policy with the consumer.
|
||||
*
|
||||
* Return: Returns 0 once ready, -ETIMEDOUT on timeout, or error value.
|
||||
*/
|
||||
int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us)
|
||||
{
|
||||
bool is_ready;
|
||||
int ret;
|
||||
|
||||
while (timeout_us--) {
|
||||
ret = zynqmp_pm_is_mphy_tx_rx_config_ready(&is_ready);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!is_ready)
|
||||
return 0;
|
||||
|
||||
usleep_range(1, 5);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_wait_mphy_tx_rx_config_ready);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_wait_sram_init_done - wait for SRAM initialization to complete
|
||||
* @timeout_us: Caller-supplied timeout budget in microseconds
|
||||
*
|
||||
* Poll the SRAM initialization-done status until it is set or the timeout
|
||||
* elapses. As with the M-PHY wait, the poll loop is EEMI-specific and kept in
|
||||
* the firmware driver so the UFS controller driver stays backend-agnostic.
|
||||
*
|
||||
* Return: Returns 0 once done, -ETIMEDOUT on timeout, or error value.
|
||||
*/
|
||||
int zynqmp_pm_wait_sram_init_done(u32 timeout_us)
|
||||
{
|
||||
bool is_done;
|
||||
int ret;
|
||||
|
||||
while (timeout_us--) {
|
||||
ret = zynqmp_pm_is_sram_init_done(&is_done);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (is_done)
|
||||
return 0;
|
||||
|
||||
usleep_range(1, 5);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_wait_sram_init_done);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_set_sram_bypass - Set SRAM bypass Control
|
||||
|
||||
@@ -1527,7 +1527,6 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
|
||||
*/
|
||||
int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr)
|
||||
{
|
||||
enum rpu_boot_mem bootmem;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -1536,22 +1535,55 @@ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr)
|
||||
* starts at the base-address and subsequent vectors are on 4-byte
|
||||
* boundaries.
|
||||
*
|
||||
* The Cortex-R5 cores can boot from TCM and OCM memories.
|
||||
* Exception vectors can start either from 0x0000_0000 (LOVEC) or
|
||||
* from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory)
|
||||
*
|
||||
* Usually firmware will put Exception vectors at LOVEC.
|
||||
*
|
||||
* The Cortex-R52 cores can boot from DDR and TCM.
|
||||
* That means vector table can be at address 0x0 or at any DDR address
|
||||
* that is in the 32-bit address range. Note that booting from DDR
|
||||
* address 0x0 is not supported and the user must always assume that if
|
||||
* 0x0 address is passed, then it will be TCM boot.
|
||||
*
|
||||
* It is not recommend that you change the exception vector.
|
||||
* Changing the EVP to HIVEC will result in increased interrupt latency
|
||||
* and jitter. Also, if the OCM is secured and the Cortex-R5F processor
|
||||
* is non-secured, then the Cortex-R5F processor cannot access the
|
||||
* HIVEC exception vectors in the OCM.
|
||||
*/
|
||||
bootmem = (bootaddr >= 0xFFFC0000) ?
|
||||
PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC;
|
||||
if (upper_32_bits(bootaddr)) {
|
||||
pr_err("invalid bootaddr = 0x%llx\n", bootaddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("RPU boot addr 0x%llx from %s.", bootaddr,
|
||||
bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM");
|
||||
/*
|
||||
* New platforms can boot from DDR and require the DDR address
|
||||
* to be configured explicitly. If the correct version of the
|
||||
* IOCTL_RPU_BOOT_ADDR_CONFIG ioctl is not supported, do not
|
||||
* treat it as a failure. If a DDR address is passed on other
|
||||
* platforms, the PM request wake EEMI call will still fail and
|
||||
* the RPU won't boot.
|
||||
*/
|
||||
ret = zynqmp_pm_is_function_supported(PM_IOCTL,
|
||||
IOCTL_RPU_BOOT_ADDR_CONFIG);
|
||||
if (!ret) {
|
||||
/* config ddr boot address */
|
||||
ret = zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3,
|
||||
node,
|
||||
IOCTL_RPU_BOOT_ADDR_CONFIG,
|
||||
bootaddr);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to set RPU Boot address 0x%llx\n",
|
||||
bootaddr);
|
||||
return ret;
|
||||
}
|
||||
} else if (ret != -EOPNOTSUPP && ret != -ENODATA) {
|
||||
pr_err("ioctl rpu boot addr config ver check failed %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Request node before starting RPU core if new version of API is supported */
|
||||
if (zynqmp_pm_feature(PM_REQUEST_NODE) > PM_API_VERSION_1) {
|
||||
@@ -1565,7 +1597,7 @@ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr)
|
||||
}
|
||||
|
||||
ret = zynqmp_pm_request_wake(node, true,
|
||||
bootmem, ZYNQMP_PM_REQUEST_ACK_NO);
|
||||
bootaddr, ZYNQMP_PM_REQUEST_ACK_NO);
|
||||
if (ret)
|
||||
pr_err("failed to start RPU = 0x%x\n", node);
|
||||
return ret;
|
||||
|
||||
@@ -182,6 +182,8 @@ struct brcmstb_dpfe_priv {
|
||||
void __iomem *regs;
|
||||
void __iomem *dmem;
|
||||
void __iomem *imem;
|
||||
resource_size_t regs_size;
|
||||
resource_size_t dmem_size;
|
||||
struct device *dev;
|
||||
const struct dpfe_api *dpfe_api;
|
||||
struct mutex lock;
|
||||
@@ -401,9 +403,14 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
|
||||
*/
|
||||
switch (msg_type) {
|
||||
case 1:
|
||||
if (DCPU_MSG_RAM_START + offset + DRAM_VENDOR_ERROR +
|
||||
sizeof(u32) > priv->regs_size)
|
||||
goto bad_offset;
|
||||
ptr = priv->regs + DCPU_MSG_RAM_START + offset;
|
||||
break;
|
||||
case 0:
|
||||
if (offset + DRAM_VENDOR_ERROR + sizeof(u32) > priv->dmem_size)
|
||||
goto bad_offset;
|
||||
ptr = priv->dmem + offset;
|
||||
break;
|
||||
default:
|
||||
@@ -415,6 +422,12 @@ static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
||||
bad_offset:
|
||||
dev_err(priv->dev, "DCPU returned out-of-range offset %#x\n", offset);
|
||||
if (buf && size)
|
||||
*size = sprintf(buf, "ERROR: DCPU offset out of range\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __finalize_command(struct brcmstb_dpfe_priv *priv)
|
||||
@@ -490,6 +503,8 @@ static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
|
||||
for (i = 0; i < MSG_FIELD_MAX; i++)
|
||||
result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
|
||||
chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
|
||||
if (chksum_idx >= MSG_FIELD_MAX)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Tell DCPU we are done */
|
||||
@@ -518,9 +533,15 @@ static int __verify_firmware(struct init_data *init,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
const struct dpfe_firmware_header *header = (void *)fw->data;
|
||||
unsigned int dmem_size, imem_size, total_size;
|
||||
unsigned int dmem_size, imem_size;
|
||||
bool is_big_endian = false;
|
||||
const u32 *chksum_ptr;
|
||||
size_t payload_size;
|
||||
|
||||
if (fw->size < sizeof(*header) + sizeof(*chksum_ptr))
|
||||
return ERR_INVALID_SIZE;
|
||||
|
||||
payload_size = fw->size - sizeof(*header) - sizeof(*chksum_ptr);
|
||||
|
||||
if (header->magic == DPFE_BE_MAGIC)
|
||||
is_big_endian = true;
|
||||
@@ -539,13 +560,8 @@ static int __verify_firmware(struct init_data *init,
|
||||
if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0)
|
||||
return ERR_INVALID_SIZE;
|
||||
|
||||
/*
|
||||
* The header + the data section + the instruction section + the
|
||||
* checksum must be equal to the total firmware size.
|
||||
*/
|
||||
total_size = dmem_size + imem_size + sizeof(*header) +
|
||||
sizeof(*chksum_ptr);
|
||||
if (total_size != fw->size)
|
||||
/* The data and instruction sections must fill the payload exactly. */
|
||||
if (dmem_size > payload_size || imem_size != payload_size - dmem_size)
|
||||
return ERR_INVALID_SIZE;
|
||||
|
||||
/* The checksum comes at the very end. */
|
||||
@@ -858,6 +874,7 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct brcmstb_dpfe_priv *priv;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -869,17 +886,21 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
|
||||
mutex_init(&priv->lock);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->regs = devm_platform_ioremap_resource_byname(pdev, "dpfe-cpu");
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu");
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "couldn't map DCPU registers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
priv->regs_size = resource_size(res);
|
||||
|
||||
priv->dmem = devm_platform_ioremap_resource_byname(pdev, "dpfe-dmem");
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-dmem");
|
||||
priv->dmem = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->dmem)) {
|
||||
dev_err(dev, "Couldn't map DCPU data memory\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
priv->dmem_size = resource_size(res);
|
||||
|
||||
priv->imem = devm_platform_ioremap_resource_byname(pdev, "dpfe-imem");
|
||||
if (IS_ERR(priv->imem)) {
|
||||
|
||||
@@ -922,6 +922,7 @@ static struct emif_data *of_get_memory_device_details(
|
||||
if (!emif || !pd || !dev_info) {
|
||||
dev_err(dev, "%s: Out of memory!!\n",
|
||||
__func__);
|
||||
of_node_put(np_ddr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -946,6 +947,7 @@ static struct emif_data *of_get_memory_device_details(
|
||||
pd->device_info->io_width, pd->phy_type, pd->ip_rev,
|
||||
emif->dev)) {
|
||||
dev_err(dev, "%s: invalid device data!!\n", __func__);
|
||||
of_node_put(np_ddr);
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
@@ -1062,7 +1064,8 @@ static struct emif_data *get_device_details(
|
||||
}
|
||||
|
||||
if (pd->min_tck) {
|
||||
temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL);
|
||||
temp = devm_kzalloc(dev, sizeof(struct lpddr2_min_tck),
|
||||
GFP_KERNEL);
|
||||
if (temp) {
|
||||
memcpy(temp, pd->min_tck, sizeof(*pd->min_tck));
|
||||
pd->min_tck = temp;
|
||||
@@ -1140,6 +1143,7 @@ static void emif_remove(struct platform_device *pdev)
|
||||
struct emif_data *emif = platform_get_drvdata(pdev);
|
||||
|
||||
emif_debugfs_exit(emif);
|
||||
of_node_put(emif->np_ddr);
|
||||
}
|
||||
|
||||
static void emif_shutdown(struct platform_device *pdev)
|
||||
|
||||
@@ -558,7 +558,7 @@
|
||||
#define EMIF_SRAM_AM33_REG_LAYOUT 0x00000000
|
||||
#define EMIF_SRAM_AM43_REG_LAYOUT 0x00000001
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef __ASSEMBLER__
|
||||
/*
|
||||
* Structure containing shadow of important registers in EMIF
|
||||
* The calculation function fills in this structure to be later used for
|
||||
@@ -603,5 +603,5 @@ void ti_emif_enter_sr(void);
|
||||
void ti_emif_exit_sr(void);
|
||||
void ti_emif_abort_sr(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* __EMIF_H */
|
||||
@@ -401,6 +401,30 @@ static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||
[25] = {0x01},
|
||||
};
|
||||
|
||||
static const u8 mtk_smi_larb_mt8189_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||
[0] = {0x8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,},
|
||||
[1] = {0x8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,},
|
||||
[2] = {0x7, 0x7, 0x4, 0x4, 0x1, 0x1, 0x2, 0x2, 0x7, 0x7,},
|
||||
[4] = {0x2f, 0x1e, 0x9, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x5, 0x1, 0x17,},
|
||||
[7] = {0x20, 0x2, 0x1, 0x1, 0x1, 0x4, 0x2, 0x1, 0x1, 0x2, 0x3, 0x2,
|
||||
0xa, 0xf, 0x4, 0x6, 0x5, 0x1,},
|
||||
[9] = {0x6, 0x3, 0xc, 0x6, 0x1, 0x4, 0x3, 0x1, 0x2, 0x4, 0x5, 0x2,
|
||||
0x4, 0x2, 0x3, 0xb, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||
0x1, 0x1,},
|
||||
[11] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||
0x1, 0x1, 0x1, 0xb, 0x1, 0x4, 0x6, 0x5, 0x6, 0x1, 0x5, 0x2,
|
||||
0x9, 0x5,},
|
||||
[13] = {0x2, 0x8, 0x8, 0x8, 0x4, 0x4, 0x4, 0x4, 0x4, 0xe, 0x4, 0x1,
|
||||
0x6, 0x6, 0x2,},
|
||||
[14] = {0x1, 0x1, 0x1, 0x20, 0xe, 0x4, 0x8, 0x8, 0x6, 0x4,},
|
||||
[16] = {0x1e, 0xc, 0x2, 0x8, 0xe, 0x2, 0x1e, 0x10, 0x4, 0x2, 0x2, 0x2,
|
||||
0x2, 0x2, 0x4, 0x2, 0x4,},
|
||||
[17] = {0x1e, 0xc, 0x2, 0x8, 0xe, 0x2, 0x1e, 0x10, 0x4, 0x2, 0x2, 0x2,
|
||||
0x2, 0x2, 0x4, 0x2, 0x4,},
|
||||
[19] = {0x2, 0x1, 0x3, 0x1,},
|
||||
[20] = {0x7, 0x7, 0x3, 0x3, 0x1, 0x1,},
|
||||
};
|
||||
|
||||
static const u8 mtk_smi_larb_mt8192_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||
[0] = {0x2, 0x2, 0x28, 0xa, 0xc, 0x28,},
|
||||
[1] = {0x2, 0x2, 0x18, 0x18, 0x18, 0xa, 0xc, 0x28,},
|
||||
@@ -533,6 +557,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
|
||||
.ostd = mtk_smi_larb_mt8188_ostd,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8189 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
.flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
|
||||
MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL,
|
||||
.ostd = mtk_smi_larb_mt8189_ostd,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
|
||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||
.ostd = mtk_smi_larb_mt8192_ostd,
|
||||
@@ -556,6 +587,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
|
||||
{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
|
||||
{.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186},
|
||||
{.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188},
|
||||
{.compatible = "mediatek,mt8189-smi-larb", .data = &mtk_smi_larb_mt8189},
|
||||
{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
|
||||
{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
|
||||
{}
|
||||
@@ -808,6 +840,17 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
|
||||
.init = mtk_smi_common_mt8195_init,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8189 = {
|
||||
.type = MTK_SMI_GEN2,
|
||||
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(5) |
|
||||
F_MMU1_LARB(7),
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8189 = {
|
||||
.type = MTK_SMI_GEN2_SUB_COMM,
|
||||
.has_gals = true,
|
||||
};
|
||||
|
||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
|
||||
.type = MTK_SMI_GEN2,
|
||||
.has_gals = true,
|
||||
@@ -852,6 +895,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
|
||||
{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
|
||||
{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
|
||||
{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
|
||||
{.compatible = "mediatek,mt8189-smi-common", .data = &mtk_smi_common_mt8189},
|
||||
{.compatible = "mediatek,mt8189-smi-sub-common", .data = &mtk_smi_sub_common_mt8189},
|
||||
{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
|
||||
{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
|
||||
{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
|
||||
|
||||
@@ -34,6 +34,7 @@ static const struct regmap_access_table rpcif_volatile_table = {
|
||||
|
||||
static const struct regmap_range xspi_volatile_ranges[] = {
|
||||
regmap_reg_range(XSPI_CDD0BUF0, XSPI_CDD0BUF0),
|
||||
regmap_reg_range(XSPI_CDD1BUF0, XSPI_CDD1BUF0),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table xspi_volatile_table = {
|
||||
@@ -311,6 +312,14 @@ static int xspi_hw_init_impl(struct rpcif_priv *xspi, bool hyperflash)
|
||||
regmap_update_bits(xspi->regmap, XSPI_INTE, XSPI_INTE_CMDCMPE,
|
||||
XSPI_INTE_CMDCMPE);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL0,
|
||||
XSPI_BMCTL0_CS0ACC(0xff), XSPI_BMCTL0_CS0ACC(0x03));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCFG,
|
||||
XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB |
|
||||
XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN,
|
||||
0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) |
|
||||
XSPI_BMCFG_PREEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -627,18 +636,14 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi)
|
||||
u32 pos = 0, max = 8;
|
||||
int ret = 0;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRNUM(0x3),
|
||||
/* Clear transaction number and request */
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0,
|
||||
XSPI_CDCTL0_TRNUM(0x3) | XSPI_CDCTL0_TRREQ,
|
||||
XSPI_CDCTL0_TRNUM(0));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0, XSPI_CDCTL0_TRREQ, 0);
|
||||
|
||||
regmap_write(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_CMDSIZE(0x1) | XSPI_CDTBUF_CMD_FIELD(xspi->command));
|
||||
|
||||
regmap_write(xspi->regmap, XSPI_CDABUF0, 0);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, XSPI_CDTBUF_ADDSIZE(0x7),
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
XSPI_CDTBUF_CMDSIZE(0x1) | XSPI_CDTBUF_CMD_FIELD(xspi->command) |
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
|
||||
regmap_write(xspi->regmap, XSPI_CDABUF0, xspi->smadr);
|
||||
|
||||
@@ -651,17 +656,12 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi)
|
||||
u32 bytes_left = xspi->xferlen - pos;
|
||||
u32 nbytes, data[2], *p = data;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_TRTYPE, XSPI_CDTBUF_TRTYPE);
|
||||
|
||||
nbytes = bytes_left >= max ? max : bytes_left;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_DATASIZE(0xf),
|
||||
XSPI_CDTBUF_DATASIZE(nbytes));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_TRTYPE | XSPI_CDTBUF_DATASIZE(0xf) |
|
||||
XSPI_CDTBUF_ADDSIZE(0x7),
|
||||
XSPI_CDTBUF_TRTYPE | XSPI_CDTBUF_DATASIZE(nbytes) |
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
|
||||
memcpy(data, xspi->buffer + pos, nbytes);
|
||||
@@ -693,30 +693,33 @@ static int xspi_manual_xfer_impl(struct rpcif_priv *xspi)
|
||||
while (pos < xspi->xferlen) {
|
||||
u32 bytes_left = xspi->xferlen - pos;
|
||||
u32 nbytes, data[2], *p = data;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_TRTYPE,
|
||||
~(u32)XSPI_CDTBUF_TRTYPE);
|
||||
u32 cdtbuf0_mask, cdtbuf0_val;
|
||||
|
||||
/* nbytes can be up to 8 bytes */
|
||||
nbytes = bytes_left >= max ? max : bytes_left;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_DATASIZE(0xf),
|
||||
XSPI_CDTBUF_DATASIZE(nbytes));
|
||||
/* clear TRTYPE */
|
||||
cdtbuf0_mask = XSPI_CDTBUF_TRTYPE;
|
||||
cdtbuf0_val = 0;
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_ADDSIZE(0x7),
|
||||
XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes));
|
||||
/* program DATASIZE */
|
||||
cdtbuf0_mask |= XSPI_CDTBUF_DATASIZE(0xf);
|
||||
cdtbuf0_val |= XSPI_CDTBUF_DATASIZE(nbytes);
|
||||
|
||||
/* program ADDSIZE */
|
||||
cdtbuf0_mask |= XSPI_CDTBUF_ADDSIZE(0x7);
|
||||
cdtbuf0_val |= XSPI_CDTBUF_ADDSIZE(xspi->addr_nbytes);
|
||||
|
||||
/* program LATE */
|
||||
cdtbuf0_mask |= XSPI_CDTBUF_LATE(0x1f);
|
||||
cdtbuf0_val |= XSPI_CDTBUF_LATE(xspi->dummy);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0, cdtbuf0_mask, cdtbuf0_val);
|
||||
|
||||
if (xspi->addr_nbytes)
|
||||
regmap_write(xspi->regmap, XSPI_CDABUF0,
|
||||
xspi->smadr + pos);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDTBUF0,
|
||||
XSPI_CDTBUF_LATE(0x1f),
|
||||
XSPI_CDTBUF_LATE(xspi->dummy));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_CDCTL0,
|
||||
XSPI_CDCTL0_TRREQ, XSPI_CDCTL0_TRREQ);
|
||||
|
||||
@@ -773,7 +776,7 @@ int rpcif_manual_xfer(struct device *dev)
|
||||
|
||||
ret = rpc->info->impl->manual_xfer(rpc);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -868,15 +871,6 @@ static size_t xspi_dirmap_read_impl(struct rpcif_priv *xspi, u64 offs,
|
||||
XSPI_CMCFG1_RDCMD_UPPER_BYTE(xspi->command) |
|
||||
XSPI_CMCFG1_RDLATE(xspi->dummy));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL0, XSPI_BMCTL0_CS0ACC(0xff),
|
||||
XSPI_BMCTL0_CS0ACC(0x01));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCFG,
|
||||
XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB |
|
||||
XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN,
|
||||
0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) |
|
||||
XSPI_BMCFG_PREEN);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_LIOCFGCS0, XSPI_LIOCFG_PRTMD(0x3ff),
|
||||
XSPI_LIOCFG_PRTMD(xspi->proto));
|
||||
|
||||
@@ -897,7 +891,7 @@ ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf)
|
||||
|
||||
read = rpc->info->impl->dirmap_read(rpc, offs, len, buf);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return read;
|
||||
}
|
||||
@@ -944,15 +938,6 @@ ssize_t xspi_dirmap_write(struct device *dev, u64 offs, size_t len, const void *
|
||||
XSPI_CMCFG2_WRCMD_UPPER(xspi->command) |
|
||||
XSPI_CMCFG2_WRLATE(xspi->dummy));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL0,
|
||||
XSPI_BMCTL0_CS0ACC(0xff), XSPI_BMCTL0_CS0ACC(0x03));
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCFG,
|
||||
XSPI_BMCFG_WRMD | XSPI_BMCFG_MWRCOMB |
|
||||
XSPI_BMCFG_MWRSIZE(0xff) | XSPI_BMCFG_PREEN,
|
||||
0 | XSPI_BMCFG_MWRCOMB | XSPI_BMCFG_MWRSIZE(0x0f) |
|
||||
XSPI_BMCFG_PREEN);
|
||||
|
||||
regmap_update_bits(xspi->regmap, XSPI_LIOCFGCS0, XSPI_LIOCFG_PRTMD(0x3ff),
|
||||
XSPI_LIOCFG_PRTMD(xspi->proto));
|
||||
|
||||
@@ -963,7 +948,7 @@ ssize_t xspi_dirmap_write(struct device *dev, u64 offs, size_t len, const void *
|
||||
regmap_update_bits(xspi->regmap, XSPI_BMCTL1,
|
||||
XSPI_BMCTL1_MWRPUSH, XSPI_BMCTL1_MWRPUSH);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return writebytes;
|
||||
}
|
||||
|
||||
@@ -1297,8 +1297,15 @@ static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_prepare_enable(dmc->fout_bpll);
|
||||
clk_prepare_enable(dmc->mout_bpll);
|
||||
ret = clk_prepare_enable(dmc->fout_bpll);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(dmc->mout_bpll);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(dmc->fout_bpll);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some bootloaders do not set clock routes correctly.
|
||||
|
||||
@@ -274,6 +274,8 @@ static int stm32_omm_configure(struct device *dev)
|
||||
writel_relaxed(omm->cr, omm->io_base + OMM_CR);
|
||||
|
||||
ret = stm32_omm_set_amcr(dev, true);
|
||||
if (ret && (mux & CR_MUXEN))
|
||||
stm32_omm_toggle_child_clock(dev, false);
|
||||
|
||||
error:
|
||||
pm_runtime_put_sync_suspend(dev);
|
||||
|
||||
+245
-147
@@ -15,6 +15,47 @@
|
||||
#include "mc.h"
|
||||
#include "tegra264-bwmgr.h"
|
||||
|
||||
/*
|
||||
* Description of a single MCF error type: where to read the status and the
|
||||
* faulting address, how to extract the high address bits, which bits encode
|
||||
* the access direction and security state and the optional error-type sub-code.
|
||||
*/
|
||||
struct tegra264_mc_fault {
|
||||
const char *const *type_names;
|
||||
u32 addr_hi_mask;
|
||||
u32 addr_hi_reg;
|
||||
u32 addr_hi_shift;
|
||||
u32 addr_reg;
|
||||
u32 rw_bit;
|
||||
u32 sec_bit;
|
||||
u32 status1_reg;
|
||||
u32 status_reg;
|
||||
u32 type_mask;
|
||||
u32 type_shift;
|
||||
};
|
||||
|
||||
/*
|
||||
* Maps an MCF interrupt to a callback that fills in the register offsets and
|
||||
* decoding parameters for that error type. The register offsets live in the
|
||||
* per-SoC tegra_mc_regs, so they are collected at runtime rather than being
|
||||
* stored in a static table.
|
||||
*/
|
||||
struct tegra264_mc_error_handler {
|
||||
u32 mask;
|
||||
void (*get_offsets)(struct tegra_mc *mc, struct tegra264_mc_fault *fault);
|
||||
};
|
||||
|
||||
/*
|
||||
* Description of a single HUB error type. addr_reg is zero for error types
|
||||
* that don't latch a fault address.
|
||||
*/
|
||||
struct tegra264_hub_error_handler {
|
||||
u32 addr_hi_reg;
|
||||
u32 addr_reg;
|
||||
u32 mask;
|
||||
u32 status_reg;
|
||||
};
|
||||
|
||||
/*
|
||||
* MC Client entries are sorted in the increasing order of the
|
||||
* override and security register offsets.
|
||||
@@ -717,11 +758,18 @@ static const char *const tegra264_rt_error_names[16] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* MC instance aperture mapping for hubc registers
|
||||
* On Tegra264 the memory controller error interrupts are distributed across
|
||||
* several HUB/HUBC apertures. Each aperture is accessed like a broadcast
|
||||
* channel through mc_ch_readl()/mc_ch_writel() using its fixed index.
|
||||
*/
|
||||
static const int mc_hubc_aperture_number[5] = {
|
||||
7, 8, 9, 10, 11
|
||||
};
|
||||
#define TEGRA264_MC_APERTURE_DISP 7
|
||||
#define TEGRA264_MC_APERTURE_SYSTEM 8
|
||||
#define TEGRA264_MC_APERTURE_VISION 9
|
||||
#define TEGRA264_MC_APERTURE_UPHY 10
|
||||
#define TEGRA264_MC_APERTURE_TOP 11
|
||||
|
||||
/* Tegra264 splits the MCF common interrupt status across five slices. */
|
||||
#define TEGRA264_MC_NUM_SLICES 5
|
||||
|
||||
/*
|
||||
* tegra264_mc_icc_set() - Pass MC client info to the BPMP-FW
|
||||
@@ -807,115 +855,149 @@ static int tegra264_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_emem(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_status;
|
||||
fault->addr_reg = mc->soc->regs->err_add;
|
||||
fault->addr_hi_reg = mc->soc->regs->err_add_hi;
|
||||
fault->type_mask = mc->soc->mc_err_status_type_mask;
|
||||
fault->type_shift = MC_ERR_STATUS_TYPE_SHIFT;
|
||||
fault->type_names = tegra264_mc_error_names;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_vpr(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_vpr_status;
|
||||
fault->addr_reg = mc->soc->regs->err_vpr_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_sec(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_sec_status;
|
||||
fault->addr_reg = mc->soc->regs->err_sec_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_mts(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_mts_status;
|
||||
fault->addr_reg = mc->soc->regs->err_mts_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_gsc(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_gen_co_status;
|
||||
fault->status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0;
|
||||
fault->addr_reg = mc->soc->regs->err_gen_co_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK;
|
||||
}
|
||||
|
||||
static void tegra264_mc_fault_route(struct tegra_mc *mc, struct tegra264_mc_fault *fault)
|
||||
{
|
||||
fault->status_reg = mc->soc->regs->err_route_status;
|
||||
fault->addr_reg = mc->soc->regs->err_route_add;
|
||||
fault->addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT;
|
||||
fault->addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
fault->rw_bit = MC_ERR_ROUTE_SANITY_RW;
|
||||
fault->sec_bit = MC_ERR_ROUTE_SANITY_SEC;
|
||||
fault->type_mask = MC_ERR_STATUS_RT_TYPE_MASK;
|
||||
fault->type_shift = MC_ERR_STATUS_RT_TYPE_SHIFT;
|
||||
fault->type_names = tegra264_rt_error_names;
|
||||
}
|
||||
|
||||
static const struct tegra264_mc_error_handler tegra264_mc_error_handlers[] = {
|
||||
{ MC_INT_DECERR_EMEM, tegra264_mc_fault_emem },
|
||||
{ MC_INT_SECURITY_VIOLATION, tegra264_mc_fault_emem },
|
||||
{ MC_INT_DECERR_VPR, tegra264_mc_fault_vpr },
|
||||
{ MC_INT_SECERR_SEC, tegra264_mc_fault_sec },
|
||||
{ MC_INT_DECERR_MTS, tegra264_mc_fault_mts },
|
||||
{ MC_INT_DECERR_GENERALIZED_CARVEOUT, tegra264_mc_fault_gsc },
|
||||
{ MC_INT_DECERR_ROUTE_SANITY, tegra264_mc_fault_route },
|
||||
{ MC_INT_DECERR_ROUTE_SANITY_GIC_MSI, tegra264_mc_fault_route },
|
||||
};
|
||||
|
||||
static void tegra264_mc_report_fault(struct tegra_mc *mc, u32 channel,
|
||||
unsigned int interrupt,
|
||||
const struct tegra264_mc_fault *fault)
|
||||
{
|
||||
const char *client = "unknown", *desc = "NA";
|
||||
u32 value, client_id, status1 = 0;
|
||||
phys_addr_t addr = 0;
|
||||
unsigned int i;
|
||||
u8 type;
|
||||
|
||||
value = mc_ch_readl(mc, channel, fault->status_reg);
|
||||
|
||||
if (fault->addr_hi_reg) {
|
||||
addr = mc_ch_readl(mc, channel, fault->addr_hi_reg);
|
||||
} else if (fault->status1_reg) {
|
||||
status1 = mc_ch_readl(mc, channel, fault->status1_reg);
|
||||
addr = (status1 >> fault->addr_hi_shift) & fault->addr_hi_mask;
|
||||
} else {
|
||||
addr = (value >> fault->addr_hi_shift) & fault->addr_hi_mask;
|
||||
}
|
||||
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, channel, fault->addr_reg);
|
||||
|
||||
client_id = value & mc->soc->client_id_mask;
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == client_id) {
|
||||
client = mc->soc->clients[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fault->type_names) {
|
||||
type = (value & fault->type_mask) >> fault->type_shift;
|
||||
desc = fault->type_names[type];
|
||||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n",
|
||||
client, value & fault->sec_bit ? "secure" : "non-secure",
|
||||
value & fault->rw_bit ? "write" : "read", &addr,
|
||||
tegra_mc_status_names[interrupt] ?: "unknown", desc);
|
||||
|
||||
if (fault->status1_reg)
|
||||
dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n",
|
||||
(status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT) &
|
||||
ERR_GENERALIZED_APERTURE_ID_MASK,
|
||||
(status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT) &
|
||||
ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK);
|
||||
}
|
||||
|
||||
static void mcf_log_fault(struct tegra_mc *mc, u32 channel, unsigned long mcf_ch_intstatus)
|
||||
{
|
||||
unsigned int bit;
|
||||
unsigned int interrupt;
|
||||
|
||||
for_each_set_bit(bit, &mcf_ch_intstatus, 32) {
|
||||
const char *client = "unknown", *desc = "NA";
|
||||
u32 status_reg, status1_reg = 0, addr_reg, addr_hi_reg = 0, err_type_mask = 0;
|
||||
u32 value, client_id, i, addr_hi_shift = 0, addr_hi_mask = 0, status1;
|
||||
u32 mc_rw_bit = MC_ERR_STATUS_RW, mc_sec_bit = MC_ERR_STATUS_SECURITY;
|
||||
phys_addr_t addr = 0;
|
||||
u8 type;
|
||||
for_each_set_bit(interrupt, &mcf_ch_intstatus, 32) {
|
||||
const struct tegra264_mc_error_handler *handler = NULL;
|
||||
struct tegra264_mc_fault fault = {
|
||||
.rw_bit = MC_ERR_STATUS_RW,
|
||||
.sec_bit = MC_ERR_STATUS_SECURITY,
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
switch (BIT(bit)) {
|
||||
case MC_INT_DECERR_EMEM:
|
||||
case MC_INT_SECURITY_VIOLATION:
|
||||
status_reg = mc->soc->regs->err_status;
|
||||
addr_reg = mc->soc->regs->err_add;
|
||||
addr_hi_reg = mc->soc->regs->err_add_hi;
|
||||
err_type_mask = mc->soc->mc_err_status_type_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_VPR:
|
||||
status_reg = mc->soc->regs->err_vpr_status;
|
||||
addr_reg = mc->soc->regs->err_vpr_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_SECERR_SEC:
|
||||
status_reg = mc->soc->regs->err_sec_status;
|
||||
addr_reg = mc->soc->regs->err_sec_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_MTS:
|
||||
status_reg = mc->soc->regs->err_mts_status;
|
||||
addr_reg = mc->soc->regs->err_mts_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_GENERALIZED_CARVEOUT:
|
||||
status_reg = mc->soc->regs->err_gen_co_status;
|
||||
status1_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS_1_0;
|
||||
addr_reg = mc->soc->regs->err_gen_co_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_GSC_ADR_HI_SHIFT;
|
||||
addr_hi_mask = MC_ERR_STATUS_GSC_ADR_HI_MASK;
|
||||
break;
|
||||
|
||||
case MC_INT_DECERR_ROUTE_SANITY:
|
||||
case MC_INT_DECERR_ROUTE_SANITY_GIC_MSI:
|
||||
status_reg = mc->soc->regs->err_route_status;
|
||||
addr_reg = mc->soc->regs->err_route_add;
|
||||
addr_hi_shift = MC_ERR_STATUS_RT_ADR_HI_SHIFT;
|
||||
addr_hi_mask = mc->soc->mc_addr_hi_mask;
|
||||
mc_sec_bit = MC_ERR_ROUTE_SANITY_SEC;
|
||||
mc_rw_bit = MC_ERR_ROUTE_SANITY_RW;
|
||||
err_type_mask = MC_ERR_STATUS_RT_TYPE_MASK;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, channel, status_reg);
|
||||
if (addr_hi_reg) {
|
||||
addr = mc_ch_readl(mc, channel, addr_hi_reg);
|
||||
} else {
|
||||
if (!status1_reg) {
|
||||
addr = ((value >> addr_hi_shift) & addr_hi_mask);
|
||||
} else {
|
||||
status1 = mc_ch_readl(mc, channel, status1_reg);
|
||||
addr = ((status1 >> addr_hi_shift) & addr_hi_mask);
|
||||
}
|
||||
}
|
||||
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, channel, addr_reg);
|
||||
|
||||
client_id = value & mc->soc->client_id_mask;
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == client_id) {
|
||||
client = mc->soc->clients[i].name;
|
||||
for (i = 0; i < ARRAY_SIZE(tegra264_mc_error_handlers); i++) {
|
||||
if (tegra264_mc_error_handlers[i].mask == BIT(interrupt)) {
|
||||
handler = &tegra264_mc_error_handlers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err_type_mask == MC_ERR_STATUS_RT_TYPE_MASK) {
|
||||
type = (value & err_type_mask) >>
|
||||
MC_ERR_STATUS_RT_TYPE_SHIFT;
|
||||
desc = tegra264_rt_error_names[type];
|
||||
} else if (err_type_mask) {
|
||||
type = (value & err_type_mask) >>
|
||||
MC_ERR_STATUS_TYPE_SHIFT;
|
||||
desc = tegra264_mc_error_names[type];
|
||||
if (!handler) {
|
||||
dev_err_ratelimited(mc->dev, "Incorrect MC interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: %s %s @%pa: %s (%s)\n",
|
||||
client, value & mc_sec_bit ? "secure" : "non-secure",
|
||||
value & mc_rw_bit ? "write" : "read", &addr,
|
||||
tegra_mc_status_names[bit] ?: "unknown", desc);
|
||||
if (status1_reg)
|
||||
dev_err_ratelimited(mc->dev, "gsc_apr_id=%u gsc_co_apr_id=%u\n",
|
||||
((status1 >> ERR_GENERALIZED_APERTURE_ID_SHIFT)
|
||||
& ERR_GENERALIZED_APERTURE_ID_MASK),
|
||||
((status1 >> ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT)
|
||||
& ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK));
|
||||
handler->get_offsets(mc, &fault);
|
||||
tegra264_mc_report_fault(mc, channel, interrupt, &fault);
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
@@ -937,7 +1019,7 @@ static irqreturn_t handle_mcf_irq(int irq, void *data)
|
||||
|
||||
for_each_set_bit(slice, &common_intstat, 32) {
|
||||
/* Find out the slice number on which interrupt occurred */
|
||||
if (slice > 4) {
|
||||
if (slice >= TEGRA264_MC_NUM_SLICES) {
|
||||
dev_err(mc->dev, "Slice index out of bounds: %u\n", slice);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
@@ -950,53 +1032,69 @@ static irqreturn_t handle_mcf_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct tegra264_hub_error_handler tegra264_hub_error_handlers[] = {
|
||||
{
|
||||
.mask = MSS_HUB_COALESCER_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_COALESCE_ERR_STATUS_0,
|
||||
.addr_reg = MSS_HUB_COALESCE_ERR_ADR_0,
|
||||
.addr_hi_reg = MSS_HUB_COALESCE_ERR_ADR_HI_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK,
|
||||
.status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_MSI_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_MSI_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_POISON_RSP_INTMASK,
|
||||
.status_reg = MSS_HUB_POISON_RSP_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0,
|
||||
},
|
||||
{
|
||||
.mask = MSS_HUB_RESERVED_PA_ERR_INTMASK,
|
||||
.status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0,
|
||||
},
|
||||
};
|
||||
|
||||
static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intstat)
|
||||
{
|
||||
unsigned int bit;
|
||||
unsigned int interrupt;
|
||||
|
||||
for_each_set_bit(bit, &hub_intstat, 32) {
|
||||
for_each_set_bit(interrupt, &hub_intstat, 32) {
|
||||
const struct tegra264_hub_error_handler *handler = NULL;
|
||||
const char *client = "unknown";
|
||||
u32 client_id, status_reg, value, i;
|
||||
u32 client_id, value;
|
||||
phys_addr_t addr = 0;
|
||||
unsigned int i;
|
||||
|
||||
switch (BIT(bit)) {
|
||||
case MSS_HUB_COALESCER_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_COALESCE_ERR_STATUS_0;
|
||||
addr = mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_HI_0);
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, hub, MSS_HUB_COALESCE_ERR_ADR_0);
|
||||
break;
|
||||
for (i = 0; i < ARRAY_SIZE(tegra264_hub_error_handlers); i++) {
|
||||
if (tegra264_hub_error_handlers[i].mask == BIT(interrupt)) {
|
||||
handler = &tegra264_hub_error_handlers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case MSS_HUB_SMMU_BYPASS_ALLOW_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_SMMU_BYPASS_ALLOW_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_ILLEGAL_TBUGRP_ID_INTMASK:
|
||||
status_reg = MSS_HUB_ILLEGAL_TBUGRP_ID_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_MSI_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_MSI_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_POISON_RSP_INTMASK:
|
||||
status_reg = MSS_HUB_POISON_RSP_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_RESTRICTED_ACCESS_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_RESTRICTED_ACCESS_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
case MSS_HUB_RESERVED_PA_ERR_INTMASK:
|
||||
status_reg = MSS_HUB_RESERVED_PA_ERR_STATUS_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!handler) {
|
||||
dev_err_ratelimited(mc->dev, "Incorrect HUB interrupt mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, hub, status_reg);
|
||||
if (handler->addr_reg) {
|
||||
addr = mc_ch_readl(mc, hub, handler->addr_hi_reg);
|
||||
addr <<= 32;
|
||||
addr |= mc_ch_readl(mc, hub, handler->addr_reg);
|
||||
}
|
||||
|
||||
value = mc_ch_readl(mc, hub, handler->status_reg);
|
||||
|
||||
client_id = value & mc->soc->client_id_mask;
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
@@ -1007,8 +1105,8 @@ static void hub_log_fault(struct tegra_mc *mc, u32 hub, unsigned long hub_intsta
|
||||
}
|
||||
|
||||
dev_err_ratelimited(mc->dev, "%s: @%pa: %s status: 0x%x\n",
|
||||
client, &addr, tegra264_hub_error_names[bit] ?: "unknown",
|
||||
value);
|
||||
client, &addr,
|
||||
tegra264_hub_error_names[interrupt] ?: "unknown", value);
|
||||
}
|
||||
|
||||
/* clear interrupts */
|
||||
@@ -1057,27 +1155,27 @@ static irqreturn_t handle_hub_irq(int irq, void *data, int mc_hubc_aperture_numb
|
||||
|
||||
static irqreturn_t handle_disp_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[0]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_DISP);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_system_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[1]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_SYSTEM);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_vision_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[2]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_VISION);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_uphy_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[3]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_UPHY);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_top_hub_irq(int irq, void *data)
|
||||
{
|
||||
return handle_hub_irq(irq, data, mc_hubc_aperture_number[4]);
|
||||
return handle_hub_irq(irq, data, TEGRA264_MC_APERTURE_TOP);
|
||||
}
|
||||
|
||||
static irqreturn_t handle_generic_irq(struct tegra_mc *mc, unsigned long intstat_reg)
|
||||
|
||||
@@ -403,6 +403,7 @@ static const struct of_device_id of_omnia_mcu_match[] = {
|
||||
{ .compatible = "cznic,turris-omnia-mcu" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_omnia_mcu_match);
|
||||
|
||||
static struct i2c_driver omnia_mcu_driver = {
|
||||
.probe = omnia_mcu_probe,
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <linux/bug.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/devm-helpers.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
@@ -841,6 +840,18 @@ static void button_release_emul_fn(struct work_struct *work)
|
||||
generic_handle_irq_safe(mcu->client->irq);
|
||||
}
|
||||
|
||||
static void omnia_disable_button_release_work(void *data)
|
||||
{
|
||||
struct delayed_work *work = data;
|
||||
|
||||
/*
|
||||
* The IRQ thread may requeue this work while the IRQ remains active.
|
||||
* Disable and drain it before releasing the IRQ action and the MCU
|
||||
* state used by the worker.
|
||||
*/
|
||||
disable_delayed_work_sync(work);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_int_from_sts(unsigned long *rising, unsigned long *falling,
|
||||
unsigned long rising_sts, unsigned long falling_sts,
|
||||
@@ -1082,21 +1093,9 @@ int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
|
||||
return dev_err_probe(dev, err, "Cannot request IRQ\n");
|
||||
|
||||
if (!new_api) {
|
||||
/*
|
||||
* The button_release_emul_work has to be initialized before the
|
||||
* thread is requested, and on driver remove it needs to be
|
||||
* canceled before the thread is freed. Therefore we can't use
|
||||
* devm_delayed_work_autocancel() directly, because the order
|
||||
* devm_delayed_work_autocancel();
|
||||
* devm_request_threaded_irq();
|
||||
* would cause improper release order:
|
||||
* free_irq();
|
||||
* cancel_delayed_work_sync();
|
||||
* Instead we first initialize the work above, and only now
|
||||
* after IRQ is requested we add the work devm action.
|
||||
*/
|
||||
err = devm_add_action(dev, devm_delayed_work_drop,
|
||||
&mcu->button_release_emul_work);
|
||||
err = devm_add_action_or_reset(dev,
|
||||
omnia_disable_button_release_work,
|
||||
&mcu->button_release_emul_work);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ source "drivers/soc/rockchip/Kconfig"
|
||||
source "drivers/soc/samsung/Kconfig"
|
||||
source "drivers/soc/sophgo/Kconfig"
|
||||
source "drivers/soc/st/Kconfig"
|
||||
source "drivers/soc/starfive/Kconfig"
|
||||
source "drivers/soc/sunxi/Kconfig"
|
||||
source "drivers/soc/tegra/Kconfig"
|
||||
source "drivers/soc/ti/Kconfig"
|
||||
|
||||
@@ -31,6 +31,7 @@ obj-y += rockchip/
|
||||
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
|
||||
obj-y += sophgo/
|
||||
obj-y += st/
|
||||
obj-y += starfive/
|
||||
obj-y += sunxi/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-y += ti/
|
||||
|
||||
@@ -20,7 +20,7 @@ static DEFINE_MUTEX(measure_lock);
|
||||
#define MSR_CONT BIT(17) /* continuous measurement */
|
||||
#define MSR_INTR BIT(18) /* interrupts */
|
||||
#define MSR_RUN BIT(19)
|
||||
#define MSR_CLK_SRC GENMASK(26, 20)
|
||||
#define MSR_CLK_SRC GENMASK(27, 20)
|
||||
#define MSR_BUSY BIT(31)
|
||||
|
||||
#define MSR_VAL_MASK GENMASK(15, 0)
|
||||
@@ -55,7 +55,7 @@ struct meson_msr {
|
||||
};
|
||||
|
||||
#define CLK_MSR_ID(__id, __name) \
|
||||
[__id] = {.id = __id, .name = __name,}
|
||||
{.id = __id, .name = __name,}
|
||||
|
||||
static const struct meson_msr_id clk_msr_m8[] = {
|
||||
CLK_MSR_ID(0, "ring_osc_out_ee0"),
|
||||
@@ -1041,6 +1041,843 @@ static const struct meson_msr_id clk_msr_t7[] = {
|
||||
CLK_MSR_ID(222, "enc0")
|
||||
};
|
||||
|
||||
static const struct meson_msr_id clk_msr_a4[] = {
|
||||
CLK_MSR_ID(0, "sys_clk"),
|
||||
CLK_MSR_ID(1, "axi_clk"),
|
||||
CLK_MSR_ID(2, "rtc_clk"),
|
||||
CLK_MSR_ID(3, "p22_usb2_ckout"),
|
||||
CLK_MSR_ID(4, "p21_usb2_ckout"),
|
||||
CLK_MSR_ID(5, "p20_usb2_ckout"),
|
||||
CLK_MSR_ID(6, "cpu_clk_div16"),
|
||||
CLK_MSR_ID(8, "eth_mpll_test"),
|
||||
CLK_MSR_ID(10, "fclk_div5"),
|
||||
CLK_MSR_ID(15, "fclk_50m"),
|
||||
CLK_MSR_ID(16, "sys_oscin32k_i"),
|
||||
CLK_MSR_ID(17, "rtc_pll"),
|
||||
CLK_MSR_ID(19, "hifi_pll"),
|
||||
CLK_MSR_ID(20, "gp0_pll"),
|
||||
CLK_MSR_ID(21, "gp1_pll"),
|
||||
CLK_MSR_ID(22, "eth_mppll_50m_ckout"),
|
||||
CLK_MSR_ID(23, "sys_pll_div16"),
|
||||
CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
|
||||
CLK_MSR_ID(27, "rtc_sec_pulse_out"),
|
||||
CLK_MSR_ID(28, "rtc_osc_clk_out"),
|
||||
CLK_MSR_ID(30, "mod_eth_phy_ref_clk"),
|
||||
CLK_MSR_ID(31, "mod_eth_tx_clk"),
|
||||
CLK_MSR_ID(32, "eth_125m"),
|
||||
CLK_MSR_ID(33, "eth_rmii"),
|
||||
CLK_MSR_ID(34, "co_clkin_to_mac"),
|
||||
CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"),
|
||||
CLK_MSR_ID(36, "co_rx_clk"),
|
||||
CLK_MSR_ID(37, "co_tx_clk"),
|
||||
CLK_MSR_ID(38, "eth_phy_rxclk"),
|
||||
CLK_MSR_ID(39, "eth_phy_plltxclk"),
|
||||
CLK_MSR_ID(40, "ephy_test_clk"),
|
||||
CLK_MSR_ID(41, "audio_core"),
|
||||
CLK_MSR_ID(51, "cts_vout_venc_clk_ph"),
|
||||
CLK_MSR_ID(52, "cts_vout_venc_clk"),
|
||||
CLK_MSR_ID(106, "deskew_pll_test_clk"),
|
||||
CLK_MSR_ID(111, "sar_adc"),
|
||||
CLK_MSR_ID(112, "ts"),
|
||||
CLK_MSR_ID(113, "sd_emmc_c"),
|
||||
CLK_MSR_ID(115, "sd_emmc_a"),
|
||||
CLK_MSR_ID(116, "gpio_msr_clk"),
|
||||
CLK_MSR_ID(117, "spicc1"),
|
||||
CLK_MSR_ID(118, "spicc0"),
|
||||
CLK_MSR_ID(119, "o_mst_sclk_vad"),
|
||||
CLK_MSR_ID(120, "o_mst_mclk_vad"),
|
||||
CLK_MSR_ID(121, "o_pdm_sysclk"),
|
||||
CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"),
|
||||
CLK_MSR_ID(123, "o_vad_clk"),
|
||||
CLK_MSR_ID(124, "earcrx_dmac_clk"),
|
||||
CLK_MSR_ID(125, "earcrx_cmdc_clk"),
|
||||
CLK_MSR_ID(126, "earctx_dmac_clk"),
|
||||
CLK_MSR_ID(127, "earctx_cmdc_clk"),
|
||||
CLK_MSR_ID(128, "tohdmitx_bclk"),
|
||||
CLK_MSR_ID(129, "tohdmitx_mclk"),
|
||||
CLK_MSR_ID(130, "tohdmitx_spdif_clk"),
|
||||
CLK_MSR_ID(131, "toacodec_bclk"),
|
||||
CLK_MSR_ID(132, "toacodec_mclk"),
|
||||
CLK_MSR_ID(133, "spdifout_b_mst_clk"),
|
||||
CLK_MSR_ID(134, "spdifout_mst_clk"),
|
||||
CLK_MSR_ID(135, "spdifin_mst_clk"),
|
||||
CLK_MSR_ID(136, "audio_mclk"),
|
||||
CLK_MSR_ID(137, "vad_clk"),
|
||||
CLK_MSR_ID(138, "tdmout_d_sclk"),
|
||||
CLK_MSR_ID(139, "tdmout_c_sclk"),
|
||||
CLK_MSR_ID(140, "tdmout_b_sclk"),
|
||||
CLK_MSR_ID(141, "tdmout_a_sclk"),
|
||||
CLK_MSR_ID(142, "tdminb_lb_sclk"),
|
||||
CLK_MSR_ID(143, "tdmin_lb_sclk"),
|
||||
CLK_MSR_ID(144, "tdmin_d_sclk"),
|
||||
CLK_MSR_ID(145, "tdmin_c_sclk"),
|
||||
CLK_MSR_ID(146, "tdmin_b_sclk"),
|
||||
CLK_MSR_ID(147, "tdmin_a_sclk"),
|
||||
CLK_MSR_ID(148, "resampleb_clk"),
|
||||
CLK_MSR_ID(149, "resamplea_clk"),
|
||||
CLK_MSR_ID(150, "pdmb_sysclk"),
|
||||
CLK_MSR_ID(151, "pdmb_dclk"),
|
||||
CLK_MSR_ID(152, "pdm_sysclk"),
|
||||
CLK_MSR_ID(153, "pdm_dclk"),
|
||||
CLK_MSR_ID(154, "alockerb_out_clk"),
|
||||
CLK_MSR_ID(155, "alockerb_in_clk"),
|
||||
CLK_MSR_ID(156, "alocker_out_clk"),
|
||||
CLK_MSR_ID(157, "alocker_in_clk"),
|
||||
CLK_MSR_ID(158, "audio_mst_clk[34]"),
|
||||
CLK_MSR_ID(159, "audio_mst_clk[35]"),
|
||||
CLK_MSR_ID(162, "pwm_h"),
|
||||
CLK_MSR_ID(163, "pwm_g"),
|
||||
CLK_MSR_ID(164, "pwm_f"),
|
||||
CLK_MSR_ID(165, "pwm_e"),
|
||||
CLK_MSR_ID(166, "pwm_d"),
|
||||
CLK_MSR_ID(167, "pwm_c"),
|
||||
CLK_MSR_ID(168, "pwm_b"),
|
||||
CLK_MSR_ID(169, "pwm_a"),
|
||||
CLK_MSR_ID(170, "AU_ADC_CLK_G128X"),
|
||||
CLK_MSR_ID(171, "AU_ADC_CLK_TO_GPIO"),
|
||||
CLK_MSR_ID(172, "AU_DAC1_CLK_G128X"),
|
||||
CLK_MSR_ID(173, "AU_DAC1_CLK_TO_GPIO"),
|
||||
CLK_MSR_ID(176, "rng_ring_osc_clk[0]"),
|
||||
CLK_MSR_ID(177, "rng_ring_osc_clk[1]"),
|
||||
CLK_MSR_ID(178, "rng_ring_osc_clk[2]"),
|
||||
CLK_MSR_ID(179, "rng_ring_osc_clk[3]"),
|
||||
CLK_MSR_ID(180, "sys_cpu_osc_ring[0](ULVT16)"),
|
||||
CLK_MSR_ID(181, "sys_cpu_osc_ring[1](ULVT20)"),
|
||||
CLK_MSR_ID(182, "sys_cpu_osc_ring[2](ULVT16)"),
|
||||
CLK_MSR_ID(183, "sys_cpu_osc_ring[3](ULVT16)"),
|
||||
CLK_MSR_ID(184, "sys_cpu_osc_ring[4](ULVT16)"),
|
||||
CLK_MSR_ID(185, "am_ring_osc_clk_out_top[0](SVT16)"),
|
||||
CLK_MSR_ID(186, "am_ring_osc_clk_out_top[1](LVT20)"),
|
||||
};
|
||||
|
||||
static const struct meson_msr_id clk_msr_a5[] = {
|
||||
CLK_MSR_ID(0, "sys_clk"),
|
||||
CLK_MSR_ID(1, "axi_clk"),
|
||||
CLK_MSR_ID(2, "rtc_clk"),
|
||||
CLK_MSR_ID(3, "dspa"),
|
||||
CLK_MSR_ID(6, "cpu_clk_div16"),
|
||||
CLK_MSR_ID(10, "fclk_div5"),
|
||||
CLK_MSR_ID(11, "mpll0"),
|
||||
CLK_MSR_ID(12, "mpll1"),
|
||||
CLK_MSR_ID(13, "mpll2"),
|
||||
CLK_MSR_ID(14, "mpll3"),
|
||||
CLK_MSR_ID(15, "fclk_50m"),
|
||||
CLK_MSR_ID(16, "sys_oscin32k_i"),
|
||||
CLK_MSR_ID(17, "rtc_pll"),
|
||||
CLK_MSR_ID(18, "mpll_clk_test_out"),
|
||||
CLK_MSR_ID(19, "hifi_pll"),
|
||||
CLK_MSR_ID(20, "gp0_pll"),
|
||||
CLK_MSR_ID(21, "gp1_pll"),
|
||||
CLK_MSR_ID(23, "sys_pll_div16"),
|
||||
CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
|
||||
CLK_MSR_ID(25, "nna_axi"),
|
||||
CLK_MSR_ID(26, "nna_core"),
|
||||
CLK_MSR_ID(27, "rtc_sec_pulse_out"),
|
||||
CLK_MSR_ID(28, "rtc_osc_clk_out"),
|
||||
CLK_MSR_ID(30, "mod_eth_phy_ref_clk"),
|
||||
CLK_MSR_ID(31, "mod_eth_tx_clk"),
|
||||
CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"),
|
||||
CLK_MSR_ID(79, "rama_clk"),
|
||||
CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
|
||||
CLK_MSR_ID(111, "sar_adc"),
|
||||
CLK_MSR_ID(112, "ts"),
|
||||
CLK_MSR_ID(113, "sd_emmc_c"),
|
||||
CLK_MSR_ID(115, "sd_emmc_a"),
|
||||
CLK_MSR_ID(116, "gpio_msr_clk"),
|
||||
CLK_MSR_ID(117, "spicc1"),
|
||||
CLK_MSR_ID(118, "spicc0"),
|
||||
CLK_MSR_ID(119, "o_mst_sclk_vad"),
|
||||
CLK_MSR_ID(120, "o_mst_mclk_vad"),
|
||||
CLK_MSR_ID(121, "o_pdm_sysclk"),
|
||||
CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"),
|
||||
CLK_MSR_ID(123, "o_vad_clk"),
|
||||
CLK_MSR_ID(124, "earcrx_dmac_clk"),
|
||||
CLK_MSR_ID(125, "earcrx_cmdc_clk"),
|
||||
CLK_MSR_ID(126, "earctx_dmac_clk"),
|
||||
CLK_MSR_ID(127, "earctx_cmdc_clk"),
|
||||
CLK_MSR_ID(128, "tohdmitx_bclk"),
|
||||
CLK_MSR_ID(129, "tohdmitx_mclk"),
|
||||
CLK_MSR_ID(130, "tohdmitx_spdif_clk"),
|
||||
CLK_MSR_ID(131, "toacodec_bclk"),
|
||||
CLK_MSR_ID(132, "toacodec_mclk"),
|
||||
CLK_MSR_ID(133, "spdifout_b_mst_clk"),
|
||||
CLK_MSR_ID(134, "spdifout_mst_clk"),
|
||||
CLK_MSR_ID(135, "spdifin_mst_clk"),
|
||||
CLK_MSR_ID(136, "audio_mclk"),
|
||||
CLK_MSR_ID(137, "vad_clk"),
|
||||
CLK_MSR_ID(138, "tdmout_d_sclk"),
|
||||
CLK_MSR_ID(139, "tdmout_c_sclk"),
|
||||
CLK_MSR_ID(140, "tdmout_b_sclk"),
|
||||
CLK_MSR_ID(141, "tdmout_a_sclk"),
|
||||
CLK_MSR_ID(142, "tdminb_lb_sclk"),
|
||||
CLK_MSR_ID(143, "tdmin_lb_sclk"),
|
||||
CLK_MSR_ID(144, "tdmin_d_sclk"),
|
||||
CLK_MSR_ID(145, "tdmin_c_sclk"),
|
||||
CLK_MSR_ID(146, "tdmin_b_sclk"),
|
||||
CLK_MSR_ID(147, "tdmin_a_sclk"),
|
||||
CLK_MSR_ID(148, "resampleb_clk"),
|
||||
CLK_MSR_ID(149, "resamplea_clk"),
|
||||
CLK_MSR_ID(150, "pdmb_sysclk"),
|
||||
CLK_MSR_ID(151, "pdmb_dclk"),
|
||||
CLK_MSR_ID(152, "pdm_sysclk"),
|
||||
CLK_MSR_ID(153, "pdm_dclk"),
|
||||
CLK_MSR_ID(154, "alockerb_out_clk"),
|
||||
CLK_MSR_ID(155, "alockerb_in_clk"),
|
||||
CLK_MSR_ID(156, "alocker_out_clk"),
|
||||
CLK_MSR_ID(157, "alocker_in_clk"),
|
||||
CLK_MSR_ID(158, "audio_mst_clk[34]"),
|
||||
CLK_MSR_ID(159, "audio_mst_clk[35]"),
|
||||
CLK_MSR_ID(162, "pwm_h"),
|
||||
CLK_MSR_ID(163, "pwm_g"),
|
||||
CLK_MSR_ID(164, "pwm_f"),
|
||||
CLK_MSR_ID(165, "pwm_e"),
|
||||
CLK_MSR_ID(166, "pwm_d"),
|
||||
CLK_MSR_ID(167, "pwm_c"),
|
||||
CLK_MSR_ID(168, "pwm_b"),
|
||||
CLK_MSR_ID(169, "pwm_a"),
|
||||
CLK_MSR_ID(176, "rng_ring_osc_clk[0]"),
|
||||
CLK_MSR_ID(177, "rng_ring_osc_clk[1]"),
|
||||
CLK_MSR_ID(178, "rng_ring_osc_clk[2]"),
|
||||
CLK_MSR_ID(179, "rng_ring_osc_clk[3]"),
|
||||
CLK_MSR_ID(180, "dmc_osc_ring(LVT16)"),
|
||||
CLK_MSR_ID(181, "dsp_osc_ring(SVT16)"),
|
||||
CLK_MSR_ID(182, "axi_srama_osc_ring(SVT16)"),
|
||||
CLK_MSR_ID(183, "nna_osc_ring[0](ULVT20)"),
|
||||
CLK_MSR_ID(184, "nna_osc_ring[1](LVT16)"),
|
||||
CLK_MSR_ID(185, "sys_cpu_osc_ring[0](ULVT16)"),
|
||||
CLK_MSR_ID(186, "sys_cpu_osc_ring[1](ULVT20)"),
|
||||
CLK_MSR_ID(187, "sys_cpu_osc_ring[2](ULVT16)"),
|
||||
CLK_MSR_ID(188, "sys_cpu_osc_ring[3](LVT16)"),
|
||||
CLK_MSR_ID(189, "axi_sramb_osc_ring(SVT16)"),
|
||||
};
|
||||
|
||||
static const struct meson_msr_id clk_msr_a9[] = {
|
||||
CLK_MSR_ID(0, "sys_clk"),
|
||||
CLK_MSR_ID(1, "axi_clk"),
|
||||
CLK_MSR_ID(2, "rtc_clk"),
|
||||
CLK_MSR_ID(3, "dspa"),
|
||||
CLK_MSR_ID(4, "mali_stack"),
|
||||
CLK_MSR_ID(5, "mali"),
|
||||
CLK_MSR_ID(6, "cpu_clk_div16"),
|
||||
CLK_MSR_ID(7, "a78_clk_div16"),
|
||||
CLK_MSR_ID(8, "dsu_clk_div16"),
|
||||
CLK_MSR_ID(9, "isp"),
|
||||
CLK_MSR_ID(10, "gp2_pll"),
|
||||
CLK_MSR_ID(11, "fclk_div5"),
|
||||
CLK_MSR_ID(12, "u2drd_usb2_ckout"),
|
||||
CLK_MSR_ID(13, "pre0_hdmirx_aud_pll_clk"),
|
||||
CLK_MSR_ID(14, "hrx20_pll_clk_test"),
|
||||
CLK_MSR_ID(15, "u2h_usb2_ckout"),
|
||||
CLK_MSR_ID(16, "fclk_50m"),
|
||||
CLK_MSR_ID(17, "u3drd_b_usb2_ckout"),
|
||||
CLK_MSR_ID(18, "gp1_pll"),
|
||||
CLK_MSR_ID(19, "hifi_pll"),
|
||||
CLK_MSR_ID(20, "gp0_pll"),
|
||||
CLK_MSR_ID(21, "hifi1_pll"),
|
||||
CLK_MSR_ID(22, "csi_phy"),
|
||||
CLK_MSR_ID(23, "sys_pll_div16"),
|
||||
CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
|
||||
CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"),
|
||||
CLK_MSR_ID(26, "ext_Tsin_B_CLK_IN"),
|
||||
CLK_MSR_ID(27, "u3p2pll1_0_clk_div16"),
|
||||
CLK_MSR_ID(28, "u3p2pll1_1_clk_div16"),
|
||||
CLK_MSR_ID(29, "upcrx0_cdrclk"),
|
||||
CLK_MSR_ID(30, "upcrx1_cdrclk"),
|
||||
CLK_MSR_ID(31, "hdmirx_aud_sck"),
|
||||
CLK_MSR_ID(32, "uptx0_clk_sync_b20"),
|
||||
CLK_MSR_ID(33, "uptx1_clk_sync_b20"),
|
||||
CLK_MSR_ID(34, "lp_pll_clk0"),
|
||||
CLK_MSR_ID(35, "lp_pll_clk1"),
|
||||
CLK_MSR_ID(36, "u3hsg_PCIE_PIPE_PCLK"),
|
||||
CLK_MSR_ID(37, "u3hsg_upcrx_cdrclk"),
|
||||
CLK_MSR_ID(38, "u3hsg_upctx_clk_sync_b20"),
|
||||
CLK_MSR_ID(39, "u3hsg_upcrxpll_clk_test"),
|
||||
CLK_MSR_ID(40, "hdmirx_acr_lclk"),
|
||||
CLK_MSR_ID(41, "i3c"),
|
||||
CLK_MSR_ID(42, "hdmirx_aud_pll"),
|
||||
CLK_MSR_ID(43, "hdmirx_acr_ref"),
|
||||
CLK_MSR_ID(44, "hdmirx_meter"),
|
||||
CLK_MSR_ID(45, "hdmirx_hdcp2x"),
|
||||
CLK_MSR_ID(46, "hdmirx_5m"),
|
||||
CLK_MSR_ID(47, "hdmirx_2m"),
|
||||
CLK_MSR_ID(48, "hdmirx_cfg"),
|
||||
CLK_MSR_ID(49, "hdmi_vx1_pix_clk"),
|
||||
CLK_MSR_ID(50, "vid_pll"),
|
||||
CLK_MSR_ID(51, "encoder0_if_clk"),
|
||||
CLK_MSR_ID(52, "encoder1"),
|
||||
CLK_MSR_ID(53, "encoder0"),
|
||||
CLK_MSR_ID(54, "vdac"),
|
||||
CLK_MSR_ID(55, "mali_aclkm"),
|
||||
CLK_MSR_ID(56, "vid1_pll"),
|
||||
CLK_MSR_ID(57, "lcd_an_ph2"),
|
||||
CLK_MSR_ID(58, "lcd_an_ph3"),
|
||||
CLK_MSR_ID(59, "hdmitx_pixel"),
|
||||
CLK_MSR_ID(60, "vdin_meas"),
|
||||
CLK_MSR_ID(61, "vpu"),
|
||||
CLK_MSR_ID(62, "vpu_clkb"),
|
||||
CLK_MSR_ID(63, "vpu_clkb_tmp"),
|
||||
CLK_MSR_ID(64, "u3p2_upcrxpll_fst_pll_clk"),
|
||||
CLK_MSR_ID(65, "vid_lock"),
|
||||
CLK_MSR_ID(66, "vapb"),
|
||||
CLK_MSR_ID(67, "ge2d"),
|
||||
CLK_MSR_ID(68, "cve"),
|
||||
CLK_MSR_ID(69, "vge"),
|
||||
CLK_MSR_ID(70, "dsi0_meas"),
|
||||
CLK_MSR_ID(71, "dsi1_meas"),
|
||||
CLK_MSR_ID(72, "mipi_csi_phy_clk_out[0]"),
|
||||
CLK_MSR_ID(73, "mipi_csi_phy_clk_out[1]"),
|
||||
CLK_MSR_ID(74, "mipi_csi_phy_clk_out[2]"),
|
||||
CLK_MSR_ID(75, "mipi_csi_phy_clk_out[3]"),
|
||||
CLK_MSR_ID(76, "hdmitx_tmds"),
|
||||
CLK_MSR_ID(77, "hdmitx_sys"),
|
||||
CLK_MSR_ID(78, "hdmitx_fe"),
|
||||
CLK_MSR_ID(80, "hdmitx_prif"),
|
||||
CLK_MSR_ID(81, "hdmitx_200m"),
|
||||
CLK_MSR_ID(82, "hdmitx_aud"),
|
||||
CLK_MSR_ID(83, "hdmitx1_pixel"),
|
||||
CLK_MSR_ID(84, "hdmitx1_fe"),
|
||||
CLK_MSR_ID(85, "gic"),
|
||||
CLK_MSR_ID(86, "lvds0_fifo_clk"),
|
||||
CLK_MSR_ID(87, "lvds1_fifo_clk"),
|
||||
CLK_MSR_ID(88, "htx_aes_clk"),
|
||||
CLK_MSR_ID(89, "amfc"),
|
||||
CLK_MSR_ID(90, "a_clk_sync_dig"),
|
||||
CLK_MSR_ID(91, "b_clk_sync_dig"),
|
||||
CLK_MSR_ID(92, "u3dp_upcrx_cdrclk"),
|
||||
CLK_MSR_ID(93, "u3dp_upctx_clk_sync_b20"),
|
||||
CLK_MSR_ID(94, "u3dp_upcrxpll_clk_test"),
|
||||
CLK_MSR_ID(95, "u3dp_upcrpll_fst_pll_clk"),
|
||||
CLK_MSR_ID(96, "u3dp_usb2_ckout"),
|
||||
CLK_MSR_ID(97, "hcodec"),
|
||||
CLK_MSR_ID(99, "hevcf"),
|
||||
CLK_MSR_ID(104, "spisg2"),
|
||||
CLK_MSR_ID(105, "spisg1"),
|
||||
CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
|
||||
CLK_MSR_ID(108, "cmpr"),
|
||||
CLK_MSR_ID(109, "dewarpa"),
|
||||
CLK_MSR_ID(110, "sc"),
|
||||
CLK_MSR_ID(111, "sar_adc"),
|
||||
CLK_MSR_ID(112, "glb"),
|
||||
CLK_MSR_ID(113, "sd_emmc_c"),
|
||||
CLK_MSR_ID(114, "sd_emmc_b"),
|
||||
CLK_MSR_ID(115, "sd_emmc_a"),
|
||||
CLK_MSR_ID(116, "gpio_msr_clk"),
|
||||
CLK_MSR_ID(117, "aux_clk_o"),
|
||||
CLK_MSR_ID(118, "spisg0"),
|
||||
CLK_MSR_ID(121, "ts"),
|
||||
CLK_MSR_ID(122, "usb_48m"),
|
||||
CLK_MSR_ID(123, "usb_250m"),
|
||||
CLK_MSR_ID(124, "eth_125m"),
|
||||
CLK_MSR_ID(125, "eth_rmii"),
|
||||
CLK_MSR_ID(126, "hrx20_tmds20_clk"),
|
||||
CLK_MSR_ID(127, "hrx20_cable_clk"),
|
||||
CLK_MSR_ID(128, "hdmirx_vid_clk"),
|
||||
CLK_MSR_ID(129, "hdmirx_aud_clk"),
|
||||
CLK_MSR_ID(130, "dptx_apb2"),
|
||||
CLK_MSR_ID(131, "dptx_aud"),
|
||||
CLK_MSR_ID(132, "audio_todptx_bclk"),
|
||||
CLK_MSR_ID(133, "audio_txhdmitx_bclk"),
|
||||
CLK_MSR_ID(134, "audio_txhdmitx_mclk"),
|
||||
CLK_MSR_ID(135, "audio_txhdmitx_spdif_clk"),
|
||||
CLK_MSR_ID(136, "mclk_0_pre"),
|
||||
CLK_MSR_ID(137, "mclk1_0_pre"),
|
||||
CLK_MSR_ID(138, "pixel0_pll_clkout"),
|
||||
CLK_MSR_ID(139, "pixel1_pll_clkout"),
|
||||
CLK_MSR_ID(140, "tcon_clk_out0"),
|
||||
CLK_MSR_ID(141, "tcon_clk_out1"),
|
||||
CLK_MSR_ID(142, "audio_todptx_spdif_clk"),
|
||||
CLK_MSR_ID(143, "audio_todptx_mclk"),
|
||||
CLK_MSR_ID(144, "dptx_lnk_clk"),
|
||||
CLK_MSR_ID(145, "edptx_lnk_clk_tx"),
|
||||
CLK_MSR_ID(146, "mod_audio_pdm_dclk_o_ao"),
|
||||
CLK_MSR_ID(147, "vid2_pll"),
|
||||
CLK_MSR_ID(151, "can1_filter"),
|
||||
CLK_MSR_ID(152, "can0_filter"),
|
||||
CLK_MSR_ID(153, "can1_pe"),
|
||||
CLK_MSR_ID(154, "can0_pe"),
|
||||
CLK_MSR_ID(155, "o_sed_clk"),
|
||||
CLK_MSR_ID(156, "pwm_n"),
|
||||
CLK_MSR_ID(157, "pwm_m"),
|
||||
CLK_MSR_ID(158, "pwm_l"),
|
||||
CLK_MSR_ID(159, "pwm_k"),
|
||||
CLK_MSR_ID(160, "pwm_j"),
|
||||
CLK_MSR_ID(161, "pwm_i"),
|
||||
CLK_MSR_ID(162, "pwm_h"),
|
||||
CLK_MSR_ID(170, "rng_ring_osc_clk[0]"),
|
||||
CLK_MSR_ID(171, "rng_ring_osc_clk[1]"),
|
||||
CLK_MSR_ID(172, "rng_ring_osc_clk[2]"),
|
||||
CLK_MSR_ID(173, "rng_ring_osc_clk[3]"),
|
||||
CLK_MSR_ID(174, "rng_ring_osc_clk[4]"),
|
||||
CLK_MSR_ID(175, "sys_cpu_osc_ring_clk[0]"),
|
||||
CLK_MSR_ID(176, "sys_cpu_osc_ring_clk[1]"),
|
||||
CLK_MSR_ID(177, "sys_cpu_osc_ring_clk[2]"),
|
||||
CLK_MSR_ID(178, "sys_cpu_osc_ring_clk[3]"),
|
||||
CLK_MSR_ID(179, "sys_cpu_osc_ring_clk[4]"),
|
||||
CLK_MSR_ID(180, "sys_cpu_osc_ring_clk[5]"),
|
||||
CLK_MSR_ID(181, "sys_cpu_osc_ring_clk[6]"),
|
||||
CLK_MSR_ID(182, "sys_cpu_osc_ring_clk[7]"),
|
||||
CLK_MSR_ID(183, "sys_cpu_osc_ring_clk[8]"),
|
||||
CLK_MSR_ID(184, "sys_cpu_osc_ring_clk[9]"),
|
||||
CLK_MSR_ID(185, "osc_ring_clk_gpu[0]"),
|
||||
CLK_MSR_ID(186, "osc_ring_clk_gpu[1]"),
|
||||
CLK_MSR_ID(187, "osc_ring_clk_vpu"),
|
||||
CLK_MSR_ID(188, "osc_ring_clk_dos[0]"),
|
||||
CLK_MSR_ID(189, "osc_ring_clk_dos[1]"),
|
||||
CLK_MSR_ID(190, "osc_ring_clk_vge"),
|
||||
CLK_MSR_ID(191, "osc_ring_clk_nna[0]"),
|
||||
CLK_MSR_ID(192, "osc_ring_clk_nna[1]"),
|
||||
CLK_MSR_ID(193, "osc_ring_clk_top[0]"),
|
||||
CLK_MSR_ID(194, "osc_ring_clk_top[1]"),
|
||||
CLK_MSR_ID(195, "nna"),
|
||||
CLK_MSR_ID(200, "pcie1_tl"),
|
||||
CLK_MSR_ID(201, "pcie0_tl"),
|
||||
CLK_MSR_ID(202, "pp"),
|
||||
CLK_MSR_ID(203, "pwm_a(ao)"),
|
||||
CLK_MSR_ID(204, "pwm_b(ao)"),
|
||||
CLK_MSR_ID(205, "pwm_c(ao)"),
|
||||
CLK_MSR_ID(206, "pwm_d(ao)"),
|
||||
CLK_MSR_ID(207, "pwm_e(ao)"),
|
||||
CLK_MSR_ID(208, "pwm_f(ao)"),
|
||||
CLK_MSR_ID(209, "pwm_g(ao)"),
|
||||
CLK_MSR_ID(210, "ao_cec"),
|
||||
CLK_MSR_ID(211, "sec_pulse_out"),
|
||||
CLK_MSR_ID(212, "osc_clk_out"),
|
||||
CLK_MSR_ID(213, "earcrx_pll_clk_out"),
|
||||
CLK_MSR_ID(215, "o_pd_sysclk"),
|
||||
CLK_MSR_ID(216, "o_earcrx_dmac_clk"),
|
||||
CLK_MSR_ID(217, "o_earcrx_cmdc_clk"),
|
||||
CLK_MSR_ID(218, "o_earctx_dmac_clk"),
|
||||
CLK_MSR_ID(219, "o_earctx_cmdc_clk"),
|
||||
CLK_MSR_ID(220, "o_earctx_ana_dmac_clk_a2d"),
|
||||
CLK_MSR_ID(221, "o_tohdmi_dp_tx_a_bclk"),
|
||||
CLK_MSR_ID(222, "o_tohdmi_dp_tx_a_mclk"),
|
||||
CLK_MSR_ID(223, "o_tohdmi_dp_tx_a_spdif_clk"),
|
||||
CLK_MSR_ID(224, "o_tohdmi_dp_tx_b_bclk"),
|
||||
CLK_MSR_ID(225, "o_tohdmi_dp_tx_b_mclk"),
|
||||
CLK_MSR_ID(226, "o_tohdmi_dp_tx_b_spdif_clk"),
|
||||
CLK_MSR_ID(227, "o_toacodec_dac_bclk"),
|
||||
CLK_MSR_ID(228, "o_toacodec_dac_mclk"),
|
||||
CLK_MSR_ID(229, "o_spdifout_b_mst_clk"),
|
||||
CLK_MSR_ID(230, "o_spdifout_mst_clk"),
|
||||
CLK_MSR_ID(231, "o_spdifin_mst_clk"),
|
||||
CLK_MSR_ID(232, "o_audio_mclk"),
|
||||
CLK_MSR_ID(233, "o_vad_clk"),
|
||||
CLK_MSR_ID(234, "o_tdmout_d_sclk"),
|
||||
CLK_MSR_ID(235, "o_tdmout_c_sclk"),
|
||||
CLK_MSR_ID(236, "o_tdmout_b_sclk"),
|
||||
CLK_MSR_ID(237, "o_tdmout_a_sclk"),
|
||||
CLK_MSR_ID(238, "o_tdminb_lb_sclk"),
|
||||
CLK_MSR_ID(239, "o_tdmin_lb_sclk"),
|
||||
CLK_MSR_ID(240, "o_tdmin_d_sclk"),
|
||||
CLK_MSR_ID(241, "o_tdmin_c_sclk"),
|
||||
CLK_MSR_ID(242, "o_tdmin_b_sclk"),
|
||||
CLK_MSR_ID(243, "o_tdmin_a_sclk"),
|
||||
CLK_MSR_ID(244, "o_resampleb_clk"),
|
||||
CLK_MSR_ID(245, "o_resamplea_clk"),
|
||||
CLK_MSR_ID(246, "o_pdmb_sysclk"),
|
||||
CLK_MSR_ID(247, "o_pdmb_dclk"),
|
||||
CLK_MSR_ID(248, "o_pdm_sysclk"),
|
||||
CLK_MSR_ID(249, "o_pdm_dclk"),
|
||||
CLK_MSR_ID(250, "c_alockerb_out_clk"),
|
||||
CLK_MSR_ID(251, "c_alockerb_in_clk"),
|
||||
CLK_MSR_ID(252, "c_alocker_out_clk"),
|
||||
CLK_MSR_ID(253, "c_alocker_in_clk"),
|
||||
CLK_MSR_ID(254, "o_resample_c_clk")
|
||||
};
|
||||
|
||||
static const struct meson_msr_id clk_msr_s6[] = {
|
||||
CLK_MSR_ID(0, "sys_clk"),
|
||||
CLK_MSR_ID(1, "axi_clk"),
|
||||
CLK_MSR_ID(2, "rtc_clk"),
|
||||
CLK_MSR_ID(3, "dspa"),
|
||||
CLK_MSR_ID(4, "mali_stack"),
|
||||
CLK_MSR_ID(5, "mali"),
|
||||
CLK_MSR_ID(6, "cpu_clk_div16"),
|
||||
CLK_MSR_ID(7, "mali_aclkm"),
|
||||
CLK_MSR_ID(8, "cecb"),
|
||||
CLK_MSR_ID(9, "gp2_pll"),
|
||||
CLK_MSR_ID(10, "fclk_div5"),
|
||||
CLK_MSR_ID(11, "p21_usb2_ckout"),
|
||||
CLK_MSR_ID(12, "p20_usb2_ckout"),
|
||||
CLK_MSR_ID(13, "eth_mpll_test"),
|
||||
CLK_MSR_ID(15, "fclk_50m"),
|
||||
CLK_MSR_ID(18, "gp1_pll"),
|
||||
CLK_MSR_ID(19, "hifi_pll"),
|
||||
CLK_MSR_ID(20, "gp0_pll"),
|
||||
CLK_MSR_ID(21, "hifi1_pll"),
|
||||
CLK_MSR_ID(22, "eth_mppll_50m_ckout"),
|
||||
CLK_MSR_ID(23, "sys_pll_div16"),
|
||||
CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
|
||||
CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"),
|
||||
CLK_MSR_ID(26, "ext_Tsin_B_CLK_IN"),
|
||||
CLK_MSR_ID(27, "mod_Tsin_C_CLK_IN"),
|
||||
CLK_MSR_ID(28, "mod_Tsin_D_CLK_IN"),
|
||||
CLK_MSR_ID(29, "dsi_pll_div_clk_out"),
|
||||
CLK_MSR_ID(30, "dsi_pll_clk"),
|
||||
CLK_MSR_ID(32, "eth_125m"),
|
||||
CLK_MSR_ID(33, "eth_rmii"),
|
||||
CLK_MSR_ID(34, "co_clkin_to_mac"),
|
||||
CLK_MSR_ID(36, "co_rx_clk"),
|
||||
CLK_MSR_ID(37, "co_tx_clk"),
|
||||
CLK_MSR_ID(38, "eth_phy_rxclk"),
|
||||
CLK_MSR_ID(39, "eth_phy_plltxclk"),
|
||||
CLK_MSR_ID(40, "ephy_test_clk"),
|
||||
CLK_MSR_ID(49, "hdmi_vx1_pix_clk"),
|
||||
CLK_MSR_ID(50, "vid_pll"),
|
||||
CLK_MSR_ID(51, "enci"),
|
||||
CLK_MSR_ID(52, "encp"),
|
||||
CLK_MSR_ID(53, "encl"),
|
||||
CLK_MSR_ID(54, "vdac"),
|
||||
CLK_MSR_ID(55, "cdac"),
|
||||
CLK_MSR_ID(57, "lcd_an_clk_ph2"),
|
||||
CLK_MSR_ID(58, "lcd_an_clk_ph3"),
|
||||
CLK_MSR_ID(59, "hdmitx_pixel"),
|
||||
CLK_MSR_ID(60, "vdin_meas"),
|
||||
CLK_MSR_ID(61, "vpu"),
|
||||
CLK_MSR_ID(62, "vpu_clkb"),
|
||||
CLK_MSR_ID(63, "vpu_clkb_tmp"),
|
||||
CLK_MSR_ID(64, "vpu_clkc"),
|
||||
CLK_MSR_ID(65, "vid_lock"),
|
||||
CLK_MSR_ID(66, "vapb"),
|
||||
CLK_MSR_ID(67, "ge2d"),
|
||||
CLK_MSR_ID(70, "mipi_dsi_meas"),
|
||||
CLK_MSR_ID(71, "mipi_dsi_phy"),
|
||||
CLK_MSR_ID(72, "mipi_csi_phy"),
|
||||
CLK_MSR_ID(73, "csi2_adapt"),
|
||||
CLK_MSR_ID(74, "cts_csi2_data"),
|
||||
CLK_MSR_ID(75, "mipi_csi_phy_out"),
|
||||
CLK_MSR_ID(76, "hdmitx_tmds"),
|
||||
CLK_MSR_ID(77, "hdmitx_sys"),
|
||||
CLK_MSR_ID(78, "hdmitx_fe"),
|
||||
CLK_MSR_ID(79, "rama_clk"),
|
||||
CLK_MSR_ID(80, "hdmitx_prif"),
|
||||
CLK_MSR_ID(81, "hdmitx_200m"),
|
||||
CLK_MSR_ID(82, "hdmitx_aud"),
|
||||
CLK_MSR_ID(84, "audio_tohdmitx_mclk"),
|
||||
CLK_MSR_ID(85, "audio_tohdmitx_bclk"),
|
||||
CLK_MSR_ID(86, "audio_tohdmitx_lrclk"),
|
||||
CLK_MSR_ID(87, "audio_tohdmitx_spdif_clk"),
|
||||
CLK_MSR_ID(88, "htx_aes_clk"),
|
||||
CLK_MSR_ID(89, "amfc"),
|
||||
CLK_MSR_ID(93, "vdec"),
|
||||
CLK_MSR_ID(99, "hevcf"),
|
||||
CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
|
||||
CLK_MSR_ID(108, "cmpr"),
|
||||
CLK_MSR_ID(109, "dewarpa"),
|
||||
CLK_MSR_ID(110, "sc"),
|
||||
CLK_MSR_ID(111, "sar_adc"),
|
||||
CLK_MSR_ID(113, "sd_emmc_c"),
|
||||
CLK_MSR_ID(114, "sd_emmc_b"),
|
||||
CLK_MSR_ID(115, "sd_emmc_a"),
|
||||
CLK_MSR_ID(116, "gpio_msr_clk"),
|
||||
CLK_MSR_ID(117, "aux_clk_o"),
|
||||
CLK_MSR_ID(118, "spicc"),
|
||||
CLK_MSR_ID(121, "ts"),
|
||||
CLK_MSR_ID(130, "o_vad_clk"),
|
||||
CLK_MSR_ID(132, "audio_locker_in_clk"),
|
||||
CLK_MSR_ID(133, "audio_locker_out_clk"),
|
||||
CLK_MSR_ID(134, "audio_tdmout_c_sclk"),
|
||||
CLK_MSR_ID(135, "audio_tdmout_b_sclk"),
|
||||
CLK_MSR_ID(136, "audio_tdmout_a_sclk"),
|
||||
CLK_MSR_ID(137, "audio_tdmin_lb_sclk"),
|
||||
CLK_MSR_ID(138, "audio_tdmin_c_sclk"),
|
||||
CLK_MSR_ID(139, "audio_tdmin_b_sclk"),
|
||||
CLK_MSR_ID(140, "audio_tdmin_a_sclk"),
|
||||
CLK_MSR_ID(141, "audio_resamplea_clk"),
|
||||
CLK_MSR_ID(142, "audio_pdm_sysclk"),
|
||||
CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"),
|
||||
CLK_MSR_ID(144, "audio_spdifout_mst_clk"),
|
||||
CLK_MSR_ID(145, "audio_spdifin_mst_clk"),
|
||||
CLK_MSR_ID(147, "audio_resampleb_clk"),
|
||||
CLK_MSR_ID(148, "pcie_pipe_clk"),
|
||||
CLK_MSR_ID(149, "pcie_ref_clk"),
|
||||
CLK_MSR_ID(150, "pcie_upcrx_cdrclk"),
|
||||
CLK_MSR_ID(151, "pcie_upcrx_clk_sync_b20"),
|
||||
CLK_MSR_ID(152, "pcie_u3p2pll1_clk_div16"),
|
||||
CLK_MSR_ID(153, "pcie_u3p2pll0_clkout"),
|
||||
CLK_MSR_ID(154, "pcie_ref_clk_p"),
|
||||
CLK_MSR_ID(160, "pwm_j"),
|
||||
CLK_MSR_ID(161, "pwm_i"),
|
||||
CLK_MSR_ID(162, "pwm_h"),
|
||||
CLK_MSR_ID(163, "pwm_g"),
|
||||
CLK_MSR_ID(164, "pwm_f"),
|
||||
CLK_MSR_ID(165, "pwm_e"),
|
||||
CLK_MSR_ID(166, "pwm_d"),
|
||||
CLK_MSR_ID(167, "pwm_c"),
|
||||
CLK_MSR_ID(168, "pwm_b"),
|
||||
CLK_MSR_ID(169, "pwm_a"),
|
||||
CLK_MSR_ID(175, "rng_ring_clk[0]"),
|
||||
CLK_MSR_ID(176, "rng_ring_clk[1]"),
|
||||
CLK_MSR_ID(177, "rng_ring_clk[2]"),
|
||||
CLK_MSR_ID(178, "rng_ring_clk[3]"),
|
||||
CLK_MSR_ID(179, "rng_ring_clk[4]"),
|
||||
CLK_MSR_ID(180, "am_ring_osc_clk_out[0]"),
|
||||
CLK_MSR_ID(181, "am_ring_osc_clk_out[1]"),
|
||||
CLK_MSR_ID(182, "am_ring_osc_clk_out[2]"),
|
||||
CLK_MSR_ID(183, "am_ring_osc_clk_out[3]"),
|
||||
CLK_MSR_ID(184, "am_ring_osc_clk_out[4]"),
|
||||
CLK_MSR_ID(185, "am_ring_osc_clk_out[5]"),
|
||||
CLK_MSR_ID(186, "am_ring_osc_clk_out[6]"),
|
||||
CLK_MSR_ID(187, "am_ring_osc_clk_out[7]"),
|
||||
CLK_MSR_ID(188, "am_ring_osc_clk_out[8]"),
|
||||
CLK_MSR_ID(189, "am_ring_osc_clk_out[9]"),
|
||||
CLK_MSR_ID(190, "am_ring_osc_clk_out[10]"),
|
||||
CLK_MSR_ID(191, "am_ring_osc_clk_out[11]"),
|
||||
CLK_MSR_ID(192, "am_ring_osc_clk_out[12]"),
|
||||
CLK_MSR_ID(193, "am_ring_osc_clk_out[13]"),
|
||||
CLK_MSR_ID(194, "am_ring_osc_clk_out[14]"),
|
||||
CLK_MSR_ID(195, "am_ring_osc_clk_out[15]"),
|
||||
CLK_MSR_ID(196, "am_ring_osc_clk_out[16]"),
|
||||
CLK_MSR_ID(197, "nna"),
|
||||
CLK_MSR_ID(198, "vc9000e_axi"),
|
||||
CLK_MSR_ID(199, "vc9000e_core"),
|
||||
CLK_MSR_ID(201, "pcie_tl"),
|
||||
CLK_MSR_ID(204, "u3p2pll1_clk_div16"),
|
||||
CLK_MSR_ID(205, "u3p2pll0_clkout"),
|
||||
CLK_MSR_ID(206, "upctx_clk_sync_b20"),
|
||||
CLK_MSR_ID(207, "upcrx_carclk"),
|
||||
CLK_MSR_ID(208, "usb_pipe_clk"),
|
||||
CLK_MSR_ID(209, "earcrx_pll_out"),
|
||||
CLK_MSR_ID(210, "mclk_pll_clk")
|
||||
};
|
||||
|
||||
static const struct meson_msr_id clk_msr_s7[] = {
|
||||
CLK_MSR_ID(0, "sys_clk"),
|
||||
CLK_MSR_ID(1, "axi_clk"),
|
||||
CLK_MSR_ID(2, "rtc_clk"),
|
||||
CLK_MSR_ID(5, "mali"),
|
||||
CLK_MSR_ID(6, "cpu_clk_div16"),
|
||||
CLK_MSR_ID(8, "cecb"),
|
||||
CLK_MSR_ID(10, "fclk_div5"),
|
||||
CLK_MSR_ID(11, "p21_usb2_ckout"),
|
||||
CLK_MSR_ID(12, "p20_usb2_ckout"),
|
||||
CLK_MSR_ID(13, "eth_mpll_test"),
|
||||
CLK_MSR_ID(15, "fclk_50m"),
|
||||
CLK_MSR_ID(18, "gp1_pll"),
|
||||
CLK_MSR_ID(19, "hifi_pll"),
|
||||
CLK_MSR_ID(20, "gp0_pll"),
|
||||
CLK_MSR_ID(21, "hifi1_pll"),
|
||||
CLK_MSR_ID(22, "eth_mppll_50m_ckout"),
|
||||
CLK_MSR_ID(23, "sys_pll_div16"),
|
||||
CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
|
||||
CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"),
|
||||
CLK_MSR_ID(32, "eth_125m"),
|
||||
CLK_MSR_ID(33, "eth_rmii"),
|
||||
CLK_MSR_ID(34, "co_clkin_to_mac"),
|
||||
CLK_MSR_ID(36, "co_rx_clk"),
|
||||
CLK_MSR_ID(37, "co_tx_clk"),
|
||||
CLK_MSR_ID(38, "eth_phy_rxclk"),
|
||||
CLK_MSR_ID(39, "eth_phy_plltxclk"),
|
||||
CLK_MSR_ID(40, "ephy_test_clk"),
|
||||
CLK_MSR_ID(49, "hdmi_vx1_pix_clk"),
|
||||
CLK_MSR_ID(50, "vid_pll"),
|
||||
CLK_MSR_ID(51, "enci"),
|
||||
CLK_MSR_ID(52, "encp"),
|
||||
CLK_MSR_ID(53, "encl"),
|
||||
CLK_MSR_ID(54, "vdac"),
|
||||
CLK_MSR_ID(55, "cdac"),
|
||||
CLK_MSR_ID(57, "lcd_an_clk_ph2"),
|
||||
CLK_MSR_ID(58, "lcd_an_clk_ph3"),
|
||||
CLK_MSR_ID(59, "hdmitx_pixel"),
|
||||
CLK_MSR_ID(60, "vdin_meas"),
|
||||
CLK_MSR_ID(61, "vpu"),
|
||||
CLK_MSR_ID(62, "vpu_clkb"),
|
||||
CLK_MSR_ID(63, "vpu_clkb_tmp"),
|
||||
CLK_MSR_ID(64, "vpu_clkc"),
|
||||
CLK_MSR_ID(65, "vid_lock"),
|
||||
CLK_MSR_ID(66, "vapb"),
|
||||
CLK_MSR_ID(67, "ge2d"),
|
||||
CLK_MSR_ID(76, "hdmitx_tmds"),
|
||||
CLK_MSR_ID(77, "hdmitx_sys"),
|
||||
CLK_MSR_ID(78, "hdmitx_fe"),
|
||||
CLK_MSR_ID(80, "hdmitx_prif"),
|
||||
CLK_MSR_ID(81, "hdmitx_200m"),
|
||||
CLK_MSR_ID(82, "hdmitx_aud"),
|
||||
CLK_MSR_ID(84, "audio_tohdmitx_mclk"),
|
||||
CLK_MSR_ID(85, "audio_tohdmitx_bclk"),
|
||||
CLK_MSR_ID(86, "audio_tohdmitx_lrclk"),
|
||||
CLK_MSR_ID(87, "audio_tohdmitx_spdif_clk"),
|
||||
CLK_MSR_ID(88, "htx_aes_clk"),
|
||||
CLK_MSR_ID(93, "vdec"),
|
||||
CLK_MSR_ID(99, "hevcf"),
|
||||
CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
|
||||
CLK_MSR_ID(110, "sc"),
|
||||
CLK_MSR_ID(111, "sar_adc"),
|
||||
CLK_MSR_ID(113, "sd_emmc_c"),
|
||||
CLK_MSR_ID(114, "sd_emmc_b"),
|
||||
CLK_MSR_ID(115, "sd_emmc_a"),
|
||||
CLK_MSR_ID(116, "gpio_msr_clk"),
|
||||
CLK_MSR_ID(118, "spicc"),
|
||||
CLK_MSR_ID(121, "ts"),
|
||||
CLK_MSR_ID(130, "o_vad_clk"),
|
||||
CLK_MSR_ID(131, "au_dac_clk_x128"),
|
||||
CLK_MSR_ID(132, "audio_locker_in_clk"),
|
||||
CLK_MSR_ID(133, "audio_locker_out_clk"),
|
||||
CLK_MSR_ID(134, "audio_tdmout_c_sclk"),
|
||||
CLK_MSR_ID(135, "audio_tdmout_b_sclk"),
|
||||
CLK_MSR_ID(136, "audio_tdmout_a_sclk"),
|
||||
CLK_MSR_ID(137, "audio_tdmin_lb_sclk"),
|
||||
CLK_MSR_ID(138, "audio_tdmin_c_sclk"),
|
||||
CLK_MSR_ID(139, "audio_tdmin_b_sclk"),
|
||||
CLK_MSR_ID(140, "audio_tdmin_a_sclk"),
|
||||
CLK_MSR_ID(141, "audio_resamplea_clk"),
|
||||
CLK_MSR_ID(142, "audio_pdm_sysclk"),
|
||||
CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"),
|
||||
CLK_MSR_ID(144, "audio_spdifout_mst_clk"),
|
||||
CLK_MSR_ID(145, "audio_spdifin_mst_clk"),
|
||||
CLK_MSR_ID(147, "audio_resampleb_clk"),
|
||||
CLK_MSR_ID(160, "pwm_j"),
|
||||
CLK_MSR_ID(161, "pwm_i"),
|
||||
CLK_MSR_ID(162, "pwm_h"),
|
||||
CLK_MSR_ID(163, "pwm_g"),
|
||||
CLK_MSR_ID(164, "pwm_f"),
|
||||
CLK_MSR_ID(165, "pwm_e"),
|
||||
CLK_MSR_ID(166, "pwm_d"),
|
||||
CLK_MSR_ID(167, "pwm_c"),
|
||||
CLK_MSR_ID(168, "pwm_b"),
|
||||
CLK_MSR_ID(169, "pwm_a"),
|
||||
CLK_MSR_ID(176, "rng_ring_clk[0]"),
|
||||
CLK_MSR_ID(177, "rng_ring_clk[1]"),
|
||||
CLK_MSR_ID(178, "rng_ring_clk[2]"),
|
||||
CLK_MSR_ID(179, "rng_ring_clk[3]"),
|
||||
CLK_MSR_ID(180, "osc_ring_clk[0](a55 core0 14_slvt)"),
|
||||
CLK_MSR_ID(181, "osc_ring_clk[1](a55 core1 14_slvt)"),
|
||||
CLK_MSR_ID(182, "osc_ring_clk[2](a55 core2 14_slvt)"),
|
||||
CLK_MSR_ID(183, "osc_ring_clk[3](a55 core3 14_slvt)"),
|
||||
CLK_MSR_ID(184, "osc_ring_clk[4](a55_pwr[0] 16_slvt)"),
|
||||
CLK_MSR_ID(185, "osc_ring_clk[5](a55_pwr[1] 14_lvt)"),
|
||||
CLK_MSR_ID(186, "osc_ring_clk[6](a55_pwr[2] 14_rvt)"),
|
||||
CLK_MSR_ID(187, "osc_ring_clk[7](mali[1] 14_lvt)"),
|
||||
CLK_MSR_ID(188, "osc_ring_clk[8](mali[1] 14_rvt)"),
|
||||
CLK_MSR_ID(189, "osc_ring_clk[9](dos[0] 16_lvt)"),
|
||||
CLK_MSR_ID(190, "osc_ring_clk[10](dos[1] 14_rvt)"),
|
||||
CLK_MSR_ID(191, "osc_ring_clk[11](ddr[0] 9t_14_lvt)"),
|
||||
CLK_MSR_ID(192, "osc_ring_clk[12](top[0] 16_rvt)"),
|
||||
};
|
||||
|
||||
static const struct meson_msr_id clk_msr_s7d[] = {
|
||||
CLK_MSR_ID(0, "sys_clk"),
|
||||
CLK_MSR_ID(1, "axi_clk"),
|
||||
CLK_MSR_ID(2, "rtc_clk"),
|
||||
CLK_MSR_ID(4, "mali_stack"),
|
||||
CLK_MSR_ID(5, "mali"),
|
||||
CLK_MSR_ID(6, "cpu_clk_div16"),
|
||||
CLK_MSR_ID(8, "cecb"),
|
||||
CLK_MSR_ID(9, "mali_aclkm"),
|
||||
CLK_MSR_ID(10, "fclk_div5"),
|
||||
CLK_MSR_ID(11, "p21_usb2_ckout"),
|
||||
CLK_MSR_ID(12, "p20_usb2_ckout"),
|
||||
CLK_MSR_ID(13, "eth_mpll_test"),
|
||||
CLK_MSR_ID(15, "fclk_50m"),
|
||||
CLK_MSR_ID(18, "gp1_pll"),
|
||||
CLK_MSR_ID(19, "hifi_pll"),
|
||||
CLK_MSR_ID(20, "gp0_pll"),
|
||||
CLK_MSR_ID(21, "hifi1_pll"),
|
||||
CLK_MSR_ID(22, "eth_mppll_50m_ckout"),
|
||||
CLK_MSR_ID(23, "sys_pll_div16"),
|
||||
CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
|
||||
CLK_MSR_ID(25, "mod_Tsin_A_CLK_IN"),
|
||||
CLK_MSR_ID(26, "mod_Tsin_B_CLK_IN"),
|
||||
CLK_MSR_ID(31, "earcrx_pll_clk_out"),
|
||||
CLK_MSR_ID(32, "eth_125m"),
|
||||
CLK_MSR_ID(33, "eth_rmii"),
|
||||
CLK_MSR_ID(34, "co_clkin_to_mac"),
|
||||
CLK_MSR_ID(36, "co_rx_clk"),
|
||||
CLK_MSR_ID(37, "co_tx_clk"),
|
||||
CLK_MSR_ID(38, "eth_phy_rxclk"),
|
||||
CLK_MSR_ID(39, "eth_phy_plltxclk"),
|
||||
CLK_MSR_ID(40, "ephy_test_clk"),
|
||||
CLK_MSR_ID(49, "hdmi_vx1_pix_clk"),
|
||||
CLK_MSR_ID(50, "vid_pll"),
|
||||
CLK_MSR_ID(51, "enci"),
|
||||
CLK_MSR_ID(52, "encp"),
|
||||
CLK_MSR_ID(53, "encl"),
|
||||
CLK_MSR_ID(54, "vdac"),
|
||||
CLK_MSR_ID(55, "cdac"),
|
||||
CLK_MSR_ID(57, "lcd_an_clk_ph2"),
|
||||
CLK_MSR_ID(58, "lcd_an_clk_ph3"),
|
||||
CLK_MSR_ID(59, "hdmitx_pixel"),
|
||||
CLK_MSR_ID(60, "vdin_meas"),
|
||||
CLK_MSR_ID(61, "vpu"),
|
||||
CLK_MSR_ID(62, "vpu_clkb"),
|
||||
CLK_MSR_ID(63, "vpu_clkb_tmp"),
|
||||
CLK_MSR_ID(64, "vpu_clkc"),
|
||||
CLK_MSR_ID(65, "vid_lock"),
|
||||
CLK_MSR_ID(66, "vapb"),
|
||||
CLK_MSR_ID(67, "ge2d"),
|
||||
CLK_MSR_ID(76, "hdmitx_tmds"),
|
||||
CLK_MSR_ID(77, "hdmitx_sys"),
|
||||
CLK_MSR_ID(78, "hdmitx_fe"),
|
||||
CLK_MSR_ID(80, "hdmitx_prif"),
|
||||
CLK_MSR_ID(81, "hdmitx_200m"),
|
||||
CLK_MSR_ID(82, "hdmitx_aud"),
|
||||
CLK_MSR_ID(84, "audio_tohdmitx_mclk"),
|
||||
CLK_MSR_ID(85, "audio_tohdmitx_bclk"),
|
||||
CLK_MSR_ID(86, "audio_tohdmitx_lrclk"),
|
||||
CLK_MSR_ID(87, "audio_tohdmitx_spdif_clk"),
|
||||
CLK_MSR_ID(88, "htx_aes_clk"),
|
||||
CLK_MSR_ID(89, "amfc"),
|
||||
CLK_MSR_ID(93, "vdec"),
|
||||
CLK_MSR_ID(97, "hcodec"),
|
||||
CLK_MSR_ID(99, "hevcf"),
|
||||
CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
|
||||
CLK_MSR_ID(110, "sc"),
|
||||
CLK_MSR_ID(111, "sar_adc"),
|
||||
CLK_MSR_ID(112, "aux_adc_clk_to_gpio"),
|
||||
CLK_MSR_ID(113, "sd_emmc_c"),
|
||||
CLK_MSR_ID(114, "sd_emmc_b"),
|
||||
CLK_MSR_ID(115, "sd_emmc_a"),
|
||||
CLK_MSR_ID(116, "gpio_msr_clk"),
|
||||
CLK_MSR_ID(117, "aux_clk_o"),
|
||||
CLK_MSR_ID(118, "spicc"),
|
||||
CLK_MSR_ID(121, "ts"),
|
||||
CLK_MSR_ID(130, "o_vad_clk"),
|
||||
CLK_MSR_ID(131, "au_dac_clk_x128"),
|
||||
CLK_MSR_ID(132, "audio_locker_in_clk"),
|
||||
CLK_MSR_ID(133, "audio_locker_out_clk"),
|
||||
CLK_MSR_ID(134, "audio_tdmout_c_sclk"),
|
||||
CLK_MSR_ID(135, "audio_tdmout_b_sclk"),
|
||||
CLK_MSR_ID(136, "audio_tdmout_a_sclk"),
|
||||
CLK_MSR_ID(137, "audio_tdmin_lb_sclk"),
|
||||
CLK_MSR_ID(138, "audio_tdmin_c_sclk"),
|
||||
CLK_MSR_ID(139, "audio_tdmin_b_sclk"),
|
||||
CLK_MSR_ID(140, "audio_tdmin_a_sclk"),
|
||||
CLK_MSR_ID(141, "audio_resamplea_clk"),
|
||||
CLK_MSR_ID(142, "audio_pdm_sysclk"),
|
||||
CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"),
|
||||
CLK_MSR_ID(144, "audio_spdifout_mst_clk"),
|
||||
CLK_MSR_ID(145, "audio_spdifin_mst_clk"),
|
||||
CLK_MSR_ID(146, "mod_audio_pdm_dclk_o"),
|
||||
CLK_MSR_ID(147, "audio_resampleb_clk"),
|
||||
CLK_MSR_ID(160, "pwm_j"),
|
||||
CLK_MSR_ID(161, "pwm_i"),
|
||||
CLK_MSR_ID(162, "pwm_h"),
|
||||
CLK_MSR_ID(163, "pwm_g"),
|
||||
CLK_MSR_ID(164, "pwm_f"),
|
||||
CLK_MSR_ID(165, "pwm_e"),
|
||||
CLK_MSR_ID(166, "pwm_d"),
|
||||
CLK_MSR_ID(167, "pwm_c"),
|
||||
CLK_MSR_ID(168, "pwm_b"),
|
||||
CLK_MSR_ID(169, "pwm_a"),
|
||||
CLK_MSR_ID(176, "rng_ring_clk[0]"),
|
||||
CLK_MSR_ID(177, "rng_ring_clk[1]"),
|
||||
CLK_MSR_ID(178, "rng_ring_clk[2]"),
|
||||
CLK_MSR_ID(179, "rng_ring_clk[3]"),
|
||||
CLK_MSR_ID(180, "osc_ring_clk[0](a55 core0 14_slvt)"),
|
||||
CLK_MSR_ID(181, "osc_ring_clk[1](a55 core1 14_slvt)"),
|
||||
CLK_MSR_ID(182, "osc_ring_clk[2](a55 core2 14_slvt)"),
|
||||
CLK_MSR_ID(183, "osc_ring_clk[3](a55 core3 14_slvt)"),
|
||||
CLK_MSR_ID(184, "osc_ring_clk[4](a55_pwr[0] 16_slvt)"),
|
||||
CLK_MSR_ID(185, "osc_ring_clk[5](a55_pwr[1] 14_lvt)"),
|
||||
CLK_MSR_ID(186, "osc_ring_clk[6](a55_pwr[2] 14_rvt)"),
|
||||
CLK_MSR_ID(187, "osc_ring_clk[7](mali[1] 14_lvt)"),
|
||||
CLK_MSR_ID(188, "osc_ring_clk[8](mali[1] 14_rvt)"),
|
||||
CLK_MSR_ID(189, "osc_ring_clk[9](dos[0] 16_lvt)"),
|
||||
CLK_MSR_ID(190, "osc_ring_clk[10](dos[1] 14_rvt)"),
|
||||
CLK_MSR_ID(191, "osc_ring_clk[11](ddr[0] 9t_14_lvt)"),
|
||||
CLK_MSR_ID(192, "osc_ring_clk[12](top[0] 16_rvt)"),
|
||||
};
|
||||
|
||||
static int meson_measure_id(struct meson_msr_id *clk_msr_id,
|
||||
unsigned int duration)
|
||||
{
|
||||
@@ -1279,6 +2116,30 @@ static const struct msr_reg_offset msr_reg_offset_v2 = {
|
||||
.duty_val = 0x18,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_a1_data = {
|
||||
.msr_table = (void *)clk_msr_a1,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_a1),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_a4_data = {
|
||||
.msr_table = (void *)clk_msr_a4,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_a4),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_a5_data = {
|
||||
.msr_table = (void *)clk_msr_a5,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_a5),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_a9_data = {
|
||||
.msr_table = (void *)clk_msr_a9,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_a9),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_c3_data = {
|
||||
.msr_table = (void *)clk_msr_c3,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_c3),
|
||||
@@ -1291,9 +2152,21 @@ static const struct meson_msr_data clk_msr_s4_data = {
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_a1_data = {
|
||||
.msr_table = (void *)clk_msr_a1,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_a1),
|
||||
static const struct meson_msr_data clk_msr_s6_data = {
|
||||
.msr_table = (void *)clk_msr_s6,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_s6),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_s7_data = {
|
||||
.msr_table = (void *)clk_msr_s7,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_s7),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
static const struct meson_msr_data clk_msr_s7d_data = {
|
||||
.msr_table = (void *)clk_msr_s7d,
|
||||
.msr_count = ARRAY_SIZE(clk_msr_s7d),
|
||||
.reg = &msr_reg_offset_v2,
|
||||
};
|
||||
|
||||
@@ -1305,16 +2178,24 @@ static const struct meson_msr_data clk_msr_t7_data = {
|
||||
|
||||
static const struct of_device_id meson_msr_match_table[] = {
|
||||
{
|
||||
.compatible = "amlogic,meson-gx-clk-measure",
|
||||
.data = &clk_msr_gx_data,
|
||||
.compatible = "amlogic,a1-clk-measure",
|
||||
.data = &clk_msr_a1_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8-clk-measure",
|
||||
.data = &clk_msr_m8_data,
|
||||
.compatible = "amlogic,a4-clk-measure",
|
||||
.data = &clk_msr_a4_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8b-clk-measure",
|
||||
.data = &clk_msr_m8_data,
|
||||
.compatible = "amlogic,a5-clk-measure",
|
||||
.data = &clk_msr_a5_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,a9-clk-measure",
|
||||
.data = &clk_msr_a9_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,c3-clk-measure",
|
||||
.data = &clk_msr_c3_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson-axg-clk-measure",
|
||||
@@ -1324,21 +2205,37 @@ static const struct of_device_id meson_msr_match_table[] = {
|
||||
.compatible = "amlogic,meson-g12a-clk-measure",
|
||||
.data = &clk_msr_g12a_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson-gx-clk-measure",
|
||||
.data = &clk_msr_gx_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson-sm1-clk-measure",
|
||||
.data = &clk_msr_sm1_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,c3-clk-measure",
|
||||
.data = &clk_msr_c3_data,
|
||||
.compatible = "amlogic,meson8-clk-measure",
|
||||
.data = &clk_msr_m8_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8b-clk-measure",
|
||||
.data = &clk_msr_m8_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,s4-clk-measure",
|
||||
.data = &clk_msr_s4_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,a1-clk-measure",
|
||||
.data = &clk_msr_a1_data,
|
||||
.compatible = "amlogic,s6-clk-measure",
|
||||
.data = &clk_msr_s6_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,s7-clk-measure",
|
||||
.data = &clk_msr_s7_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,s7d-clk-measure",
|
||||
.data = &clk_msr_s7d_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,t7-clk-measure",
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r')
|
||||
#define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x')
|
||||
#define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm')
|
||||
#define APPLE_RTKIT_CRASHLOG_REGS FOURCC('C', 'r', 'g', '8')
|
||||
#define APPLE_RTKIT_CRASHLOG_AARCH32 FOURCC('C', 'r', 'g', 'A')
|
||||
#define APPLE_RTKIT_CRASHLOG_AARCH64 FOURCC('C', 'r', 'g', '8')
|
||||
|
||||
/* For COMPILE_TEST on non-ARM64 architectures */
|
||||
#ifndef PSR_MODE_EL0t
|
||||
@@ -25,6 +26,21 @@
|
||||
#define PSR_MODE_MASK 0x0000000f
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AArch32 mode definitions: APPLE_RTKIT depends on APPLE_MAILBOX, which
|
||||
* depends on 64BIT, so there is no need to care about COMPILE_TEST on ARM.
|
||||
*/
|
||||
#define USR_MODE 0x00000010
|
||||
#define FIQ_MODE 0x00000011
|
||||
#define IRQ_MODE 0x00000012
|
||||
#define SVC_MODE 0x00000013
|
||||
#define MON_MODE 0x00000016
|
||||
#define ABT_MODE 0x00000017
|
||||
#define HYP_MODE 0x0000001a
|
||||
#define UND_MODE 0x0000001b
|
||||
#define SYSTEM_MODE 0x0000001f
|
||||
#define MODE_MASK_32 0x0000001f
|
||||
|
||||
struct apple_rtkit_crashlog_header {
|
||||
u32 fourcc;
|
||||
u32 version;
|
||||
@@ -42,7 +58,7 @@ struct apple_rtkit_crashlog_mbox_entry {
|
||||
};
|
||||
static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18);
|
||||
|
||||
struct apple_rtkit_crashlog_regs {
|
||||
struct apple_rtkit_crashlog_aarch64 {
|
||||
u32 unk_0;
|
||||
u32 unk_4;
|
||||
u64 regs[31];
|
||||
@@ -58,7 +74,21 @@ struct apple_rtkit_crashlog_regs {
|
||||
u64 esr;
|
||||
u64 unk_Z;
|
||||
} __packed;
|
||||
static_assert(sizeof(struct apple_rtkit_crashlog_regs) == 0x350);
|
||||
static_assert(sizeof(struct apple_rtkit_crashlog_aarch64) == 0x350);
|
||||
|
||||
struct apple_rtkit_crashlog_aarch32 {
|
||||
u32 unk_0;
|
||||
u32 unk_4;
|
||||
u32 regs[16];
|
||||
u32 psr;
|
||||
u32 unk_x1;
|
||||
u8 stack[0x100];
|
||||
u32 unk_x2;
|
||||
u32 unk_x3;
|
||||
u32 unk_x4;
|
||||
u32 unk_x5;
|
||||
} __packed;
|
||||
static_assert(sizeof(struct apple_rtkit_crashlog_aarch32) == 0x160);
|
||||
|
||||
static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
|
||||
size_t size)
|
||||
@@ -123,21 +153,84 @@ static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr,
|
||||
size_t size)
|
||||
static void apple_rtkit_crashlog_dump_aarch32(struct apple_rtkit *rtk, u8 *bfr,
|
||||
size_t size)
|
||||
{
|
||||
struct apple_rtkit_crashlog_regs *regs;
|
||||
const char *el;
|
||||
struct apple_rtkit_crashlog_aarch32 *state;
|
||||
const char *mode;
|
||||
int i;
|
||||
|
||||
if (size < sizeof(*regs)) {
|
||||
dev_warn(rtk->dev, "RTKit: Regs section too small: 0x%zx", size);
|
||||
if (size < sizeof(*state)) {
|
||||
dev_warn(rtk->dev, "RTKit: AArch32 section too small: 0x%zx", size);
|
||||
return;
|
||||
}
|
||||
|
||||
regs = (struct apple_rtkit_crashlog_regs *)bfr;
|
||||
state = (struct apple_rtkit_crashlog_aarch32 *)bfr;
|
||||
|
||||
switch (regs->psr & PSR_MODE_MASK) {
|
||||
switch (state->psr & MODE_MASK_32) {
|
||||
case USR_MODE:
|
||||
mode = "User";
|
||||
break;
|
||||
case FIQ_MODE:
|
||||
mode = "FIQ";
|
||||
break;
|
||||
case IRQ_MODE:
|
||||
mode = "IRQ";
|
||||
break;
|
||||
case SVC_MODE:
|
||||
mode = "Supervisor";
|
||||
break;
|
||||
case MON_MODE:
|
||||
mode = "Monitor";
|
||||
break;
|
||||
case ABT_MODE:
|
||||
mode = "Abort";
|
||||
break;
|
||||
case HYP_MODE:
|
||||
mode = "Hypervisor";
|
||||
break;
|
||||
case UND_MODE:
|
||||
mode = "Undefined";
|
||||
break;
|
||||
case SYSTEM_MODE:
|
||||
mode = "System";
|
||||
break;
|
||||
default:
|
||||
mode = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
dev_warn(rtk->dev, "RTKit: Exception dump:");
|
||||
dev_warn(rtk->dev, " == Exception taken from %s mode ==", mode);
|
||||
dev_warn(rtk->dev, " PSR = 0x%x", state->psr);
|
||||
dev_warn(rtk->dev, "\n");
|
||||
|
||||
for (i = 0; i < 16; i += 4)
|
||||
dev_warn(rtk->dev,
|
||||
" r%02d-r%02d = %08x %08x %08x %08x\n",
|
||||
i, i + 3,
|
||||
state->regs[i], state->regs[i + 1],
|
||||
state->regs[i + 2], state->regs[i + 3]);
|
||||
|
||||
dev_warn(rtk->dev, "\n");
|
||||
}
|
||||
|
||||
static void apple_rtkit_crashlog_dump_aarch64(struct apple_rtkit *rtk, u8 *bfr,
|
||||
size_t size)
|
||||
{
|
||||
struct apple_rtkit_crashlog_aarch64 *state;
|
||||
const char *el;
|
||||
int i;
|
||||
|
||||
if (size < sizeof(*state)) {
|
||||
dev_warn(rtk->dev, "RTKit: AArch64 section too small: 0x%zx",
|
||||
size);
|
||||
return;
|
||||
}
|
||||
|
||||
state = (struct apple_rtkit_crashlog_aarch64 *)bfr;
|
||||
|
||||
switch (state->psr & PSR_MODE_MASK) {
|
||||
case PSR_MODE_EL0t:
|
||||
el = "EL0t";
|
||||
break;
|
||||
@@ -160,11 +253,11 @@ static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr,
|
||||
|
||||
dev_warn(rtk->dev, "RTKit: Exception dump:");
|
||||
dev_warn(rtk->dev, " == Exception taken from %s ==", el);
|
||||
dev_warn(rtk->dev, " PSR = 0x%llx", regs->psr);
|
||||
dev_warn(rtk->dev, " PC = 0x%llx\n", regs->pc);
|
||||
dev_warn(rtk->dev, " ESR = 0x%llx\n", regs->esr);
|
||||
dev_warn(rtk->dev, " FAR = 0x%llx\n", regs->far);
|
||||
dev_warn(rtk->dev, " SP = 0x%llx\n", regs->sp);
|
||||
dev_warn(rtk->dev, " PSR = 0x%llx", state->psr);
|
||||
dev_warn(rtk->dev, " PC = 0x%llx\n", state->pc);
|
||||
dev_warn(rtk->dev, " ESR = 0x%llx\n", state->esr);
|
||||
dev_warn(rtk->dev, " FAR = 0x%llx\n", state->far);
|
||||
dev_warn(rtk->dev, " SP = 0x%llx\n", state->sp);
|
||||
dev_warn(rtk->dev, "\n");
|
||||
|
||||
for (i = 0; i < 31; i += 4) {
|
||||
@@ -172,12 +265,12 @@ static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr,
|
||||
dev_warn(rtk->dev,
|
||||
" x%02d-x%02d = %016llx %016llx %016llx %016llx\n",
|
||||
i, i + 3,
|
||||
regs->regs[i], regs->regs[i + 1],
|
||||
regs->regs[i + 2], regs->regs[i + 3]);
|
||||
state->regs[i], state->regs[i + 1],
|
||||
state->regs[i + 2], state->regs[i + 3]);
|
||||
else
|
||||
dev_warn(rtk->dev,
|
||||
" x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3,
|
||||
regs->regs[i], regs->regs[i + 1], regs->regs[i + 2]);
|
||||
state->regs[i], state->regs[i + 1], state->regs[i + 2]);
|
||||
}
|
||||
|
||||
dev_warn(rtk->dev, "\n");
|
||||
@@ -229,9 +322,13 @@ void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
|
||||
apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16,
|
||||
section_size);
|
||||
break;
|
||||
case APPLE_RTKIT_CRASHLOG_REGS:
|
||||
apple_rtkit_crashlog_dump_regs(rtk, bfr + offset + 16,
|
||||
section_size);
|
||||
case APPLE_RTKIT_CRASHLOG_AARCH32:
|
||||
apple_rtkit_crashlog_dump_aarch32(rtk, bfr + offset + 16,
|
||||
section_size);
|
||||
break;
|
||||
case APPLE_RTKIT_CRASHLOG_AARCH64:
|
||||
apple_rtkit_crashlog_dump_aarch64(rtk, bfr + offset + 16,
|
||||
section_size);
|
||||
break;
|
||||
default:
|
||||
dev_warn(rtk->dev,
|
||||
|
||||
@@ -404,9 +404,7 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = {
|
||||
|
||||
static int __init atmel_soc_device_init(void)
|
||||
{
|
||||
struct device_node *np __free(device_node) = of_find_node_by_path("/");
|
||||
|
||||
if (!of_match_node(at91_soc_allowed_list, np))
|
||||
if (!of_machine_device_match(at91_soc_allowed_list))
|
||||
return 0;
|
||||
|
||||
at91_soc_init(socs);
|
||||
|
||||
@@ -88,6 +88,7 @@ static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev)
|
||||
|
||||
/* clear the affinity hint */
|
||||
irq_set_affinity_hint(irq->virq, NULL);
|
||||
devm_free_irq(&dpio_dev->dev, irq->virq, &dpio_dev->dev);
|
||||
}
|
||||
|
||||
static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu)
|
||||
@@ -244,9 +245,9 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_dpaa2_io_create:
|
||||
unregister_dpio_irq_handlers(dpio_dev);
|
||||
err_register_dpio_irq:
|
||||
dpaa2_io_down(priv->io);
|
||||
err_dpaa2_io_create:
|
||||
fsl_mc_free_irqs(dpio_dev);
|
||||
err_allocate_irqs:
|
||||
dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
|
||||
@@ -276,10 +277,10 @@ static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
|
||||
priv = dev_get_drvdata(dev);
|
||||
cpu = dpaa2_io_get_cpu(priv->io);
|
||||
|
||||
dpaa2_io_down(priv->io);
|
||||
|
||||
dpio_teardown_irqs(dpio_dev);
|
||||
|
||||
dpaa2_io_down(priv->io);
|
||||
|
||||
cpumask_set_cpu(cpu, cpus_unused_mask);
|
||||
|
||||
err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
|
||||
|
||||
+26
-41
@@ -32,8 +32,13 @@ struct qe_gpio_chip {
|
||||
/* shadowed data register to clear/set bits safely */
|
||||
u32 cpdata;
|
||||
|
||||
/* saved_regs used to restore dedicated functions */
|
||||
struct qe_pio_regs saved_regs;
|
||||
/* saved regs used to restore dedicated functions */
|
||||
u32 saved_cpodr;
|
||||
u32 saved_cpdata;
|
||||
u32 saved_cpdir1;
|
||||
u32 saved_cpdir2;
|
||||
u32 saved_cppar1;
|
||||
u32 saved_cppar2;
|
||||
};
|
||||
|
||||
static void qe_gpio_save_regs(struct qe_gpio_chip *qe_gc)
|
||||
@@ -41,12 +46,12 @@ static void qe_gpio_save_regs(struct qe_gpio_chip *qe_gc)
|
||||
struct qe_pio_regs __iomem *regs = qe_gc->regs;
|
||||
|
||||
qe_gc->cpdata = ioread32be(®s->cpdata);
|
||||
qe_gc->saved_regs.cpdata = qe_gc->cpdata;
|
||||
qe_gc->saved_regs.cpdir1 = ioread32be(®s->cpdir1);
|
||||
qe_gc->saved_regs.cpdir2 = ioread32be(®s->cpdir2);
|
||||
qe_gc->saved_regs.cppar1 = ioread32be(®s->cppar1);
|
||||
qe_gc->saved_regs.cppar2 = ioread32be(®s->cppar2);
|
||||
qe_gc->saved_regs.cpodr = ioread32be(®s->cpodr);
|
||||
qe_gc->saved_cpdata = qe_gc->cpdata;
|
||||
qe_gc->saved_cpdir1 = ioread32be(®s->cpdir1);
|
||||
qe_gc->saved_cpdir2 = ioread32be(®s->cpdir2);
|
||||
qe_gc->saved_cppar1 = ioread32be(®s->cppar1);
|
||||
qe_gc->saved_cppar2 = ioread32be(®s->cppar2);
|
||||
qe_gc->saved_cpodr = ioread32be(®s->cpodr);
|
||||
}
|
||||
|
||||
static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
@@ -196,18 +201,17 @@ struct qe_pin {
|
||||
/**
|
||||
* qe_pin_request - Request a QE pin
|
||||
* @dev: device to get the pin from
|
||||
* @index: index of the pin in the device tree
|
||||
* @gpiod: GPIO descriptor associated with this pin
|
||||
* Context: non-atomic
|
||||
*
|
||||
* This function return qe_pin so that you could use it with the rest of
|
||||
* the QE Pin Multiplexing API.
|
||||
*/
|
||||
struct qe_pin *qe_pin_request(struct device *dev, int index)
|
||||
struct qe_pin *qe_pin_request(struct device *dev, struct gpio_desc *gpiod)
|
||||
{
|
||||
struct gpio_device *gdev;
|
||||
struct qe_pin *qe_pin;
|
||||
struct gpio_chip *gc;
|
||||
struct gpio_desc *gpiod;
|
||||
int gpio_num;
|
||||
int err;
|
||||
|
||||
qe_pin = kzalloc_obj(*qe_pin);
|
||||
@@ -216,34 +220,20 @@ struct qe_pin *qe_pin_request(struct device *dev, int index)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request gpio as nonexclusive as it was likely reserved by the
|
||||
* caller, and we are not planning on controlling it, we only need
|
||||
* the descriptor to the to the gpio chip structure.
|
||||
*/
|
||||
gpiod = gpiod_get_index(dev, NULL, index,
|
||||
GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
|
||||
err = PTR_ERR_OR_ZERO(gpiod);
|
||||
if (err)
|
||||
goto err0;
|
||||
|
||||
gc = gpiod_to_chip(gpiod);
|
||||
gpio_num = desc_to_gpio(gpiod);
|
||||
/* We no longer need this descriptor */
|
||||
gpiod_put(gpiod);
|
||||
|
||||
if (WARN_ON(!gc)) {
|
||||
gdev = gpiod_to_gpio_device(gpiod);
|
||||
if (WARN_ON(!gdev)) {
|
||||
err = -ENODEV;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
gc = gpio_device_get_chip(gdev);
|
||||
qe_pin->controller = gpiochip_get_data(gc);
|
||||
/*
|
||||
* FIXME: this gets the local offset on the gpio_chip so that the driver
|
||||
* can manipulate pin control settings through its custom API. The real
|
||||
* solution is to create a real pin control driver for this.
|
||||
*/
|
||||
qe_pin->num = gpio_num - gc->base;
|
||||
qe_pin->num = desc_to_gpio(gpiod) - gc->base;
|
||||
|
||||
if (!fwnode_device_is_compatible(gc->fwnode, "fsl,mpc8323-qe-pario-bank")) {
|
||||
dev_dbg(dev, "%s: tried to get a non-qe pin\n", __func__);
|
||||
@@ -284,7 +274,6 @@ void qe_pin_set_dedicated(struct qe_pin *qe_pin)
|
||||
{
|
||||
struct qe_gpio_chip *qe_gc = qe_pin->controller;
|
||||
struct qe_pio_regs __iomem *regs = qe_gc->regs;
|
||||
struct qe_pio_regs *sregs = &qe_gc->saved_regs;
|
||||
int pin = qe_pin->num;
|
||||
u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1));
|
||||
u32 mask2 = 0x3 << (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2);
|
||||
@@ -294,24 +283,20 @@ void qe_pin_set_dedicated(struct qe_pin *qe_pin)
|
||||
spin_lock_irqsave(&qe_gc->lock, flags);
|
||||
|
||||
if (second_reg) {
|
||||
qe_clrsetbits_be32(®s->cpdir2, mask2,
|
||||
sregs->cpdir2 & mask2);
|
||||
qe_clrsetbits_be32(®s->cppar2, mask2,
|
||||
sregs->cppar2 & mask2);
|
||||
qe_clrsetbits_be32(®s->cpdir2, mask2, qe_gc->saved_cpdir2 & mask2);
|
||||
qe_clrsetbits_be32(®s->cppar2, mask2, qe_gc->saved_cppar2 & mask2);
|
||||
} else {
|
||||
qe_clrsetbits_be32(®s->cpdir1, mask2,
|
||||
sregs->cpdir1 & mask2);
|
||||
qe_clrsetbits_be32(®s->cppar1, mask2,
|
||||
sregs->cppar1 & mask2);
|
||||
qe_clrsetbits_be32(®s->cpdir1, mask2, qe_gc->saved_cpdir1 & mask2);
|
||||
qe_clrsetbits_be32(®s->cppar1, mask2, qe_gc->saved_cppar1 & mask2);
|
||||
}
|
||||
|
||||
if (sregs->cpdata & mask1)
|
||||
if (qe_gc->saved_cpdata & mask1)
|
||||
qe_gc->cpdata |= mask1;
|
||||
else
|
||||
qe_gc->cpdata &= ~mask1;
|
||||
|
||||
iowrite32be(qe_gc->cpdata, ®s->cpdata);
|
||||
qe_clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1);
|
||||
qe_clrsetbits_be32(®s->cpodr, mask1, qe_gc->saved_cpodr & mask1);
|
||||
spin_unlock_irqrestore(&qe_gc->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(qe_pin_set_dedicated);
|
||||
|
||||
@@ -865,12 +865,12 @@ err:
|
||||
clk_put(tsa->tdm[i].l1rclk_clk);
|
||||
}
|
||||
if (tsa->tdm[i].l1tsync_clk) {
|
||||
clk_disable_unprepare(tsa->tdm[i].l1rsync_clk);
|
||||
clk_put(tsa->tdm[i].l1rsync_clk);
|
||||
clk_disable_unprepare(tsa->tdm[i].l1tsync_clk);
|
||||
clk_put(tsa->tdm[i].l1tsync_clk);
|
||||
}
|
||||
if (tsa->tdm[i].l1tclk_clk) {
|
||||
clk_disable_unprepare(tsa->tdm[i].l1rclk_clk);
|
||||
clk_put(tsa->tdm[i].l1rclk_clk);
|
||||
clk_disable_unprepare(tsa->tdm[i].l1tclk_clk);
|
||||
clk_put(tsa->tdm[i].l1tclk_clk);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -1039,12 +1039,12 @@ static void tsa_remove(struct platform_device *pdev)
|
||||
clk_put(tsa->tdm[i].l1rclk_clk);
|
||||
}
|
||||
if (tsa->tdm[i].l1tsync_clk) {
|
||||
clk_disable_unprepare(tsa->tdm[i].l1rsync_clk);
|
||||
clk_put(tsa->tdm[i].l1rsync_clk);
|
||||
clk_disable_unprepare(tsa->tdm[i].l1tsync_clk);
|
||||
clk_put(tsa->tdm[i].l1tsync_clk);
|
||||
}
|
||||
if (tsa->tdm[i].l1tclk_clk) {
|
||||
clk_disable_unprepare(tsa->tdm[i].l1rclk_clk);
|
||||
clk_put(tsa->tdm[i].l1rclk_clk);
|
||||
clk_disable_unprepare(tsa->tdm[i].l1tclk_clk);
|
||||
clk_put(tsa->tdm[i].l1tclk_clk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,35 +5,200 @@
|
||||
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x030
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN 0x038
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN 0x03c
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x058
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_WDMA0_SEL_IN 0x05c
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_UFOE_SEL_IN 0x060
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN 0x064
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN 0x068
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN 0x06c
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN 0x070
|
||||
#define MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN 0x074
|
||||
|
||||
#define MT8167_OVL0_MOUT_EN_COLOR0 0x1
|
||||
#define MT8167_OVL0_MOUT_EN_WDMA0 0x2
|
||||
#define MT8167_OVL0_MOUT_EN_MASK 0x3
|
||||
|
||||
#define MT8167_DITHER_MOUT_EN_RDMA0 0x1
|
||||
#define MT8167_DITHER_MOUT_EN_UFOE 0x2
|
||||
#define MT8167_DITHER_MOUT_EN_WDMA0 0x4
|
||||
#define MT8167_DITHER_MOUT_EN_MASK 0x7
|
||||
|
||||
#define MT8167_RDMA0_SOUT_DSI0 0x2
|
||||
#define MT8167_RDMA0_SOUT_MASK 0x3
|
||||
#define MT8167_UFOE_MOUT_EN_DSI0 0x1
|
||||
#define MT8167_UFOE_MOUT_EN_DPI0 0x2
|
||||
/*
|
||||
* For some reason Android sources and the data sheet don't agree here,
|
||||
* the data sheet has UFOE_MOUT_EN_WDMA0 as 0x4 and does not mention DPI1.
|
||||
*/
|
||||
#define MT8167_UFOE_MOUT_EN_DPI1 0x4
|
||||
#define MT8167_UFOE_MOUT_EN_WDMA0 0x8
|
||||
#define MT8167_UFOE_MOUT_EN_MASK 0xF
|
||||
|
||||
#define MT8167_COLOR0_SEL_IN_RDMA0 0x0
|
||||
#define MT8167_COLOR0_SEL_IN_OVL0 0x1
|
||||
#define MT8167_COLOR0_SEL_IN_MASK 0x1
|
||||
|
||||
#define MT8167_WDMA0_SEL_IN_OVL0 0x0
|
||||
#define MT8167_WDMA0_SEL_IN_DITHER 0x1
|
||||
#define MT8167_WDMA0_SEL_IN_UFOE 0x2
|
||||
#define MT8167_WDMA0_SEL_IN_MASK 0x3
|
||||
|
||||
#define MT8167_UFOE_SEL_IN_RDMA0 0x0
|
||||
#define MT8167_UFOE_SEL_IN_DITHER 0x1
|
||||
#define MT8167_UFOE_SEL_IN_MASK 0x1
|
||||
|
||||
#define MT8167_DSI0_SEL_IN_UFOE 0x0
|
||||
#define MT8167_DSI0_SEL_IN_RDMA0 0x1
|
||||
#define MT8167_DSI0_SEL_IN_RDMA1 0x2
|
||||
#define MT8167_DSI0_SEL_IN_MASK 0x3
|
||||
|
||||
#define MT8167_DPI0_SEL_IN_UFOE 0x0
|
||||
#define MT8167_DPI0_SEL_IN_RDMA0 0x1
|
||||
#define MT8167_DPI0_SEL_IN_RDMA1 0x2
|
||||
#define MT8167_DPI0_SEL_IN_MASK 0x3
|
||||
|
||||
#define MT8167_DPI1_SEL_IN_UFOE 0x0
|
||||
#define MT8167_DPI1_SEL_IN_RDMA0 0x1
|
||||
#define MT8167_DPI1_SEL_IN_RDMA1 0x2
|
||||
#define MT8167_DPI1_SEL_IN_MASK 0x3
|
||||
|
||||
#define MT8167_RDMA0_SOUT_UFOE 0x0
|
||||
#define MT8167_RDMA0_SOUT_COLOR0 0x1
|
||||
#define MT8167_RDMA0_SOUT_DSI0 0x2
|
||||
#define MT8167_RDMA0_SOUT_DPI0 0x3
|
||||
/* DPI1 is only defined in Android sources, not in the data sheet */
|
||||
#define MT8167_RDMA0_SOUT_DPI1 0x4
|
||||
#define MT8167_RDMA0_SOUT_MASK 0x7
|
||||
|
||||
#define MT8167_RDMA1_SOUT_DSI0 0x0
|
||||
#define MT8167_RDMA1_SOUT_DPI0 0x1
|
||||
/* DPI1 is only defined in Android sources, not in the data sheet */
|
||||
#define MT8167_RDMA1_SOUT_DPI1 0x2
|
||||
#define MT8167_RDMA1_SOUT_MASK 0x3
|
||||
|
||||
static const struct mtk_mmsys_routes mt8167_mmsys_routing_table[] = {
|
||||
/* OVL0<->COLOR0 */
|
||||
MMSYS_ROUTE(OVL, 0, COLOR, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0,
|
||||
OVL0_MOUT_EN_COLOR0),
|
||||
MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, MT8167_OVL0_MOUT_EN_MASK,
|
||||
MT8167_OVL0_MOUT_EN_COLOR0),
|
||||
MMSYS_ROUTE(OVL, 0, COLOR, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, MT8167_COLOR0_SEL_IN_MASK,
|
||||
MT8167_COLOR0_SEL_IN_OVL0),
|
||||
|
||||
/* OVL0<->WDMA0 */
|
||||
MMSYS_ROUTE(OVL, 0, WDMA, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, MT8167_OVL0_MOUT_EN_MASK,
|
||||
MT8167_OVL0_MOUT_EN_WDMA0),
|
||||
MMSYS_ROUTE(OVL, 0, WDMA, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_WDMA0_SEL_IN, MT8167_COLOR0_SEL_IN_MASK,
|
||||
MT8167_WDMA0_SEL_IN_OVL0),
|
||||
|
||||
/* DITHER0 outputs */
|
||||
MMSYS_ROUTE(DITHER, 0, RDMA, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_MASK,
|
||||
MT8167_DITHER_MOUT_EN_RDMA0),
|
||||
MMSYS_ROUTE(OVL, 0, COLOR, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0,
|
||||
COLOR0_SEL_IN_OVL0),
|
||||
MMSYS_ROUTE(RDMA, 0, DSI, 0,
|
||||
MMSYS_ROUTE(DITHER, 0, UFOE, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_MASK,
|
||||
MT8167_DITHER_MOUT_EN_UFOE),
|
||||
MMSYS_ROUTE(DITHER, 0, WDMA, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_MASK,
|
||||
MT8167_DITHER_MOUT_EN_WDMA0),
|
||||
|
||||
/* UFOE<->DSI0 */
|
||||
MMSYS_ROUTE(UFOE, 0, DSI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK,
|
||||
MT8167_UFOE_MOUT_EN_DSI0),
|
||||
MMSYS_ROUTE(UFOE, 0, DSI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_MASK,
|
||||
MT8167_DSI0_SEL_IN_RDMA0),
|
||||
MT8167_DSI0_SEL_IN_UFOE),
|
||||
|
||||
/* UFOE<->DPI0 */
|
||||
MMSYS_ROUTE(UFOE, 0, DPI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK,
|
||||
MT8167_UFOE_MOUT_EN_DPI0),
|
||||
MMSYS_ROUTE(UFOE, 0, DPI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, MT8167_DPI0_SEL_IN_MASK,
|
||||
MT8167_DPI0_SEL_IN_UFOE),
|
||||
|
||||
/* UFOE<->DPI1 */
|
||||
MMSYS_ROUTE(UFOE, 0, DPI, 1,
|
||||
MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK,
|
||||
MT8167_UFOE_MOUT_EN_DPI1),
|
||||
MMSYS_ROUTE(UFOE, 0, DPI, 1,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN, MT8167_DPI1_SEL_IN_MASK,
|
||||
MT8167_DPI1_SEL_IN_UFOE),
|
||||
|
||||
/* UFOE<->WDMA0 */
|
||||
MMSYS_ROUTE(UFOE, 0, WDMA, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8167_UFOE_MOUT_EN_MASK,
|
||||
MT8167_UFOE_MOUT_EN_WDMA0),
|
||||
MMSYS_ROUTE(UFOE, 0, WDMA, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_WDMA0_SEL_IN, MT8167_WDMA0_SEL_IN_MASK,
|
||||
MT8167_WDMA0_SEL_IN_UFOE),
|
||||
|
||||
/* RDMA0<->UFOE */
|
||||
MMSYS_ROUTE(RDMA, 0, UFOE, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK,
|
||||
MT8167_RDMA0_SOUT_UFOE),
|
||||
MMSYS_ROUTE(RDMA, 0, UFOE, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_UFOE_SEL_IN, MT8167_UFOE_SEL_IN_MASK,
|
||||
MT8167_UFOE_SEL_IN_RDMA0),
|
||||
|
||||
/* RDMA0->COLOR0 */
|
||||
MMSYS_ROUTE(RDMA, 0, COLOR, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK,
|
||||
MT8167_RDMA0_SOUT_COLOR0),
|
||||
MMSYS_ROUTE(RDMA, 0, COLOR, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, MT8167_COLOR0_SEL_IN_MASK,
|
||||
MT8167_COLOR0_SEL_IN_RDMA0),
|
||||
|
||||
/* RDMA0<->DSI0 */
|
||||
MMSYS_ROUTE(RDMA, 0, DSI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK,
|
||||
MT8167_RDMA0_SOUT_DSI0),
|
||||
MMSYS_ROUTE(RDMA, 0, DSI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_MASK,
|
||||
MT8167_DSI0_SEL_IN_RDMA0),
|
||||
|
||||
/* RDMA0<->DPI0 */
|
||||
MMSYS_ROUTE(RDMA, 0, DPI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK,
|
||||
MT8167_RDMA0_SOUT_DPI0),
|
||||
MMSYS_ROUTE(RDMA, 0, DPI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, MT8167_DPI0_SEL_IN_MASK,
|
||||
MT8167_DPI0_SEL_IN_RDMA0),
|
||||
|
||||
/* RDMA0<->DPI1 */
|
||||
MMSYS_ROUTE(RDMA, 0, DPI, 1,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_MASK,
|
||||
MT8167_RDMA0_SOUT_DPI1),
|
||||
MMSYS_ROUTE(RDMA, 0, DPI, 1,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN, MT8167_DPI1_SEL_IN_MASK,
|
||||
MT8167_DPI1_SEL_IN_RDMA0),
|
||||
|
||||
/* RDMA1<->DSI0 */
|
||||
MMSYS_ROUTE(RDMA, 1, DSI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN, MT8167_RDMA1_SOUT_MASK,
|
||||
MT8167_RDMA1_SOUT_DSI0),
|
||||
MMSYS_ROUTE(RDMA, 1, DSI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_MASK,
|
||||
MT8167_DSI0_SEL_IN_RDMA1),
|
||||
|
||||
/* RDMA1<->DPI0 */
|
||||
MMSYS_ROUTE(RDMA, 1, DPI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN, MT8167_RDMA1_SOUT_MASK,
|
||||
MT8167_RDMA1_SOUT_DPI0),
|
||||
MMSYS_ROUTE(RDMA, 1, DPI, 0,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DPI0_SEL_IN, MT8167_DPI0_SEL_IN_MASK,
|
||||
MT8167_DPI0_SEL_IN_RDMA1),
|
||||
|
||||
/* RDMA1<->DPI1 */
|
||||
MMSYS_ROUTE(RDMA, 1, DPI, 1,
|
||||
MT8167_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN, MT8167_RDMA1_SOUT_MASK,
|
||||
MT8167_RDMA1_SOUT_DPI1),
|
||||
MMSYS_ROUTE(RDMA, 1, DPI, 1,
|
||||
MT8167_DISP_REG_CONFIG_DISP_DPI1_SEL_IN, MT8167_DPI1_SEL_IN_MASK,
|
||||
MT8167_DPI1_SEL_IN_RDMA1),
|
||||
};
|
||||
|
||||
#endif /* __SOC_MEDIATEK_MT8167_MMSYS_H */
|
||||
@@ -148,6 +148,7 @@ static int mediatek_regulator_coupler_init(void)
|
||||
if (!of_machine_is_compatible("mediatek,mt8183") &&
|
||||
!of_machine_is_compatible("mediatek,mt8186") &&
|
||||
!of_machine_is_compatible("mediatek,mt8188") &&
|
||||
!of_machine_is_compatible("mediatek,mt8189") &&
|
||||
!of_machine_is_compatible("mediatek,mt8192"))
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ no_flash:
|
||||
of_data = (struct mpfs_syscon_config *) device_get_match_data(dev);
|
||||
if (!of_data) {
|
||||
ret = dev_err_probe(dev, -EINVAL, "Error getting match data\n");
|
||||
goto out_free_channel;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
for (i = 0; i < of_data->nb_subdevs; i++) {
|
||||
@@ -173,8 +173,9 @@ no_flash:
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_channel:
|
||||
mbox_free_channel(sys_controller->chan);
|
||||
out_put:
|
||||
mpfs_sys_controller_put(sys_controller);
|
||||
return ret;
|
||||
out_free:
|
||||
kfree(sys_controller);
|
||||
return ret;
|
||||
|
||||
@@ -39,7 +39,6 @@ config QCOM_COMMAND_DB
|
||||
|
||||
config QCOM_GENI_SE
|
||||
tristate "Qualcomm GENI Serial Engine Driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
default ARCH_QCOM
|
||||
help
|
||||
This driver is used to manage Generic Interface (GENI) firmware based
|
||||
|
||||
+32
-43
@@ -338,29 +338,6 @@ static void apr_rxwq(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
static int apr_device_match(struct device *dev, const struct device_driver *drv)
|
||||
{
|
||||
struct apr_device *adev = to_apr_device(dev);
|
||||
const struct apr_driver *adrv = to_apr_driver(drv);
|
||||
const struct apr_device_id *id = adrv->id_table;
|
||||
|
||||
/* Attempt an OF style match first */
|
||||
if (of_driver_match_device(dev, drv))
|
||||
return 1;
|
||||
|
||||
if (!id)
|
||||
return 0;
|
||||
|
||||
while (id->domain_id != 0 || id->svc_id != 0) {
|
||||
if (id->domain_id == adev->domain_id &&
|
||||
id->svc_id == adev->svc.id)
|
||||
return 1;
|
||||
id++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apr_device_probe(struct device *dev)
|
||||
{
|
||||
struct apr_device *adev = to_apr_device(dev);
|
||||
@@ -401,7 +378,7 @@ static int apr_uevent(const struct device *dev, struct kobj_uevent_env *env)
|
||||
|
||||
const struct bus_type aprbus = {
|
||||
.name = "aprbus",
|
||||
.match = apr_device_match,
|
||||
.match = of_driver_match_device,
|
||||
.probe = apr_device_probe,
|
||||
.uevent = apr_uevent,
|
||||
.remove = apr_device_remove,
|
||||
@@ -434,31 +411,35 @@ static int apr_add_device(struct device *dev, struct device_node *np,
|
||||
if (np)
|
||||
snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np);
|
||||
|
||||
switch (apr->type) {
|
||||
case PR_TYPE_APR:
|
||||
dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
|
||||
domain_id, svc_id);
|
||||
break;
|
||||
case PR_TYPE_GPR:
|
||||
dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name,
|
||||
domain_id, svc_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
adev->dev.bus = &aprbus;
|
||||
adev->dev.parent = dev;
|
||||
adev->dev.of_node = np;
|
||||
adev->dev.release = apr_dev_release;
|
||||
adev->dev.driver = NULL;
|
||||
device_initialize(&adev->dev);
|
||||
|
||||
switch (apr->type) {
|
||||
case PR_TYPE_APR:
|
||||
ret = dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
|
||||
domain_id, svc_id);
|
||||
break;
|
||||
case PR_TYPE_GPR:
|
||||
ret = dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name,
|
||||
domain_id, svc_id);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
goto out_put_device;
|
||||
|
||||
spin_lock(&apr->svcs_lock);
|
||||
ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC);
|
||||
spin_unlock(&apr->svcs_lock);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "idr_alloc failed: %d\n", ret);
|
||||
goto out;
|
||||
goto out_put_device;
|
||||
}
|
||||
|
||||
/* Protection domain is optional, it does not exist on older platforms */
|
||||
@@ -466,18 +447,26 @@ static int apr_add_device(struct device *dev, struct device_node *np,
|
||||
1, &adev->service_path);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
dev_err(dev, "Failed to read second value of qcom,protection-domain\n");
|
||||
goto out;
|
||||
goto out_remove_idr;
|
||||
}
|
||||
|
||||
dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev));
|
||||
|
||||
ret = device_register(&adev->dev);
|
||||
ret = device_add(&adev->dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "device_register failed: %d\n", ret);
|
||||
put_device(&adev->dev);
|
||||
dev_err(dev, "device_add failed: %d\n", ret);
|
||||
goto out_remove_idr;
|
||||
}
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
out_remove_idr:
|
||||
spin_lock(&apr->svcs_lock);
|
||||
idr_remove(&apr->svcs_idr, svc_id);
|
||||
spin_unlock(&apr->svcs_lock);
|
||||
flush_workqueue(apr->rxwq);
|
||||
out_put_device:
|
||||
put_device(&adev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -626,11 +626,11 @@ static const struct llcc_slice_config glymur_data[] = {
|
||||
|
||||
static const struct llcc_slice_config ipq5424_data[] = {
|
||||
{
|
||||
.usecase_id = LLCC_CPUSS,
|
||||
.usecase_id = LLCC_PPE_RXDESC,
|
||||
.slice_id = 1,
|
||||
.max_cap = 768,
|
||||
.priority = 1,
|
||||
.bonus_ways = 0xFFFF,
|
||||
.max_cap = 128,
|
||||
.priority = 3,
|
||||
.bonus_ways = 0x0FFF,
|
||||
.retain_on_pc = true,
|
||||
.activate_on_init = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
@@ -642,12 +642,52 @@ static const struct llcc_slice_config ipq5424_data[] = {
|
||||
.vict_prio = true,
|
||||
},
|
||||
{
|
||||
.usecase_id = LLCC_VIDSC0,
|
||||
.usecase_id = LLCC_CPUSS,
|
||||
.slice_id = 2,
|
||||
.max_cap = 256,
|
||||
.priority = 2,
|
||||
.max_cap = 768,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xF000,
|
||||
.bonus_ways = 0x0FFF,
|
||||
.retain_on_pc = true,
|
||||
.activate_on_init = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.stale_en = true,
|
||||
.stale_cap_en = true,
|
||||
},
|
||||
{
|
||||
.usecase_id = LLCC_PPE_RXFILL,
|
||||
.slice_id = 5,
|
||||
.max_cap = 128,
|
||||
.priority = 3,
|
||||
.bonus_ways = 0x0FFF,
|
||||
.retain_on_pc = true,
|
||||
.activate_on_init = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.stale_en = true,
|
||||
.stale_cap_en = true,
|
||||
.alloc_oneway_en = true,
|
||||
.ovcap_en = true,
|
||||
.ovcap_prio = true,
|
||||
.vict_prio = true,
|
||||
},
|
||||
{
|
||||
.usecase_id = LLCC_WLAN_5G,
|
||||
.slice_id = 6,
|
||||
.max_cap = 128,
|
||||
.priority = 3,
|
||||
.bonus_ways = 0xC000,
|
||||
.retain_on_pc = true,
|
||||
.activate_on_init = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.stale_en = true,
|
||||
.stale_cap_en = true,
|
||||
},
|
||||
{
|
||||
.usecase_id = LLCC_WLAN_6G,
|
||||
.slice_id = 7,
|
||||
.max_cap = 128,
|
||||
.priority = 3,
|
||||
.bonus_ways = 0x3000,
|
||||
.retain_on_pc = true,
|
||||
.activate_on_init = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
@@ -1014,6 +1054,128 @@ static const struct llcc_slice_config kaanapali_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct llcc_slice_config nord_data[] = {
|
||||
{
|
||||
.usecase_id = LLCC_CPUSS,
|
||||
.slice_id = 1,
|
||||
.max_cap = 3072,
|
||||
.priority = 0,
|
||||
.bonus_ways = 0xff,
|
||||
.activate_on_init = true,
|
||||
.write_scid_en = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_CMPT,
|
||||
.slice_id = 34,
|
||||
.max_cap = 0,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_GPUHTW,
|
||||
.slice_id = 11,
|
||||
.max_cap = 512,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_GPU,
|
||||
.slice_id = 12,
|
||||
.max_cap = 2048,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.write_scid_en = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_MMUHWT,
|
||||
.slice_id = 13,
|
||||
.max_cap = 1024,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.activate_on_init = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_CAMFW,
|
||||
.slice_id = 20,
|
||||
.max_cap = 512,
|
||||
.priority = 2,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_ECC,
|
||||
.slice_id = 26,
|
||||
.max_cap = 1536,
|
||||
.priority = 3,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.activate_on_init = true,
|
||||
.write_scid_en = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_WRCACHE,
|
||||
.slice_id = 31,
|
||||
.max_cap = 2048,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.activate_on_init = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_LCPDARE,
|
||||
.slice_id = 30,
|
||||
.max_cap = 512,
|
||||
.priority = 3,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.activate_on_init = true,
|
||||
.alloc_oneway_en = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_COMPUTE1,
|
||||
.slice_id = 22,
|
||||
.max_cap = 0,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_PCIE_TCU,
|
||||
.slice_id = 15,
|
||||
.max_cap = 0,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.activate_on_init = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_GPU_LITTLE,
|
||||
.slice_id = 9,
|
||||
.max_cap = 2048,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.write_scid_en = true,
|
||||
.write_scid_cacheable_en = true,
|
||||
.vict_prio = true,
|
||||
}, {
|
||||
.usecase_id = LLCC_GPUHTW_LITTLE,
|
||||
.slice_id = 14,
|
||||
.max_cap = 512,
|
||||
.priority = 1,
|
||||
.fixed_size = true,
|
||||
.bonus_ways = 0xff,
|
||||
.vict_prio = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct llcc_slice_config sa8775p_data[] = {
|
||||
{
|
||||
.usecase_id = LLCC_CPUSS,
|
||||
@@ -4444,6 +4606,17 @@ static const struct qcom_llcc_config glymur_cfg[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config nord_cfg[] = {
|
||||
{
|
||||
.sct_data = nord_data,
|
||||
.size = ARRAY_SIZE(nord_data),
|
||||
.reg_offset = llcc_v6_reg_offset,
|
||||
.edac_reg_offset = &llcc_v6_edac_reg_offset,
|
||||
.num_banks = 16,
|
||||
.no_edac = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct qcom_llcc_config qcs615_cfg[] = {
|
||||
{
|
||||
.sct_data = qcs615_data,
|
||||
@@ -4711,6 +4884,11 @@ static const struct qcom_sct_config glymur_cfgs = {
|
||||
.num_config = ARRAY_SIZE(glymur_cfg),
|
||||
};
|
||||
|
||||
static const struct qcom_sct_config nord_cfgs = {
|
||||
.llcc_config = nord_cfg,
|
||||
.num_config = ARRAY_SIZE(nord_cfg),
|
||||
};
|
||||
|
||||
static const struct qcom_sct_config qcs615_cfgs = {
|
||||
.llcc_config = qcs615_cfg,
|
||||
.num_config = ARRAY_SIZE(qcs615_cfg),
|
||||
@@ -5617,6 +5795,10 @@ static int qcom_llcc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
drv_data->ecc_irq = platform_get_irq_optional(pdev, 0);
|
||||
if (drv_data->ecc_irq < 0 && drv_data->ecc_irq != -ENXIO)
|
||||
return dev_err_probe(&pdev->dev, drv_data->ecc_irq,
|
||||
"failed to get IRQ resource\n");
|
||||
|
||||
drv_data->edac_reg_offset = cfg->edac_reg_offset;
|
||||
drv_data->ecc_irq_configured = cfg->irq_configured;
|
||||
drv_data->dev = dev;
|
||||
@@ -5649,6 +5831,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
|
||||
{ .compatible = "qcom,hawi-llcc", .data = &hawi_sct_cfgs },
|
||||
{ .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs},
|
||||
{ .compatible = "qcom,kaanapali-llcc", .data = &kaanapali_cfgs},
|
||||
{ .compatible = "qcom,nord-llcc", .data = &nord_cfgs},
|
||||
{ .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs},
|
||||
{ .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs},
|
||||
{ .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs},
|
||||
|
||||
@@ -250,7 +250,8 @@ static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||
guard(mutex)(&__pmic_glink_lock);
|
||||
pg = __pmic_glink;
|
||||
if (!pg)
|
||||
return dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n");
|
||||
return dev_err_probe(&rpdev->dev, -EPROBE_DEFER,
|
||||
"no pmic_glink device to attach to\n");
|
||||
|
||||
dev_set_drvdata(&rpdev->dev, pg);
|
||||
pg->pdr_available = rpdev->id.driver_data;
|
||||
|
||||
@@ -451,7 +451,7 @@ static void pmic_glink_altmode_sc8180xp_notify(struct pmic_glink_altmode *altmod
|
||||
alt_port->mode = mode;
|
||||
alt_port->hpd_state = hpd_state;
|
||||
alt_port->hpd_irq = hpd_irq;
|
||||
schedule_work(&alt_port->work);
|
||||
queue_work(system_freezable_wq, &alt_port->work);
|
||||
}
|
||||
|
||||
#define SC8280XP_DPAM_MASK 0x3f
|
||||
@@ -502,7 +502,7 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod
|
||||
alt_port->tbt_data = *tbt;
|
||||
}
|
||||
|
||||
schedule_work(&alt_port->work);
|
||||
queue_work(system_freezable_wq, &alt_port->work);
|
||||
}
|
||||
|
||||
static void pmic_glink_altmode_callback(const void *data, size_t len, void *priv)
|
||||
|
||||
@@ -143,7 +143,7 @@ static void pmic_pdcharger_ulog_rpmsg_remove(struct rpmsg_device *rpdev)
|
||||
{
|
||||
struct pmic_pdcharger_ulog *pg = dev_get_drvdata(&rpdev->dev);
|
||||
|
||||
cancel_delayed_work_sync(&pg->ulog_work);
|
||||
disable_delayed_work_sync(&pg->ulog_work);
|
||||
}
|
||||
|
||||
static const struct rpmsg_device_id pmic_pdcharger_ulog_rpmsg_id_match[] = {
|
||||
|
||||
@@ -42,7 +42,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(geni_se_regs);
|
||||
*
|
||||
* GENI based QUP is a highly-flexible and programmable module for supporting
|
||||
* a wide range of serial interfaces like UART, SPI, I2C, I3C, etc. A single
|
||||
* QUP module can provide upto 8 serial interfaces, using its internal
|
||||
* QUP module can provide up to 8 serial interfaces, using its internal
|
||||
* serial engines. The actual configuration is determined by the target
|
||||
* platform configuration. The protocol supported by each interface is
|
||||
* determined by the firmware loaded to the serial engine. Each SE consists
|
||||
@@ -101,22 +101,26 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(geni_se_regs);
|
||||
* @base: Base address of this instance of QUP wrapper core
|
||||
* @clks: Handle to the primary & optional secondary AHB clocks
|
||||
* @num_clks: Count of clocks
|
||||
* @prog_ram_depth: Available CFG RAM depth for instance without SE_HW_PARAM_2
|
||||
*/
|
||||
struct geni_wrapper {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk_bulk_data clks[MAX_CLKS];
|
||||
unsigned int num_clks;
|
||||
unsigned int prog_ram_depth;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct geni_se_desc - Data structure to represent the QUP Wrapper resources
|
||||
* @clks: Name of the primary & optional secondary AHB clocks
|
||||
* @num_clks: Count of clock names
|
||||
* @prog_ram_depth: Available CFG RAM depth for instance without SE_HW_PARAM_2
|
||||
*/
|
||||
struct geni_se_desc {
|
||||
unsigned int num_clks;
|
||||
const char * const *clks;
|
||||
unsigned int prog_ram_depth;
|
||||
};
|
||||
|
||||
static const char * const icc_path_names[] = {"qup-core", "qup-config",
|
||||
@@ -920,7 +924,7 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(geni_se_rx_dma_unprep);
|
||||
|
||||
int geni_icc_get(struct geni_se *se, const char *icc_ddr)
|
||||
int geni_icc_get(struct geni_se *se)
|
||||
{
|
||||
struct geni_icc_path *icc_paths = se->icc_paths;
|
||||
|
||||
@@ -1217,7 +1221,7 @@ int geni_se_resources_init(struct geni_se *se)
|
||||
|
||||
se->has_opp = (ret == 0);
|
||||
|
||||
ret = geni_icc_get(se, "qup-memory");
|
||||
ret = geni_icc_get(se);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1230,25 +1234,29 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init);
|
||||
* @se: Pointer to the serial engine structure.
|
||||
* @fw: Pointer to the firmware image.
|
||||
* @protocol: Expected serial engine protocol type.
|
||||
* @fw_size_out: Non-NULL output parameter; receives the rounded, validated
|
||||
* firmware word count on success.
|
||||
*
|
||||
* Identifies the appropriate firmware image or configuration required for a
|
||||
* specific communication protocol instance running on a Qualcomm GENI
|
||||
* controller. Validates the firmware size against the hardware PROG_RAM_DEPTH
|
||||
* read from SE_HW_PARAM_2.
|
||||
*
|
||||
* Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise.
|
||||
* Return: pointer to a valid 'const struct se_fw_hdr' if found, or NULL otherwise.
|
||||
*/
|
||||
static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw,
|
||||
enum geni_se_protocol_type protocol)
|
||||
static const struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw,
|
||||
enum geni_se_protocol_type protocol,
|
||||
u32 *fw_size_out)
|
||||
{
|
||||
struct geni_wrapper *wrapper = se->wrapper;
|
||||
struct device *dev = se->dev;
|
||||
const struct elf32_hdr *ehdr;
|
||||
const struct elf32_phdr *phdrs;
|
||||
const struct elf32_phdr *phdr;
|
||||
struct se_fw_hdr *sefw;
|
||||
const struct se_fw_hdr *sefw;
|
||||
u32 fw_end, cfg_idx_end, cfg_val_end;
|
||||
u32 prog_ram_depth;
|
||||
u16 fw_size;
|
||||
u32 fw_size;
|
||||
int i;
|
||||
|
||||
if (!fw || fw->size < sizeof(struct elf32_hdr))
|
||||
@@ -1287,27 +1295,29 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct
|
||||
if (phdr->p_filesz < sizeof(struct se_fw_hdr))
|
||||
continue;
|
||||
|
||||
sefw = (struct se_fw_hdr *)(fw->data + phdr->p_offset);
|
||||
sefw = (const struct se_fw_hdr *)(fw->data + phdr->p_offset);
|
||||
fw_size = le16_to_cpu(sefw->fw_size_in_items);
|
||||
|
||||
if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1)
|
||||
continue;
|
||||
|
||||
if (le16_to_cpu(sefw->serial_protocol) != protocol)
|
||||
continue;
|
||||
|
||||
if (fw_size % 2 != 0)
|
||||
fw_size++;
|
||||
|
||||
fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32);
|
||||
cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) +
|
||||
le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u8);
|
||||
cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) +
|
||||
le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32);
|
||||
|
||||
if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1)
|
||||
continue;
|
||||
|
||||
if (le32_to_cpu(sefw->serial_protocol) != protocol)
|
||||
continue;
|
||||
|
||||
if (fw_size % 2 != 0) {
|
||||
fw_size++;
|
||||
sefw->fw_size_in_items = cpu_to_le16(fw_size);
|
||||
}
|
||||
|
||||
prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK,
|
||||
readl_relaxed(se->base + SE_HW_PARAM_2));
|
||||
if (wrapper->prog_ram_depth)
|
||||
prog_ram_depth = wrapper->prog_ram_depth;
|
||||
else
|
||||
prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK,
|
||||
readl_relaxed(se->base + SE_HW_PARAM_2));
|
||||
if (fw_size >= prog_ram_depth) {
|
||||
dev_err(dev, "Firmware size (%u) exceeds RAM size (%u)\n",
|
||||
fw_size, prog_ram_depth);
|
||||
@@ -1320,6 +1330,7 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct
|
||||
continue;
|
||||
}
|
||||
|
||||
*fw_size_out = fw_size;
|
||||
return sefw;
|
||||
}
|
||||
|
||||
@@ -1430,17 +1441,17 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw,
|
||||
{
|
||||
const u32 *fw_data, *cfg_val_arr;
|
||||
const u8 *cfg_idx_arr;
|
||||
u32 i, reg_value;
|
||||
u32 i, reg_value, fw_size_in_items;
|
||||
int ret;
|
||||
struct se_fw_hdr *hdr;
|
||||
const struct se_fw_hdr *hdr;
|
||||
|
||||
hdr = geni_find_protocol_fw(se, fw, protocol);
|
||||
hdr = geni_find_protocol_fw(se, fw, protocol, &fw_size_in_items);
|
||||
if (!hdr)
|
||||
return -EINVAL;
|
||||
|
||||
fw_data = (const u32 *)((u8 *)hdr + le16_to_cpu(hdr->fw_offset));
|
||||
fw_data = (const u32 *)((const u8 *)hdr + le16_to_cpu(hdr->fw_offset));
|
||||
cfg_idx_arr = (const u8 *)hdr + le16_to_cpu(hdr->cfg_idx_offset);
|
||||
cfg_val_arr = (const u32 *)((u8 *)hdr + le16_to_cpu(hdr->cfg_val_offset));
|
||||
cfg_val_arr = (const u32 *)((const u8 *)hdr + le16_to_cpu(hdr->cfg_val_offset));
|
||||
|
||||
ret = geni_icc_set_bw(se);
|
||||
if (ret)
|
||||
@@ -1511,7 +1522,7 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw,
|
||||
|
||||
/* Program RAM address space. */
|
||||
memcpy_toio(se->base + SE_GENI_CFG_RAMN, fw_data,
|
||||
le16_to_cpu(hdr->fw_size_in_items) * sizeof(u32));
|
||||
fw_size_in_items * sizeof(u32));
|
||||
|
||||
/* Put default values on GENI's output pads. */
|
||||
writel_relaxed(0x1, se->base + GENI_FORCE_DEFAULT_REG);
|
||||
@@ -1617,6 +1628,7 @@ static int geni_se_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(wrapper->base);
|
||||
|
||||
desc = device_get_match_data(&pdev->dev);
|
||||
wrapper->prog_ram_depth = desc->prog_ram_depth;
|
||||
|
||||
if (!has_acpi_companion(&pdev->dev) && desc->num_clks) {
|
||||
int i;
|
||||
@@ -1669,6 +1681,7 @@ static const char * const i2c_master_hub_clks[] = {
|
||||
static const struct geni_se_desc i2c_master_hub_desc = {
|
||||
.clks = i2c_master_hub_clks,
|
||||
.num_clks = ARRAY_SIZE(i2c_master_hub_clks),
|
||||
.prog_ram_depth = 1020,
|
||||
};
|
||||
|
||||
static const struct of_device_id geni_se_dt_match[] = {
|
||||
|
||||
@@ -602,10 +602,8 @@ static int qmp_probe(struct platform_device *pdev)
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
ret = devm_request_irq(&pdev->dev, irq, qmp_intr, 0,
|
||||
"aoss-qmp", qmp);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to request interrupt\n");
|
||||
if (ret < 0)
|
||||
goto err_free_mbox;
|
||||
}
|
||||
|
||||
ret = qmp_open(qmp);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -371,6 +371,14 @@ static const struct stats_config rpm_data_dba0 = {
|
||||
.subsystem_stats_in_smem = false,
|
||||
};
|
||||
|
||||
static const struct stats_config rpm_data_shikra = {
|
||||
.stats_offset = 0,
|
||||
.num_records = 2,
|
||||
.appended_stats_avail = true,
|
||||
.dynamic_offset = true,
|
||||
.subsystem_stats_in_smem = true,
|
||||
};
|
||||
|
||||
static const struct stats_config rpmh_data_sdm845 = {
|
||||
.stats_offset = 0x48,
|
||||
.num_records = 2,
|
||||
@@ -396,6 +404,7 @@ static const struct of_device_id qcom_stats_table[] = {
|
||||
{ .compatible = "qcom,rpm-stats", .data = &rpm_data },
|
||||
{ .compatible = "qcom,rpmh-stats", .data = &rpmh_data },
|
||||
{ .compatible = "qcom,sdm845-rpmh-stats", .data = &rpmh_data_sdm845 },
|
||||
{ .compatible = "qcom,shikra-rpm-stats", .data = &rpm_data_shikra },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_stats_table);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
struct rsc_drv;
|
||||
|
||||
/**
|
||||
* struct tcs_group: group of Trigger Command Sets (TCS) to send state requests
|
||||
* struct tcs_group - group of Trigger Command Sets (TCS) to send state requests
|
||||
* to the controller
|
||||
*
|
||||
* @drv: The controller.
|
||||
@@ -53,7 +53,7 @@ struct tcs_group {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rpmh_request: the message to be sent to rpmh-rsc
|
||||
* struct rpmh_request - the message to be sent to rpmh-rsc
|
||||
*
|
||||
* @msg: the request
|
||||
* @cmd: the payload that will be part of the @msg
|
||||
@@ -70,7 +70,7 @@ struct rpmh_request {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rpmh_ctrlr: our representation of the controller
|
||||
* struct rpmh_ctrlr - our representation of the controller
|
||||
*
|
||||
* @cache: the list of cached requests
|
||||
* @cache_lock: synchronize access to the cache data
|
||||
@@ -84,13 +84,19 @@ struct rpmh_ctrlr {
|
||||
struct list_head batch_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rsc_ver - Hardware version of the RSC controller.
|
||||
*
|
||||
* @major: Major version number.
|
||||
* @minor: Minor version number.
|
||||
*/
|
||||
struct rsc_ver {
|
||||
u32 major;
|
||||
u32 minor;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rsc_drv: the Direct Resource Voter (DRV) of the
|
||||
* struct rsc_drv - the Direct Resource Voter (DRV) of the
|
||||
* Resource State Coordinator controller (RSC)
|
||||
*
|
||||
* @name: Controller identifier.
|
||||
@@ -116,6 +122,8 @@ struct rsc_ver {
|
||||
* slot
|
||||
* @client: Handle to the DRV's client.
|
||||
* @dev: RSC device.
|
||||
* @ver: HW version of the RSC controller.
|
||||
* @regs: Pointer to the register offset table for this version.
|
||||
*/
|
||||
struct rsc_drv {
|
||||
const char *name;
|
||||
|
||||
@@ -842,7 +842,7 @@ exit:
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_rsc_cpu_pm_callback() - Check if any of the AMCs are busy.
|
||||
* rpmh_rsc_cpu_pm_callback() - CPU PM notifier to flush sleep/wake TCS data.
|
||||
* @nfb: Pointer to the notifier block in struct rsc_drv.
|
||||
* @action: CPU_PM_ENTER, CPU_PM_ENTER_FAILED, or CPU_PM_EXIT.
|
||||
* @v: Unused
|
||||
@@ -923,7 +923,7 @@ static int rpmh_rsc_cpu_pm_callback(struct notifier_block *nfb,
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_rsc_pd_callback() - Check if any of the AMCs are busy.
|
||||
* rpmh_rsc_pd_callback() - PM domain callback to flush sleep/wake TCS data.
|
||||
* @nfb: Pointer to the genpd notifier block in struct rsc_drv.
|
||||
* @action: GENPD_NOTIFY_PRE_OFF, GENPD_NOTIFY_OFF, GENPD_NOTIFY_PRE_ON or GENPD_NOTIFY_ON.
|
||||
* @v: Unused
|
||||
|
||||
+28
-12
@@ -41,7 +41,7 @@
|
||||
#define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
|
||||
|
||||
/**
|
||||
* struct cache_req: the request object for caching
|
||||
* struct cache_req - the request object for caching
|
||||
*
|
||||
* @addr: the address of the resource
|
||||
* @sleep_val: the sleep vote
|
||||
@@ -56,7 +56,7 @@ struct cache_req {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct batch_cache_req - An entry in our batch catch
|
||||
* struct batch_cache_req - An entry in our batch cache
|
||||
*
|
||||
* @list: linked list obj
|
||||
* @count: number of messages
|
||||
@@ -76,6 +76,14 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
|
||||
return &drv->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_tx_done() - Signal the completion of a RPMH transfer.
|
||||
* @msg: The request that was previously sent.
|
||||
*
|
||||
* Called by the RSC driver when an active-only transfer is complete.
|
||||
* Signals any blocking waiter and frees the message if it was dynamically
|
||||
* allocated.
|
||||
*/
|
||||
void rpmh_tx_done(const struct tcs_request *msg)
|
||||
{
|
||||
struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
|
||||
@@ -157,7 +165,7 @@ unlock:
|
||||
}
|
||||
|
||||
/**
|
||||
* __rpmh_write: Cache and send the RPMH request
|
||||
* __rpmh_write() - Cache and send the RPMH request.
|
||||
*
|
||||
* @dev: The device making the request
|
||||
* @state: Active/Sleep request type
|
||||
@@ -166,6 +174,8 @@ unlock:
|
||||
* Cache the RPMH request and send if the state is ACTIVE_ONLY.
|
||||
* SLEEP/WAKE_ONLY requests are not sent to the controller at
|
||||
* this time. Use rpmh_flush() to send them to the controller.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
static int __rpmh_write(const struct device *dev, enum rpmh_state state,
|
||||
struct rpmh_request *rpm_msg)
|
||||
@@ -248,7 +258,7 @@ int rpmh_read(const struct device *dev, struct tcs_cmd *cmd)
|
||||
EXPORT_SYMBOL_GPL(rpmh_read);
|
||||
|
||||
/**
|
||||
* rpmh_write_async: Write a set of RPMH commands
|
||||
* rpmh_write_async() - Write a set of RPMH commands.
|
||||
*
|
||||
* @dev: The device making the request
|
||||
* @state: Active/sleep set
|
||||
@@ -257,6 +267,8 @@ EXPORT_SYMBOL_GPL(rpmh_read);
|
||||
*
|
||||
* Write a set of RPMH commands, the order of commands is maintained
|
||||
* and will be sent as a single shot.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int rpmh_write_async(const struct device *dev, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, u32 n)
|
||||
@@ -280,7 +292,7 @@ int rpmh_write_async(const struct device *dev, enum rpmh_state state,
|
||||
EXPORT_SYMBOL_GPL(rpmh_write_async);
|
||||
|
||||
/**
|
||||
* rpmh_write: Write a set of RPMH commands and block until response
|
||||
* rpmh_write() - Write a set of RPMH commands and block until response
|
||||
*
|
||||
* @dev: The device making the request
|
||||
* @state: Active/sleep set
|
||||
@@ -288,6 +300,8 @@ EXPORT_SYMBOL_GPL(rpmh_write_async);
|
||||
* @n: The number of elements in @cmd
|
||||
*
|
||||
* May sleep. Do not call from atomic contexts.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int rpmh_write(const struct device *dev, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, u32 n)
|
||||
@@ -342,7 +356,7 @@ static int flush_batch(struct rpmh_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_write_batch: Write multiple sets of RPMH commands and wait for the
|
||||
* rpmh_write_batch() - Write multiple sets of RPMH commands and wait for the
|
||||
* batch to finish.
|
||||
*
|
||||
* @dev: the device making the request
|
||||
@@ -350,13 +364,15 @@ static int flush_batch(struct rpmh_ctrlr *ctrlr)
|
||||
* @cmd: The payload data
|
||||
* @n: The array of count of elements in each batch, 0 terminated.
|
||||
*
|
||||
* Write a request to the RSC controller without caching. If the request
|
||||
* state is ACTIVE, then the requests are treated as completion request
|
||||
* and sent to the controller immediately. The function waits until all the
|
||||
* commands are complete. If the request was to SLEEP or WAKE_ONLY, then the
|
||||
* request is sent as fire-n-forget and no ack is expected.
|
||||
* If the request state is ACTIVE_ONLY, the requests are sent to the
|
||||
* controller immediately and the function waits until all commands are
|
||||
* complete. If the state is SLEEP or WAKE_ONLY, the requests are cached
|
||||
* and the function returns immediately; they are sent to the controller
|
||||
* later by rpmh_flush().
|
||||
*
|
||||
* May sleep. Do not call from atomic contexts for ACTIVE_ONLY requests.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, u32 *n)
|
||||
@@ -519,7 +535,7 @@ exit:
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_invalidate: Invalidate sleep and wake sets in batch_cache
|
||||
* rpmh_invalidate() - Invalidate sleep and wake sets in batch_cache
|
||||
*
|
||||
* @dev: The device making the request
|
||||
*
|
||||
|
||||
@@ -20,12 +20,22 @@
|
||||
#define MAX_DDR_FREQ_NUM_V5 14
|
||||
|
||||
#define MAX_CHAN_NUM 8
|
||||
#define MAX_CHAN_NUM_V7_GLYMUR 16
|
||||
#define MAX_RANK_NUM 2
|
||||
|
||||
#define DDR_HBB_MIN 13
|
||||
#define DDR_HBB_MAX 19
|
||||
|
||||
#define MAX_SHUB_ENTRIES 8
|
||||
#define MAX_SHUB_ENTRIES_V7_GLYMUR 10
|
||||
#define MAX_DDR_REGIONS_V7_GLYMUR 4
|
||||
|
||||
/*
|
||||
* Glymur's DRAM information entry has 256 bytes of trailing zeroes
|
||||
* after its DDR details, four region slots, 10-entry SHUB frequency
|
||||
* plan, and v6 misc information.
|
||||
*/
|
||||
#define DDR_V7_GLYMUR_RESERVED_SIZE 256
|
||||
|
||||
static struct smem_dram *__dram;
|
||||
|
||||
@@ -39,6 +49,7 @@ enum ddr_info_version {
|
||||
INFO_V6, /* INFO_V6 seems to only have shipped with 6 DDR regions, unlike V7 */
|
||||
INFO_V7,
|
||||
INFO_V7_WITH_6_REGIONS,
|
||||
INFO_V7_GLYMUR,
|
||||
};
|
||||
|
||||
struct smem_dram {
|
||||
@@ -188,6 +199,37 @@ struct ddr_details_v7 {
|
||||
struct ddr_regions_v5 ddr_regions;
|
||||
};
|
||||
|
||||
struct ddr_regions_v7_glymur {
|
||||
__le32 ddr_region_num;
|
||||
__le64 ddr_rank0_size;
|
||||
__le64 ddr_rank1_size;
|
||||
__le64 ddr_cs0_start_addr;
|
||||
__le64 ddr_cs1_start_addr;
|
||||
__le32 highest_bank_addr_bit;
|
||||
struct ddr_region_v5 ddr_region[MAX_DDR_REGIONS_V7_GLYMUR];
|
||||
};
|
||||
|
||||
struct ddr_details_v7_glymur {
|
||||
u8 manufacturer_id;
|
||||
u8 device_type;
|
||||
struct ddr_part_details ddr_params[MAX_CHAN_NUM_V7_GLYMUR];
|
||||
struct ddr_freq_plan_v5 ddr_freq_tbl;
|
||||
u8 num_channels;
|
||||
u8 sct_config;
|
||||
struct ddr_regions_v7_glymur ddr_regions;
|
||||
};
|
||||
|
||||
struct shub_freq_plan_entry_v7_glymur {
|
||||
u8 num_shub_freqs;
|
||||
struct shub_freq_table shub_freq[MAX_SHUB_ENTRIES_V7_GLYMUR];
|
||||
};
|
||||
|
||||
struct ddr_v7_glymur_tail {
|
||||
struct shub_freq_plan_entry_v7_glymur shub_freq_plan;
|
||||
struct ddr_misc_info_v6 misc_info;
|
||||
u8 reserved[DDR_V7_GLYMUR_RESERVED_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* qcom_smem_dram_get_hbb(): Get the Highest bank address bit
|
||||
*
|
||||
@@ -219,7 +261,7 @@ static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data)
|
||||
|
||||
if (freq_entry->freq_khz && freq_entry->enabled) {
|
||||
u32 freq_khz = le32_to_cpu(freq_entry->freq_khz);
|
||||
dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz;
|
||||
dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,8 +273,11 @@ static void smem_dram_parse_v3_14freqs_data(struct smem_dram *dram, void *data)
|
||||
for (int i = 0; i < MAX_DDR_FREQ_NUM_V3 + 1; i++) {
|
||||
struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
|
||||
|
||||
if (freq_entry->freq_khz && freq_entry->enabled)
|
||||
dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
|
||||
if (freq_entry->freq_khz && freq_entry->enabled) {
|
||||
u32 freq_khz = le32_to_cpu(freq_entry->freq_khz);
|
||||
|
||||
dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +293,7 @@ static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data)
|
||||
|
||||
if (freq_entry->freq_khz && freq_entry->enabled) {
|
||||
u32 freq_khz = le32_to_cpu(freq_entry->freq_khz);
|
||||
dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz;
|
||||
dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,7 +310,7 @@ static void smem_dram_parse_v5_data(struct smem_dram *dram, void *data)
|
||||
|
||||
if (freq_entry->freq_khz && freq_entry->enabled) {
|
||||
u32 freq_khz = le32_to_cpu(freq_entry->freq_khz);
|
||||
dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz;
|
||||
dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,6 +327,23 @@ static void smem_dram_parse_v7_data(struct smem_dram *dram, void *data)
|
||||
|
||||
if (freq_entry->freq_khz && freq_entry->enabled) {
|
||||
u32 freq_khz = le32_to_cpu(freq_entry->freq_khz);
|
||||
dram->frequencies[dram->num_frequencies++] = 1000UL * freq_khz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void smem_dram_parse_v7_glymur_data(struct smem_dram *dram, void *data)
|
||||
{
|
||||
struct ddr_details_v7_glymur *details = data;
|
||||
|
||||
dram->hbb = le32_to_cpu(details->ddr_regions.highest_bank_addr_bit);
|
||||
|
||||
for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) {
|
||||
struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
|
||||
|
||||
if (freq_entry->freq_khz && freq_entry->enabled) {
|
||||
u32 freq_khz = le32_to_cpu(freq_entry->freq_khz);
|
||||
|
||||
dram->frequencies[dram->num_frequencies++] = 1000 * freq_khz;
|
||||
}
|
||||
}
|
||||
@@ -341,6 +403,10 @@ static int smem_dram_infer_struct_version(size_t size)
|
||||
sizeof(struct shub_freq_plan_entry))
|
||||
return INFO_V7_WITH_6_REGIONS;
|
||||
|
||||
if (size == sizeof(struct ddr_details_v7_glymur) +
|
||||
sizeof(struct ddr_v7_glymur_tail))
|
||||
return INFO_V7_GLYMUR;
|
||||
|
||||
return INFO_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -382,7 +448,7 @@ struct dentry *smem_dram_parse(struct qcom_smem *smem, struct device *dev)
|
||||
return ERR_PTR(-ENODATA);
|
||||
|
||||
ver = smem_dram_infer_struct_version(actual_size);
|
||||
if (ver < 0) {
|
||||
if ((int)ver < 0) {
|
||||
/* Some SoCs don't provide data that's useful for us */
|
||||
return ERR_PTR(-ENODATA);
|
||||
} else if (ver == INFO_UNKNOWN) {
|
||||
@@ -415,6 +481,9 @@ struct dentry *smem_dram_parse(struct qcom_smem *smem, struct device *dev)
|
||||
case INFO_V7_WITH_6_REGIONS:
|
||||
smem_dram_parse_v7_data(dram, data);
|
||||
break;
|
||||
case INFO_V7_GLYMUR:
|
||||
smem_dram_parse_v7_glymur_data(dram, data);
|
||||
break;
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ struct smp2p_entry {
|
||||
struct qcom_smp2p *smp2p;
|
||||
|
||||
const char *name;
|
||||
u32 *value;
|
||||
u32 __iomem *value;
|
||||
u32 last_value;
|
||||
|
||||
struct irq_domain *domain;
|
||||
@@ -276,7 +276,7 @@ static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p)
|
||||
list_for_each_entry(entry, &smp2p->inbound, node) {
|
||||
memcpy(buf, in->entries[i].name, sizeof(buf));
|
||||
if (!strcmp(buf, entry->name)) {
|
||||
entry->value = &in->entries[i].value;
|
||||
entry->value = (u32 __iomem *)&in->entries[i].value;
|
||||
entry->last_value = readl(entry->value);
|
||||
break;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
|
||||
list_for_each_entry(entry, &smp2p->inbound, node) {
|
||||
memcpy(buf, in->entries[i].name, sizeof(buf));
|
||||
if (!strcmp(buf, entry->name)) {
|
||||
entry->value = &in->entries[i].value;
|
||||
entry->value = (u32 __iomem *)&in->entries[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -411,15 +411,9 @@ static int smp2p_set_irq_type(struct irq_data *irqd, unsigned int type)
|
||||
if (!(type & IRQ_TYPE_EDGE_BOTH))
|
||||
return -EINVAL;
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
set_bit(irq, entry->irq_rising);
|
||||
else
|
||||
clear_bit(irq, entry->irq_rising);
|
||||
assign_bit(irq, entry->irq_rising, type & IRQ_TYPE_EDGE_RISING);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
set_bit(irq, entry->irq_falling);
|
||||
else
|
||||
clear_bit(irq, entry->irq_falling);
|
||||
assign_bit(irq, entry->irq_falling, type & IRQ_TYPE_EDGE_FALLING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -528,7 +522,7 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p,
|
||||
memcpy(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME);
|
||||
|
||||
/* Make the logical entry reference the physical value */
|
||||
entry->value = &out->entries[out->valid_entries].value;
|
||||
entry->value = (u32 __iomem *)&out->entries[out->valid_entries].value;
|
||||
|
||||
out->valid_entries++;
|
||||
|
||||
@@ -720,10 +714,8 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
|
||||
NULL, qcom_smp2p_intr,
|
||||
IRQF_ONESHOT,
|
||||
NULL, (void *)smp2p);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request interrupt\n");
|
||||
if (ret)
|
||||
goto unwind_interfaces;
|
||||
}
|
||||
|
||||
/*
|
||||
* Treat smp2p interrupt as wakeup source, but keep it disabled
|
||||
|
||||
+13
-23
@@ -82,8 +82,8 @@ struct qcom_smsm {
|
||||
u32 num_hosts;
|
||||
u32 num_entries;
|
||||
|
||||
u32 *local_state;
|
||||
u32 *subscription;
|
||||
u32 __iomem *local_state;
|
||||
u32 __iomem *subscription;
|
||||
struct qcom_smem_state *state;
|
||||
|
||||
spinlock_t lock;
|
||||
@@ -115,8 +115,8 @@ struct smsm_entry {
|
||||
DECLARE_BITMAP(irq_falling, 32);
|
||||
unsigned long last_value;
|
||||
|
||||
u32 *remote_state;
|
||||
u32 *subscription;
|
||||
u32 __iomem *remote_state;
|
||||
u32 __iomem *subscription;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -277,10 +277,8 @@ static void smsm_unmask_irq(struct irq_data *irqd)
|
||||
u32 val;
|
||||
|
||||
/* Make sure our last cached state is up-to-date */
|
||||
if (readl(entry->remote_state) & BIT(irq))
|
||||
set_bit(irq, &entry->last_value);
|
||||
else
|
||||
clear_bit(irq, &entry->last_value);
|
||||
assign_bit(irq, &entry->last_value,
|
||||
readl(entry->remote_state) & BIT(irq));
|
||||
|
||||
set_bit(irq, entry->irq_enabled);
|
||||
|
||||
@@ -304,15 +302,9 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type)
|
||||
if (!(type & IRQ_TYPE_EDGE_BOTH))
|
||||
return -EINVAL;
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
set_bit(irq, entry->irq_rising);
|
||||
else
|
||||
clear_bit(irq, entry->irq_rising);
|
||||
assign_bit(irq, entry->irq_rising, type & IRQ_TYPE_EDGE_RISING);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
set_bit(irq, entry->irq_falling);
|
||||
else
|
||||
clear_bit(irq, entry->irq_falling);
|
||||
assign_bit(irq, entry->irq_falling, type & IRQ_TYPE_EDGE_FALLING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -451,10 +443,8 @@ static int smsm_inbound_entry(struct qcom_smsm *smsm,
|
||||
NULL, smsm_intr,
|
||||
IRQF_ONESHOT,
|
||||
"smsm", (void *)entry);
|
||||
if (ret) {
|
||||
dev_err(smsm->dev, "failed to request interrupt\n");
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smsm_irq_ops, entry);
|
||||
if (!entry->domain) {
|
||||
@@ -513,9 +503,9 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||
struct device_node *node;
|
||||
struct smsm_entry *entry;
|
||||
struct qcom_smsm *smsm;
|
||||
u32 *intr_mask;
|
||||
u32 __iomem *intr_mask;
|
||||
size_t size;
|
||||
u32 *states;
|
||||
u32 __iomem *states;
|
||||
u32 id;
|
||||
int ret;
|
||||
|
||||
@@ -579,7 +569,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL);
|
||||
states = (u32 __iomem *)qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL);
|
||||
if (IS_ERR(states)) {
|
||||
dev_err(&pdev->dev, "Unable to acquire shared state entry\n");
|
||||
ret = PTR_ERR(states);
|
||||
@@ -594,7 +584,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL);
|
||||
intr_mask = (u32 __iomem *)qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL);
|
||||
if (IS_ERR(intr_mask)) {
|
||||
dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n");
|
||||
ret = PTR_ERR(intr_mask);
|
||||
|
||||
@@ -450,6 +450,7 @@ static const struct soc_id soc_id[] = {
|
||||
{ qcom_board_id(IPQ8172) },
|
||||
{ qcom_board_id(IPQ8173) },
|
||||
{ qcom_board_id(IPQ8174) },
|
||||
{ qcom_board_id(SM7250) },
|
||||
{ qcom_board_id(IPQ6018) },
|
||||
{ qcom_board_id(IPQ6028) },
|
||||
{ qcom_board_id(SDM429W) },
|
||||
@@ -541,8 +542,10 @@ static const struct soc_id soc_id[] = {
|
||||
{ qcom_board_id(QCS9075) },
|
||||
{ qcom_board_id(QCS615) },
|
||||
{ qcom_board_id(SA8797P) },
|
||||
{ qcom_board_id(SM8975) },
|
||||
{ qcom_board_id(CQ7790M) },
|
||||
{ qcom_board_id(CQ7790S) },
|
||||
{ qcom_board_id(SM8950) },
|
||||
{ qcom_board_id(CQ2390M) },
|
||||
{ qcom_board_id(CQ2390S) },
|
||||
{ qcom_board_id(IQ2390S) },
|
||||
|
||||
@@ -105,6 +105,13 @@ static const struct qcom_ubwc_cfg_data milos_data = {
|
||||
.highest_bank_bit = 15,
|
||||
};
|
||||
|
||||
static const struct qcom_ubwc_cfg_data ubwc_7_0_hbb16 = {
|
||||
.ubwc_enc_version = UBWC_7_0,
|
||||
.flags = UBWC_SWIZZLE_ENABLE_LVL2 |
|
||||
UBWC_SWIZZLE_ENABLE_LVL3,
|
||||
.highest_bank_bit = 16,
|
||||
};
|
||||
|
||||
static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = {
|
||||
{ .compatible = "qcom,apq8016", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,apq8026", .data = &no_ubwc_data },
|
||||
@@ -112,8 +119,11 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = {
|
||||
{ .compatible = "qcom,apq8096", .data = &ubwc_1_0_hbb15 },
|
||||
{ .compatible = "qcom,eliza", .data = &ubwc_5_0_hbb15 },
|
||||
{ .compatible = "qcom,glymur", .data = &glymur_data},
|
||||
{ .compatible = "qcom,hawi", .data = &ubwc_7_0_hbb16 },
|
||||
{ .compatible = "qcom,kaanapali", .data = &ubwc_6_0_hbb16 },
|
||||
{ .compatible = "qcom,kalambo", .data = &glymur_data },
|
||||
{ .compatible = "qcom,mahua", .data = &glymur_data },
|
||||
{ .compatible = "qcom,maili", .data = &ubwc_7_0_hbb16, },
|
||||
{ .compatible = "qcom,milos", .data = &milos_data },
|
||||
{ .compatible = "qcom,msm8226", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8916", .data = &no_ubwc_data },
|
||||
@@ -121,12 +131,14 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = {
|
||||
{ .compatible = "qcom,msm8937", .data = &ubwc_1_0_hbb14 },
|
||||
{ .compatible = "qcom,msm8929", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8939", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8952", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8953", .data = &ubwc_1_0_hbb14 },
|
||||
{ .compatible = "qcom,msm8956", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8974", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8976", .data = &no_ubwc_data },
|
||||
{ .compatible = "qcom,msm8996", .data = &ubwc_1_0_hbb15 },
|
||||
{ .compatible = "qcom,msm8998", .data = &ubwc_1_0_hbb15 },
|
||||
{ .compatible = "qcom,nord", .data = &glymur_data },
|
||||
{ .compatible = "qcom,qcm2290", .data = &ubwc_0_0_hbb15, },
|
||||
{ .compatible = "qcom,qcm6490", .data = &ubwc_3_1_hbb14, },
|
||||
{ .compatible = "qcom,qcs8300", .data = &ubwc_4_0_hbb16, },
|
||||
|
||||
@@ -227,6 +227,14 @@ config ARCH_R8A774A1
|
||||
help
|
||||
This enables support for the Renesas RZ/G2M SoC.
|
||||
|
||||
config ARCH_R8A774A3
|
||||
bool "ARM64 Platform support for R8A774A3 (RZ/G2M v3.0)"
|
||||
default y if ARCH_RENESAS
|
||||
select ARCH_RCAR_GEN3
|
||||
select SYSC_R8A774A3
|
||||
help
|
||||
This enables support for the Renesas RZ/G2M SoC (version 3.0).
|
||||
|
||||
config ARCH_R8A774B1
|
||||
bool "ARM64 Platform support for R8A774B1 (RZ/G2N)"
|
||||
default y if ARCH_RENESAS
|
||||
@@ -410,6 +418,7 @@ config ARCH_R9A09G011
|
||||
config ARCH_R9A09G047
|
||||
bool "ARM64 Platform support for R9A09G047 (RZ/G3E)"
|
||||
default y if ARCH_RENESAS
|
||||
select RENESAS_RZV2H_ICU
|
||||
select SYS_R9A09G047
|
||||
help
|
||||
This enables support for the Renesas RZ/G3E SoC variants.
|
||||
@@ -417,6 +426,7 @@ config ARCH_R9A09G047
|
||||
config ARCH_R9A09G056
|
||||
bool "ARM64 Platform support for R9A09G056 (RZ/V2N)"
|
||||
default y if ARCH_RENESAS
|
||||
select RENESAS_RZV2H_ICU
|
||||
select SYS_R9A09G056
|
||||
help
|
||||
This enables support for the Renesas RZ/V2N SoC variants.
|
||||
@@ -468,11 +478,12 @@ endif # RISCV
|
||||
config RCAR_MFIS
|
||||
tristate "Renesas R-Car MFIS driver"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
depends on MAILBOX
|
||||
depends on MAILBOX && HWSPINLOCK
|
||||
help
|
||||
Select this option to enable the Renesas R-Car MFIS core driver for
|
||||
the MFIS device found on SoCs like R-Car. On families like Gen5, this
|
||||
is needed to communicate with the SCP.
|
||||
Select this option to enable support for the Renesas R-Car
|
||||
Multifunctional Interface (MFIS) device found on SoCs like R-Car.
|
||||
On families like R-Car Gen5, this is needed to communicate with the
|
||||
SCP.
|
||||
|
||||
config PWC_RZV2M
|
||||
bool "Renesas RZ/V2M PWC support" if COMPILE_TEST
|
||||
@@ -486,6 +497,7 @@ config RZN1_IRQMUX
|
||||
config SYSC_RZ
|
||||
bool "System controller for RZ SoCs" if COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
select AUXILIARY_BUS
|
||||
|
||||
config SYSC_R9A08G045
|
||||
bool "Renesas System controller support for R9A08G045 (RZ/G3S)" if COMPILE_TEST
|
||||
@@ -494,6 +506,8 @@ config SYSC_R9A08G045
|
||||
config SYSC_R9A08G046
|
||||
bool "Renesas System controller support for R9A08G046 (RZ/G3L)" if COMPILE_TEST
|
||||
select SYSC_RZ
|
||||
select POWER_SEQUENCING
|
||||
select POWER_SEQUENCING_RENESAS_PWRRDY
|
||||
|
||||
config SYS_R9A09G047
|
||||
bool "Renesas System controller support for R9A09G047 (RZ/G3E)" if COMPILE_TEST
|
||||
|
||||
@@ -76,6 +76,7 @@ static const struct rz_sysc_soc_id_init_data rzg3l_sysc_soc_id_init_data __initc
|
||||
.devid_offset = 0xa04,
|
||||
.revision_mask = GENMASK(31, 28),
|
||||
.specific_id_mask = GENMASK(27, 0),
|
||||
.pwrrdy_pwrseq = true,
|
||||
};
|
||||
|
||||
const struct rz_sysc_init_data rzg3l_sysc_init_data __initconst = {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#include <dt-bindings/soc/renesas,r8a78000-mfis.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/hwspinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -19,12 +20,18 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/* FIXME: hwspinlock core refactoring to not need internal header is on-going */
|
||||
#include "../../hwspinlock/hwspinlock_internal.h"
|
||||
|
||||
#define MFISLCKR0 0xc0
|
||||
#define MFISLCKR8 0x0724
|
||||
#define MFISWPCNTR 0x0900
|
||||
#define MFISWACNTR 0x0904
|
||||
|
||||
#define MFIS_X5H_IICR(i) ((i) * 0x1000 + 0x00)
|
||||
#define MFIS_X5H_EICR(i) ((i) * 0x1000 + 0x04)
|
||||
|
||||
#define MFIS_NUM_LOCKS 64
|
||||
#define MFIS_UNPROTECT_KEY 0xACCE0000
|
||||
|
||||
struct mfis_priv;
|
||||
@@ -42,6 +49,7 @@ struct mfis_info {
|
||||
unsigned int mb_tx_uses_eicr:1;
|
||||
unsigned int mb_channels_are_unidir:1;
|
||||
u32 (*mb_calc_reg)(u32 chan_num, bool tx_uses_eicr, bool is_only_rx);
|
||||
int hwsp_base_id;
|
||||
};
|
||||
|
||||
struct mfis_chan_priv {
|
||||
@@ -50,7 +58,7 @@ struct mfis_chan_priv {
|
||||
};
|
||||
|
||||
struct mfis_priv {
|
||||
spinlock_t unprotect_lock; /* guards access to the unprotection reg */
|
||||
raw_spinlock_t unprotect_lock; /* guards access to unprotection reg */
|
||||
struct device *dev;
|
||||
struct mfis_reg common_reg;
|
||||
struct mfis_reg mbox_reg;
|
||||
@@ -59,6 +67,9 @@ struct mfis_priv {
|
||||
/* mailbox private data */
|
||||
struct mbox_controller mbox;
|
||||
struct mfis_chan_priv *chan_privs;
|
||||
|
||||
/* hwspinlock private data */
|
||||
struct hwspinlock_device bank; /* flex array inside, must be last! */
|
||||
};
|
||||
|
||||
static u32 mfis_read(struct mfis_reg *mreg, unsigned int reg)
|
||||
@@ -80,12 +91,44 @@ static void mfis_write(struct mfis_reg *mreg, u32 reg, u32 val)
|
||||
unprotect_code = (MFIS_UNPROTECT_KEY & ~unprotect_mask) |
|
||||
((mreg->start + reg) & unprotect_mask);
|
||||
|
||||
spin_lock_irqsave(&priv->unprotect_lock, flags);
|
||||
raw_spin_lock_irqsave(&priv->unprotect_lock, flags);
|
||||
iowrite32(unprotect_code, priv->common_reg.base + MFISWACNTR);
|
||||
iowrite32(val, mreg->base + reg);
|
||||
spin_unlock_irqrestore(&priv->unprotect_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&priv->unprotect_lock, flags);
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* HW Spinlocks *
|
||||
********************************************************/
|
||||
|
||||
#define MFISLCKR8_CH_OFS (MFISLCKR8 - 8 * sizeof(u32))
|
||||
|
||||
static int rcar_mfis_hwsp_trylock(struct hwspinlock *lock)
|
||||
{
|
||||
struct mfis_priv *priv = lock->priv;
|
||||
int id = hwlock_to_id(lock) - lock->bank->base_id;
|
||||
u32 val, reg;
|
||||
|
||||
reg = id * sizeof(u32) + (id < 8 ? MFISLCKR0 : MFISLCKR8_CH_OFS);
|
||||
val = mfis_read(&priv->common_reg, reg);
|
||||
return !val;
|
||||
}
|
||||
|
||||
static void rcar_mfis_hwsp_unlock(struct hwspinlock *lock)
|
||||
{
|
||||
struct mfis_priv *priv = lock->priv;
|
||||
int id = hwlock_to_id(lock) - lock->bank->base_id;
|
||||
u32 reg;
|
||||
|
||||
reg = id * sizeof(u32) + (id < 8 ? MFISLCKR0 : MFISLCKR8_CH_OFS);
|
||||
mfis_write(&priv->common_reg, reg, 0);
|
||||
}
|
||||
|
||||
static const struct hwspinlock_ops rcar_mfis_hwsp_ops = {
|
||||
.trylock = rcar_mfis_hwsp_trylock,
|
||||
.unlock = rcar_mfis_hwsp_unlock,
|
||||
};
|
||||
|
||||
/********************************************************
|
||||
* Mailbox *
|
||||
********************************************************/
|
||||
@@ -314,7 +357,7 @@ static int mfis_probe(struct platform_device *pdev)
|
||||
struct mfis_priv *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
priv = devm_kzalloc(dev, struct_size(priv, bank.lock, MFIS_NUM_LOCKS), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -323,7 +366,7 @@ static int mfis_probe(struct platform_device *pdev)
|
||||
if (!priv->info)
|
||||
return -ENOENT;
|
||||
|
||||
spin_lock_init(&priv->unprotect_lock);
|
||||
raw_spin_lock_init(&priv->unprotect_lock);
|
||||
|
||||
ret = mfis_reg_probe(pdev, priv, &priv->common_reg, "common", true);
|
||||
if (ret)
|
||||
@@ -333,6 +376,14 @@ static int mfis_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (unsigned int ch = 0; ch < MFIS_NUM_LOCKS; ch++)
|
||||
priv->bank.lock[ch].priv = priv;
|
||||
|
||||
ret = devm_hwspin_lock_register(dev, &priv->bank, &rcar_mfis_hwsp_ops,
|
||||
priv->info->hwsp_base_id, MFIS_NUM_LOCKS);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mfis_mb_probe(priv);
|
||||
}
|
||||
|
||||
@@ -357,6 +408,7 @@ static const struct mfis_info mfis_info_r8a78000_scp = {
|
||||
.mb_tx_uses_eicr = true,
|
||||
.mb_channels_are_unidir = true,
|
||||
.mb_calc_reg = mfis_mb_r8a78000_calc_reg,
|
||||
.hwsp_base_id = MFIS_NUM_LOCKS,
|
||||
};
|
||||
|
||||
static const struct of_device_id mfis_mfd_of_match[] = {
|
||||
|
||||
@@ -93,6 +93,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
|
||||
{ .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 },
|
||||
/* RZ/G2 is handled like R-Car Gen3 */
|
||||
{ .compatible = "renesas,r8a774a1-rst", .data = &rcar_rst_gen3 },
|
||||
{ .compatible = "renesas,r8a774a3-rst", .data = &rcar_rst_gen3 },
|
||||
{ .compatible = "renesas,r8a774b1-rst", .data = &rcar_rst_gen3 },
|
||||
{ .compatible = "renesas,r8a774c0-rst", .data = &rcar_rst_gen3 },
|
||||
{ .compatible = "renesas,r8a774e1-rst", .data = &rcar_rst_gen3 },
|
||||
|
||||
@@ -312,6 +312,9 @@ static const struct of_device_id renesas_socs[] __initconst __maybe_unused = {
|
||||
#ifdef CONFIG_ARCH_R8A774A1
|
||||
{ .compatible = "renesas,r8a774a1", .data = &soc_rz_g2m },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A774A3
|
||||
{ .compatible = "renesas,r8a774a3", .data = &soc_rz_g2m },
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_R8A774B1
|
||||
{ .compatible = "renesas,r8a774b1", .data = &soc_rz_g2n },
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2024 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/io.h>
|
||||
@@ -149,6 +150,10 @@ static int rz_sysc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
if (data->soc_id_init_data->pwrrdy_pwrseq &&
|
||||
!devm_auxiliary_device_create(dev, "pwrseq-pwrrdy", regmap))
|
||||
return -ENODEV;
|
||||
|
||||
return of_syscon_register_regmap(dev->of_node, regmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* @revision_mask: SYSC SoC ID revision mask
|
||||
* @specific_id_mask: SYSC SoC ID specific ID mask
|
||||
* @print_id: print SoC-specific extended device identification
|
||||
* @pwrrdy_pwrseq: has pwrrdy register controlled through power sequencer
|
||||
*/
|
||||
struct rz_sysc_soc_id_init_data {
|
||||
const char * const family;
|
||||
@@ -29,6 +30,7 @@ struct rz_sysc_soc_id_init_data {
|
||||
u32 specific_id_mask;
|
||||
void (*print_id)(struct device *dev, void __iomem *sysc_base,
|
||||
struct soc_device_attribute *soc_dev_attr);
|
||||
bool pwrrdy_pwrseq;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,6 +64,7 @@ static const struct exynos_soc_id {
|
||||
{ "EXYNOS8890", 0xE8890000 },
|
||||
/* Compatible with: samsung,exynos850-chipid */
|
||||
{ "EXYNOS2200", 0xE9925000 },
|
||||
{ "EXYNOS5515", 0xE5515000 },
|
||||
{ "EXYNOS7885", 0xE7885000 },
|
||||
{ "EXYNOS850", 0xE3830000 },
|
||||
{ "EXYNOS8895", 0xE8895000 },
|
||||
|
||||
Loaded 100 of 140 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user