diff options
author | 2025-03-29 17:18:50 -0700 | |
---|---|---|
committer | 2025-03-29 17:18:50 -0700 | |
commit | 472863ab2aca6f4d2b7db828f77c36c5d1f43d9a (patch) | |
tree | 68c84d4774da92fc16aacc1689d7e4a412bedfd8 | |
parent | Merge tag 'hwlock-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux (diff) | |
parent | remoteproc: qcom_q6v5_pas: Make single-PD handling more robust (diff) | |
download | wireguard-linux-472863ab2aca6f4d2b7db828f77c36c5d1f43d9a.tar.xz wireguard-linux-472863ab2aca6f4d2b7db828f77c36c5d1f43d9a.zip |
Merge tag 'rproc-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux
Pull remoteproc updates from Bjorn Andersson:
- Transition the i.MX8MP DSP remoteproc driver to use the reset
framework for driving the run/stall reset bits
- Add support for managing the modem remoteprocessor on the Qualcomm
MSM8226, MSM8926, and SM8750 platforms
* tag 'rproc-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: (28 commits)
remoteproc: qcom_q6v5_pas: Make single-PD handling more robust
remoteproc: qcom_q6v5_pas: Use resource with CX PD for MSM8226
remoteproc: core: Clear table_sz when rproc_shutdown
remoteproc: sysmon: Update qcom_add_sysmon_subdev() comment
dt-bindings: remoteproc: Consolidate SC8180X and SM8150 PAS files
irqdomain: remoteproc: Switch to of_fwnode_handle()
remoteproc: qcom: pas: add minidump_id to SC7280 WPSS
remoteproc: imx_dsp_rproc: Document run_stall struct member
remoteproc: qcom: pas: Add SM8750 MPSS
dt-bindings: remoteproc: Add SM8750 MPSS
imx_dsp_rproc: Use reset controller API to control the DSP
reset: imx8mp-audiomix: Add support for DSP run/stall
reset: imx8mp-audiomix: Introduce active_low configuration option
reset: imx8mp-audiomix: Prepare the code for more reset bits
reset: imx8mp-audiomix: Add prefix for internal macro
dt-bindings: dsp: fsl,dsp: Add resets property
dt-bindings: reset: audiomix: Add reset ids for EARC and DSP
remoteproc: qcom_wcnss: Handle platforms with only single power domain
dt-bindings: remoteproc: qcom,wcnss-pil: Add support for single power-domain platforms
remoteproc: qcom_q6v5_mss: Add modem support on MSM8926
...
18 files changed, 499 insertions, 165 deletions
diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml index ab93ffd3d2e5..b8693e4b4b0d 100644 --- a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml +++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml @@ -82,6 +82,15 @@ properties: description: Phandle to syscon block which provide access for processor enablement + resets: + minItems: 1 + + reset-names: + minItems: 1 + items: + - const: runstall + - const: softreset + required: - compatible - reg @@ -164,6 +173,17 @@ allOf: - const: txdb1 - const: rxdb0 - const: rxdb1 + - if: + properties: + compatible: + contains: + enum: + - fsl,imx8mp-dsp + - fsl,imx8mp-hifi4 + then: + required: + - resets + - reset-names additionalProperties: false @@ -186,6 +206,7 @@ examples: }; - | #include <dt-bindings/clock/imx8mp-clock.h> + #include <dt-bindings/reset/imx8mp-reset-audiomix.h> dsp_reserved: dsp@92400000 { reg = <0x92400000 0x1000000>; no-map; @@ -220,5 +241,6 @@ examples: <&mu2 3 0>; memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>, <&dsp_vdev0vring1>, <&dsp_reserved>; - fsl,dsp-ctrl = <&audio_blk_ctrl>; + resets = <&audio_blk_ctrl IMX8MP_AUDIOMIX_DSP_RUNSTALL>; + reset-names = "runstall"; }; diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml index 588b010b2a9e..c179b560572b 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml @@ -17,8 +17,10 @@ properties: compatible: oneOf: - enum: + - qcom,msm8226-mss-pil - qcom,msm8909-mss-pil - qcom,msm8916-mss-pil + - qcom,msm8926-mss-pil - qcom,msm8953-mss-pil - qcom,msm8974-mss-pil @@ -70,16 +72,18 @@ properties: items: - description: CX proxy power domain (control handed over after startup) - description: MX proxy power domain (control handed over after startup) + (not valid for qcom,msm8226-mss-pil, qcom,msm8926-mss-pil + and qcom,msm8974-mss-pil) - description: MSS proxy power domain (control handed over after startup) (only valid for qcom,msm8953-mss-pil) - minItems: 2 + minItems: 1 power-domain-names: items: - const: cx - - const: mx + - const: mx # not valid for qcom,msm8226-mss-pil, qcom-msm8926-mss-pil and qcom,msm8974-mss-pil - const: mss # only valid for qcom,msm8953-mss-pil - minItems: 2 + minItems: 1 pll-supply: description: PLL proxy supply (control handed over after startup) @@ -106,6 +110,15 @@ properties: items: - const: stop + qcom,ext-bhs-reg: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: External power block headswitch (BHS) register + (only valid for qcom,msm8226-mss-pil) + items: + - items: + - description: phandle to external BHS syscon region + - description: offset to the external BHS register + qcom,halt-regs: $ref: /schemas/types.yaml#/definitions/phandle-array description: @@ -207,17 +220,58 @@ allOf: required: - power-domains - power-domain-names - else: + + - if: + properties: + compatible: + contains: + enum: + - qcom,msm8909-mss-pil + - qcom,msm8916-mss-pil + then: properties: power-domains: + minItems: 2 maxItems: 2 power-domain-names: + minItems: 2 maxItems: 2 - if: properties: compatible: - const: qcom,msm8974-mss-pil + contains: + enum: + - qcom,msm8226-mss-pil + - qcom,msm8926-mss-pil + - qcom,msm8974-mss-pil + then: + properties: + power-domains: + maxItems: 1 + power-domain-names: + maxItems: 1 + required: + - mx-supply + + - if: + properties: + compatible: + const: qcom,msm8226-mss-pil + then: + required: + - qcom,ext-bhs-reg + else: + properties: + qcom,ext-bhs-reg: false + + - if: + properties: + compatible: + contains: + enum: + - qcom,msm8926-mss-pil + - qcom,msm8974-mss-pil then: required: - mss-supply diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml deleted file mode 100644 index 45ee9fbe0966..000000000000 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml +++ /dev/null @@ -1,96 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/remoteproc/qcom,sc8180x-pas.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Qualcomm SC8180X Peripheral Authentication Service - -maintainers: - - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> - -description: - Qualcomm SC8180X SoC Peripheral Authentication Service loads and boots - firmware on the Qualcomm DSP Hexagon cores. - -properties: - compatible: - enum: - - qcom,sc8180x-adsp-pas - - qcom,sc8180x-cdsp-pas - - qcom,sc8180x-mpss-pas - - reg: - maxItems: 1 - - clocks: - items: - - description: XO clock - - clock-names: - items: - - const: xo - - qcom,qmp: - $ref: /schemas/types.yaml#/definitions/phandle - description: Reference to the AOSS side-channel message RAM. - - smd-edge: false - - memory-region: - maxItems: 1 - description: Reference to the reserved-memory for the Hexagon core - - firmware-name: - maxItems: 1 - description: Firmware name for the Hexagon core - -required: - - compatible - - reg - - memory-region - -allOf: - - $ref: /schemas/remoteproc/qcom,pas-common.yaml# - - if: - properties: - compatible: - enum: - - qcom,sc8180x-adsp-pas - - qcom,sc8180x-cdsp-pas - then: - properties: - interrupts: - maxItems: 5 - interrupt-names: - maxItems: 5 - else: - properties: - interrupts: - minItems: 6 - interrupt-names: - minItems: 6 - - - if: - properties: - compatible: - enum: - - qcom,sc8180x-adsp-pas - - qcom,sc8180x-cdsp-pas - then: - properties: - power-domains: - items: - - description: LCX power domain - - description: LMX power domain - power-domain-names: - items: - - const: lcx - - const: lmx - else: - properties: - # TODO: incomplete - power-domains: false - power-domain-names: false - -unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index 059cb87b4d6c..eeb6a8aafeb9 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -127,7 +127,7 @@ examples: clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; clock-names = "xo"; - firmware-name = "qcom/sm6115/adsp.mdt"; + firmware-name = "qcom/sm6115/adsp.mbn"; interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index d67386c50fa4..56ff6386534d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -60,6 +60,9 @@ allOf: properties: compatible: enum: + - qcom,sc8180x-adsp-pas + - qcom,sc8180x-cdsp-pas + - qcom,sc8180x-slpi-pas - qcom,sm8150-adsp-pas - qcom,sm8150-cdsp-pas - qcom,sm8150-slpi-pas @@ -83,6 +86,8 @@ allOf: properties: compatible: enum: + - qcom,sc8180x-adsp-pas + - qcom,sc8180x-cdsp-pas - qcom,sm8150-adsp-pas - qcom,sm8150-cdsp-pas - qcom,sm8250-cdsp-pas @@ -99,6 +104,7 @@ allOf: properties: compatible: enum: + - qcom,sc8180x-mpss-pas - qcom,sm8150-mpss-pas then: properties: @@ -115,6 +121,7 @@ allOf: properties: compatible: enum: + - qcom,sc8180x-slpi-pas - qcom,sm8150-slpi-pas - qcom,sm8250-adsp-pas - qcom,sm8250-slpi-pas diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index a24cbb61bda7..2dd479cf4821 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -24,11 +24,15 @@ properties: - qcom,sm8650-adsp-pas - qcom,sm8650-cdsp-pas - qcom,sm8650-mpss-pas + - qcom,sm8750-mpss-pas - qcom,x1e80100-adsp-pas - qcom,x1e80100-cdsp-pas - items: - const: qcom,sm8750-adsp-pas - const: qcom,sm8550-adsp-pas + - items: + - const: qcom,sm8750-cdsp-pas + - const: qcom,sm8650-cdsp-pas reg: maxItems: 1 @@ -114,6 +118,23 @@ allOf: memory-region: minItems: 3 maxItems: 3 + + - if: + properties: + compatible: + contains: + enum: + - qcom,sm8750-cdsp-pas + then: + properties: + interrupts: + maxItems: 6 + interrupt-names: + maxItems: 6 + memory-region: + minItems: 3 + maxItems: 3 + - if: properties: compatible: @@ -147,6 +168,21 @@ allOf: - if: properties: compatible: + enum: + - qcom,sm8750-mpss-pas + then: + properties: + interrupts: + minItems: 6 + interrupt-names: + minItems: 6 + memory-region: + minItems: 4 + maxItems: 4 + + - if: + properties: + compatible: contains: enum: - qcom,sm8550-adsp-pas @@ -171,6 +207,7 @@ allOf: - qcom,sdx75-mpss-pas - qcom,sm8550-mpss-pas - qcom,sm8650-mpss-pas + - qcom,sm8750-mpss-pas then: properties: power-domains: @@ -184,10 +221,11 @@ allOf: - if: properties: compatible: - enum: - - qcom,sm8550-cdsp-pas - - qcom,sm8650-cdsp-pas - - qcom,x1e80100-cdsp-pas + contains: + enum: + - qcom,sm8550-cdsp-pas + - qcom,sm8650-cdsp-pas + - qcom,x1e80100-cdsp-pas then: properties: power-domains: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml index 8e033b22d28c..117fb4d0c4ad 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml @@ -69,9 +69,11 @@ properties: CX regulator to be held on behalf of the booting of the WCNSS core. power-domains: + minItems: 1 maxItems: 2 power-domain-names: + minItems: 1 items: - const: cx - const: mx @@ -187,22 +189,43 @@ allOf: - qcom,pronto-v1-pil - qcom,pronto-v2-pil then: - properties: - vddmx-supply: - deprecated: true - description: Deprecated for qcom,pronto-v1/2-pil - - vddcx-supply: - deprecated: true - description: Deprecated for qcom,pronto-v1/2-pil - + # CX and MX must be present either as power domains or regulators oneOf: + # Both CX and MX represented as power domains - required: - power-domains - power-domain-names + properties: + power-domains: + minItems: 2 + power-domain-names: + minItems: 2 + vddmx-supply: false + vddcx-supply: false + # CX represented as power domain, MX as regulator + - required: + - power-domains + - power-domain-names + - vddmx-supply + properties: + power-domains: + maxItems: 1 + power-domain-names: + maxItems: 1 + vddcx-supply: false + # Both CX and MX represented as regulators - required: - vddmx-supply - vddcx-supply + properties: + power-domains: false + power-domain-names: false + vddmx-supply: + deprecated: true + description: Deprecated for qcom,pronto-v1/2-pil + vddcx-supply: + deprecated: true + description: Deprecated for qcom,pronto-v1/2-pil - if: properties: @@ -212,6 +235,10 @@ allOf: - qcom,pronto-v3-pil then: properties: + power-domains: + minItems: 2 + power-domain-names: + minItems: 2 vddmx-supply: false vddcx-supply: false diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index ea5024919c2f..90cb1fc13e71 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -19,6 +19,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/remoteproc.h> +#include <linux/reset.h> #include <linux/slab.h> #include "imx_rproc.h" @@ -95,6 +96,7 @@ enum imx_dsp_rp_mbox_messages { /** * struct imx_dsp_rproc - DSP remote processor state * @regmap: regmap handler + * @run_stall: reset control handle used for Run/Stall operation * @rproc: rproc handler * @dsp_dcfg: device configuration pointer * @clks: clocks needed by this device @@ -111,6 +113,7 @@ enum imx_dsp_rp_mbox_messages { */ struct imx_dsp_rproc { struct regmap *regmap; + struct reset_control *run_stall; struct rproc *rproc; const struct imx_dsp_rproc_dcfg *dsp_dcfg; struct clk_bulk_data clks[DSP_RPROC_CLK_MAX]; @@ -192,9 +195,7 @@ static int imx8mp_dsp_reset(struct imx_dsp_rproc *priv) /* Keep reset asserted for 10 cycles */ usleep_range(1, 2); - regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2, - IMX8M_AudioDSP_REG2_RUNSTALL, - IMX8M_AudioDSP_REG2_RUNSTALL); + reset_control_assert(priv->run_stall); /* Take the DSP out of reset and keep stalled for FW loading */ pwrctl = readl(dap + IMX8M_DAP_PWRCTL); @@ -231,13 +232,9 @@ static int imx8ulp_dsp_reset(struct imx_dsp_rproc *priv) /* Specific configuration for i.MX8MP */ static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = { - .src_reg = IMX8M_AudioDSP_REG2, - .src_mask = IMX8M_AudioDSP_REG2_RUNSTALL, - .src_start = 0, - .src_stop = IMX8M_AudioDSP_REG2_RUNSTALL, .att = imx_dsp_rproc_att_imx8mp, .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8mp), - .method = IMX_RPROC_MMIO, + .method = IMX_RPROC_RESET_CONTROLLER, }; static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = { @@ -329,6 +326,9 @@ static int imx_dsp_rproc_start(struct rproc *rproc) true, rproc->bootaddr); break; + case IMX_RPROC_RESET_CONTROLLER: + ret = reset_control_deassert(priv->run_stall); + break; default: return -EOPNOTSUPP; } @@ -369,6 +369,9 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) false, rproc->bootaddr); break; + case IMX_RPROC_RESET_CONTROLLER: + ret = reset_control_assert(priv->run_stall); + break; default: return -EOPNOTSUPP; } @@ -995,6 +998,13 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv) priv->regmap = regmap; break; + case IMX_RPROC_RESET_CONTROLLER: + priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall"); + if (IS_ERR(priv->run_stall)) { + dev_err(dev, "Failed to get DSP runstall reset control\n"); + return PTR_ERR(priv->run_stall); + } + break; default: ret = -EOPNOTSUPP; break; diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 17a7d051c531..cfd38d37e146 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -24,6 +24,8 @@ enum imx_rproc_method { IMX_RPROC_SMC, /* Through System Control Unit API */ IMX_RPROC_SCU_API, + /* Through Reset Controller API */ + IMX_RPROC_RESET_CONTROLLER, }; /* dcfg flags */ diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 5f463937cbbf..9c7182b3b038 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -724,6 +724,7 @@ out: * @rproc: remote processor to apply the address translation for * @da: device address to translate * @len: length of the memory buffer + * @is_iomem: pointer filled in to indicate if @da is iomapped memory * * Custom function implementing the rproc .da_to_va ops to provide address * translation (device address to kernel virtual address) for internal RAMs diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 1656574b7317..4a4eb9c0b133 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -563,7 +563,7 @@ static int pru_handle_intrmap(struct rproc *rproc) return -ENODEV; } - fwspec.fwnode = of_node_to_fwnode(irq_parent); + fwspec.fwnode = of_fwnode_handle(irq_parent); fwspec.param_count = 3; for (i = 0; i < pru->evt_count; i++) { fwspec.param[0] = rsc->pru_intc_map[i].event; diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index e78bd986dc3f..0c0199fb0e68 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -134,6 +134,11 @@ #define BOOT_FSM_TIMEOUT 10000 #define BHS_CHECK_MAX_LOOPS 200 +/* External power block headswitch */ +#define EXTERNAL_BHS_ON BIT(0) +#define EXTERNAL_BHS_STATUS BIT(4) +#define EXTERNAL_BHS_TIMEOUT_US 50 + struct reg_info { struct regulator *reg; int uV; @@ -161,6 +166,7 @@ struct rproc_hexagon_res { bool has_mba_logs; bool has_spare_reg; bool has_qaccept_regs; + bool has_ext_bhs_reg; bool has_ext_cntl_regs; bool has_vq6; }; @@ -180,6 +186,7 @@ struct q6v5 { u32 halt_nc; u32 halt_vq6; u32 conn_box; + u32 ext_bhs; u32 qaccept_mdm; u32 qaccept_cx; @@ -237,6 +244,7 @@ struct q6v5 { bool has_mba_logs; bool has_spare_reg; bool has_qaccept_regs; + bool has_ext_bhs_reg; bool has_ext_cntl_regs; bool has_vq6; u64 mpss_perm; @@ -246,8 +254,10 @@ struct q6v5 { }; enum { + MSS_MSM8226, MSS_MSM8909, MSS_MSM8916, + MSS_MSM8926, MSS_MSM8953, MSS_MSM8974, MSS_MSM8996, @@ -415,6 +425,34 @@ static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds, } } +static int q6v5_external_bhs_enable(struct q6v5 *qproc) +{ + u32 val; + int ret = 0; + + /* + * Enable external power block headswitch and wait for it to + * stabilize + */ + regmap_set_bits(qproc->conn_map, qproc->ext_bhs, EXTERNAL_BHS_ON); + + ret = regmap_read_poll_timeout(qproc->conn_map, qproc->ext_bhs, + val, val & EXTERNAL_BHS_STATUS, + 1, EXTERNAL_BHS_TIMEOUT_US); + + if (ret) { + dev_err(qproc->dev, "External BHS timed out\n"); + ret = -ETIMEDOUT; + } + + return ret; +} + +static void q6v5_external_bhs_disable(struct q6v5 *qproc) +{ + regmap_clear_bits(qproc->conn_map, qproc->ext_bhs, EXTERNAL_BHS_ON); +} + static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, u64 *current_perm, bool local, bool remote, phys_addr_t addr, size_t size) @@ -1112,11 +1150,17 @@ static int q6v5_mba_load(struct q6v5 *qproc) goto disable_proxy_clk; } + if (qproc->has_ext_bhs_reg) { + ret = q6v5_external_bhs_enable(qproc); + if (ret < 0) + goto disable_vdd; + } + ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks, qproc->reset_clk_count); if (ret) { dev_err(qproc->dev, "failed to enable reset clocks\n"); - goto disable_vdd; + goto disable_ext_bhs; } ret = q6v5_reset_deassert(qproc); @@ -1214,6 +1258,9 @@ assert_reset: disable_reset_clks: q6v5_clk_disable(qproc->dev, qproc->reset_clks, qproc->reset_clk_count); +disable_ext_bhs: + if (qproc->has_ext_bhs_reg) + q6v5_external_bhs_disable(qproc); disable_vdd: q6v5_regulator_disable(qproc, qproc->active_regs, qproc->active_reg_count); @@ -1281,6 +1328,8 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc) qproc->reset_clk_count); q6v5_clk_disable(qproc->dev, qproc->active_clks, qproc->active_clk_count); + if (qproc->has_ext_bhs_reg) + q6v5_external_bhs_disable(qproc); q6v5_regulator_disable(qproc, qproc->active_regs, qproc->active_reg_count); @@ -1750,6 +1799,23 @@ static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev) qproc->qaccept_axi = args.args[2]; } + if (qproc->has_ext_bhs_reg) { + ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, + "qcom,ext-bhs-reg", + 1, 0, &args); + if (ret < 0) { + dev_err(&pdev->dev, "failed to parse ext-bhs-reg 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->ext_bhs = args.args[0]; + } + if (qproc->has_ext_cntl_regs) { ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, "qcom,ext-regs", @@ -1831,6 +1897,13 @@ static int q6v5_pds_attach(struct device *dev, struct device **devs, while (pd_names[num_pds]) num_pds++; + /* Handle single power domain */ + if (num_pds == 1 && dev->pm_domain) { + devs[0] = dev; + pm_runtime_enable(dev); + return 1; + } + for (i = 0; i < num_pds; i++) { devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]); if (IS_ERR_OR_NULL(devs[i])) { @@ -1851,8 +1924,15 @@ unroll_attach: static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds, size_t pd_count) { + struct device *dev = qproc->dev; int i; + /* Handle single power domain */ + if (pd_count == 1 && dev->pm_domain) { + pm_runtime_disable(dev); + return; + } + for (i = 0; i < pd_count; i++) dev_pm_domain_detach(pds[i], false); } @@ -2007,6 +2087,7 @@ static int q6v5_probe(struct platform_device *pdev) platform_set_drvdata(pdev, qproc); qproc->has_qaccept_regs = desc->has_qaccept_regs; + qproc->has_ext_bhs_reg = desc->has_ext_bhs_reg; qproc->has_ext_cntl_regs = desc->has_ext_cntl_regs; qproc->has_vq6 = desc->has_vq6; qproc->has_spare_reg = desc->has_spare_reg; @@ -2160,6 +2241,7 @@ static const struct rproc_hexagon_res sc7180_mss = { .has_mba_logs = true, .has_spare_reg = true, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_SC7180, @@ -2188,6 +2270,7 @@ static const struct rproc_hexagon_res sc7280_mss = { .has_mba_logs = true, .has_spare_reg = false, .has_qaccept_regs = true, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = true, .has_vq6 = true, .version = MSS_SC7280, @@ -2219,6 +2302,7 @@ static const struct rproc_hexagon_res sdm660_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_SDM660, @@ -2254,6 +2338,7 @@ static const struct rproc_hexagon_res sdm845_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_SDM845, @@ -2285,6 +2370,7 @@ static const struct rproc_hexagon_res msm8998_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8998, @@ -2323,6 +2409,7 @@ static const struct rproc_hexagon_res msm8996_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8996, @@ -2357,6 +2444,7 @@ static const struct rproc_hexagon_res msm8909_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8909, @@ -2402,6 +2490,7 @@ static const struct rproc_hexagon_res msm8916_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8916, @@ -2437,6 +2526,7 @@ static const struct rproc_hexagon_res msm8953_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8953, @@ -2449,17 +2539,101 @@ static const struct rproc_hexagon_res msm8974_mss = { .supply = "pll", .uA = 100000, }, + { + .supply = "mx", + .uV = 1050000, + }, {} }, .fallback_proxy_supply = (struct qcom_mss_reg_res[]) { { + .supply = "cx", + .uA = 100000, + }, + {} + }, + .active_supply = (struct qcom_mss_reg_res[]) { + { + .supply = "mss", + .uV = 1050000, + .uA = 100000, + }, + {} + }, + .proxy_clk_names = (char*[]){ + "xo", + NULL + }, + .active_clk_names = (char*[]){ + "iface", + "bus", + "mem", + NULL + }, + .proxy_pd_names = (char*[]){ + "cx", + NULL + }, + .need_mem_protection = false, + .has_alt_reset = false, + .has_mba_logs = false, + .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_bhs_reg = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, + .version = MSS_MSM8974, +}; + +static const struct rproc_hexagon_res msm8226_mss = { + .hexagon_mba_image = "mba.b00", + .proxy_supply = (struct qcom_mss_reg_res[]) { + { + .supply = "pll", + .uA = 100000, + }, + { .supply = "mx", .uV = 1050000, }, + {} + }, + .proxy_clk_names = (char*[]){ + "xo", + NULL + }, + .active_clk_names = (char*[]){ + "iface", + "bus", + "mem", + NULL + }, + .proxy_pd_names = (char*[]){ + "cx", + NULL + }, + .need_mem_protection = false, + .has_alt_reset = false, + .has_mba_logs = false, + .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_bhs_reg = true, + .has_ext_cntl_regs = false, + .has_vq6 = false, + .version = MSS_MSM8226, +}; + +static const struct rproc_hexagon_res msm8926_mss = { + .hexagon_mba_image = "mba.b00", + .proxy_supply = (struct qcom_mss_reg_res[]) { { - .supply = "cx", + .supply = "pll", .uA = 100000, }, + { + .supply = "mx", + .uV = 1050000, + }, {} }, .active_supply = (struct qcom_mss_reg_res[]) { @@ -2481,7 +2655,6 @@ static const struct rproc_hexagon_res msm8974_mss = { NULL }, .proxy_pd_names = (char*[]){ - "mx", "cx", NULL }, @@ -2490,15 +2663,18 @@ static const struct rproc_hexagon_res msm8974_mss = { .has_mba_logs = false, .has_spare_reg = false, .has_qaccept_regs = false, + .has_ext_bhs_reg = false, .has_ext_cntl_regs = false, .has_vq6 = false, - .version = MSS_MSM8974, + .version = MSS_MSM8926, }; static const struct of_device_id q6v5_of_match[] = { { .compatible = "qcom,q6v5-pil", .data = &msm8916_mss}, + { .compatible = "qcom,msm8226-mss-pil", .data = &msm8226_mss}, { .compatible = "qcom,msm8909-mss-pil", .data = &msm8909_mss}, { .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss}, + { .compatible = "qcom,msm8926-mss-pil", .data = &msm8926_mss}, { .compatible = "qcom,msm8953-mss-pil", .data = &msm8953_mss}, { .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss}, { .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss}, diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 97c4bdd9222a..b306f223127c 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -501,16 +501,16 @@ static int adsp_pds_attach(struct device *dev, struct device **devs, if (!pd_names) return 0; + while (pd_names[num_pds]) + num_pds++; + /* Handle single power domain */ - if (dev->pm_domain) { + if (num_pds == 1 && dev->pm_domain) { devs[0] = dev; pm_runtime_enable(dev); return 1; } - while (pd_names[num_pds]) - num_pds++; - for (i = 0; i < num_pds; i++) { devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]); if (IS_ERR_OR_NULL(devs[i])) { @@ -535,7 +535,7 @@ static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds, int i; /* Handle single power domain */ - if (dev->pm_domain && pd_count) { + if (pd_count == 1 && dev->pm_domain) { pm_runtime_disable(dev); return; } @@ -1348,6 +1348,7 @@ static const struct adsp_data sc7280_wpss_resource = { .crash_reason_smem = 626, .firmware_name = "wpss.mdt", .pas_id = 6, + .minidump_id = 4, .auto_boot = false, .proxy_pd_names = (char*[]){ "cx", @@ -1409,8 +1410,32 @@ static const struct adsp_data sm8650_mpss_resource = { .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, }; +static const struct adsp_data sm8750_mpss_resource = { + .crash_reason_smem = 421, + .firmware_name = "modem.mdt", + .dtb_firmware_name = "modem_dtb.mdt", + .pas_id = 4, + .dtb_pas_id = 0x26, + .minidump_id = 3, + .auto_boot = false, + .decrypt_shutdown = true, + .proxy_pd_names = (char*[]){ + "cx", + "mss", + NULL + }, + .load_state = "modem", + .ssr_name = "mpss", + .sysmon_name = "modem", + .ssctl_id = 0x12, + .smem_host_id = 1, + .region_assign_idx = 2, + .region_assign_count = 2, + .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, +}; + static const struct of_device_id adsp_of_match[] = { - { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init}, + { .compatible = "qcom,msm8226-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource}, @@ -1474,6 +1499,7 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,sm8650-adsp-pas", .data = &sm8550_adsp_resource}, { .compatible = "qcom,sm8650-cdsp-pas", .data = &sm8650_cdsp_resource}, { .compatible = "qcom,sm8650-mpss-pas", .data = &sm8650_mpss_resource}, + { .compatible = "qcom,sm8750-mpss-pas", .data = &sm8750_mpss_resource}, { .compatible = "qcom,x1e80100-adsp-pas", .data = &x1e80100_adsp_resource}, { .compatible = "qcom,x1e80100-cdsp-pas", .data = &x1e80100_cdsp_resource}, { }, diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c index c24e4a882873..660ac6fc4082 100644 --- a/drivers/remoteproc/qcom_sysmon.c +++ b/drivers/remoteproc/qcom_sysmon.c @@ -619,7 +619,7 @@ static irqreturn_t sysmon_shutdown_interrupt(int irq, void *data) * @name: name of this subdev, to use in SSR * @ssctl_instance: instance id of the ssctl QMI service * - * Return: A new qcom_sysmon object, or NULL on failure + * Return: A new qcom_sysmon object, or an error pointer on failure */ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, const char *name, diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 5b5664603eed..775b056d795a 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -117,10 +117,10 @@ static const struct wcnss_data pronto_v1_data = { .pmu_offset = 0x1004, .spare_offset = 0x1088, - .pd_names = { "mx", "cx" }, + .pd_names = { "cx", "mx" }, .vregs = (struct wcnss_vreg_info[]) { - { "vddmx", 950000, 1150000, 0 }, { "vddcx", .super_turbo = true}, + { "vddmx", 950000, 1150000, 0 }, { "vddpx", 1800000, 1800000, 0 }, }, .num_pd_vregs = 2, @@ -131,10 +131,10 @@ static const struct wcnss_data pronto_v2_data = { .pmu_offset = 0x1004, .spare_offset = 0x1088, - .pd_names = { "mx", "cx" }, + .pd_names = { "cx", "mx" }, .vregs = (struct wcnss_vreg_info[]) { - { "vddmx", 1287500, 1287500, 0 }, { "vddcx", .super_turbo = true }, + { "vddmx", 1287500, 1287500, 0 }, { "vddpx", 1800000, 1800000, 0 }, }, .num_pd_vregs = 2, @@ -397,8 +397,17 @@ static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev) static int wcnss_init_pds(struct qcom_wcnss *wcnss, const char * const pd_names[WCNSS_MAX_PDS]) { + struct device *dev = wcnss->dev; int i, ret; + /* Handle single power domain */ + if (dev->pm_domain) { + wcnss->pds[0] = dev; + wcnss->num_pds = 1; + pm_runtime_enable(dev); + return 0; + } + for (i = 0; i < WCNSS_MAX_PDS; i++) { if (!pd_names[i]) break; @@ -418,8 +427,15 @@ static int wcnss_init_pds(struct qcom_wcnss *wcnss, static void wcnss_release_pds(struct qcom_wcnss *wcnss) { + struct device *dev = wcnss->dev; int i; + /* Handle single power domain */ + if (wcnss->num_pds == 1 && dev->pm_domain) { + pm_runtime_disable(dev); + return; + } + for (i = 0; i < wcnss->num_pds; i++) dev_pm_domain_detach(wcnss->pds[i], false); } @@ -437,10 +453,13 @@ static int wcnss_init_regulators(struct qcom_wcnss *wcnss, * the regulators for the power domains. For old device trees we need to * reserve extra space to manage them through the regulator interface. */ - if (wcnss->num_pds) - info += num_pd_vregs; - else + if (wcnss->num_pds) { + info += wcnss->num_pds; + /* Handle single power domain case */ + num_vregs += num_pd_vregs - wcnss->num_pds; + } else { num_vregs += num_pd_vregs; + } bulk = devm_kcalloc(wcnss->dev, num_vregs, sizeof(struct regulator_bulk_data), diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index c2cf0d277729..b21eedefff87 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2025,6 +2025,7 @@ int rproc_shutdown(struct rproc *rproc) kfree(rproc->cached_table); rproc->cached_table = NULL; rproc->table_ptr = NULL; + rproc->table_sz = 0; out: mutex_unlock(&rproc->lock); return ret; diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c index 6e3f3069f727..6b357adfe646 100644 --- a/drivers/reset/reset-imx8mp-audiomix.c +++ b/drivers/reset/reset-imx8mp-audiomix.c @@ -3,6 +3,8 @@ * Copyright 2024 NXP */ +#include <dt-bindings/reset/imx8mp-reset-audiomix.h> + #include <linux/auxiliary_bus.h> #include <linux/device.h> #include <linux/io.h> @@ -11,8 +13,36 @@ #include <linux/of_address.h> #include <linux/reset-controller.h> -#define EARC 0x200 -#define EARC_RESET_MASK 0x3 +#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200 +#define IMX8MP_AUDIOMIX_EARC_RESET_MASK BIT(1) +#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK BIT(2) + +#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET 0x108 +#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK BIT(5) + +struct imx8mp_reset_map { + unsigned int offset; + unsigned int mask; + bool active_low; +}; + +static const struct imx8mp_reset_map reset_map[] = { + [IMX8MP_AUDIOMIX_EARC_RESET] = { + .offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET, + .mask = IMX8MP_AUDIOMIX_EARC_RESET_MASK, + .active_low = true, + }, + [IMX8MP_AUDIOMIX_EARC_PHY_RESET] = { + .offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET, + .mask = IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK, + .active_low = true, + }, + [IMX8MP_AUDIOMIX_DSP_RUNSTALL] = { + .offset = IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET, + .mask = IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK, + .active_low = false, + }, +}; struct imx8mp_audiomix_reset { struct reset_controller_dev rcdev; @@ -25,38 +55,42 @@ static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_contr return container_of(rcdev, struct imx8mp_audiomix_reset, rcdev); } -static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) +static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) { struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev); void __iomem *reg_addr = priv->base; - unsigned int mask, reg; - unsigned long flags; + unsigned int mask, offset, active_low; + unsigned long reg, flags; + + mask = reset_map[id].mask; + offset = reset_map[id].offset; + active_low = reset_map[id].active_low; - mask = BIT(id); spin_lock_irqsave(&priv->lock, flags); - reg = readl(reg_addr + EARC); - writel(reg & ~mask, reg_addr + EARC); + + reg = readl(reg_addr + offset); + if (active_low ^ assert) + reg |= mask; + else + reg &= ~mask; + writel(reg, reg_addr + offset); + spin_unlock_irqrestore(&priv->lock, flags); return 0; } +static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return imx8mp_audiomix_update(rcdev, id, true); +} + static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) { - struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev); - void __iomem *reg_addr = priv->base; - unsigned int mask, reg; - unsigned long flags; - - mask = BIT(id); - spin_lock_irqsave(&priv->lock, flags); - reg = readl(reg_addr + EARC); - writel(reg | mask, reg_addr + EARC); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; + return imx8mp_audiomix_update(rcdev, id, false); } static const struct reset_control_ops imx8mp_audiomix_reset_ops = { @@ -78,7 +112,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev, spin_lock_init(&priv->lock); priv->rcdev.owner = THIS_MODULE; - priv->rcdev.nr_resets = fls(EARC_RESET_MASK); + priv->rcdev.nr_resets = ARRAY_SIZE(reset_map); priv->rcdev.ops = &imx8mp_audiomix_reset_ops; priv->rcdev.of_node = dev->parent->of_node; priv->rcdev.dev = dev; diff --git a/include/dt-bindings/reset/imx8mp-reset-audiomix.h b/include/dt-bindings/reset/imx8mp-reset-audiomix.h new file mode 100644 index 000000000000..746c1337ed99 --- /dev/null +++ b/include/dt-bindings/reset/imx8mp-reset-audiomix.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* + * Copyright 2025 NXP + */ + +#ifndef DT_BINDING_RESET_IMX8MP_AUDIOMIX_H +#define DT_BINDING_RESET_IMX8MP_AUDIOMIX_H + +#define IMX8MP_AUDIOMIX_EARC_RESET 0 +#define IMX8MP_AUDIOMIX_EARC_PHY_RESET 1 +#define IMX8MP_AUDIOMIX_DSP_RUNSTALL 2 + +#endif /* DT_BINDING_RESET_IMX8MP_AUDIOMIX_H */ |