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