149 lines
2.9 KiB
C
149 lines
2.9 KiB
C
/*
|
|
* 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;
|
|
|
|
metal_asm volatile(" mfs %0, rmsr\n"
|
|
" msrclr r0, %1\n"
|
|
: "=r"(state)
|
|
: "i"(MSR_IE)
|
|
: "memory");
|
|
|
|
return state &= MSR_IE;
|
|
}
|
|
|
|
void sys_irq_restore_enable(unsigned int flags)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
if (flags)
|
|
metal_asm volatile(" msrset %0, %1\n"
|
|
: "=r"(tmp)
|
|
: "i"(MSR_IE)
|
|
: "memory");
|
|
}
|
|
|
|
#else /* XPAR_MICROBLAZE_USE_MSR_INSTR == 0 */
|
|
unsigned int sys_irq_save_disable(void)
|
|
{
|
|
unsigned int tmp, state;
|
|
|
|
metal_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;
|
|
}
|
|
|
|
void sys_irq_restore_enable(unsigned int flags)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
if (flags)
|
|
metal_asm volatile(" mfs %0, rmsr\n"
|
|
" or %0, %0, %1\n"
|
|
" mts rmsr, %0\n"
|
|
: "=r"(tmp)
|
|
: "r"(flags)
|
|
: "memory");
|
|
}
|
|
#endif /* XPAR_MICROBLAZE_USE_MSR_INSTR */
|
|
|
|
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)
|
|
{
|
|
metal_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;
|
|
}
|