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 * 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 char *name;
64 int shared;
65 void *data;
66 void (*isr)(int vector, void *data);
67 };
68 struct isr_info isr_table[ISR_COUNT];
69 static int intr_count = 0;
70 /* Flag to show status of global interrupts. 0 for disabled and 1 for enabled. This
71 * is added to prevent recursive global interrupts enablement/disablement.
72 */
73 static int intr_enable_flag = 1;
75 /**
76 * env_allocate_memory - implementation
77 *
78 * @param size
79 */
80 void *env_allocate_memory(unsigned int size)
81 {
82 return (malloc(size));
83 }
85 /**
86 * env_free_memory - implementation
87 *
88 * @param ptr
89 */
90 void env_free_memory(void *ptr)
91 {
92 if (ptr != NULL) {
93 free(ptr);
94 }
95 }
97 /**
98 * env_map_vatopa - implementation
99 *
100 * @param address
101 */
102 unsigned long env_map_vatopa(void *address)
103 {
104 return platform_vatopa(address);
105 }
107 /**
108 * env_map_patova - implementation
109 *
110 * @param address
111 */
112 void *env_map_patova(unsigned long address)
113 {
114 return platform_patova(address);
115 }
117 /**
118 * env_create_sync_lock
119 *
120 * Creates a synchronization lock primitive. It is used
121 * when signal has to be sent from the interrupt context to main
122 * thread context.
123 */
124 int env_create_sync_lock(void **lock, int state)
125 {
126 int *slock;
128 slock = (int *)malloc(sizeof(int));
129 if (slock) {
130 *slock = state;
131 *lock = slock;
132 } else {
133 *lock = NULL;
134 return -1;
135 }
137 return 0;
138 }
140 /**
141 * env_delete_sync_lock
142 *
143 * Deletes the given lock
144 *
145 */
146 void env_delete_sync_lock(void *lock)
147 {
148 if (lock)
149 free(lock);
150 }
152 /**
153 * env_acquire_sync_lock
154 *
155 * Tries to acquire the lock, if lock is not available then call to
156 * this function waits for lock to become available.
157 */
158 void env_acquire_sync_lock(void *lock)
159 {
160 acquire_spin_lock(lock);
161 }
163 /**
164 * env_release_sync_lock
165 *
166 * Releases the given lock.
167 */
169 void env_release_sync_lock(void *lock)
170 {
171 release_spin_lock(lock);
172 }
174 /**
175 * env_sleep_msec
176 *
177 * Suspends the calling thread for given time , in msecs.
178 */
180 void env_sleep_msec(int num_msec)
181 {
182 (void)num_msec; /* TODO: implement sleep_msec*/
184 }
186 /**
187 * env_disable_interrupts
188 *
189 * Disables system interrupts
190 *
191 */
192 void env_disable_interrupts()
193 {
194 if (intr_enable_flag == 1) {
195 disable_global_interrupts();
196 intr_enable_flag = 0;
197 }
198 }
200 /**
201 * env_restore_interrupts
202 *
203 * Enables system interrupts
204 *
205 */
206 void env_restore_interrupts()
207 {
208 if (intr_enable_flag == 0) {
209 restore_global_interrupts();
210 intr_enable_flag = 1;
211 }
212 }
214 /**
215 * env_register_isr_shared
216 *
217 * Registers interrupt handler for the given interrupt vector.
218 *
219 * @param vector - interrupt vector number
220 * @param isr - interrupt handler
221 * @param name - interrupt name
222 * @param shared - if the interrupt is shared or not
223 */
224 void env_register_isr_shared(int vector, void *data,
225 void (*isr) (int vector, void *data),
226 char *name,
227 int shared)
228 {
229 env_disable_interrupts();
231 if (intr_count < ISR_COUNT) {
232 /* Save interrupt data */
233 isr_table[intr_count].vector = vector;
234 isr_table[intr_count].data = data;
235 isr_table[intr_count].name = name;
236 isr_table[intr_count].shared = shared;
237 isr_table[intr_count++].isr = isr;
238 }
240 env_restore_interrupts();
241 }
242 /**
243 * env_register_isr
244 *
245 * Registers interrupt handler for the given interrupt vector.
246 *
247 * @param vector - interrupt vector number
248 * @param isr - interrupt handler
249 */
250 void env_register_isr(int vector, void *data,
251 void (*isr) (int vector, void *data))
252 {
253 env_register_isr_shared(vector, data, isr, 0, 0);
254 }
256 void env_update_isr(int vector, void *data,
257 void (*isr) (int vector, void *data),
258 char *name,
259 int shared)
260 {
261 int idx;
262 struct isr_info *info;
264 env_disable_interrupts();
266 for (idx = 0; idx < ISR_COUNT; idx++) {
267 info = &isr_table[idx];
268 if (info->vector == vector) {
269 if (name && strcmp(info->name, name)) {
270 continue;
271 }
272 info->data = data;
273 info->isr = isr;
274 info->shared = shared;
275 break;
276 }
277 }
279 env_restore_interrupts();
280 }
282 /**
283 * env_enable_interrupt
284 *
285 * Enables the given interrupt
286 *
287 * @param vector - interrupt vector number
288 * @param priority - interrupt priority
289 * @param polarity - interrupt polarity
290 */
292 void env_enable_interrupt(unsigned int vector, unsigned int priority,
293 unsigned int polarity)
294 {
295 int idx;
297 env_disable_interrupts();
299 for (idx = 0; idx < ISR_COUNT; idx++) {
300 if (isr_table[idx].vector == (int)vector) {
301 isr_table[idx].priority = priority;
302 isr_table[idx].type = polarity;
303 platform_interrupt_enable(vector, polarity, priority);
304 break;
305 }
306 }
308 env_restore_interrupts();
309 }
311 /**
312 * env_disable_interrupt
313 *
314 * Disables the given interrupt
315 *
316 * @param vector - interrupt vector number
317 */
319 void env_disable_interrupt(unsigned int vector)
320 {
321 platform_interrupt_disable(vector);
322 }
324 /**
325 * env_map_memory
326 *
327 * Enables memory mapping for given memory region.
328 *
329 * @param pa - physical address of memory
330 * @param va - logical address of memory
331 * @param size - memory size
332 * param flags - flags for cache/uncached and access type
333 */
335 void env_map_memory(unsigned int pa, unsigned int va, unsigned int size,
336 unsigned int flags)
337 {
338 platform_map_mem_region(va, pa, size, flags);
339 }
341 /**
342 * env_disable_cache
343 *
344 * Disables system caches.
345 *
346 */
348 void env_disable_cache(void)
349 {
350 platform_cache_all_flush_invalidate();
351 platform_cache_disable();
352 }
354 /**
355 * env_flush_invalidate_all_caches
356 *
357 * Flush and Invalidate all caches.
358 *
359 */
361 void env_flush_invalidate_all_caches(void)
362 {
363 platform_cache_all_flush_invalidate();
364 }
367 /**
368 *
369 * env_get_timestamp
370 *
371 * Returns a 64 bit time stamp.
372 *
373 *
374 */
375 unsigned long long env_get_timestamp(void)
376 {
378 /* TODO: Provide implementation for baremetal */
379 return 0;
380 }
382 /*========================================================= */
383 /* Util data / functions for BM */
385 void bm_env_isr(int vector)
386 {
387 int idx;
388 struct isr_info *info;
390 env_disable_interrupt(vector);
391 for (idx = 0; idx < ISR_COUNT; idx++) {
392 info = &isr_table[idx];
393 if (info->vector == vector) {
394 info->isr(info->vector, info->data);
395 env_enable_interrupt(info->vector, info->priority,
396 info->type);
397 if (!info->shared)
398 break;
399 }
400 }
401 }
403 /**
404 *
405 * acquire_spin_lock
406 *
407 */
408 static void acquire_spin_lock(void *plock)
409 {
410 const unsigned int lockVal = 0;
411 volatile unsigned int retVal;
413 do {
414 retVal = xchg(plock, lockVal);
415 } while (retVal == lockVal);
416 }
418 /**
419 * release_spin_lock
420 */
421 static void release_spin_lock(void *plock)
422 {
423 MEM_BARRIER();
425 xchg(plock, 1);
426 }