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:
Linus Torvalds committed 2026-10-22 07:52:50 -10:00
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
View File
@@ -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"
+2
View File
@@ -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
+1 -1
View File
@@ -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];
+1
View File
@@ -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
-1
View File
@@ -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.
+5 -1
View File
@@ -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;
+45 -19
View File
@@ -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);
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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;
+76 -33
View File
@@ -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)
+54 -7
View File
@@ -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);
+171 -91
View File
@@ -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);
+6 -3
View File
@@ -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;
};
+24 -6
View File
@@ -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;
}
}
+11 -25
View File
@@ -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
+6 -1
View File
@@ -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);
+875
View File
@@ -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");
+8 -2
View File
@@ -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;
+4 -2
View File
@@ -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) =
+3 -2
View File
@@ -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
+1 -1
View File
@@ -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,
+55 -132
View File
@@ -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)
+2 -1
View File
@@ -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);
+3 -3
View File
@@ -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;
+66 -4
View File
@@ -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
+38 -6
View File
@@ -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;
+31 -10
View File
@@ -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)) {
+5 -1
View File
@@ -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)
+2 -2
View File
@@ -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 */
+45
View File
@@ -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},
+36 -51
View File
@@ -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;
}
+9 -2
View File
@@ -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.
+2
View File
@@ -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
View File
@@ -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,
+15 -16
View File
@@ -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;
}
+1
View File
@@ -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"
+1
View File
@@ -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/
+912 -15
View File
@@ -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",
+119 -22
View File
@@ -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,
+1 -3
View File
@@ -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);
+5 -4
View File
@@ -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
View File
@@ -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(&regs->cpdata);
qe_gc->saved_regs.cpdata = qe_gc->cpdata;
qe_gc->saved_regs.cpdir1 = ioread32be(&regs->cpdir1);
qe_gc->saved_regs.cpdir2 = ioread32be(&regs->cpdir2);
qe_gc->saved_regs.cppar1 = ioread32be(&regs->cppar1);
qe_gc->saved_regs.cppar2 = ioread32be(&regs->cppar2);
qe_gc->saved_regs.cpodr = ioread32be(&regs->cpodr);
qe_gc->saved_cpdata = qe_gc->cpdata;
qe_gc->saved_cpdir1 = ioread32be(&regs->cpdir1);
qe_gc->saved_cpdir2 = ioread32be(&regs->cpdir2);
qe_gc->saved_cppar1 = ioread32be(&regs->cppar1);
qe_gc->saved_cppar2 = ioread32be(&regs->cppar2);
qe_gc->saved_cpodr = ioread32be(&regs->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(&regs->cpdir2, mask2,
sregs->cpdir2 & mask2);
qe_clrsetbits_be32(&regs->cppar2, mask2,
sregs->cppar2 & mask2);
qe_clrsetbits_be32(&regs->cpdir2, mask2, qe_gc->saved_cpdir2 & mask2);
qe_clrsetbits_be32(&regs->cppar2, mask2, qe_gc->saved_cppar2 & mask2);
} else {
qe_clrsetbits_be32(&regs->cpdir1, mask2,
sregs->cpdir1 & mask2);
qe_clrsetbits_be32(&regs->cppar1, mask2,
sregs->cppar1 & mask2);
qe_clrsetbits_be32(&regs->cpdir1, mask2, qe_gc->saved_cpdir1 & mask2);
qe_clrsetbits_be32(&regs->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, &regs->cpdata);
qe_clrsetbits_be32(&regs->cpodr, mask1, sregs->cpodr & mask1);
qe_clrsetbits_be32(&regs->cpodr, mask1, qe_gc->saved_cpodr & mask1);
spin_unlock_irqrestore(&qe_gc->lock, flags);
}
EXPORT_SYMBOL(qe_pin_set_dedicated);
+8 -8
View File
@@ -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);
}
}
}
+174 -9
View File
@@ -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;
+4 -3
View File
@@ -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;
-1
View File
@@ -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
View File
@@ -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;
}
+191 -8
View File
@@ -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},
+2 -1
View File
@@ -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;
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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[] = {
+41 -28
View File
@@ -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[] = {
+1 -3
View File
@@ -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)
+9
View File
@@ -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);
+12 -4
View File
@@ -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;
+2 -2
View File
@@ -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
View File
@@ -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
*
+75 -6
View File
@@ -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);
}
+7 -15
View File
@@ -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
View File
@@ -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);
+3
View File
@@ -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) },
+12
View File
@@ -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, },
+18 -4
View File
@@ -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
+1
View File
@@ -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 = {
+57 -5
View File
@@ -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[] = {
+1
View File
@@ -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 },
+3
View File
@@ -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
View File
@@ -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);
}
+2
View File
@@ -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;
};
/**
+1
View File
@@ -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