]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/media/platform/qcom/venus/firmware.c
Merge tag 'rdma-rc-2017-07-26' of git://git.kernel.org/pub/scm/linux/kernel/git/leon...
[linux.git] / drivers / media / platform / qcom / venus / firmware.c
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
15 #include <linux/dma-mapping.h>
16 #include <linux/firmware.h>
17 #include <linux/kernel.h>
18 #include <linux/of.h>
19 #include <linux/of_reserved_mem.h>
20 #include <linux/slab.h>
21 #include <linux/qcom_scm.h>
22 #include <linux/soc/qcom/mdt_loader.h>
23
24 #include "firmware.h"
25
26 #define VENUS_PAS_ID                    9
27 #define VENUS_FW_MEM_SIZE               SZ_8M
28
29 static void device_release_dummy(struct device *dev)
30 {
31         of_reserved_mem_device_release(dev);
32 }
33
34 int venus_boot(struct device *parent, struct device *fw_dev, const char *fwname)
35 {
36         const struct firmware *mdt;
37         phys_addr_t mem_phys;
38         ssize_t fw_size;
39         size_t mem_size;
40         void *mem_va;
41         int ret;
42
43         if (!qcom_scm_is_available())
44                 return -EPROBE_DEFER;
45
46         fw_dev->parent = parent;
47         fw_dev->release = device_release_dummy;
48
49         ret = dev_set_name(fw_dev, "%s:%s", dev_name(parent), "firmware");
50         if (ret)
51                 return ret;
52
53         ret = device_register(fw_dev);
54         if (ret < 0)
55                 return ret;
56
57         ret = of_reserved_mem_device_init_by_idx(fw_dev, parent->of_node, 0);
58         if (ret)
59                 goto err_unreg_device;
60
61         mem_size = VENUS_FW_MEM_SIZE;
62
63         mem_va = dmam_alloc_coherent(fw_dev, mem_size, &mem_phys, GFP_KERNEL);
64         if (!mem_va) {
65                 ret = -ENOMEM;
66                 goto err_unreg_device;
67         }
68
69         ret = request_firmware(&mdt, fwname, fw_dev);
70         if (ret < 0)
71                 goto err_unreg_device;
72
73         fw_size = qcom_mdt_get_size(mdt);
74         if (fw_size < 0) {
75                 ret = fw_size;
76                 release_firmware(mdt);
77                 goto err_unreg_device;
78         }
79
80         ret = qcom_mdt_load(fw_dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
81                             mem_size);
82
83         release_firmware(mdt);
84
85         if (ret)
86                 goto err_unreg_device;
87
88         ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
89         if (ret)
90                 goto err_unreg_device;
91
92         return 0;
93
94 err_unreg_device:
95         device_unregister(fw_dev);
96         return ret;
97 }
98
99 int venus_shutdown(struct device *fw_dev)
100 {
101         int ret;
102
103         ret = qcom_scm_pas_shutdown(VENUS_PAS_ID);
104         device_unregister(fw_dev);
105         memset(fw_dev, 0, sizeof(*fw_dev));
106
107         return ret;
108 }