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 /**************************************************************************
32 * FILE NAME
33 *
34 * bm_env.c
35 *
36 *
37 * DESCRIPTION
38 *
39 * This file is Bare Metal Implementation of env layer for OpenAMP.
40 *
41 *
42 **************************************************************************/
44 #include "openamp/env.h"
45 #include "machine.h"
46 #include "machine_system.h"
48 #include <stdlib.h>
49 #include <string.h>
51 static void acquire_spin_lock(void *plock);
52 static void release_spin_lock(void *plock);
54 /* Max supprted ISR counts */
55 #define ISR_COUNT 4
56 /**
57 * Structure to keep track of registered ISR's.
58 */
59 struct isr_info {
60 int vector;
61 int priority;
62 int type;
63 void *data;
64 void (*isr)(int vector, void *data);
65 };
66 struct isr_info isr_table[ISR_COUNT];
67 int Intr_Count = 0;
68 /* Flag to show status of global interrupts. 0 for disabled and 1 for enabled. This
69 * is added to prevent recursive global interrupts enablement/disablement.
70 */
71 int Intr_Enable_Flag = 1;
73 /**
74 * env_init
75 *
76 * Initializes OS/BM environment.
77 *
78 */
79 int env_init()
80 {
81 return 0;
82 }
84 /**
85 * env_deinit
86 *
87 * Uninitializes OS/BM environment.
88 *
89 * @returns - execution status
90 */
92 int env_deinit()
93 {
94 return 0;
95 }
97 /**
98 * env_allocate_memory - implementation
99 *
100 * @param size
101 */
102 void *env_allocate_memory(unsigned int size)
103 {
104 return (malloc(size));
105 }
107 /**
108 * env_free_memory - implementation
109 *
110 * @param ptr
111 */
112 void env_free_memory(void *ptr)
113 {
114 if (ptr != NULL) {
115 free(ptr);
116 }
117 }
119 /**
120 *
121 * env_memset - implementation
122 *
123 * @param ptr
124 * @param value
125 * @param size
126 */
127 void env_memset(void *ptr, int value, unsigned long size)
128 {
129 memset(ptr, value, size);
130 }
132 /**
133 *
134 * env_memcpy - implementation
135 *
136 * @param dst
137 * @param src
138 * @param len
139 */
140 void env_memcpy(void *dst, void const *src, unsigned long len)
141 {
142 memcpy(dst, src, len);
143 }
145 /**
146 *
147 * env_strcmp - implementation
148 *
149 * @param dst
150 * @param src
151 */
153 int env_strcmp(const char *dst, const char *src)
154 {
155 return (strcmp(dst, src));
156 }
158 /**
159 *
160 * env_strncpy - implementation
161 *
162 * @param dest
163 * @param src
164 * @param len
165 */
166 void env_strncpy(char *dest, const char *src, unsigned long len)
167 {
168 strncpy(dest, src, len);
169 }
171 /**
172 *
173 * env_strncmp - implementation
174 *
175 * @param dest
176 * @param src
177 * @param len
178 */
179 int env_strncmp(char *dest, const char *src, unsigned long len)
180 {
181 return (strncmp(dest, src, len));
182 }
184 /**
185 *
186 * env_mb - implementation
187 *
188 */
189 void env_mb()
190 {
191 MEM_BARRIER();
192 }
194 /**
195 * osalr_mb - implementation
196 */
197 void env_rmb()
198 {
199 MEM_BARRIER();
200 }
202 /**
203 * env_wmb - implementation
204 */
205 void env_wmb()
206 {
207 MEM_BARRIER();
208 }
210 /**
211 * env_map_vatopa - implementation
212 *
213 * @param address
214 */
215 unsigned long env_map_vatopa(void *address)
216 {
217 return platform_vatopa(address);
218 }
220 /**
221 * env_map_patova - implementation
222 *
223 * @param address
224 */
225 void *env_map_patova(unsigned long address)
226 {
227 return platform_patova(address);
228 }
230 /**
231 * env_create_mutex
232 *
233 * Creates a mutex with the given initial count.
234 *
235 */
236 int env_create_mutex(void **lock, int count)
237 {
238 return 0;
239 }
241 /**
242 * env_delete_mutex
243 *
244 * Deletes the given lock
245 *
246 */
247 void env_delete_mutex(void *lock)
248 {
249 }
251 /**
252 * env_lock_mutex
253 *
254 * Tries to acquire the lock, if lock is not available then call to
255 * this function will suspend.
256 */
257 void env_lock_mutex(void *lock)
258 {
259 env_disable_interrupts();
260 }
262 /**
263 * env_unlock_mutex
264 *
265 * Releases the given lock.
266 */
268 void env_unlock_mutex(void *lock)
269 {
270 env_restore_interrupts();
271 }
273 /**
274 * env_create_sync_lock
275 *
276 * Creates a synchronization lock primitive. It is used
277 * when signal has to be sent from the interrupt context to main
278 * thread context.
279 */
280 int env_create_sync_lock(void **lock, int state)
281 {
282 int *slock;
284 slock = (int *)malloc(sizeof(int));
285 if (slock) {
286 *slock = state;
287 *lock = slock;
288 } else {
289 *lock = NULL;
290 return -1;
291 }
293 return 0;
294 }
296 /**
297 * env_delete_sync_lock
298 *
299 * Deletes the given lock
300 *
301 */
302 void env_delete_sync_lock(void *lock)
303 {
304 if (lock)
305 free(lock);
306 }
308 /**
309 * env_acquire_sync_lock
310 *
311 * Tries to acquire the lock, if lock is not available then call to
312 * this function waits for lock to become available.
313 */
314 void env_acquire_sync_lock(void *lock)
315 {
316 acquire_spin_lock(lock);
317 }
319 /**
320 * env_release_sync_lock
321 *
322 * Releases the given lock.
323 */
325 void env_release_sync_lock(void *lock)
326 {
327 release_spin_lock(lock);
328 }
330 /**
331 * env_sleep_msec
332 *
333 * Suspends the calling thread for given time , in msecs.
334 */
336 void env_sleep_msec(int num_msec)
337 {
339 }
341 /**
342 * env_disable_interrupts
343 *
344 * Disables system interrupts
345 *
346 */
347 void env_disable_interrupts()
348 {
349 if (Intr_Enable_Flag == 1) {
350 disable_global_interrupts();
351 Intr_Enable_Flag = 0;
352 }
353 }
355 /**
356 * env_restore_interrupts
357 *
358 * Enables system interrupts
359 *
360 */
361 void env_restore_interrupts()
362 {
363 if (Intr_Enable_Flag == 0) {
364 restore_global_interrupts();
365 Intr_Enable_Flag = 1;
366 }
367 }
369 /**
370 * env_register_isr
371 *
372 * Registers interrupt handler for the given interrupt vector.
373 *
374 * @param vector - interrupt vector number
375 * @param isr - interrupt handler
376 */
377 void env_register_isr(int vector, void *data,
378 void (*isr) (int vector, void *data))
379 {
380 env_disable_interrupts();
382 if (Intr_Count < ISR_COUNT) {
383 /* Save interrupt data */
384 isr_table[Intr_Count].vector = vector;
385 isr_table[Intr_Count].data = data;
386 isr_table[Intr_Count++].isr = isr;
387 }
389 env_restore_interrupts();
390 }
392 void env_update_isr(int vector, void *data,
393 void (*isr) (int vector, void *data))
394 {
395 int idx;
396 struct isr_info *info;
398 env_disable_interrupts();
400 for (idx = 0; idx < ISR_COUNT; idx++) {
401 info = &isr_table[idx];
402 if (info->vector == vector) {
403 info->data = data;
404 info->isr = isr;
405 break;
406 }
407 }
409 env_restore_interrupts();
410 }
412 /**
413 * env_enable_interrupt
414 *
415 * Enables the given interrupt
416 *
417 * @param vector - interrupt vector number
418 * @param priority - interrupt priority
419 * @param polarity - interrupt polarity
420 */
422 void env_enable_interrupt(unsigned int vector, unsigned int priority,
423 unsigned int polarity)
424 {
425 int idx;
427 env_disable_interrupts();
429 for (idx = 0; idx < ISR_COUNT; idx++) {
430 if (isr_table[idx].vector == vector) {
431 isr_table[idx].priority = priority;
432 isr_table[idx].type = polarity;
433 platform_interrupt_enable(vector, polarity, priority);
434 break;
435 }
436 }
438 env_restore_interrupts();
439 }
441 /**
442 * env_disable_interrupt
443 *
444 * Disables the given interrupt
445 *
446 * @param vector - interrupt vector number
447 */
449 void env_disable_interrupt(unsigned int vector)
450 {
451 platform_interrupt_disable(vector);
452 }
454 /**
455 * env_map_memory
456 *
457 * Enables memory mapping for given memory region.
458 *
459 * @param pa - physical address of memory
460 * @param va - logical address of memory
461 * @param size - memory size
462 * param flags - flags for cache/uncached and access type
463 */
465 void env_map_memory(unsigned int pa, unsigned int va, unsigned int size,
466 unsigned int flags)
467 {
468 platform_map_mem_region(va, pa, size, flags);
469 }
471 /**
472 * env_disable_cache
473 *
474 * Disables system caches.
475 *
476 */
478 void env_disable_cache()
479 {
480 platform_cache_all_flush_invalidate();
481 platform_cache_disable();
482 }
484 /**
485 *
486 * env_get_timestamp
487 *
488 * Returns a 64 bit time stamp.
489 *
490 *
491 */
492 unsigned long long env_get_timestamp(void)
493 {
495 /* TODO: Provide implementation for baremetal */
496 return 0;
497 }
499 /*========================================================= */
500 /* Util data / functions for BM */
502 void bm_env_isr(int vector)
503 {
504 int idx;
505 struct isr_info *info;
507 env_disable_interrupt(vector);
508 for (idx = 0; idx < ISR_COUNT; idx++) {
509 info = &isr_table[idx];
510 if (info->vector == vector) {
511 info->isr(info->vector, info->data);
512 env_enable_interrupt(info->vector, info->priority,
513 info->type);
514 break;
515 }
516 }
517 }
519 /**
520 *
521 * acquire_spin_lock
522 *
523 */
524 static void acquire_spin_lock(void *plock)
525 {
526 const int lockVal = 0;
527 volatile unsigned int retVal;
529 do {
530 retVal = xchg(plock, lockVal);
531 } while (retVal == lockVal);
532 }
534 /**
535 * release_spin_lock
536 */
537 static void release_spin_lock(void *plock)
538 {
539 MEM_BARRIER();
541 xchg(plock, 1);
542 }