建立工程,成功创建两个虚拟串口
This commit is contained in:
3
source/OpenAMP/libmetal/lib/system/CMakeLists.txt
Normal file
3
source/OpenAMP/libmetal/lib/system/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
add_subdirectory (${PROJECT_SYSTEM})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
24
source/OpenAMP/libmetal/lib/system/freertos/CMakeLists.txt
Normal file
24
source/OpenAMP/libmetal/lib/system/freertos/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
collect (PROJECT_LIB_HEADERS alloc.h)
|
||||
collect (PROJECT_LIB_HEADERS assert.h)
|
||||
collect (PROJECT_LIB_HEADERS cache.h)
|
||||
collect (PROJECT_LIB_HEADERS condition.h)
|
||||
collect (PROJECT_LIB_HEADERS io.h)
|
||||
collect (PROJECT_LIB_HEADERS irq.h)
|
||||
collect (PROJECT_LIB_HEADERS log.h)
|
||||
collect (PROJECT_LIB_HEADERS mutex.h)
|
||||
collect (PROJECT_LIB_HEADERS sleep.h)
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES condition.c)
|
||||
collect (PROJECT_LIB_SOURCES device.c)
|
||||
collect (PROJECT_LIB_SOURCES init.c)
|
||||
collect (PROJECT_LIB_SOURCES io.c)
|
||||
collect (PROJECT_LIB_SOURCES irq.c)
|
||||
collect (PROJECT_LIB_SOURCES shmem.c)
|
||||
collect (PROJECT_LIB_SOURCES time.c)
|
||||
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
add_subdirectory(${PROJECT_MACHINE})
|
||||
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
39
source/OpenAMP/libmetal/lib/system/freertos/alloc.h
Normal file
39
source/OpenAMP/libmetal/lib/system/freertos/alloc.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/alloc.c
|
||||
* @brief FreeRTOS libmetal memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/freertos/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_ALLOC__H__
|
||||
#define __METAL_FREERTOS_ALLOC__H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (pvPortMalloc(size));
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
vPortFree(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_ALLOC__H__ */
|
27
source/OpenAMP/libmetal/lib/system/freertos/assert.h
Normal file
27
source/OpenAMP/libmetal/lib/system/freertos/assert.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief FreeRTOS assertion support.
|
||||
*/
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/freertos/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_ASSERT__H__
|
||||
#define __METAL_FREERTOS_ASSERT__H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for FreeRTOS applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) assert(cond)
|
||||
|
||||
#endif /* __METAL_FREERTOS_ASSERT__H__ */
|
||||
|
40
source/OpenAMP/libmetal/lib/system/freertos/cache.h
Normal file
40
source/OpenAMP/libmetal/lib/system/freertos/cache.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/cache.h
|
||||
* @brief FreeRTOS cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/freertos/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_CACHE__H__
|
||||
#define __METAL_FREERTOS_CACHE__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void metal_machine_cache_flush(void *addr, unsigned int len);
|
||||
extern void metal_machine_cache_invalidate(void *addr, unsigned int len);
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_flush(addr, len);
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_invalidate(addr, len);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_CACHE__H__ */
|
21
source/OpenAMP/libmetal/lib/system/freertos/condition.c
Normal file
21
source/OpenAMP/libmetal/lib/system/freertos/condition.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.c
|
||||
* @brief Generic libmetal condition variable handling.
|
||||
*/
|
||||
|
||||
#include <metal/condition.h>
|
||||
|
||||
int metal_condition_wait(struct metal_condition *cv,
|
||||
metal_mutex_t *m)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
(void)m;
|
||||
return 0;
|
||||
}
|
64
source/OpenAMP/libmetal/lib/system/freertos/condition.h
Normal file
64
source/OpenAMP/libmetal/lib/system/freertos/condition.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.h
|
||||
* @brief Generic condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/freertos/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_CONDITION__H__
|
||||
#define __METAL_FREERTOS_CONDITION__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int v; /**< condition variable value. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_CONDITION__H__ */
|
31
source/OpenAMP/libmetal/lib/system/freertos/device.c
Normal file
31
source/OpenAMP/libmetal/lib/system/freertos/device.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/device.c
|
||||
* @brief FreeRTOS device operations.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_generic_dev_sys_open(struct metal_device *dev)
|
||||
{
|
||||
struct metal_io_region *io;
|
||||
unsigned i;
|
||||
|
||||
/* map I/O memory regions */
|
||||
for (i = 0; i < dev->num_regions; i++) {
|
||||
io = &dev->regions[i];
|
||||
if (!io->size)
|
||||
break;
|
||||
metal_sys_io_mem_map(io);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
28
source/OpenAMP/libmetal/lib/system/freertos/init.c
Normal file
28
source/OpenAMP/libmetal/lib/system/freertos/init.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/init.c
|
||||
* @brief FreeRTOS libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/device.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
metal_unused(params);
|
||||
metal_bus_register(&metal_generic_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
metal_bus_unregister(&metal_generic_bus);
|
||||
}
|
31
source/OpenAMP/libmetal/lib/system/freertos/io.c
Normal file
31
source/OpenAMP/libmetal/lib/system/freertos/io.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/io.c
|
||||
* @brief FreeRTOS libmetal io operations
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io)
|
||||
{
|
||||
unsigned long p;
|
||||
size_t psize;
|
||||
void *va;
|
||||
|
||||
va = io->virt;
|
||||
psize = io->size;
|
||||
if (psize) {
|
||||
if (psize >> io->page_shift)
|
||||
psize = (size_t)1 << io->page_shift;
|
||||
for (p = 0; p <= (io->size >> io->page_shift); p++) {
|
||||
metal_machine_io_mem_map(va, io->physmap[p],
|
||||
psize, io->mem_flags);
|
||||
va += psize;
|
||||
}
|
||||
}
|
||||
}
|
44
source/OpenAMP/libmetal/lib/system/freertos/io.h
Normal file
44
source/OpenAMP/libmetal/lib/system/freertos/io.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/io.h
|
||||
* @brief FreeRTOS specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/freertos/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREEROTS_IO__H__
|
||||
#define __METAL_FREEROTS_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief memory mapping for an I/O region
|
||||
*/
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io);
|
||||
|
||||
/**
|
||||
* @brief memory mapping
|
||||
*/
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREEROTS_IO__H__ */
|
279
source/OpenAMP/libmetal/lib/system/freertos/irq.c
Normal file
279
source/OpenAMP/libmetal/lib/system/freertos/irq.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/irq.c
|
||||
* @brief FreeRTOS libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <metal/irq.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/alloc.h>
|
||||
|
||||
/** IRQ handlers descriptor structure */
|
||||
struct metal_irq_hddesc {
|
||||
metal_irq_handler hd; /**< irq handler */
|
||||
void *drv_id; /**< id to identify the driver
|
||||
of the irq handler */
|
||||
struct metal_device *dev; /**< device identifier */
|
||||
struct metal_list node; /**< node on irq handlers list */
|
||||
};
|
||||
|
||||
/** IRQ descriptor structure */
|
||||
struct metal_irq_desc {
|
||||
int irq; /**< interrupt number */
|
||||
struct metal_list hdls; /**< interrupt handlers */
|
||||
struct metal_list node; /**< node on irqs list */
|
||||
};
|
||||
|
||||
/** IRQ state structure */
|
||||
struct metal_irqs_state {
|
||||
struct metal_list irqs; /**< interrupt descriptors */
|
||||
metal_mutex_t irq_lock; /**< access lock */
|
||||
};
|
||||
|
||||
static struct metal_irqs_state _irqs = {
|
||||
.irqs = METAL_INIT_LIST(_irqs.irqs),
|
||||
.irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock),
|
||||
};
|
||||
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p = NULL;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
struct metal_list *node;
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((drv_id == NULL) || (hd == NULL)) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node;
|
||||
|
||||
/* Check if drv_id already exist */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
/* if drv_id already exist reject */
|
||||
if ((hdl_p->drv_id == drv_id) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d already registered."
|
||||
"Will not register again.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* irq found and drv_id not used, get out of metal_list_for_each */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Either need to add handler to an existing list or to a new one */
|
||||
hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc));
|
||||
if (hdl_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d cannot allocate mem for drv_id %d.\n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hdl_p->hd = hd;
|
||||
hdl_p->drv_id = drv_id;
|
||||
hdl_p->dev = dev;
|
||||
|
||||
/* interrupt already registered, add handler to existing list*/
|
||||
if ((irq_p != NULL) && (irq_p->irq == irq)) {
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interrupt was not already registered, add */
|
||||
irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc));
|
||||
if (irq_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
irq_p->irq = irq;
|
||||
metal_list_init(&irq_p->hdls);
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&_irqs.irqs, &irq_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for metal_irq_unregister() */
|
||||
static void metal_irq_delete_node(struct metal_list *node, void *p_to_free)
|
||||
{
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
irq_flags_save=metal_irq_save_disable();
|
||||
metal_list_del(node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
metal_free_memory(p_to_free);
|
||||
}
|
||||
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p;
|
||||
struct metal_list *node;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node, *h_prenode;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
unsigned int delete_count = 0;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n",
|
||||
__func__, irq);
|
||||
|
||||
/* Search through handlers */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
if (((hd == NULL) || (hdl_p->hd == hd)) &&
|
||||
((drv_id == NULL) || (hdl_p->drv_id == drv_id)) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: unregister hd=%p drv_id=%p dev=%p\n",
|
||||
__func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev);
|
||||
h_prenode = h_node->prev;
|
||||
metal_irq_delete_node(h_node, hdl_p);
|
||||
delete_count++;
|
||||
h_node = h_prenode;
|
||||
}
|
||||
}
|
||||
|
||||
/* we did not find any handler to delete */
|
||||
if (!delete_count) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n",
|
||||
__func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
|
||||
/* if interrupt handlers list is empty, unregister interrupt */
|
||||
if (metal_list_is_empty(&irq_p->hdls)) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: handlers list empty, unregister interrupt\n",
|
||||
__func__);
|
||||
metal_irq_delete_node(node, irq_p);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
unsigned int metal_irq_save_disable(void)
|
||||
{
|
||||
return sys_irq_save_disable();
|
||||
}
|
||||
|
||||
void metal_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
sys_irq_restore_enable(flags);
|
||||
}
|
||||
|
||||
void metal_irq_enable(unsigned int vector)
|
||||
{
|
||||
sys_irq_enable(vector);
|
||||
}
|
||||
|
||||
void metal_irq_disable(unsigned int vector)
|
||||
{
|
||||
sys_irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default handler
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_irq_desc *irq_p;
|
||||
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if ((unsigned int)irq_p->irq == vector) {
|
||||
struct metal_list *h_node;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
(hdl_p->hd)(vector, hdl_p->drv_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
source/OpenAMP/libmetal/lib/system/freertos/irq.h
Normal file
34
source/OpenAMP/libmetal/lib/system/freertos/irq.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/irq.c
|
||||
* @brief FreeRTOS libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/freertos/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_IRQ__H__
|
||||
#define __METAL_FREERTOS_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief default interrupt handler
|
||||
* @param[in] vector interrupt vector
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_IRQ__H__ */
|
52
source/OpenAMP/libmetal/lib/system/freertos/log.h
Normal file
52
source/OpenAMP/libmetal/lib/system/freertos/log.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Linaro nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/log.h
|
||||
* @brief FreeRTOS libmetal log handler definition.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#error "Include metal/log.h instead of metal/freertos/log.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_LOG__H__
|
||||
#define __METAL_FREERTOS_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_LOG__H__ */
|
77
source/OpenAMP/libmetal/lib/system/freertos/mutex.h
Normal file
77
source/OpenAMP/libmetal/lib/system/freertos/mutex.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/mutex.h
|
||||
* @brief FreeRTOS mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#error "Include metal/mutex.h instead of metal/freertos/mutex.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_MUTEX__H__
|
||||
#define __METAL_FREERTOS_MUTEX__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
atomic_int v;
|
||||
} metal_mutex_t;
|
||||
|
||||
/*
|
||||
* METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) }
|
||||
/*
|
||||
* METAL_MUTEX_DEFINE - used for defining and initializing a global or
|
||||
* static singleton mutex
|
||||
*/
|
||||
#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
|
||||
|
||||
static inline void __metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_store(&mutex->v, 0);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
return 1 - atomic_flag_test_and_set(&mutex->v);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
while (atomic_flag_test_and_set(&mutex->v)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_flag_clear(&mutex->v);
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return atomic_load(&mutex->v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_MUTEX__H__ */
|
18
source/OpenAMP/libmetal/lib/system/freertos/shmem.c
Normal file
18
source/OpenAMP/libmetal/lib/system/freertos/shmem.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/shmem.c
|
||||
* @brief FreeRTOS libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <metal/shmem.h>
|
||||
|
||||
int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **io)
|
||||
{
|
||||
return metal_shmem_open_generic(name, size, io);
|
||||
}
|
39
source/OpenAMP/libmetal/lib/system/freertos/sleep.h
Normal file
39
source/OpenAMP/libmetal/lib/system/freertos/sleep.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/sleep.h
|
||||
* @brief FreeRTOS sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#error "Include metal/sleep.h instead of metal/freertos/sleep.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_SLEEP__H__
|
||||
#define __METAL_FREERTOS_SLEEP__H__
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
const TickType_t xDelay = usec / portTICK_PERIOD_MS;
|
||||
vTaskDelay(xDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_SLEEP__H__ */
|
54
source/OpenAMP/libmetal/lib/system/freertos/sys.h
Normal file
54
source/OpenAMP/libmetal/lib/system/freertos/sys.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/sys.h
|
||||
* @brief FreeRTOS system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#define __METAL_FREERTOS_SYS__H__
|
||||
|
||||
#include "./@PROJECT_MACHINE@/sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef METAL_MAX_DEVICE_REGIONS
|
||||
#define METAL_MAX_DEVICE_REGIONS 1
|
||||
#endif
|
||||
|
||||
/** Structure for FreeRTOS libmetal runtime state. */
|
||||
struct metal_state {
|
||||
|
||||
/** Common (system independent) data. */
|
||||
struct metal_common_state common;
|
||||
};
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief restore interrupts to state before disable_global_interrupt()
|
||||
*/
|
||||
void sys_irq_restore_enable(unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief disable all interrupts
|
||||
*/
|
||||
unsigned int sys_irq_save_disable(void);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_SYS__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
74
source/OpenAMP/libmetal/lib/system/freertos/template/sys.c
Normal file
74
source/OpenAMP/libmetal/lib/system/freertos/template/sys.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/template/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
metal_unused(flags);
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
return 0;
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
metal_unused(vector);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
metal_unused(vector);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_generic_default_poll(void)
|
||||
{
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
metal_unused(pa);
|
||||
metal_unused(size);
|
||||
metal_unused(flags);
|
||||
|
||||
/* Add implementation here */
|
||||
|
||||
return va;
|
||||
}
|
35
source/OpenAMP/libmetal/lib/system/freertos/template/sys.h
Normal file
35
source/OpenAMP/libmetal/lib/system/freertos/template/sys.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/template/sys.h
|
||||
* @brief freertos template system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_TEMPLATE_SYS__H__
|
||||
#define __METAL_FREERTOS_TEMPLATE_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
void sys_irq_enable(unsigned int vector);
|
||||
|
||||
void sys_irq_disable(unsigned int vector);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_SYS__H__ */
|
20
source/OpenAMP/libmetal/lib/system/freertos/time.c
Normal file
20
source/OpenAMP/libmetal/lib/system/freertos/time.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/time.c
|
||||
* @brief freertos libmetal time handling.
|
||||
*/
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <metal/time.h>
|
||||
|
||||
unsigned long long metal_get_timestamp(void)
|
||||
{
|
||||
return (unsigned long long)xTaskGetTickCount();
|
||||
}
|
||||
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
95
source/OpenAMP/libmetal/lib/system/freertos/zynq7/sys.c
Normal file
95
source/OpenAMP/libmetal/lib/system/freertos/zynq7/sys.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynq7/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
/* Translation table is 16K in size */
|
||||
#define ARM_AR_MEM_TTB_SIZE 16*1024
|
||||
|
||||
/* Each TTB descriptor covers a 1MB region */
|
||||
#define ARM_AR_MEM_TTB_SECT_SIZE 1024*1024
|
||||
|
||||
/* Mask off lower bits of addr */
|
||||
#define ARM_AR_MEM_TTB_SECT_SIZE_MASK (~(ARM_AR_MEM_TTB_SECT_SIZE-1UL))
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~flags);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != state) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
unsigned int section_offset;
|
||||
unsigned int ttb_addr;
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
/* Ensure the virtual and physical addresses are aligned on a
|
||||
section boundary */
|
||||
pa &= ARM_AR_MEM_TTB_SECT_SIZE_MASK;
|
||||
|
||||
/* Loop through entire region of memory (one MMU section at a time).
|
||||
Each section requires a TTB entry. */
|
||||
for (section_offset = 0; section_offset < size;
|
||||
section_offset += ARM_AR_MEM_TTB_SECT_SIZE) {
|
||||
|
||||
/* Calculate translation table entry for this memory section */
|
||||
ttb_addr = (pa + section_offset);
|
||||
|
||||
/* Write translation table entry value to entry address */
|
||||
Xil_SetTlbAttributes(ttb_addr, flags);
|
||||
}
|
||||
|
||||
return va;
|
||||
}
|
43
source/OpenAMP/libmetal/lib/system/freertos/zynq7/sys.h
Normal file
43
source/OpenAMP/libmetal/lib/system/freertos/zynq7/sys.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynq7/sys.h
|
||||
* @brief freertos zynq7 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#include "xscugic.h"
|
||||
|
||||
#ifndef __METAL_FREERTOS_ZYNQ7_SYS__H__
|
||||
#define __METAL_FREERTOS_ZYNQ7_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_ZYNQ7_SYS__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
100
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_a53/sys.c
Normal file
100
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_a53/sys.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynqmp_a53/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xreg_cortexa53.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
#define MB (1024 * 1024UL)
|
||||
#define GB (1024 * 1024 * 1024UL)
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~flags);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != state) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
unsigned long section_offset;
|
||||
unsigned long ttb_addr;
|
||||
#if defined (__aarch64__)
|
||||
unsigned long ttb_size = (pa < 4*GB) ? 2*MB : 1*GB;
|
||||
#else
|
||||
unsigned long ttb_size = 1*MB;
|
||||
#endif
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
|
||||
/* Ensure alignement on a section boundary */
|
||||
pa &= ~(ttb_size-1UL);
|
||||
|
||||
/* Loop through entire region of memory (one MMU section at a time).
|
||||
Each section requires a TTB entry. */
|
||||
for (section_offset = 0; section_offset < size; ) {
|
||||
/* Calculate translation table entry for this memory section */
|
||||
ttb_addr = (pa + section_offset);
|
||||
|
||||
/* Write translation table entry value to entry address */
|
||||
Xil_SetTlbAttributes(ttb_addr, flags);
|
||||
|
||||
#if defined (__aarch64__)
|
||||
/* recalculate if we started below 4GB and going above in 64bit mode */
|
||||
if ( ttb_addr >= 4*GB ) {
|
||||
ttb_size = 1*GB;
|
||||
}
|
||||
#endif
|
||||
section_offset += ttb_size;
|
||||
}
|
||||
|
||||
return va;
|
||||
}
|
43
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_a53/sys.h
Normal file
43
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_a53/sys.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynqmp_a53/sys.h
|
||||
* @brief freertos zynqmp_a53 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#include "xscugic.h"
|
||||
|
||||
#ifndef __METAL_FREERTOS_ZYNQMP_A53_SYS__H__
|
||||
#define __METAL_FREERTOS_ZYNQMP_A53_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_ZYNQMP_A53_SYS__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
87
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_r5/sys.c
Normal file
87
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_r5/sys.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynqmp_r5/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xil_mpu.h"
|
||||
#include "xreg_cortexr5.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
#define MPU_REGION_SIZE_MIN 0x20
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~flags);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != state) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
size_t rsize = MPU_REGION_SIZE_MIN;
|
||||
metal_phys_addr_t base_pa;
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
while(1) {
|
||||
if (rsize < size) {
|
||||
rsize <<= 1;
|
||||
continue;
|
||||
} else {
|
||||
base_pa = pa & ~(rsize - 1);
|
||||
if ((base_pa + rsize) < (pa + size)) {
|
||||
rsize <<= 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Xil_SetMPURegion(base_pa, rsize, flags);
|
||||
return va;
|
||||
}
|
43
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_r5/sys.h
Normal file
43
source/OpenAMP/libmetal/lib/system/freertos/zynqmp_r5/sys.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynqmp_r5/sys.h
|
||||
* @brief freertos zynqmp_r5 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#include "xscugic.h"
|
||||
|
||||
#ifndef __METAL_FREERTOS_ZYNQMP_R5_SYS__H__
|
||||
#define __METAL_FREERTOS_ZYNQMP_R5_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_ZYNQMP_R5_SYS__H__ */
|
24
source/OpenAMP/libmetal/lib/system/generic/CMakeLists.txt
Normal file
24
source/OpenAMP/libmetal/lib/system/generic/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
collect (PROJECT_LIB_HEADERS alloc.h)
|
||||
collect (PROJECT_LIB_HEADERS assert.h)
|
||||
collect (PROJECT_LIB_HEADERS cache.h)
|
||||
collect (PROJECT_LIB_HEADERS condition.h)
|
||||
collect (PROJECT_LIB_HEADERS io.h)
|
||||
collect (PROJECT_LIB_HEADERS irq.h)
|
||||
collect (PROJECT_LIB_HEADERS log.h)
|
||||
collect (PROJECT_LIB_HEADERS mutex.h)
|
||||
collect (PROJECT_LIB_HEADERS sleep.h)
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES condition.c)
|
||||
collect (PROJECT_LIB_SOURCES device.c)
|
||||
collect (PROJECT_LIB_SOURCES init.c)
|
||||
collect (PROJECT_LIB_SOURCES io.c)
|
||||
collect (PROJECT_LIB_SOURCES irq.c)
|
||||
collect (PROJECT_LIB_SOURCES shmem.c)
|
||||
collect (PROJECT_LIB_SOURCES time.c)
|
||||
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
add_subdirectory(${PROJECT_MACHINE})
|
||||
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
39
source/OpenAMP/libmetal/lib/system/generic/alloc.h
Normal file
39
source/OpenAMP/libmetal/lib/system/generic/alloc.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/alloc.c
|
||||
* @brief generic libmetal memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/generic/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_ALLOC__H__
|
||||
#define __METAL_GENERIC_ALLOC__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (malloc(size));
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_ALLOC__H__ */
|
28
source/OpenAMP/libmetal/lib/system/generic/assert.h
Normal file
28
source/OpenAMP/libmetal/lib/system/generic/assert.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief Generic assertion support.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/generic/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_ASSERT__H__
|
||||
#define __METAL_GENERIC_ASSERT__H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for bare-metal applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) assert(cond)
|
||||
|
||||
#endif /* __METAL_GENERIC_ASSERT__H__ */
|
||||
|
40
source/OpenAMP/libmetal/lib/system/generic/cache.h
Normal file
40
source/OpenAMP/libmetal/lib/system/generic/cache.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/cache.h
|
||||
* @brief generic cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/generic/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_CACHE__H__
|
||||
#define __METAL_GENERIC_CACHE__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void metal_machine_cache_flush(void *addr, unsigned int len);
|
||||
extern void metal_machine_cache_invalidate(void *addr, unsigned int len);
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_flush(addr, len);
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_invalidate(addr, len);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_CACHE__H__ */
|
49
source/OpenAMP/libmetal/lib/system/generic/condition.c
Normal file
49
source/OpenAMP/libmetal/lib/system/generic/condition.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.c
|
||||
* @brief Generic libmetal condition variable handling.
|
||||
*/
|
||||
|
||||
#include <metal/condition.h>
|
||||
#include <metal/irq.h>
|
||||
|
||||
extern void metal_generic_default_poll(void);
|
||||
|
||||
int metal_condition_wait(struct metal_condition *cv,
|
||||
metal_mutex_t *m)
|
||||
{
|
||||
metal_mutex_t *tmpm = 0;
|
||||
int v;
|
||||
unsigned int flags;
|
||||
|
||||
/* Check if the mutex has been acquired */
|
||||
if (!cv || !m || !metal_mutex_is_acquired(m))
|
||||
return -EINVAL;
|
||||
|
||||
if (!atomic_compare_exchange_strong(&cv->m->v, &tmpm->v, m->v)) {
|
||||
if (m != tmpm)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v = atomic_load(&cv->v);
|
||||
|
||||
/* Release the mutex first. */
|
||||
metal_mutex_release(m);
|
||||
do {
|
||||
flags = metal_irq_save_disable();
|
||||
if (atomic_load(&cv->v) != v) {
|
||||
metal_irq_restore_enable(flags);
|
||||
break;
|
||||
}
|
||||
metal_generic_default_poll();
|
||||
metal_irq_restore_enable(flags);
|
||||
} while(1);
|
||||
/* Acquire the mutex again. */
|
||||
metal_mutex_acquire(m);
|
||||
return 0;
|
||||
}
|
68
source/OpenAMP/libmetal/lib/system/generic/condition.h
Normal file
68
source/OpenAMP/libmetal/lib/system/generic/condition.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.h
|
||||
* @brief Generic condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/generic/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_CONDITION__H__
|
||||
#define __METAL_GENERIC_CONDITION__H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <metal/atomic.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <metal/errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int v; /**< condition variable value. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
cv->m = NULL;
|
||||
atomic_init(&cv->v, 0);
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
if (!cv)
|
||||
return -EINVAL;
|
||||
|
||||
/** wake up waiters if there are any. */
|
||||
atomic_fetch_add(&cv->v, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
return metal_condition_signal(cv);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_CONDITION__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
77
source/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c
Normal file
77
source/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Xilinx nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
|
||||
#include "metal/io.h"
|
||||
#include "metal/sys.h"
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
(void)addr;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
(void)addr;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void __attribute__((weak)) metal_generic_default_poll(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
(void)va;
|
||||
(void)pa;
|
||||
(void)size;
|
||||
(void)flags;
|
||||
|
||||
return va;
|
||||
}
|
65
source/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h
Normal file
65
source/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Xilinx nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/mp1_m4/sys.h
|
||||
* @brief generic mp1_m4 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MP1_M4_SYS__H__
|
||||
#define __METAL_GENERIC_MP1_M4_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(MAX_IRQS)
|
||||
#define MAX_IRQS 8 /**< maximum number of irqs */
|
||||
#endif
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */
|
32
source/OpenAMP/libmetal/lib/system/generic/generic_device.c
Normal file
32
source/OpenAMP/libmetal/lib/system/generic/generic_device.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/device.c
|
||||
* @brief Generic libmetal device operations.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_generic_dev_sys_open(struct metal_device *dev)
|
||||
{
|
||||
struct metal_io_region *io;
|
||||
unsigned i;
|
||||
|
||||
/* map I/O memory regions */
|
||||
for (i = 0; i < dev->num_regions; i++) {
|
||||
io = &dev->regions[i];
|
||||
if (!io->size)
|
||||
break;
|
||||
metal_sys_io_mem_map(io);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
28
source/OpenAMP/libmetal/lib/system/generic/generic_init.c
Normal file
28
source/OpenAMP/libmetal/lib/system/generic/generic_init.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/init.c
|
||||
* @brief Generic libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/device.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
metal_unused(params);
|
||||
metal_bus_register(&metal_generic_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
metal_bus_unregister(&metal_generic_bus);
|
||||
}
|
31
source/OpenAMP/libmetal/lib/system/generic/generic_io.c
Normal file
31
source/OpenAMP/libmetal/lib/system/generic/generic_io.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/io.c
|
||||
* @brief Generic libmetal io operations
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io)
|
||||
{
|
||||
unsigned long p;
|
||||
size_t psize;
|
||||
size_t *va;
|
||||
|
||||
va = (size_t *)io->virt;
|
||||
psize = io->size;
|
||||
if (psize) {
|
||||
if (psize >> io->page_shift)
|
||||
psize = (size_t)1 << io->page_shift;
|
||||
for (p = 0; p <= (io->size >> io->page_shift); p++) {
|
||||
metal_machine_io_mem_map(va, io->physmap[p],
|
||||
psize, io->mem_flags);
|
||||
va += psize;
|
||||
}
|
||||
}
|
||||
}
|
18
source/OpenAMP/libmetal/lib/system/generic/generic_shmem.c
Normal file
18
source/OpenAMP/libmetal/lib/system/generic/generic_shmem.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/shmem.c
|
||||
* @brief Generic libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <metal/shmem.h>
|
||||
|
||||
int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **io)
|
||||
{
|
||||
return metal_shmem_open_generic(name, size, io);
|
||||
}
|
44
source/OpenAMP/libmetal/lib/system/generic/io.h
Normal file
44
source/OpenAMP/libmetal/lib/system/generic/io.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/io.h
|
||||
* @brief Generic specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/generic/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_IO__H__
|
||||
#define __METAL_GENERIC_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief memory mapping for an I/O region
|
||||
*/
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io);
|
||||
|
||||
/**
|
||||
* @brief memory mapping
|
||||
*/
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_IO__H__ */
|
279
source/OpenAMP/libmetal/lib/system/generic/irq.c
Normal file
279
source/OpenAMP/libmetal/lib/system/generic/irq.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/irq.c
|
||||
* @brief generic libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <metal/irq.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/alloc.h>
|
||||
|
||||
/** IRQ handlers descriptor structure */
|
||||
struct metal_irq_hddesc {
|
||||
metal_irq_handler hd; /**< irq handler */
|
||||
void *drv_id; /**< id to identify the driver
|
||||
of the irq handler */
|
||||
struct metal_device *dev; /**< device identifier */
|
||||
struct metal_list node; /**< node on irq handlers list */
|
||||
};
|
||||
|
||||
/** IRQ descriptor structure */
|
||||
struct metal_irq_desc {
|
||||
int irq; /**< interrupt number */
|
||||
struct metal_list hdls; /**< interrupt handlers */
|
||||
struct metal_list node; /**< node on irqs list */
|
||||
};
|
||||
|
||||
/** IRQ state structure */
|
||||
struct metal_irqs_state {
|
||||
struct metal_list irqs; /**< interrupt descriptors */
|
||||
metal_mutex_t irq_lock; /**< access lock */
|
||||
};
|
||||
|
||||
static struct metal_irqs_state _irqs = {
|
||||
.irqs = METAL_INIT_LIST(_irqs.irqs),
|
||||
.irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock),
|
||||
};
|
||||
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p = NULL;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
struct metal_list *node;
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((drv_id == NULL) || (hd == NULL)) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node;
|
||||
|
||||
/* Check if drv_id already exist */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
/* if drv_id already exist reject */
|
||||
if ((hdl_p->drv_id == drv_id) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d already registered."
|
||||
"Will not register again.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* irq found and drv_id not used, get out of metal_list_for_each */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Either need to add handler to an existing list or to a new one */
|
||||
hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc));
|
||||
if (hdl_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d cannot allocate mem for drv_id %d.\n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hdl_p->hd = hd;
|
||||
hdl_p->drv_id = drv_id;
|
||||
hdl_p->dev = dev;
|
||||
|
||||
/* interrupt already registered, add handler to existing list*/
|
||||
if ((irq_p != NULL) && (irq_p->irq == irq)) {
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interrupt was not already registered, add */
|
||||
irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc));
|
||||
if (irq_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
irq_p->irq = irq;
|
||||
metal_list_init(&irq_p->hdls);
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&_irqs.irqs, &irq_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for metal_irq_unregister() */
|
||||
static void metal_irq_delete_node(struct metal_list *node, void *p_to_free)
|
||||
{
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
irq_flags_save=metal_irq_save_disable();
|
||||
metal_list_del(node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
metal_free_memory(p_to_free);
|
||||
}
|
||||
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p;
|
||||
struct metal_list *node;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node, *h_prenode;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
unsigned int delete_count = 0;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n",
|
||||
__func__, irq);
|
||||
|
||||
/* Search through handlers */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
if (((hd == NULL) || (hdl_p->hd == hd)) &&
|
||||
((drv_id == NULL) || (hdl_p->drv_id == drv_id)) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: unregister hd=%p drv_id=%p dev=%p\n",
|
||||
__func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev);
|
||||
h_prenode = h_node->prev;
|
||||
metal_irq_delete_node(h_node, hdl_p);
|
||||
h_node = h_prenode;
|
||||
delete_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* we did not find any handler to delete */
|
||||
if (!delete_count) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n",
|
||||
__func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
|
||||
/* if interrupt handlers list is empty, unregister interrupt */
|
||||
if (metal_list_is_empty(&irq_p->hdls)) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: handlers list empty, unregister interrupt\n",
|
||||
__func__);
|
||||
metal_irq_delete_node(node, irq_p);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
unsigned int metal_irq_save_disable(void)
|
||||
{
|
||||
return sys_irq_save_disable();
|
||||
}
|
||||
|
||||
void metal_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
sys_irq_restore_enable(flags);
|
||||
}
|
||||
|
||||
void metal_irq_enable(unsigned int vector)
|
||||
{
|
||||
sys_irq_enable(vector);
|
||||
}
|
||||
|
||||
void metal_irq_disable(unsigned int vector)
|
||||
{
|
||||
sys_irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default handler
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_irq_desc *irq_p;
|
||||
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if ((unsigned int)irq_p->irq == vector) {
|
||||
struct metal_list *h_node;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
(hdl_p->hd)(vector, hdl_p->drv_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
source/OpenAMP/libmetal/lib/system/generic/irq.h
Normal file
34
source/OpenAMP/libmetal/lib/system/generic/irq.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/irq.c
|
||||
* @brief Generic libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/generic/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_IRQ__H__
|
||||
#define __METAL_GENERIC_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief default interrupt handler
|
||||
* @param[in] vector interrupt vector
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_IRQ__H__ */
|
52
source/OpenAMP/libmetal/lib/system/generic/log.h
Normal file
52
source/OpenAMP/libmetal/lib/system/generic/log.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Linaro nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/log.h
|
||||
* @brief Generic libmetal log handler definition.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#error "Include metal/log.h instead of metal/generic/log.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_LOG__H__
|
||||
#define __METAL_GENERIC_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_LOG__H__ */
|
@@ -0,0 +1,10 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
check_include_files(xintc.h HAS_XINTC)
|
||||
if (HAS_XINTC)
|
||||
add_definitions(-DHAS_XINTC)
|
||||
endif(HAS_XINTC)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/microblaze_generic/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/assert.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include <xil_cache.h>
|
||||
#include <xil_exception.h>
|
||||
#ifdef HAS_XINTC
|
||||
#include <xintc.h>
|
||||
#include <xparameters.h>
|
||||
#endif /* HAS_XINTC */
|
||||
|
||||
#define MSR_IE 0x2UL /* MicroBlaze status register interrupt enable mask */
|
||||
|
||||
#if (XPAR_MICROBLAZE_USE_MSR_INSTR != 0)
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state;
|
||||
|
||||
asm volatile(" mfs %0, rmsr \n"
|
||||
" msrclr r0, %1 \n"
|
||||
: "=r"(state)
|
||||
: "i"(MSR_IE)
|
||||
: "memory");
|
||||
|
||||
return state &= MSR_IE;
|
||||
}
|
||||
#else /* XPAR_MICROBLAZE_USE_MSR_INSTR == 0 */
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int tmp, state;
|
||||
|
||||
asm volatile (" mfs %0, rmsr \n"
|
||||
" andi %1, %0, %2 \n"
|
||||
" mts rmsr, %1 \n"
|
||||
: "=r"(state), "=r"(tmp)
|
||||
: "i"(~MSR_IE)
|
||||
: "memory");
|
||||
|
||||
return state &= MSR_IE;
|
||||
}
|
||||
#endif /* XPAR_MICROBLAZE_USE_MSR_INSTR */
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
asm volatile(" mfs %0, rmsr \n"
|
||||
" or %0, %0, %1 \n"
|
||||
" mts rmsr, %0 \n"
|
||||
: "=r"(tmp)
|
||||
: "r"(~flags)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static void sys_irq_change(unsigned int vector, int is_enable)
|
||||
{
|
||||
#ifdef HAS_XINTC
|
||||
XIntc_Config *cfgptr;
|
||||
unsigned int ier;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 1 >> ((vector%32)-1); /* set bit corresponding to interrupt */
|
||||
mask = is_enable ? mask : ~mask; /* if disable then turn off bit */
|
||||
|
||||
cfgptr = XIntc_LookupConfig(vector/32);
|
||||
Xil_AssertVoid(cfgptr != NULL);
|
||||
Xil_AssertVoid(vector < XPAR_INTC_MAX_NUM_INTR_INPUTS);
|
||||
|
||||
ier = XIntc_In32(cfgptr->BaseAddress + XIN_IER_OFFSET);
|
||||
|
||||
XIntc_Out32(cfgptr->BaseAddress + XIN_IER_OFFSET,
|
||||
(ier | mask));
|
||||
#else
|
||||
(void)vector;
|
||||
(void)is_enable;
|
||||
metal_assert(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void metal_weak sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
sys_irq_change(vector, 1);
|
||||
}
|
||||
|
||||
void metal_weak sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
sys_irq_change(vector, 0);
|
||||
}
|
||||
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len){
|
||||
Xil_DCacheFlush();
|
||||
}
|
||||
else{
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len){
|
||||
Xil_DCacheInvalidate();
|
||||
}
|
||||
else {
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief make microblaze wait
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("nop");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
(void)pa;
|
||||
(void)size;
|
||||
(void)flags;
|
||||
return va;
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/microblaze_generic/sys.h
|
||||
* @brief generic microblaze system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MICROBLAZE_SYS__H__
|
||||
#define __METAL_GENERIC_MICROBLAZE_SYS__H__
|
||||
|
||||
#include <metal/compiler.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
void metal_weak sys_irq_enable(unsigned int vector);
|
||||
|
||||
void metal_weak sys_irq_disable(unsigned int vector);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MICROBLAZE_SYS__H__ */
|
79
source/OpenAMP/libmetal/lib/system/generic/mutex.h
Normal file
79
source/OpenAMP/libmetal/lib/system/generic/mutex.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/mutex.h
|
||||
* @brief Generic mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#error "Include metal/mutex.h instead of metal/generic/mutex.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MUTEX__H__
|
||||
#define __METAL_GENERIC_MUTEX__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
union{
|
||||
atomic_int v;
|
||||
atomic_flag w;
|
||||
};
|
||||
} metal_mutex_t;
|
||||
|
||||
/*
|
||||
* METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) }
|
||||
/*
|
||||
* METAL_MUTEX_DEFINE - used for defining and initializing a global or
|
||||
* static singleton mutex
|
||||
*/
|
||||
#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
|
||||
|
||||
static inline void __metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_store(&mutex->v, 0);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
return 1 - atomic_flag_test_and_set(&mutex->w);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
while (atomic_flag_test_and_set(&mutex->w)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_flag_clear(&mutex->w);
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return atomic_load(&mutex->v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MUTEX__H__ */
|
38
source/OpenAMP/libmetal/lib/system/generic/sleep.h
Normal file
38
source/OpenAMP/libmetal/lib/system/generic/sleep.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sleep.h
|
||||
* @brief Generic sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#error "Include metal/sleep.h instead of metal/generic/sleep.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_SLEEP__H__
|
||||
#define __METAL_GENERIC_SLEEP__H__
|
||||
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
metal_unused(usec);
|
||||
/* Fix me */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_SLEEP__H__ */
|
63
source/OpenAMP/libmetal/lib/system/generic/sys.h
Normal file
63
source/OpenAMP/libmetal/lib/system/generic/sys.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sys.h
|
||||
* @brief Generic system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#define __METAL_GENERIC_SYS__H__
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./@PROJECT_MACHINE@/sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef METAL_MAX_DEVICE_REGIONS
|
||||
#define METAL_MAX_DEVICE_REGIONS 1
|
||||
#endif
|
||||
|
||||
/** Structure of generic libmetal runtime state. */
|
||||
struct metal_state {
|
||||
|
||||
/** Common (system independent) data. */
|
||||
struct metal_common_state common;
|
||||
};
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief restore interrupts to state before disable_global_interrupt()
|
||||
*/
|
||||
void sys_irq_restore_enable(unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief disable all interrupts
|
||||
*/
|
||||
unsigned int sys_irq_save_disable(void);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_SYS__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
74
source/OpenAMP/libmetal/lib/system/generic/template/sys.c
Normal file
74
source/OpenAMP/libmetal/lib/system/generic/template/sys.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/template/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
metal_unused(flags);
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
return 0;
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
metal_unused(vector);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
metal_unused(vector);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_generic_default_poll(void)
|
||||
{
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
metal_unused(pa);
|
||||
metal_unused(size);
|
||||
metal_unused(flags);
|
||||
|
||||
/* Add implementation here */
|
||||
|
||||
return va;
|
||||
}
|
35
source/OpenAMP/libmetal/lib/system/generic/template/sys.h
Normal file
35
source/OpenAMP/libmetal/lib/system/generic/template/sys.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/template/sys.h
|
||||
* @brief generic template system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_TEMPLATE_SYS__H__
|
||||
#define __METAL_GENERIC_TEMPLATE_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
void sys_irq_enable(unsigned int vector);
|
||||
|
||||
void sys_irq_disable(unsigned int vector);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_TEMPLATE_SYS__H__ */
|
19
source/OpenAMP/libmetal/lib/system/generic/time.c
Normal file
19
source/OpenAMP/libmetal/lib/system/generic/time.c
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/time.c
|
||||
* @brief Generic libmetal time handling.
|
||||
*/
|
||||
|
||||
#include <metal/time.h>
|
||||
|
||||
unsigned long long metal_get_timestamp(void)
|
||||
{
|
||||
/* TODO: Implement timestamp for generic system */
|
||||
return 0;
|
||||
}
|
||||
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
92
source/OpenAMP/libmetal/lib/system/generic/zynq7/sys.c
Normal file
92
source/OpenAMP/libmetal/lib/system/generic/zynq7/sys.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/zynq7/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
/* Each TTB descriptor covers a 1MB region */
|
||||
#define ARM_AR_MEM_TTB_SECT_SIZE 1024*1024
|
||||
|
||||
/* Mask off lower bits of addr */
|
||||
#define ARM_AR_MEM_TTB_SECT_SIZE_MASK (~(ARM_AR_MEM_TTB_SECT_SIZE-1UL))
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~flags);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != state) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
unsigned int section_offset;
|
||||
unsigned int ttb_addr;
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
/* Ensure the virtual and physical addresses are aligned on a
|
||||
section boundary */
|
||||
pa &= ARM_AR_MEM_TTB_SECT_SIZE_MASK;
|
||||
|
||||
/* Loop through entire region of memory (one MMU section at a time).
|
||||
Each section requires a TTB entry. */
|
||||
for (section_offset = 0; section_offset < size;
|
||||
section_offset += ARM_AR_MEM_TTB_SECT_SIZE) {
|
||||
|
||||
/* Calculate translation table entry for this memory section */
|
||||
ttb_addr = (pa + section_offset);
|
||||
|
||||
/* Write translation table entry value to entry address */
|
||||
Xil_SetTlbAttributes(ttb_addr, flags);
|
||||
}
|
||||
|
||||
return va;
|
||||
}
|
43
source/OpenAMP/libmetal/lib/system/generic/zynq7/sys.h
Normal file
43
source/OpenAMP/libmetal/lib/system/generic/zynq7/sys.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/zynq7/sys.h
|
||||
* @brief generic zynq7 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#include "xscugic.h"
|
||||
|
||||
#ifndef __METAL_GENERIC_ZYNQ7_SYS__H__
|
||||
#define __METAL_GENERIC_ZYNQ7_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_ZYNQ7_SYS__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
100
source/OpenAMP/libmetal/lib/system/generic/zynqmp_a53/sys.c
Normal file
100
source/OpenAMP/libmetal/lib/system/generic/zynqmp_a53/sys.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/zynqmp_a53/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xreg_cortexa53.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
#define MB (1024 * 1024UL)
|
||||
#define GB (1024 * 1024 * 1024UL)
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~flags);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != state) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
unsigned long section_offset;
|
||||
unsigned long ttb_addr;
|
||||
#if defined (__aarch64__)
|
||||
unsigned long ttb_size = (pa < 4*GB) ? 2*MB : 1*GB;
|
||||
#else
|
||||
unsigned long ttb_size = 1*MB;
|
||||
#endif
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
|
||||
/* Ensure alignement on a section boundary */
|
||||
pa &= ~(ttb_size-1UL);
|
||||
|
||||
/* Loop through entire region of memory (one MMU section at a time).
|
||||
Each section requires a TTB entry. */
|
||||
for (section_offset = 0; section_offset < size; ) {
|
||||
/* Calculate translation table entry for this memory section */
|
||||
ttb_addr = (pa + section_offset);
|
||||
|
||||
/* Write translation table entry value to entry address */
|
||||
Xil_SetTlbAttributes(ttb_addr, flags);
|
||||
|
||||
#if defined (__aarch64__)
|
||||
/* recalculate if we started below 4GB and going above in 64bit mode */
|
||||
if ( ttb_addr >= 4*GB ) {
|
||||
ttb_size = 1*GB;
|
||||
}
|
||||
#endif
|
||||
section_offset += ttb_size;
|
||||
}
|
||||
|
||||
return va;
|
||||
}
|
43
source/OpenAMP/libmetal/lib/system/generic/zynqmp_a53/sys.h
Normal file
43
source/OpenAMP/libmetal/lib/system/generic/zynqmp_a53/sys.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/zynqmp_a53/sys.h
|
||||
* @brief generic zynqmp_a53 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#include "xscugic.h"
|
||||
|
||||
#ifndef __METAL_GENERIC_ZYNQMP_A53_SYS__H__
|
||||
#define __METAL_GENERIC_ZYNQMP_A53_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_ZYNQMP_A53_SYS__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
87
source/OpenAMP/libmetal/lib/system/generic/zynqmp_r5/sys.c
Normal file
87
source/OpenAMP/libmetal/lib/system/generic/zynqmp_r5/sys.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/zynqmp_r5/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xil_mpu.h"
|
||||
#include "xreg_cortexr5.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
#define MPU_REGION_SIZE_MIN 0x20
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~flags);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
unsigned int state = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != state) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
size_t rsize = MPU_REGION_SIZE_MIN;
|
||||
metal_phys_addr_t base_pa;
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
while(1) {
|
||||
if (rsize < size) {
|
||||
rsize <<= 1;
|
||||
continue;
|
||||
} else {
|
||||
base_pa = pa & ~(rsize - 1);
|
||||
if ((base_pa + rsize) < (pa + size)) {
|
||||
rsize <<= 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Xil_SetMPURegion(base_pa, rsize, flags);
|
||||
return va;
|
||||
}
|
43
source/OpenAMP/libmetal/lib/system/generic/zynqmp_r5/sys.h
Normal file
43
source/OpenAMP/libmetal/lib/system/generic/zynqmp_r5/sys.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/zynqmp_r5/sys.h
|
||||
* @brief generic zynqmp_r5 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#include "xscugic.h"
|
||||
|
||||
#ifndef __METAL_GENERIC_ZYNQMP_R5_SYS__H__
|
||||
#define __METAL_GENERIC_ZYNQMP_R5_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR, vector);
|
||||
}
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_ZYNQMP_R5_SYS__H__ */
|
20
source/OpenAMP/libmetal/lib/system/linux/CMakeLists.txt
Normal file
20
source/OpenAMP/libmetal/lib/system/linux/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
collect (PROJECT_LIB_HEADERS alloc.h)
|
||||
collect (PROJECT_LIB_HEADERS assert.h)
|
||||
collect (PROJECT_LIB_HEADERS cache.h)
|
||||
collect (PROJECT_LIB_HEADERS condition.h)
|
||||
collect (PROJECT_LIB_HEADERS io.h)
|
||||
collect (PROJECT_LIB_HEADERS irq.h)
|
||||
collect (PROJECT_LIB_HEADERS log.h)
|
||||
collect (PROJECT_LIB_HEADERS mutex.h)
|
||||
collect (PROJECT_LIB_HEADERS sleep.h)
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES condition.c)
|
||||
collect (PROJECT_LIB_SOURCES device.c)
|
||||
collect (PROJECT_LIB_SOURCES init.c)
|
||||
collect (PROJECT_LIB_SOURCES irq.c)
|
||||
collect (PROJECT_LIB_SOURCES shmem.c)
|
||||
collect (PROJECT_LIB_SOURCES time.c)
|
||||
collect (PROJECT_LIB_SOURCES utilities.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
39
source/OpenAMP/libmetal/lib/system/linux/alloc.h
Normal file
39
source/OpenAMP/libmetal/lib/system/linux/alloc.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/alloc.h
|
||||
* @brief linux memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/linux/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_ALLOC__H__
|
||||
#define __METAL_LINUX_ALLOC__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (malloc(size));
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_ALLOC__H__ */
|
28
source/OpenAMP/libmetal/lib/system/linux/assert.h
Normal file
28
source/OpenAMP/libmetal/lib/system/linux/assert.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief Linux assertion support.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/linux/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_ASSERT__H__
|
||||
#define __METAL_LINUX_ASSERT__H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for Linux-based applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) assert(cond)
|
||||
|
||||
#endif /* __METAL_LINUX_ASSERT__H__ */
|
||||
|
49
source/OpenAMP/libmetal/lib/system/linux/cache.h
Normal file
49
source/OpenAMP/libmetal/lib/system/linux/cache.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/cache.h
|
||||
* @brief Linux cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/linux/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_CACHE__H__
|
||||
#define __METAL_LINUX_CACHE__H__
|
||||
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
/** Do nothing.
|
||||
* Do not flush cache from Linux userspace.
|
||||
*/
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
/** Do nothing.
|
||||
* Do not flush cache from Linux userspace.
|
||||
*/
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_CACHE__H__ */
|
40
source/OpenAMP/libmetal/lib/system/linux/condition.c
Normal file
40
source/OpenAMP/libmetal/lib/system/linux/condition.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.c
|
||||
* @brief Generic libmetal condition variable handling.
|
||||
*/
|
||||
|
||||
#include <metal/condition.h>
|
||||
|
||||
int metal_condition_wait(struct metal_condition *cv,
|
||||
metal_mutex_t *m)
|
||||
{
|
||||
metal_mutex_t *tmpm = 0;
|
||||
int v = 0;
|
||||
|
||||
/* Check if the mutex has been acquired */
|
||||
if (!cv || !m || !metal_mutex_is_acquired(m))
|
||||
return -EINVAL;
|
||||
|
||||
if (!atomic_compare_exchange_strong(&cv->m, &tmpm, m)) {
|
||||
if (m != tmpm)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v = atomic_load(&cv->wakeups);
|
||||
atomic_fetch_add(&cv->waiters, 1);
|
||||
|
||||
/* Release the mutex before sleeping. */
|
||||
metal_mutex_release(m);
|
||||
syscall(SYS_futex, &cv->wakeups, FUTEX_WAIT, v, NULL, NULL, 0);
|
||||
atomic_fetch_sub(&cv->waiters, 1);
|
||||
/* Acquire the mutex after it's waken up. */
|
||||
metal_mutex_acquire(m);
|
||||
|
||||
return 0;
|
||||
}
|
74
source/OpenAMP/libmetal/lib/system/linux/condition.h
Normal file
74
source/OpenAMP/libmetal/lib/system/linux/condition.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/condition.h
|
||||
* @brief Linux condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/linux/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_CONDITION__H__
|
||||
#define __METAL_LINUX_CONDITION__H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <metal/atomic.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <metal/errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int waiters; /**< number of waiters. */
|
||||
atomic_int wakeups; /**< number of wakeups. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0), ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
cv->m = NULL;
|
||||
atomic_init(&cv->waiters, 0);
|
||||
atomic_init(&cv->wakeups, 0);
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
if (!cv)
|
||||
return -EINVAL;
|
||||
|
||||
atomic_fetch_add(&cv->wakeups, 1);
|
||||
if (atomic_load(&cv->waiters) > 0)
|
||||
syscall(SYS_futex, &cv->wakeups, FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
if (!cv)
|
||||
return -EINVAL;
|
||||
|
||||
atomic_fetch_add(&cv->wakeups, 1);
|
||||
if (atomic_load(&cv->waiters) > 0)
|
||||
syscall(SYS_futex, &cv->wakeups, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __METAL_LINUX_CONDITION__H__ */
|
669
source/OpenAMP/libmetal/lib/system/linux/device.c
Normal file
669
source/OpenAMP/libmetal/lib/system/linux/device.c
Normal file
@@ -0,0 +1,669 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/device.c
|
||||
* @brief Linux libmetal device operations.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/irq.h>
|
||||
|
||||
#define MAX_DRIVERS 64
|
||||
|
||||
struct linux_bus;
|
||||
struct linux_device;
|
||||
|
||||
struct linux_driver {
|
||||
const char *drv_name;
|
||||
const char *mod_name;
|
||||
const char *cls_name;
|
||||
struct sysfs_driver *sdrv;
|
||||
int (*dev_open)(struct linux_bus *lbus,
|
||||
struct linux_device *ldev);
|
||||
void (*dev_close)(struct linux_bus *lbus,
|
||||
struct linux_device *ldev);
|
||||
void (*dev_irq_ack)(struct linux_bus *lbus,
|
||||
struct linux_device *ldev,
|
||||
int irq);
|
||||
int (*dev_dma_map)(struct linux_bus *lbus,
|
||||
struct linux_device *ldev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out);
|
||||
void (*dev_dma_unmap)(struct linux_bus *lbus,
|
||||
struct linux_device *ldev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents);
|
||||
};
|
||||
|
||||
struct linux_bus {
|
||||
struct metal_bus bus;
|
||||
const char *bus_name;
|
||||
struct linux_driver drivers[MAX_DRIVERS];
|
||||
struct sysfs_bus *sbus;
|
||||
};
|
||||
|
||||
struct linux_device {
|
||||
struct metal_device device;
|
||||
char dev_name[PATH_MAX];
|
||||
char dev_path[PATH_MAX];
|
||||
char cls_path[PATH_MAX];
|
||||
metal_phys_addr_t region_phys[METAL_MAX_DEVICE_REGIONS];
|
||||
struct linux_driver *ldrv;
|
||||
struct sysfs_device *sdev;
|
||||
struct sysfs_attribute *override;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static struct linux_bus *to_linux_bus(struct metal_bus *bus)
|
||||
{
|
||||
return metal_container_of(bus, struct linux_bus, bus);
|
||||
}
|
||||
|
||||
static struct linux_device *to_linux_device(struct metal_device *device)
|
||||
{
|
||||
return metal_container_of(device, struct linux_device, device);
|
||||
}
|
||||
|
||||
static int metal_uio_read_map_attr(struct linux_device *ldev, unsigned index,
|
||||
const char *name, unsigned long *value)
|
||||
{
|
||||
const char *cls = ldev->cls_path;
|
||||
struct sysfs_attribute *attr;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
int result;
|
||||
|
||||
result = snprintf(path, sizeof(path), "%s/maps/map%u/%s", cls, index, name);
|
||||
if (result >= (int)sizeof(path))
|
||||
return -EOVERFLOW;
|
||||
attr = sysfs_open_attribute(path);
|
||||
if (!attr || sysfs_read_attribute(attr) != 0)
|
||||
return -errno;
|
||||
|
||||
*value = strtoul(attr->value, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int metal_uio_dev_bind(struct linux_device *ldev,
|
||||
struct linux_driver *ldrv)
|
||||
{
|
||||
struct sysfs_attribute *attr;
|
||||
int result;
|
||||
|
||||
if (strcmp(ldev->sdev->driver_name, ldrv->drv_name) == 0)
|
||||
return 0;
|
||||
|
||||
if (strcmp(ldev->sdev->driver_name, SYSFS_UNKNOWN) != 0) {
|
||||
metal_log(METAL_LOG_INFO, "device %s in use by driver %s\n",
|
||||
ldev->dev_name, ldev->sdev->driver_name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
attr = sysfs_get_device_attr(ldev->sdev, "driver_override");
|
||||
if (!attr) {
|
||||
metal_log(METAL_LOG_ERROR, "device %s has no override\n",
|
||||
ldev->dev_name);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
result = sysfs_write_attribute(attr, ldrv->drv_name,
|
||||
strlen(ldrv->drv_name));
|
||||
if (result) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to set override on %s\n",
|
||||
ldev->dev_name);
|
||||
return -errno;
|
||||
}
|
||||
ldev->override = attr;
|
||||
|
||||
attr = sysfs_get_driver_attr(ldrv->sdrv, "bind");
|
||||
if (!attr) {
|
||||
metal_log(METAL_LOG_ERROR, "driver %s has no bind\n", ldrv->drv_name);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
result = sysfs_write_attribute(attr, ldev->dev_name,
|
||||
strlen(ldev->dev_name));
|
||||
if (result) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to bind %s to %s\n",
|
||||
ldev->dev_name, ldrv->drv_name);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "bound device %s to driver %s\n",
|
||||
ldev->dev_name, ldrv->drv_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int metal_uio_dev_open(struct linux_bus *lbus, struct linux_device *ldev)
|
||||
{
|
||||
char *instance, path[SYSFS_PATH_MAX];
|
||||
struct linux_driver *ldrv = ldev->ldrv;
|
||||
unsigned long *phys, offset=0, size=0;
|
||||
struct metal_io_region *io;
|
||||
struct dlist *dlist;
|
||||
int result, i;
|
||||
void *virt;
|
||||
int irq_info;
|
||||
|
||||
|
||||
ldev->fd = -1;
|
||||
|
||||
ldev->sdev = sysfs_open_device(lbus->bus_name, ldev->dev_name);
|
||||
if (!ldev->sdev) {
|
||||
metal_log(METAL_LOG_ERROR, "device %s:%s not found\n",
|
||||
lbus->bus_name, ldev->dev_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
metal_log(METAL_LOG_DEBUG, "opened sysfs device %s:%s\n",
|
||||
lbus->bus_name, ldev->dev_name);
|
||||
|
||||
result = metal_uio_dev_bind(ldev, ldrv);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = snprintf(path, sizeof(path), "%s/uio", ldev->sdev->path);
|
||||
if (result >= (int)sizeof(path))
|
||||
return -EOVERFLOW;
|
||||
dlist = sysfs_open_directory_list(path);
|
||||
if (!dlist) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to scan class path %s\n",
|
||||
path);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
dlist_for_each_data(dlist, instance, char) {
|
||||
result = snprintf(ldev->cls_path, sizeof(ldev->cls_path),
|
||||
"%s/%s", path, instance);
|
||||
if (result >= (int)sizeof(ldev->cls_path))
|
||||
return -EOVERFLOW;
|
||||
result = snprintf(ldev->dev_path, sizeof(ldev->dev_path),
|
||||
"/dev/%s", instance);
|
||||
if (result >= (int)sizeof(ldev->dev_path))
|
||||
return -EOVERFLOW;
|
||||
break;
|
||||
}
|
||||
sysfs_close_list(dlist);
|
||||
|
||||
if (sysfs_path_is_dir(ldev->cls_path) != 0) {
|
||||
metal_log(METAL_LOG_ERROR, "invalid device class path %s\n",
|
||||
ldev->cls_path);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
if (!access(ldev->dev_path, F_OK))
|
||||
break;
|
||||
usleep(10);
|
||||
i++;
|
||||
} while (i < 1000);
|
||||
if (i >= 1000) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to open file %s, timeout.\n",
|
||||
ldev->dev_path);
|
||||
return -ENODEV;
|
||||
}
|
||||
result = metal_open(ldev->dev_path, 0);
|
||||
if (result < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to open device %s\n",
|
||||
ldev->dev_path, strerror(-result));
|
||||
return result;
|
||||
}
|
||||
ldev->fd = result;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "opened %s:%s as %s\n",
|
||||
lbus->bus_name, ldev->dev_name, ldev->dev_path);
|
||||
|
||||
for (i = 0, result = 0; !result && i < METAL_MAX_DEVICE_REGIONS; i++) {
|
||||
phys = &ldev->region_phys[ldev->device.num_regions];
|
||||
result = (result ? result :
|
||||
metal_uio_read_map_attr(ldev, i, "offset", &offset));
|
||||
result = (result ? result :
|
||||
metal_uio_read_map_attr(ldev, i, "addr", phys));
|
||||
result = (result ? result :
|
||||
metal_uio_read_map_attr(ldev, i, "size", &size));
|
||||
result = (result ? result :
|
||||
metal_map(ldev->fd, offset, size, 0, 0, &virt));
|
||||
if (!result) {
|
||||
io = &ldev->device.regions[ldev->device.num_regions];
|
||||
metal_io_init(io, virt, phys, size, -1, 0, NULL);
|
||||
ldev->device.num_regions++;
|
||||
}
|
||||
}
|
||||
|
||||
irq_info = 1;
|
||||
if (write(ldev->fd, &irq_info, sizeof(irq_info)) <= 0) {
|
||||
metal_log(METAL_LOG_INFO,
|
||||
"%s: No IRQ for device %s.\n",
|
||||
__func__, ldev->dev_name);
|
||||
ldev->device.irq_num = 0;
|
||||
ldev->device.irq_info = (void *)-1;
|
||||
} else {
|
||||
ldev->device.irq_num = 1;
|
||||
ldev->device.irq_info = (void *)(intptr_t)ldev->fd;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void metal_uio_dev_close(struct linux_bus *lbus,
|
||||
struct linux_device *ldev)
|
||||
{
|
||||
(void)lbus;
|
||||
|
||||
if ((intptr_t)ldev->device.irq_info >= 0)
|
||||
/* Normally this call would not be needed, and is added as precaution.
|
||||
Also for uio there is only 1 interrupt associated to the fd/device,
|
||||
we therefore do not need to specify a particular device */
|
||||
metal_irq_unregister(ldev->fd, NULL, NULL, NULL);
|
||||
|
||||
if (ldev->override) {
|
||||
sysfs_write_attribute(ldev->override, "", 1);
|
||||
ldev->override = NULL;
|
||||
}
|
||||
if (ldev->sdev) {
|
||||
sysfs_close_device(ldev->sdev);
|
||||
ldev->sdev = NULL;
|
||||
}
|
||||
if (ldev->fd >= 0) {
|
||||
close(ldev->fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void metal_uio_dev_irq_ack(struct linux_bus *lbus,
|
||||
struct linux_device *ldev,
|
||||
int irq)
|
||||
{
|
||||
(void)lbus;
|
||||
(void)irq;
|
||||
int irq_info = 1;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = read(ldev->fd, (void *)&val, sizeof(val));
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s, read uio irq fd %d failed: %d.\n",
|
||||
__func__, ldev->fd, ret);
|
||||
return;
|
||||
}
|
||||
ret = write(ldev->fd, &irq_info, sizeof(irq_info));
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s, write uio irq fd %d failed: %d.\n",
|
||||
__func__, ldev->fd, errno);
|
||||
}
|
||||
}
|
||||
|
||||
static int metal_uio_dev_dma_map(struct linux_bus *lbus,
|
||||
struct linux_device *ldev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out)
|
||||
{
|
||||
int i, j;
|
||||
void *vaddr_sg_lo, *vaddr_sg_hi, *vaddr_lo, *vaddr_hi;
|
||||
struct metal_io_region *io;
|
||||
|
||||
(void)lbus;
|
||||
(void)dir;
|
||||
|
||||
/* Check if the the input virt address is MMIO address */
|
||||
for (i = 0; i < nents_in; i++) {
|
||||
vaddr_sg_lo = sg_in[i].virt;
|
||||
vaddr_sg_hi = vaddr_sg_lo + sg_in[i].len;
|
||||
for (j = 0, io = ldev->device.regions;
|
||||
j < (int)ldev->device.num_regions; j++, io++) {
|
||||
vaddr_lo = io->virt;
|
||||
vaddr_hi = vaddr_lo + io->size;
|
||||
if (vaddr_sg_lo >= vaddr_lo &&
|
||||
vaddr_sg_hi <= vaddr_hi) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == (int)ldev->device.num_regions) {
|
||||
metal_log(METAL_LOG_WARNING,
|
||||
"%s,%s: input address isn't MMIO addr: 0x%x,%d.\n",
|
||||
__func__, ldev->dev_name, vaddr_sg_lo, sg_in[i].len);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (sg_out != sg_in)
|
||||
memcpy(sg_out, sg_in, nents_in*(sizeof(struct metal_sg)));
|
||||
return nents_in;
|
||||
}
|
||||
|
||||
static void metal_uio_dev_dma_unmap(struct linux_bus *lbus,
|
||||
struct linux_device *ldev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents)
|
||||
{
|
||||
(void) lbus;
|
||||
(void) ldev;
|
||||
(void) dir;
|
||||
(void) sg;
|
||||
(void) nents;
|
||||
return;
|
||||
}
|
||||
|
||||
static struct linux_bus linux_bus[] = {
|
||||
{
|
||||
.bus_name = "platform",
|
||||
.drivers = {
|
||||
{
|
||||
.drv_name = "uio_pdrv_genirq",
|
||||
.mod_name = "uio_pdrv_genirq",
|
||||
.cls_name = "uio",
|
||||
.dev_open = metal_uio_dev_open,
|
||||
.dev_close = metal_uio_dev_close,
|
||||
.dev_irq_ack = metal_uio_dev_irq_ack,
|
||||
.dev_dma_map = metal_uio_dev_dma_map,
|
||||
.dev_dma_unmap = metal_uio_dev_dma_unmap,
|
||||
},
|
||||
{
|
||||
.drv_name = "uio_dmem_genirq",
|
||||
.mod_name = "uio_dmem_genirq",
|
||||
.cls_name = "uio",
|
||||
.dev_open = metal_uio_dev_open,
|
||||
.dev_close = metal_uio_dev_close,
|
||||
.dev_irq_ack = metal_uio_dev_irq_ack,
|
||||
.dev_dma_map = metal_uio_dev_dma_map,
|
||||
.dev_dma_unmap = metal_uio_dev_dma_unmap,
|
||||
},
|
||||
{ 0 /* sentinel */ }
|
||||
}
|
||||
},
|
||||
{
|
||||
.bus_name = "pci",
|
||||
.drivers = {
|
||||
{
|
||||
.drv_name = "vfio-pci",
|
||||
.mod_name = "vfio-pci",
|
||||
},
|
||||
{
|
||||
.drv_name = "uio_pci_generic",
|
||||
.mod_name = "uio_pci_generic",
|
||||
.cls_name = "uio",
|
||||
.dev_open = metal_uio_dev_open,
|
||||
.dev_close = metal_uio_dev_close,
|
||||
.dev_irq_ack = metal_uio_dev_irq_ack,
|
||||
.dev_dma_map = metal_uio_dev_dma_map,
|
||||
.dev_dma_unmap = metal_uio_dev_dma_unmap,
|
||||
},
|
||||
{ 0 /* sentinel */ }
|
||||
}
|
||||
},
|
||||
{
|
||||
/* sentinel */
|
||||
.bus_name = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
#define for_each_linux_bus(lbus) \
|
||||
for ((lbus) = linux_bus; (lbus)->bus_name; (lbus)++)
|
||||
#define for_each_linux_driver(lbus, ldrv) \
|
||||
for ((ldrv) = lbus->drivers; (ldrv)->drv_name; (ldrv)++)
|
||||
|
||||
|
||||
static int metal_linux_dev_open(struct metal_bus *bus,
|
||||
const char *dev_name,
|
||||
struct metal_device **device)
|
||||
{
|
||||
struct linux_bus *lbus = to_linux_bus(bus);
|
||||
struct linux_device *ldev = NULL;
|
||||
struct linux_driver *ldrv;
|
||||
int error;
|
||||
|
||||
ldev = malloc(sizeof(*ldev));
|
||||
if (!ldev)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_linux_driver(lbus, ldrv) {
|
||||
|
||||
/* Check if we have a viable driver. */
|
||||
if (!ldrv->sdrv || !ldrv->dev_open)
|
||||
continue;
|
||||
|
||||
/* Allocate a linux device if we haven't already. */
|
||||
if (!ldev)
|
||||
ldev = malloc(sizeof(*ldev));
|
||||
if (!ldev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Reset device data. */
|
||||
memset(ldev, 0, sizeof(*ldev));
|
||||
strncpy(ldev->dev_name, dev_name, sizeof(ldev->dev_name) - 1);
|
||||
ldev->fd = -1;
|
||||
ldev->ldrv = ldrv;
|
||||
ldev->device.bus = bus;
|
||||
|
||||
/* Try and open the device. */
|
||||
error = ldrv->dev_open(lbus, ldev);
|
||||
if (error) {
|
||||
ldrv->dev_close(lbus, ldev);
|
||||
continue;
|
||||
}
|
||||
|
||||
*device = &ldev->device;
|
||||
(*device)->name = ldev->dev_name;
|
||||
|
||||
metal_list_add_tail(&bus->devices, &(*device)->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldev)
|
||||
free(ldev);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void metal_linux_dev_close(struct metal_bus *bus,
|
||||
struct metal_device *device)
|
||||
{
|
||||
struct linux_device *ldev = to_linux_device(device);
|
||||
struct linux_bus *lbus = to_linux_bus(bus);
|
||||
|
||||
ldev->ldrv->dev_close(lbus, ldev);
|
||||
metal_list_del(&device->node);
|
||||
free(ldev);
|
||||
}
|
||||
|
||||
static void metal_linux_bus_close(struct metal_bus *bus)
|
||||
{
|
||||
struct linux_bus *lbus = to_linux_bus(bus);
|
||||
struct linux_driver *ldrv;
|
||||
|
||||
for_each_linux_driver(lbus, ldrv) {
|
||||
if (ldrv->sdrv)
|
||||
sysfs_close_driver(ldrv->sdrv);
|
||||
ldrv->sdrv = NULL;
|
||||
}
|
||||
|
||||
sysfs_close_bus(lbus->sbus);
|
||||
lbus->sbus = NULL;
|
||||
}
|
||||
|
||||
static void metal_linux_dev_irq_ack(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
int irq)
|
||||
{
|
||||
struct linux_device *ldev = to_linux_device(device);
|
||||
struct linux_bus *lbus = to_linux_bus(bus);
|
||||
|
||||
return ldev->ldrv->dev_irq_ack(lbus, ldev, irq);
|
||||
}
|
||||
|
||||
static int metal_linux_dev_dma_map(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out)
|
||||
{
|
||||
struct linux_device *ldev = to_linux_device(device);
|
||||
struct linux_bus *lbus = to_linux_bus(bus);
|
||||
|
||||
return ldev->ldrv->dev_dma_map(lbus, ldev, dir, sg_in,
|
||||
nents_in, sg_out);
|
||||
}
|
||||
|
||||
static void metal_linux_dev_dma_unmap(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents)
|
||||
{
|
||||
struct linux_device *ldev = to_linux_device(device);
|
||||
struct linux_bus *lbus = to_linux_bus(bus);
|
||||
|
||||
ldev->ldrv->dev_dma_unmap(lbus, ldev, dir, sg,
|
||||
nents);
|
||||
}
|
||||
|
||||
static const struct metal_bus_ops metal_linux_bus_ops = {
|
||||
.bus_close = metal_linux_bus_close,
|
||||
.dev_open = metal_linux_dev_open,
|
||||
.dev_close = metal_linux_dev_close,
|
||||
.dev_irq_ack = metal_linux_dev_irq_ack,
|
||||
.dev_dma_map = metal_linux_dev_dma_map,
|
||||
.dev_dma_unmap = metal_linux_dev_dma_unmap,
|
||||
};
|
||||
|
||||
static int metal_linux_register_bus(struct linux_bus *lbus)
|
||||
{
|
||||
lbus->bus.name = lbus->bus_name;
|
||||
lbus->bus.ops = metal_linux_bus_ops;
|
||||
return metal_bus_register(&lbus->bus);
|
||||
}
|
||||
|
||||
static int metal_linux_probe_driver(struct linux_bus *lbus,
|
||||
struct linux_driver *ldrv)
|
||||
{
|
||||
char command[256];
|
||||
int ret;
|
||||
|
||||
ldrv->sdrv = sysfs_open_driver(lbus->bus_name, ldrv->drv_name);
|
||||
|
||||
/* Try probing the module and then open the driver. */
|
||||
if (!ldrv->sdrv) {
|
||||
ret = snprintf(command, sizeof(command),
|
||||
"modprobe %s > /dev/null 2>&1", ldrv->mod_name);
|
||||
if (ret >= (int)sizeof(command))
|
||||
return -EOVERFLOW;
|
||||
ret = system(command);
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_WARNING,
|
||||
"%s: executing system command '%s' failed.\n",
|
||||
__func__, command);
|
||||
}
|
||||
ldrv->sdrv = sysfs_open_driver(lbus->bus_name, ldrv->drv_name);
|
||||
}
|
||||
|
||||
/* Try sudo probing the module and then open the driver. */
|
||||
if (!ldrv->sdrv) {
|
||||
ret = snprintf(command, sizeof(command),
|
||||
"sudo modprobe %s > /dev/null 2>&1", ldrv->mod_name);
|
||||
if (ret >= (int)sizeof(command))
|
||||
return -EOVERFLOW;
|
||||
ret = system(command);
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_WARNING,
|
||||
"%s: executing system command '%s' failed.\n",
|
||||
__func__, command);
|
||||
}
|
||||
ldrv->sdrv = sysfs_open_driver(lbus->bus_name, ldrv->drv_name);
|
||||
}
|
||||
|
||||
/* If all else fails... */
|
||||
return ldrv->sdrv ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
static int metal_linux_probe_bus(struct linux_bus *lbus)
|
||||
{
|
||||
struct linux_driver *ldrv;
|
||||
int error = -ENODEV;
|
||||
|
||||
lbus->sbus = sysfs_open_bus(lbus->bus_name);
|
||||
if (!lbus->sbus)
|
||||
return -ENODEV;
|
||||
|
||||
for_each_linux_driver(lbus, ldrv) {
|
||||
error = metal_linux_probe_driver(lbus, ldrv);
|
||||
if (!error)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
sysfs_close_bus(lbus->sbus);
|
||||
lbus->sbus = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = metal_linux_register_bus(lbus);
|
||||
if (error) {
|
||||
sysfs_close_driver(ldrv->sdrv);
|
||||
ldrv->sdrv = NULL;
|
||||
sysfs_close_bus(lbus->sbus);
|
||||
lbus->sbus = NULL;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int metal_linux_bus_init(void)
|
||||
{
|
||||
struct linux_bus *lbus;
|
||||
int valid = 0;
|
||||
|
||||
for_each_linux_bus(lbus)
|
||||
valid += metal_linux_probe_bus(lbus) ? 0 : 1;
|
||||
|
||||
return valid ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
void metal_linux_bus_finish(void)
|
||||
{
|
||||
struct linux_bus *lbus;
|
||||
struct metal_bus *bus;
|
||||
|
||||
for_each_linux_bus(lbus) {
|
||||
if (metal_bus_find(lbus->bus_name, &bus) == 0)
|
||||
metal_bus_unregister(bus);
|
||||
}
|
||||
}
|
||||
|
||||
int metal_generic_dev_sys_open(struct metal_device *dev)
|
||||
{
|
||||
(void)dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_linux_get_device_property(struct metal_device *device,
|
||||
const char *property_name,
|
||||
void *output, int len)
|
||||
{
|
||||
int fd = 0;
|
||||
int status = 0;
|
||||
const int flags = O_RDONLY;
|
||||
const int mode = S_IRUSR | S_IRGRP | S_IROTH;
|
||||
struct linux_device *ldev = to_linux_device(device);
|
||||
char path[PATH_MAX];
|
||||
|
||||
snprintf(path, sizeof(path), "%s/of_node/%s",
|
||||
ldev->sdev->path, property_name);
|
||||
fd = open(path, flags, mode);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
status = read(fd, output, len);
|
||||
|
||||
return status < 0 ? -errno : 0;
|
||||
}
|
||||
|
174
source/OpenAMP/libmetal/lib/system/linux/init.c
Normal file
174
source/OpenAMP/libmetal/lib/system/linux/init.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/init.c
|
||||
* @brief Linux libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
extern int metal_linux_irq_init();
|
||||
extern void metal_linux_irq_shutdown();
|
||||
|
||||
/** Sort function for page size array. */
|
||||
static int metal_pagesize_compare(const void *_a, const void *_b)
|
||||
{
|
||||
const struct metal_page_size *a = _a, *b = _b;
|
||||
long diff = a->page_size - b->page_size;
|
||||
return metal_sign(diff);
|
||||
}
|
||||
|
||||
static int metal_add_page_size(const char *path, int shift, int mmap_flags)
|
||||
{
|
||||
int index = _metal.num_page_sizes;
|
||||
unsigned long size = 1UL << shift;
|
||||
|
||||
if (index >= MAX_PAGE_SIZES) {
|
||||
metal_log(METAL_LOG_WARNING, "skipped page size %ld - overflow\n",
|
||||
size);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (!path || shift <= 0) {
|
||||
metal_log(METAL_LOG_WARNING, "skipped page size %ld - invalid args\n",
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
_metal.page_sizes[index].page_shift = shift;
|
||||
_metal.page_sizes[index].page_size = size;
|
||||
_metal.page_sizes[index].mmap_flags = mmap_flags;
|
||||
strncpy(_metal.page_sizes[index].path, path, PATH_MAX);
|
||||
_metal.num_page_sizes ++;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "added page size %ld @%s\n", size, path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int metal_init_page_sizes(void)
|
||||
{
|
||||
const int max_sizes = MAX_PAGE_SIZES - 1;
|
||||
long sizes[max_sizes];
|
||||
|
||||
/* Determine system page size. */
|
||||
sizes[0] = getpagesize();
|
||||
if (sizes[0] <= 0) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to get page size\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
_metal.page_size = sizes[0];
|
||||
_metal.page_shift = metal_log2(sizes[0]);
|
||||
metal_add_page_size(_metal.tmp_path, _metal.page_shift, 0);
|
||||
|
||||
#ifdef HAVE_HUGETLBFS_H
|
||||
#ifndef MAP_HUGE_SHIFT
|
||||
/* System does not support multiple huge page sizes. */
|
||||
sizes[0] = gethugepagesize();
|
||||
if (sizes[0] > 0) {
|
||||
metal_add_page_size(hugetlbfs_find_path(),
|
||||
metal_log2(sizes[0]),
|
||||
MAP_HUGETLB);
|
||||
}
|
||||
#else
|
||||
if (gethugepagesize() >= 0) {
|
||||
int i, count;
|
||||
|
||||
/* System supports multiple huge page sizes. */
|
||||
count = gethugepagesizes(sizes, max_sizes);
|
||||
for (i = 0; i < count; i++) {
|
||||
int shift = metal_log2(sizes[i]);
|
||||
if ((shift & MAP_HUGE_MASK) != shift)
|
||||
continue;
|
||||
metal_add_page_size(
|
||||
hugetlbfs_find_path_for_size(sizes[i]),
|
||||
shift, (MAP_HUGETLB |
|
||||
(shift << MAP_HUGE_SHIFT)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Finally sort the resulting array by size. */
|
||||
qsort(_metal.page_sizes, _metal.num_page_sizes,
|
||||
sizeof(struct metal_page_size), metal_pagesize_compare);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
static char sysfs_path[SYSFS_PATH_MAX];
|
||||
const char *tmp_path;
|
||||
unsigned int seed;
|
||||
FILE* urandom;
|
||||
int result;
|
||||
|
||||
/* Determine sysfs mount point. */
|
||||
result = sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path));
|
||||
if (result) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to get sysfs path (%s)\n",
|
||||
strerror(-result));
|
||||
return result;
|
||||
}
|
||||
_metal.sysfs_path = sysfs_path;
|
||||
|
||||
/* Find the temporary directory location. */
|
||||
tmp_path = getenv("TMPDIR");
|
||||
if (!tmp_path)
|
||||
tmp_path = "/tmp";
|
||||
_metal.tmp_path = tmp_path;
|
||||
|
||||
/* Initialize the pseudo-random number generator. */
|
||||
urandom = fopen("/dev/urandom", "r");
|
||||
if (!urandom) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to open /dev/urandom (%s)\n",
|
||||
strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
if (fread(&seed, 1, sizeof(seed), urandom) <= 0) {
|
||||
metal_log(METAL_LOG_DEBUG, "Failed fread /dev/urandom\n");
|
||||
}
|
||||
fclose(urandom);
|
||||
srand(seed);
|
||||
|
||||
result = metal_init_page_sizes();
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
result = metal_linux_bus_init();
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
result = open("/proc/self/pagemap", O_RDONLY | O_CLOEXEC);
|
||||
if (result < 0) {
|
||||
metal_log(METAL_LOG_DEBUG, "Failed pagemap open - %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
_metal.pagemap_fd = result;
|
||||
|
||||
metal_unused(params);
|
||||
|
||||
/* Initialize IRQ handling */
|
||||
metal_linux_irq_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
|
||||
/* Shutdown IRQ handling */
|
||||
metal_linux_irq_shutdown();
|
||||
metal_linux_bus_finish();
|
||||
close(_metal.pagemap_fd);
|
||||
|
||||
}
|
35
source/OpenAMP/libmetal/lib/system/linux/io.h
Normal file
35
source/OpenAMP/libmetal/lib/system/linux/io.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/io.h
|
||||
* @brief Linux specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/linux/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_IO__H__
|
||||
#define __METAL_LINUX_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
#define metal_sys_io_mem_map(...)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_IO__H__ */
|
374
source/OpenAMP/libmetal/lib/system/linux/irq.c
Normal file
374
source/OpenAMP/libmetal/lib/system/linux/irq.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file linux/irq.c
|
||||
* @brief Linux libmetal irq operations
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <metal/device.h>
|
||||
#include <metal/irq.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/alloc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <stdint.h>
|
||||
#include <metal/errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
|
||||
#define MAX_IRQS FD_SETSIZE /**< maximum number of irqs */
|
||||
#define METAL_IRQ_STOP 0xFFFFFFFF /**< stop interrupts handling thread */
|
||||
|
||||
/** IRQ handler descriptor structure */
|
||||
struct metal_irq_hddesc {
|
||||
metal_irq_handler hd; /**< irq handler */
|
||||
struct metal_device *dev; /**< metal device */
|
||||
void *drv_id; /**< id to identify the driver
|
||||
of the irq handler*/
|
||||
struct metal_list list; /**< handler list container */
|
||||
};
|
||||
|
||||
struct metal_irqs_state {
|
||||
struct metal_irq_hddesc hds[MAX_IRQS]; /**< irqs handlers descriptor */
|
||||
signed char irq_reg_stat[MAX_IRQS]; /**< irqs registration statistics.
|
||||
It restore how many handlers have
|
||||
been registered for each IRQ. */
|
||||
|
||||
int irq_reg_fd; /**< irqs registration notification file
|
||||
descriptor */
|
||||
|
||||
metal_mutex_t irq_lock; /**< irq handling lock */
|
||||
|
||||
unsigned int irq_state; /**< global irq handling state */
|
||||
|
||||
pthread_t irq_pthread; /**< irq handling thread id */
|
||||
};
|
||||
|
||||
struct metal_irqs_state _irqs;
|
||||
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
uint64_t val = 1;
|
||||
struct metal_irq_hddesc *hd_desc;
|
||||
struct metal_list *h_node;
|
||||
int ret;
|
||||
|
||||
if ((irq < 0) || (irq >= MAX_IRQS)) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d is larger than the max supported %d.\n",
|
||||
__func__, irq, MAX_IRQS - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((drv_id == NULL) || (hd == NULL)) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
if (_irqs.irq_state == METAL_IRQ_STOP) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: failed. metal IRQ handling has stopped.\n",
|
||||
__func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
metal_list_for_each(&_irqs.hds[irq].list, h_node) {
|
||||
hd_desc = metal_container_of(h_node, struct metal_irq_hddesc, list);
|
||||
|
||||
/* if drv_id already exist reject */
|
||||
if ((hd_desc->drv_id == drv_id) &&
|
||||
((dev == NULL) || (hd_desc->dev == dev))) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d already registered."
|
||||
"Will not register again.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* drv_id not used, get out of metal_list_for_each */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add to the end */
|
||||
hd_desc = metal_allocate_memory(sizeof(struct metal_irq_hddesc));
|
||||
if (hd_desc == NULL) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d cannot allocate mem for drv_id %d.\n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hd_desc->hd = hd;
|
||||
hd_desc->drv_id = drv_id;
|
||||
hd_desc->dev = dev;
|
||||
metal_list_add_tail(&_irqs.hds[irq].list, &hd_desc->list);
|
||||
|
||||
_irqs.irq_reg_stat[irq]++;
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
|
||||
ret = write(_irqs.irq_reg_fd, &val, sizeof(val));
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: write failed IRQ %d\n", __func__, irq);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: registered IRQ %d\n", __func__, irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
uint64_t val = 1;
|
||||
struct metal_irq_hddesc *hd_desc;
|
||||
struct metal_list *h_node;
|
||||
int ret;
|
||||
unsigned int delete_count = 0;
|
||||
|
||||
if ((irq < 0) || (irq >= MAX_IRQS)) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d is larger than the max supported %d.\n",
|
||||
__func__, irq, MAX_IRQS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
if (_irqs.irq_state == METAL_IRQ_STOP) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: failed. metal IRQ handling has stopped.\n", __func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!hd && !drv_id && !dev) {
|
||||
if (0 == _irqs.irq_reg_stat[irq])
|
||||
goto no_entry;
|
||||
|
||||
_irqs.irq_reg_stat[irq] = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Search through handlers */
|
||||
metal_list_for_each(&_irqs.hds[irq].list, h_node) {
|
||||
hd_desc = metal_container_of(h_node, struct metal_irq_hddesc, list);
|
||||
|
||||
if (((hd == NULL) || (hd_desc->hd == hd)) &&
|
||||
((drv_id == NULL) || (hd_desc->drv_id == drv_id)) &&
|
||||
((dev == NULL) || (hd_desc->dev == dev))) {
|
||||
if (_irqs.irq_reg_stat[irq] > 0)
|
||||
_irqs.irq_reg_stat[irq]--;
|
||||
h_node = h_node->prev;
|
||||
metal_list_del(h_node->next);
|
||||
metal_free_memory(hd_desc);
|
||||
delete_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_count)
|
||||
goto out;
|
||||
|
||||
no_entry:
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching entry.\n", __func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
out:
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
ret = write(_irqs.irq_reg_fd, &val, sizeof(val));
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: write failed IRQ %d\n", __func__, irq);
|
||||
}
|
||||
metal_log(METAL_LOG_DEBUG, "%s: unregistered IRQ %d (%d)\n", __func__, irq, delete_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int metal_irq_save_disable()
|
||||
{
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_irq_restore_enable(unsigned flags)
|
||||
{
|
||||
(void)flags;
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
}
|
||||
|
||||
void metal_irq_enable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
void metal_irq_disable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRQ handler
|
||||
* @param[in] args not used. required for pthread.
|
||||
*/
|
||||
static void *metal_linux_irq_handling(void *args)
|
||||
{
|
||||
struct sched_param param;
|
||||
uint64_t val;
|
||||
int ret;
|
||||
int i, j, pfds_total;
|
||||
struct pollfd *pfds;
|
||||
|
||||
(void) args;
|
||||
|
||||
pfds = (struct pollfd *)malloc(MAX_IRQS * sizeof(struct pollfd));
|
||||
if (!pfds) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: failed to allocate irq fds mem.\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
/* Ignore the set scheduler error */
|
||||
ret = sched_setscheduler(0, SCHED_FIFO, ¶m);
|
||||
if (ret) {
|
||||
metal_log(METAL_LOG_WARNING, "%s: Failed to set scheduler: %d.\n",
|
||||
__func__, ret);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
if (_irqs.irq_state == METAL_IRQ_STOP) {
|
||||
/* Killing this IRQ handling thread */
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the fdset */
|
||||
memset(pfds, 0, MAX_IRQS * sizeof(struct pollfd));
|
||||
pfds[0].fd = _irqs.irq_reg_fd;
|
||||
pfds[0].events = POLLIN;
|
||||
for(i = 0, j = 1; i < MAX_IRQS && j < MAX_IRQS; i++) {
|
||||
if (_irqs.irq_reg_stat[i] > 0) {
|
||||
pfds[j].fd = i;
|
||||
pfds[j].events = POLLIN;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
/* Wait for interrupt */
|
||||
ret = poll(pfds, j, -1);
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: poll() failed: %s.\n",
|
||||
__func__, strerror(errno));
|
||||
break;
|
||||
}
|
||||
/* Waken up from interrupt */
|
||||
pfds_total = j;
|
||||
for (i = 0; i < pfds_total; i++) {
|
||||
if ( (pfds[i].fd == _irqs.irq_reg_fd) &&
|
||||
(pfds[i].revents & (POLLIN | POLLRDNORM))) {
|
||||
/* IRQ registration change notification */
|
||||
if (read(pfds[i].fd, (void*)&val, sizeof(uint64_t)) < 0)
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s, read irq fd %d failed.\n",
|
||||
__func__, pfds[i].fd);
|
||||
} else if ((pfds[i].revents & (POLLIN | POLLRDNORM))) {
|
||||
struct metal_irq_hddesc *hd_desc; /**< irq handler descriptor */
|
||||
struct metal_device *dev = NULL; /**< metal device IRQ belongs to */
|
||||
int irq_handled = 0; /**< flag to indicate if irq is handled */
|
||||
struct metal_list *h_node;
|
||||
|
||||
metal_list_for_each(&_irqs.hds[pfds[i].fd].list, h_node) {
|
||||
hd_desc = metal_container_of(h_node, struct metal_irq_hddesc, list);
|
||||
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
if (!dev)
|
||||
dev = hd_desc->dev;
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
|
||||
if ((hd_desc->hd)(pfds[i].fd, hd_desc->drv_id) == METAL_IRQ_HANDLED)
|
||||
irq_handled = 1;
|
||||
}
|
||||
if (irq_handled) {
|
||||
if (dev && dev->bus->ops.dev_irq_ack)
|
||||
dev->bus->ops.dev_irq_ack(dev->bus, dev, i);
|
||||
}
|
||||
} else if (pfds[i].revents) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: poll unexpected. fd %d: %d\n",
|
||||
__func__, pfds[i].fd, pfds[i].revents);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pfds);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief irq handling initialization
|
||||
* @return 0 on sucess, non-zero on failure
|
||||
*/
|
||||
int metal_linux_irq_init()
|
||||
{
|
||||
int ret, irq;
|
||||
|
||||
memset(&_irqs, 0, sizeof(_irqs));
|
||||
|
||||
/* init handlers list for each interrupt in table */
|
||||
for (irq=0; irq < MAX_IRQS; irq++) {
|
||||
metal_list_init(&_irqs.hds[irq].list);
|
||||
}
|
||||
|
||||
_irqs.irq_reg_fd = eventfd(0,0);
|
||||
if (_irqs.irq_reg_fd < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "Failed to create eventfd for IRQ handling.\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
metal_mutex_init(&_irqs.irq_lock);
|
||||
ret = pthread_create(&_irqs.irq_pthread, NULL,
|
||||
metal_linux_irq_handling, NULL);
|
||||
if (ret != 0) {
|
||||
metal_log(METAL_LOG_ERROR, "Failed to create IRQ thread: %d.\n", ret);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief irq handling shutdown
|
||||
*/
|
||||
void metal_linux_irq_shutdown()
|
||||
{
|
||||
int ret;
|
||||
uint64_t val = 1;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s\n", __func__);
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
_irqs.irq_state = METAL_IRQ_STOP;
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
ret = write (_irqs.irq_reg_fd, &val, sizeof(val));
|
||||
if (ret < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "Failed to write.\n");
|
||||
}
|
||||
ret = pthread_join(_irqs.irq_pthread, NULL);
|
||||
if (ret) {
|
||||
metal_log(METAL_LOG_ERROR, "Failed to join IRQ thread: %d.\n", ret);
|
||||
}
|
||||
close(_irqs.irq_reg_fd);
|
||||
metal_mutex_deinit(&_irqs.irq_lock);
|
||||
}
|
19
source/OpenAMP/libmetal/lib/system/linux/irq.h
Normal file
19
source/OpenAMP/libmetal/lib/system/linux/irq.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/irq.h
|
||||
* @brief Linux libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/linux/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_IRQ__H__
|
||||
#define __METAL_LINUX_IRQ__H__
|
||||
|
||||
#endif /* __METAL_LINUX_IRQ__H__ */
|
52
source/OpenAMP/libmetal/lib/system/linux/log.h
Normal file
52
source/OpenAMP/libmetal/lib/system/linux/log.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Linaro nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/log.h
|
||||
* @brief Linux libmetal log handler definition.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#error "Include metal/log.h instead of metal/linux/log.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_LOG__H__
|
||||
#define __METAL_LINUX_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_LOG__H__ */
|
98
source/OpenAMP/libmetal/lib/system/linux/mutex.h
Normal file
98
source/OpenAMP/libmetal/lib/system/linux/mutex.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/mutex.h
|
||||
* @brief Linux mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#error "Include metal/mutex.h instead of metal/linux/mutex.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_MUTEX__H__
|
||||
#define __METAL_LINUX_MUTEX__H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
atomic_int v;
|
||||
} metal_mutex_t;
|
||||
|
||||
/*
|
||||
* METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) }
|
||||
/*
|
||||
* METAL_MUTEX_DEFINE - used for defining and initializing a global or
|
||||
* static singleton mutex
|
||||
*/
|
||||
#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
|
||||
|
||||
static inline int __metal_mutex_cmpxchg(metal_mutex_t *mutex,
|
||||
int exp, int val)
|
||||
{
|
||||
atomic_compare_exchange_strong(&mutex->v, (int *)&exp, val);
|
||||
return exp;
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_store(&mutex->v, 0);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
int val = 0;
|
||||
return atomic_compare_exchange_strong(&mutex->v, &val, 1);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
if (atomic_compare_exchange_strong(&mutex->v, &c, 1))
|
||||
return;
|
||||
if (c != 2)
|
||||
c = atomic_exchange(&mutex->v, 2);
|
||||
while (c != 0) {
|
||||
syscall(SYS_futex, &mutex->v, FUTEX_WAIT, 2, NULL, NULL, 0);
|
||||
c = atomic_exchange(&mutex->v, 2);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
if (atomic_fetch_sub(&mutex->v, 1) != 1) {
|
||||
atomic_store(&mutex->v, 0);
|
||||
syscall(SYS_futex, &mutex->v, FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return atomic_load(&mutex->v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_MUTEX__H__ */
|
119
source/OpenAMP/libmetal/lib/system/linux/shmem.c
Normal file
119
source/OpenAMP/libmetal/lib/system/linux/shmem.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/shmem.c
|
||||
* @brief Linux libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <metal/shmem.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
struct metal_shmem {
|
||||
struct metal_io_region io;
|
||||
metal_phys_addr_t *phys;
|
||||
};
|
||||
|
||||
static void metal_shmem_io_close(struct metal_io_region *io)
|
||||
{
|
||||
metal_unmap(io->virt, io->size);
|
||||
free((void *)io->physmap);
|
||||
}
|
||||
|
||||
static const struct metal_io_ops metal_shmem_io_ops = {
|
||||
NULL, NULL, NULL, NULL, NULL, metal_shmem_io_close
|
||||
};
|
||||
|
||||
static int metal_shmem_try_map(struct metal_page_size *ps, int fd, size_t size,
|
||||
struct metal_io_region **result)
|
||||
{
|
||||
size_t pages, page, phys_size;
|
||||
struct metal_io_region *io;
|
||||
metal_phys_addr_t *phys;
|
||||
uint8_t *virt;
|
||||
void *mem;
|
||||
int error;
|
||||
|
||||
size = metal_align_up(size, ps->page_size);
|
||||
pages = size / ps->page_size;
|
||||
|
||||
error = metal_map(fd, 0, size, 1, ps->mmap_flags, &mem);
|
||||
if (error) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to mmap shmem - %s\n",
|
||||
strerror(-error));
|
||||
return error;
|
||||
}
|
||||
|
||||
error = metal_mlock(mem, size);
|
||||
if (error) {
|
||||
metal_log(METAL_LOG_WARNING, "failed to mlock shmem - %s\n",
|
||||
strerror(-error));
|
||||
}
|
||||
|
||||
phys_size = sizeof(*phys) * pages;
|
||||
phys = malloc(phys_size);
|
||||
if (!phys) {
|
||||
metal_unmap(mem, size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
io = malloc(sizeof(*io));
|
||||
if (!io) {
|
||||
free(phys);
|
||||
metal_unmap(mem, size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (_metal.pagemap_fd < 0) {
|
||||
phys[0] = 0;
|
||||
metal_log(METAL_LOG_WARNING,
|
||||
"shmem - failed to get va2pa mapping. use offset as pa.\n");
|
||||
metal_io_init(io, mem, phys, size, -1, 0, &metal_shmem_io_ops);
|
||||
} else {
|
||||
for (virt = mem, page = 0; page < pages; page++) {
|
||||
size_t offset = page * ps->page_size;
|
||||
error = metal_virt2phys(virt + offset, &phys[page]);
|
||||
if (error < 0)
|
||||
phys[page] = METAL_BAD_OFFSET;
|
||||
}
|
||||
metal_io_init(io, mem, phys, size, ps->page_shift, 0,
|
||||
&metal_shmem_io_ops);
|
||||
}
|
||||
*result = io;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **result)
|
||||
{
|
||||
struct metal_page_size *ps;
|
||||
int fd, error;
|
||||
|
||||
error = metal_shmem_open_generic(name, size, result);
|
||||
if (!error)
|
||||
return error;
|
||||
|
||||
error = metal_open(name, 1);
|
||||
if (error < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "Failed to open shmem file :%s\n", name);
|
||||
return error;
|
||||
}
|
||||
fd = error;
|
||||
|
||||
/* Iterate through page sizes in decreasing order. */
|
||||
metal_for_each_page_size_down(ps) {
|
||||
if (ps->page_size > 2 * size)
|
||||
continue;
|
||||
error = metal_shmem_try_map(ps, fd, size, result);
|
||||
if (!error)
|
||||
break;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return error;
|
||||
}
|
36
source/OpenAMP/libmetal/lib/system/linux/sleep.h
Normal file
36
source/OpenAMP/libmetal/lib/system/linux/sleep.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/sleep.h
|
||||
* @brief linux sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#error "Include metal/sleep.h instead of metal/linux/sleep.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_SLEEP__H__
|
||||
#define __METAL_LINUX_SLEEP__H__
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
return usleep(usec);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_SLEEP__H__ */
|
145
source/OpenAMP/libmetal/lib/system/linux/sys.h
Normal file
145
source/OpenAMP/libmetal/lib/system/linux/sys.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/sys.h
|
||||
* @brief Linux system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/linux/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_LINUX_SYS__H__
|
||||
#define __METAL_LINUX_SYS__H__
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <sysfs/libsysfs.h>
|
||||
#ifdef HAVE_HUGETLBFS_H
|
||||
#include <hugetlbfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define METAL_INVALID_VADDR NULL
|
||||
#define MAX_PAGE_SIZES 32
|
||||
|
||||
struct metal_device;
|
||||
|
||||
/** Structure of shared page or hugepage sized data. */
|
||||
struct metal_page_size {
|
||||
/** Page size. */
|
||||
size_t page_size;
|
||||
|
||||
/** Page shift. */
|
||||
unsigned long page_shift;
|
||||
|
||||
/** Path to hugetlbfs (or tmpfs) mount point. */
|
||||
char path[PATH_MAX];
|
||||
|
||||
/** Flags to use for mmap. */
|
||||
int mmap_flags;
|
||||
};
|
||||
|
||||
/** Structure of linux specific libmetal runtime state. */
|
||||
struct metal_state {
|
||||
|
||||
/** Common (system independent) data. */
|
||||
struct metal_common_state common;
|
||||
|
||||
/** file descriptor for shared data. */
|
||||
int data_fd;
|
||||
|
||||
/** system page size. */
|
||||
unsigned long page_size;
|
||||
|
||||
/** system page shift. */
|
||||
unsigned long page_shift;
|
||||
|
||||
/** sysfs mount point. */
|
||||
const char *sysfs_path;
|
||||
|
||||
/** sysfs mount point. */
|
||||
const char *tmp_path;
|
||||
|
||||
/** available page sizes. */
|
||||
struct metal_page_size page_sizes[MAX_PAGE_SIZES];
|
||||
|
||||
/** number of available page sizes. */
|
||||
int num_page_sizes;
|
||||
|
||||
/** File descriptor for /proc/self/pagemap (or -1). */
|
||||
int pagemap_fd;
|
||||
};
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
extern int metal_linux_bus_init(void);
|
||||
extern void metal_linux_bus_finish(void);
|
||||
|
||||
extern int metal_open(const char *path, int shm);
|
||||
extern int metal_open_unlinked(const char *path, int shm);
|
||||
extern int metal_mktemp(char *template, int fifo);
|
||||
extern int metal_mktemp_unlinked(char *template);
|
||||
|
||||
extern int metal_map(int fd, off_t offset, size_t size, int expand,
|
||||
int flags, void **result);
|
||||
extern int metal_unmap(void *mem, size_t size);
|
||||
extern int metal_mlock(void *mem, size_t size);
|
||||
|
||||
extern void metal_randomize_string(char *template);
|
||||
extern void metal_mktemp_template(char template[PATH_MAX],
|
||||
const char *name);
|
||||
extern int metal_virt2phys(void *addr, unsigned long *phys);
|
||||
|
||||
/**
|
||||
* @brief Read a device tree property of a device
|
||||
*
|
||||
* @param[in] device metal_device of the intended DT node
|
||||
* @param[in] property_name name of the property to be read
|
||||
* @param[out] output output buffer to store read data
|
||||
* @param[in] len number of bytes to be read
|
||||
* @return 0 on success, or -errno on error.
|
||||
*/
|
||||
extern int metal_linux_get_device_property(struct metal_device *device,
|
||||
const char *property_name,
|
||||
void *output, int len);
|
||||
|
||||
#define metal_for_each_page_size_up(ps) \
|
||||
for ((ps) = &_metal.page_sizes[0]; \
|
||||
(ps) <= &_metal.page_sizes[_metal.num_page_sizes - 1]; \
|
||||
(ps)++)
|
||||
|
||||
#define metal_for_each_page_size_down(ps) \
|
||||
for ((ps) = &_metal.page_sizes[_metal.num_page_sizes - 1]; \
|
||||
(ps) >= &_metal.page_sizes[0]; \
|
||||
(ps)--)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LINUX_SYS__H__ */
|
34
source/OpenAMP/libmetal/lib/system/linux/time.c
Normal file
34
source/OpenAMP/libmetal/lib/system/linux/time.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/time.c
|
||||
* @brief Linux libmetal time handling.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <metal/time.h>
|
||||
|
||||
#define NS_PER_S (1000 * 1000 * 1000)
|
||||
|
||||
unsigned long long metal_get_timestamp(void)
|
||||
{
|
||||
unsigned long long t = 0;
|
||||
struct timespec tp;
|
||||
int r;
|
||||
|
||||
r = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
if (r == -1) {
|
||||
metal_log(METAL_LOG_ERROR,"clock_gettime failed!\n");
|
||||
return t;
|
||||
} else {
|
||||
t = tp.tv_sec * (NS_PER_S);
|
||||
t += tp.tv_nsec;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
288
source/OpenAMP/libmetal/lib/system/linux/utilities.c
Normal file
288
source/OpenAMP/libmetal/lib/system/linux/utilities.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file utils.c
|
||||
* @brief Linux libmetal utility functions.
|
||||
*/
|
||||
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
/**
|
||||
* @brief Open (or create) a file.
|
||||
*
|
||||
* This function opens or creates a file with read/write permissions and the
|
||||
* O_CLOEXEC flag set.
|
||||
*
|
||||
* @param[in] path File path to open.
|
||||
* @param[in] shm Open shared memory (via shm_open) if non-zero.
|
||||
* @return File descriptor.
|
||||
*/
|
||||
int metal_open(const char *path, int shm)
|
||||
{
|
||||
const int flags = O_RDWR | O_CREAT | O_CLOEXEC;
|
||||
const int mode = S_IRUSR | S_IWUSR;
|
||||
int fd;
|
||||
|
||||
if (!path || !strlen(path))
|
||||
return -EINVAL;
|
||||
|
||||
fd = shm ? shm_open(path, flags, mode) : open(path, flags, mode);
|
||||
return fd < 0 ? -errno : fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Open (or create) and unlink a file.
|
||||
*
|
||||
* This function opens or creates a file with read/write permissions and the
|
||||
* O_CLOEXEC flag set. This file is then unlinked to ensure that it is removed
|
||||
* when the last reference to the file is dropped. This ensures that libmetal
|
||||
* shared maps are released appropriately once all users of the shared data
|
||||
* exit.
|
||||
*
|
||||
* @param[in] path File path to open.
|
||||
* @param[in] shm Open shared memory (via shm_open) if non-zero.
|
||||
* @return File descriptor.
|
||||
*/
|
||||
int metal_open_unlinked(const char *path, int shm)
|
||||
{
|
||||
int fd, error;
|
||||
|
||||
fd = metal_open(path, shm);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
error = shm ? shm_unlink(path) : unlink(path);
|
||||
error = error < 0 ? -errno : 0;
|
||||
if (error)
|
||||
close(fd);
|
||||
|
||||
return error ? error : fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Randomize a string.
|
||||
*
|
||||
* This function randomizes the contents of a string.
|
||||
*
|
||||
* @param[in] template String to be randomized.
|
||||
*/
|
||||
void metal_randomize_string(char *template)
|
||||
{
|
||||
const char *chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789-=";
|
||||
while (*template) {
|
||||
*template++ = chars[rand() % 64];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a file name template suitable for use with metal_mktemp.
|
||||
*
|
||||
* @param[out] template Template string to be filled in.
|
||||
* @param[in] name Module/user identifier used as part of the
|
||||
* generated template.
|
||||
*/
|
||||
void metal_mktemp_template(char template[PATH_MAX], const char *name)
|
||||
{
|
||||
snprintf(template, PATH_MAX, "%s/metal-%s-XXXXXX",
|
||||
_metal.tmp_path, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a temporary file or fifo.
|
||||
*
|
||||
* This function creates a temporary file or fifo, and sets the O_CLOEXEC flag
|
||||
* on it.
|
||||
*
|
||||
* @param[in] template File name template (the last 6 characters must
|
||||
* be XXXXXX per mkstemp requirements).
|
||||
* @param[in] fifo Non-zero to create a FIFO instead of a regular
|
||||
* file.
|
||||
* @return File descriptor.
|
||||
*/
|
||||
int metal_mktemp(char *template, int fifo)
|
||||
{
|
||||
const int mode = S_IRUSR | S_IWUSR;
|
||||
int result, len, flags;
|
||||
char *suffix;
|
||||
|
||||
if (!template)
|
||||
return -EINVAL;
|
||||
|
||||
len = strlen(template);
|
||||
suffix = &template[len - 6];
|
||||
if (len < 6 || strcmp(suffix, "XXXXXX")) {
|
||||
metal_log(METAL_LOG_ERROR, "template %s has no trailing pattern\n",
|
||||
template);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = (fifo
|
||||
? O_RDONLY | O_NONBLOCK | O_CLOEXEC
|
||||
: O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC);
|
||||
|
||||
for (;;) {
|
||||
metal_randomize_string(suffix);
|
||||
if (fifo) {
|
||||
result = mkfifo(template, mode);
|
||||
if (result < 0) {
|
||||
if (errno == EEXIST)
|
||||
continue;
|
||||
metal_log(METAL_LOG_ERROR, "mkfifo(%s) failed (%s)\n",
|
||||
template, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
result = open(template, flags, mode);
|
||||
if (result < 0) {
|
||||
if (fifo)
|
||||
unlink(template);
|
||||
if (errno == EEXIST)
|
||||
continue;
|
||||
metal_log(METAL_LOG_ERROR, "open() failed (%s)\n",
|
||||
strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Open (or create) and unlink a temporary file.
|
||||
*
|
||||
* This function creates a temporary file, and sets the O_CLOEXEC flag on it.
|
||||
* O_CLOEXEC flag set. This file is then unlinked to ensure that it is removed
|
||||
* when the last reference to the file is dropped. This ensures that libmetal
|
||||
* shared maps are released appropriately once all users of the shared data
|
||||
* exit.
|
||||
*
|
||||
* @param[in] template File name template (the last 6 characters must
|
||||
* be XXXXXX per mkstemp requirements).
|
||||
* @return File descriptor.
|
||||
*/
|
||||
int metal_mktemp_unlinked(char *template)
|
||||
{
|
||||
int fd, error;
|
||||
|
||||
fd = metal_mktemp(template, 0);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
error = unlink(template) < 0 ? -errno : 0;
|
||||
if (error)
|
||||
close(fd);
|
||||
|
||||
return error ? error : fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Map a segment of a file/device.
|
||||
*
|
||||
* This function maps a segment of a file or device into the process address
|
||||
* space, after optionally expanding the file if necessary. If required, the
|
||||
* file is expanded to hold the requested map area. This is done under and
|
||||
* advisory lock, and therefore the called must not have an advisory lock on
|
||||
* the file being mmapped.
|
||||
*
|
||||
* @param[in] fd File descriptor to map.
|
||||
* @param[in] offset Offset in file to map.
|
||||
* @param[in] size Size of region to map.
|
||||
* @param[in] expand Allow file expansion via ftruncate if non-zero.
|
||||
* @param[in] flags Flags for mmap(), MAP_SHARED included implicitly.
|
||||
* @param[out] result Returned pointer to new memory map.
|
||||
* @return 0 on success, or -errno on error.
|
||||
*/
|
||||
int metal_map(int fd, off_t offset, size_t size, int expand, int flags,
|
||||
void **result)
|
||||
{
|
||||
int prot = PROT_READ | PROT_WRITE, error;
|
||||
void *mem;
|
||||
|
||||
flags |= MAP_SHARED;
|
||||
|
||||
if (fd < 0) {
|
||||
fd = -1;
|
||||
flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
} else if (expand) {
|
||||
off_t reqsize = offset + size;
|
||||
struct stat stat;
|
||||
|
||||
error = flock(fd, LOCK_EX) < 0 ? -errno : 0;
|
||||
if (!error)
|
||||
error = fstat(fd, &stat);
|
||||
if (!error && stat.st_size < reqsize)
|
||||
error = ftruncate(fd, reqsize);
|
||||
if (!error)
|
||||
flock(fd, LOCK_UN);
|
||||
if (error)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
mem = mmap(NULL, size, prot, flags, fd, offset);
|
||||
if (mem == MAP_FAILED)
|
||||
return -errno;
|
||||
*result = mem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unmap a segment of the process address space.
|
||||
*
|
||||
* This function unmaps a segment of the process address space.
|
||||
*
|
||||
* @param[in] mem Segment to unmap.
|
||||
* @param[in] size Size of region to unmap.
|
||||
* @return 0 on success, or -errno on error.
|
||||
*/
|
||||
int metal_unmap(void *mem, size_t size)
|
||||
{
|
||||
return munmap(mem, size) < 0 ? -errno : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock in a region of the process address space.
|
||||
*
|
||||
* @param[in] mem Pointer to start of region.
|
||||
* @param[in] size Size of region.
|
||||
* @return 0 on success, or -errno on error.
|
||||
*/
|
||||
int metal_mlock(void *mem, size_t size)
|
||||
{
|
||||
return mlock(mem, size) ? -errno : 0;
|
||||
}
|
||||
|
||||
int metal_virt2phys(void *addr, unsigned long *phys)
|
||||
{
|
||||
off_t offset;
|
||||
uint64_t entry;
|
||||
int error;
|
||||
|
||||
if (_metal.pagemap_fd < 0)
|
||||
return -ENOSYS;
|
||||
|
||||
offset = ((uintptr_t)addr >> _metal.page_shift) * sizeof(entry);
|
||||
error = pread(_metal.pagemap_fd, &entry, sizeof(entry), offset);
|
||||
if (error < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "failed pagemap pread (offset %llx) - %s\n",
|
||||
(unsigned long long)offset, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Check page present and not swapped. */
|
||||
if ((entry >> 62) != 2) {
|
||||
metal_log(METAL_LOG_ERROR, "pagemap page not present, %llx -> %llx\n",
|
||||
(unsigned long long)offset, (unsigned long long)entry);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
*phys = (entry & ((1ULL << 54) - 1)) << _metal.page_shift;
|
||||
return 0;
|
||||
}
|
25
source/OpenAMP/libmetal/lib/system/zephyr/CMakeLists.txt
Normal file
25
source/OpenAMP/libmetal/lib/system/zephyr/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
collect (PROJECT_LIB_HEADERS alloc.h)
|
||||
collect (PROJECT_LIB_HEADERS assert.h)
|
||||
collect (PROJECT_LIB_HEADERS cache.h)
|
||||
collect (PROJECT_LIB_HEADERS condition.h)
|
||||
collect (PROJECT_LIB_HEADERS io.h)
|
||||
collect (PROJECT_LIB_HEADERS irq.h)
|
||||
collect (PROJECT_LIB_HEADERS log.h)
|
||||
collect (PROJECT_LIB_HEADERS mutex.h)
|
||||
collect (PROJECT_LIB_HEADERS sleep.h)
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES alloc.c)
|
||||
collect (PROJECT_LIB_SOURCES condition.c)
|
||||
collect (PROJECT_LIB_SOURCES device.c)
|
||||
collect (PROJECT_LIB_SOURCES init.c)
|
||||
collect (PROJECT_LIB_SOURCES irq.c)
|
||||
collect (PROJECT_LIB_SOURCES log.c)
|
||||
collect (PROJECT_LIB_SOURCES shmem.c)
|
||||
collect (PROJECT_LIB_SOURCES time.c)
|
||||
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
add_subdirectory(${PROJECT_MACHINE})
|
||||
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
28
source/OpenAMP/libmetal/lib/system/zephyr/alloc.c
Normal file
28
source/OpenAMP/libmetal/lib/system/zephyr/alloc.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/alloc.c
|
||||
* @brief Zephyr libmetal memory allocation handling.
|
||||
*/
|
||||
|
||||
#include <metal/alloc.h>
|
||||
#include <metal/compiler.h>
|
||||
|
||||
#if (CONFIG_HEAP_MEM_POOL_SIZE <= 0)
|
||||
|
||||
void* metal_weak metal_zephyr_allocate_memory(unsigned int size)
|
||||
{
|
||||
(void)size;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void metal_weak metal_zephyr_free_memory(void *ptr)
|
||||
{
|
||||
(void)ptr;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HEAP_MEM_POOL_SIZE */
|
57
source/OpenAMP/libmetal/lib/system/zephyr/alloc.h
Normal file
57
source/OpenAMP/libmetal/lib/system/zephyr/alloc.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/alloc.h
|
||||
* @brief zephyr libmetal memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/zephyr/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_ALLOC__H__
|
||||
#define __METAL_ZEPHYR_ALLOC__H__
|
||||
|
||||
#include <kernel.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return k_malloc(size);
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
k_free(ptr);
|
||||
}
|
||||
#else
|
||||
|
||||
void *metal_zephyr_allocate_memory(unsigned int size);
|
||||
void metal_zephyr_free_memory(void *ptr);
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return metal_zephyr_allocate_memory(size);
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
metal_zephyr_free_memory(ptr);
|
||||
}
|
||||
#endif /* CONFIG_HEAP_MEM_POOL_SIZE */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ZEPHYR_ALLOC__H__ */
|
28
source/OpenAMP/libmetal/lib/system/zephyr/assert.h
Normal file
28
source/OpenAMP/libmetal/lib/system/zephyr/assert.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief Zephyr assertion support.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/zephyr/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_ASSERT__H__
|
||||
#define __METAL_ZEPHYR_ASSERT__H__
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for Zephyr-based applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) __ASSERT_NO_MSG(cond)
|
||||
|
||||
#endif /* __METAL_ZEPHYR_ASSERT__H__ */
|
||||
|
42
source/OpenAMP/libmetal/lib/system/zephyr/cache.h
Normal file
42
source/OpenAMP/libmetal/lib/system/zephyr/cache.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/cache.h
|
||||
* @brief Zephyr cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/zephyr/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_CACHE__H__
|
||||
#define __METAL_ZEPHYR_CACHE__H__
|
||||
|
||||
#include <cache.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
sys_cache_flush((vaddr_t) addr, len);
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ZEPHYR_CACHE__H__ */
|
49
source/OpenAMP/libmetal/lib/system/zephyr/condition.c
Normal file
49
source/OpenAMP/libmetal/lib/system/zephyr/condition.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/condition.c
|
||||
* @brief Zephyr libmetal condition variable handling.
|
||||
*/
|
||||
|
||||
#include <metal/condition.h>
|
||||
#include <metal/irq.h>
|
||||
|
||||
extern void metal_generic_default_poll(void);
|
||||
|
||||
int metal_condition_wait(struct metal_condition *cv,
|
||||
metal_mutex_t *m)
|
||||
{
|
||||
metal_mutex_t *tmpm = 0;
|
||||
int v;
|
||||
unsigned int flags;
|
||||
|
||||
/* Check if the mutex has been acquired */
|
||||
if (!cv || !m || !metal_mutex_is_acquired(m))
|
||||
return -EINVAL;
|
||||
|
||||
if (!atomic_compare_exchange_strong(&cv->m, &tmpm, m)) {
|
||||
if (m != tmpm)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v = atomic_load(&cv->v);
|
||||
|
||||
/* Release the mutex first. */
|
||||
metal_mutex_release(m);
|
||||
do {
|
||||
flags = metal_irq_save_disable();
|
||||
if (atomic_load(&cv->v) != v) {
|
||||
metal_irq_restore_enable(flags);
|
||||
break;
|
||||
}
|
||||
metal_generic_default_poll();
|
||||
metal_irq_restore_enable(flags);
|
||||
} while(1);
|
||||
/* Acquire the mutex again. */
|
||||
metal_mutex_acquire(m);
|
||||
return 0;
|
||||
}
|
67
source/OpenAMP/libmetal/lib/system/zephyr/condition.h
Normal file
67
source/OpenAMP/libmetal/lib/system/zephyr/condition.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/condition.h
|
||||
* @brief Zephyr condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/generic/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_CONDITION__H__
|
||||
#define __METAL_ZEPHYR_CONDITION__H__
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <metal/atomic.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int v; /**< condition variable value. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
cv->m = NULL;
|
||||
atomic_init(&cv->v, 0);
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
if (!cv)
|
||||
return -EINVAL;
|
||||
|
||||
/** wake up waiters if there are any. */
|
||||
atomic_fetch_add(&cv->v, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
return metal_condition_signal(cv);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ZEPHYR_CONDITION__H__ */
|
@@ -0,0 +1,5 @@
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
22
source/OpenAMP/libmetal/lib/system/zephyr/cortexm/sys.c
Normal file
22
source/OpenAMP/libmetal/lib/system/zephyr/cortexm/sys.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/qemu_cortex_m3/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
__asm__ __volatile__("wfi");
|
||||
}
|
27
source/OpenAMP/libmetal/lib/system/zephyr/cortexm/sys.h
Normal file
27
source/OpenAMP/libmetal/lib/system/zephyr/cortexm/sys.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/qemu_cortex_m3/sys.h
|
||||
* @brief Zephyr QEMU Cortex M3 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ZEPHYR_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_CORTEXM_SYS__H__
|
||||
#define __METAL_ZEPHYR_CORTEXM_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ZEPHYR_CORTEXM_SYS__H__ */
|
36
source/OpenAMP/libmetal/lib/system/zephyr/device.c
Normal file
36
source/OpenAMP/libmetal/lib/system/zephyr/device.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/device.c
|
||||
* @brief Zephyr libmetal device definitions.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_generic_dev_sys_open(struct metal_device *dev)
|
||||
{
|
||||
metal_unused(dev);
|
||||
|
||||
/* Since Zephyr runs bare-metal there is no mapping that needs to be
|
||||
* done of IO regions
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct metal_bus metal_generic_bus = {
|
||||
.name = "generic",
|
||||
.ops = {
|
||||
.bus_close = NULL,
|
||||
.dev_open = metal_generic_dev_open,
|
||||
.dev_close = NULL,
|
||||
.dev_irq_ack = NULL,
|
||||
.dev_dma_map = NULL,
|
||||
.dev_dma_unmap = NULL,
|
||||
},
|
||||
};
|
27
source/OpenAMP/libmetal/lib/system/zephyr/init.c
Normal file
27
source/OpenAMP/libmetal/lib/system/zephyr/init.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/init.c
|
||||
* @brief Zephyr libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
metal_bus_register(&metal_generic_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
metal_bus_unregister(&metal_generic_bus);
|
||||
}
|
55
source/OpenAMP/libmetal/lib/system/zephyr/io.h
Normal file
55
source/OpenAMP/libmetal/lib/system/zephyr/io.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/io.h
|
||||
* @brief Zephyr specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/zephyr/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_IO__H__
|
||||
#define __METAL_ZEPHYR_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief memory mapping for an I/O region
|
||||
*/
|
||||
static inline void metal_sys_io_mem_map(struct metal_io_region *io)
|
||||
{
|
||||
metal_unused(io);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief memory mapping
|
||||
*/
|
||||
static inline void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
metal_unused(pa);
|
||||
metal_unused(size);
|
||||
metal_unused(flags);
|
||||
|
||||
return va;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ZEPHYR_IO__H__ */
|
280
source/OpenAMP/libmetal/lib/system/zephyr/irq.c
Normal file
280
source/OpenAMP/libmetal/lib/system/zephyr/irq.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/irq.c
|
||||
* @brief Zephyr libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <metal/irq.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/alloc.h>
|
||||
#include <irq.h>
|
||||
|
||||
/** IRQ handlers descriptor structure */
|
||||
struct metal_irq_hddesc {
|
||||
metal_irq_handler hd; /**< irq handler */
|
||||
void *drv_id; /**< id to identify the driver
|
||||
of the irq handler */
|
||||
struct metal_device *dev; /**< device identifier */
|
||||
struct metal_list node; /**< node on irq handlers list */
|
||||
};
|
||||
|
||||
/** IRQ descriptor structure */
|
||||
struct metal_irq_desc {
|
||||
int irq; /**< interrupt number */
|
||||
struct metal_list hdls; /**< interrupt handlers */
|
||||
struct metal_list node; /**< node on irqs list */
|
||||
};
|
||||
|
||||
/** IRQ state structure */
|
||||
struct metal_irqs_state {
|
||||
struct metal_list irqs; /**< interrupt descriptors */
|
||||
metal_mutex_t irq_lock; /**< access lock */
|
||||
};
|
||||
|
||||
static struct metal_irqs_state _irqs = {
|
||||
.irqs = METAL_INIT_LIST(_irqs.irqs),
|
||||
.irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock),
|
||||
};
|
||||
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p = NULL;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
struct metal_list *node;
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((drv_id == NULL) || (hd == NULL)) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node;
|
||||
|
||||
/* Check if drv_id already exist */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
/* if drv_id already exist reject */
|
||||
if ((hdl_p->drv_id == drv_id) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d already registered."
|
||||
"Will not register again.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* irq found and drv_id not used, get out of metal_list_for_each */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Either need to add handler to an existing list or to a new one */
|
||||
hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc));
|
||||
if (hdl_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d cannot allocate mem for drv_id %d.\n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hdl_p->hd = hd;
|
||||
hdl_p->drv_id = drv_id;
|
||||
hdl_p->dev = dev;
|
||||
|
||||
/* interrupt already registered, add handler to existing list*/
|
||||
if ((irq_p != NULL) && (irq_p->irq == irq)) {
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interrupt was not already registered, add */
|
||||
irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc));
|
||||
if (irq_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
irq_p->irq = irq;
|
||||
metal_list_init(&irq_p->hdls);
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&_irqs.irqs, &irq_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for metal_irq_unregister() */
|
||||
static void metal_irq_delete_node(struct metal_list *node, void *p_to_free)
|
||||
{
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
irq_flags_save=metal_irq_save_disable();
|
||||
metal_list_del(node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
metal_free_memory(p_to_free);
|
||||
}
|
||||
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p;
|
||||
struct metal_list *node;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node, *h_prenode;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
unsigned int delete_count = 0;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n",
|
||||
__func__, irq);
|
||||
|
||||
/* Search through handlers */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
if (((hd == NULL) || (hdl_p->hd == hd)) &&
|
||||
((drv_id == NULL) || (hdl_p->drv_id == drv_id)) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: unregister hd=%p drv_id=%p dev=%p\n",
|
||||
__func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev);
|
||||
h_prenode = h_node->prev;
|
||||
metal_irq_delete_node(h_node, hdl_p);
|
||||
h_node = h_prenode;
|
||||
delete_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* we did not find any handler to delete */
|
||||
if (!delete_count) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n",
|
||||
__func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
|
||||
/* if interrupt handlers list is empty, unregister interrupt */
|
||||
if (metal_list_is_empty(&irq_p->hdls)) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: handlers list empty, unregister interrupt\n",
|
||||
__func__);
|
||||
metal_irq_delete_node(node, irq_p);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
unsigned int metal_irq_save_disable(void)
|
||||
{
|
||||
return irq_lock();
|
||||
}
|
||||
|
||||
void metal_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
irq_unlock(flags);
|
||||
}
|
||||
|
||||
void metal_irq_enable(unsigned int vector)
|
||||
{
|
||||
irq_enable(vector);
|
||||
}
|
||||
|
||||
void metal_irq_disable(unsigned int vector)
|
||||
{
|
||||
irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default handler
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_irq_desc *irq_p;
|
||||
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if ((unsigned int)irq_p->irq == vector) {
|
||||
struct metal_list *h_node;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
(hdl_p->hd)(vector, hdl_p->drv_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
source/OpenAMP/libmetal/lib/system/zephyr/irq.h
Normal file
34
source/OpenAMP/libmetal/lib/system/zephyr/irq.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file zephyr/irq.c
|
||||
* @brief Zephyr libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/zephyr/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_ZEPHYR_IRQ__H__
|
||||
#define __METAL_ZEPHYR_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief default interrupt handler
|
||||
* @param[in] vector interrupt vector
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ZEPHYR_IRQ__H__ */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user