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

Commit c54fc865 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'rproc-v4.19' of git://github.com/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson:
 "This adds support for pre-start and post-shutdown hooks for remoteproc
  subdevices, refactors the Qualcomm Hexagon support to allow reuse
  between several drivers, makes authentication in the MDT file loader
  optional, migrates a few format strings to use %pK and migrates the
  Davinci driver to use the reset framework"

* tag 'rproc-v4.19' of git://github.com/andersson/remoteproc:
  remoteproc/davinci: use the reset framework
  remoteproc/davinci: Mark error recovery as disabled
  remoteproc: st_slim: replace "%p" with "%pK"
  remoteproc: replace "%p" with "%pK"
  remoteproc: qcom: fix Q6V5_WCSS dependencies
  remoteproc: Reset table_ptr in rproc_start() failure paths
  remoteproc: qcom: q6v5-pil: fix modem hang on SDM845 after axis2 clk unvote
  remoteproc: qcom q6v5: fix modular build
  remoteproc: Introduce prepare and unprepare for subdevices
  remoteproc: rename subdev probe and remove functions
  remoteproc: Make client initialize ops in rproc_subdev
  remoteproc: Make start and stop in subdev optional
  remoteproc: Rename subdev functions to start/stop
  remoteproc: qcom: Introduce Hexagon V5 based WCSS driver
  remoteproc: qcom: q6v5-pil: Use common q6v5 helpers
  remoteproc: qcom: adsp: Use common q6v5 helpers
  remoteproc: q6v5: Extract common resource handling
  remoteproc: qcom: mdt_loader: Make the firmware authentication optional
parents 6eaac34f b2201ee5
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ on the Qualcomm Hexagon core.
	Value type: <string>
	Definition: must be one of:
		    "qcom,q6v5-pil",
		    "qcom,ipq8074-wcss-pil"
		    "qcom,msm8916-mss-pil",
		    "qcom,msm8974-mss-pil"
		    "qcom,msm8996-mss-pil"
@@ -50,11 +51,15 @@ on the Qualcomm Hexagon core.
	Usage: required
	Value type: <phandle>
	Definition: reference to the reset-controller for the modem sub-system
		    reference to the list of 3 reset-controllers for the
		    wcss sub-system

- reset-names:
	Usage: required
	Value type: <stringlist>
	Definition: must be "mss_restart"
	Definition: must be "mss_restart" for the modem sub-system
	Definition: must be "wcss_aon_reset", "wcss_reset", "wcss_q6_reset"
		    for the wcss syb-system

- cx-supply:
- mss-supply:
+23 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ config QCOM_ADSP_PIL
	depends on QCOM_SYSMON || QCOM_SYSMON=n
	select MFD_SYSCON
	select QCOM_MDT_LOADER
	select QCOM_Q6V5_COMMON
	select QCOM_RPROC_COMMON
	select QCOM_SCM
	help
@@ -102,6 +103,11 @@ config QCOM_ADSP_PIL
config QCOM_RPROC_COMMON
	tristate

config QCOM_Q6V5_COMMON
	tristate
	depends on ARCH_QCOM
	depends on QCOM_SMEM

config QCOM_Q6V5_PIL
	tristate "Qualcomm Hexagon V5 Peripherial Image Loader"
	depends on OF && ARCH_QCOM
@@ -110,12 +116,29 @@ config QCOM_Q6V5_PIL
	depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
	depends on QCOM_SYSMON || QCOM_SYSMON=n
	select MFD_SYSCON
	select QCOM_Q6V5_COMMON
	select QCOM_RPROC_COMMON
	select QCOM_SCM
	help
	  Say y here to support the Qualcomm Peripherial Image Loader for the
	  Hexagon V5 based remote processors.

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_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
	depends on QCOM_SYSMON || QCOM_SYSMON=n
	select MFD_SYSCON
	select QCOM_MDT_LOADER
	select QCOM_Q6V5_COMMON
	select QCOM_RPROC_COMMON
	select QCOM_SCM
	help
	  Say y here to support the Qualcomm Peripheral Image Loader for the
	  Hexagon V5 based WCSS remote processors.

config QCOM_SYSMON
	tristate "Qualcomm sysmon driver"
	depends on RPMSG
+2 −0
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@ obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
obj-$(CONFIG_KEYSTONE_REMOTEPROC)	+= keystone_remoteproc.o
obj-$(CONFIG_QCOM_ADSP_PIL)		+= qcom_adsp_pil.o
obj-$(CONFIG_QCOM_RPROC_COMMON)		+= qcom_common.o
obj-$(CONFIG_QCOM_Q6V5_COMMON)		+= qcom_q6v5.o
obj-$(CONFIG_QCOM_Q6V5_PIL)		+= qcom_q6v5_pil.o
obj-$(CONFIG_QCOM_Q6V5_WCSS)		+= qcom_q6v5_wcss.o
obj-$(CONFIG_QCOM_SYSMON)		+= qcom_sysmon.o
obj-$(CONFIG_QCOM_WCNSS_PIL)		+= qcom_wcnss_pil.o
qcom_wcnss_pil-y			+= qcom_wcnss.o
+32 −5
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -20,8 +21,6 @@
#include <linux/platform_device.h>
#include <linux/remoteproc.h>

#include <mach/clock.h>   /* for davinci_clk_reset_assert/deassert() */

#include "remoteproc_internal.h"

static char *da8xx_fw_name;
@@ -72,6 +71,7 @@ struct da8xx_rproc {
	struct da8xx_rproc_mem *mem;
	int num_mems;
	struct clk *dsp_clk;
	struct reset_control *dsp_reset;
	void (*ack_fxn)(struct irq_data *data);
	struct irq_data *irq_data;
	void __iomem *chipsig;
@@ -138,6 +138,7 @@ static int da8xx_rproc_start(struct rproc *rproc)
	struct device *dev = rproc->dev.parent;
	struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
	struct clk *dsp_clk = drproc->dsp_clk;
	struct reset_control *dsp_reset = drproc->dsp_reset;
	int ret;

	/* hw requires the start (boot) address be on 1KB boundary */
@@ -155,7 +156,12 @@ static int da8xx_rproc_start(struct rproc *rproc)
		return ret;
	}

	davinci_clk_reset_deassert(dsp_clk);
	ret = reset_control_deassert(dsp_reset);
	if (ret) {
		dev_err(dev, "reset_control_deassert() failed: %d\n", ret);
		clk_disable_unprepare(dsp_clk);
		return ret;
	}

	return 0;
}
@@ -163,8 +169,15 @@ static int da8xx_rproc_start(struct rproc *rproc)
static int da8xx_rproc_stop(struct rproc *rproc)
{
	struct da8xx_rproc *drproc = rproc->priv;
	struct device *dev = rproc->dev.parent;
	int ret;

	ret = reset_control_assert(drproc->dsp_reset);
	if (ret) {
		dev_err(dev, "reset_control_assert() failed: %d\n", ret);
		return ret;
	}

	davinci_clk_reset_assert(drproc->dsp_clk);
	clk_disable_unprepare(drproc->dsp_clk);

	return 0;
@@ -232,6 +245,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
	struct resource *bootreg_res;
	struct resource *chipsig_res;
	struct clk *dsp_clk;
	struct reset_control *dsp_reset;
	void __iomem *chipsig;
	void __iomem *bootreg;
	int irq;
@@ -268,6 +282,15 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
		return PTR_ERR(dsp_clk);
	}

	dsp_reset = devm_reset_control_get_exclusive(dev, NULL);
	if (IS_ERR(dsp_reset)) {
		if (PTR_ERR(dsp_reset) != -EPROBE_DEFER)
			dev_err(dev, "unable to get reset control: %ld\n",
				PTR_ERR(dsp_reset));

		return PTR_ERR(dsp_reset);
	}

	if (dev->of_node) {
		ret = of_reserved_mem_device_init(dev);
		if (ret) {
@@ -284,9 +307,13 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
		goto free_mem;
	}

	/* error recovery is not supported at present */
	rproc->recovery_disabled = true;

	drproc = rproc->priv;
	drproc->rproc = rproc;
	drproc->dsp_clk = dsp_clk;
	drproc->dsp_reset = dsp_reset;
	rproc->has_iommu = false;

	ret = da8xx_rproc_get_internal_memories(pdev, drproc);
@@ -309,7 +336,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
	 * *not* in reset, but da8xx_rproc_start() needs the DSP to be
	 * held in reset at the time it is called.
	 */
	ret = davinci_clk_reset_assert(drproc->dsp_clk);
	ret = reset_control_assert(dsp_reset);
	if (ret)
		goto free_rproc;

+27 −129
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/soc/qcom/smem_state.h>

#include "qcom_common.h"
#include "qcom_q6v5.h"
#include "remoteproc_internal.h"

struct adsp_data {
@@ -48,14 +49,7 @@ struct qcom_adsp {
	struct device *dev;
	struct rproc *rproc;

	int wdog_irq;
	int fatal_irq;
	int ready_irq;
	int handover_irq;
	int stop_ack_irq;

	struct qcom_smem_state *state;
	unsigned stop_bit;
	struct qcom_q6v5 q6v5;

	struct clk *xo;
	struct clk *aggre2_clk;
@@ -96,6 +90,8 @@ static int adsp_start(struct rproc *rproc)
	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
	int ret;

	qcom_q6v5_prepare(&adsp->q6v5);

	ret = clk_prepare_enable(adsp->xo);
	if (ret)
		return ret;
@@ -119,16 +115,14 @@ static int adsp_start(struct rproc *rproc)
		goto disable_px_supply;
	}

	ret = wait_for_completion_timeout(&adsp->start_done,
					  msecs_to_jiffies(5000));
	if (!ret) {
	ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
	if (ret == -ETIMEDOUT) {
		dev_err(adsp->dev, "start timed out\n");
		qcom_scm_pas_shutdown(adsp->pas_id);
		ret = -ETIMEDOUT;
		goto disable_px_supply;
	}

	ret = 0;
	return 0;

disable_px_supply:
	regulator_disable(adsp->px_supply);
@@ -142,28 +136,34 @@ static int adsp_start(struct rproc *rproc)
	return ret;
}

static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
{
	struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);

	regulator_disable(adsp->px_supply);
	regulator_disable(adsp->cx_supply);
	clk_disable_unprepare(adsp->aggre2_clk);
	clk_disable_unprepare(adsp->xo);
}

static int adsp_stop(struct rproc *rproc)
{
	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
	int handover;
	int ret;

	qcom_smem_state_update_bits(adsp->state,
				    BIT(adsp->stop_bit),
				    BIT(adsp->stop_bit));

	ret = wait_for_completion_timeout(&adsp->stop_done,
					  msecs_to_jiffies(5000));
	if (ret == 0)
	ret = qcom_q6v5_request_stop(&adsp->q6v5);
	if (ret == -ETIMEDOUT)
		dev_err(adsp->dev, "timed out on wait\n");

	qcom_smem_state_update_bits(adsp->state,
				    BIT(adsp->stop_bit),
				    0);

	ret = qcom_scm_pas_shutdown(adsp->pas_id);
	if (ret)
		dev_err(adsp->dev, "failed to shutdown: %d\n", ret);

	handover = qcom_q6v5_unprepare(&adsp->q6v5);
	if (handover)
		qcom_pas_handover(&adsp->q6v5);

	return ret;
}

@@ -187,53 +187,6 @@ static const struct rproc_ops adsp_ops = {
	.load = adsp_load,
};

static irqreturn_t adsp_wdog_interrupt(int irq, void *dev)
{
	struct qcom_adsp *adsp = dev;

	rproc_report_crash(adsp->rproc, RPROC_WATCHDOG);

	return IRQ_HANDLED;
}

static irqreturn_t adsp_fatal_interrupt(int irq, void *dev)
{
	struct qcom_adsp *adsp = dev;
	size_t len;
	char *msg;

	msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, adsp->crash_reason_smem, &len);
	if (!IS_ERR(msg) && len > 0 && msg[0])
		dev_err(adsp->dev, "fatal error received: %s\n", msg);

	rproc_report_crash(adsp->rproc, RPROC_FATAL_ERROR);

	return IRQ_HANDLED;
}

static irqreturn_t adsp_ready_interrupt(int irq, void *dev)
{
	return IRQ_HANDLED;
}

static irqreturn_t adsp_handover_interrupt(int irq, void *dev)
{
	struct qcom_adsp *adsp = dev;

	complete(&adsp->start_done);

	return IRQ_HANDLED;
}

static irqreturn_t adsp_stop_ack_interrupt(int irq, void *dev)
{
	struct qcom_adsp *adsp = dev;

	complete(&adsp->stop_done);

	return IRQ_HANDLED;
}

static int adsp_init_clock(struct qcom_adsp *adsp)
{
	int ret;
@@ -272,29 +225,6 @@ static int adsp_init_regulator(struct qcom_adsp *adsp)
	return PTR_ERR_OR_ZERO(adsp->px_supply);
}

static int adsp_request_irq(struct qcom_adsp *adsp,
			     struct platform_device *pdev,
			     const char *name,
			     irq_handler_t thread_fn)
{
	int ret;

	ret = platform_get_irq_byname(pdev, name);
	if (ret < 0) {
		dev_err(&pdev->dev, "no %s IRQ defined\n", name);
		return ret;
	}

	ret = devm_request_threaded_irq(&pdev->dev, ret,
					NULL, thread_fn,
					IRQF_ONESHOT,
					"adsp", adsp);
	if (ret)
		dev_err(&pdev->dev, "request %s IRQ failed\n", name);

	return ret;
}

static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
{
	struct device_node *node;
@@ -348,13 +278,9 @@ static int adsp_probe(struct platform_device *pdev)
	adsp->dev = &pdev->dev;
	adsp->rproc = rproc;
	adsp->pas_id = desc->pas_id;
	adsp->crash_reason_smem = desc->crash_reason_smem;
	adsp->has_aggre2_clk = desc->has_aggre2_clk;
	platform_set_drvdata(pdev, adsp);

	init_completion(&adsp->start_done);
	init_completion(&adsp->stop_done);

	ret = adsp_alloc_memory_region(adsp);
	if (ret)
		goto free_rproc;
@@ -367,37 +293,10 @@ static int adsp_probe(struct platform_device *pdev)
	if (ret)
		goto free_rproc;

	ret = adsp_request_irq(adsp, pdev, "wdog", adsp_wdog_interrupt);
	if (ret < 0)
		goto free_rproc;
	adsp->wdog_irq = ret;

	ret = adsp_request_irq(adsp, pdev, "fatal", adsp_fatal_interrupt);
	if (ret < 0)
		goto free_rproc;
	adsp->fatal_irq = ret;

	ret = adsp_request_irq(adsp, pdev, "ready", adsp_ready_interrupt);
	if (ret < 0)
		goto free_rproc;
	adsp->ready_irq = ret;

	ret = adsp_request_irq(adsp, pdev, "handover", adsp_handover_interrupt);
	if (ret < 0)
		goto free_rproc;
	adsp->handover_irq = ret;

	ret = adsp_request_irq(adsp, pdev, "stop-ack", adsp_stop_ack_interrupt);
	if (ret < 0)
		goto free_rproc;
	adsp->stop_ack_irq = ret;

	adsp->state = qcom_smem_state_get(&pdev->dev, "stop",
					  &adsp->stop_bit);
	if (IS_ERR(adsp->state)) {
		ret = PTR_ERR(adsp->state);
	ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
			     qcom_pas_handover);
	if (ret)
		goto free_rproc;
	}

	qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
	qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
@@ -422,7 +321,6 @@ static int adsp_remove(struct platform_device *pdev)
{
	struct qcom_adsp *adsp = platform_get_drvdata(pdev);

	qcom_smem_state_put(adsp->state);
	rproc_del(adsp->rproc);

	qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
Loading