rt-thread/bsp/AE210P/board/ae210p.c

339 lines
9.0 KiB
C

#include <nds32_intrinsic.h>
#include "debug.h"
#include "nds32.h"
#include "cache.h"
#define CACHE_NONE 0
#define CACHE_WRITEBACK 2
#define CACHE_WRITETHROUGH 3
#if (defined(CONFIG_CPU_ICACHE_ENABLE) || defined(CONFIG_CPU_DCACHE_ENABLE))
/* Cacheable */
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
#define CACHE_MODE CACHE_WRITETHROUGH
#else
#define CACHE_MODE CACHE_WRITEBACK
#endif
#else
/* Uncacheable */
#define CACHE_MODE CACHE_NONE
#endif
#define MMU_CTL_MSK \
(MMU_CTL_mskD \
| MMU_CTL_mskNTC0 \
| MMU_CTL_mskNTC1 \
| MMU_CTL_mskNTC2 \
| MMU_CTL_mskNTC3 \
| MMU_CTL_mskTBALCK \
| MMU_CTL_mskMPZIU \
| MMU_CTL_mskNTM0 \
| MMU_CTL_mskNTM1 \
| MMU_CTL_mskNTM2 \
| MMU_CTL_mskNTM3)
/*
* NTC0: CACHE_MODE, NTC1~NTC3: Non-cacheable
* MSC_CFG.ADR24 = 0 : NTM0~NTM3 are mapped to partition 0/0/0/0
* MSC_CFG.ADR24 = 1 : NTM0~NTM3 are mapped to partition 0/1/2/3
*/
#define MMU_CTL_INIT \
(0x0UL << MMU_CTL_offD \
| (CACHE_MODE) << MMU_CTL_offNTC0 \
| 0x0UL << MMU_CTL_offNTC1 \
| 0x0UL << MMU_CTL_offNTC2 \
| 0x0UL << MMU_CTL_offNTC3 \
| 0x0UL << MMU_CTL_offTBALCK \
| 0x0UL << MMU_CTL_offMPZIU \
| 0x0UL << MMU_CTL_offNTM0 \
| 0x0UL << MMU_CTL_offNTM1 \
| 0x0UL << MMU_CTL_offNTM2 \
| 0x0UL << MMU_CTL_offNTM3)
#define MMU_CTL_INIT_ADR24 \
(MMU_CTL_INIT \
| 0x0UL << MMU_CTL_offNTM0 \
| 0x1UL << MMU_CTL_offNTM1 \
| 0x2UL << MMU_CTL_offNTM2 \
| 0x3UL << MMU_CTL_offNTM3)
#define CACHE_CTL_MSK \
(CACHE_CTL_mskIC_EN \
| CACHE_CTL_mskDC_EN \
| CACHE_CTL_mskICALCK \
| CACHE_CTL_mskDCALCK \
| CACHE_CTL_mskDCCWF \
| CACHE_CTL_mskDCPMW)
/* ICache/DCache enable */
#define CACHE_CTL_CACHE_ON \
(0x1UL << CACHE_CTL_offIC_EN \
| 0x1UL << CACHE_CTL_offDC_EN \
| 0x0UL << CACHE_CTL_offICALCK \
| 0x0UL << CACHE_CTL_offDCALCK \
| 0x1UL << CACHE_CTL_offDCCWF \
| 0x1UL << CACHE_CTL_offDCPMW)
/*
* Interrupt priority :
* PIT(IRQ #2): highest priority
* Others: lowest priority
*/
#define PRI1_DEFAULT 0xFFFFFFFF
#define PRI2_DEFAULT 0xFFFFFFFF
/* This must be a leaf function, no child function */
void _nds32_init_mem(void) __attribute__((naked, optimize("Os")));
void _nds32_init_mem(void)
{
/* Enable DLM */
__nds32__mtsr(EDLM_BASE | 0x1, NDS32_SR_DLMB);
__nds32__dsb();
}
/*
* Initialize MMU configure and cache ability.
*/
static void mmu_init(void)
{
//#ifndef __NDS32_ISA_V3M__
// unsigned int reg;
//
// /* MMU initialization: NTC0~NTC3, NTM0~NTM3 */
// reg = (__nds32__mfsr(NDS32_SR_MMU_CTL) & ~MMU_CTL_MSK) | MMU_CTL_INIT;
//
// if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskADR24)
// reg = (__nds32__mfsr(NDS32_SR_MMU_CTL) & ~MMU_CTL_MSK) | MMU_CTL_INIT_ADR24;
// else
// reg = (__nds32__mfsr(NDS32_SR_MMU_CTL) & ~MMU_CTL_MSK) | MMU_CTL_INIT;
//
// __nds32__mtsr(reg, NDS32_SR_MMU_CTL);
// __nds32__dsb();
//#endif
}
/*
* Platform specific initialization
*/
static void plf_init(void)
{
/* Set default Hardware interrupts priority */
__nds32__mtsr(PRI1_DEFAULT, NDS32_SR_INT_PRI);
__nds32__mtsr(PRI2_DEFAULT, NDS32_SR_INT_PRI2);
/* Mask all HW interrupts except SWI */
__nds32__mtsr((1 << IRQ_SYS_TICK_VECTOR) | (1 << IRQ_SWI_VECTOR), NDS32_SR_INT_MASK2);
/* Reset the PIT (timers) */
REG32(PIT_INT_EN) = 0; /* disable all timer interrupt */
REG32(PIT_CH_EN) = 0; /* disable all timer */
REG32(PIT_INT_ST) = -1; /* clear pending events */
REG32(PIT_CHNx_LOAD(0)) = 0; /* clean channel 0 reload */
REG32(PIT_CHNx_LOAD(1)) = 0; /* clean channel 1 reload */
REG32(PIT_CHNx_LOAD(2)) = 0; /* clean channel 2 reload */
REG32(PIT_CHNx_LOAD(3)) = 0; /* clean channel 3 reload */
}
/*
* All AE210P hardware initialization
*/
void hardware_init(void)
{
mmu_init(); /* mmu/cache */
plf_init(); /* Perform any platform specific initializations */
#if (defined(CONFIG_CPU_ICACHE_ENABLE) || defined(CONFIG_CPU_DCACHE_ENABLE))
unsigned int reg;
/* Invalid ICache */
nds32_icache_flush();
/* Invalid DCache */
nds32_dcache_invalidate();
/* Enable I/Dcache */
reg = (__nds32__mfsr(NDS32_SR_CACHE_CTL) & ~CACHE_CTL_MSK) | CACHE_CTL_CACHE_ON;
__nds32__mtsr(reg, NDS32_SR_CACHE_CTL);
#endif
}
/********************************
* HAL Level : Interrupt
********************************/
/* 32IVIC without SOC INTC */
/*
* mask/unmask priority >= _irqs_ interrupts
* used in ISR & gie diable
*/
uint32_t hal_intc_irq_mask(int _irqs_)
{
uint32_t prv_msk = __nds32__mfsr(NDS32_SR_INT_MASK2);
if (_irqs_ == -1 )
{
__nds32__mtsr(0, NDS32_SR_INT_MASK2);
}
else if (_irqs_ < 32 )
{
SR_CLRB32(NDS32_SR_INT_MASK2,_irqs_);
}
else
{
DEBUG(1,1,"_irqs_:%d, is invalid!\r\n",_irqs_);
return -1;
}
return prv_msk;
}
void hal_intc_irq_unmask(uint32_t _msk_)
{
__nds32__mtsr( _msk_ , NDS32_SR_INT_MASK2);
}
void hal_intc_irq_clean(int _irqs_)
{
if ( _irqs_ == IRQ_SWI_VECTOR )
{
SR_CLRB32(NDS32_SR_INT_PEND, INT_PEND_offSWI);
}
else
{
/* PEND2 is W1C */
SR_SETB32(NDS32_SR_INT_PEND2,_irqs_);
}
}
void hal_intc_irq_clean_all()
{
__nds32__mtsr(-1,NDS32_SR_INT_PEND2);
}
void hal_intc_irq_disable(int _irqs_)
{
SR_CLRB32(NDS32_SR_INT_MASK2,_irqs_);
}
void hal_intc_irq_disable_all()
{
__nds32__mtsr(0x0,NDS32_SR_INT_MASK2);
}
void hal_intc_irq_enable(int _irqs_)
{
SR_SETB32(NDS32_SR_INT_MASK2,_irqs_);
}
void hal_intc_irq_set_priority( uint32_t _prio1_, uint32_t _prio2_ )
{
__nds32__mtsr(_prio1_, NDS32_SR_INT_PRI);
__nds32__mtsr(_prio2_, NDS32_SR_INT_PRI2);
}
void hal_intc_irq_config(uint8_t _irq_, uint8_t _edge_, uint8_t _falling_){}
void hal_intc_swi_enable()
{
//SR_SETB32(NDS32_SR_INT_MASK,16);
SR_SETB32(NDS32_SR_INT_MASK2,IRQ_SWI_VECTOR);
}
void hal_intc_swi_disable()
{
SR_CLRB32(NDS32_SR_INT_MASK2,IRQ_SWI_VECTOR);
}
void hal_intc_swi_clean()
{
SR_CLRB32(NDS32_SR_INT_PEND, INT_PEND_offSWI);
}
void hal_intc_swi_trigger()
{
SR_SETB32(NDS32_SR_INT_PEND,INT_PEND_offSWI);
}
uint32_t hal_intc_get_all_pend()
{
return __nds32__mfsr(NDS32_SR_INT_PEND2);
}
/********************************
* TIMER HAL Function
********************************/
static const uint8_t timer_irq[4] = {IRQ_PIT_VECTOR, IRQ_PIT_VECTOR, IRQ_PIT_VECTOR, IRQ_PIT_VECTOR};
uint32_t hal_timer_irq_mask(uint32_t _tmr_ )
{
return hal_intc_irq_mask(timer_irq[_tmr_-1]);
}
void hal_timer_irq_unmask(uint32_t _msk_ )
{
hal_intc_irq_unmask(_msk_);
}
void hal_timer_irq_clear(uint32_t _tmr_ )
{
/* Clean IP pending, W1C */
#ifndef CONFIG_TX_DEMO
REG32(PIT_INT_ST) = (0x1 << (5*(_tmr_-1)));
#endif
hal_intc_irq_clean(timer_irq[_tmr_-1]);
}
void hal_timer_set_period(uint32_t _tmr_, uint32_t _period_ )
{
REG32(PIT_CHNx_LOAD(_tmr_-1)) = _period_;
//REG32(PIT_CHNx_COUNT(_tmr_-1))= _period_;
}
void hal_timer_irq_control(uint32_t _tmr_, uint32_t enable )
{
if (enable)
REG32(PIT_INT_EN) = REG32(PIT_INT_EN) | (0x1 << (5*(_tmr_-1)));
else
REG32(PIT_INT_EN) = REG32(PIT_INT_EN) & ~(0x1 << (5*(_tmr_-1)));
}
void hal_timer_set_upward(uint32_t _tmr_ ,uint32_t up)
{
if ( up )
DEBUG(1,1,"PIT Timer only support downward!\r\n");
}
void hal_timer_start(uint32_t _tmr_)
{
/* config channel mode */
/* 32 bits timer, APB clock */
REG32(PIT_CHNx_CTL(_tmr_-1)) = ( PIT_CH_CTL_APBCLK | PIT_CH_CTL_TMR32 );
/* enable channel */
REG32(PIT_CH_EN) = REG32(PIT_CH_EN) | (0x1 << (5*(_tmr_-1)));
}
void hal_timer_stop(uint32_t _tmr_ )
{
REG32(PIT_CH_EN) = REG32(PIT_CH_EN) & ~(0x1 << (5*(_tmr_-1)));
}
uint32_t hal_timer_read(uint32_t _tmr_ )
{
/* By default, timer would decrease from load value to 0 */
return REG32( PIT_CHNx_LOAD(_tmr_-1) ) - REG32( PIT_CHNx_COUNT(_tmr_-1) );
}
uint32_t hal_timer_count_read(uint32_t _tmr_ )
{
return REG32( PIT_CHNx_COUNT(_tmr_-1) );
}
uint32_t hal_timer_irq_status(uint32_t _tmr_)
{
/* return PIT int status */
/* PIT need #channel & #timer */
/* just return all int status */
return REG32(PIT_INT_ST);
}