]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/open-amp.git/blob - lib/remoteproc/remoteproc.c
remoteproc: remove ipi deinit function
[processor-sdk/open-amp.git] / lib / remoteproc / remoteproc.c
1 /*
2  * Copyright (c) 2014, Mentor Graphics Corporation
3  * All rights reserved.
4  * Copyright (c) 2015 Xilinx, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  *    this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  * 3. Neither the name of Mentor Graphics Corporation nor the names of its
15  *    contributors may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
31 #include <string.h>
32 #include "openamp/remoteproc.h"
33 #include "openamp/remoteproc_loader.h"
34 #include "openamp/rsc_table_parser.h"
35 #include "openamp/env.h"
36 #include "openamp/hil.h"
37 #include "metal/sys.h"
39 /**
40  * remoteproc_resource_init
41  *
42  * Initializes resources for remoteproc remote configuration. Only
43  * remoteproc remote applications are allowed to call this function.
44  *
45  * @param rsc_info          - pointer to resource table info control
46  *                                                        block
47  * @param pdata             - platform data for remote processor
48  * @param channel_created   - callback function for channel creation
49  * @param channel_destroyed - callback function for channel deletion
50  * @param default_cb        - default callback for channel I/O
51  * @param rproc_handle      - pointer to new remoteproc instance
52  *
53  * @param returns - status of function execution
54  *
55  */
56 int remoteproc_resource_init(struct rsc_table_info *rsc_info,
57                              void *pdata,
58                              rpmsg_chnl_cb_t channel_created,
59                              rpmsg_chnl_cb_t channel_destroyed,
60                              rpmsg_rx_cb_t default_cb,
61                              struct remote_proc **rproc_handle)
62 {
64         struct remote_proc *rproc;
65         int status;
67         if (!rsc_info) {
68                 return RPROC_ERR_PARAM;
69         }
71         rproc = env_allocate_memory(sizeof(struct remote_proc));
72         if (rproc) {
73                 memset(rproc, 0x00, sizeof(struct remote_proc));
74                 /* There can be only one master for remote configuration so use the
75                  * rsvd cpu id for creating hil proc */
76                 rproc->proc = hil_create_proc(pdata, HIL_RSVD_CPU_ID);
77                 if (rproc->proc) {
78                         /* Parse resource table */
79                         status =
80                             handle_rsc_table(rproc, rsc_info->rsc_tab,
81                                              rsc_info->size);
82                         if (status == RPROC_SUCCESS) {
83                                 /* Initialize RPMSG "messaging" component */
84                                 *rproc_handle = rproc;
85                                 status =
86                                     rpmsg_init(NULL, rproc->proc->cpu_id,
87                                                &rproc->rdev, channel_created,
88                                                channel_destroyed, default_cb,
89                                                RPMSG_MASTER);
90                         } else {
91                                 status = RPROC_ERR_NO_RSC_TABLE;
92                         }
93                 } else {
94                         status = RPROC_ERR_CPU_ID;
95                 }
96         } else {
97                 status = RPROC_ERR_NO_MEM;
98         }
100         /* Cleanup in case of error */
101         if (status != RPROC_SUCCESS) {
102                 *rproc_handle = 0;
103                 (void)remoteproc_resource_deinit(rproc);
104                 return status;
105         }
106         return status;
109 /**
110  * remoteproc_resource_deinit
111  *
112  * Uninitializes resources for remoteproc "remote" configuration.
113  *
114  * @param rproc - pointer to rproc instance
115  *
116  * @param returns - status of function execution
117  *
118  */
120 int remoteproc_resource_deinit(struct remote_proc *rproc)
122         if (rproc) {
123                 if (rproc->rdev) {
124                         rpmsg_deinit(rproc->rdev);
125                 }
126                 if (rproc->proc) {
127                         hil_delete_proc(rproc->proc);
128                 }
130                 env_free_memory(rproc);
131         }
133         metal_finish();
135         /*
136          * Flush and Invalidate the caches - When the application is built with
137          * Xilinx Standalone BSP, caches are invalidated as part of boot process.
138          * Even if the master boots firmware multiple times without hard reset on
139          * same core, caches are flushed and invalidated at the end of
140          * remoteproc_resource_deinit for this run and caches would be again
141          * invalidated before starting the main thread of the application on next
142          * run to avoid any cache inconsistencies.
143          */
144          env_flush_invalidate_all_caches();
147         return RPROC_SUCCESS;
150 /**
151  * remoteproc_init
152  *
153  * Initializes resources for remoteproc master configuration. Only
154  * remoteproc master applications are allowed to call this function.
155  *
156  * @param fw_name           - name of frimware
157  * @param pdata             - platform data for remote processor
158  * @param channel_created   - callback function for channel creation
159  * @param channel_destroyed - callback function for channel deletion
160  * @param default_cb        - default callback for channel I/O
161  * @param rproc_handle      - pointer to new remoteproc instance
162  *
163  * @param returns - status of function execution
164  *
165  */
166 int remoteproc_init(char *fw_name, void *pdata,
167                     rpmsg_chnl_cb_t channel_created,
168                     rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb,
169                     struct remote_proc **rproc_handle)
172         struct remote_proc *rproc;
173         struct resource_table *rsc_table;
174         unsigned int fw_addr, fw_size, rsc_size;
175         int status;
177         if (!fw_name) {
178                 return RPROC_ERR_PARAM;
179         }
181         rproc = env_allocate_memory(sizeof(struct remote_proc));
182         if (rproc) {
183                 memset((void *)rproc, 0x00, sizeof(struct remote_proc));
184                 /* Create proc instance */
185                 rproc->proc = hil_create_proc(pdata, HIL_RSVD_CPU_ID);
186                 if (rproc->proc) {
187                         /* Retrieve firmware attributes */
188                         status =
189                             hil_get_firmware(fw_name, &fw_addr,
190                                              &fw_size);
191                         if (!status) {
192                                 /* Initialize ELF loader - currently only ELF format is supported */
193                                 rproc->loader =
194                                     remoteproc_loader_init(ELF_LOADER);
195                                 if (rproc->loader) {
196                                         /* Attach the given firmware with the ELF parser/loader */
197                                         status =
198                                             remoteproc_loader_attach_firmware
199                                             (rproc->loader,
200                                              (void *)fw_addr);
201                                 } else {
202                                         status = RPROC_ERR_LOADER;
203                                 }
204                         }
205                 } else {
206                         status = RPROC_ERR_NO_MEM;
207                 }
208         } else {
209                 status = RPROC_ERR_NO_MEM;
210         }
212         if (!status) {
213                 rproc->role = RPROC_MASTER;
215                 /* Get resource table from firmware */
216                 rsc_table =
217                     remoteproc_loader_retrieve_resource_section(rproc->loader,
218                                                                 &rsc_size);
219                 if (rsc_table) {
220                         /* Parse resource table */
221                         status = handle_rsc_table(rproc, rsc_table, rsc_size);
222                 } else {
223                         status = RPROC_ERR_NO_RSC_TABLE;
224                 }
225         }
227         /* Cleanup in case of error */
228         if (status != RPROC_SUCCESS) {
229                 (void)remoteproc_deinit(rproc);
230                 return status;
231         }
233         rproc->channel_created = channel_created;
234         rproc->channel_destroyed = channel_destroyed;
235         rproc->default_cb = default_cb;
237         *rproc_handle = rproc;
239         return status;
242 /**
243  * remoteproc_deinit
244  *
245  * Uninitializes resources for remoteproc "master" configuration.
246  *
247  * @param rproc - pointer to remote proc instance
248  *
249  * @param returns - status of function execution
250  *
251  */
252 int remoteproc_deinit(struct remote_proc *rproc)
255         if (rproc) {
256                 if (rproc->loader) {
257                         (void)remoteproc_loader_delete(rproc->loader);
258                         rproc->loader = RPROC_NULL;
259                 }
260                 if (rproc->proc) {
261                         hil_delete_proc(rproc->proc);
262                         rproc->proc = RPROC_NULL;
263                 }
264                 env_free_memory(rproc);
265         }
267         metal_finish();
269         return RPROC_SUCCESS;
272 /**
273  * remoteproc_boot
274  *
275  * This function loads the image on the remote processor and starts
276  * its execution from image load address.
277  *
278  * @param rproc - pointer to remoteproc instance to boot
279  *
280  * @param returns - status of function execution
281  */
282 int remoteproc_boot(struct remote_proc *rproc)
285         void *load_addr;
286         int status;
288         if (!rproc) {
289                 return RPROC_ERR_PARAM;
290         }
292         /* Stop the remote CPU */
293         hil_shutdown_cpu(rproc->proc);
295         /* Load the firmware */
296         status = remoteproc_loader_load_remote_firmware(rproc->loader);
297         if (status == RPROC_SUCCESS) {
298                 load_addr = remoteproc_get_load_address(rproc->loader);
299                 if (load_addr != RPROC_ERR_PTR) {
300                         /* Start the remote cpu */
301                         status = hil_boot_cpu(rproc->proc,
302                                               (unsigned int)load_addr);
303                         if (status == RPROC_SUCCESS) {
304                                 /* Wait for remote side to come up. This delay is arbitrary and may
305                                  * need adjustment for different configuration of remote systems */
306                                 env_sleep_msec(RPROC_BOOT_DELAY);
308                                 /* Initialize RPMSG "messaging" component */
310                                 /* It is a work-around to work with remote Linux context. 
311                                    Since the upstream Linux rpmsg implementation always 
312                                    assumes itself to be an rpmsg master, we initialize
313                                    the remote device as an rpmsg master for remote Linux
314                                    configuration only. */
315 #if defined (OPENAMP_REMOTE_LINUX_ENABLE)
316                                 status =
317                                     rpmsg_init(NULL, rproc->proc->cpu_id,
318                                                &rproc->rdev,
319                                                rproc->channel_created,
320                                                rproc->channel_destroyed,
321                                                rproc->default_cb, RPMSG_MASTER);
322 #else
323                                 status =
324                                     rpmsg_init(NULL, rproc->proc->cpu_id,
325                                                &rproc->rdev,
326                                                rproc->channel_created,
327                                                rproc->channel_destroyed,
328                                                rproc->default_cb, RPMSG_REMOTE);
329 #endif
330                         }
331                 } else {
332                         status = RPROC_ERR_LOADER;
333                 }
334         } else {
335                 status = RPROC_ERR_LOADER;
336         }
338         return status;
341 /**
342  * remoteproc_shutdown
343  *
344  * This function shutdowns the remote execution context
345  *
346  * @param rproc - pointer to remote proc instance to shutdown
347  *
348  * @param returns - status of function execution
349  */
350 int remoteproc_shutdown(struct remote_proc *rproc)
353         if (rproc) {
354                 if (rproc->rdev) {
355                         rpmsg_deinit(rproc->rdev);
356                         rproc->rdev = RPROC_NULL;
357                 }
358                 if (rproc->proc) {
359                         hil_shutdown_cpu(rproc->proc);
360                 }
361         }
363         return RPROC_SUCCESS;