[RESEND PATCH v2] remoteproc: qcom: Add venus rproc support on msm8996 platform.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch is based on
	https://patchwork.kernel.org/patch/9415627/
	https://patchwork.kernel.org/patch/9415651/

This patch add clock initialization, enable and disable support.
Required resource name string and rating are differentiated based
on compatible string. Also added documentation for venus pil on
msm8996.

Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@xxxxxxxxxxxxxx>
---
 .../devicetree/bindings/remoteproc/qcom,venus.txt  |  26 ++++-
 drivers/remoteproc/qcom_venus_pil.c                | 116 ++++++++++++++++++++-
 2 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,venus.txt b/Documentation/devicetree/bindings/remoteproc/qcom,venus.txt
index 2d73ba1..417026b 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,venus.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,venus.txt
@@ -6,13 +6,30 @@ on the Qualcomm Venus remote processor core.
 - compatible:
 	Usage: required
 	Value type: <string>
-	Definition: must contain "qcom,venus-pil"
+	Definition: must contain "qcom,venus-pil" or
+				"qcom,venus-msm8996-pil"
 
 - memory-region:
 	Usage: required
 	Value type: <phandle>
 	Definition: a phandle to a node describing reserved memory
 
+- clocks:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: reference to the core, iface and bus and maxi clocks to be held on
+		    behalf of the booting of the venus core
+
+- clock-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: should be "core_clk", "iface_clk", "bus_clk", "maxi_clk"
+
+- power-domains:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: reference to the venus gdsc to be turned on before booting venus core
+
 * An example
 	reserved-memory {
 		#address-cells = <2>;
@@ -29,5 +46,12 @@ on the Qualcomm Venus remote processor core.
 
 	rproc_venus@0 {
 		compatible = "qcom,venus-pil";
+		clocks = <&mmcc VIDEO_CORE_CLK>,
+				<&mmcc VIDEO_AHB_CLK>,
+				<&mmcc VIDEO_AXI_CLK>,
+				<&mmcc VIDEO_MAXI_CLK>;
+
+		clock-names = "core_clk", "iface_clk", "bus_clk", "maxi_clk";
+		power-domains = <&mmcc VENUS_GDSC>;
 		memory-region = <&venus_mem>;
 	};
diff --git a/drivers/remoteproc/qcom_venus_pil.c b/drivers/remoteproc/qcom_venus_pil.c
index 6d4e55b..f91f873 100644
--- a/drivers/remoteproc/qcom_venus_pil.c
+++ b/drivers/remoteproc/qcom_venus_pil.c
@@ -19,8 +19,10 @@
 #include <linux/module.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/qcom_scm.h>
 #include <linux/remoteproc.h>
+#include <linux/of_device.h>
 
 #include "qcom_mdt_loader.h"
 #include "remoteproc_internal.h"
@@ -30,6 +32,11 @@
 #define VENUS_PAS_ID			9
 #define VENUS_FW_MEM_SIZE		SZ_8M
 
+struct venus_rproc_res {
+	char **venus_clks;
+	int venus_clk_rate[4];
+};
+
 struct qcom_venus {
 	struct device *dev;
 	struct rproc *rproc;
@@ -37,6 +44,8 @@ struct qcom_venus {
 	phys_addr_t mem_phys;
 	void *mem_va;
 	size_t mem_size;
+	struct clk *venus_clks[4];
+	int clk_count;
 };
 
 static int venus_load(struct rproc *rproc, const struct firmware *fw)
@@ -78,11 +87,49 @@ static int venus_load(struct rproc *rproc, const struct firmware *fw)
 	.load = venus_load,
 };
 
+static int qcom_venus_clk_enable(struct device *dev, struct clk **clks,
+								int clk_count)
+{
+	int rc = 0;
+	int i;
+
+	for (i = 0; i < clk_count; i++) {
+		rc = clk_prepare_enable(clks[i]);
+		if (rc) {
+			dev_err(dev, "Clock enable failed\n");
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	for (i--; i >= 0; i--)
+		clk_disable_unprepare(clks[i]);
+
+	return rc;
+}
+
+static void qcom_venus_clk_disable(struct qcom_venus *venus)
+{
+	int i;
+	struct clk **clks = venus->venus_clks;
+
+	for (i = 0; i < venus->clk_count; i++)
+		clk_disable_unprepare(clks[i]);
+}
+
 static int venus_start(struct rproc *rproc)
 {
 	struct qcom_venus *venus = rproc->priv;
 	int ret;
 
+	ret = qcom_venus_clk_enable(venus->dev, venus->venus_clks,
+			venus->clk_count);
+	if (ret) {
+		dev_err(venus->dev, "failed to enable venus_clk\n");
+		return ret;
+	}
+
 	ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
 	if (ret)
 		dev_err(venus->dev,
@@ -101,6 +148,8 @@ static int venus_stop(struct rproc *rproc)
 	if (ret)
 		dev_err(venus->dev, "failed to shutdown: %d\n", ret);
 
+	qcom_venus_clk_disable(venus);
+
 	return ret;
 }
 
@@ -123,13 +172,58 @@ static void *venus_da_to_va(struct rproc *rproc, u64 da, int len)
 	.da_to_va = venus_da_to_va,
 };
 
+static int qcom_venus_init_clocks(struct device *dev, struct clk **clks,
+		char **clk_str, const int *rate)
+{
+	int clk_count = 0, i;
+
+	if (!clk_str)
+		return 0;
+
+	while (clk_str[clk_count] != NULL)
+		clk_count++;
+
+	if (!clk_count)
+		return clk_count;
+
+	if (!clks)
+		return -ENOMEM;
+
+	for (i = 0; i < clk_count; i++) {
+		const char *clock_name;
+
+		clock_name = clk_str[i];
+		clks[i] = devm_clk_get(dev, clock_name);
+		if (IS_ERR(clks[i])) {
+
+			int rc = PTR_ERR(clks[i]);
+
+			if (rc != -EPROBE_DEFER)
+				dev_err(dev, "Failed to get %s clock\n",
+					clock_name);
+			return rc;
+		}
+		clk_set_rate(clks[i], clk_round_rate(clks[i], rate[i]));
+
+	}
+
+	return clk_count;
+}
+
+
+
 static int venus_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct qcom_venus *venus;
 	struct rproc *rproc;
+	const struct venus_rproc_res *desc;
 	int ret;
 
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc)
+		return -EINVAL;
+
 	if (!qcom_scm_is_available())
 		return -EPROBE_DEFER;
 
@@ -158,6 +252,14 @@ static int venus_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, venus);
 
+	ret = qcom_venus_init_clocks(&pdev->dev, venus->venus_clks,
+			desc->venus_clks, desc->venus_clk_rate);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to setup venus clocks.\n");
+		return ret;
+	}
+	venus->clk_count = ret;
+
 	venus->mem_va = dma_alloc_coherent(dev, venus->mem_size,
 					   &venus->mem_phys, GFP_KERNEL);
 	if (!venus->mem_va) {
@@ -194,8 +296,20 @@ static int venus_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct venus_rproc_res venus_msm8996_res = {
+	.venus_clks = (char*[]){"core_clk", "iface_clk", "bus_clk",
+		"maxi_clk", NULL},
+	.venus_clk_rate = {19200000, 19200000, 19200000, 80000000},
+};
+
+static const struct venus_rproc_res venus_8916_res = {
+	.venus_clks = NULL,
+	.venus_clk_rate = {0},
+};
+
 static const struct of_device_id venus_of_match[] = {
-	{ .compatible = "qcom,venus-pil" },
+	{ .compatible = "qcom,venus-msm8996-pil", .data = &venus_msm8996_res },
+	{ .compatible = "qcom,venus-pil", .data = &venus_8916_res},
 	{ },
 };
 
-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux