diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2021-09-30 14:28:03 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2021-09-30 14:28:03 +1000 |
commit | 060bfb797db485567796d1a98fe06097c36b0fe1 (patch) | |
tree | d22f44327aa0301fb6242bf78f701d39a473e2b7 | |
parent | 4efd9b239741ad40581945cb6bd8e8fa12e1800e (diff) | |
parent | 45500e830ed59eca0dca23874ca405f45009f6d4 (diff) | |
download | devel-060bfb797db485567796d1a98fe06097c36b0fe1.tar.gz |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git
26 files changed, 982 insertions, 245 deletions
diff --git a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml new file mode 100644 index 00000000000000..d892d29a656b32 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/remoteproc/amlogic,meson-mx-ao-arc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic Meson AO ARC Remote Processor bindings + +description: + Amlogic Meson6, Meson8, Meson8b and Meson8m2 SoCs embed an ARC core + controller for always-on operations, typically used for managing + system suspend. Meson6 and older use a ARC core based on the ARCv1 + ISA, while Meson8, Meson8b and Meson8m2 use an ARC EM4 (ARCv2 ISA) + core. + +maintainers: + - Martin Blumenstingl <martin.blumenstingl@googlemail.com> + +properties: + compatible: + items: + - enum: + - amlogic,meson8-ao-arc + - amlogic,meson8b-ao-arc + - const: amlogic,meson-mx-ao-arc + + firmware-name: + $ref: /schemas/types.yaml#/definitions/string + description: + The name of the firmware which should be loaded for this remote + processor. + + reg: + description: + Address ranges of the remap and CPU control addresses for the + remote processor. + minItems: 2 + + reg-names: + items: + - const: remap + - const: cpu + + resets: + minItems: 1 + + clocks: + minItems: 1 + + sram: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandles to a reserved SRAM region which is used as the memory of + the ARC core. The region should be defined as child nodes of the + AHB SRAM node as per the generic bindings in + Documentation/devicetree/bindings/sram/sram.yaml + + amlogic,secbus2: + $ref: /schemas/types.yaml#/definitions/phandle + description: + A phandle to the SECBUS2 region which contains some configuration + bits of this remote processor + +required: + - compatible + - reg + - reg-names + - resets + - clocks + - sram + - amlogic,secbus2 + +additionalProperties: false + +examples: + - | + remoteproc@1c { + compatible= "amlogic,meson8-ao-arc", "amlogic,meson-mx-ao-arc"; + reg = <0x1c 0x8>, <0x38 0x8>; + reg-names = "remap", "cpu"; + resets = <&media_cpu_reset>; + clocks = <&media_cpu_clock>; + sram = <&ahb_sram_ao_arc>; + amlogic,secbus2 = <&secbus2>; + }; + +... diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt deleted file mode 100644 index 3f5f78764b6024..00000000000000 --- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt +++ /dev/null @@ -1,36 +0,0 @@ -Mediatek SCP Bindings ----------------------------------------- - -This binding provides support for ARM Cortex M4 Co-processor found on some -Mediatek SoCs. - -Required properties: -- compatible Should be "mediatek,mt8183-scp" -- reg Should contain the address ranges for memory regions: - SRAM, CFG, and L1TCM. -- reg-names Contains the corresponding names for the memory regions: - "sram", "cfg", and "l1tcm". -- clocks Clock for co-processor (See: ../clock/clock-bindings.txt) -- clock-names Contains the corresponding name for the clock. This - should be named "main". - -Subnodes --------- - -Subnodes of the SCP represent rpmsg devices. The names of the devices are not -important. The properties of these nodes are defined by the individual bindings -for the rpmsg devices - but must contain the following property: - -- mtk,rpmsg-name Contains the name for the rpmsg device. Used to match - the subnode to rpmsg device announced by SCP. - -Example: - - scp: scp@10500000 { - compatible = "mediatek,mt8183-scp"; - reg = <0 0x10500000 0 0x80000>, - <0 0x105c0000 0 0x5000>; - reg-names = "sram", "cfg"; - clocks = <&infracfg CLK_INFRA_SCPSYS>; - clock-names = "main"; - }; diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml new file mode 100644 index 00000000000000..d21a25ee96e623 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/mtk,scp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek SCP Bindings + +maintainers: + - Tinghan Shen <tinghan.shen@mediatek.com> + +description: + This binding provides support for ARM Cortex M4 Co-processor found on some + Mediatek SoCs. + +properties: + compatible: + enum: + - mediatek,mt8183-scp + - mediatek,mt8192-scp + - mediatek,mt8195-scp + + reg: + description: + Should contain the address ranges for memory regions SRAM, CFG, and + L1TCM. + maxItems: 3 + + reg-names: + items: + - const: sram + - const: cfg + - const: l1tcm + + clocks: + description: + Clock for co-processor (see ../clock/clock-bindings.txt). + Required by mt8183 and mt8192. + maxItems: 1 + + clock-names: + const: main + +required: + - compatible + - reg + - reg-names + +if: + properties: + compatible: + enum: + - mediatek,mt8183-scp + - mediatek,mt8192-scp +then: + required: + - clocks + - clock-names + +additionalProperties: + type: object + description: + Subnodes of the SCP represent rpmsg devices. The names of the devices + are not important. The properties of these nodes are defined by the + individual bindings for the rpmsg devices. + properties: + mediatek,rpmsg-name: + $ref: /schemas/types.yaml#/definitions/string-array + description: + Contains the name for the rpmsg device. Used to match + the subnode to rpmsg device announced by SCP. + + required: + - mediatek,rpmsg-name + +examples: + - | + #include <dt-bindings/clock/mt8183-clk.h> + + scp@10500000 { + compatible = "mediatek,mt8183-scp"; + reg = <0x10500000 0x80000>, + <0x10700000 0x8000>, + <0x10720000 0xe0000>; + reg-names = "sram", "cfg", "l1tcm"; + clocks = <&infracfg CLK_INFRA_SCPSYS>; + clock-names = "main"; + + cros_ec { + mediatek,rpmsg-name = "cros-ec-rpmsg"; + }; + }; diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 0c112f3264a929..63e06d93bca3b5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -25,6 +25,7 @@ properties: - qcom,qcs404-cdsp-pas - qcom,qcs404-wcss-pas - qcom,sc7180-mpss-pas + - qcom,sc7280-mpss-pas - qcom,sc8180x-adsp-pas - qcom,sc8180x-cdsp-pas - qcom,sc8180x-mpss-pas @@ -93,6 +94,10 @@ properties: maxItems: 1 description: Reference to the reserved-memory for the Hexagon core + qcom,qmp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AOSS side-channel message RAM. + qcom,smem-states: $ref: /schemas/types.yaml#/definitions/phandle-array description: States used by the AP to signal the Hexagon core @@ -147,6 +152,7 @@ allOf: - qcom,msm8998-adsp-pas - qcom,qcs404-adsp-pas - qcom,qcs404-wcss-pas + - qcom,sc7280-mpss-pas - qcom,sc8180x-adsp-pas - qcom,sc8180x-cdsp-pas - qcom,sc8180x-mpss-pas @@ -292,6 +298,7 @@ allOf: contains: enum: - qcom,sc7180-mpss-pas + - qcom,sc7280-mpss-pas - qcom,sc8180x-mpss-pas - qcom,sdx55-mpss-pas - qcom,sm8150-mpss-pas @@ -369,13 +376,11 @@ allOf: properties: power-domains: items: - - description: Load State power domain - description: CX power domain - description: MX power domain - description: MSS power domain power-domain-names: items: - - const: load_state - const: cx - const: mx - const: mss @@ -391,43 +396,21 @@ allOf: properties: power-domains: items: - - description: Load State power domain - description: CX power domain - power-domain-names: - items: - - const: load_state - - const: cx - if: properties: compatible: contains: enum: + - qcom,sc7280-mpss-pas + - qcom,sdx55-mpss-pas - qcom,sm8150-mpss-pas - qcom,sm8350-mpss-pas then: properties: power-domains: items: - - description: Load State power domain - - description: CX power domain - - description: MSS power domain - power-domain-names: - items: - - const: load_state - - const: cx - - const: mss - - - if: - properties: - compatible: - contains: - enum: - - qcom,sdx55-mpss-pas - then: - properties: - power-domains: - items: - description: CX power domain - description: MSS power domain power-domain-names: @@ -451,12 +434,10 @@ allOf: properties: power-domains: items: - - description: Load State power domain - description: LCX power domain - description: LMX power domain power-domain-names: items: - - const: load_state - const: lcx - const: lmx @@ -470,12 +451,10 @@ allOf: properties: power-domains: items: - - description: Load State power domain - description: CX power domain - description: MXC power domain power-domain-names: items: - - const: load_state - const: cx - const: mxc @@ -500,6 +479,7 @@ allOf: contains: enum: - qcom,sc7180-mpss-pas + - qcom,sc7280-mpss-pas then: properties: resets: @@ -511,6 +491,25 @@ allOf: - const: mss_restart - const: pdc_reset + - if: + properties: + compatible: + contains: + enum: + - qcom,msm8974-adsp-pil + - qcom,msm8996-adsp-pil + - qcom,msm8996-slpi-pil + - qcom,msm8998-adsp-pas + - qcom,msm8998-slpi-pas + - qcom,qcs404-adsp-pas + - qcom,qcs404-cdsp-pas + - qcom,qcs404-wcss-pas + - qcom,sdm660-adsp-pas + - qcom,sdx55-mpss-pas + then: + properties: + qcom,qmp: false + examples: - | #include <dt-bindings/clock/qcom,rpmcc.h> diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt index 69c49c7b2cffe7..8f1507052afd10 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt @@ -15,6 +15,7 @@ on the Qualcomm Hexagon core. "qcom,msm8996-mss-pil" "qcom,msm8998-mss-pil" "qcom,sc7180-mss-pil" + "qcom,sc7280-mss-pil" "qcom,sdm845-mss-pil" - reg: @@ -47,6 +48,7 @@ on the Qualcomm Hexagon core. qcom,msm8996-mss-pil: qcom,msm8998-mss-pil: qcom,sc7180-mss-pil: + qcom,sc7280-mss-pil: qcom,sdm845-mss-pil: must be "wdog", "fatal", "ready", "handover", "stop-ack", "shutdown-ack" @@ -87,6 +89,8 @@ on the Qualcomm Hexagon core. qcom,sc7180-mss-pil: must be "iface", "bus", "xo", "snoc_axi", "mnoc_axi", "nav" + qcom,sc7280-mss-pil: + must be "iface", "xo", "snoc_axi", "offline", "pka" qcom,sdm845-mss-pil: must be "iface", "bus", "mem", "xo", "gpll0_mss", "snoc_axi", "mnoc_axi", "prng" @@ -98,7 +102,7 @@ on the Qualcomm Hexagon core. reference to the list of 3 reset-controllers for the wcss sub-system reference to the list of 2 reset-controllers for the modem - sub-system on SC7180, SDM845 SoCs + sub-system on SC7180, SC7280, SDM845 SoCs - reset-names: Usage: required @@ -107,7 +111,7 @@ on the Qualcomm Hexagon core. must be "wcss_aon_reset", "wcss_reset", "wcss_q6_reset" for the wcss sub-system must be "mss_restart", "pdc_reset" for the modem - sub-system on SC7180, SDM845 SoCs + sub-system on SC7180, SC7280, SDM845 SoCs For devices where the mba and mpss sub-nodes are not specified, mba/mpss region should be referenced as follows: @@ -173,8 +177,16 @@ For the compatible string below the following supplies are required: qcom,msm8998-mss-pil: must be "cx", "mx" qcom,sc7180-mss-pil: + must be "cx", "mx", "mss" + qcom,sc7280-mss-pil: + must be "cx", "mss" qcom,sdm845-mss-pil: - must be "cx", "mx", "mss", "load_state" + must be "cx", "mx", "mss" + +- qcom,qmp: + Usage: optional + Value type: <phandle> + Definition: reference to the AOSS side-channel message RAM. - qcom,smem-states: Usage: required @@ -193,6 +205,9 @@ For the compatible string below the following supplies are required: Definition: a phandle reference to a syscon representing TCSR followed by the three offsets within syscon for q6, modem and nc halt registers. + a phandle reference to a syscon representing TCSR followed + by the four offsets within syscon for q6, modem, nc and vq6 + halt registers on SC7280 SoCs. For the compatible strings below the following phandle references are required: "qcom,sc7180-mss-pil" @@ -203,6 +218,24 @@ For the compatible strings below the following phandle references are required: by the offset within syscon for conn_box_spare0 register used by the modem sub-system running on SC7180 SoC. +For the compatible strings below the following phandle references are required: + "qcom,sc7280-mss-pil" +- qcom,ext-regs: + Usage: required + Value type: <prop-encoded-array> + Definition: two phandle references to syscons representing TCSR_REG and + TCSR register space followed by the two offsets within the syscon + to force_clk_en/rscc_disable and axim1_clk_off/crypto_clk_off + registers respectively. + +- qcom,qaccept-regs: + Usage: required + Value type: <prop-encoded-array> + Definition: a phandle reference to a syscon representing TCSR followed + by the three offsets within syscon for mdm, cx and axi + qaccept registers used by the modem sub-system running on + SC7280 SoC. + The Hexagon node must contain iommus property as described in ../iommu/iommu.txt on platforms which do not have TrustZone. diff --git a/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml index 6070456a7b67bf..5ec6505ac40830 100644 --- a/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml @@ -133,9 +133,7 @@ unevaluatedProperties: false examples: - | - / { - model = "Texas Instruments K3 J721E SoC"; - compatible = "ti,j721e"; + soc { #address-cells = <2>; #size-cells = <2>; diff --git a/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml index 130fbaacc4b153..eeef255c40454f 100644 --- a/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml @@ -230,9 +230,7 @@ additionalProperties: false examples: - | - / { - model = "Texas Instruments K3 AM654 SoC"; - compatible = "ti,am654-evm", "ti,am654"; + soc { #address-cells = <2>; #size-cells = <2>; diff --git a/MAINTAINERS b/MAINTAINERS index e30d7a718ffdb5..f52fe16f07923c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15979,7 +15979,7 @@ M: Bjorn Andersson <bjorn.andersson@linaro.org> M: Mathieu Poirier <mathieu.poirier@linaro.org> L: linux-remoteproc@vger.kernel.org S: Maintained -T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git rproc-next +T: git https://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git rproc-next F: Documentation/ABI/testing/sysfs-class-remoteproc F: Documentation/devicetree/bindings/remoteproc/ F: Documentation/staging/remoteproc.rst @@ -15993,7 +15993,7 @@ M: Bjorn Andersson <bjorn.andersson@linaro.org> M: Mathieu Poirier <mathieu.poirier@linaro.org> L: linux-remoteproc@vger.kernel.org S: Maintained -T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git rpmsg-next +T: git https://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git rpmsg-next F: Documentation/ABI/testing/sysfs-bus-rpmsg F: Documentation/staging/rpmsg.rst F: drivers/rpmsg/ diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 9a6eedc3994a54..dcb87a366ec718 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -127,6 +127,17 @@ config KEYSTONE_REMOTEPROC It's safe to say N here if you're not interested in the Keystone DSPs or just want to use a bare minimum kernel. +config MESON_MX_AO_ARC_REMOTEPROC + tristate "Amlogic Meson6/8/8b/8m2 AO ARC remote processor support" + depends on HAS_IOMEM + depends on (ARM && ARCH_MESON) || COMPILE_TEST + select GENERIC_ALLOCATOR + help + Say m or y here to have support for the AO ARC remote processor + on Amlogic Meson6/Meson8/Meson8b/Meson8m2 SoCs. This is + typically used for system suspend. + If unsure say N. + config PRU_REMOTEPROC tristate "TI PRU remoteproc support" depends on TI_PRUSS @@ -154,7 +165,7 @@ config QCOM_Q6V5_ADSP tristate "Qualcomm Technology Inc ADSP Peripheral Image Loader" depends on OF && ARCH_QCOM depends on QCOM_SMEM - depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n @@ -173,7 +184,7 @@ config QCOM_Q6V5_MSS tristate "Qualcomm Hexagon V5 self-authenticating modem subsystem support" depends on OF && ARCH_QCOM depends on QCOM_SMEM - depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n @@ -192,7 +203,7 @@ config QCOM_Q6V5_PAS tristate "Qualcomm Hexagon v5 Peripheral Authentication Service support" depends on OF && ARCH_QCOM depends on QCOM_SMEM - depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n @@ -213,7 +224,7 @@ config QCOM_Q6V5_WCSS tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader" depends on OF && ARCH_QCOM depends on QCOM_SMEM - depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n @@ -246,7 +257,7 @@ config QCOM_SYSMON config QCOM_WCNSS_PIL tristate "Qualcomm WCNSS Peripheral Image Loader" depends on OF && ARCH_QCOM - depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SMEM depends on QCOM_SYSMON || QCOM_SYSMON=n diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index bb26c9e4ef9cf3..ce1abeb30907ba 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o +obj-$(CONFIG_MESON_MX_AO_ARC_REMOTEPROC)+= meson_mx_ao_arc.o obj-$(CONFIG_PRU_REMOTEPROC) += pru_rproc.o obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil_info.o obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index d88f76f5305ebc..4ae416ba50807e 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -71,6 +71,7 @@ struct imx_rproc_mem { /* att flags */ /* M4 own area. Can be mapped at probe */ #define ATT_OWN BIT(1) +#define ATT_IOMEM BIT(2) /* address translation table */ struct imx_rproc_att { @@ -117,7 +118,7 @@ struct imx_rproc { static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { /* dev addr , sys addr , size , flags */ /* ITCM */ - { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, + { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM }, /* OCRAM_S */ { 0x00180000, 0x00180000, 0x00009000, 0 }, /* OCRAM */ @@ -131,7 +132,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { /* DDR (Code) - alias */ { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, /* DTCM */ - { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, + { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM }, /* OCRAM_S - alias */ { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, /* OCRAM */ @@ -147,7 +148,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { /* dev addr , sys addr , size , flags */ /* TCML - alias */ - { 0x00000000, 0x007e0000, 0x00020000, 0 }, + { 0x00000000, 0x007e0000, 0x00020000, ATT_IOMEM}, /* OCRAM_S */ { 0x00180000, 0x00180000, 0x00008000, 0 }, /* OCRAM */ @@ -159,9 +160,9 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { /* DDR (Code) - alias */ { 0x10000000, 0x80000000, 0x0FFE0000, 0 }, /* TCML */ - { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN }, + { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM}, /* TCMU */ - { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, + { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM}, /* OCRAM_S */ { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, /* OCRAM */ @@ -199,12 +200,12 @@ static const struct imx_rproc_att imx_rproc_att_imx7d[] = { /* OCRAM_PXP (Code) - alias */ { 0x00940000, 0x00940000, 0x00008000, 0 }, /* TCML (Code) */ - { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, + { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM }, /* DDR (Code) - alias, first part of DDR (Data) */ { 0x10000000, 0x80000000, 0x0FFF0000, 0 }, /* TCMU (Data) */ - { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, + { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM }, /* OCRAM (Data) */ { 0x20200000, 0x00900000, 0x00020000, 0 }, /* OCRAM_EPDC (Data) */ @@ -218,18 +219,18 @@ static const struct imx_rproc_att imx_rproc_att_imx7d[] = { static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { /* dev addr , sys addr , size , flags */ /* TCML (M4 Boot Code) - alias */ - { 0x00000000, 0x007F8000, 0x00008000, 0 }, + { 0x00000000, 0x007F8000, 0x00008000, ATT_IOMEM }, /* OCRAM_S (Code) */ { 0x00180000, 0x008F8000, 0x00004000, 0 }, /* OCRAM_S (Code) - alias */ { 0x00180000, 0x008FC000, 0x00004000, 0 }, /* TCML (Code) */ - { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, + { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM }, /* DDR (Code) - alias, first part of DDR (Data) */ { 0x10000000, 0x80000000, 0x0FFF8000, 0 }, /* TCMU (Data) */ - { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, + { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM }, /* OCRAM_S (Data) - alias? */ { 0x208F8000, 0x008F8000, 0x00004000, 0 }, /* DDR (Data) */ @@ -341,7 +342,7 @@ static int imx_rproc_stop(struct rproc *rproc) } static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, - size_t len, u64 *sys) + size_t len, u64 *sys, bool *is_iomem) { const struct imx_rproc_dcfg *dcfg = priv->dcfg; int i; @@ -354,6 +355,8 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, unsigned int offset = da - att->da; *sys = att->sa + offset; + if (is_iomem) + *is_iomem = att->flags & ATT_IOMEM; return 0; } } @@ -377,7 +380,7 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i * On device side we have many aliases, so we need to convert device * address (M4) to system bus address first. */ - if (imx_rproc_da_to_sys(priv, da, len, &sys)) + if (imx_rproc_da_to_sys(priv, da, len, &sys, is_iomem)) return NULL; for (i = 0; i < IMX_RPROC_MEM_MAX; i++) { @@ -553,8 +556,12 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, if (b >= IMX_RPROC_MEM_MAX) break; - priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, - att->sa, att->size); + if (att->flags & ATT_IOMEM) + priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, + att->sa, att->size); + else + priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, + att->sa, att->size); if (!priv->mem[b].cpu_addr) { dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa); return -ENOMEM; @@ -575,8 +582,8 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, struct resource res; node = of_parse_phandle(np, "memory-region", a); - /* Not map vdev region */ - if (!strcmp(node->name, "vdev")) + /* Not map vdevbuffer, vdevring region */ + if (!strncmp(node->name, "vdev", strlen("vdev"))) continue; err = of_address_to_resource(node, 0, &res); if (err) { @@ -590,14 +597,14 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, break; /* Not use resource version, because we might share region */ - priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, res.start, resource_size(&res)); + priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res)); if (!priv->mem[b].cpu_addr) { dev_err(dev, "failed to remap %pr\n", &res); return -ENOMEM; } priv->mem[b].sys_addr = res.start; priv->mem[b].size = resource_size(&res); - if (!strcmp(node->name, "rsc_table")) + if (!strcmp(node->name, "rsc-table")) priv->rsc_table = priv->mem[b].cpu_addr; b++; } diff --git a/drivers/remoteproc/meson_mx_ao_arc.c b/drivers/remoteproc/meson_mx_ao_arc.c new file mode 100644 index 00000000000000..3d8f927ae448fe --- /dev/null +++ b/drivers/remoteproc/meson_mx_ao_arc.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com> + */ + +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/genalloc.h> +#include <linux/io.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/property.h> +#include <linux/regmap.h> +#include <linux/remoteproc.h> +#include <linux/reset.h> +#include <linux/sizes.h> + +#include "remoteproc_internal.h" + +#define AO_REMAP_REG0 0x0 +#define AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU GENMASK(3, 0) + +#define AO_REMAP_REG1 0x4 +#define AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR BIT(4) +#define AO_REMAP_REG1_REMAP_AHB_SRAM_BITS_17_14_FOR_MEDIA_CPU GENMASK(3, 0) + +#define AO_CPU_CNTL 0x0 +#define AO_CPU_CNTL_AHB_SRAM_BITS_31_20 GENMASK(28, 16) +#define AO_CPU_CNTL_HALT BIT(9) +#define AO_CPU_CNTL_UNKNONWN BIT(8) +#define AO_CPU_CNTL_RUN BIT(0) + +#define AO_CPU_STAT 0x4 + +#define AO_SECURE_REG0 0x0 +#define AO_SECURE_REG0_AHB_SRAM_BITS_19_12 GENMASK(15, 8) + +/* Only bits [31:20] and [17:14] are usable, all other bits must be zero */ +#define MESON_AO_RPROC_SRAM_USABLE_BITS 0xfff3c000 + +#define MESON_AO_RPROC_MEMORY_OFFSET 0x10000000 + +struct meson_mx_ao_arc_rproc_priv { + void __iomem *remap_base; + void __iomem *cpu_base; + unsigned long sram_va; + phys_addr_t sram_pa; + size_t sram_size; + struct gen_pool *sram_pool; + struct reset_control *arc_reset; + struct clk *arc_pclk; + struct regmap *secbus2_regmap; +}; + +static int meson_mx_ao_arc_rproc_start(struct rproc *rproc) +{ + struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; + phys_addr_t translated_sram_addr; + u32 tmp; + int ret; + + ret = clk_prepare_enable(priv->arc_pclk); + if (ret) + return ret; + + tmp = FIELD_PREP(AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU, + priv->sram_pa >> 14); + writel(tmp, priv->remap_base + AO_REMAP_REG0); + + /* + * The SRAM content as seen by the ARC core always starts at 0x0 + * regardless of the value given here (this was discovered by trial and + * error). For SoCs older than Meson6 we probably have to set + * AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR to achieve the + * same. (At least) For Meson8 and newer that bit must not be set. + */ + writel(0x0, priv->remap_base + AO_REMAP_REG1); + + regmap_update_bits(priv->secbus2_regmap, AO_SECURE_REG0, + AO_SECURE_REG0_AHB_SRAM_BITS_19_12, + FIELD_PREP(AO_SECURE_REG0_AHB_SRAM_BITS_19_12, + priv->sram_pa >> 12)); + + ret = reset_control_reset(priv->arc_reset); + if (ret) { + clk_disable_unprepare(priv->arc_pclk); + return ret; + } + + usleep_range(10, 100); + + /* + * Convert from 0xd9000000 to 0xc9000000 as the vendor driver does. + * This only seems to be relevant for the AO_CPU_CNTL register. It is + * unknown why this is needed. + */ + translated_sram_addr = priv->sram_pa - MESON_AO_RPROC_MEMORY_OFFSET; + + tmp = FIELD_PREP(AO_CPU_CNTL_AHB_SRAM_BITS_31_20, + translated_sram_addr >> 20); + tmp |= AO_CPU_CNTL_UNKNONWN | AO_CPU_CNTL_RUN; + writel(tmp, priv->cpu_base + AO_CPU_CNTL); + + usleep_range(20, 200); + + return 0; +} + +static int meson_mx_ao_arc_rproc_stop(struct rproc *rproc) +{ + struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; + + writel(AO_CPU_CNTL_HALT, priv->cpu_base + AO_CPU_CNTL); + + clk_disable_unprepare(priv->arc_pclk); + + return 0; +} + +static void *meson_mx_ao_arc_rproc_da_to_va(struct rproc *rproc, u64 da, + size_t len, bool *is_iomem) +{ + struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; + + /* The memory from the ARC core's perspective always starts at 0x0. */ + if ((da + len) > priv->sram_size) + return NULL; + + return (void *)priv->sram_va + da; +} + +static struct rproc_ops meson_mx_ao_arc_rproc_ops = { + .start = meson_mx_ao_arc_rproc_start, + .stop = meson_mx_ao_arc_rproc_stop, + .da_to_va = meson_mx_ao_arc_rproc_da_to_va, + .get_boot_addr = rproc_elf_get_boot_addr, + .load = rproc_elf_load_segments, + .sanity_check = rproc_elf_sanity_check, +}; + +static int meson_mx_ao_arc_rproc_probe(struct platform_device *pdev) +{ + struct meson_mx_ao_arc_rproc_priv *priv; + struct device *dev = &pdev->dev; + const char *fw_name = NULL; + struct rproc *rproc; + int ret; + + device_property_read_string(dev, "firmware-name", &fw_name); + + rproc = devm_rproc_alloc(dev, "meson-mx-ao-arc", + &meson_mx_ao_arc_rproc_ops, fw_name, + sizeof(*priv)); + if (!rproc) + return -ENOMEM; + + rproc->has_iommu = false; + priv = rproc->priv; + + priv->sram_pool = of_gen_pool_get(dev->of_node, "sram", 0); + if (!priv->sram_pool) { + dev_err(dev, "Could not get SRAM pool\n"); + return -ENODEV; + } + + priv->sram_size = gen_pool_avail(priv->sram_pool); + + priv->sram_va = gen_pool_alloc(priv->sram_pool, priv->sram_size); + if (!priv->sram_va) { + dev_err(dev, "Could not alloc memory in SRAM pool\n"); + return -ENOMEM; + } + + priv->sram_pa = gen_pool_virt_to_phys(priv->sram_pool, priv->sram_va); + if (priv->sram_pa & ~MESON_AO_RPROC_SRAM_USABLE_BITS) { + dev_err(dev, "SRAM address contains unusable bits\n"); + ret = -EINVAL; + goto err_free_genpool; + } + + priv->secbus2_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "amlogic,secbus2"); + if (IS_ERR(priv->secbus2_regmap)) { + dev_err(dev, "Failed to find SECBUS2 regmap\n"); + ret = PTR_ERR(priv->secbus2_regmap); + goto err_free_genpool; + } + + priv->remap_base = devm_platform_ioremap_resource_byname(pdev, "remap"); + if (IS_ERR(priv->remap_base)) { + ret = PTR_ERR(priv->remap_base); + goto err_free_genpool; + } + + priv->cpu_base = devm_platform_ioremap_resource_byname(pdev, "cpu"); + if (IS_ERR(priv->cpu_base)) { + ret = PTR_ERR(priv->cpu_base); + goto err_free_genpool; + } + + priv->arc_reset = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(priv->arc_reset)) { + dev_err(dev, "Failed to get ARC reset\n"); + ret = PTR_ERR(priv->arc_reset); + goto err_free_genpool; + } + + priv->arc_pclk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->arc_pclk)) { + dev_err(dev, "Failed to get the ARC PCLK\n"); + ret = PTR_ERR(priv->arc_pclk); + goto err_free_genpool; + } + + platform_set_drvdata(pdev, rproc); + + ret = rproc_add(rproc); + if (ret) + goto err_free_genpool; + + return 0; + +err_free_genpool: + gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size); + return ret; +} + +static int meson_mx_ao_arc_rproc_remove(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; + + rproc_del(rproc); + gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size); + + return 0; +} + +static const struct of_device_id meson_mx_ao_arc_rproc_match[] = { + { .compatible = "amlogic,meson8-ao-arc" }, + { .compatible = "amlogic,meson8b-ao-arc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, meson_mx_ao_arc_rproc_match); + +static struct platform_driver meson_mx_ao_arc_rproc_driver = { + .probe = meson_mx_ao_arc_rproc_probe, + .remove = meson_mx_ao_arc_rproc_remove, + .driver = { + .name = "meson-mx-ao-arc-rproc", + .of_match_table = meson_mx_ao_arc_rproc_match, + }, +}; +module_platform_driver(meson_mx_ao_arc_rproc_driver); + +MODULE_DESCRIPTION("Amlogic Meson6/8/8b/8m2 AO ARC remote processor driver"); +MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h index 61901f5efa051e..5ff3867c72f373 100644 --- a/drivers/remoteproc/mtk_common.h +++ b/drivers/remoteproc/mtk_common.h @@ -72,6 +72,7 @@ struct scp_ipi_desc { struct mtk_scp; struct mtk_scp_of_data { + int (*scp_clk_get)(struct mtk_scp *scp); int (*scp_before_load)(struct mtk_scp *scp); void (*scp_irq_handler)(struct mtk_scp *scp); void (*scp_reset_assert)(struct mtk_scp *scp); diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index 9679cc26895e57..36e48cf58ed63a 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -312,6 +312,32 @@ static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp, return -ENOENT; } +static int mt8183_scp_clk_get(struct mtk_scp *scp) +{ + struct device *dev = scp->dev; + int ret = 0; + + scp->clk = devm_clk_get(dev, "main"); + if (IS_ERR(scp->clk)) { + dev_err(dev, "Failed to get clock\n"); + ret = PTR_ERR(scp->clk); + } + + return ret; +} + +static int mt8192_scp_clk_get(struct mtk_scp *scp) +{ + return mt8183_scp_clk_get(scp); +} + +static int mt8195_scp_clk_get(struct mtk_scp *scp) +{ + scp->clk = NULL; + + return 0; +} + static int mt8183_scp_before_load(struct mtk_scp *scp) { /* Clear SCP to host interrupt */ @@ -785,12 +811,9 @@ static int scp_probe(struct platform_device *pdev) if (ret) goto destroy_mutex; - scp->clk = devm_clk_get(dev, "main"); - if (IS_ERR(scp->clk)) { - dev_err(dev, "Failed to get clock\n"); - ret = PTR_ERR(scp->clk); + ret = scp->data->scp_clk_get(scp); + if (ret) goto release_dev_mem; - } /* register SCP initialization IPI */ ret = scp_ipi_register(scp, SCP_IPI_INIT, scp_init_ipi_handler, scp); @@ -852,6 +875,7 @@ static int scp_remove(struct platform_device *pdev) } static const struct mtk_scp_of_data mt8183_of_data = { + .scp_clk_get = mt8183_scp_clk_get, .scp_before_load = mt8183_scp_before_load, .scp_irq_handler = mt8183_scp_irq_handler, .scp_reset_assert = mt8183_scp_reset_assert, @@ -864,6 +888,19 @@ static const struct mtk_scp_of_data mt8183_of_data = { }; static const struct mtk_scp_of_data mt8192_of_data = { + .scp_clk_get = mt8192_scp_clk_get, + .scp_before_load = mt8192_scp_before_load, + .scp_irq_handler = mt8192_scp_irq_handler, + .scp_reset_assert = mt8192_scp_reset_assert, + .scp_reset_deassert = mt8192_scp_reset_deassert, + .scp_stop = mt8192_scp_stop, + .scp_da_to_va = mt8192_scp_da_to_va, + .host_to_scp_reg = MT8192_GIPC_IN_SET, + .host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT, +}; + +static const struct mtk_scp_of_data mt8195_of_data = { + .scp_clk_get = mt8195_scp_clk_get, .scp_before_load = mt8192_scp_before_load, .scp_irq_handler = mt8192_scp_irq_handler, .scp_reset_assert = mt8192_scp_reset_assert, @@ -877,6 +914,7 @@ static const struct mtk_scp_of_data mt8192_of_data = { static const struct of_device_id mtk_scp_of_match[] = { { .compatible = "mediatek,mt8183-scp", .data = &mt8183_of_data }, { .compatible = "mediatek,mt8192-scp", .data = &mt8192_of_data }, + { .compatible = "mediatek,mt8195-scp", .data = &mt8195_of_data }, {}, }; MODULE_DEVICE_TABLE(of, mtk_scp_of_match); diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 7e9244c748da6d..eada7e34f3af51 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -16,8 +16,30 @@ #include "qcom_common.h" #include "qcom_q6v5.h" +#define Q6V5_LOAD_STATE_MSG_LEN 64 #define Q6V5_PANIC_DELAY_MS 200 +static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable) +{ + char buf[Q6V5_LOAD_STATE_MSG_LEN]; + int ret; + + if (!q6v5->qmp) + return 0; + + ret = snprintf(buf, sizeof(buf), + "{class: image, res: load_state, name: %s, val: %s}", + q6v5->load_state, enable ? "on" : "off"); + + WARN_ON(ret >= Q6V5_LOAD_STATE_MSG_LEN); + + ret = qmp_send(q6v5->qmp, buf, sizeof(buf)); + if (ret) + dev_err(q6v5->dev, "failed to toggle load state\n"); + + return ret; +} + /** * qcom_q6v5_prepare() - reinitialize the qcom_q6v5 context before start * @q6v5: reference to qcom_q6v5 context to be reinitialized @@ -26,6 +48,12 @@ */ int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5) { + int ret; + + ret = q6v5_load_state_toggle(q6v5, true); + if (ret) + return ret; + reinit_completion(&q6v5->start_done); reinit_completion(&q6v5->stop_done); @@ -47,6 +75,7 @@ EXPORT_SYMBOL_GPL(qcom_q6v5_prepare); int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5) { disable_irq(q6v5->handover_irq); + q6v5_load_state_toggle(q6v5, false); return !q6v5->handover_issued; } @@ -196,12 +225,13 @@ EXPORT_SYMBOL_GPL(qcom_q6v5_panic); * @pdev: platform_device reference for acquiring resources * @rproc: associated remoteproc instance * @crash_reason: SMEM id for crash reason string, or 0 if none + * @load_state: load state resource string * @handover: function to be called when proxy resources should be released * * Return: 0 on success, negative errno on failure */ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, - struct rproc *rproc, int crash_reason, + struct rproc *rproc, int crash_reason, const char *load_state, void (*handover)(struct qcom_q6v5 *q6v5)) { int ret; @@ -286,9 +316,34 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, return PTR_ERR(q6v5->state); } + q6v5->load_state = devm_kstrdup_const(&pdev->dev, load_state, GFP_KERNEL); + q6v5->qmp = qmp_get(&pdev->dev); + if (IS_ERR(q6v5->qmp)) { + if (PTR_ERR(q6v5->qmp) != -ENODEV) + return dev_err_probe(&pdev->dev, PTR_ERR(q6v5->qmp), + "failed to acquire load state\n"); + q6v5->qmp = NULL; + } else if (!q6v5->load_state) { + if (!load_state) + dev_err(&pdev->dev, "load state resource string empty\n"); + + qmp_put(q6v5->qmp); + return load_state ? -ENOMEM : -EINVAL; + } + return 0; } EXPORT_SYMBOL_GPL(qcom_q6v5_init); +/** + * qcom_q6v5_deinit() - deinitialize the q6v5 common struct + * @q6v5: reference to qcom_q6v5 context to be deinitialized + */ +void qcom_q6v5_deinit(struct qcom_q6v5 *q6v5) +{ + qmp_put(q6v5->qmp); +} +EXPORT_SYMBOL_GPL(qcom_q6v5_deinit); + MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Qualcomm Peripheral Image Loader for Q6V5"); diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h index 1c212f670cbc58..f35e04471ed756 100644 --- a/drivers/remoteproc/qcom_q6v5.h +++ b/drivers/remoteproc/qcom_q6v5.h @@ -5,6 +5,7 @@ #include <linux/kernel.h> #include <linux/completion.h> +#include <linux/soc/qcom/qcom_aoss.h> struct rproc; struct qcom_smem_state; @@ -15,6 +16,8 @@ struct qcom_q6v5 { struct rproc *rproc; struct qcom_smem_state *state; + struct qmp *qmp; + unsigned stop_bit; int wdog_irq; @@ -32,12 +35,14 @@ struct qcom_q6v5 { bool running; + const char *load_state; void (*handover)(struct qcom_q6v5 *q6v5); }; int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, - struct rproc *rproc, int crash_reason, + struct rproc *rproc, int crash_reason, const char *load_state, void (*handover)(struct qcom_q6v5 *q6v5)); +void qcom_q6v5_deinit(struct qcom_q6v5 *q6v5); int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5); int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index 8b0d8bbacd2e49..098362e6e233bb 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -185,7 +185,9 @@ static int adsp_start(struct rproc *rproc) int ret; unsigned int val; - qcom_q6v5_prepare(&adsp->q6v5); + ret = qcom_q6v5_prepare(&adsp->q6v5); + if (ret) + return ret; ret = clk_prepare_enable(adsp->xo); if (ret) @@ -465,7 +467,7 @@ static int adsp_probe(struct platform_device *pdev) if (ret) goto disable_pm; - ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, + ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, NULL, qcom_adsp_pil_handover); if (ret) goto disable_pm; @@ -500,6 +502,7 @@ static int adsp_remove(struct platform_device *pdev) rproc_del(adsp->rproc); + qcom_q6v5_deinit(&adsp->q6v5); qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); qcom_remove_sysmon_subdev(adsp->sysmon); qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 423b31dfa57416..ec0701126ab3d7 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -77,6 +77,14 @@ #define HALT_ACK_TIMEOUT_US 100000 +/* QACCEPT Register Offsets */ +#define QACCEPT_ACCEPT_REG 0x0 +#define QACCEPT_ACTIVE_REG 0x4 +#define QACCEPT_DENY_REG 0x8 +#define QACCEPT_REQ_REG 0xC + +#define QACCEPT_TIMEOUT_US 50 + /* QDSP6SS_RESET */ #define Q6SS_STOP_CORE BIT(0) #define Q6SS_CORE_ARES BIT(1) @@ -137,13 +145,15 @@ struct rproc_hexagon_res { char **proxy_clk_names; char **reset_clk_names; char **active_clk_names; - char **active_pd_names; char **proxy_pd_names; int version; bool need_mem_protection; bool has_alt_reset; bool has_mba_logs; bool has_spare_reg; + bool has_qaccept_regs; + bool has_ext_cntl_regs; + bool has_vq6; }; struct q6v5 { @@ -159,8 +169,18 @@ struct q6v5 { u32 halt_q6; u32 halt_modem; u32 halt_nc; + u32 halt_vq6; u32 conn_box; + u32 qaccept_mdm; + u32 qaccept_cx; + u32 qaccept_axi; + + u32 axim1_clk_off; + u32 crypto_clk_off; + u32 force_clk_on; + u32 rscc_disable; + struct reset_control *mss_restart; struct reset_control *pdc_reset; @@ -169,12 +189,10 @@ struct q6v5 { struct clk *active_clks[8]; struct clk *reset_clks[4]; struct clk *proxy_clks[4]; - struct device *active_pds[1]; struct device *proxy_pds[3]; int active_clk_count; int reset_clk_count; int proxy_clk_count; - int active_pd_count; int proxy_pd_count; struct reg_info active_regs[1]; @@ -204,6 +222,9 @@ struct q6v5 { bool has_alt_reset; bool has_mba_logs; bool has_spare_reg; + bool has_qaccept_regs; + bool has_ext_cntl_regs; + bool has_vq6; int mpss_perm; int mba_perm; const char *hexagon_mdt_image; @@ -216,6 +237,7 @@ enum { MSS_MSM8996, MSS_MSM8998, MSS_SC7180, + MSS_SC7280, MSS_SDM845, }; @@ -476,6 +498,12 @@ static int q6v5_reset_assert(struct q6v5 *qproc) regmap_update_bits(qproc->conn_map, qproc->conn_box, AXI_GATING_VALID_OVERRIDE, 0); ret = reset_control_deassert(qproc->mss_restart); + } else if (qproc->has_ext_cntl_regs) { + regmap_write(qproc->conn_map, qproc->rscc_disable, 0); + reset_control_assert(qproc->pdc_reset); + reset_control_assert(qproc->mss_restart); + reset_control_deassert(qproc->pdc_reset); + ret = reset_control_deassert(qproc->mss_restart); } else { ret = reset_control_assert(qproc->mss_restart); } @@ -493,7 +521,7 @@ static int q6v5_reset_deassert(struct q6v5 *qproc) ret = reset_control_reset(qproc->mss_restart); writel(0, qproc->rmb_base + RMB_MBA_ALT_RESET); reset_control_deassert(qproc->pdc_reset); - } else if (qproc->has_spare_reg) { + } else if (qproc->has_spare_reg || qproc->has_ext_cntl_regs) { ret = reset_control_reset(qproc->mss_restart); } else { ret = reset_control_deassert(qproc->mss_restart); @@ -607,7 +635,7 @@ static int q6v5proc_reset(struct q6v5 *qproc) } goto pbl_wait; - } else if (qproc->version == MSS_SC7180) { + } else if (qproc->version == MSS_SC7180 || qproc->version == MSS_SC7280) { val = readl(qproc->reg_base + QDSP6SS_SLEEP); val |= Q6SS_CBCR_CLKEN; writel(val, qproc->reg_base + QDSP6SS_SLEEP); @@ -790,6 +818,89 @@ pbl_wait: return ret; } +static int q6v5proc_enable_qchannel(struct q6v5 *qproc, struct regmap *map, u32 offset) +{ + unsigned int val; + int ret; + + if (!qproc->has_qaccept_regs) + return 0; + + if (qproc->has_ext_cntl_regs) { + regmap_write(qproc->conn_map, qproc->rscc_disable, 0); + regmap_write(qproc->conn_map, qproc->force_clk_on, 1); + + ret = regmap_read_poll_timeout(qproc->halt_map, qproc->axim1_clk_off, val, + !val, 1, Q6SS_CBCR_TIMEOUT_US); + if (ret) { + dev_err(qproc->dev, "failed to enable axim1 clock\n"); + return -ETIMEDOUT; + } + } + + regmap_write(map, offset + QACCEPT_REQ_REG, 1); + + /* Wait for accept */ + ret = regmap_read_poll_timeout(map, offset + QACCEPT_ACCEPT_REG, val, val, 5, + QACCEPT_TIMEOUT_US); + if (ret) { + dev_err(qproc->dev, "qchannel enable failed\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void q6v5proc_disable_qchannel(struct q6v5 *qproc, struct regmap *map, u32 offset) +{ + int ret; + unsigned int val, retry; + unsigned int nretry = 10; + bool takedown_complete = false; + + if (!qproc->has_qaccept_regs) + return; + + while (!takedown_complete && nretry) { + nretry--; + + /* Wait for active transactions to complete */ + regmap_read_poll_timeout(map, offset + QACCEPT_ACTIVE_REG, val, !val, 5, + QACCEPT_TIMEOUT_US); + + /* Request Q-channel transaction takedown */ + regmap_write(map, offset + QACCEPT_REQ_REG, 0); + + /* + * If the request is denied, reset the Q-channel takedown request, + * wait for active transactions to complete and retry takedown. + */ + retry = 10; + while (retry) { + usleep_range(5, 10); + retry--; + ret = regmap_read(map, offset + QACCEPT_DENY_REG, &val); + if (!ret && val) { + regmap_write(map, offset + QACCEPT_REQ_REG, 1); + break; + } + + ret = regmap_read(map, offset + QACCEPT_ACCEPT_REG, &val); + if (!ret && !val) { + takedown_complete = true; + break; + } + } + + if (!retry) + break; + } + + /* Rely on mss_restart to clear out pending transactions on takedown failure */ + if (!takedown_complete) + dev_err(qproc->dev, "qchannel takedown failed\n"); +} + static void q6v5proc_halt_axi_port(struct q6v5 *qproc, struct regmap *halt_map, u32 offset) @@ -895,18 +1006,14 @@ static int q6v5_mba_load(struct q6v5 *qproc) int xfermemop_ret; bool mba_load_err = false; - qcom_q6v5_prepare(&qproc->q6v5); - - ret = q6v5_pds_enable(qproc, qproc->active_pds, qproc->active_pd_count); - if (ret < 0) { - dev_err(qproc->dev, "failed to enable active power domains\n"); - goto disable_irqs; - } + ret = qcom_q6v5_prepare(&qproc->q6v5); + if (ret) + return ret; ret = q6v5_pds_enable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); if (ret < 0) { dev_err(qproc->dev, "failed to enable proxy power domains\n"); - goto disable_active_pds; + goto disable_irqs; } ret = q6v5_regulator_enable(qproc, qproc->fallback_proxy_regs, @@ -957,6 +1064,12 @@ static int q6v5_mba_load(struct q6v5 *qproc) goto assert_reset; } + ret = q6v5proc_enable_qchannel(qproc, qproc->halt_map, qproc->qaccept_axi); + if (ret) { + dev_err(qproc->dev, "failed to enable axi bridge\n"); + goto disable_active_clks; + } + /* * Some versions of the MBA firmware will upon boot wipe the MPSS region as well, so provide * the Q6 access to this region. @@ -1003,8 +1116,13 @@ static int q6v5_mba_load(struct q6v5 *qproc) halt_axi_ports: q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6); + if (qproc->has_vq6) + q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_vq6); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); + q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_mdm); + q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_cx); + q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_axi); mba_load_err = true; reclaim_mba: xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true, @@ -1039,8 +1157,6 @@ disable_fallback_proxy_reg: qproc->fallback_proxy_reg_count); disable_proxy_pds: q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); -disable_active_pds: - q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count); disable_irqs: qcom_q6v5_unprepare(&qproc->q6v5); @@ -1056,6 +1172,8 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc) qproc->dp_size = 0; q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6); + if (qproc->has_vq6) + q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_vq6); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); if (qproc->version == MSS_MSM8996) { @@ -1068,6 +1186,24 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc) writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); } + if (qproc->has_ext_cntl_regs) { + regmap_write(qproc->conn_map, qproc->rscc_disable, 1); + + ret = regmap_read_poll_timeout(qproc->halt_map, qproc->axim1_clk_off, val, + !val, 1, Q6SS_CBCR_TIMEOUT_US); + if (ret) + dev_err(qproc->dev, "failed to enable axim1 clock\n"); + + ret = regmap_read_poll_timeout(qproc->halt_map, qproc->crypto_clk_off, val, + !val, 1, Q6SS_CBCR_TIMEOUT_US); + if (ret) + dev_err(qproc->dev, "failed to enable crypto clock\n"); + } + + q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_mdm); + q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_cx); + q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_axi); + q6v5_reset_assert(qproc); q6v5_clk_disable(qproc->dev, qproc->reset_clks, @@ -1076,7 +1212,6 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc) qproc->active_clk_count); q6v5_regulator_disable(qproc, qproc->active_regs, qproc->active_reg_count); - q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count); /* In case of failure or coredump scenario where reclaiming MBA memory * could not happen reclaim it here. @@ -1481,6 +1616,7 @@ static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev) { struct of_phandle_args args; struct resource *res; + int halt_cell_cnt = 3; int ret; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6"); @@ -1493,8 +1629,11 @@ static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev) if (IS_ERR(qproc->rmb_base)) return PTR_ERR(qproc->rmb_base); + if (qproc->has_vq6) + halt_cell_cnt++; + ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, - "qcom,halt-regs", 3, 0, &args); + "qcom,halt-regs", halt_cell_cnt, 0, &args); if (ret < 0) { dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n"); return -EINVAL; @@ -1509,6 +1648,52 @@ static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev) qproc->halt_modem = args.args[1]; qproc->halt_nc = args.args[2]; + if (qproc->has_vq6) + qproc->halt_vq6 = args.args[3]; + + if (qproc->has_qaccept_regs) { + ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, + "qcom,qaccept-regs", + 3, 0, &args); + if (ret < 0) { + dev_err(&pdev->dev, "failed to parse qaccept-regs\n"); + return -EINVAL; + } + + qproc->qaccept_mdm = args.args[0]; + qproc->qaccept_cx = args.args[1]; + qproc->qaccept_axi = args.args[2]; + } + + if (qproc->has_ext_cntl_regs) { + ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, + "qcom,ext-regs", + 2, 0, &args); + if (ret < 0) { + dev_err(&pdev->dev, "failed to parse ext-regs index 0\n"); + return -EINVAL; + } + + qproc->conn_map = syscon_node_to_regmap(args.np); + of_node_put(args.np); + if (IS_ERR(qproc->conn_map)) + return PTR_ERR(qproc->conn_map); + + qproc->force_clk_on = args.args[0]; + qproc->rscc_disable = args.args[1]; + + ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, + "qcom,ext-regs", + 2, 1, &args); + if (ret < 0) { + dev_err(&pdev->dev, "failed to parse ext-regs index 1\n"); + return -EINVAL; + } + + qproc->axim1_clk_off = args.args[0]; + qproc->crypto_clk_off = args.args[1]; + } + if (qproc->has_spare_reg) { ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, "qcom,spare-regs", @@ -1600,7 +1785,7 @@ static int q6v5_init_reset(struct q6v5 *qproc) return PTR_ERR(qproc->mss_restart); } - if (qproc->has_alt_reset || qproc->has_spare_reg) { + if (qproc->has_alt_reset || qproc->has_spare_reg || qproc->has_ext_cntl_regs) { qproc->pdc_reset = devm_reset_control_get_exclusive(qproc->dev, "pdc_reset"); if (IS_ERR(qproc->pdc_reset)) { @@ -1707,6 +1892,9 @@ static int q6v5_probe(struct platform_device *pdev) platform_set_drvdata(pdev, qproc); + qproc->has_qaccept_regs = desc->has_qaccept_regs; + qproc->has_ext_cntl_regs = desc->has_ext_cntl_regs; + qproc->has_vq6 = desc->has_vq6; qproc->has_spare_reg = desc->has_spare_reg; ret = q6v5_init_mem(qproc, pdev); if (ret) @@ -1756,14 +1944,6 @@ static int q6v5_probe(struct platform_device *pdev) } qproc->active_reg_count = ret; - ret = q6v5_pds_attach(&pdev->dev, qproc->active_pds, - desc->active_pd_names); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to attach active power domains\n"); - goto free_rproc; - } - qproc->active_pd_count = ret; - ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds, desc->proxy_pd_names); /* Fallback to regulators for old device trees */ @@ -1773,12 +1953,12 @@ static int q6v5_probe(struct platform_device *pdev) desc->fallback_proxy_supply); if (ret < 0) { dev_err(&pdev->dev, "Failed to get fallback proxy regulators.\n"); - goto detach_active_pds; + goto free_rproc; } qproc->fallback_proxy_reg_count = ret; } else if (ret < 0) { dev_err(&pdev->dev, "Failed to init power domains\n"); - goto detach_active_pds; + goto free_rproc; } else { qproc->proxy_pd_count = ret; } @@ -1792,7 +1972,7 @@ static int q6v5_probe(struct platform_device *pdev) qproc->need_mem_protection = desc->need_mem_protection; qproc->has_mba_logs = desc->has_mba_logs; - ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, + ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, "modem", qcom_msa_handover); if (ret) goto detach_proxy_pds; @@ -1822,8 +2002,6 @@ remove_subdevs: qcom_remove_glink_subdev(rproc, &qproc->glink_subdev); detach_proxy_pds: q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count); -detach_active_pds: - q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count); free_rproc: rproc_free(rproc); @@ -1837,13 +2015,13 @@ static int q6v5_remove(struct platform_device *pdev) rproc_del(rproc); + qcom_q6v5_deinit(&qproc->q6v5); qcom_remove_sysmon_subdev(qproc->sysmon); qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev); qcom_remove_smd_subdev(rproc, &qproc->smd_subdev); qcom_remove_glink_subdev(rproc, &qproc->glink_subdev); q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count); - q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count); rproc_free(rproc); @@ -1867,10 +2045,6 @@ static const struct rproc_hexagon_res sc7180_mss = { "nav", NULL }, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", "mx", @@ -1881,9 +2055,40 @@ static const struct rproc_hexagon_res sc7180_mss = { .has_alt_reset = false, .has_mba_logs = true, .has_spare_reg = true, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, .version = MSS_SC7180, }; +static const struct rproc_hexagon_res sc7280_mss = { + .hexagon_mba_image = "mba.mbn", + .proxy_clk_names = (char*[]){ + "xo", + "pka", + NULL + }, + .active_clk_names = (char*[]){ + "iface", + "offline", + "snoc_axi", + NULL + }, + .proxy_pd_names = (char*[]){ + "cx", + "mss", + NULL + }, + .need_mem_protection = true, + .has_alt_reset = false, + .has_mba_logs = true, + .has_spare_reg = false, + .has_qaccept_regs = true, + .has_ext_cntl_regs = true, + .has_vq6 = true, + .version = MSS_SC7280, +}; + static const struct rproc_hexagon_res sdm845_mss = { .hexagon_mba_image = "mba.mbn", .proxy_clk_names = (char*[]){ @@ -1903,10 +2108,6 @@ static const struct rproc_hexagon_res sdm845_mss = { "mnoc_axi", NULL }, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", "mx", @@ -1917,6 +2118,9 @@ static const struct rproc_hexagon_res sdm845_mss = { .has_alt_reset = true, .has_mba_logs = false, .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, .version = MSS_SDM845, }; @@ -1945,6 +2149,9 @@ static const struct rproc_hexagon_res msm8998_mss = { .has_alt_reset = false, .has_mba_logs = false, .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, .version = MSS_MSM8998, }; @@ -1976,6 +2183,9 @@ static const struct rproc_hexagon_res msm8996_mss = { .has_alt_reset = false, .has_mba_logs = false, .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, .version = MSS_MSM8996, }; @@ -2018,6 +2228,9 @@ static const struct rproc_hexagon_res msm8916_mss = { .has_alt_reset = false, .has_mba_logs = false, .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, .version = MSS_MSM8916, }; @@ -2068,6 +2281,9 @@ static const struct rproc_hexagon_res msm8974_mss = { .has_alt_reset = false, .has_mba_logs = false, .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, .version = MSS_MSM8974, }; @@ -2078,6 +2294,7 @@ static const struct of_device_id q6v5_of_match[] = { { .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss}, { .compatible = "qcom,msm8998-mss-pil", .data = &msm8998_mss}, { .compatible = "qcom,sc7180-mss-pil", .data = &sc7180_mss}, + { .compatible = "qcom,sc7280-mss-pil", .data = &sc7280_mss}, { .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss}, { }, }; diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 401b1ec9078525..03857dc9cdc128 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -37,9 +37,9 @@ struct adsp_data { bool has_aggre2_clk; bool auto_boot; - char **active_pd_names; char **proxy_pd_names; + const char *load_state; const char *ssr_name; const char *sysmon_name; int ssctl_id; @@ -57,10 +57,8 @@ struct qcom_adsp { struct regulator *cx_supply; struct regulator *px_supply; - struct device *active_pds[1]; struct device *proxy_pds[3]; - int active_pd_count; int proxy_pd_count; int pas_id; @@ -149,15 +147,13 @@ static int adsp_start(struct rproc *rproc) struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; int ret; - qcom_q6v5_prepare(&adsp->q6v5); - - ret = adsp_pds_enable(adsp, adsp->active_pds, adsp->active_pd_count); - if (ret < 0) - goto disable_irqs; + ret = qcom_q6v5_prepare(&adsp->q6v5); + if (ret) + return ret; ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); if (ret < 0) - goto disable_active_pds; + goto disable_irqs; ret = clk_prepare_enable(adsp->xo); if (ret) @@ -201,8 +197,6 @@ disable_xo_clk: clk_disable_unprepare(adsp->xo); disable_proxy_pds: adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -disable_active_pds: - adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count); disable_irqs: qcom_q6v5_unprepare(&adsp->q6v5); @@ -234,7 +228,6 @@ static int adsp_stop(struct rproc *rproc) if (ret) dev_err(adsp->dev, "failed to shutdown: %d\n", ret); - adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count); handover = qcom_q6v5_unprepare(&adsp->q6v5); if (handover) qcom_pas_handover(&adsp->q6v5); @@ -456,19 +449,13 @@ static int adsp_probe(struct platform_device *pdev) if (ret) goto free_rproc; - ret = adsp_pds_attach(&pdev->dev, adsp->active_pds, - desc->active_pd_names); - if (ret < 0) - goto free_rproc; - adsp->active_pd_count = ret; - ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds, desc->proxy_pd_names); if (ret < 0) - goto detach_active_pds; + goto free_rproc; adsp->proxy_pd_count = ret; - ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, + ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state, qcom_pas_handover); if (ret) goto detach_proxy_pds; @@ -492,8 +479,6 @@ static int adsp_probe(struct platform_device *pdev) detach_proxy_pds: adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -detach_active_pds: - adsp_pds_detach(adsp, adsp->active_pds, adsp->active_pd_count); free_rproc: rproc_free(rproc); @@ -506,6 +491,7 @@ static int adsp_remove(struct platform_device *pdev) rproc_del(adsp->rproc); + qcom_q6v5_deinit(&adsp->q6v5); qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); qcom_remove_sysmon_subdev(adsp->sysmon); qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); @@ -526,20 +512,29 @@ static const struct adsp_data adsp_resource_init = { .ssctl_id = 0x14, }; +static const struct adsp_data sdm845_adsp_resource_init = { + .crash_reason_smem = 423, + .firmware_name = "adsp.mdt", + .pas_id = 1, + .has_aggre2_clk = false, + .auto_boot = true, + .load_state = "adsp", + .ssr_name = "lpass", + .sysmon_name = "adsp", + .ssctl_id = 0x14, +}; + static const struct adsp_data sm8150_adsp_resource = { .crash_reason_smem = 423, .firmware_name = "adsp.mdt", .pas_id = 1, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", NULL }, + .load_state = "adsp", .ssr_name = "lpass", .sysmon_name = "adsp", .ssctl_id = 0x14, @@ -551,15 +546,12 @@ static const struct adsp_data sm8250_adsp_resource = { .pas_id = 1, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "lcx", "lmx", NULL }, + .load_state = "adsp", .ssr_name = "lpass", .sysmon_name = "adsp", .ssctl_id = 0x14, @@ -571,21 +563,18 @@ static const struct adsp_data sm8350_adsp_resource = { .pas_id = 1, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "lcx", "lmx", NULL }, + .load_state = "adsp", .ssr_name = "lpass", .sysmon_name = "adsp", .ssctl_id = 0x14, }; -static const struct adsp_data msm8998_adsp_resource = { +static const struct adsp_data msm8996_adsp_resource = { .crash_reason_smem = 423, .firmware_name = "adsp.mdt", .pas_id = 1, @@ -611,20 +600,29 @@ static const struct adsp_data cdsp_resource_init = { .ssctl_id = 0x17, }; +static const struct adsp_data sdm845_cdsp_resource_init = { + .crash_reason_smem = 601, + .firmware_name = "cdsp.mdt", + .pas_id = 18, + .has_aggre2_clk = false, + .auto_boot = true, + .load_state = "cdsp", + .ssr_name = "cdsp", + .sysmon_name = "cdsp", + .ssctl_id = 0x17, +}; + static const struct adsp_data sm8150_cdsp_resource = { .crash_reason_smem = 601, .firmware_name = "cdsp.mdt", .pas_id = 18, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", NULL }, + .load_state = "cdsp", .ssr_name = "cdsp", .sysmon_name = "cdsp", .ssctl_id = 0x17, @@ -636,14 +634,11 @@ static const struct adsp_data sm8250_cdsp_resource = { .pas_id = 18, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", NULL }, + .load_state = "cdsp", .ssr_name = "cdsp", .sysmon_name = "cdsp", .ssctl_id = 0x17, @@ -655,14 +650,11 @@ static const struct adsp_data sm8350_cdsp_resource = { .pas_id = 18, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", NULL }, + .load_state = "cdsp", .ssr_name = "cdsp", .sysmon_name = "cdsp", .ssctl_id = 0x17, @@ -675,15 +667,12 @@ static const struct adsp_data mpss_resource_init = { .minidump_id = 3, .has_aggre2_clk = false, .auto_boot = false, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", "mss", NULL }, + .load_state = "modem", .ssr_name = "mpss", .sysmon_name = "modem", .ssctl_id = 0x12, @@ -695,14 +684,11 @@ static const struct adsp_data sc8180x_mpss_resource = { .pas_id = 4, .has_aggre2_clk = false, .auto_boot = false, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "cx", NULL }, + .load_state = "modem", .ssr_name = "mpss", .sysmon_name = "modem", .ssctl_id = 0x12, @@ -714,6 +700,10 @@ static const struct adsp_data slpi_resource_init = { .pas_id = 12, .has_aggre2_clk = true, .auto_boot = true, + .proxy_pd_names = (char*[]){ + "ssc_cx", + NULL + }, .ssr_name = "dsps", .sysmon_name = "slpi", .ssctl_id = 0x16, @@ -725,15 +715,12 @@ static const struct adsp_data sm8150_slpi_resource = { .pas_id = 12, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "lcx", "lmx", NULL }, + .load_state = "slpi", .ssr_name = "dsps", .sysmon_name = "slpi", .ssctl_id = 0x16, @@ -745,15 +732,12 @@ static const struct adsp_data sm8250_slpi_resource = { .pas_id = 12, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "lcx", "lmx", NULL }, + .load_state = "slpi", .ssr_name = "dsps", .sysmon_name = "slpi", .ssctl_id = 0x16, @@ -765,35 +749,17 @@ static const struct adsp_data sm8350_slpi_resource = { .pas_id = 12, .has_aggre2_clk = false, .auto_boot = true, - .active_pd_names = (char*[]){ - "load_state", - NULL - }, .proxy_pd_names = (char*[]){ "lcx", "lmx", NULL }, + .load_state = "slpi", .ssr_name = "dsps", .sysmon_name = "slpi", .ssctl_id = 0x16, }; -static const struct adsp_data msm8998_slpi_resource = { - .crash_reason_smem = 424, - .firmware_name = "slpi.mdt", - .pas_id = 12, - .has_aggre2_clk = true, - .auto_boot = true, - .proxy_pd_names = (char*[]){ - "ssc_cx", - NULL - }, - .ssr_name = "dsps", - .sysmon_name = "slpi", - .ssctl_id = 0x16, -}; - static const struct adsp_data wcss_resource_init = { .crash_reason_smem = 421, .firmware_name = "wcnss.mdt", @@ -822,20 +788,21 @@ static const struct adsp_data sdx55_mpss_resource = { static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, - { .compatible = "qcom,msm8996-adsp-pil", .data = &adsp_resource_init}, + { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init}, - { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8998_adsp_resource}, - { .compatible = "qcom,msm8998-slpi-pas", .data = &msm8998_slpi_resource}, + { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource}, + { .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init}, { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init}, + { .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init}, { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource}, { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource}, { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource}, { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init}, - { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init}, - { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init}, + { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init}, + { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init}, { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource}, { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource}, { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource}, diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index 20d50ec7eff1b6..bb0947f7770ea0 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -1044,8 +1044,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev) if (ret) goto free_rproc; - ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, - NULL); + ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, NULL, NULL); if (ret) goto free_rproc; @@ -1074,7 +1073,9 @@ free_rproc: static int q6v5_wcss_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); + struct q6v5_wcss *wcss = rproc->priv; + qcom_q6v5_deinit(&wcss->q6v5); rproc_del(rproc); rproc_free(rproc); diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index ebadc6c08e1160..80bbafee98463c 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -25,7 +25,6 @@ #include <linux/soc/qcom/mdt_loader.h> #include <linux/soc/qcom/smem.h> #include <linux/soc/qcom/smem_state.h> -#include <linux/rpmsg/qcom_smd.h> #include "qcom_common.h" #include "remoteproc_internal.h" diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c index aee657cc08c6a1..c892f433a323e1 100644 --- a/drivers/remoteproc/remoteproc_coredump.c +++ b/drivers/remoteproc/remoteproc_coredump.c @@ -152,8 +152,8 @@ static void rproc_copy_segment(struct rproc *rproc, void *dest, struct rproc_dump_segment *segment, size_t offset, size_t size) { + bool is_iomem = false; void *ptr; - bool is_iomem; if (segment->dump) { segment->dump(rproc, segment, dest, offset, size); diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index 469c52e62faffc..d635d19a5aa8a8 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c @@ -178,8 +178,8 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) u64 filesz = elf_phdr_get_p_filesz(class, phdr); u64 offset = elf_phdr_get_p_offset(class, phdr); u32 type = elf_phdr_get_p_type(class, phdr); + bool is_iomem = false; void *ptr; - bool is_iomem; if (type != PT_LOAD) continue; @@ -220,7 +220,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) /* put the segment where the remote processor expects it */ if (filesz) { if (is_iomem) - memcpy_fromio(ptr, (void __iomem *)(elf_data + offset), filesz); + memcpy_toio((void __iomem *)ptr, elf_data + offset, filesz); else memcpy(ptr, elf_data + offset, filesz); } diff --git a/drivers/rpmsg/mtk_rpmsg.c b/drivers/rpmsg/mtk_rpmsg.c index 96a17ec2914011..5b4404b8be4c75 100644 --- a/drivers/rpmsg/mtk_rpmsg.c +++ b/drivers/rpmsg/mtk_rpmsg.c @@ -183,7 +183,7 @@ mtk_rpmsg_match_device_subnode(struct device_node *node, const char *channel) int ret; for_each_available_child_of_node(node, child) { - ret = of_property_read_string(child, "mtk,rpmsg-name", &name); + ret = of_property_read_string(child, "mediatek,rpmsg-name", &name); if (ret) continue; diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 05533c71b10ede..c7b9de6550808b 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1440,7 +1440,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, } rpdev->ept = &channel->ept; - strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE); + strscpy_pad(rpdev->id.name, name, RPMSG_NAME_SIZE); rpdev->src = RPMSG_ADDR_ANY; rpdev->dst = RPMSG_ADDR_ANY; rpdev->ops = &glink_device_ops; diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index d97dcd049f18f8..a8dcf8a9ae885a 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -231,7 +231,7 @@ static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev /* This shouldn't be possible */ WARN_ON(1); - return ERR_PTR(-ENXIO); + return NULL; } static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) |