2018-07-04 19:08:14

by Vikash Garodia

[permalink] [raw]
Subject: [PATCH v3 0/4] Venus updates - PIL

Hello,

Here is v3 with following comments addressed:

* merged patch 1 and 4 from v2.
* removed enum for Video CPU state and handled it as a bool.
* introduced a flag to specify if tz is not present.
* add misc code review comments related to better coding ways

There is an ongoing discussion on getting iova in a specified
range. Once concluded, will update the series, if needed.

Comments are welcome!

Vikash Garodia (4):
venus: firmware: add routine to reset ARM9
venus: firmware: move load firmware in a separate function
venus: firmware: add no TZ boot and shutdown routine
venus: firmware: register separate driver for firmware device

.../devicetree/bindings/media/qcom,venus.txt | 17 +-
drivers/media/platform/qcom/venus/core.c | 59 +++++-
drivers/media/platform/qcom/venus/core.h | 6 +
drivers/media/platform/qcom/venus/firmware.c | 203 ++++++++++++++++++---
drivers/media/platform/qcom/venus/firmware.h | 7 +-
drivers/media/platform/qcom/venus/hfi_venus.c | 13 +-
drivers/media/platform/qcom/venus/hfi_venus_io.h | 5 +
7 files changed, 263 insertions(+), 47 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



2018-07-04 19:08:52

by Vikash Garodia

[permalink] [raw]
Subject: [PATCH v3 1/4] venus: firmware: add routine to reset ARM9

Add routine to reset the ARM9 and brings it out of reset. Also
abstract the Venus CPU state handling with a new function. This
is in preparation to add PIL functionality in venus driver.

Signed-off-by: Vikash Garodia <[email protected]>
---
drivers/media/platform/qcom/venus/core.h | 1 +
drivers/media/platform/qcom/venus/firmware.c | 36 ++++++++++++++++++++++++
drivers/media/platform/qcom/venus/firmware.h | 1 +
drivers/media/platform/qcom/venus/hfi_venus.c | 13 +++------
drivers/media/platform/qcom/venus/hfi_venus_io.h | 5 ++++
5 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 2f02365..eb5ee66 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -129,6 +129,7 @@ struct venus_core {
struct device *dev;
struct device *dev_dec;
struct device *dev_enc;
+ bool no_tz;
struct mutex lock;
struct list_head instances;
atomic_t insts_count;
diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
index 521d4b3..3968553d 100644
--- a/drivers/media/platform/qcom/venus/firmware.c
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -22,11 +22,47 @@
#include <linux/sizes.h>
#include <linux/soc/qcom/mdt_loader.h>

+#include "core.h"
#include "firmware.h"
+#include "hfi_venus_io.h"

#define VENUS_PAS_ID 9
#define VENUS_FW_MEM_SIZE (6 * SZ_1M)

+static void venus_reset_cpu(struct venus_core *core)
+{
+ void __iomem *base = core->base;
+
+ writel(0, base + WRAPPER_FW_START_ADDR);
+ writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR);
+ writel(0, base + WRAPPER_CPA_START_ADDR);
+ writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR);
+ writel(0x0, base + WRAPPER_CPU_CGC_DIS);
+ writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG);
+
+ /* Make sure all register writes are committed. */
+ mb();
+
+ /* Bring ARM9 out of reset */
+ writel_relaxed(0, base + WRAPPER_A9SS_SW_RESET);
+}
+
+int venus_set_hw_state(struct venus_core *core, bool resume)
+{
+ void __iomem *base = core->base;
+
+ if (!core->no_tz)
+ return qcom_scm_set_remote_state(resume, 0);
+
+ if (resume)
+ venus_reset_cpu(core);
+ else
+ writel(1, base + WRAPPER_A9SS_SW_RESET);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(venus_set_hw_state);
+
int venus_boot(struct device *dev, const char *fwname)
{
const struct firmware *mdt;
diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
index 428efb5..ff2e70e 100644
--- a/drivers/media/platform/qcom/venus/firmware.h
+++ b/drivers/media/platform/qcom/venus/firmware.h
@@ -18,5 +18,6 @@

int venus_boot(struct device *dev, const char *fwname);
int venus_shutdown(struct device *dev);
+int venus_set_hw_state(struct venus_core *core, bool suspend);

#endif
diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index 9366dae..5b56925 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -19,7 +19,6 @@
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
-#include <linux/qcom_scm.h>
#include <linux/slab.h>

#include "core.h"
@@ -27,6 +26,7 @@
#include "hfi_msgs.h"
#include "hfi_venus.h"
#include "hfi_venus_io.h"
+#include "firmware.h"

#define HFI_MASK_QHDR_TX_TYPE 0xff000000
#define HFI_MASK_QHDR_RX_TYPE 0x00ff0000
@@ -55,11 +55,6 @@
#define IFACEQ_VAR_LARGE_PKT_SIZE 512
#define IFACEQ_VAR_HUGE_PKT_SIZE (1024 * 12)

-enum tzbsp_video_state {
- TZBSP_VIDEO_STATE_SUSPEND = 0,
- TZBSP_VIDEO_STATE_RESUME
-};
-
struct hfi_queue_table_header {
u32 version;
u32 size;
@@ -575,7 +570,7 @@ static int venus_power_off(struct venus_hfi_device *hdev)
if (!hdev->power_enabled)
return 0;

- ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
+ ret = venus_set_hw_state(hdev->core, false);
if (ret)
return ret;

@@ -595,7 +590,7 @@ static int venus_power_on(struct venus_hfi_device *hdev)
if (hdev->power_enabled)
return 0;

- ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_RESUME, 0);
+ ret = venus_set_hw_state(hdev->core, true);
if (ret)
goto err;

@@ -608,7 +603,7 @@ static int venus_power_on(struct venus_hfi_device *hdev)
return 0;

err_suspend:
- qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
+ venus_set_hw_state(hdev->core, false);
err:
hdev->power_enabled = false;
return ret;
diff --git a/drivers/media/platform/qcom/venus/hfi_venus_io.h b/drivers/media/platform/qcom/venus/hfi_venus_io.h
index def0926..0a4210f 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus_io.h
+++ b/drivers/media/platform/qcom/venus/hfi_venus_io.h
@@ -112,6 +112,11 @@
#define WRAPPER_CPU_STATUS (WRAPPER_BASE + 0x2014)
#define WRAPPER_CPU_STATUS_WFI BIT(0)
#define WRAPPER_SW_RESET (WRAPPER_BASE + 0x3000)
+#define WRAPPER_CPA_START_ADDR (WRAPPER_BASE + 0x1020)
+#define WRAPPER_CPA_END_ADDR (WRAPPER_BASE + 0x1024)
+#define WRAPPER_FW_START_ADDR (WRAPPER_BASE + 0x1028)
+#define WRAPPER_FW_END_ADDR (WRAPPER_BASE + 0x102C)
+#define WRAPPER_A9SS_SW_RESET (WRAPPER_BASE + 0x3000)

/* Venus 4xx */
#define WRAPPER_VCODEC0_MMCC_POWER_STATUS (WRAPPER_BASE + 0x90)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2018-07-04 19:08:56

by Vikash Garodia

[permalink] [raw]
Subject: [PATCH v3 2/4] venus: firmware: move load firmware in a separate function

Separate firmware loading part into a new function.

Signed-off-by: Vikash Garodia <[email protected]>
---
drivers/media/platform/qcom/venus/core.c | 4 +-
drivers/media/platform/qcom/venus/firmware.c | 58 +++++++++++++++++-----------
drivers/media/platform/qcom/venus/firmware.h | 2 +-
3 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index bb6add9..75b9785 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -84,7 +84,7 @@ static void venus_sys_error_handler(struct work_struct *work)

pm_runtime_get_sync(core->dev);

- ret |= venus_boot(core->dev, core->res->fwname);
+ ret |= venus_boot(core);

ret |= hfi_core_resume(core, true);

@@ -284,7 +284,7 @@ static int venus_probe(struct platform_device *pdev)
if (ret < 0)
goto err_runtime_disable;

- ret = venus_boot(dev, core->res->fwname);
+ ret = venus_boot(core);
if (ret)
goto err_runtime_disable;

diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
index 3968553d..6d6cca4 100644
--- a/drivers/media/platform/qcom/venus/firmware.c
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -63,40 +63,37 @@ int venus_set_hw_state(struct venus_core *core, bool resume)
}
EXPORT_SYMBOL_GPL(venus_set_hw_state);

-int venus_boot(struct device *dev, const char *fwname)
+static int venus_load_fw(struct venus_core *core, const char *fwname,
+ phys_addr_t *mem_phys, size_t *mem_size)
{
const struct firmware *mdt;
struct device_node *node;
- phys_addr_t mem_phys;
+ struct device *dev;
struct resource r;
ssize_t fw_size;
- size_t mem_size;
void *mem_va;
int ret;

- if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available())
- return -EPROBE_DEFER;
-
+ dev = core->dev;
node = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!node) {
dev_err(dev, "no memory-region specified\n");
return -EINVAL;
}
-
ret = of_address_to_resource(node, 0, &r);
if (ret)
return ret;

- mem_phys = r.start;
- mem_size = resource_size(&r);
+ *mem_phys = r.start;
+ *mem_size = resource_size(&r);

- if (mem_size < VENUS_FW_MEM_SIZE)
+ if (*mem_size < VENUS_FW_MEM_SIZE)
return -EINVAL;

- mem_va = memremap(r.start, mem_size, MEMREMAP_WC);
+ mem_va = memremap(r.start, *mem_size, MEMREMAP_WC);
if (!mem_va) {
dev_err(dev, "unable to map memory region: %pa+%zx\n",
- &r.start, mem_size);
+ &r.start, *mem_size);
return -ENOMEM;
}

@@ -110,24 +107,41 @@ int venus_boot(struct device *dev, const char *fwname)
release_firmware(mdt);
goto err_unmap;
}
-
- ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
- mem_size);
+ if (core->no_tz)
+ ret = qcom_mdt_load_no_init(dev, mdt, fwname, VENUS_PAS_ID,
+ mem_va, *mem_phys, *mem_size, NULL);
+ else
+ ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va,
+ *mem_phys, *mem_size);

release_firmware(mdt);

- if (ret)
- goto err_unmap;
-
- ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
- if (ret)
- goto err_unmap;
-
err_unmap:
memunmap(mem_va);
return ret;
}

+int venus_boot(struct venus_core *core)
+{
+ phys_addr_t mem_phys;
+ size_t mem_size;
+ int ret;
+ struct device *dev;
+
+ if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER))
+ return -EPROBE_DEFER;
+
+ dev = core->dev;
+
+ ret = venus_load_fw(core, core->res->fwname, &mem_phys, &mem_size);
+ if (ret) {
+ dev_err(dev, "fail to load video firmware\n");
+ return -EINVAL;
+ }
+
+ return qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
+}
+
int venus_shutdown(struct device *dev)
{
return qcom_scm_pas_shutdown(VENUS_PAS_ID);
diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
index ff2e70e..36a5fc2 100644
--- a/drivers/media/platform/qcom/venus/firmware.h
+++ b/drivers/media/platform/qcom/venus/firmware.h
@@ -16,7 +16,7 @@

struct device;

-int venus_boot(struct device *dev, const char *fwname);
+int venus_boot(struct venus_core *core);
int venus_shutdown(struct device *dev);
int venus_set_hw_state(struct venus_core *core, bool suspend);

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2018-07-04 19:09:03

by Vikash Garodia

[permalink] [raw]
Subject: [PATCH v3 4/4] venus: firmware: register separate driver for firmware device

A separate child device is added for video firmware.
This is needed to
[1] configure the firmware context bank with the desired SID.
[2] ensure that the iova for firmware region is from 0x0.

Signed-off-by: Vikash Garodia <[email protected]>
---
.../devicetree/bindings/media/qcom,venus.txt | 17 +++++++-
drivers/media/platform/qcom/venus/core.c | 49 +++++++++++++++++++---
drivers/media/platform/qcom/venus/firmware.c | 18 ++++++++
drivers/media/platform/qcom/venus/firmware.h | 2 +
4 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/qcom,venus.txt b/Documentation/devicetree/bindings/media/qcom,venus.txt
index 00d0d1b..975fb12 100644
--- a/Documentation/devicetree/bindings/media/qcom,venus.txt
+++ b/Documentation/devicetree/bindings/media/qcom,venus.txt
@@ -53,7 +53,7 @@

* Subnodes
The Venus video-codec node must contain two subnodes representing
-video-decoder and video-encoder.
+video-decoder and video-encoder, one optional firmware subnode.

Every of video-encoder or video-decoder subnode should have:

@@ -79,6 +79,17 @@ Every of video-encoder or video-decoder subnode should have:
power domain which is responsible for collapsing
and restoring power to the subcore.

+The firmware sub node must have:
+
+- compatible:
+ Usage: required
+ Value type: <stringlist>
+ Definition: Value should contain "venus-firmware"
+- iommus:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A list of phandle and IOMMU specifier pairs.
+
* An Example
video-codec@1d00000 {
compatible = "qcom,msm8916-venus";
@@ -105,4 +116,8 @@ Every of video-encoder or video-decoder subnode should have:
clock-names = "core";
power-domains = <&mmcc VENUS_CORE1_GDSC>;
};
+ venus-firmware {
+ compatible = "qcom,venus-firmware";
+ iommus = <&apps_smmu 0x10b2 0x0>;
+ }
};
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 393994e..420dca3 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -179,6 +179,20 @@ static u32 to_v4l2_codec_type(u32 codec)
}
}

+static int store_firmware_dev(struct device *dev, void *data)
+{
+ struct venus_core *core = data;
+ if (!core)
+ return -EINVAL;
+
+ if (of_device_is_compatible(dev->of_node, "qcom,venus-firmware")) {
+ core->fw.dev = dev;
+ core->no_tz = true;
+ }
+
+ return 0;
+}
+
static int venus_enumerate_codecs(struct venus_core *core, u32 type)
{
const struct hfi_inst_ops dummy_ops = {};
@@ -284,6 +298,13 @@ static int venus_probe(struct platform_device *pdev)
if (ret < 0)
goto err_runtime_disable;

+ ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+ if (ret)
+ goto err_runtime_disable;
+
+ /* Attempt to store firmware device */
+ device_for_each_child(dev, core, store_firmware_dev);
+
ret = venus_boot(core);
if (ret)
goto err_runtime_disable;
@@ -308,10 +329,6 @@ static int venus_probe(struct platform_device *pdev)
if (ret)
goto err_core_deinit;

- ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
- if (ret)
- goto err_dev_unregister;
-
ret = pm_runtime_put_sync(dev);
if (ret)
goto err_dev_unregister;
@@ -488,7 +505,29 @@ static __maybe_unused int venus_runtime_resume(struct device *dev)
.pm = &venus_pm_ops,
},
};
-module_platform_driver(qcom_venus_driver);
+
+static int __init venus_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&qcom_video_firmware_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&qcom_venus_driver);
+ if (ret)
+ platform_driver_unregister(&qcom_video_firmware_driver);
+
+ return ret;
+}
+module_init(venus_init);
+
+static void __exit venus_exit(void)
+{
+ platform_driver_unregister(&qcom_venus_driver);
+ platform_driver_unregister(&qcom_video_firmware_driver);
+}
+module_exit(venus_exit);

MODULE_ALIAS("platform:qcom-venus");
MODULE_DESCRIPTION("Qualcomm Venus video encoder and decoder driver");
diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
index 2a98d9e..4c0d808 100644
--- a/drivers/media/platform/qcom/venus/firmware.c
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -12,6 +12,7 @@
*
*/

+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/firmware.h>
@@ -231,3 +232,20 @@ int venus_shutdown(struct venus_core *core)

return ret;
}
+
+static const struct of_device_id firmware_dt_match[] = {
+ { .compatible = "qcom,venus-firmware" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, firmware_dt_match);
+
+struct platform_driver qcom_video_firmware_driver = {
+ .driver = {
+ .name = "qcom-video-firmware",
+ .of_match_table = firmware_dt_match,
+ },
+};
+
+MODULE_ALIAS("platform:qcom-video-firmware");
+MODULE_DESCRIPTION("Qualcomm Venus firmware driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
index 92736d6..8f4848f 100644
--- a/drivers/media/platform/qcom/venus/firmware.h
+++ b/drivers/media/platform/qcom/venus/firmware.h
@@ -16,6 +16,8 @@

struct device;

+extern struct platform_driver qcom_video_firmware_driver;
+
int venus_boot(struct venus_core *core);
int venus_shutdown(struct venus_core *core);
int venus_set_hw_state(struct venus_core *core, bool suspend);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2018-07-04 19:10:06

by Vikash Garodia

[permalink] [raw]
Subject: [PATCH v3 3/4] venus: firmware: add no TZ boot and shutdown routine

Video hardware is mainly comprised of vcodec subsystem and video
control subsystem. Video control has ARM9 which executes the video
firmware instructions whereas vcodec does the video frame processing.
This change adds support to load the video firmware and bring ARM9
out of reset for platforms which does not have trustzone.

Signed-off-by: Vikash Garodia <[email protected]>
---
drivers/media/platform/qcom/venus/core.c | 6 +-
drivers/media/platform/qcom/venus/core.h | 5 ++
drivers/media/platform/qcom/venus/firmware.c | 93 ++++++++++++++++++++++++++--
drivers/media/platform/qcom/venus/firmware.h | 2 +-
4 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 75b9785..393994e 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -76,7 +76,7 @@ static void venus_sys_error_handler(struct work_struct *work)
hfi_core_deinit(core, true);
hfi_destroy(core);
mutex_lock(&core->lock);
- venus_shutdown(core->dev);
+ venus_shutdown(core);

pm_runtime_put_sync(core->dev);

@@ -323,7 +323,7 @@ static int venus_probe(struct platform_device *pdev)
err_core_deinit:
hfi_core_deinit(core, false);
err_venus_shutdown:
- venus_shutdown(dev);
+ venus_shutdown(core);
err_runtime_disable:
pm_runtime_set_suspended(dev);
pm_runtime_disable(dev);
@@ -344,7 +344,7 @@ static int venus_remove(struct platform_device *pdev)
WARN_ON(ret);

hfi_destroy(core);
- venus_shutdown(dev);
+ venus_shutdown(core);
of_platform_depopulate(dev);

pm_runtime_put_sync(dev);
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index eb5ee66..abe4ddf 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -81,6 +81,10 @@ struct venus_caps {
bool valid; /* used only for Venus v1xx */
};

+struct video_firmware {
+ struct device *dev;
+ struct iommu_domain *iommu_domain;
+};
/**
* struct venus_core - holds core parameters valid for all instances
*
@@ -129,6 +133,7 @@ struct venus_core {
struct device *dev;
struct device *dev_dec;
struct device *dev_enc;
+ struct video_firmware fw;
bool no_tz;
struct mutex lock;
struct list_head instances;
diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
index 6d6cca4..2a98d9e 100644
--- a/drivers/media/platform/qcom/venus/firmware.c
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -12,8 +12,10 @@
*
*/

+#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -27,7 +29,8 @@
#include "hfi_venus_io.h"

#define VENUS_PAS_ID 9
-#define VENUS_FW_MEM_SIZE (6 * SZ_1M)
+#define VENUS_FW_MEM_SIZE (5 * SZ_1M)
+#define VENUS_FW_START_ADDR 0x0

static void venus_reset_cpu(struct venus_core *core)
{
@@ -121,6 +124,76 @@ static int venus_load_fw(struct venus_core *core, const char *fwname,
return ret;
}

+int venus_boot_noTZ(struct venus_core *core, phys_addr_t mem_phys,
+ size_t mem_size)
+{
+ struct iommu_domain *iommu;
+ struct device *dev;
+ int ret;
+
+ if (!core->fw.dev)
+ return -EPROBE_DEFER;
+
+ dev = core->fw.dev;
+
+ iommu = iommu_domain_alloc(&platform_bus_type);
+ if (!iommu) {
+ dev_err(dev, "Failed to allocate iommu domain\n");
+ return -ENOMEM;
+ }
+
+ ret = iommu_attach_device(iommu, dev);
+ if (ret) {
+ dev_err(dev, "could not attach device\n");
+ goto err_attach;
+ }
+
+ ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size,
+ IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV);
+ if (ret) {
+ dev_err(dev, "could not map video firmware region\n");
+ goto err_map;
+ }
+ core->fw.iommu_domain = iommu;
+ venus_reset_cpu(core);
+
+ return 0;
+
+err_map:
+ iommu_detach_device(iommu, dev);
+err_attach:
+ iommu_domain_free(iommu);
+ return ret;
+}
+
+int venus_shutdown_noTZ(struct venus_core *core)
+{
+ struct iommu_domain *iommu;
+ size_t unmapped = 0;
+ u32 reg;
+ struct device *dev = core->fw.dev;
+ void __iomem *reg_base = core->base;
+
+ /* Assert the reset to ARM9 */
+ reg = readl_relaxed(reg_base + WRAPPER_A9SS_SW_RESET);
+ reg |= BIT(4);
+ writel_relaxed(reg, reg_base + WRAPPER_A9SS_SW_RESET);
+
+ /* Make sure reset is asserted before the mapping is removed */
+ mb();
+
+ iommu = core->fw.iommu_domain;
+
+ unmapped = iommu_unmap(iommu, VENUS_FW_START_ADDR, VENUS_FW_MEM_SIZE);
+ if (unmapped != VENUS_FW_MEM_SIZE)
+ dev_err(dev, "failed to unmap firmware\n");
+
+ iommu_detach_device(iommu, dev);
+ iommu_domain_free(iommu);
+
+ return 0;
+}
+
int venus_boot(struct venus_core *core)
{
phys_addr_t mem_phys;
@@ -139,10 +212,22 @@ int venus_boot(struct venus_core *core)
return -EINVAL;
}

- return qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
+ if (core->no_tz)
+ ret = venus_boot_noTZ(core, mem_phys, mem_size);
+ else
+ ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
+
+ return ret;
}

-int venus_shutdown(struct device *dev)
+int venus_shutdown(struct venus_core *core)
{
- return qcom_scm_pas_shutdown(VENUS_PAS_ID);
+ int ret = 0;
+
+ if (core->no_tz)
+ ret = venus_shutdown_noTZ(core);
+ else
+ ret = qcom_scm_pas_shutdown(VENUS_PAS_ID);
+
+ return ret;
}
diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
index 36a5fc2..92736d6 100644
--- a/drivers/media/platform/qcom/venus/firmware.h
+++ b/drivers/media/platform/qcom/venus/firmware.h
@@ -17,7 +17,7 @@
struct device;

int venus_boot(struct venus_core *core);
-int venus_shutdown(struct device *dev);
+int venus_shutdown(struct venus_core *core);
int venus_set_hw_state(struct venus_core *core, bool suspend);

#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2018-07-05 23:38:29

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v3 4/4] venus: firmware: register separate driver for firmware device

On Thu, Jul 05, 2018 at 12:36:52AM +0530, Vikash Garodia wrote:
> A separate child device is added for video firmware.
> This is needed to
> [1] configure the firmware context bank with the desired SID.
> [2] ensure that the iova for firmware region is from 0x0.
>
> Signed-off-by: Vikash Garodia <[email protected]>
> ---
> .../devicetree/bindings/media/qcom,venus.txt | 17 +++++++-

Reviewed-by: Rob Herring <[email protected]>

> drivers/media/platform/qcom/venus/core.c | 49 +++++++++++++++++++---
> drivers/media/platform/qcom/venus/firmware.c | 18 ++++++++
> drivers/media/platform/qcom/venus/firmware.h | 2 +
> 4 files changed, 80 insertions(+), 6 deletions(-)

2018-07-25 09:36:53

by Stanimir Varbanov

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] venus: firmware: add routine to reset ARM9

Hi Vikash,

On 07/04/2018 10:06 PM, Vikash Garodia wrote:
> Add routine to reset the ARM9 and brings it out of reset. Also
> abstract the Venus CPU state handling with a new function. This
> is in preparation to add PIL functionality in venus driver.
>
> Signed-off-by: Vikash Garodia <[email protected]>
> ---
> drivers/media/platform/qcom/venus/core.h | 1 +
> drivers/media/platform/qcom/venus/firmware.c | 36 ++++++++++++++++++++++++
> drivers/media/platform/qcom/venus/firmware.h | 1 +
> drivers/media/platform/qcom/venus/hfi_venus.c | 13 +++------
> drivers/media/platform/qcom/venus/hfi_venus_io.h | 5 ++++
> 5 files changed, 47 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
> index 2f02365..eb5ee66 100644
> --- a/drivers/media/platform/qcom/venus/core.h
> +++ b/drivers/media/platform/qcom/venus/core.h
> @@ -129,6 +129,7 @@ struct venus_core {
> struct device *dev;
> struct device *dev_dec;
> struct device *dev_enc;
> + bool no_tz;
> struct mutex lock;
> struct list_head instances;
> atomic_t insts_count;
> diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
> index 521d4b3..3968553d 100644
> --- a/drivers/media/platform/qcom/venus/firmware.c
> +++ b/drivers/media/platform/qcom/venus/firmware.c
> @@ -22,11 +22,47 @@
> #include <linux/sizes.h>
> #include <linux/soc/qcom/mdt_loader.h>
>
> +#include "core.h"
> #include "firmware.h"
> +#include "hfi_venus_io.h"
>
> #define VENUS_PAS_ID 9
> #define VENUS_FW_MEM_SIZE (6 * SZ_1M)
>
> +static void venus_reset_cpu(struct venus_core *core)
> +{
> + void __iomem *base = core->base;
> +
> + writel(0, base + WRAPPER_FW_START_ADDR);
> + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR);
> + writel(0, base + WRAPPER_CPA_START_ADDR);
> + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR);
> + writel(0x0, base + WRAPPER_CPU_CGC_DIS);
> + writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG);
> +
> + /* Make sure all register writes are committed. */
> + mb();
> +
> + /* Bring ARM9 out of reset */
> + writel_relaxed(0, base + WRAPPER_A9SS_SW_RESET);

replace writel_relaxed with writel and drop above mb. The writel has wmb
just before writing so I think using writel here is better choice.

> +}
> +
> +int venus_set_hw_state(struct venus_core *core, bool resume)

s/resume/suspend as it is done in the function prototype in firmware.h.

> +{
> + void __iomem *base = core->base;
> +
> + if (!core->no_tz)
> + return qcom_scm_set_remote_state(resume, 0);
> +
> + if (resume)
> + venus_reset_cpu(core);
> + else
> + writel(1, base + WRAPPER_A9SS_SW_RESET);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(venus_set_hw_state);
> +
> int venus_boot(struct device *dev, const char *fwname)
> {
> const struct firmware *mdt;
> diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
> index 428efb5..ff2e70e 100644
> --- a/drivers/media/platform/qcom/venus/firmware.h
> +++ b/drivers/media/platform/qcom/venus/firmware.h
> @@ -18,5 +18,6 @@
>
> int venus_boot(struct device *dev, const char *fwname);
> int venus_shutdown(struct device *dev);
> +int venus_set_hw_state(struct venus_core *core, bool suspend);

could you make two inline functions here, call them
venus_set_hw_state_suspend() and venus_set_hw_state_resume() which just
call venus_set_hw_state with the right state.

>
> #endif
> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
> index 9366dae..5b56925 100644
> --- a/drivers/media/platform/qcom/venus/hfi_venus.c
> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c
> @@ -19,7 +19,6 @@
> #include <linux/interrupt.h>
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> -#include <linux/qcom_scm.h>
> #include <linux/slab.h>
>
> #include "core.h"
> @@ -27,6 +26,7 @@
> #include "hfi_msgs.h"
> #include "hfi_venus.h"
> #include "hfi_venus_io.h"
> +#include "firmware.h"
>
> #define HFI_MASK_QHDR_TX_TYPE 0xff000000
> #define HFI_MASK_QHDR_RX_TYPE 0x00ff0000
> @@ -55,11 +55,6 @@
> #define IFACEQ_VAR_LARGE_PKT_SIZE 512
> #define IFACEQ_VAR_HUGE_PKT_SIZE (1024 * 12)
>
> -enum tzbsp_video_state {
> - TZBSP_VIDEO_STATE_SUSPEND = 0,
> - TZBSP_VIDEO_STATE_RESUME
> -};
> -
> struct hfi_queue_table_header {
> u32 version;
> u32 size;
> @@ -575,7 +570,7 @@ static int venus_power_off(struct venus_hfi_device *hdev)
> if (!hdev->power_enabled)
> return 0;
>
> - ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
> + ret = venus_set_hw_state(hdev->core, false);

... and use venus_set_hw_state_suspend()

> if (ret)
> return ret;
>
> @@ -595,7 +590,7 @@ static int venus_power_on(struct venus_hfi_device *hdev)
> if (hdev->power_enabled)
> return 0;
>
> - ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_RESUME, 0);
> + ret = venus_set_hw_state(hdev->core, true);

... and use venus_set_hw_state_resume()

> if (ret)
> goto err;
>
> @@ -608,7 +603,7 @@ static int venus_power_on(struct venus_hfi_device *hdev)
> return 0;
>
> err_suspend:
> - qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
> + venus_set_hw_state(hdev->core, false);
> err:
> hdev->power_enabled = false;
> return ret;
> diff --git a/drivers/media/platform/qcom/venus/hfi_venus_io.h b/drivers/media/platform/qcom/venus/hfi_venus_io.h
> index def0926..0a4210f 100644
> --- a/drivers/media/platform/qcom/venus/hfi_venus_io.h
> +++ b/drivers/media/platform/qcom/venus/hfi_venus_io.h
> @@ -112,6 +112,11 @@
> #define WRAPPER_CPU_STATUS (WRAPPER_BASE + 0x2014)
> #define WRAPPER_CPU_STATUS_WFI BIT(0)
> #define WRAPPER_SW_RESET (WRAPPER_BASE + 0x3000)
> +#define WRAPPER_CPA_START_ADDR (WRAPPER_BASE + 0x1020)
> +#define WRAPPER_CPA_END_ADDR (WRAPPER_BASE + 0x1024)
> +#define WRAPPER_FW_START_ADDR (WRAPPER_BASE + 0x1028)
> +#define WRAPPER_FW_END_ADDR (WRAPPER_BASE + 0x102C)
> +#define WRAPPER_A9SS_SW_RESET (WRAPPER_BASE + 0x3000)

something is wrong with tabs/indentation could you check? seems only
WRAPPER_FW_END_ADDR is fine.

>
> /* Venus 4xx */
> #define WRAPPER_VCODEC0_MMCC_POWER_STATUS (WRAPPER_BASE + 0x90)
>

--
regards,
Stan

2018-07-25 09:37:36

by Stanimir Varbanov

[permalink] [raw]
Subject: Re: [PATCH v3 3/4] venus: firmware: add no TZ boot and shutdown routine

Hi Vikash,

On 07/04/2018 10:06 PM, Vikash Garodia wrote:
> Video hardware is mainly comprised of vcodec subsystem and video
> control subsystem. Video control has ARM9 which executes the video
> firmware instructions whereas vcodec does the video frame processing.
> This change adds support to load the video firmware and bring ARM9
> out of reset for platforms which does not have trustzone.
>
> Signed-off-by: Vikash Garodia <[email protected]>
> ---
> drivers/media/platform/qcom/venus/core.c | 6 +-
> drivers/media/platform/qcom/venus/core.h | 5 ++
> drivers/media/platform/qcom/venus/firmware.c | 93 ++++++++++++++++++++++++++--
> drivers/media/platform/qcom/venus/firmware.h | 2 +-
> 4 files changed, 98 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
> index 75b9785..393994e 100644
> --- a/drivers/media/platform/qcom/venus/core.c
> +++ b/drivers/media/platform/qcom/venus/core.c
> @@ -76,7 +76,7 @@ static void venus_sys_error_handler(struct work_struct *work)
> hfi_core_deinit(core, true);
> hfi_destroy(core);
> mutex_lock(&core->lock);
> - venus_shutdown(core->dev);
> + venus_shutdown(core);
>
> pm_runtime_put_sync(core->dev);
>
> @@ -323,7 +323,7 @@ static int venus_probe(struct platform_device *pdev)
> err_core_deinit:
> hfi_core_deinit(core, false);
> err_venus_shutdown:
> - venus_shutdown(dev);
> + venus_shutdown(core);
> err_runtime_disable:
> pm_runtime_set_suspended(dev);
> pm_runtime_disable(dev);
> @@ -344,7 +344,7 @@ static int venus_remove(struct platform_device *pdev)
> WARN_ON(ret);
>
> hfi_destroy(core);
> - venus_shutdown(dev);
> + venus_shutdown(core);
> of_platform_depopulate(dev);
>
> pm_runtime_put_sync(dev);
> diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
> index eb5ee66..abe4ddf 100644
> --- a/drivers/media/platform/qcom/venus/core.h
> +++ b/drivers/media/platform/qcom/venus/core.h
> @@ -81,6 +81,10 @@ struct venus_caps {
> bool valid; /* used only for Venus v1xx */
> };
>
> +struct video_firmware {
> + struct device *dev;
> + struct iommu_domain *iommu_domain;
> +};

add an empty line here

> /**
> * struct venus_core - holds core parameters valid for all instances
> *
> @@ -129,6 +133,7 @@ struct venus_core {
> struct device *dev;
> struct device *dev_dec;
> struct device *dev_enc;
> + struct video_firmware fw;
> bool no_tz;
> struct mutex lock;
> struct list_head instances;
> diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
> index 6d6cca4..2a98d9e 100644
> --- a/drivers/media/platform/qcom/venus/firmware.c
> +++ b/drivers/media/platform/qcom/venus/firmware.c
> @@ -12,8 +12,10 @@
> *
> */
>
> +#include <linux/platform_device.h>
> #include <linux/device.h>
> #include <linux/firmware.h>
> +#include <linux/iommu.h>
> #include <linux/kernel.h>
> #include <linux/io.h>
> #include <linux/of.h>
> @@ -27,7 +29,8 @@
> #include "hfi_venus_io.h"
>
> #define VENUS_PAS_ID 9
> -#define VENUS_FW_MEM_SIZE (6 * SZ_1M)
> +#define VENUS_FW_MEM_SIZE (5 * SZ_1M)

This change should be subject to a separate patch.

> +#define VENUS_FW_START_ADDR 0x0
>
> static void venus_reset_cpu(struct venus_core *core)
> {
> @@ -121,6 +124,76 @@ static int venus_load_fw(struct venus_core *core, const char *fwname,
> return ret;
> }
>
> +int venus_boot_noTZ(struct venus_core *core, phys_addr_t mem_phys,
> + size_t mem_size)

please use lowercase for function names and correct the size_t mem_size
indentation.

> +{
> + struct iommu_domain *iommu;

s/iommu/iommu_dom ?

> + struct device *dev;
> + int ret;
> +
> + if (!core->fw.dev)
> + return -EPROBE_DEFER;
> +
> + dev = core->fw.dev;

you could make this initialization in declaration and check for !dev
above in the if statement.

> +
> + iommu = iommu_domain_alloc(&platform_bus_type);
> + if (!iommu) {
> + dev_err(dev, "Failed to allocate iommu domain\n");
> + return -ENOMEM;
> + }
> +
> + ret = iommu_attach_device(iommu, dev);
> + if (ret) {
> + dev_err(dev, "could not attach device\n");
> + goto err_attach;
> + }
> +
> + ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size,
> + IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV);

spaces between IOMMU_xxx

> + if (ret) {
> + dev_err(dev, "could not map video firmware region\n");
> + goto err_map;
> + }

add blank line here

> + core->fw.iommu_domain = iommu;
> + venus_reset_cpu(core);
> +
> + return 0;
> +
> +err_map:
> + iommu_detach_device(iommu, dev);
> +err_attach:
> + iommu_domain_free(iommu);
> + return ret;
> +}
> +
> +int venus_shutdown_noTZ(struct venus_core *core)

s/noTZ/notz

> +{
> + struct iommu_domain *iommu;
> + size_t unmapped = 0;
> + u32 reg;
> + struct device *dev = core->fw.dev;
> + void __iomem *reg_base = core->base;
> +
> + /* Assert the reset to ARM9 */
> + reg = readl_relaxed(reg_base + WRAPPER_A9SS_SW_RESET);
> + reg |= BIT(4);

can we have a define for bit 4, probably where we defined
WRAPPER_A9SS_SW_RESET register.

> + writel_relaxed(reg, reg_base + WRAPPER_A9SS_SW_RESET);
> +
> + /* Make sure reset is asserted before the mapping is removed */
> + mb();

mb() is used for compiler barrier as far as I know, isn't better to just
read the register and keep the comment?

> +
> + iommu = core->fw.iommu_domain;
> +
> + unmapped = iommu_unmap(iommu, VENUS_FW_START_ADDR, VENUS_FW_MEM_SIZE);
> + if (unmapped != VENUS_FW_MEM_SIZE)
> + dev_err(dev, "failed to unmap firmware\n");
> +
> + iommu_detach_device(iommu, dev);
> + iommu_domain_free(iommu);
> +
> + return 0;
> +}
> +
> int venus_boot(struct venus_core *core)
> {
> phys_addr_t mem_phys;
> @@ -139,10 +212,22 @@ int venus_boot(struct venus_core *core)
> return -EINVAL;
> }
>
> - return qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
> + if (core->no_tz)
> + ret = venus_boot_noTZ(core, mem_phys, mem_size);
> + else
> + ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
> +
> + return ret;
> }
>
> -int venus_shutdown(struct device *dev)
> +int venus_shutdown(struct venus_core *core)
> {
> - return qcom_scm_pas_shutdown(VENUS_PAS_ID);
> + int ret = 0;

no need to initialize to 0

> +
> + if (core->no_tz)
> + ret = venus_shutdown_noTZ(core);
> + else
> + ret = qcom_scm_pas_shutdown(VENUS_PAS_ID);
> +
> + return ret;
> }
> diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
> index 36a5fc2..92736d6 100644
> --- a/drivers/media/platform/qcom/venus/firmware.h
> +++ b/drivers/media/platform/qcom/venus/firmware.h
> @@ -17,7 +17,7 @@
> struct device;
>
> int venus_boot(struct venus_core *core);
> -int venus_shutdown(struct device *dev);
> +int venus_shutdown(struct venus_core *core);
> int venus_set_hw_state(struct venus_core *core, bool suspend);
>
> #endif
>

--
regards,
Stan

2018-07-25 09:38:38

by Stanimir Varbanov

[permalink] [raw]
Subject: Re: [PATCH v3 2/4] venus: firmware: move load firmware in a separate function

Hi Vikash,

On 07/04/2018 10:06 PM, Vikash Garodia wrote:
> Separate firmware loading part into a new function.

I cannot apply this patch in order to test the series.

>
> Signed-off-by: Vikash Garodia <[email protected]>
> ---
> drivers/media/platform/qcom/venus/core.c | 4 +-
> drivers/media/platform/qcom/venus/firmware.c | 58 +++++++++++++++++-----------
> drivers/media/platform/qcom/venus/firmware.h | 2 +-
> 3 files changed, 39 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
> index bb6add9..75b9785 100644
> --- a/drivers/media/platform/qcom/venus/core.c
> +++ b/drivers/media/platform/qcom/venus/core.c
> @@ -84,7 +84,7 @@ static void venus_sys_error_handler(struct work_struct *work)
>
> pm_runtime_get_sync(core->dev);
>
> - ret |= venus_boot(core->dev, core->res->fwname);
> + ret |= venus_boot(core);
>
> ret |= hfi_core_resume(core, true);
>
> @@ -284,7 +284,7 @@ static int venus_probe(struct platform_device *pdev)
> if (ret < 0)
> goto err_runtime_disable;
>
> - ret = venus_boot(dev, core->res->fwname);
> + ret = venus_boot(core);
> if (ret)
> goto err_runtime_disable;
>
> diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
> index 3968553d..6d6cca4 100644
> --- a/drivers/media/platform/qcom/venus/firmware.c
> +++ b/drivers/media/platform/qcom/venus/firmware.c
> @@ -63,40 +63,37 @@ int venus_set_hw_state(struct venus_core *core, bool resume)
> }
> EXPORT_SYMBOL_GPL(venus_set_hw_state);
>
> -int venus_boot(struct device *dev, const char *fwname)
> +static int venus_load_fw(struct venus_core *core, const char *fwname,
> + phys_addr_t *mem_phys, size_t *mem_size)

the next function argument on new line should be just below open brace

> {
> const struct firmware *mdt;
> struct device_node *node;
> - phys_addr_t mem_phys;
> + struct device *dev;
> struct resource r;
> ssize_t fw_size;
> - size_t mem_size;
> void *mem_va;
> int ret;
>
> - if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available())
> - return -EPROBE_DEFER;
> -
> + dev = core->dev;
> node = of_parse_phandle(dev->of_node, "memory-region", 0);
> if (!node) {
> dev_err(dev, "no memory-region specified\n");
> return -EINVAL;
> }
> -

please don't delete above blank line

> ret = of_address_to_resource(node, 0, &r);
> if (ret)
> return ret;
>
> - mem_phys = r.start;
> - mem_size = resource_size(&r);
> + *mem_phys = r.start;
> + *mem_size = resource_size(&r);
>
> - if (mem_size < VENUS_FW_MEM_SIZE)
> + if (*mem_size < VENUS_FW_MEM_SIZE)
> return -EINVAL;
>
> - mem_va = memremap(r.start, mem_size, MEMREMAP_WC);
> + mem_va = memremap(r.start, *mem_size, MEMREMAP_WC);
> if (!mem_va) {
> dev_err(dev, "unable to map memory region: %pa+%zx\n",
> - &r.start, mem_size);
> + &r.start, *mem_size);
> return -ENOMEM;
> }
>
> @@ -110,24 +107,41 @@ int venus_boot(struct device *dev, const char *fwname)
> release_firmware(mdt);
> goto err_unmap;
> }
> -
> - ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
> - mem_size);
> + if (core->no_tz)
> + ret = qcom_mdt_load_no_init(dev, mdt, fwname, VENUS_PAS_ID,
> + mem_va, *mem_phys, *mem_size, NULL);

indentation is wrong see the original code

> + else
> + ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va,
> + *mem_phys, *mem_size);

indentation again

>
> release_firmware(mdt);
>
> - if (ret)
> - goto err_unmap;
> -
> - ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
> - if (ret)
> - goto err_unmap;
> -
> err_unmap:
> memunmap(mem_va);
> return ret;
> }
>
> +int venus_boot(struct venus_core *core)
> +{
> + phys_addr_t mem_phys;
> + size_t mem_size;
> + int ret;
> + struct device *dev;

please order declarations from longer to shorter.

> +
> + if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER))
> + return -EPROBE_DEFER;

the original venus_boot was checking for || !qcom_scm_is_available() why
is that removed? It was done on purpose.

> +
> + dev = core->dev;

this could be done when dev is declared.

> +
> + ret = venus_load_fw(core, core->res->fwname, &mem_phys, &mem_size);
> + if (ret) {
> + dev_err(dev, "fail to load video firmware\n");
> + return -EINVAL;
> + }
> +
> + return qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
> +}
> +
> int venus_shutdown(struct device *dev)
> {
> return qcom_scm_pas_shutdown(VENUS_PAS_ID);
> diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
> index ff2e70e..36a5fc2 100644
> --- a/drivers/media/platform/qcom/venus/firmware.h
> +++ b/drivers/media/platform/qcom/venus/firmware.h
> @@ -16,7 +16,7 @@
>
> struct device;
>
> -int venus_boot(struct device *dev, const char *fwname);
> +int venus_boot(struct venus_core *core);
> int venus_shutdown(struct device *dev);
> int venus_set_hw_state(struct venus_core *core, bool suspend);
>
>

--
regards,
Stan

2018-07-25 11:16:15

by Stanimir Varbanov

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] venus: firmware: add routine to reset ARM9

Hi,

On 07/04/2018 10:06 PM, Vikash Garodia wrote:
> Add routine to reset the ARM9 and brings it out of reset. Also
> abstract the Venus CPU state handling with a new function. This
> is in preparation to add PIL functionality in venus driver.
>
> Signed-off-by: Vikash Garodia <[email protected]>
> ---
> drivers/media/platform/qcom/venus/core.h | 1 +
> drivers/media/platform/qcom/venus/firmware.c | 36 ++++++++++++++++++++++++
> drivers/media/platform/qcom/venus/firmware.h | 1 +
> drivers/media/platform/qcom/venus/hfi_venus.c | 13 +++------
> drivers/media/platform/qcom/venus/hfi_venus_io.h | 5 ++++
> 5 files changed, 47 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
> index 2f02365..eb5ee66 100644
> --- a/drivers/media/platform/qcom/venus/core.h
> +++ b/drivers/media/platform/qcom/venus/core.h
> @@ -129,6 +129,7 @@ struct venus_core {
> struct device *dev;
> struct device *dev_dec;
> struct device *dev_enc;
> + bool no_tz;
> struct mutex lock;
> struct list_head instances;
> atomic_t insts_count;
> diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
> index 521d4b3..3968553d 100644
> --- a/drivers/media/platform/qcom/venus/firmware.c
> +++ b/drivers/media/platform/qcom/venus/firmware.c
> @@ -22,11 +22,47 @@
> #include <linux/sizes.h>
> #include <linux/soc/qcom/mdt_loader.h>
>
> +#include "core.h"
> #include "firmware.h"
> +#include "hfi_venus_io.h"
>
> #define VENUS_PAS_ID 9
> #define VENUS_FW_MEM_SIZE (6 * SZ_1M)
>
> +static void venus_reset_cpu(struct venus_core *core)
> +{
> + void __iomem *base = core->base;
> +
> + writel(0, base + WRAPPER_FW_START_ADDR);
> + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR);
> + writel(0, base + WRAPPER_CPA_START_ADDR);
> + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR);
> + writel(0x0, base + WRAPPER_CPU_CGC_DIS);
> + writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG);
> +
> + /* Make sure all register writes are committed. */
> + mb();
> +
> + /* Bring ARM9 out of reset */
> + writel_relaxed(0, base + WRAPPER_A9SS_SW_RESET);
> +}
> +
> +int venus_set_hw_state(struct venus_core *core, bool resume)
> +{
> + void __iomem *base = core->base;
> +
> + if (!core->no_tz)
> + return qcom_scm_set_remote_state(resume, 0);
> +
> + if (resume)
> + venus_reset_cpu(core);
> + else
> + writel(1, base + WRAPPER_A9SS_SW_RESET);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(venus_set_hw_state);

This export_symbol shouldn't be needed

--
regards,
Stan

2018-08-06 08:20:36

by Vikash Garodia

[permalink] [raw]
Subject: Re: [PATCH v3 3/4] venus: firmware: add no TZ boot and shutdown routine

Hi Stanimir,

Thanks for your review.

On 2018-07-25 15:06, Stanimir Varbanov wrote:
> Hi Vikash,
>
> On 07/04/2018 10:06 PM, Vikash Garodia wrote:
>
<snip>

>>
>> #define VENUS_PAS_ID 9
>> -#define VENUS_FW_MEM_SIZE (6 * SZ_1M)
>> +#define VENUS_FW_MEM_SIZE (5 * SZ_1M)
>
> This change should be subject to a separate patch.
Ok.

>
<snip>

>> + writel_relaxed(reg, reg_base + WRAPPER_A9SS_SW_RESET);
>> +
>> + /* Make sure reset is asserted before the mapping is removed */
>> + mb();
>
> mb() is used for compiler barrier as far as I know, isn't better to
> just
> read the register and keep the comment?

mb() can ensure that the instructions are ordered. This is needed to
ensure
reset before the mapping is removed.

Thanks,
Vikash

2018-08-06 08:26:00

by Vikash Garodia

[permalink] [raw]
Subject: Re: [PATCH v3 2/4] venus: firmware: move load firmware in a separate function

Hi Stanimir,

On 2018-07-25 15:05, Stanimir Varbanov wrote:
> Hi Vikash,
>
> On 07/04/2018 10:06 PM, Vikash Garodia wrote:

<snip>

>> +
>> + if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER))
>> + return -EPROBE_DEFER;
>
> the original venus_boot was checking for || !qcom_scm_is_available()
> why
> is that removed? It was done on purpose.

For booting venus without tz, scm calls are not needed. Does it look
good to
keep the check for "!core->no_tz" case alone ?

if (!core->no_tz && !qcom_scm_is_available())
return -EPROBE_DEFER;

Thanks,
Vikash

2018-08-06 13:47:11

by Vikash Garodia

[permalink] [raw]
Subject: Re: [PATCH v3 2/4] venus: firmware: move load firmware in a separate function

Hi Stanimir,

On 2018-07-25 15:05, Stanimir Varbanov wrote:
> Hi Vikash,
>
> On 07/04/2018 10:06 PM, Vikash Garodia wrote:
>> Separate firmware loading part into a new function.
>
> I cannot apply this patch in order to test the series.
Sorry about the inconvenience. Most probably this PIL patch series
was based on previous version of the venus update series from you.
I have posted a new series which is based on the latest venus driver.

>>
>> Signed-off-by: Vikash Garodia <[email protected]>
>> ---
<snip>