Commit c35f902c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull remoteproc updates from Bjorn Andersson:

 - Enable coredump support for the i.MX HiFi core remoteproc, and clean
   up the i.MX remoteproc driver.

 - Introduce remoteprocs on the Qualcomm Milos platform. Gracefully shut
   own the ADSP remoteproc when bootloader has loaded the "Lite"
   firmware on X Elite. Improve the resource handover procedure to avoid
   possibly duplicate handling.

 - Transition the TI DA8xx, TI Keystone, and TI Wakeup M3 remoteproc
   drivers to handle resources using devres.

* tag 'rproc-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: (29 commits)
  remoteproc: pru: Fix potential NULL pointer dereference in pru_rproc_set_ctable()
  remoteproc: qcom: pas: Drop redundant assignment to ret
  remoteproc: qcom: pas: Shutdown lite ADSP DTB on X1E
  remoteproc: qcom: q6v5: Avoid handling handover twice
  remoteproc: qcom: q6v5: Avoid disabling handover IRQ twice
  remoteproc: qcom: pas: Add Milos remoteproc support
  dt-bindings: remoteproc: qcom,milos-pas: Document remoteprocs
  remoteproc: qcom_q6v5_mss: support loading MBN file on msm8974
  remoteproc: imx_rproc: Clean up after ops introduction
  remoteproc: imx_rproc: Simplify IMX_RPROC_SMC switch case
  remoteproc: imx_rproc: Simplify IMX_RPROC_SCU_API switch case
  remoteproc: imx_rproc: Simplify IMX_RPROC_MMIO switch case
  remoteproc: imx_rproc: Move imx_rproc_dcfg closer to imx_rproc_of_match
  remoteproc: imx_rproc: Introduce start/stop/detect_mode ops for imx_rproc_dcfg
  remoteproc: k3: Correctly release some resources allocated in k3_rproc_request_mbox()
  remoteproc: wkup_m3: Use devm_rproc_add() helper
  remoteproc: wkup_m3: Use devm_rproc_alloc() helper
  remoteproc: wkup_m3: Use devm action to call PM runtime put sync
  remoteproc: wkup_m3: Use devm_pm_runtime_enable() helper
  remoteproc: keystone: Use devm_rproc_add() helper
  ...
parents 54ba6d9b d41e075b
Loading
Loading
Loading
Loading
+198 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/remoteproc/qcom,milos-pas.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Qualcomm Milos SoC Peripheral Authentication Service

maintainers:
  - Luca Weiss <luca.weiss@fairphone.com>

description:
  Qualcomm Milos SoC Peripheral Authentication Service loads and boots firmware
  on the Qualcomm DSP Hexagon cores.

properties:
  compatible:
    enum:
      - qcom,milos-adsp-pas
      - qcom,milos-cdsp-pas
      - qcom,milos-mpss-pas
      - qcom,milos-wpss-pas

  reg:
    maxItems: 1

  clocks:
    items:
      - description: XO clock

  clock-names:
    items:
      - const: xo

  interrupts:
    minItems: 6
    maxItems: 6

  interrupt-names:
    minItems: 6
    maxItems: 6

  qcom,qmp:
    $ref: /schemas/types.yaml#/definitions/phandle
    description: Reference to the AOSS side-channel message RAM.

  smd-edge: false

  firmware-name:
    minItems: 1
    items:
      - description: Firmware name of the Hexagon core
      - description: Firmware name of the Hexagon Devicetree

  memory-region:
    minItems: 1
    items:
      - description: Memory region for core Firmware authentication
      - description: Memory region for Devicetree Firmware authentication

required:
  - compatible
  - reg
  - memory-region

allOf:
  - $ref: /schemas/remoteproc/qcom,pas-common.yaml#
  - if:
      properties:
        compatible:
          enum:
            - qcom,milos-adsp-pas
            - qcom,milos-cdsp-pas
    then:
      properties:
        memory-region:
          minItems: 2
        firmware-name:
          minItems: 2
    else:
      properties:
        memory-region:
          maxItems: 1
        firmware-name:
          maxItems: 1

  - if:
      properties:
        compatible:
          contains:
            enum:
              - qcom,milos-adsp-pas
    then:
      properties:
        power-domains:
          items:
            - description: LCX power domain
            - description: LMX power domain
        power-domain-names:
          items:
            - const: lcx
            - const: lmx

  - if:
      properties:
        compatible:
          enum:
            - qcom,milos-cdsp-pas
            - qcom,milos-wpss-pas
    then:
      properties:
        power-domains:
          items:
            - description: CX power domain
            - description: MX power domain
        power-domain-names:
          items:
            - const: cx
            - const: mx

  - if:
      properties:
        compatible:
          enum:
            - qcom,milos-mpss-pas
    then:
      properties:
        power-domains:
          items:
            - description: CX power domain
            - description: MSS power domain
        power-domain-names:
          items:
            - const: cx
            - const: mss

unevaluatedProperties: false

examples:
  - |
    #include <dt-bindings/clock/qcom,rpmh.h>
    #include <dt-bindings/interconnect/qcom,icc.h>
    #include <dt-bindings/interconnect/qcom,milos-rpmh.h>
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/mailbox/qcom-ipcc.h>
    #include <dt-bindings/power/qcom,rpmhpd.h>

    remoteproc@3000000 {
        compatible = "qcom,milos-adsp-pas";
        reg = <0x03000000 0x10000>;

        interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
                              <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>,
                              <&smp2p_adsp_in 7 IRQ_TYPE_EDGE_RISING>;
        interrupt-names = "wdog",
                          "fatal",
                          "ready",
                          "handover",
                          "stop-ack",
                          "shutdown-ack";

        clocks = <&rpmhcc RPMH_CXO_CLK>;
        clock-names = "xo";

        power-domains = <&rpmhpd RPMHPD_LCX>,
                        <&rpmhpd RPMHPD_LMX>;
        power-domain-names = "lcx",
                             "lmx";

        interconnects = <&lpass_ag_noc MASTER_LPASS_PROC QCOM_ICC_TAG_ALWAYS
                         &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;

        memory-region = <&adspslpi_mem>, <&q6_adsp_dtb_mem>;

        firmware-name = "qcom/milos/vendor/device/adsp.mbn",
                        "qcom/milos/vendor/device/adsp_dtb.mbn";

        qcom,qmp = <&aoss_qmp>;

        qcom,smem-states = <&smp2p_adsp_out 0>;
        qcom,smem-state-names = "stop";

        glink-edge {
            interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
                                         IPCC_MPROC_SIGNAL_GLINK_QMP
                                         IRQ_TYPE_EDGE_RISING>;
            mboxes = <&ipcc IPCC_CLIENT_LPASS
                            IPCC_MPROC_SIGNAL_GLINK_QMP>;

            label = "lpass";
            qcom,remote-pid = <2>;

            /* ... */
        };
    };
+17 −40
Original line number Diff line number Diff line
@@ -233,6 +233,13 @@ static int da8xx_rproc_get_internal_memories(struct platform_device *pdev,
	return 0;
}

static void da8xx_rproc_mem_release(void *data)
{
	struct device *dev = data;

	of_reserved_mem_device_release(dev);
}

static int da8xx_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
@@ -274,14 +281,13 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
		ret = of_reserved_mem_device_init(dev);
		if (ret)
			return dev_err_probe(dev, ret, "device does not have specific CMA pool\n");
		devm_add_action_or_reset(&pdev->dev, da8xx_rproc_mem_release, &pdev->dev);
	}

	rproc = rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name,
	rproc = devm_rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name,
				 sizeof(*drproc));
	if (!rproc) {
		ret = -ENOMEM;
		goto free_mem;
	}
	if (!rproc)
		return -ENOMEM;

	/* error recovery is not supported at present */
	rproc->recovery_disabled = true;
@@ -294,9 +300,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)

	ret = da8xx_rproc_get_internal_memories(pdev, drproc);
	if (ret)
		goto free_rproc;

	platform_set_drvdata(pdev, rproc);
		return ret;

	/* everything the ISR needs is now setup, so hook it up */
	ret = devm_request_threaded_irq(dev, irq, da8xx_rproc_callback,
@@ -304,7 +308,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
					rproc);
	if (ret) {
		dev_err(dev, "devm_request_threaded_irq error: %d\n", ret);
		goto free_rproc;
		return ret;
	}

	/*
@@ -314,7 +318,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
	 */
	ret = reset_control_assert(dsp_reset);
	if (ret)
		goto free_rproc;
		return ret;

	drproc->chipsig = chipsig;
	drproc->bootreg = bootreg;
@@ -322,39 +326,13 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
	drproc->irq_data = irq_data;
	drproc->irq = irq;

	ret = rproc_add(rproc);
	ret = devm_rproc_add(dev, rproc);
	if (ret) {
		dev_err(dev, "rproc_add failed: %d\n", ret);
		goto free_rproc;
	}

	return 0;

free_rproc:
	rproc_free(rproc);
free_mem:
	if (dev->of_node)
		of_reserved_mem_device_release(dev);
		return ret;
	}

static void da8xx_rproc_remove(struct platform_device *pdev)
{
	struct rproc *rproc = platform_get_drvdata(pdev);
	struct da8xx_rproc *drproc = rproc->priv;
	struct device *dev = &pdev->dev;

	/*
	 * The devm subsystem might end up releasing things before
	 * freeing the irq, thus allowing an interrupt to sneak in while
	 * the device is being removed.  This should prevent that.
	 */
	disable_irq(drproc->irq);

	rproc_del(rproc);
	rproc_free(rproc);
	if (dev->of_node)
		of_reserved_mem_device_release(dev);
	return 0;
}

static const struct of_device_id davinci_rproc_of_match[] __maybe_unused = {
@@ -365,7 +343,6 @@ MODULE_DEVICE_TABLE(of, davinci_rproc_of_match);

static struct platform_driver da8xx_rproc_driver = {
	.probe = da8xx_rproc_probe,
	.remove = da8xx_rproc_remove,
	.driver = {
		.name = "davinci-rproc",
		.of_match_table = of_match_ptr(davinci_rproc_of_match),
+29 −16
Original line number Diff line number Diff line
@@ -774,7 +774,6 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc)
{
	struct imx_dsp_rproc *priv = rproc->priv;
	struct device *dev = rproc->dev.parent;
	struct rproc_mem_entry *carveout;
	int ret;

	ret = imx_dsp_rproc_add_carveout(priv);
@@ -785,15 +784,6 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc)

	pm_runtime_get_sync(dev);

	/*
	 * Clear buffers after pm rumtime for internal ocram is not
	 * accessible if power and clock are not enabled.
	 */
	list_for_each_entry(carveout, &rproc->carveouts, node) {
		if (carveout->va)
			memset(carveout->va, 0, carveout->len);
	}

	return  0;
}

@@ -1022,13 +1012,39 @@ static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw
	return 0;
}

static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw)
{
	struct imx_dsp_rproc *priv = rproc->priv;
	const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg;
	struct rproc_mem_entry *carveout;
	int ret;

	/* Reset DSP if needed */
	if (dsp_dcfg->reset)
		dsp_dcfg->reset(priv);
	/*
	 * Clear buffers after pm rumtime for internal ocram is not
	 * accessible if power and clock are not enabled.
	 */
	list_for_each_entry(carveout, &rproc->carveouts, node) {
		if (carveout->va)
			memset(carveout->va, 0, carveout->len);
	}

	ret = imx_dsp_rproc_elf_load_segments(rproc, fw);
	if (ret)
		return ret;

	return 0;
}

static const struct rproc_ops imx_dsp_rproc_ops = {
	.prepare	= imx_dsp_rproc_prepare,
	.unprepare	= imx_dsp_rproc_unprepare,
	.start		= imx_dsp_rproc_start,
	.stop		= imx_dsp_rproc_stop,
	.kick		= imx_dsp_rproc_kick,
	.load		= imx_dsp_rproc_elf_load_segments,
	.load		= imx_dsp_rproc_load,
	.parse_fw	= imx_dsp_rproc_parse_fw,
	.handle_rsc	= imx_dsp_rproc_handle_rsc,
	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
@@ -1189,6 +1205,8 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev)
		goto err_detach_domains;
	}

	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_XTENSA);

	pm_runtime_enable(dev);

	return 0;
@@ -1214,7 +1232,6 @@ static int imx_dsp_runtime_resume(struct device *dev)
{
	struct rproc *rproc = dev_get_drvdata(dev);
	struct imx_dsp_rproc *priv = rproc->priv;
	const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg;
	int ret;

	/*
@@ -1235,10 +1252,6 @@ static int imx_dsp_runtime_resume(struct device *dev)
		return ret;
	}

	/* Reset DSP if needed */
	if (dsp_dcfg->reset)
		dsp_dcfg->reset(priv);

	return 0;
}

+258 −191
Original line number Diff line number Diff line
@@ -285,161 +285,101 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = {
	{ 0x80000000, 0x80000000, 0x60000000, 0 },
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX8M_M7_STOP,
	.gpr_reg	= IMX8M_GPR22,
	.gpr_wait	= IMX8M_GPR22_CM7_CPUWAIT,
	.att		= imx_rproc_att_imx8mn,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
	.method		= IMX_RPROC_MMIO,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = {
	.att		= imx_rproc_att_imx8mn,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
	.method		= IMX_RPROC_SMC,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX7D_M4_STOP,
	.att		= imx_rproc_att_imx8mq,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mq),
	.method		= IMX_RPROC_MMIO,
};
static int imx_rproc_arm_smc_start(struct rproc *rproc)
{
	struct arm_smccc_res res;

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qm = {
	.att            = imx_rproc_att_imx8qm,
	.att_size       = ARRAY_SIZE(imx_rproc_att_imx8qm),
	.method         = IMX_RPROC_SCU_API,
};
	arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res);

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qxp = {
	.att		= imx_rproc_att_imx8qxp,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8qxp),
	.method		= IMX_RPROC_SCU_API,
};
	return res.a0;
}

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = {
	.att		= imx_rproc_att_imx8ulp,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8ulp),
	.method		= IMX_RPROC_NONE,
};
static int imx_rproc_mmio_start(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;

static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = {
	.att		= imx_rproc_att_imx7ulp,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx7ulp),
	.method		= IMX_RPROC_NONE,
	.flags		= IMX_RPROC_NEED_SYSTEM_OFF,
};
	if (priv->gpr)
		return regmap_clear_bits(priv->gpr, dcfg->gpr_reg, dcfg->gpr_wait);

static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX7D_M4_STOP,
	.att		= imx_rproc_att_imx7d,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx7d),
	.method		= IMX_RPROC_MMIO,
};
	return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start);
}

static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = {
	.src_reg	= IMX6SX_SRC_SCR,
	.src_mask	= IMX6SX_M4_RST_MASK,
	.src_start	= IMX6SX_M4_START,
	.src_stop	= IMX6SX_M4_STOP,
	.att		= imx_rproc_att_imx6sx,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx6sx),
	.method		= IMX_RPROC_MMIO,
};
static int imx_rproc_scu_api_start(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;

static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
	.att		= imx_rproc_att_imx93,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx93),
	.method		= IMX_RPROC_SMC,
};
	return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry);
}

static int imx_rproc_start(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
	struct device *dev = priv->dev;
	struct arm_smccc_res res;
	int ret;

	ret = imx_rproc_xtr_mbox_init(rproc, true);
	if (ret)
		return ret;

	switch (dcfg->method) {
	case IMX_RPROC_MMIO:
		if (priv->gpr) {
			ret = regmap_clear_bits(priv->gpr, dcfg->gpr_reg,
						dcfg->gpr_wait);
		} else {
			ret = regmap_update_bits(priv->regmap, dcfg->src_reg,
						 dcfg->src_mask,
						 dcfg->src_start);
		}
		break;
	case IMX_RPROC_SMC:
		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res);
		ret = res.a0;
		break;
	case IMX_RPROC_SCU_API:
		ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry);
		break;
	default:
	if (!dcfg->ops || !dcfg->ops->start)
		return -EOPNOTSUPP;
	}

	ret = dcfg->ops->start(rproc);
	if (ret)
		dev_err(dev, "Failed to enable remote core!\n");

	return ret;
}

static int imx_rproc_stop(struct rproc *rproc)
static int imx_rproc_arm_smc_stop(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
	struct device *dev = priv->dev;
	struct arm_smccc_res res;

	arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res);
	if (res.a1)
		dev_info(priv->dev, "Not in wfi, force stopped\n");

	return res.a0;
}

static int imx_rproc_mmio_stop(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
	int ret;

	switch (dcfg->method) {
	case IMX_RPROC_MMIO:
	if (priv->gpr) {
			ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg,
					      dcfg->gpr_wait);
		ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg, dcfg->gpr_wait);
		if (ret) {
				dev_err(priv->dev,
					"Failed to quiescence M4 platform!\n");
			dev_err(priv->dev, "Failed to quiescence M4 platform!\n");
			return ret;
		}
	}

		ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
					 dcfg->src_stop);
		break;
	case IMX_RPROC_SMC:
		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res);
		ret = res.a0;
		if (res.a1)
			dev_info(dev, "Not in wfi, force stopped\n");
		break;
	case IMX_RPROC_SCU_API:
		ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry);
		break;
	default:
		return -EOPNOTSUPP;
	return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop);
}

static int imx_rproc_scu_api_stop(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;

	return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry);
}

static int imx_rproc_stop(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
	struct device *dev = priv->dev;
	int ret;

	if (!dcfg->ops || !dcfg->ops->stop)
		return -EOPNOTSUPP;

	ret = dcfg->ops->stop(rproc);
	if (ret)
		dev_err(dev, "Failed to stop remote core\n");
	else
@@ -922,27 +862,73 @@ static int imx_rproc_attach_pd(struct imx_rproc *priv)
	return 0;
}

static int imx_rproc_detect_mode(struct imx_rproc *priv)
static int imx_rproc_arm_smc_detect_mode(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	struct arm_smccc_res res;

	arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res);
	if (res.a0)
		priv->rproc->state = RPROC_DETACHED;

	return 0;
}

static int imx_rproc_mmio_detect_mode(struct rproc *rproc)
{
	struct regmap_config config = { .name = "imx-rproc" };
	const struct regmap_config config = { .name = "imx-rproc" };
	struct imx_rproc *priv = rproc->priv;
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
	struct device *dev = priv->dev;
	struct regmap *regmap;
	struct arm_smccc_res res;
	int ret;
	u32 val;
	u8 pt;
	int ret;

	switch (dcfg->method) {
	case IMX_RPROC_NONE:
		priv->rproc->state = RPROC_DETACHED;
	priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr");
	if (IS_ERR(priv->gpr))
		priv->gpr = NULL;

	regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
	if (IS_ERR(regmap)) {
		dev_err(dev, "failed to find syscon\n");
		return PTR_ERR(regmap);
	}

	priv->regmap = regmap;
	regmap_attach_dev(dev, regmap, &config);

	if (priv->gpr) {
		ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val);
		if (val & dcfg->gpr_wait) {
			/*
			 * After cold boot, the CM indicates its in wait
			 * state, but not fully powered off. Power it off
			 * fully so firmware can be loaded into it.
			 */
			imx_rproc_stop(priv->rproc);
			return 0;
	case IMX_RPROC_SMC:
		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res);
		if (res.a0)
		}
	}

	ret = regmap_read(regmap, dcfg->src_reg, &val);
	if (ret) {
		dev_err(dev, "Failed to read src\n");
		return ret;
	}

	if ((val & dcfg->src_mask) != dcfg->src_stop)
		priv->rproc->state = RPROC_DETACHED;

	return 0;
	case IMX_RPROC_SCU_API:
}

static int imx_rproc_scu_api_detect_mode(struct rproc *rproc)
{
	struct imx_rproc *priv = rproc->priv;
	struct device *dev = priv->dev;
	int ret;
	u8 pt;

	ret = imx_scu_get_handle(&priv->ipc_handle);
	if (ret)
		return ret;
@@ -997,46 +983,22 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv)
	}

	return 0;
	default:
		break;
	}

	priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr");
	if (IS_ERR(priv->gpr))
		priv->gpr = NULL;

	regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
	if (IS_ERR(regmap)) {
		dev_err(dev, "failed to find syscon\n");
		return PTR_ERR(regmap);
}

	priv->regmap = regmap;
	regmap_attach_dev(dev, regmap, &config);
static int imx_rproc_detect_mode(struct imx_rproc *priv)
{
	const struct imx_rproc_dcfg *dcfg = priv->dcfg;

	if (priv->gpr) {
		ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val);
		if (val & dcfg->gpr_wait) {
	/*
			 * After cold boot, the CM indicates its in wait
			 * state, but not fully powered off. Power it off
			 * fully so firmware can be loaded into it.
	 * To i.MX{7,8} ULP, Linux is under control of RTOS, no need
	 * dcfg->ops or dcfg->ops->detect_mode, it is state RPROC_DETACHED.
	 */
			imx_rproc_stop(priv->rproc);
	if (!dcfg->ops || !dcfg->ops->detect_mode) {
		priv->rproc->state = RPROC_DETACHED;
		return 0;
	}
	}

	ret = regmap_read(regmap, dcfg->src_reg, &val);
	if (ret) {
		dev_err(dev, "Failed to read src\n");
		return ret;
	}

	if ((val & dcfg->src_mask) != dcfg->src_stop)
		priv->rproc->state = RPROC_DETACHED;

	return 0;
	return dcfg->ops->detect_mode(priv->rproc);
}

static int imx_rproc_clk_enable(struct imx_rproc *priv)
@@ -1207,6 +1169,111 @@ static void imx_rproc_remove(struct platform_device *pdev)
	destroy_workqueue(priv->workqueue);
}

static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = {
	.start		= imx_rproc_arm_smc_start,
	.stop		= imx_rproc_arm_smc_stop,
	.detect_mode	= imx_rproc_arm_smc_detect_mode,
};

static const struct imx_rproc_plat_ops imx_rproc_ops_mmio = {
	.start		= imx_rproc_mmio_start,
	.stop		= imx_rproc_mmio_stop,
	.detect_mode	= imx_rproc_mmio_detect_mode,
};

static const struct imx_rproc_plat_ops imx_rproc_ops_scu_api = {
	.start		= imx_rproc_scu_api_start,
	.stop		= imx_rproc_scu_api_stop,
	.detect_mode	= imx_rproc_scu_api_detect_mode,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX8M_M7_STOP,
	.gpr_reg	= IMX8M_GPR22,
	.gpr_wait	= IMX8M_GPR22_CM7_CPUWAIT,
	.att		= imx_rproc_att_imx8mn,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
	.method		= IMX_RPROC_MMIO,
	.ops		= &imx_rproc_ops_mmio,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = {
	.att		= imx_rproc_att_imx8mn,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
	.method		= IMX_RPROC_SMC,
	.ops		= &imx_rproc_ops_arm_smc,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX7D_M4_STOP,
	.att		= imx_rproc_att_imx8mq,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mq),
	.method		= IMX_RPROC_MMIO,
	.ops		= &imx_rproc_ops_mmio,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qm = {
	.att            = imx_rproc_att_imx8qm,
	.att_size       = ARRAY_SIZE(imx_rproc_att_imx8qm),
	.method         = IMX_RPROC_SCU_API,
	.ops		= &imx_rproc_ops_scu_api,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qxp = {
	.att		= imx_rproc_att_imx8qxp,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8qxp),
	.method		= IMX_RPROC_SCU_API,
	.ops		= &imx_rproc_ops_scu_api,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = {
	.att		= imx_rproc_att_imx8ulp,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8ulp),
	.method		= IMX_RPROC_NONE,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = {
	.att		= imx_rproc_att_imx7ulp,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx7ulp),
	.method		= IMX_RPROC_NONE,
	.flags		= IMX_RPROC_NEED_SYSTEM_OFF,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX7D_M4_STOP,
	.att		= imx_rproc_att_imx7d,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx7d),
	.method		= IMX_RPROC_MMIO,
	.ops		= &imx_rproc_ops_mmio,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = {
	.src_reg	= IMX6SX_SRC_SCR,
	.src_mask	= IMX6SX_M4_RST_MASK,
	.src_start	= IMX6SX_M4_START,
	.src_stop	= IMX6SX_M4_STOP,
	.att		= imx_rproc_att_imx6sx,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx6sx),
	.method		= IMX_RPROC_MMIO,
	.ops		= &imx_rproc_ops_mmio,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
	.att		= imx_rproc_att_imx93,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx93),
	.method		= IMX_RPROC_SMC,
	.ops		= &imx_rproc_ops_arm_smc,
};

static const struct of_device_id imx_rproc_of_match[] = {
	{ .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp },
	{ .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d },
+7 −0
Original line number Diff line number Diff line
@@ -31,6 +31,12 @@ enum imx_rproc_method {
/* dcfg flags */
#define IMX_RPROC_NEED_SYSTEM_OFF	BIT(0)

struct imx_rproc_plat_ops {
	int (*start)(struct rproc *rproc);
	int (*stop)(struct rproc *rproc);
	int (*detect_mode)(struct rproc *rproc);
};

struct imx_rproc_dcfg {
	u32				src_reg;
	u32				src_mask;
@@ -42,6 +48,7 @@ struct imx_rproc_dcfg {
	size_t				att_size;
	enum imx_rproc_method		method;
	u32				flags;
	const struct imx_rproc_plat_ops	*ops;
};

#endif /* _IMX_RPROC_H */
Loading