decfab0dc25d292373a9e31bd58e2b12afe91f3f
1 /*
2 * Copyright (c) 2016 Xilinx, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * 3. Neither the name of Mentor Graphics Corporation nor the names of its
13 * contributors may be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
29 #include <string.h>
30 #include "openamp/hil.h"
31 #include "openamp/remoteproc_plat.h"
32 #include "metal/device.h"
33 #include "metal/io.h"
34 #include "metal/shmem.h"
36 /**
37 * rproc_platform_open_metal_dev
38 *
39 * Open metal device and get the I/O region
40 *
41 * @param[in] bus_name - metal device bus name
42 * @param[in] dev_name - metal device name
43 * @param[out] dev - return metal device handle
44 * @param[out] io - return metal device I/O region
45 *
46 * @return - 0 for success, non-zero for errors.
47 */
48 static int rproc_plat_open_metal_dev(char *bus_name, char *dev_name,
49 struct metal_device **dev,
50 struct metal_io_region **io)
51 {
52 int ret;
53 ret = metal_device_open(bus_name, dev_name, dev);
54 if (ret)
55 return ret;
56 *io = metal_device_io_region(*dev, 0);
57 if (!(*io)) {
58 metal_device_close(*dev);
59 *dev = 0;
60 return -1;
61 }
62 return 0;
63 }
65 int rproc_init_plat_data(void *pdata,
66 struct hil_proc *proc)
67 {
68 unsigned int type;
69 struct metal_device *dev;
70 struct metal_io_region *io;
71 int num_vrings = 0;
72 int num_rpmsg_chnls = 0;
73 int ret;
75 if (!proc || !pdata)
76 return -1;
77 memcpy(proc, pdata, sizeof(struct proc_info_hdr));
79 pdata += sizeof(struct proc_info_hdr);
80 while(1) {
81 type = *((unsigned int *)pdata);
82 if (type > PLAT_RSC_LAST) {
83 return -1;
84 } else if (type == PLAT_RSC_LAST) {
85 proc->vdev.num_vrings = num_vrings;
86 proc->num_chnls = num_rpmsg_chnls;
87 return 0;
88 } else if (type == PLAT_RSC_VRING) {
89 struct plat_vring *pvring =
90 (struct plat_vring *)pdata;
91 struct proc_vring *vring =
92 &proc->vdev.vring_info[num_vrings];
93 /* Open the vring IPI device */
94 if (pvring->ipi_dev_name) {
95 ret = rproc_plat_open_metal_dev(
96 pvring->ipi_bus_name,
97 pvring->ipi_dev_name,
98 &dev, &io);
99 if (ret)
100 return ret;
101 vring->intr_info.dev = dev;
102 vring->intr_info.io = io;
103 vring->intr_info.vect_id =
104 (uintptr_t)dev->irq_info;
105 }
106 vring->intr_info.data = pvring->ipi_dev_data;
107 /* Open the vring descriptor memory device */
108 if (pvring->vdev_name) {
109 ret = rproc_plat_open_metal_dev(
110 pvring->vdev_bus_name,
111 pvring->vdev_name,
112 &dev, &io);
113 if (ret)
114 return ret;
115 vring->dev = dev;
116 vring->io = io;
117 }
118 num_vrings++;
119 pdata += sizeof(struct plat_vring);
120 } else if (type == PLAT_RSC_SHM) {
121 struct plat_shm *pshm =
122 (struct plat_shm *)pdata;
123 /* Open the shared memory device */
124 ret = metal_shmem_open(pshm->shm_name,
125 pshm->size,
126 &io);
127 if (ret)
128 return ret;
129 proc->sh_buff.io = io;
130 if (io->size != (size_t)(-1)) {
131 metal_io_mem_map(
132 metal_io_virt_to_phys(io, io->virt),
133 io, io->size);
134 proc->sh_buff.start_addr = io->virt;
135 proc->sh_buff.size = io->size;
136 }
137 pdata += sizeof(struct plat_shm);
138 } else if (type == PLAT_RSC_RPMSG_CHANNEL) {
139 struct plat_rpmsg_chnl *pchl =
140 (struct plat_rpmsg_chnl *)pdata;
141 strcpy(proc->chnls[num_rpmsg_chnls].name, pchl->name);
142 num_rpmsg_chnls++;
143 pdata += sizeof(struct plat_rpmsg_chnl);
144 }
145 }
147 }
149 void rproc_close_plat(struct hil_proc *proc)
150 {
151 if (!proc)
152 return;
153 int i;
154 int num_vrings = proc->vdev.num_vrings;
155 struct metal_device *dev;
156 struct proc_vring *vring;
158 /* Close the vrings devices */
159 for (i = 0; i < num_vrings; i++) {
160 vring = &proc->vdev.vring_info[i];
161 dev = vring->dev;
162 if (dev) {
163 metal_device_close(dev);
164 vring->dev = NULL;
165 }
166 dev = vring->intr_info.dev;
167 if (dev) {
168 metal_device_close(dev);
169 vring->intr_info.dev = NULL;
170 }
171 }
172 }