diff options
| author | Bernard Xiong <[email protected]> | 2016-04-24 19:34:41 +0800 |
|---|---|---|
| committer | Bernard Xiong <[email protected]> | 2016-04-24 19:34:41 +0800 |
| commit | 255f8b7c3447b3adf06f1fb998d9861cde81558b (patch) | |
| tree | d2763802f1e23daa0a5878dc2abea10c4690d3b7 /libcpu | |
| parent | bef87f8aff8ed2518c7d70e4e6fe7a50de2364d4 (diff) | |
[BSP] Add BSP for Ingenic X1000 CPU
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/mips/xburst/SConscript | 11 | ||||
| -rw-r--r-- | libcpu/mips/xburst/cache.c | 118 | ||||
| -rw-r--r-- | libcpu/mips/xburst/cache.h | 62 | ||||
| -rw-r--r-- | libcpu/mips/xburst/cache_gcc.S | 42 | ||||
| -rw-r--r-- | libcpu/mips/xburst/context_gcc.S | 146 | ||||
| -rw-r--r-- | libcpu/mips/xburst/cpu.c | 75 | ||||
| -rw-r--r-- | libcpu/mips/xburst/exception.c | 81 | ||||
| -rw-r--r-- | libcpu/mips/xburst/interrupt.c | 249 | ||||
| -rw-r--r-- | libcpu/mips/xburst/mipscfg.c | 358 | ||||
| -rw-r--r-- | libcpu/mips/xburst/stack.c | 103 | ||||
| -rw-r--r-- | libcpu/mips/xburst/stack.h | 28 | ||||
| -rw-r--r-- | libcpu/mips/xburst/start_gcc.S | 150 | ||||
| -rw-r--r-- | libcpu/mips/xburst/x1000.h | 329 |
13 files changed, 1752 insertions, 0 deletions
diff --git a/libcpu/mips/xburst/SConscript b/libcpu/mips/xburst/SConscript new file mode 100644 index 0000000000..0f06c299bb --- /dev/null +++ b/libcpu/mips/xburst/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.S') +CPPPATH = [cwd] + +group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/mips/xburst/cache.c b/libcpu/mips/xburst/cache.c new file mode 100644 index 0000000000..cd37f69993 --- /dev/null +++ b/libcpu/mips/xburst/cache.c @@ -0,0 +1,118 @@ +/* + * File : cache.c + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes +*/ + +#include "../xburst/cache.h" + +#include <board.h> + +#define CACHE_SIZE 16*1024 +#define CACHE_LINE_SIZE 32 +#define KSEG0 0x80000000 + +#define K0_TO_K1() \ +do { \ + unsigned long __k0_addr; \ + \ + __asm__ __volatile__( \ + "la %0, 1f\n\t" \ + "or %0, %0, %1\n\t" \ + "jr %0\n\t" \ + "nop\n\t" \ + "1: nop\n" \ + : "=&r"(__k0_addr) \ + : "r" (0x20000000) ); \ +} while(0) + +#define K1_TO_K0() \ +do { \ + unsigned long __k0_addr; \ + __asm__ __volatile__( \ + "nop;nop;nop;nop;nop;nop;nop\n\t" \ + "la %0, 1f\n\t" \ + "jr %0\n\t" \ + "nop\n\t" \ + "1: nop\n" \ + : "=&r" (__k0_addr)); \ +} while (0) + +#define INVALIDATE_BTB() \ +do { \ + unsigned long tmp; \ + __asm__ __volatile__( \ + ".set mips32\n\t" \ + "mfc0 %0, $16, 7\n\t" \ + "nop\n\t" \ + "ori %0, 2\n\t" \ + "mtc0 %0, $16, 7\n\t" \ + "nop\n\t" \ + ".set mips2\n\t" \ + : "=&r" (tmp)); \ +} while (0) + +#define SYNC_WB() __asm__ __volatile__ ("sync") + +#define cache_op(op,addr) \ + __asm__ __volatile__( \ + " .set noreorder \n" \ + " .set mips32\n\t \n" \ + " cache %0, %1 \n" \ + " .set mips0 \n" \ + " .set reorder" \ + : \ + : "i" (op), "m" (*(unsigned char *)(addr))) + +void __icache_invalidate_all(void) +{ + unsigned int i; + + K0_TO_K1(); + + asm volatile (".set noreorder\n" + ".set mips32\n\t" + "mtc0\t$0,$28\n\t" + "mtc0\t$0,$29\n" + ".set mips0\n" + ".set reorder\n"); + for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE) + cache_op(Index_Store_Tag_I, i); + + K1_TO_K0(); + + INVALIDATE_BTB(); +} + +void __dcache_writeback_all(void) +{ + unsigned int i; + + for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE) + cache_op(Index_Writeback_Inv_D, i); + + SYNC_WB(); +} + +void rt_hw_cache_init(void) +{ + __dcache_writeback_all(); + __icache_invalidate_all(); +} + diff --git a/libcpu/mips/xburst/cache.h b/libcpu/mips/xburst/cache.h new file mode 100644 index 0000000000..c0f8a1f424 --- /dev/null +++ b/libcpu/mips/xburst/cache.h @@ -0,0 +1,62 @@ +/* + * File : cache.h + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes +*/ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +/* + * Cache Operations + */ +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Invalidate_SI 0x02 +#define Index_Writeback_Inv_SD 0x03 +#define Index_Load_Tag_I 0x04 +#define Index_Load_Tag_D 0x05 +#define Index_Load_Tag_SI 0x06 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#define Index_Store_Tag_SI 0x0A +#define Index_Store_Tag_SD 0x0B +#define Create_Dirty_Excl_D 0x0d +#define Create_Dirty_Excl_SD 0x0f +#define Hit_Invalidate_I 0x10 +#define Hit_Invalidate_D 0x11 +#define Hit_Invalidate_SI 0x12 +#define Hit_Invalidate_SD 0x13 +#define Fill 0x14 +#define Hit_Writeback_Inv_D 0x15 +/* 0x16 is unused */ +#define Hit_Writeback_Inv_SD 0x17 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 +/* 0x1a is unused */ +#define Hit_Writeback_SD 0x1b +/* 0x1c is unused */ +/* 0x1e is unused */ +#define Hit_Set_Virtual_SI 0x1e +#define Hit_Set_Virtual_SD 0x1f + +void rt_hw_cache_init(void); + +#endif diff --git a/libcpu/mips/xburst/cache_gcc.S b/libcpu/mips/xburst/cache_gcc.S new file mode 100644 index 0000000000..76552698d0 --- /dev/null +++ b/libcpu/mips/xburst/cache_gcc.S @@ -0,0 +1,42 @@ +/* + * File : cache_init.S + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include "../common/mips.inc" +#include "../common/mipsregs.h" +#include "../common/stackframe.h" + + .text + .set noreorder + + .globl cache_init + .ent cache_init +cache_init: + .set noreorder + mtc0 zero, CP0_TAGLO + move t0, a0 // cache total size + move t1, a1 // cache line size + li t2, 0x80000000 + addu t3, t0, t2 + +_cache_init_loop: + cache 8, 0(t2) // icache_index_store_tag + cache 9, 0(t2) // dcache_index_store_tag + addu t2, t1 + bne t2, t3, _cache_init_loop + nop + + mfc0 t0, CP0_CONFIG + li t1, 0x7 + not t1 + and t0, t0, t1 + or t0, 0x3 // cacheable, noncoherent, write-back, write allocate + mtc0 t0, CP0_CONFIG + + jr ra + nop + + .set reorder + .end cache_init diff --git a/libcpu/mips/xburst/context_gcc.S b/libcpu/mips/xburst/context_gcc.S new file mode 100644 index 0000000000..d018de3da8 --- /dev/null +++ b/libcpu/mips/xburst/context_gcc.S @@ -0,0 +1,146 @@ +/* + * File : context_gcc.S + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + * 2010-09-11 bernard port to Jz4755 + */ +#include "../common/mips.inc" +#include "../common/stackframe.h" +#include "stack.h" + + .section ".text", "ax" + .set noreorder + +/* + * rt_base_t rt_hw_interrupt_disable() + */ + .globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + mfc0 v0, CP0_STATUS + and v1, v0, 0xfffffffe + mtc0 v1, CP0_STATUS + jr ra + nop + +/* + * void rt_hw_interrupt_enable(rt_base_t level) + */ + .globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + mtc0 a0, CP0_STATUS + jr ra + nop + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to) + * a0 --> from + * a1 --> to + */ + .globl rt_hw_context_switch +rt_hw_context_switch: + mtc0 ra, CP0_EPC + SAVE_ALL + + sw sp, 0(a0) /* store sp in preempted tasks TCB */ + lw sp, 0(a1) /* get new task stack pointer */ + + RESTORE_ALL_AND_RET + +/* + * void rt_hw_context_switch_to(rt_uint32 to)/* + * a0 --> to + */ + .globl rt_hw_context_switch_to +rt_hw_context_switch_to: + lw sp, 0(a0) /* get new task stack pointer */ + + RESTORE_ALL_AND_RET + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/* + */ + .globl rt_thread_switch_interrupt_flag + .globl rt_interrupt_from_thread + .globl rt_interrupt_to_thread + .globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + la t0, rt_thread_switch_interrupt_flag + lw t1, 0(t0) + nop + bnez t1, _reswitch + nop + li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */ + sw t1, 0(t0) + la t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */ + sw a0, 0(t0) +_reswitch: + la t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */ + sw a1, 0(t0) + jr ra + nop + + .globl system_dump + +/* + * void rt_hw_context_switch_interrupt_do(rt_base_t flag) + */ + .globl rt_interrupt_enter + .globl rt_interrupt_leave + .globl mips_irq_handle +mips_irq_handle: + SAVE_ALL + + mfc0 t0, CP0_CAUSE + mfc0 t1, CP0_STATUS + and t0, t1 + + andi t0, 0xff00 + beqz t0, spurious_interrupt + nop + + /* let k0 keep the current context sp */ + move k0, sp + /* switch to kernel stack */ + li sp, SYSTEM_STACK + + jal rt_interrupt_enter + nop + jal rt_interrupt_dispatch + nop + jal rt_interrupt_leave + nop + + /* switch sp back to thread's context */ + move sp, k0 + + /* + * if rt_thread_switch_interrupt_flag set, jump to + * rt_hw_context_switch_interrupt_do and don't return + */ + la k0, rt_thread_switch_interrupt_flag + lw k1, 0(k0) + beqz k1, spurious_interrupt + nop + sw zero, 0(k0) /* clear flag */ + nop + + /* + * switch to the new thread + */ + la k0, rt_interrupt_from_thread + lw k1, 0(k0) + nop + sw sp, 0(k1) /* store sp in preempted tasks's TCB */ + + la k0, rt_interrupt_to_thread + lw k1, 0(k0) + nop + lw sp, 0(k1) /* get new task's stack pointer */ + j spurious_interrupt + nop + +spurious_interrupt: + RESTORE_ALL_AND_RET + + .set reorder diff --git a/libcpu/mips/xburst/cpu.c b/libcpu/mips/xburst/cpu.c new file mode 100644 index 0000000000..88137535d9 --- /dev/null +++ b/libcpu/mips/xburst/cpu.c @@ -0,0 +1,75 @@ +/* + * File : cpu.c + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-07-09 Bernard first version + * 2010-09-11 Bernard add CPU reset implementation + */ +#include <rtthread.h> +#include <board.h> + +/** + * @addtogroup Ingenic + */ +/*@{*/ + +/** + * this function will reset CPU + * + */ +void rt_hw_cpu_reset() +{ + /* open the watch-dog */ + REG_WDT_TCSR = WDT_TCSR_EXT_EN; + REG_WDT_TCSR |= WDT_TCSR_PRESCALE_1024; + REG_WDT_TDR = 0x03; + REG_WDT_TCNT = 0x00; + REG_WDT_TCER |= WDT_TCER_TCEN; + + rt_kprintf("reboot system...\n"); + while (1); +} + +/** + * this function will shutdown CPU + * + */ +void rt_hw_cpu_shutdown() +{ + rt_kprintf("shutdown...\n"); + + while (1); +} + +/** + * This function finds the first bit set (beginning with the least significant bit) + * in value and return the index of that bit. + * + * Bits are numbered starting at 1 (the least significant bit). A return value of + * zero from any of these functions means that the argument was zero. + * + * @return return the index of the first bit set. If value is 0, then this function + * shall return 0. + */ +int __rt_ffs(int value) +{ + return __builtin_ffs(value); +} + +/*@}*/ diff --git a/libcpu/mips/xburst/exception.c b/libcpu/mips/xburst/exception.c new file mode 100644 index 0000000000..aebdf704ea --- /dev/null +++ b/libcpu/mips/xburst/exception.c @@ -0,0 +1,81 @@ +/* + * File : exception.c + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include <rtthread.h> +#include <rthw.h> +#include "../common/exception.h" +#include "../common/mipsregs.h" + +/** + * @addtogroup Ingenic + */ +/*@{*/ + +/** + * exception handle table + */ +exception_func_t sys_exception_handlers[33]; + +/** + * setup the exception handle + */ +exception_func_t rt_set_except_vector(int n, exception_func_t func) +{ + exception_func_t old_handler = sys_exception_handlers[n]; + + if ((n == 0) || (n > 32) || (!func)) + { + return 0; + } + + sys_exception_handlers[n] = func; + + return old_handler; +} + +void tlb_refill_handler(void) +{ + rt_kprintf("tlb-miss happens, epc: 0x%08x\n", read_c0_epc()); + rt_hw_cpu_shutdown(); +} + +void cache_error_handler(void) +{ + rt_kprintf("cache exception happens, epc: 0x%08x\n", read_c0_epc()); + rt_hw_cpu_shutdown(); +} + +static void unhandled_exception_handle(pt_regs_t *regs) +{ + rt_kprintf("exception happens, epc: 0x%08x\n", regs->cp0_epc); +} + +void install_default_execpt_handle(void) +{ + rt_int32_t i; + + for (i=0; i<33; i++) + sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle; +} + +/*@}*/ + diff --git a/libcpu/mips/xburst/interrupt.c b/libcpu/mips/xburst/interrupt.c new file mode 100644 index 0000000000..4d39c8f621 --- /dev/null +++ b/libcpu/mips/xburst/interrupt.c @@ -0,0 +1,249 @@ +/* + * File : interrupt.c + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * 2010-07-09 Bernard first version + * 2013-03-29 aozima Modify the interrupt interface implementations. + */ + +#include <rtthread.h> +#include <rthw.h> +#include <board.h> + +#if defined(RT_USING_JZ4770) || defined(RT_USING_JZ4775) || defined(RT_USING_JZ_M150) || defined(RT_USING_JZ_X1000) +#define INTERRUPTS_MAX 64 +#else +#define INTERRUPTS_MAX 32 +#endif + +extern rt_uint32_t rt_interrupt_nest; +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +static struct rt_irq_desc isr_table[INTERRUPTS_MAX]; + +/** + * @addtogroup Ingenic + */ +/*@{*/ + +static void rt_hw_interrupt_handler(int vector, void *param) +{ + rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + rt_int32_t idx; + + rt_memset(isr_table, 0x00, sizeof(isr_table)); + for (idx = 0; idx < INTERRUPTS_MAX; idx ++) + { + isr_table[idx].handler = rt_hw_interrupt_handler; + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + /* mask interrupt */ + __intc_mask_irq(vector); +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + __intc_unmask_irq(vector); +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param handler the interrupt service routine to be installed + * @param param the interrupt service function parameter + * @param name the interrupt name + * @return old handler + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if(vector < INTERRUPTS_MAX) + { + old_handler = isr_table[vector].handler; + +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + + return old_handler; +} + +#if defined(RT_USING_JZ4770) || defined(RT_USING_JZ4775) || defined(RT_USING_JZ_M150) || defined(RT_USING_JZ_X1000) +/* + * fls - find last bit set. + * @word: The word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +rt_inline int fls(int x) +{ + __asm__("clz %0, %1" : "=r" (x) : "r" (x)); + + return 32 - x; +} +#endif + +#include <mipsregs.h> + +void rt_interrupt_dispatch(void *ptreg) +{ + int i; + void *param; + rt_isr_handler_t irq_func; + +#if defined(RT_USING_JZ4770) || defined(RT_USING_JZ4775) || defined(RT_USING_JZ_M150) || defined(RT_USING_JZ_X1000) + int irq = 0, group; + rt_uint32_t intc_ipr0 = 0, intc_ipr1 = 0, vpu_pending = 0; + + rt_uint32_t c0_status, c0_cause; + rt_uint32_t pending_im; + + /* check os timer */ + c0_status = read_c0_status(); + c0_cause = read_c0_cause(); + + pending_im = (c0_cause & ST0_IM) & (c0_status & ST0_IM); + + if (pending_im & CAUSEF_IP3) + { + extern void rt_hw_ost_handler(void); + rt_hw_ost_handler(); + return; + } + + if (pending_im & CAUSEF_IP2) + { + intc_ipr0 = REG_INTC_IPR(0); + intc_ipr1 = REG_INTC_IPR(1); + + if (intc_ipr0) + { + irq = fls(intc_ipr0) - 1; + intc_ipr0 &= ~(1<<irq); + } + else if(intc_ipr1) + { + irq = fls(intc_ipr1) - 1; + intc_ipr1 &= ~(1<<irq); + irq += 32; + } +#ifndef RT_USING_JZ_X1000 /* X1000 has no VPU */ + else + { + __asm__ __volatile__ ( + "mfc0 %0, $13, 0 \n\t" + "nop \n\t" + :"=r"(vpu_pending) + :); + + if(vpu_pending & 0x800) + irq = IRQ_VPU; + else + return; + } +#endif + + if (irq >= INTERRUPTS_MAX) + rt_kprintf("max interrupt, irq=%d\n", irq); + + /* do interrupt */ + irq_func = isr_table[irq].handler; + param = isr_table[irq].param; + (*irq_func)(irq, param); + +#ifdef RT_USING_INTERRUPT_INFO + isr_table[i].counter++; +#endif /* RT_USING_INTERRUPT_INFO */ + + /* ack interrupt */ + __intc_ack_irq(irq); + } + + if (pending_im & CAUSEF_IP0) + rt_kprintf("CAUSEF_IP0\n"); + if (pending_im & CAUSEF_IP1) + rt_kprintf("CAUSEF_IP1\n"); + if (pending_im & CAUSEF_IP4) + rt_kprintf("CAUSEF_IP4\n"); + if (pending_im & CAUSEF_IP5) + rt_kprintf("CAUSEF_IP5\n"); + if (pending_im & CAUSEF_IP6) + rt_kprintf("CAUSEF_IP6\n"); + if (pending_im & CAUSEF_IP7) + rt_kprintf("CAUSEF_IP7\n"); +#else + static rt_uint32_t pending = 0; + + /* the hardware interrupt */ + pending |= REG_INTC_IPR; + if (!pending) return; + + for (i = INTERRUPTS_MAX; i > 0; --i) + { + if ((pending & (1<<i))) + { + pending &= ~(1<<i); + + /* do interrupt */ + irq_func = isr_table[i].handler; + param = isr_table[i].param; + (*irq_func)(i, param); + +#ifdef RT_USING_INTERRUPT_INFO + isr_table[i].counter++; +#endif /* RT_USING_INTERRUPT_INFO */ + + /* ack interrupt */ + __intc_ack_irq(i); + } + } +#endif +} + +/*@}*/ diff --git a/libcpu/mips/xburst/mipscfg.c b/libcpu/mips/xburst/mipscfg.c new file mode 100644 index 0000000000..1e9b0c032f --- /dev/null +++ b/libcpu/mips/xburst/mipscfg.c @@ -0,0 +1,358 @@ +/* + * File : mipscfg.c + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-05-27 swkyer first version + */ +#include <rtthread.h> +#include "../common/mipsregs.h" +#include "../common/mipscfg.h" + +mips32_core_cfg_t g_mips_core = +{ + 16, /* icache_line_size */ + 256, /* icache_lines_per_way */ + 4, /* icache_ways */ + 16, /* dcache_line_size */ + 256, /* dcache_lines_per_way */ + 4, /* dcache_ways */ + 16, /* max_tlb_entries */ +}; + +static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n) +{ + rt_uint16_t rets = 1; + + while (n--) + rets *= b; + + return rets; +} + +/** + * read core attribute + */ +void mips32_cfg_init(void) +{ + rt_uint16_t val; + rt_uint32_t cp0_config1; + + cp0_config1 = read_c0_config(); + if (cp0_config1 & 0x80000000) + { + cp0_config1 = read_c0_config1(); + + val = (cp0_config1 & (7<<22))>>22; + g_mips_core.icache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<19))>>19; + g_mips_core.icache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<16))>>16; + g_mips_core.icache_ways = val + 1; + + val = (cp0_config1 & (7<<13))>>13; + g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<10))>>10; + g_mips_core.dcache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<7))>>7; + g_mips_core.dcache_ways = val + 1; + + val = (cp0_config1 & (0x3F<<25))>>25; + g_mips_core.max_tlb_entries = val + 1; + } +} + +#ifdef RT_USING_FINSH +#include <finsh.h> +static void CP0_status_analyze(unsigned long value) +{ + if(value & (1<<26)) + rt_kprintf(" FR"); + if(value & (1<<23)) + rt_kprintf(" PX"); + if(value & (1<<22)) + rt_kprintf(" BEV"); + if(value & (1<<20)) + rt_kprintf(" SR"); + if(value & (1<<19)) + rt_kprintf(" NMI"); + if(value & (1<<20)) + rt_kprintf(" SR"); + if(value & (0xFF<<8)) + rt_kprintf(" IM:0x%02X", (value >> 8) & 0xFF); + if(value & (1<<7)) + rt_kprintf(" KX"); + if(value & (1<<6)) + rt_kprintf(" SX"); + if(value & (1<<5)) + rt_kprintf(" UX"); + if(value & (0x03<<3)) + rt_kprintf(" KSU:0x%02X", (value >> 3) & 0x03); + if(value & (1<<2)) + rt_kprintf(" ERL"); + if(value & (1<<1)) + rt_kprintf(" EXL"); + if(value & (1<<0)) + rt_kprintf(" IE"); +} + +static void CP0_config0_analyze(unsigned long value) +{ + /* [31] M */ + if(value & (1UL<<31)) + rt_kprintf(" M"); + + /* [15] BE */ + if(value & (1<<15)) + rt_kprintf(" big-endian"); + else + rt_kprintf(" little-endian"); + + /* [14:13] AT */ + { + int AT = (value >> 13) & 0x03; + + if(AT == 0) + { + rt_kprintf(" MIPS32"); + } + else if(AT == 1) + { + rt_kprintf(" MIPS64/A32"); + } + else if(AT == 2) + { + rt_kprintf(" MIPS64/A64"); + } + else + { + rt_kprintf(" unkown"); + } + } + + /* [12:10] AR */ + { + int AR = (value >> 10) & 0x07; + + if(AR == 0) + { + rt_kprintf(" R1"); + } + else if(AR == 1) + { + rt_kprintf(" R2"); + } + else + { + rt_kprintf(" reserve"); + } + } + + /* [3] VI */ + if(value & (1UL<<31)) + rt_kprintf(" VI"); + + /* [2:0] K0 */ + { + int K0 = value & 0x07; + + if(K0 == 2) + { + rt_kprintf(" uncached"); + } + else if(K0 == 3) + { + rt_kprintf(" cacheable"); + } + else + { + rt_kprintf(" K0:reserve"); + } + } +} + +static void CP0_config1_analyze(unsigned long value) +{ + /* [31] M */ + if(value & (1UL<<31)) + rt_kprintf(" M"); + + /* [30:25] MMU size */ + { + int MMU_size = (value >> 25) & 0x3F; + rt_kprintf(" TLB:%d", MMU_size + 1); + } + + /* [24:22] IS, [21:19] IL, [18:16] IA */ + { + int IS = (value >> 22) & 0x07; + int IL = (value >> 19) & 0x07; + int IA = (value >> 16) & 0x07; + + IA = IA + 1; + IS = 64 << IS; + IL = 2 << IL; + rt_kprintf(" Icache-%dKB:%dway*%dset*%dbyte", + (IA*IS*IL) >> 10, IA, IS, IL); + } + + /* [15:13] DS, [12:10] DL, [9:7] DA */ + { + int DS = (value >> 13) & 0x07; + int DL = (value >> 10) & 0x07; + int DA = (value >> 7) & 0x07; + + DA = DA + 1; + DS = 64 << DS; + DL = 2 << DL; + rt_kprintf(" Dcache-%dKB:%dway*%dset*%dbyte", + (DA*DS*DL) >> 10, DA, DS, DL); + } + + /* [6] C2 */ + if(value & (1UL<<6)) + rt_kprintf(" CP2"); + + /* [5] MD */ + if(value & (1UL<<5)) + rt_kprintf(" MDMX-ASE"); + + /* [4] PC */ + if(value & (1UL<<4)) + rt_kprintf(" performa-count"); + + /* [3] WR */ + if(value & (1UL<<3)) + rt_kprintf(" Watch"); + + /* [2] CA */ + if(value & (1UL<<2)) + rt_kprintf(" MIPS16e"); + + /* [1] EP */ + if(value & (1UL<<1)) + rt_kprintf(" EJTAG"); + + /* [0] FP */ + if(value & (1UL<<0)) + rt_kprintf(" FPU"); +} + +static void CP0_config2_analyze(unsigned long value) +{ + /* [31] M */ + if(value & (1UL<<31)) + rt_kprintf(" M"); +} + +static void CP0_config3_analyze(unsigned long value) +{ + /* [31] M */ + if(value & (1UL<<31)) + rt_kprintf(" M"); +} + +static void list_mips(void) +{ + unsigned long value; + unsigned long num = 0; + + rt_kprintf("MIPS coprocessor register:\r\n"); + + rt_kprintf("( 0,0) INDEX : 0x%08X\r\n", read_c0_index()); + rt_kprintf("( 1,0) RANDOM : 0x%08X\r\n", read_c0_random()); + rt_kprintf("( 2,0) ENTRYLO0 : 0x%08X\r\n", read_c0_entrylo0()); + rt_kprintf("( 3,0) ENTRYLO1 : 0x%08X\r\n", read_c0_entrylo1()); + rt_kprintf("( 4,0) CONTEXT : 0x%08X\r\n", read_c0_context()); + rt_kprintf("( 5,0) PAGEMASK : 0x%08X\r\n", read_c0_pagemask()); + rt_kprintf("( 6,0) WIRED : 0x%08X\r\n", read_c0_wired()); + rt_kprintf("( 7,0) INFO : 0x%08X\r\n", read_c0_info()); + rt_kprintf("( 8,0) BADVADDR : 0x%08X\r\n", read_c0_badvaddr()); + rt_kprintf("( 9,0) COUNT : 0x%08X\r\n", read_c0_count()); + rt_kprintf("(10,0) ENTRYHI : 0x%08X\r\n", read_c0_entryhi()); + rt_kprintf("(11,0) COMPARE : 0x%08X\r\n", read_c0_compare()); + + value = read_c0_status(); + rt_kprintf("(12,0) STATUS : 0x%08X", value); + CP0_status_analyze(value); + rt_kprintf("\r\n"); + + /* + rt_kprintf("(12,1) INTCTL : 0x%08X\r\n", __read_32bit_c0_register(12, 1)); + rt_kprintf("(12,2) SRSCTL : 0x%08X\r\n", __read_32bit_c0_register(12, 2)); + */ + + rt_kprintf("(13,0) CAUSE : 0x%08X\r\n", read_c0_cause()); + rt_kprintf("(14,0) EPC : 0x%08X\r\n", read_c0_epc()); + rt_kprintf("(15,0) PRID : 0x%08X\r\n", read_c0_prid()); + rt_kprintf("(15,1) EBASE : 0x%08X\r\n", read_c0_ebase()); + + value = read_c0_config(); + rt_kprintf("(16,0) CONFIG : 0x%08X", value); + CP0_config0_analyze(value); + rt_kprintf("\r\n"); + if(value & (1UL << 31)) + { + value = read_c0_config1(); + rt_kprintf("(16,1) CONFIG1 : 0x%08X", value); + CP0_config1_analyze(value); + rt_kprintf("\r\n"); + + if(value & (1UL << 31)) + { + value = read_c0_config2(); + rt_kprintf("(16,2) CONFIG2 : 0x%08X\r\n", value); + CP0_config2_analyze(value); + rt_kprintf("\r\n"); + + if(value & (1UL << 31)) + { + value = read_c0_config3(); + rt_kprintf("(16,3) CONFIG3 : 0x%08X\r\n", value); + CP0_config3_analyze(value); + rt_kprintf("\r\n"); + } + } + } + + rt_kprintf("(17,0) LLADDR : 0x%08X\r\n", __read_32bit_c0_register($17, 0)); + rt_kprintf("(18,0) WATCHLO : 0x%08X\r\n", __read_32bit_c0_register($18, 0)); + rt_kprintf("(19,0) WATCHHI : 0x%08X\r\n", __read_32bit_c0_register($19, 0)); + rt_kprintf("(20,0) XCONTEXT : 0x%08X\r\n", __read_32bit_c0_register($20, 0)); + rt_kprintf("(21,0) FRAMEMASK : 0x%08X\r\n", __read_32bit_c0_register($21, 0)); + rt_kprintf("(22,0) DIAGNOSTIC: 0x%08X\r\n", __read_32bit_c0_register($22, 0)); + rt_kprintf("(23,0) DEBUG : 0x%08X\r\n", __read_32bit_c0_register($23, 0)); + rt_kprintf("(24,0) DEPC : 0x%08X\r\n", __read_32bit_c0_register($24, 0)); + + rt_kprintf("(25,0) PERFCTL0 : 0x%08X\r\n", __read_32bit_c0_register($25, 0)); + rt_kprintf("(26,0) ECC : 0x%08X\r\n", __read_32bit_c0_register($26, 0)); + rt_kprintf("(27,0) CACHEERR : 0x%08X\r\n", __read_32bit_c0_register($27, 0)); + rt_kprintf("(28,0) TAGLO : 0x%08X\r\n", __read_32bit_c0_register($28, 0)); + rt_kprintf("(29,0) TAGHI : 0x%08X\r\n", __read_32bit_c0_register($29, 0)); + + /* + rt_kprintf("(30,0) ERROREPC : 0x%08X\r\n", __read_32bit_c0_register($30, 0)); + rt_kprintf("(31,0) DESAVE : 0x%08X\r\n", __read_32bit_c0_register($31, 0)); + */ + + + rt_kprintf("\r\n"); +} +FINSH_FUNCTION_EXPORT(list_mips, list CPU info) +#endif /* RT_USING_FINSH */ + diff --git a/libcpu/mips/xburst/stack.c b/libcpu/mips/xburst/stack.c new file mode 100644 index 0000000000..ceba8b9d9d --- /dev/null +++ b/libcpu/mips/xburst/stack.c @@ -0,0 +1,103 @@ +/* + * File : stack.c + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + * 2010-07-07 Bernard porting to Ingenic CPU + */ +#include <rtthread.h> + +/** + * @addtogroup Ingenic + */ +/*@{*/ + +extern rt_uint32_t cp0_get_cause(void); +extern rt_uint32_t cp0_get_status(void); +extern rt_uint32_t cp0_get_hi(void); +extern rt_uint32_t cp0_get_lo(void); + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) +{ + rt_uint32_t *stk; + static rt_uint32_t g_sr = 0; + + if (g_sr == 0) + { + g_sr = cp0_get_status(); + g_sr &= 0xfffffffe; + g_sr |= 0x0403; + } + + /** Start at stack top */ + stk = (rt_uint32_t *)stack_addr; + *(stk) = (rt_uint32_t) tentry; /* pc: Entry Point */ + *(--stk) = (rt_uint32_t) 0xeeee; /* c0_cause */ + *(--stk) = (rt_uint32_t) 0xffff; /* c0_badvaddr */ + *(--stk) = (rt_uint32_t) cp0_get_lo(); /* lo */ + *(--stk) = (rt_uint32_t) cp0_get_hi(); /* hi */ + *(--stk) = (rt_uint32_t) g_sr; /* C0_SR: HW2 = En, IE = En */ + *(--stk) = (rt_uint32_t) texit; /* ra */ + *(--stk) = (rt_uint32_t) 0x0000001e; /* s8 */ + *(--stk) = (rt_uint32_t) stack_addr; /* sp */ + *(--stk) = (rt_uint32_t) 0x0000001c; /* gp */ + *(--stk) = (rt_uint32_t) 0x0000001b; /* k1 */ + *(--stk) = (rt_uint32_t) 0x0000001a; /* k0 */ + *(--stk) = (rt_uint32_t) 0x00000019; /* t9 */ + *(--stk) = (rt_uint32_t) 0x00000018; /* t8 */ + *(--stk) = (rt_uint32_t) 0x00000017; /* s7 */ + *(--stk) = (rt_uint32_t) 0x00000016; /* s6 */ + *(--stk) = (rt_uint32_t) 0x00000015; /* s5 */ + *(--stk) = (rt_uint32_t) 0x00000014; /* s4 */ + *(--stk) = (rt_uint32_t) 0x00000013; /* s3 */ + *(--stk) = (rt_uint32_t) 0x00000012; /* s2 */ + *(--stk) = (rt_uint32_t) 0x00000011; /* s1 */ + *(--stk) = (rt_uint32_t) 0x00000010; /* s0 */ + *(--stk) = (rt_uint32_t) 0x0000000f; /* t7 */ + *(--stk) = (rt_uint32_t) 0x0000000e; /* t6 */ + *(--stk) = (rt_uint32_t) 0x0000000d; /* t5 */ + *(--stk) = (rt_uint32_t) 0x0000000c; /* t4 */ + *(--stk) = (rt_uint32_t) 0x0000000b; /* t3 */ + *(--stk) = (rt_uint32_t) 0x0000000a; /* t2 */ + *(--stk) = (rt_uint32_t) 0x00000009; /* t1 */ + *(--stk) = (rt_uint32_t) 0x00000008; /* t0 */ + *(--stk) = (rt_uint32_t) 0x00000007; /* a3 */ + *(--stk) = (rt_uint32_t) 0x00000006; /* a2 */ + *(--stk) = (rt_uint32_t) 0x00000005; /* a1 */ + *(--stk) = (rt_uint32_t) parameter; /* a0 */ + *(--stk) = (rt_uint32_t) 0x00000003; /* v1 */ + *(--stk) = (rt_uint32_t) 0x00000002; /* v0 */ + *(--stk) = (rt_uint32_t) 0x00000001; /* at */ + *(--stk) = (rt_uint32_t) 0x00000000; /* zero */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/libcpu/mips/xburst/stack.h b/libcpu/mips/xburst/stack.h new file mode 100644 index 0000000000..5bb7206c11 --- /dev/null +++ b/libcpu/mips/xburst/stack.h @@ -0,0 +1,28 @@ +/* + * File : stack.h + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes +*/ + +#ifndef __STACK_H__ +#define __STACK_H__ + +#define SYSTEM_STACK 0x80003fe8 /* the kernel system stack address */ + +#endif diff --git a/libcpu/mips/xburst/start_gcc.S b/libcpu/mips/xburst/start_gcc.S new file mode 100644 index 0000000000..322c2beae8 --- /dev/null +++ b/libcpu/mips/xburst/start_gcc.S @@ -0,0 +1,150 @@ +/* + * File : start_gcc.S + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + * 2010-09-04 bernard porting to Jz47xx + */ + +#include "../common/mips.inc" +#include "../common/stackframe.h" +#include "stack.h" + + .section ".start", "ax" + .set noreorder + + /* the program entry */ + .globl _start +_start: + .set noreorder + la ra, _start + + li t1, 0x00800000 + mtc0 t1, CP0_CAUSE + + /* init cp0 registers. */ + li t0, 0x0000FC00 /* BEV = 0 and mask all interrupt */ + mtc0 t0, CP0_STATUS + + /* setup stack pointer */ + li sp, SYSTEM_STACK + la gp, _gp + + /* init caches, assumes a 4way * 128set * 32byte I/D cache */ + mtc0 zero, CP0_TAGLO /* TAGLO reg */ + mtc0 zero, CP0_TAGHI /* TAGHI reg */ + li t0, 3 /* enable cache for kseg0 accesses */ + mtc0 t0, CP0_CONFIG /* CONFIG reg */ + la t0, 0x80000000 /* an idx op should use an unmappable address */ + ori t1, t0, 0x4000 /* 16kB cache */ + +_cache_loop: + cache 0x8, 0(t0) /* index store icache tag */ + cache 0x9, 0(t0) /* index store dcache tag */ + bne t0, t1, _cache_loop + addiu t0, t0, 0x20 /* 32 bytes per cache line */ + nop + + /* invalidate BTB */ + mfc0 t0, CP0_CONFIG + nop + ori t0, 2 + mtc0 t0, CP0_CONFIG + nop + + /* copy IRAM section */ + la t0, _iramcopy + la t1, _iramstart + la t2, _iramend +_iram_loop: + lw t3, 0(t0) + sw t3, 0(t1) + addiu t1, 4 + bne t1, t2, _iram_loop + addiu t0, 4 + /* clear bss */ + la t0, __bss_start + la t1, __bss_end +_clr_bss_loop: + sw zero, 0(t0) + bne t0, t1, _clr_bss_loop + addiu t0, t0, 4 + + /* jump to RT-Thread RTOS */ + jal rtthread_startup + nop + + /* restart, never die */ + j _start + nop + .set reorder + + .globl cp0_get_cause +cp0_get_cause: + mfc0 v0, CP0_CAUSE + jr ra + nop + + .globl cp0_get_status +cp0_get_status: + mfc0 v0, CP0_STATUS + jr ra + nop + + .globl cp0_get_hi +cp0_get_hi: + mfhi v0 + jr ra + nop + + .globl cp0_get_lo +cp0_get_lo: + mflo v0 + jr ra + nop + + .extern tlb_refill_handler + .extern cache_error_handler + + /* Exception Handler */ + /* 0x0 - TLB refill handler */ + .section .vectors.1, "ax", %progbits + j tlb_refill_handler + nop + + /* 0x100 - Cache error handler */ + .section .vectors.2, "ax", %progbits + j cache_error_handler + nop + + /* 0x180 - Exception/Interrupt handler */ + .section .vectors.3, "ax", %progbits + j _general_exception_handler + nop + + /* 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) */ + .section .vectors.4, "ax", %progbits + j _irq_handler + nop + + .section .vectors, "ax", %progbits + .extern mips_irq_handle + + /* general exception handler */ +_general_exception_handler: + .set noreorder + mfc0 k1, CP0_CAUSE + andi k1, k1, 0x7c + srl k1, k1, 2 + lw k0, sys_exception_handlers(k1) + jr k0 + nop + .set reorder + + /* interrupt handler */ +_irq_handler: + .set noreorder + la k0, mips_irq_handle + jr k0 + nop + .set reorder diff --git a/libcpu/mips/xburst/x1000.h b/libcpu/mips/xburst/x1000.h new file mode 100644 index 0000000000..71d11783a3 --- /dev/null +++ b/libcpu/mips/xburst/x1000.h @@ -0,0 +1,329 @@ +/* + * File : x1000.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-11-19 Urey the first version + */ + +#ifndef X1000_H__ +#define X1000_H__ + +#ifndef __ASSEMBLY__ + +// typedef unsigned int size_t; +#define u64 unsigned long long +#define u32 unsigned int +#define u16 unsigned short +#define u8 unsigned char + +#define U64 unsigned long long +#define U32 unsigned int +#define U16 unsigned short +#define U8 unsigned char + +#define S64 signed long long +#define S32 int +#define S16 short int +#define S8 signed char + +#define cache_unroll(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, (%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + +/* cpu pipeline flush */ +static inline void jz_sync(void) +{ + __asm__ volatile ("sync"); +} + +static inline void writeb(u8 value, u32 address) +{ + *((volatile u8 *) address) = value; +} +static inline void writew( u16 value, u32 address) +{ + *((volatile u16 *) address) = value; +} +static inline void writel(u32 value, u32 address) +{ + *((volatile u32 *) address) = value; +} + +static inline u8 readb(u32 address) +{ + return *((volatile u8 *)address); +} + +static inline u16 readw(u32 address) +{ + return *((volatile u16 *)address); +} + +static inline u32 readl(u32 address) +{ + return *((volatile u32 *)address); +} + +static inline void jz_writeb(u32 address, u8 value) +{ + *((volatile u8 *)address) = value; +} + +static inline void jz_writew(u32 address, u16 value) +{ + *((volatile u16 *)address) = value; +} + +static inline void jz_writel(u32 address, u32 value) +{ + *((volatile u32 *)address) = value; +} + +static inline u8 jz_readb(u32 address) +{ + return *((volatile u8 *)address); +} + +static inline u16 jz_readw(u32 address) +{ + return *((volatile u16 *)address); +} + +static inline u32 jz_readl(u32 address) +{ + return *((volatile u32 *)address); +} + +#define REG8(addr) *((volatile u8 *)(addr)) +#define REG16(addr) *((volatile u16 *)(addr)) +#define REG32(addr) *((volatile u32 *)(addr)) + +#define BIT(n) (0x01u << (n)) + +#else + +#define REG8(addr) (addr) +#define REG16(addr) (addr) +#define REG32(addr) (addr) + +#endif /* !ASSEMBLY */ + + +//---------------------------------------------------------------------- +// Register Definitions +// +/* AHB0 BUS Devices Base */ +#define HARB0_BASE 0xB3000000 +#define EMC_BASE 0xB3010000 +#define DDRC_BASE 0xB3020000 +#define MDMAC_BASE 0xB3030000 +#define LCD_BASE 0xB3050000 +#define TVE_BASE 0xB3050000 +#define SLCD_BASE 0xB3050000 +#define CIM_BASE 0xB3060000 +#define IPU_BASE 0xB3080000 +/* AHB1 BUS Devices Base */ +#define HARB1_BASE 0xB3200000 +#define DMAGP0_BASE 0xB3210000 +#define DMAGP1_BASE 0xB3220000 +#define DMAGP2_BASE 0xB3230000 +#define MC_BASE 0xB3250000 +#define ME_BASE 0xB3260000 +#define DEBLK_BASE 0xB3270000 +#define IDCT_BASE 0xB3280000 +#define CABAC_BASE 0xB3290000 +#define TCSM0_BASE 0xB32B0000 +#define TCSM1_BASE 0xB32C0000 +#define SRAM_BASE 0xB32D0000 +/* AHB2 BUS Devices Base */ +#define HARB2_BASE 0xB3400000 +#define NEMC_BASE 0xB3410000 +#define DMAC_BASE 0xB3420000 +#define UHC_BASE 0xB3430000 +#define UDC_BASE 0xB3440000 +#define GPS_BASE 0xB3480000 +#define ETHC_BASE 0xB34B0000 +#define BCH_BASE 0xB34D0000 +#define MSC0_BASE 0xB3450000 +#define MSC1_BASE 0xB3460000 +#define MSC2_BASE 0xB3470000 + +/* APB BUS Devices Base */ +#define CPM_BASE 0xB0000000 +#define INTC_BASE 0xB0001000 +#define TCU_BASE 0xB0002000 +#define WDT_BASE 0xB0002000 +#define OST_BASE 0xB2000000 /* OS Timer */ +#define RTC_BASE 0xB0003000 +#define GPIO_BASE 0xB0010000 +#define AIC_BASE 0xB0020000 +#define DMIC_BASE 0xB0021000 +#define ICDC_BASE 0xB0020000 +#define UART0_BASE 0xB0030000 +#define UART1_BASE 0xB0031000 +#define UART2_BASE 0xB0032000 +#define UART3_BASE 0xB0033000 +#define SCC_BASE 0xB0040000 +#define SSI0_BASE 0xB0043000 +#define SSI1_BASE 0xB0044000 +#define SSI2_BASE 0xB0045000 +#define I2C0_BASE 0xB0050000 +#define I2C1_BASE 0xB0051000 +#define PS2_BASE 0xB0060000 +#define SADC_BASE 0xB0070000 +#define OWI_BASE 0xB0072000 +#define TSSI_BASE 0xB0073000 + +/* NAND CHIP Base Address*/ +#define NEMC_CS1_IOBASE 0Xbb000000 +#define NEMC_CS2_IOBASE 0Xba000000 +#define NEMC_CS3_IOBASE 0Xb9000000 +#define NEMC_CS4_IOBASE 0Xb8000000 +#define NEMC_CS5_IOBASE 0Xb7000000 +#define NEMC_CS6_IOBASE 0Xb6000000 + +/********************************************************************************************************* +** WDT +*********************************************************************************************************/ +#define WDT_TDR (WDT_BASE + 0x00) +#define WDT_TCER (WDT_BASE + 0x04) +#define WDT_TCNT (WDT_BASE + 0x08) +#define WDT_TCSR (WDT_BASE + 0x0C) + +#define REG_WDT_TDR REG16(WDT_TDR) +#define REG_WDT_TCER REG8(WDT_TCER) +#define REG_WDT_TCNT REG16(WDT_TCNT) +#define REG_WDT_TCSR REG16(WDT_TCSR) + +#define WDT_TSCR_WDTSC (1 << 16) + +#define WDT_TCSR_PRESCALE_1 (0 << 3) +#define WDT_TCSR_PRESCALE_4 (1 << 3) +#define WDT_TCSR_PRESCALE_16 (2 << 3) +#define WDT_TCSR_PRESCALE_64 (3 << 3) +#define WDT_TCSR_PRESCALE_256 (4 << 3) +#define WDT_TCSR_PRESCALE_1024 (5 << 3) + +#define WDT_TCSR_EXT_EN (1 << 2) +#define WDT_TCSR_RTC_EN (1 << 1) +#define WDT_TCSR_PCK_EN (1 << 0) + +#define WDT_TCER_TCEN (1 << 0) + +/********************************************************************************************************* +** �ж�Դ +*********************************************************************************************************/ +/* INTC (Interrupt Controller) */ +#define INTC_ISR(n) (INTC_BASE + 0x00 + (n) * 0x20) +#define INTC_IMR(n) (INTC_BASE + 0x04 + (n) * 0x20) +#define INTC_IMSR(n) (INTC_BASE + 0x08 + (n) * 0x20) +#define INTC_IMCR(n) (INTC_BASE + 0x0c + (n) * 0x20) +#define INTC_IPR(n) (INTC_BASE + 0x10 + (n) * 0x20) + +#define REG_INTC_ISR(n) REG32(INTC_ISR((n))) +#define REG_INTC_IMR(n) REG32(INTC_IMR((n))) +#define REG_INTC_IMSR(n) REG32(INTC_IMSR((n))) +#define REG_INTC_IMCR(n) REG32(INTC_IMCR((n))) +#define REG_INTC_IPR(n) REG32(INTC_IPR((n))) + +// interrupt controller interrupts +#define IRQ_DMIC 0 +#define IRQ_AIC0 1 +#define IRQ_RESERVED2 2 +#define IRQ_RESERVED3 3 +#define IRQ_RESERVED4 4 +#define IRQ_RESERVED5 5 +#define IRQ_RESERVED6 6 +#define IRQ_SFC 7 +#define IRQ_SSI0 8 +#define IRQ_RESERVED9 9 +#define IRQ_PDMA 10 +#define IRQ_PDMAD 11 +#define IRQ_RESERVED12 12 +#define IRQ_RESERVED13 13 +#define IRQ_GPIO3 14 +#define IRQ_GPIO2 15 +#define IRQ_GPIO1 16 +#define IRQ_GPIO0 17 +#define IRQ_RESERVED18 18 +#define IRQ_RESERVED19 19 +#define IRQ_RESERVED20 20 +#define IRQ_OTG 21 +#define IRQ_RESERVED22 22 +#define IRQ_AES 23 +#define IRQ_RESERVED24 24 +#define IRQ_TCU2 25 +#define IRQ_TCU1 26 +#define IRQ_TCU0 27 +#define IRQ_RESERVED28 28 +#define IRQ_RESERVED29 29 +#define IRQ_CIM 30 +#define IRQ_LCD 31 +#define IRQ_RTC 32 +#define IRQ_RESERVED33 33 +#define IRQ_RESERVED34 34 +#define IRQ_RESERVED35 35 +#define IRQ_MSC1 36 +#define IRQ_MSC0 37 +#define IRQ_SCC 38 +#define IRQ_RESERVED39 39 +#define IRQ_PCM0 40 +#define IRQ_RESERVED41 41 +#define IRQ_RESERVED42 42 +#define IRQ_RESERVED43 43 +#define IRQ_HARB2 44 +#define IRQ_RESERVED45 45 +#define IRQ_HARB0 46 +#define IRQ_CPM 47 +#define IRQ_RESERVED48 48 +#define IRQ_UART2 49 +#define IRQ_UART1 50 +#define IRQ_UART0 51 +#define IRQ_DDR 52 +#define IRQ_RESERVED53 53 +#define IRQ_EFUSE 54 +#define IRQ_MAC 55 +#define IRQ_RESERVED56 56 +#define IRQ_RESERVED57 57 +#define IRQ_I2C2 58 +#define IRQ_I2C1 59 +#define IRQ_I2C0 60 +#define IRQ_PDMAM 61 +#define IRQ_JPEG 62 +#define IRQ_RESERVED63 63 + +#define IRQ_INTC_MAX 63 + +#ifndef __ASSEMBLY__ + +#define __intc_unmask_irq(n) (REG_INTC_IMCR((n)/32) = (1 << ((n)%32))) +#define __intc_mask_irq(n) (REG_INTC_IMSR((n)/32) = (1 << ((n)%32))) +#define __intc_ack_irq(n) (REG_INTC_IPR((n)/32) = (1 << ((n)%32))) /* A dummy ack, as the Pending Register is Read Only. Should we remove __intc_ack_irq() */ + +#endif /* !__ASSEMBLY__ */ + +#endif /* _JZ_M150_H_ */ |
