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

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

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

Pull remoteproc updates from Bjorn Andersson:
 "This brings a few minor fixes to the Davinci driver, drops a orphan
  include file from the StE cleanup done ealier and introduces support
  for booting the modem on Qualcomm's SDM845 platform"

* tag 'rproc-v4.18' of git://github.com/andersson/remoteproc:
  remoteproc: q6v5: Allow defining GLINK edge for mss remoteproc
  remoteproc: q6v5: Add support for mss remoteproc on SDM845
  remoteproc: q6v5: Introduce reset assert/deassert helper functions
  dt-bindings: remoteproc: Add Q6v5 Modem PIL binding for SDM845
  remoteproc: q6v5: Move proxy unvote to handover irq handler
  remoteproc: q6v5: Return irq from q6v5_request_irq()
  remoteproc/ste: remove abandoned include file
  remoteproc/davinci: use octal permissions for module_param()
  remoteproc/davinci: prepare and unprepare the clock where needed
  remoteproc/davinci: add the missing retval check for clk_enable()
  remoteproc: Remove depends on HAS_DMA in case of platform dependency
  remoteproc: Prevent incorrect rproc state on xfer mem ownership failure
parents 6f75edea 4725496e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ on the Qualcomm Hexagon core.
		    "qcom,msm8916-mss-pil",
		    "qcom,msm8974-mss-pil"
		    "qcom,msm8996-mss-pil"
		    "qcom,sdm845-mss-pil"

- reg:
	Usage: required
+0 −1
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ config IMX_REMOTEPROC

config OMAP_REMOTEPROC
	tristate "OMAP remoteproc support"
	depends on HAS_DMA
	depends on ARCH_OMAP4 || SOC_OMAP5
	depends on OMAP_IOMMU
	select MAILBOX
+9 −3
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
#include "remoteproc_internal.h"

static char *da8xx_fw_name;
module_param(da8xx_fw_name, charp, S_IRUGO);
module_param(da8xx_fw_name, charp, 0444);
MODULE_PARM_DESC(da8xx_fw_name,
		 "Name of DSP firmware file in /lib/firmware (if not specified defaults to 'rproc-dsp-fw')");

@@ -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;
	int ret;

	/* hw requires the start (boot) address be on 1KB boundary */
	if (rproc->bootaddr & 0x3ff) {
@@ -148,7 +149,12 @@ static int da8xx_rproc_start(struct rproc *rproc)

	writel(rproc->bootaddr, drproc->bootreg);

	clk_enable(dsp_clk);
	ret = clk_prepare_enable(dsp_clk);
	if (ret) {
		dev_err(dev, "clk_prepare_enable() failed: %d\n", ret);
		return ret;
	}

	davinci_clk_reset_deassert(dsp_clk);

	return 0;
@@ -159,7 +165,7 @@ static int da8xx_rproc_stop(struct rproc *rproc)
	struct da8xx_rproc *drproc = rproc->priv;

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

	return 0;
}
+178 −23
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@
#define RMB_PMI_META_DATA_REG		0x10
#define RMB_PMI_CODE_START_REG		0x14
#define RMB_PMI_CODE_LENGTH_REG		0x18
#define RMB_MBA_MSS_STATUS		0x40
#define RMB_MBA_ALT_RESET		0x44

#define RMB_CMD_META_DATA_READY		0x1
#define RMB_CMD_LOAD_READY		0x2
@@ -104,6 +106,13 @@
#define QDSP6SS_XO_CBCR		0x0038
#define QDSP6SS_ACC_OVERRIDE_VAL		0x20

/* QDSP6v65 parameters */
#define QDSP6SS_SLEEP                   0x3C
#define QDSP6SS_BOOT_CORE_START         0x400
#define QDSP6SS_BOOT_CMD                0x404
#define SLEEP_CHECK_MAX_LOOPS           200
#define BOOT_FSM_TIMEOUT                10000

struct reg_info {
	struct regulator *reg;
	int uV;
@@ -121,9 +130,11 @@ struct rproc_hexagon_res {
	struct qcom_mss_reg_res *proxy_supply;
	struct qcom_mss_reg_res *active_supply;
	char **proxy_clk_names;
	char **reset_clk_names;
	char **active_clk_names;
	int version;
	bool need_mem_protection;
	bool has_alt_reset;
};

struct q6v5 {
@@ -143,9 +154,15 @@ struct q6v5 {
	struct qcom_smem_state *state;
	unsigned stop_bit;

	int handover_irq;

	bool proxy_unvoted;

	struct clk *active_clks[8];
	struct clk *reset_clks[4];
	struct clk *proxy_clks[4];
	int active_clk_count;
	int reset_clk_count;
	int proxy_clk_count;

	struct reg_info active_regs[1];
@@ -166,10 +183,12 @@ struct q6v5 {
	void *mpss_region;
	size_t mpss_size;

	struct qcom_rproc_glink glink_subdev;
	struct qcom_rproc_subdev smd_subdev;
	struct qcom_rproc_ssr ssr_subdev;
	struct qcom_sysmon *sysmon;
	bool need_mem_protection;
	bool has_alt_reset;
	int mpss_perm;
	int mba_perm;
	int version;
@@ -179,6 +198,7 @@ enum {
	MSS_MSM8916,
	MSS_MSM8974,
	MSS_MSM8996,
	MSS_SDM845,
};

static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
@@ -333,6 +353,29 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
	return 0;
}

static int q6v5_reset_assert(struct q6v5 *qproc)
{
	if (qproc->has_alt_reset)
		return reset_control_reset(qproc->mss_restart);
	else
		return reset_control_assert(qproc->mss_restart);
}

static int q6v5_reset_deassert(struct q6v5 *qproc)
{
	int ret;

	if (qproc->has_alt_reset) {
		writel(1, qproc->rmb_base + RMB_MBA_ALT_RESET);
		ret = reset_control_reset(qproc->mss_restart);
		writel(0, qproc->rmb_base + RMB_MBA_ALT_RESET);
	} else {
		ret = reset_control_deassert(qproc->mss_restart);
	}

	return ret;
}

static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms)
{
	unsigned long timeout;
@@ -385,8 +428,35 @@ static int q6v5proc_reset(struct q6v5 *qproc)
	int ret;
	int i;

	if (qproc->version == MSS_SDM845) {
		val = readl(qproc->reg_base + QDSP6SS_SLEEP);
		val |= 0x1;
		writel(val, qproc->reg_base + QDSP6SS_SLEEP);

	if (qproc->version == MSS_MSM8996) {
		ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_SLEEP,
					 val, !(val & BIT(31)), 1,
					 SLEEP_CHECK_MAX_LOOPS);
		if (ret) {
			dev_err(qproc->dev, "QDSP6SS Sleep clock timed out\n");
			return -ETIMEDOUT;
		}

		/* De-assert QDSP6 stop core */
		writel(1, qproc->reg_base + QDSP6SS_BOOT_CORE_START);
		/* Trigger boot FSM */
		writel(1, qproc->reg_base + QDSP6SS_BOOT_CMD);

		ret = readl_poll_timeout(qproc->rmb_base + RMB_MBA_MSS_STATUS,
				val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
		if (ret) {
			dev_err(qproc->dev, "Boot FSM failed to complete.\n");
			/* Reset the modem so that boot FSM is in reset state */
			q6v5_reset_deassert(qproc);
			return ret;
		}

		goto pbl_wait;
	} else if (qproc->version == MSS_MSM8996) {
		/* Override the ACC value if required */
		writel(QDSP6SS_ACC_OVERRIDE_VAL,
		       qproc->reg_base + QDSP6SS_STRAP_ACC);
@@ -494,6 +564,7 @@ static int q6v5proc_reset(struct q6v5 *qproc)
	val &= ~Q6SS_STOP_CORE;
	writel(val, qproc->reg_base + QDSP6SS_RESET_REG);

pbl_wait:
	/* Wait for PBL status */
	ret = q6v5_rmb_pbl_wait(qproc, 1000);
	if (ret == -ETIMEDOUT) {
@@ -727,11 +798,15 @@ static int q6v5_start(struct rproc *rproc)
	int xfermemop_ret;
	int ret;

	qproc->proxy_unvoted = false;

	enable_irq(qproc->handover_irq);

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

	ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
@@ -747,12 +822,20 @@ static int q6v5_start(struct rproc *rproc)
		dev_err(qproc->dev, "failed to enable supplies\n");
		goto disable_proxy_clk;
	}
	ret = reset_control_deassert(qproc->mss_restart);

	ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks,
			      qproc->reset_clk_count);
	if (ret) {
		dev_err(qproc->dev, "failed to deassert mss restart\n");
		dev_err(qproc->dev, "failed to enable reset clocks\n");
		goto disable_vdd;
	}

	ret = q6v5_reset_deassert(qproc);
	if (ret) {
		dev_err(qproc->dev, "failed to deassert mss restart\n");
		goto disable_reset_clks;
	}

	ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
			      qproc->active_clk_count);
	if (ret) {
@@ -761,13 +844,11 @@ static int q6v5_start(struct rproc *rproc)
	}

	/* Assign MBA image access in DDR to q6 */
	xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
						qproc->mba_phys,
						qproc->mba_size);
	if (xfermemop_ret) {
	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
				      qproc->mba_phys, qproc->mba_size);
	if (ret) {
		dev_err(qproc->dev,
			"assigning Q6 access to mba memory failed: %d\n",
			xfermemop_ret);
			"assigning Q6 access to mba memory failed: %d\n", ret);
		goto disable_active_clks;
	}

@@ -810,11 +891,6 @@ static int q6v5_start(struct rproc *rproc)
			"Failed to reclaim mba buffer system may become unstable\n");
	qproc->running = true;

	q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
			 qproc->proxy_clk_count);
	q6v5_regulator_disable(qproc, qproc->proxy_regs,
			       qproc->proxy_reg_count);

	return 0;

reclaim_mpss:
@@ -842,7 +918,10 @@ static int q6v5_start(struct rproc *rproc)
			 qproc->active_clk_count);

assert_reset:
	reset_control_assert(qproc->mss_restart);
	q6v5_reset_assert(qproc);
disable_reset_clks:
	q6v5_clk_disable(qproc->dev, qproc->reset_clks,
			 qproc->reset_clk_count);
disable_vdd:
	q6v5_regulator_disable(qproc, qproc->active_regs,
			       qproc->active_reg_count);
@@ -853,6 +932,9 @@ static int q6v5_start(struct rproc *rproc)
	q6v5_regulator_disable(qproc, qproc->proxy_regs,
			       qproc->proxy_reg_count);

disable_irqs:
	disable_irq(qproc->handover_irq);

	return ret;
}

@@ -892,7 +974,19 @@ static int q6v5_stop(struct rproc *rproc)
				      qproc->mpss_phys, qproc->mpss_size);
	WARN_ON(ret);

	reset_control_assert(qproc->mss_restart);
	q6v5_reset_assert(qproc);

	disable_irq(qproc->handover_irq);

	if (!qproc->proxy_unvoted) {
		q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
				 qproc->proxy_clk_count);
		q6v5_regulator_disable(qproc, qproc->proxy_regs,
				       qproc->proxy_reg_count);
	}

	q6v5_clk_disable(qproc->dev, qproc->reset_clks,
			 qproc->reset_clk_count);
	q6v5_clk_disable(qproc->dev, qproc->active_clks,
			 qproc->active_clk_count);
	q6v5_regulator_disable(qproc, qproc->active_regs,
@@ -960,7 +1054,7 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)
	return IRQ_HANDLED;
}

static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
static irqreturn_t q6v5_ready_interrupt(int irq, void *dev)
{
	struct q6v5 *qproc = dev;

@@ -968,6 +1062,20 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
	return IRQ_HANDLED;
}

static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
{
	struct q6v5 *qproc = dev;

	q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
			 qproc->proxy_clk_count);
	q6v5_regulator_disable(qproc, qproc->proxy_regs,
			       qproc->proxy_reg_count);

	qproc->proxy_unvoted = true;

	return IRQ_HANDLED;
}

static irqreturn_t q6v5_stop_ack_interrupt(int irq, void *dev)
{
	struct q6v5 *qproc = dev;
@@ -1051,22 +1159,23 @@ static int q6v5_request_irq(struct q6v5 *qproc,
			     const char *name,
			     irq_handler_t thread_fn)
{
	int irq;
	int ret;

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

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

	return ret;
	return ret ? : irq;
}

static int q6v5_alloc_memory_region(struct q6v5 *qproc)
@@ -1157,6 +1266,14 @@ static int q6v5_probe(struct platform_device *pdev)
	}
	qproc->proxy_clk_count = ret;

	ret = q6v5_init_clocks(&pdev->dev, qproc->reset_clks,
			       desc->reset_clk_names);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get reset clocks.\n");
		goto free_rproc;
	}
	qproc->reset_clk_count = ret;

	ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,
			       desc->active_clk_names);
	if (ret < 0) {
@@ -1186,6 +1303,7 @@ static int q6v5_probe(struct platform_device *pdev)
		goto free_rproc;

	qproc->version = desc->version;
	qproc->has_alt_reset = desc->has_alt_reset;
	qproc->need_mem_protection = desc->need_mem_protection;
	ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
	if (ret < 0)
@@ -1195,9 +1313,15 @@ static int q6v5_probe(struct platform_device *pdev)
	if (ret < 0)
		goto free_rproc;

	ret = q6v5_request_irq(qproc, pdev, "ready", q6v5_ready_interrupt);
	if (ret < 0)
		goto free_rproc;

	ret = q6v5_request_irq(qproc, pdev, "handover", q6v5_handover_interrupt);
	if (ret < 0)
		goto free_rproc;
	qproc->handover_irq = ret;
	disable_irq(qproc->handover_irq);

	ret = q6v5_request_irq(qproc, pdev, "stop-ack", q6v5_stop_ack_interrupt);
	if (ret < 0)
@@ -1210,6 +1334,7 @@ static int q6v5_probe(struct platform_device *pdev)
	}
	qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
	qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
	qcom_add_glink_subdev(rproc, &qproc->glink_subdev);
	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);
@@ -1233,6 +1358,7 @@ static int q6v5_remove(struct platform_device *pdev)
	rproc_del(qproc->rproc);

	qcom_remove_sysmon_subdev(qproc->sysmon);
	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);
	rproc_free(qproc->rproc);
@@ -1240,6 +1366,31 @@ static int q6v5_remove(struct platform_device *pdev)
	return 0;
}

static const struct rproc_hexagon_res sdm845_mss = {
	.hexagon_mba_image = "mba.mbn",
	.proxy_clk_names = (char*[]){
			"xo",
			"axis2",
			"prng",
			NULL
	},
	.reset_clk_names = (char*[]){
			"iface",
			"snoc_axi",
			NULL
	},
	.active_clk_names = (char*[]){
			"bus",
			"mem",
			"gpll0_mss",
			"mnoc_axi",
			NULL
	},
	.need_mem_protection = true,
	.has_alt_reset = true,
	.version = MSS_SDM845,
};

static const struct rproc_hexagon_res msm8996_mss = {
	.hexagon_mba_image = "mba.mbn",
	.proxy_clk_names = (char*[]){
@@ -1255,6 +1406,7 @@ static const struct rproc_hexagon_res msm8996_mss = {
			NULL
	},
	.need_mem_protection = true,
	.has_alt_reset = false,
	.version = MSS_MSM8996,
};

@@ -1286,6 +1438,7 @@ static const struct rproc_hexagon_res msm8916_mss = {
		NULL
	},
	.need_mem_protection = false,
	.has_alt_reset = false,
	.version = MSS_MSM8916,
};

@@ -1325,6 +1478,7 @@ static const struct rproc_hexagon_res msm8974_mss = {
		NULL
	},
	.need_mem_protection = false,
	.has_alt_reset = false,
	.version = MSS_MSM8974,
};

@@ -1333,6 +1487,7 @@ static const struct of_device_id q6v5_of_match[] = {
	{ .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss},
	{ .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss},
	{ .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss},
	{ .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss},
	{ },
};
MODULE_DEVICE_TABLE(of, q6v5_of_match);

include/linux/ste_modem_shm.h

deleted100644 → 0
+0 −56
Original line number Diff line number Diff line
/*
 * Copyright (C) ST-Ericsson AB 2012
 * Author: Sjur Brendeland / sjur.brandeland@stericsson.com
 *
 * License terms: GNU General Public License (GPL) version 2
 */

#ifndef __INC_MODEM_DEV_H
#define __INC_MODEM_DEV_H
#include <linux/types.h>
#include <linux/platform_device.h>

struct ste_modem_device;

/**
 * struct ste_modem_dev_cb - Callbacks for modem initiated events.
 * @kick: Called when the modem kicks the host.
 *
 * This structure contains callbacks for actions triggered by the modem.
 */
struct ste_modem_dev_cb {
	void (*kick)(struct ste_modem_device *mdev, int notify_id);
};

/**
 * struct ste_modem_dev_ops - Functions to control modem and modem interface.
 *
 * @power:	Main power switch, used for cold-start or complete power off.
 * @kick:	Kick the modem.
 * @kick_subscribe: Subscribe for notifications from the modem.
 * @setup:	Provide callback functions to modem device.
 *
 * This structure contains functions used by the ste remoteproc driver
 * to manage the modem.
 */
struct ste_modem_dev_ops {
	int (*power)(struct ste_modem_device *mdev, bool on);
	int (*kick)(struct ste_modem_device *mdev, int notify_id);
	int (*kick_subscribe)(struct ste_modem_device *mdev, int notify_id);
	int (*setup)(struct ste_modem_device *mdev,
		     struct ste_modem_dev_cb *cfg);
};

/**
 * struct ste_modem_device - represent the STE modem device
 * @pdev: Reference to platform device
 * @ops: Operations used to manage the modem.
 * @drv_data: Driver private data.
 */
struct ste_modem_device {
	struct platform_device pdev;
	struct ste_modem_dev_ops ops;
	void *drv_data;
};

#endif /*INC_MODEM_DEV_H*/