summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/qcom/venus/firmware.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:02:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:02:30 +0000
commit76cb841cb886eef6b3bee341a2266c76578724ad (patch)
treef5892e5ba6cc11949952a6ce4ecbe6d516d6ce58 /drivers/media/platform/qcom/venus/firmware.c
parentInitial commit. (diff)
downloadlinux-76cb841cb886eef6b3bee341a2266c76578724ad.tar.xz
linux-76cb841cb886eef6b3bee341a2266c76578724ad.zip
Adding upstream version 4.19.249.upstream/4.19.249
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/media/platform/qcom/venus/firmware.c')
-rw-r--r--drivers/media/platform/qcom/venus/firmware.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
new file mode 100644
index 000000000..c4a577848
--- /dev/null
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/qcom_scm.h>
+#include <linux/sizes.h>
+#include <linux/soc/qcom/mdt_loader.h>
+
+#include "firmware.h"
+
+#define VENUS_PAS_ID 9
+#define VENUS_FW_MEM_SIZE (6 * SZ_1M)
+
+int venus_boot(struct device *dev, const char *fwname)
+{
+ const struct firmware *mdt;
+ struct device_node *node;
+ phys_addr_t mem_phys;
+ 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;
+
+ 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);
+
+ if (mem_size < VENUS_FW_MEM_SIZE)
+ return -EINVAL;
+
+ 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);
+ return -ENOMEM;
+ }
+
+ ret = request_firmware(&mdt, fwname, dev);
+ if (ret < 0)
+ goto err_unmap;
+
+ fw_size = qcom_mdt_get_size(mdt);
+ if (fw_size < 0) {
+ ret = fw_size;
+ release_firmware(mdt);
+ goto err_unmap;
+ }
+
+ ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
+ mem_size, NULL);
+
+ 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_shutdown(struct device *dev)
+{
+ return qcom_scm_pas_shutdown(VENUS_PAS_ID);
+}