Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f194646 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'rproc-v5.1' of git://github.com/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson:
 "This contains the last patches in Loic's remoteproc resource table
  handling changes, a number of updates to documentation, support for
  invoking the crash handler (for testing purposes), a fix for the
  handling of virtio devices during recovery, performance state votes in
  Qualcomm modem driver, support for specifying board specific firmware
  path for Qualcomm modem driver and improved support for graceful
  shutdown of Qualcomm remoteprocs"

* tag 'rproc-v5.1' of git://github.com/andersson/remoteproc: (33 commits)
  remoteproc: fix for "dma-mapping: remove the DMA_MEMORY_EXCLUSIVE flag"
  remoteproc: fix rproc_check_carveout_da() returned error and comments
  remoteproc: fix trace buffer va initialization
  remoteproc: fix rproc_alloc_carveout() for rproc with iommu domain
  remoteproc: add warning on resource table cast
  remoteproc: fix rproc_alloc_carveout() bad variable cast
  remoteproc: fix rproc_da_to_va in case of unallocated carveout
  remoteproc: correct rproc_mem_entry_init() comments
  remoteproc: fix recovery procedure
  rpmsg: virtio: change header file sort style
  rpmsg: virtio: allocate buffer from parent
  remoteproc: st: add reserved memory support
  remoteproc: create vdev subdevice with specific dma memory pool
  remoteproc: q6v5_adsp: Remove voting for lpass_aon clock
  dt-binding: remoteproc: Remove lpass_aon clock from adsp pil clock list
  remoteproc: q6v5-mss: Active powerdomain for SDM845
  remoteproc: q6v5-mss: Vote for rpmh power domains
  remoteproc: qcom: Add support for parsing fw dt bindings
  remoteproc: qcom_q6v5: don't auto boot remote processor
  remoteproc: qcom: Wait for shutdown-ack/ind on sysmon shutdown
  ...
parents dc2535be d664ce75
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ on the Qualcomm Technology Inc. ADSP Hexagon core.
	Value type: <stringlist>
	Definition: List of clock input name strings sorted in the same
		    order as the clocks property. Definition must have
		    "xo", "sway_cbcr", "lpass_aon", "lpass_ahbs_aon_cbcr",
		    "xo", "sway_cbcr", "lpass_ahbs_aon_cbcr",
		    "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", "qdsp6ss_sleep"
		    and "qdsp6ss_core".

@@ -100,13 +100,12 @@ ADSP, as it is found on SDM845 boards.

		clocks = <&rpmhcc RPMH_CXO_CLK>,
			<&gcc GCC_LPASS_SWAY_CLK>,
			<&lpasscc LPASS_AUDIO_WRAPPER_AON_CLK>,
			<&lpasscc LPASS_Q6SS_AHBS_AON_CLK>,
			<&lpasscc LPASS_Q6SS_AHBM_AON_CLK>,
			<&lpasscc LPASS_QDSP6SS_XO_CLK>,
			<&lpasscc LPASS_QDSP6SS_SLEEP_CLK>,
			<&lpasscc LPASS_QDSP6SS_CORE_CLK>;
		clock-names = "xo", "sway_cbcr", "lpass_aon",
		clock-names = "xo", "sway_cbcr",
			"lpass_ahbs_aon_cbcr",
			"lpass_ahbm_aon_cbcr", "qdsp6ss_xo",
			"qdsp6ss_sleep", "qdsp6ss_core";
+20 −3
Original line number Diff line number Diff line
@@ -19,13 +19,30 @@ on the Qualcomm ADSP Hexagon core.
- interrupts-extended:
	Usage: required
	Value type: <prop-encoded-array>
	Definition: must list the watchdog, fatal IRQs ready, handover and
		    stop-ack IRQs
	Definition: reference to the interrupts that match interrupt-names

- interrupt-names:
	Usage: required
	Value type: <stringlist>
	Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack"
	Definition: The interrupts needed depends on the compatible
		    string:
	qcom,msm8974-adsp-pil:
	qcom,msm8996-adsp-pil:
	qcom,msm8996-slpi-pil:
	qcom,qcs404-adsp-pas:
	qcom,qcs404-cdsp-pas:
	qcom,sdm845-adsp-pas:
	qcom,sdm845-cdsp-pas:
		    must be "wdog", "fatal", "ready", "handover", "stop-ack"
	qcom,qcs404-wcss-pas:
		    must be "wdog", "fatal", "ready", "handover", "stop-ack",
		    "shutdown-ack"

- firmware-name:
	Usage: optional
	Value type: <string>
	Definition: must list the relative firmware image path for the
		    Hexagon Core.

- clocks:
	Usage: required
+73 −6
Original line number Diff line number Diff line
@@ -28,24 +28,51 @@ on the Qualcomm Hexagon core.
- interrupts-extended:
	Usage: required
	Value type: <prop-encoded-array>
	Definition: must list the watchdog, fatal IRQs ready, handover and
		    stop-ack IRQs
	Definition: reference to the interrupts that match interrupt-names

- interrupt-names:
	Usage: required
	Value type: <stringlist>
	Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack"
	Definition: The interrupts needed depends on the the compatible
		    string:
	qcom,q6v5-pil:
	qcom,ipq8074-wcss-pil:
	qcom,msm8916-mss-pil:
	qcom,msm8974-mss-pil:
		    must be "wdog", "fatal", "ready", "handover", "stop-ack"
	qcom,msm8996-mss-pil:
	qcom,sdm845-mss-pil:
		    must be "wdog", "fatal", "ready", "handover", "stop-ack",
		    "shutdown-ack"

- firmware-name:
	Usage: optional
	Value type: <stringlist>
	Definition: must list the relative firmware image paths for mba and
		    modem. They are used for booting and authenticating the
		    Hexagon core.

- clocks:
	Usage: required
	Value type: <phandle>
	Definition: reference to the iface, bus and mem clocks to be held on
		    behalf of the booting of the Hexagon core
	Definition: reference to the clocks that match clock-names

- clock-names:
	Usage: required
	Value type: <stringlist>
	Definition: must be "iface", "bus", "mem"
	Definition: The clocks needed depend on the compatible string:
	qcom,ipq8074-wcss-pil:
		    no clock names required
	qcom,q6v5-pil:
	qcom,msm8916-mss-pil:
	qcom,msm8974-mss-pil:
		    must be "iface", "bus", "mem", "xo"
	qcom,msm8996-mss-pil:
		    must be "iface", "bus", "mem", "xo", "gpll0_mss",
		    "snoc_axi", "mnoc_axi", "pnoc", "qdss"
	qcom,sdm845-mss-pil:
		    must be "iface", "bus", "mem", "xo", "gpll0_mss",
		    "snoc_axi", "mnoc_axi", "prng"

- resets:
	Usage: required
@@ -65,6 +92,19 @@ on the Qualcomm Hexagon core.
		    must be "mss_restart", "pdc_reset" for the modem
		    sub-system on SDM845 SoCs

For the compatible strings below the following supplies are required:
  "qcom,q6v5-pil"
  "qcom,msm8916-mss-pil",
- cx-supply:
- mx-supply:
- pll-supply:
	Usage: required
	Value type: <phandle>
	Definition: reference to the regulators to be held on behalf of the
		    booting of the Hexagon core

For the compatible string below the following supplies are required:
  "qcom,msm8974-mss-pil"
- cx-supply:
- mss-supply:
- mx-supply:
@@ -74,6 +114,33 @@ on the Qualcomm Hexagon core.
	Definition: reference to the regulators to be held on behalf of the
		    booting of the Hexagon core

For the compatible string below the following supplies are required:
  "qcom,msm8996-mss-pil"
- pll-supply:
	Usage: required
	Value type: <phandle>
	Definition: reference to the regulators to be held on behalf of the
		    booting of the Hexagon core

- power-domains:
	Usage: required
	Value type: <phandle>
	Definition: reference to power-domains that match power-domain-names

- power-domain-names:
	Usage: required
	Value type: <stringlist>
	Definition: The power-domains needed depend on the compatible string:
	qcom,q6v5-pil:
	qcom,ipq8074-wcss-pil:
	qcom,msm8916-mss-pil:
	qcom,msm8974-mss-pil:
		    no power-domain names required
	qcom,msm8996-mss-pil:
		    must be "cx", "mx"
	qcom,sdm845-mss-pil:
		    must be "cx", "mx", "mss", "load_state"

- qcom,smem-states:
	Usage: required
	Value type: <phandle>
+5 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@

/* list of clocks required by ADSP PIL */
static const char * const adsp_clk_id[] = {
	"sway_cbcr", "lpass_aon", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
	"sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
	"qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core",
};

@@ -439,6 +439,10 @@ static int adsp_probe(struct platform_device *pdev)
	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
					      desc->sysmon_name,
					      desc->ssctl_id);
	if (IS_ERR(adsp->sysmon)) {
		ret = PTR_ERR(adsp->sysmon);
		goto disable_pm;
	}

	ret = rproc_add(rproc);
	if (ret)
+194 −15
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/remoteproc.h>
@@ -131,6 +133,8 @@ 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;
@@ -156,9 +160,13 @@ 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];
	struct reg_info proxy_regs[3];
@@ -188,6 +196,7 @@ struct q6v5 {
	bool has_alt_reset;
	int mpss_perm;
	int mba_perm;
	const char *hexagon_mdt_image;
	int version;
};

@@ -321,6 +330,41 @@ static void q6v5_clk_disable(struct device *dev,
		clk_disable_unprepare(clks[i]);
}

static int q6v5_pds_enable(struct q6v5 *qproc, struct device **pds,
			   size_t pd_count)
{
	int ret;
	int i;

	for (i = 0; i < pd_count; i++) {
		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
		ret = pm_runtime_get_sync(pds[i]);
		if (ret < 0)
			goto unroll_pd_votes;
	}

	return 0;

unroll_pd_votes:
	for (i--; i >= 0; i--) {
		dev_pm_genpd_set_performance_state(pds[i], 0);
		pm_runtime_put(pds[i]);
	}

	return ret;
};

static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
			     size_t pd_count)
{
	int i;

	for (i = 0; i < pd_count; i++) {
		dev_pm_genpd_set_performance_state(pds[i], 0);
		pm_runtime_put(pds[i]);
	}
}

static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
				   bool remote_owner, phys_addr_t addr,
				   size_t size)
@@ -690,11 +734,23 @@ static int q6v5_mba_load(struct q6v5 *qproc)

	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 = 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;
	}

	ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
				    qproc->proxy_reg_count);
	if (ret) {
		dev_err(qproc->dev, "failed to enable proxy supplies\n");
		goto disable_irqs;
		goto disable_proxy_pds;
	}

	ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
@@ -791,6 +847,10 @@ static int q6v5_mba_load(struct q6v5 *qproc)
disable_proxy_reg:
	q6v5_regulator_disable(qproc, qproc->proxy_regs,
			       qproc->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);

@@ -830,6 +890,7 @@ 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.
@@ -841,6 +902,8 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc)

	ret = qcom_q6v5_unprepare(&qproc->q6v5);
	if (ret) {
		q6v5_pds_disable(qproc, qproc->proxy_pds,
				 qproc->proxy_pd_count);
		q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
				 qproc->proxy_clk_count);
		q6v5_regulator_disable(qproc, qproc->proxy_regs,
@@ -860,17 +923,26 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
	phys_addr_t min_addr = PHYS_ADDR_MAX;
	phys_addr_t max_addr = 0;
	bool relocate = false;
	char seg_name[10];
	char *fw_name;
	size_t fw_name_len;
	ssize_t offset;
	size_t size = 0;
	void *ptr;
	int ret;
	int i;

	ret = request_firmware(&fw, "modem.mdt", qproc->dev);
	fw_name_len = strlen(qproc->hexagon_mdt_image);
	if (fw_name_len <= 4)
		return -EINVAL;

	fw_name = kstrdup(qproc->hexagon_mdt_image, GFP_KERNEL);
	if (!fw_name)
		return -ENOMEM;

	ret = request_firmware(&fw, fw_name, qproc->dev);
	if (ret < 0) {
		dev_err(qproc->dev, "unable to load modem.mdt\n");
		return ret;
		dev_err(qproc->dev, "unable to load %s\n", fw_name);
		goto out;
	}

	/* Initialize the RMB validator */
@@ -918,10 +990,11 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
		ptr = qproc->mpss_region + offset;

		if (phdr->p_filesz) {
			snprintf(seg_name, sizeof(seg_name), "modem.b%02d", i);
			ret = request_firmware(&seg_fw, seg_name, qproc->dev);
			/* Replace "xxx.xxx" with "xxx.bxx" */
			sprintf(fw_name + fw_name_len - 3, "b%02d", i);
			ret = request_firmware(&seg_fw, fw_name, qproc->dev);
			if (ret) {
				dev_err(qproc->dev, "failed to load %s\n", seg_name);
				dev_err(qproc->dev, "failed to load %s\n", fw_name);
				goto release_firmware;
			}

@@ -960,6 +1033,8 @@ static int q6v5_mpss_load(struct q6v5 *qproc)

release_firmware:
	release_firmware(fw);
out:
	kfree(fw_name);

	return ret < 0 ? ret : 0;
}
@@ -1075,9 +1150,10 @@ static int qcom_q6v5_register_dump_segments(struct rproc *rproc,
	unsigned long i;
	int ret;

	ret = request_firmware(&fw, "modem.mdt", qproc->dev);
	ret = request_firmware(&fw, qproc->hexagon_mdt_image, qproc->dev);
	if (ret < 0) {
		dev_err(qproc->dev, "unable to load modem.mdt\n");
		dev_err(qproc->dev, "unable to load %s\n",
			qproc->hexagon_mdt_image);
		return ret;
	}

@@ -1121,6 +1197,7 @@ static void qcom_msa_handover(struct qcom_q6v5 *q6v5)
			 qproc->proxy_clk_count);
	q6v5_regulator_disable(qproc, qproc->proxy_regs,
			       qproc->proxy_reg_count);
	q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
}

static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev)
@@ -1181,6 +1258,45 @@ static int q6v5_init_clocks(struct device *dev, struct clk **clks,
	return i;
}

static int q6v5_pds_attach(struct device *dev, struct device **devs,
			   char **pd_names)
{
	size_t num_pds = 0;
	int ret;
	int i;

	if (!pd_names)
		return 0;

	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(devs[i])) {
			ret = PTR_ERR(devs[i]);
			goto unroll_attach;
		}
	}

	return num_pds;

unroll_attach:
	for (i--; i >= 0; i--)
		dev_pm_domain_detach(devs[i], false);

	return ret;
};

static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds,
			    size_t pd_count)
{
	int i;

	for (i = 0; i < pd_count; i++)
		dev_pm_domain_detach(pds[i], false);
}

static int q6v5_init_reset(struct q6v5 *qproc)
{
	qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev,
@@ -1253,6 +1369,7 @@ static int q6v5_probe(struct platform_device *pdev)
	const struct rproc_hexagon_res *desc;
	struct q6v5 *qproc;
	struct rproc *rproc;
	const char *mba_image;
	int ret;

	desc = of_device_get_match_data(&pdev->dev);
@@ -1262,16 +1379,30 @@ static int q6v5_probe(struct platform_device *pdev)
	if (desc->need_mem_protection && !qcom_scm_is_available())
		return -EPROBE_DEFER;

	mba_image = desc->hexagon_mba_image;
	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
					    0, &mba_image);
	if (ret < 0 && ret != -EINVAL)
		return ret;

	rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,
			    desc->hexagon_mba_image, sizeof(*qproc));
			    mba_image, sizeof(*qproc));
	if (!rproc) {
		dev_err(&pdev->dev, "failed to allocate rproc\n");
		return -ENOMEM;
	}

	rproc->auto_boot = false;

	qproc = (struct q6v5 *)rproc->priv;
	qproc->dev = &pdev->dev;
	qproc->rproc = rproc;
	qproc->hexagon_mdt_image = "modem.mdt";
	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
					    1, &qproc->hexagon_mdt_image);
	if (ret < 0 && ret != -EINVAL)
		return ret;

	platform_set_drvdata(pdev, qproc);

	ret = q6v5_init_mem(qproc, pdev);
@@ -1322,10 +1453,26 @@ 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);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to init power domains\n");
		goto detach_active_pds;
	}
	qproc->proxy_pd_count = ret;

	qproc->has_alt_reset = desc->has_alt_reset;
	ret = q6v5_init_reset(qproc);
	if (ret)
		goto free_rproc;
		goto detach_proxy_pds;

	qproc->version = desc->version;
	qproc->need_mem_protection = desc->need_mem_protection;
@@ -1333,7 +1480,7 @@ static int q6v5_probe(struct platform_device *pdev)
	ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM,
			     qcom_msa_handover);
	if (ret)
		goto free_rproc;
		goto detach_proxy_pds;

	qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
	qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
@@ -1341,13 +1488,21 @@ static int q6v5_probe(struct platform_device *pdev)
	qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
	qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
	qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
	if (IS_ERR(qproc->sysmon)) {
		ret = PTR_ERR(qproc->sysmon);
		goto detach_proxy_pds;
	}

	ret = rproc_add(rproc);
	if (ret)
		goto free_rproc;
		goto detach_proxy_pds;

	return 0;

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);

@@ -1364,6 +1519,10 @@ static int q6v5_remove(struct platform_device *pdev)
	qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
	qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
	qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);

	q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
	q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);

	rproc_free(qproc->rproc);

	return 0;
@@ -1388,6 +1547,16 @@ static const struct rproc_hexagon_res sdm845_mss = {
			"mnoc_axi",
			NULL
	},
	.active_pd_names = (char*[]){
			"load_state",
			NULL
	},
	.proxy_pd_names = (char*[]){
			"cx",
			"mx",
			"mss",
			NULL
	},
	.need_mem_protection = true,
	.has_alt_reset = true,
	.version = MSS_SDM845,
@@ -1395,16 +1564,26 @@ static const struct rproc_hexagon_res sdm845_mss = {

static const struct rproc_hexagon_res msm8996_mss = {
	.hexagon_mba_image = "mba.mbn",
	.proxy_supply = (struct qcom_mss_reg_res[]) {
		{
			.supply = "pll",
			.uA = 100000,
		},
		{}
	},
	.proxy_clk_names = (char*[]){
			"xo",
			"pnoc",
			"qdss",
			NULL
	},
	.active_clk_names = (char*[]){
			"iface",
			"bus",
			"mem",
			"gpll0_mss_clk",
			"gpll0_mss",
			"snoc_axi",
			"mnoc_axi",
			NULL
	},
	.need_mem_protection = true,
Loading