]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/platform/qcom/venus/firmware.c
Merge tag 'for-linus-20170825' of git://git.infradead.org/linux-mtd
[mirror_ubuntu-artful-kernel.git] / drivers / media / platform / qcom / venus / firmware.c
CommitLineData
af2c3834
SV
1/*
2 * Copyright (C) 2017 Linaro Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
377a22d3 15#include <linux/device.h>
af2c3834
SV
16#include <linux/firmware.h>
17#include <linux/kernel.h>
377a22d3 18#include <linux/io.h>
af2c3834 19#include <linux/of.h>
377a22d3 20#include <linux/of_address.h>
af2c3834 21#include <linux/qcom_scm.h>
377a22d3 22#include <linux/sizes.h>
af2c3834
SV
23#include <linux/soc/qcom/mdt_loader.h>
24
25#include "firmware.h"
26
af2c3834 27#define VENUS_PAS_ID 9
377a22d3 28#define VENUS_FW_MEM_SIZE (6 * SZ_1M)
af2c3834 29
377a22d3 30int venus_boot(struct device *dev, const char *fwname)
af2c3834
SV
31{
32 const struct firmware *mdt;
377a22d3 33 struct device_node *node;
af2c3834 34 phys_addr_t mem_phys;
377a22d3 35 struct resource r;
af2c3834
SV
36 ssize_t fw_size;
37 size_t mem_size;
38 void *mem_va;
39 int ret;
40
b8f9bdc1 41 if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available())
af2c3834
SV
42 return -EPROBE_DEFER;
43
377a22d3
SV
44 node = of_parse_phandle(dev->of_node, "memory-region", 0);
45 if (!node) {
46 dev_err(dev, "no memory-region specified\n");
47 return -EINVAL;
48 }
af2c3834 49
377a22d3 50 ret = of_address_to_resource(node, 0, &r);
af2c3834
SV
51 if (ret)
52 return ret;
53
377a22d3
SV
54 mem_phys = r.start;
55 mem_size = resource_size(&r);
af2c3834 56
377a22d3
SV
57 if (mem_size < VENUS_FW_MEM_SIZE)
58 return -EINVAL;
af2c3834 59
377a22d3 60 mem_va = memremap(r.start, mem_size, MEMREMAP_WC);
af2c3834 61 if (!mem_va) {
377a22d3
SV
62 dev_err(dev, "unable to map memory region: %pa+%zx\n",
63 &r.start, mem_size);
64 return -ENOMEM;
af2c3834
SV
65 }
66
377a22d3 67 ret = request_firmware(&mdt, fwname, dev);
af2c3834 68 if (ret < 0)
377a22d3 69 goto err_unmap;
af2c3834
SV
70
71 fw_size = qcom_mdt_get_size(mdt);
72 if (fw_size < 0) {
73 ret = fw_size;
74 release_firmware(mdt);
377a22d3 75 goto err_unmap;
af2c3834
SV
76 }
77
377a22d3 78 ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
50058a9a 79 mem_size);
af2c3834
SV
80
81 release_firmware(mdt);
82
83 if (ret)
377a22d3 84 goto err_unmap;
af2c3834
SV
85
86 ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
87 if (ret)
377a22d3 88 goto err_unmap;
af2c3834 89
377a22d3
SV
90err_unmap:
91 memunmap(mem_va);
af2c3834
SV
92 return ret;
93}
94
377a22d3 95int venus_shutdown(struct device *dev)
af2c3834 96{
377a22d3 97 return qcom_scm_pas_shutdown(VENUS_PAS_ID);
af2c3834 98}