diff --git a/.cproject b/.cproject new file mode 100644 index 0000000000000000000000000000000000000000..29a5151493e69c235e8c7357513b8857878fd781 --- /dev/null +++ b/.cproject @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000000000000000000000000000000000000..a910085a23d5750ac70bc5244ded86318a452986 --- /dev/null +++ b/.project @@ -0,0 +1,26 @@ + + + rtt_master + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/bsp/AE210P/.PHONY.size b/bsp/AE210P/.PHONY.size new file mode 100644 index 0000000000000000000000000000000000000000..18649320941cef672f27a56f8b874d1815eb0f77 --- /dev/null +++ b/bsp/AE210P/.PHONY.size @@ -0,0 +1,2 @@ + text (code + rodata) data bss dec hex filename + 67240 (58320 + 8920) 408 10168 77816 12ff8 rtthread.elf diff --git a/bsp/AE210P/Makefile b/bsp/AE210P/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..778015bb92b37bdd6ecd8f32382ae0a1422f8f98 --- /dev/null +++ b/bsp/AE210P/Makefile @@ -0,0 +1,301 @@ +#************************************************************ +# RT-Thread RTOS makefile base on Andes N1068A core +# +# Mengxin Technology Co., Ltd. +# Archer Chang +# 2017.07.25 16:00 +# +#************************************************************ + +CROSS_COMPILE ?= nds32le-elf- +SIZE_OUTPUTS = .PHONY.size + +CC := $(CROSS_COMPILE)gcc +OBJCOPY := $(CROSS_COMPILE)objcopy +AR := $(CROSS_COMPILE)ar +AS := $(CROSS_COMPILE)as + +ifeq ($(DEBUG),1) + OPTIM := -O0 -g2 +else + OPTIM := -O2 -g0 +endif + +ROOT_PATH := . +RTOS_PATH := $(ROOT_PATH)/../.. +ARCH_PATH := $(RTOS_PATH)/libcpu +KERNEL_PATH := $(RTOS_PATH)/src +COMPONENTS_PATH := $(RTOS_PATH)/components +COMPONENTS_INIT_PATH := $(COMPONENTS_PATH)/init +COMPONENTS_DRV_PATH := $(COMPONENTS_PATH)/drivers +COMPONENTS_DRVSRC_PATH := $(COMPONENTS_DRV_PATH)/src +COMPONENTS_DRVINC_PATH := $(COMPONENTS_DRV_PATH)/include +COMPONENTS_DRVINC_DRV_PATH := $(COMPONENTS_DRVINC_PATH)/drivers +BSP_PATH := $(RTOS_PATH)/bsp +CLI_PATH := $(COMPONENTS_PATH)/finsh + +PLATFORM_PATH := $(BSP_PATH)/AE210P +ARCH_SEL_PATH := $(ARCH_PATH)/nds32 +CONFIG_PATH := $(PLATFORM_PATH) +BOARD_PATH := $(PLATFORM_PATH)/board +#LIBC_PATH := $(PLATFORM_PATH)/libc +LDSCRIPT := $(BOARD_PATH)/ae210p.ld +CONFIG_H := $(CONFIG_PATH)/config.h +PLATFORM_DEF := -DAE210P +ARCH_INCLUDE_PATH := $(ARCH_PATH)/nds32 + +HW_HAL_SRC := $(BOARD_PATH)/ae210p.c \ + $(PLATFORM_PATH)/board.c \ + $(ARCH_SEL_PATH)/cpuport.c \ + $(PLATFORM_PATH)/startup.c \ + $(PLATFORM_PATH)/application.c + +DRIVERS_PATH := $(PLATFORM_PATH)/driver + +OS_DEF := -DCONFIG_OS_RTTHREAD +INCLUDE_PATH := \ + -I$(RTOS_PATH) \ + -I$(ARCH_INCLUDE_PATH) \ + -I$(RTOS_PATH)/include \ + -I${KERNEL_PATH} \ + -I$(CONFIG_PATH) \ + -I$(PLATFORM_PATH) \ + -I$(BOARD_PATH) \ + -I$(DRIVERS_PATH) \ + -I$(CLI_PATH) \ + -I$(COMPONENTS_DRVINC_PATH) \ + -I$(COMPONENTS_DRVINC_DRV_PATH) \ + -I$(COMPONENTS_INIT_PATH) + +SMALL_HEAP_DEF := + +#Check GCC version +VERSION := $(shell $(CC) --version | grep ^$(CC) | sed 's/^.* //g') +GCC_VERSION := $(shell echo $(VERSION)| sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/' ) + +# GCC version before 4.8.2 doesn't support -mcmodel +ifneq ($(shell expr `echo $(GCC_VERSION)` \< 40802 ),1) + CMODEL := -mcmodel=large +endif + +CFLAGS := \ + $(INCLUDE_PATH) \ + -Wall \ + $(PLATFORM_DEF) \ + $(OS_DEF) \ + $(SMALL_HEAP_DEF) \ + -fno-builtin -fomit-frame-pointer -funroll-loops \ + -fno-strict-aliasing -ffunction-sections \ + $(CMODEL) \ + $(OPTIM) \ + $(OSC_DEF) \ + $(CFLAGS_EXT) + +LD_FLAGS := $(OPTIM) -fno-builtin -nostartfiles -static -Wl,--gc-sections $(CMODEL) +AFLAGS := -fno-builtin + +# Add `-fno-delete-null-pointer-checks` flag if the compiler supports it. +# GCC assumes that programs cannot safely dereference null pointers, +# and that no code or data element resides there. +# However, 0x0 is the vector table memory location, so the test must not be removed. +ifeq ($(shell $(CC) -fno-delete-null-pointer-checks -E - 2>/dev/null >/dev/null /dev/null && echo IFC),IFC) + ifeq ($(NO_IFC),y) + CFLAGS += -mno-ifc -DCONFIG_NO_NDS32_EXT_IFC + LD_FLAGS += -Wl,--mno-ifc + endif +else + ifneq ($(NO_IFC),) + $(error this toolchain do not support IFC extension) + endif +endif + +ifeq ($(shell echo | $(CC) -E -dM - | grep __NDS32_EXT_EX9__ > /dev/null && echo EX9),EX9) + ifeq ($(NO_EX9),y) + CFLAGS += -mno-ex9 -DCONFIG_NO_NDS32_EXT_EX9 + LD_FLAGS += -Wl,--mno-ex9 + endif +else + ifneq ($(NO_EX9),) + $(error this toolchain do not support EX9 extension) + endif +endif + +ifeq ($(CACHE),1) + CFLAGS += -DCONFIG_CACHE_SUPPORT +endif + + +# add INTC check +ifeq ($(EXT_INTC),1) + CFLAGS += -DCONFIG_EXT_INTC +endif + +# HWZOL check +ifeq ($(HWZOL),1) + ifeq ($(shell echo | $(CC) -E -dM -mext-zol - | grep '\<__NDS32_EXT_ZOL__\>' > /dev/null && echo "ZOL"), ZOL) + CFLAGS += -DCONFIG_HWZOL + LD_FLAGS += -mext-zol + else + $(error this toolchain do not support ZOL extension) + endif +endif + +RTOS_SRC := \ + $(KERNEL_PATH)/clock.c \ + $(KERNEL_PATH)/device.c \ + $(KERNEL_PATH)/idle.c \ + $(KERNEL_PATH)/ipc.c \ + $(KERNEL_PATH)/irq.c \ + $(KERNEL_PATH)/kservice.c \ + $(KERNEL_PATH)/mem.c \ + $(KERNEL_PATH)/mempool.c \ + $(KERNEL_PATH)/scheduler.c \ + $(KERNEL_PATH)/thread.c \ + $(KERNEL_PATH)/timer.c \ + $(KERNEL_PATH)/object.c \ + +NDS32_SRC := \ + $(PLATFORM_PATH)/reset.c \ + $(PLATFORM_PATH)/cache.c \ + $(HW_HAL_SRC) \ + +BOOT_SRC := \ + $(PLATFORM_PATH)/start.S \ + $(ARCH_SEL_PATH)/context_gcc.S + +CLI_SRC := +ifeq ($(USING_CLI),1) + CLI_SRC += $(KERNEL_PATH)/components.c \ + $(COMPONENTS_DRVSRC_PATH)/ringbuffer.c \ + $(COMPONENTS_DRVSRC_PATH)/completion.c \ + $(COMPONENTS_DRVSRC_PATH)/dataqueue.c \ + $(CLI_PATH)/cmd.c \ + $(CLI_PATH)/finsh_compiler.c \ + $(CLI_PATH)/finsh_error.c \ + $(CLI_PATH)/finsh_heap.c \ + $(CLI_PATH)/finsh_init.c \ + $(CLI_PATH)/finsh_node.c \ + $(CLI_PATH)/finsh_ops.c \ + $(CLI_PATH)/finsh_parser.c \ + $(CLI_PATH)/finsh_token.c \ + $(CLI_PATH)/finsh_var.c \ + $(CLI_PATH)/finsh_vm.c \ + $(CLI_PATH)/msh.c \ + $(CLI_PATH)/msh_cmd.c \ + $(CLI_PATH)/shell.c \ + $(CLI_PATH)/symbol.c +endif + +#DRIVER_SRC := \ + ${UART_DRIVER_SRC} \ + ${LCD_DRIVER_SRC} \ + ${SD_DRIVER_SRC} \ + ${TOUCHSCREEN_DRIVER_SRC} \ + ${AC97_DRIVER_SRC} \ + ${DMA_DRIVER_SRC} \ + ${HAL_DRIVER_SRC} \ + +DRIVER_SRC := \ + $(PLATFORM_PATH)/driver/uart/uart.c \ + $(PLATFORM_PATH)/driver/gpio/gpio.c \ + $(BOARD_PATH)/uart_dev.c \ + $(COMPONENTS_DRV_PATH)/serial/serial.c +# $(PLATFORM_PATH)/driver/dma/dmad.c + +#LIBC_SRC := \ +# $(LIBC_PATH)/stdio/fgets.c \ +# $(LIBC_PATH)/stdio/fputs.c \ +# $(LIBC_PATH)/stdio/fprintf.c \ +# $(LIBC_PATH)/stdio/do_printf.c \ +# $(LIBC_PATH)/stdio/printf.c \ +# $(LIBC_PATH)/string/memcpy.c \ +# $(LIBC_PATH)/string/memmove.c \ +# $(LIBC_PATH)/string/memset.c \ +# $(LIBC_PATH)/string/strcat.c \ +# $(LIBC_PATH)/string/strcasecmp.c \ +# $(LIBC_PATH)/string/strcmp.c \ +# $(LIBC_PATH)/string/strcpy.c \ +# $(LIBC_PATH)/string/strdup.c \ +# $(LIBC_PATH)/string/strlen.c \ +# $(LIBC_PATH)/string/strstr.c \ +# $(LIBC_PATH)/string/strupr.c \ +# $(LIBC_PATH)/string/wchar.c \ +# $(LIBC_PATH)/stdlib/qsort.c + +#LIBC_FILE_SRC := \ +# $(LIBC_PATH)/stdio/file.c \ + +#******************************************** +# Applications +#******************************************** +APP_SRCS := + +################################################################# +# # +# Source code to each application # +# # +################################################################# +SRCS := \ + ${NDS32_SRC} \ + ${RTOS_SRC} \ + ${DRIVER_SRC} \ + ${CLI_SRC} \ + ${APP_SRCS} #\ +# ${LIBC_SRC} + +ALL_C_SRCS := ${SRCS} +ALL_AS_SRCS += ${BOOT_SRC} + +# % can match to all the strings +ALL_C_OBJS := $(patsubst %.S,%.o,$(patsubst %.c,%.o,${ALL_C_SRCS})) +ALL_AS_OBJS := $(patsubst %.S,%.o,${ALL_AS_SRCS}) + +OBJS = ${ALL_C_OBJS} ${ALL_AS_OBJS} + +.PHONY: all clean distclean + +all: ${APP}.elf ${APP}.bin $(SIZE_OUTPUTS) + if test ! -d ./build; then \ + mkdir ./build; \ + fi + mv ${APP}.elf ${APP}.bin ./build + +clean: + $(RM) $(OBJS) + $(RM) ./build/${APP}.elf ./build/${APP}.bin + +distclean: clean + $(RM) -rf build/ + +.SUFFIXES : .o .c .S + +.c.o : $(CONFIG_H) + $(CC) -include $(CONFIG_H) -c $(CFLAGS) $< -o $@ +.S.o : $(CONFIG_H) + $(CC) -include $(CONFIG_H) -c $(CFLAGS) $(AFLAGS) $< -o $@ + +${APP}.elf: $(CONFIG_H) ${KCONFIG_CONFIG} ${ALL_C_OBJS} ${ALL_AS_OBJS} + @echo ' ' + $(CC) -T$(LDSCRIPT) ${ALL_C_OBJS} ${ALL_AS_OBJS} $(LD_FLAGS) $(LFLAGS_EXT) -o $@ + @echo ' ' + +${APP}.bin: ${APP}.elf +# @echo ' ' + $(OBJCOPY) ${APP}.elf -O binary ${APP}.bin + @echo ' ' + +.PHONY.size: +# @echo ' ' + $(CROSS_COMPILE)size ${APP}.elf | tee .PHONY.size + @echo ' ' + +.PHONY: all clean distclean .PHONY.size diff --git a/bsp/AE210P/application.c b/bsp/AE210P/application.c new file mode 100644 index 0000000000000000000000000000000000000000..7680506e9d389113ba6feae429cbb4b380c1d4e4 --- /dev/null +++ b/bsp/AE210P/application.c @@ -0,0 +1,136 @@ +/* + * File : application.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-01-05 Bernard the first version + * 2013-07-12 aozima update for auto initial. + */ + +/** + * @addtogroup STM32 + */ +/*@{*/ + +#include +#include +#include + +#ifdef RT_USING_COMPONENTS_INIT +#include +#endif /* RT_USING_COMPONENTS_INIT */ + +#ifdef RT_USING_DFS +/* dfs filesystem:ELM filesystem init */ +#include +/* dfs Filesystem APIs */ +#include +#endif + +#ifdef RT_USING_RTGUI +#include +#include +#include +#include +#include +#endif + +void rt_init_thread_entry(void* parameter) +{ +#ifdef RT_USING_COMPONENTS_INIT + /* initialization RT-Thread Components */ + rt_components_init(); +#endif + + /* Filesystem Initialization */ +#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT) + /* mount sd card fat partition 1 as root directory */ + if (dfs_mount("sd0", "/", "elm", 0, 0) == 0) + { + rt_kprintf("File System initialized!\n"); + } + else + rt_kprintf("File System initialzation failed!\n"); +#endif /* RT_USING_DFS */ + +#ifdef RT_USING_RTGUI + { + extern void rt_hw_lcd_init(); + extern void rtgui_touch_hw_init(void); + + rt_device_t lcd; + + /* init lcd */ + rt_hw_lcd_init(); + + /* init touch panel */ + rtgui_touch_hw_init(); + + /* find lcd device */ + lcd = rt_device_find("lcd"); + + /* set lcd device as rtgui graphic driver */ + rtgui_graphic_set_device(lcd); + +#ifndef RT_USING_COMPONENTS_INIT + /* init rtgui system server */ + rtgui_system_server_init(); +#endif + + calibration_set_restore(cali_setup); + calibration_set_after(cali_store); + calibration_init(); + } +#endif /* #ifdef RT_USING_RTGUI */ +} + +//#include "debug.h" +// +//rt_thread_t test_thread[2]; +// +//void rt_test_thread_entry(void *parameter) +//{ +// uint32_t num = (uint32_t)parameter; +// uint32_t schedule_times = 0; +// +// while (1) +// { +// DEBUG(1, 0, "%d:%d\r\n", num, schedule_times++); +// rt_thread_delay(1); +// } +//} + +int rt_application_init(void) +{ + rt_thread_t init_thread; + +#if (RT_THREAD_PRIORITY_MAX == 32) + init_thread = rt_thread_create("init", + rt_init_thread_entry, RT_NULL, + 2048, 8, 20); +#else + init_thread = rt_thread_create("init", + rt_init_thread_entry, RT_NULL, + 2048, 80, 20); +#endif + + if (init_thread != RT_NULL) + rt_thread_startup(init_thread); + +// test_thread[0] = rt_thread_create("t1", rt_test_thread_entry, (void *)1, 1024, 26, 5); +// test_thread[1] = rt_thread_create("t2", rt_test_thread_entry, (void *)2, 1024, 26, 5); +// if (test_thread[0] != RT_NULL) +// rt_thread_startup(test_thread[0]); +// if (test_thread[1] != RT_NULL) +// rt_thread_startup(test_thread[1]); + + return 0; +} + +/*@}*/ diff --git a/bsp/AE210P/board.c b/bsp/AE210P/board.c new file mode 100644 index 0000000000000000000000000000000000000000..ee0222141803e7fe5875906a34f4bb0a1318d3a0 --- /dev/null +++ b/bsp/AE210P/board.c @@ -0,0 +1,95 @@ +/* + * File : board.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2009 RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-01-05 Bernard first implementation + * 2013-07-12 aozima update for auto initial. + */ + +#include +#include + +#include "nds32.h" +#include "bsp_hal.h" +#include "ae210p.h" +#include "debug.h" +//#include "uart/uart.h" +#include "uart_dev.h" + +#include "board.h" +#include "rtconfig.h" + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* clean timer device pending*/ + hal_timer_irq_clear(1); + + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/*********************************************************** + * Set timer 1 as system tick by default + ***********************************************************/ + +void BSP_Tmr_TickInit(uint32_t tmrId, uint32_t period, uint32_t vecId, void *isr) +{ + /* set tick period */ + hal_timer_set_period(tmrId, period); + + /* enable timer1 interrupt */ + hal_timer_irq_control(tmrId, 1); + + /****************************** + * tick ISR init + ******************************/ + /* init trigger mode */ + /* Set edge trigger, falling edge */ + hal_intc_irq_config(vecId, 1, 0); + /* clean pending */ + hal_intc_irq_clean(vecId); + /* enable timer interrupt */ + hal_intc_irq_enable(vecId); + + if (isr) + OS_CPU_Vector_Table[vecId] = isr; + else + DEBUG(1, 1, "Invalid tick handler!!\r\n"); + + /* start timer */ + hal_timer_start(tmrId); +} + +/* + * Setup system tick for OS required. + */ +void bsp_init(void) +{ + /* disable interrupt first */ + rt_hw_interrupt_disable(); + +// drv_uart_init(); + rt_hw_usart_init(); + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + + /* System tick init */ + BSP_Tmr_TickInit(0x1, (MB_PCLK / RT_TICK_PER_SECOND), IRQ_SYS_TICK_VECTOR, SysTick_Handler); +} + +/*@}*/ diff --git a/bsp/AE210P/board.h b/bsp/AE210P/board.h new file mode 100644 index 0000000000000000000000000000000000000000..22dc3dc9f1d1c4ec7222f900ce5f74fff68e37a8 --- /dev/null +++ b/bsp/AE210P/board.h @@ -0,0 +1,28 @@ +/* + * File : board.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-09-22 Bernard add board.h to this bsp + */ + +// <<< Use Configuration Wizard in Context Menu >>> +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "nds32.h" + +/* board configuration */ + +//#define RT_USING_UART01 1 +#define RT_USING_UART02 1 + +void rt_hw_board_init(void); + +#endif /* __BOARD_H__ */ diff --git a/bsp/AE210P/board/ae210p.c b/bsp/AE210P/board/ae210p.c new file mode 100644 index 0000000000000000000000000000000000000000..ee0cfaca758d0612be4e67375f3331c151cdea4f --- /dev/null +++ b/bsp/AE210P/board/ae210p.c @@ -0,0 +1,338 @@ +#include +#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); +} diff --git a/bsp/AE210P/board/ae210p.h b/bsp/AE210P/board/ae210p.h new file mode 100644 index 0000000000000000000000000000000000000000..7fc6e6c126e13e80ccb3ed3630b65db8ccf59a0b --- /dev/null +++ b/bsp/AE210P/board/ae210p.h @@ -0,0 +1,74 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2014 + * All Rights Reserved. + * + ****************************************************************************/ + +#ifndef __AE210P_H__ +#define __AE210P_H__ + +#ifndef __ASSEMBLER__ +#include +#include +#endif + +/***************************************************************************** + * System clock + ****************************************************************************/ +#define KHz 1000 +#define MHz 1000000 + +#define MB_OSCCLK (20 * MHz) +#define MB_CPUCLK (40 * MHz) +#define MB_HCLK (MB_CPUCLK) +#define MB_PCLK (MB_CPUCLK) +#define MB_UCLK (MB_OSCCLK) + +/***************************************************************************** + * IRQ Vector + ****************************************************************************/ +#define IRQ_RTCPERIOD_VECTOR 0 +#define IRQ_RTCALARM_VECTOR 1 +#define IRQ_PIT_VECTOR 2 +#define IRQ_SPI1_VECTOR 3 +#define IRQ_SPI2_VECTOR 4 +#define IRQ_I2C_VECTOR 5 +#define IRQ_GPIO_VECTOR 6 +#define IRQ_UART1_VECTOR 7 +#define IRQ_UATR2_VECTOR 8 +#define IRQ_DMA_VECTOR 9 +#define IRQ_BMC_VECTOR 10 +#define IRQ_SWI_VECTOR 11 + +/* EXT_INT_0~19 are reserved for vendor IPs */ +#define IRQ_EXTINT0_VECTOR 12 +#define IRQ_EXTINT1_VECTOR 13 +#define IRQ_EXTINT2_VECTOR 14 +#define IRQ_EXTINT3_VECTOR 15 +#define IRQ_EXTINT4_VECTOR 16 +#define IRQ_EXTINT5_VECTOR 17 +#define IRQ_EXTINT6_VECTOR 18 +#define IRQ_EXTINT7_VECTOR 19 +#define IRQ_EXTINT8_VECTOR 20 +#define IRQ_EXTINT9_VECTOR 21 +#define IRQ_EXTINT10_VECTOR 22 +#define IRQ_EXTINT11_VECTOR 23 +#define IRQ_EXTINT12_VECTOR 24 +#define IRQ_EXTINT13_VECTOR 25 +#define IRQ_EXTINT14_VECTOR 26 +#define IRQ_EXTINT15_VECTOR 27 +#define IRQ_EXTINT16_VECTOR 28 +#define IRQ_EXTINT17_VECTOR 29 +#define IRQ_EXTINT18_VECTOR 30 +#define IRQ_EXTINT19_VECTOR 31 + +/* The system tick IRQ for OS */ +#define IRQ_SYS_TICK_VECTOR IRQ_PIT_VECTOR +#define IRQ_SYS_TICK2_VECTOR IRQ_PIT_VECTOR + +/* Include ae210p memory mapping and register definition */ +#include "ae210p_defs.h" +#include "ae210p_regs.h" + +#endif /* __AE210P_H__ */ diff --git a/bsp/AE210P/board/ae210p.ld b/bsp/AE210P/board/ae210p.ld new file mode 100644 index 0000000000000000000000000000000000000000..fd79ebb12fcc3216b426521927a75b46894e4f64 --- /dev/null +++ b/bsp/AE210P/board/ae210p.ld @@ -0,0 +1,202 @@ +/* This file is generated by nds_ldsag (version (2017-01-11) ). */ +ENTRY(_start) +SECTIONS +{ + PROVIDE (__executable_start = 0x0); + NDS_SAG_LMA_FLASH1 = 0x0 ; + . = 0x0; + ROM_BEGIN = .; + .nds32_init : { KEEP(*(.nds32_init )) } + .interp : { *(.interp ) } + .hash : { *(.hash ) } + .dynsym : { *(.dynsym ) } + .dynstr : { *(.dynstr ) } + .gnu.version : { *(.gnu.version ) } + .gnu.version_d : { *(.gnu.version_d ) } + .gnu.version_r : { *(.gnu.version_r ) } + .rel.init : { *(.rel.init ) } + .rela.init : { *(.rela.init ) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.* ) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.* ) } + .rel.fini : { *(.rel.fini ) } + .rela.fini : { *(.rela.fini ) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.* ) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.* ) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* ) } + .rela.data.rel.ro : { *(.rel.data.rel.ro* ) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.* ) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.* ) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.* ) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.* ) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.* ) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.* ) } + .rel.ctors : { *(.rel.ctors ) } + .rela.ctors : { *(.rela.ctors ) } + .rel.dtors : { *(.rel.dtors ) } + .rela.dtors : { *(.rela.dtors ) } + .rela.dyn : { *(rela.dyn ) *(.rela__libc_subfreeres ) *(.rela__libc_atexit ) *(.rela__libc_thread_subfreeres ) *(.rela.init_array ) *(.rela.fini_array ) } + .rel.got : { *(.rel.got ) } + .rela.got : { *(.rela.got ) } + .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.* ) } + .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.* ) } + .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.* ) } + .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.* ) } + .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.* ) } + .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.* ) } + .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.* ) } + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.* ) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.* ) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.* ) } + .rel.plt : { *(.rel.plt ) } + .rela.plt : { *(.rela.plt ) } + .init : { KEEP(*(.init )) } + .plt : { *(.plt ) } + .text : { *(.text .stub .text.* .gnu.linkonce.t.* ) KEEP(*(.text.*personality* )) *(.gnu.warning ) . = ALIGN(4); } + .fini : { KEEP(*(.fini )) } + .ex9.itable : { *(.ex9.itable ) } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.* ) } + .rodata1 : { *(.rodata1 ) } + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.* ) } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.* ) } + .eh_frame_hdr : { *(.eh_frame_hdr ) } + . = ALIGN(4); + __fsymtab_start = .; + FSymTab : { KEEP(*(FSymTab )) } + . = ALIGN(4); + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + VSymTab : { KEEP(*(VSymTab )) } + . = ALIGN(4); + __vsymtab_end = .; + . = ALIGN(4); + __rt_init_start = .; + .rti_fn.0 : { KEEP(*(.rti_fn.0 )) } + .rti_fn.0.end : { KEEP(*(.rti_fn.0.end )) } + .rti_fn.1 : { KEEP(*(.rti_fn.1 )) } + .rti_fn.1.end : { KEEP(*(.rti_fn.1.end )) } + .rti_fn.2 : { KEEP(*(.rti_fn.2 )) } + .rti_fn.2.end : { KEEP(*(.rti_fn.2.end )) } + .rti_fn.3 : { KEEP(*(.rti_fn.3 )) } + .rti_fn.3.end : { KEEP(*(.rti_fn.3.end )) } + .rti_fn.4 : { KEEP(*(.rti_fn.4 )) } + .rti_fn.4.end : { KEEP(*(.rti_fn.4.end )) } + .rti_fn.5 : { KEEP(*(.rti_fn.5 )) } + .rti_fn.5.end : { KEEP(*(.rti_fn.5.end )) } + .rti_fn.6 : { KEEP(*(.rti_fn.6 )) } + .rti_fn.6.end : { KEEP(*(.rti_fn.6.end )) } + .rti_fn.7 : { KEEP(*(.rti_fn.7 )) } + .rti_fn.7.end : { KEEP(*(.rti_fn.7.end )) } + . = ALIGN(4); + __rt_init_end = .; + ROM_SIZE = . - ROM_BEGIN; + . = 0x200000; + RAM_BEGIN = .; + . = ALIGN(0x20); + __rw_lma_start = LOADADDR (.eh_frame); + __rw_vma_start = ADDR(.eh_frame); + .eh_frame : AT(ALIGN(LOADADDR (.rti_fn.7.end) + SIZEOF (.rti_fn.7.end), 32)) + { KEEP(*(.eh_frame )) } + .gcc_except_table : AT(ALIGN(LOADADDR (.eh_frame) + SIZEOF (.eh_frame), ALIGNOF(.gcc_except_table))) + { KEEP(*(.gcc_except_table )) *(.gcc_except_table.* ) } + .tdata : AT(ALIGN(LOADADDR (.gcc_except_table) + SIZEOF (.gcc_except_table), ALIGNOF(.tdata))) + { *(.tdata .tdata.* .gnu.linkonce.td.* ) } + . = ALIGN(4); + PROVIDE (__preinit_array_start = .); + .preinit_array : AT(ALIGN(ALIGN(LOADADDR (.tdata) + SIZEOF (.tdata), ALIGNOF(.preinit_array)), 4)) + { KEEP(*(.preinit_array )) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : AT(ALIGN(LOADADDR (.preinit_array) + SIZEOF (.preinit_array), ALIGNOF(.init_array))) + { KEEP(*(.init_array )) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : AT(ALIGN(LOADADDR (.init_array) + SIZEOF (.init_array), ALIGNOF(.fini_array))) + { KEEP(*(.fini_array )) } + PROVIDE (__fini_array_end = .); + .ctors : AT(ALIGN(LOADADDR (.fini_array) + SIZEOF (.fini_array), ALIGNOF(.ctors))) + { KEEP(*crtbegin*.o(.ctors)) KEEP(*(EXCLUDE_FILE (*crtend*.o) .ctors)) KEEP(*(SORT(.ctors.* ))) KEEP(*(.ctors )) } + .dtors : AT(ALIGN(LOADADDR (.ctors) + SIZEOF (.ctors), ALIGNOF(.dtors))) + { KEEP(*crtbegin*.o(.dtors)) KEEP(*(EXCLUDE_FILE (*crtend*.o) .dtors)) KEEP(*(SORT(.dtors.* ))) KEEP(*(.dtors )) } + .jcr : AT(ALIGN(LOADADDR (.dtors) + SIZEOF (.dtors), ALIGNOF(.jcr))) + { KEEP(*(.jcr )) } + .data.rel.ro : AT(ALIGN(LOADADDR (.jcr) + SIZEOF (.jcr), ALIGNOF(.data.rel.ro))) + { *(.data.rel.ro.local ) *(.data.rel.ro* ) } + .dynamic : AT(ALIGN(LOADADDR (.data.rel.ro) + SIZEOF (.data.rel.ro), ALIGNOF(.dynamic))) + { *(.dynamic ) } + .data : AT(ALIGN(LOADADDR (.dynamic) + SIZEOF (.dynamic), ALIGNOF(.data))) + { *(.data .data.* .gnu.linkonce.d.* ) KEEP(*(.gnu.linkonce.d.*personality* )) SORT(CONSTRUCTORS) . = ALIGN(8); } + .data1 : AT(ALIGN(LOADADDR (.data) + SIZEOF (.data), ALIGNOF(.data1))) + { *(.data1 ) . = ALIGN(8); } + . = ALIGN(4); + .got : AT(ALIGN(ALIGN(LOADADDR (.data1) + SIZEOF (.data1), ALIGNOF(.got)), 4)) + { *(.got.plt ) *(.got ) } + .sdata_d : AT(ALIGN(LOADADDR (.got) + SIZEOF (.got), ALIGNOF(.sdata_d))) + { *(.sdata_d .sdata_d.* ) } + .sdata_w : AT(ALIGN(LOADADDR (.sdata_d) + SIZEOF (.sdata_d), ALIGNOF(.sdata_w))) + { *(.sdata_w .sdata_w.* ) } + .sdata_h : AT(ALIGN(LOADADDR (.sdata_w) + SIZEOF (.sdata_w), ALIGNOF(.sdata_h))) + { *(.sdata_h .sdata_h.* ) } + .sdata_b : AT(ALIGN(LOADADDR (.sdata_h) + SIZEOF (.sdata_h), ALIGNOF(.sdata_b))) + { *(.sdata_b .sdata_b.* ) } + .sdata_f : AT(ALIGN(LOADADDR (.sdata_b) + SIZEOF (.sdata_b), ALIGNOF(.sdata_f))) + { *(.sdata_f .sdata_f.* ) } + . = ALIGN(4); + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + __rw_lma_end = LOADADDR (.tbss); + .tbss : AT(ALIGN(ALIGN(LOADADDR (.sdata_f) + SIZEOF (.sdata_f), ALIGNOF(.tbss)), 4)) + { *(.tbss .tbss.* .gnu.linkonce.tb.* ) *(.tcommon ) } + .sbss_f : AT(ALIGN(LOADADDR (.tbss) + SIZEOF (.tbss), ALIGNOF(.sbss_f))) + { *(.sbss_f .sbss_f.* ) *(.scommon_f .scommon_f.* ) } + .sbss_b : AT(ALIGN(LOADADDR (.sbss_f) + SIZEOF (.sbss_f), ALIGNOF(.sbss_b))) + { *(.sbss_b .sbss_b.* ) *(.scommon_b .scommon_b.* ) . = ALIGN(2); } + .sbss_h : AT(ALIGN(LOADADDR (.sbss_b) + SIZEOF (.sbss_b), ALIGNOF(.sbss_h))) + { *(.sbss_h .sbss_h.* ) *(.scommon_h .scommon_h.* ) . = ALIGN(4); } + .sbss_w : AT(ALIGN(LOADADDR (.sbss_h) + SIZEOF (.sbss_h), ALIGNOF(.sbss_w))) + { *(.sbss_w .sbss_w.* ) *(.scommon_w .scommon_w.* ) *(.dynsbss ) *(.scommon ) . = ALIGN(8); } + .sbss_d : AT(ALIGN(LOADADDR (.sbss_w) + SIZEOF (.sbss_w), ALIGNOF(.sbss_d))) + { *(.sbss_d .sbss_d.* ) *(.scommon_d .scommon_d.* ) } + .bss : AT(ALIGN(LOADADDR (.sbss_d) + SIZEOF (.sbss_d), ALIGNOF(.bss))) + { *(.dynbss ) *(.bss .bss.* .gnu.linkonce.b.* ) *(COMMON ) . = ALIGN(4); } + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + . = ALIGN(4); + _end = .; + PROVIDE (end = .); + PROVIDE (_stack = 0x24fff8); + RAM_SIZE = . - RAM_BEGIN; + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .note.nds32 0 : { *(.note.nds32) *(.note.nds32.*) } + .comment 0 : { *(.comment) } + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} +ASSERT((DEFINED (_RELAX_END_) ? ROM_SIZE : 0x0)<= 0x80000, "ROM OVERFLOW"); +ASSERT((DEFINED (_RELAX_END_) ? RAM_SIZE : 0x0)<= 0x50000, "RAM OVERFLOW"); diff --git a/bsp/AE210P/board/ae210p.sag b/bsp/AE210P/board/ae210p.sag new file mode 100644 index 0000000000000000000000000000000000000000..2c83487bf6998c1c60f9a031fef3932f89439383 --- /dev/null +++ b/bsp/AE210P/board/ae210p.sag @@ -0,0 +1,68 @@ +USER_SECTIONS FSymTab +USER_SECTIONS VSymTab +USER_SECTIONS .rti_fn.0 +USER_SECTIONS .rti_fn.0.end +USER_SECTIONS .rti_fn.1 +USER_SECTIONS .rti_fn.1.end +USER_SECTIONS .rti_fn.2 +USER_SECTIONS .rti_fn.2.end +USER_SECTIONS .rti_fn.3 +USER_SECTIONS .rti_fn.3.end +USER_SECTIONS .rti_fn.4 +USER_SECTIONS .rti_fn.4.end +USER_SECTIONS .rti_fn.5 +USER_SECTIONS .rti_fn.5.end +USER_SECTIONS .rti_fn.6 +USER_SECTIONS .rti_fn.6.end +USER_SECTIONS .rti_fn.7 +USER_SECTIONS .rti_fn.7.end +FLASH1 0x0 +{ + ROM 0x0 0x80000 ; EILM_SIZE <= 512KB + { + * (+RO) + + . = ALIGN(4); + ADDR __fsymtab_start + * KEEP( FSymTab ) + . = ALIGN(4); + ADDR __fsymtab_end + . = ALIGN(4); + ADDR __vsymtab_start + * KEEP( VSymTab ) + . = ALIGN(4); + ADDR __vsymtab_end + . = ALIGN(4); + ADDR __rt_init_start + * KEEP( .rti_fn.0 ) + * KEEP( .rti_fn.0.end ) + * KEEP( .rti_fn.1 ) + * KEEP( .rti_fn.1.end ) + * KEEP( .rti_fn.2 ) + * KEEP( .rti_fn.2.end ) + * KEEP( .rti_fn.3 ) + * KEEP( .rti_fn.3.end ) + * KEEP( .rti_fn.4 ) + * KEEP( .rti_fn.4.end ) + * KEEP( .rti_fn.5 ) + * KEEP( .rti_fn.5.end ) + * KEEP( .rti_fn.6 ) + * KEEP( .rti_fn.6.end ) + * KEEP( .rti_fn.7 ) + * KEEP( .rti_fn.7.end ) + . = ALIGN(4); + ADDR __rt_init_end + } + +; RAM 0x200000 0x80000 ; EDLM_SIZE <= 512KB + RAM 0x200000 0x50000 ; EDLM_SIZE <= 320KB + { + LOADADDR NEXT __rw_lma_start + ADDR NEXT __rw_vma_start + *(+RW) + LOADADDR NEXT __rw_lma_end + *(+ZI) +; STACK = 0x27fff8 ; 512KB + STACK = 0x24fff8 ; 320KB + } +} \ No newline at end of file diff --git a/bsp/AE210P/board/ae210p_defs.h b/bsp/AE210P/board/ae210p_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..cbfc157c6aa9af7d6ed34848687c24a6a477fbc5 --- /dev/null +++ b/bsp/AE210P/board/ae210p_defs.h @@ -0,0 +1,306 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2014 + * All Rights Reserved. + * + * Revision History: + * + * Jan.11.2014 Created. + ****************************************************************************/ + +#ifndef __AE210_DEFS_H__ +#define __AE210_DEFS_H__ + +/***************************************************************************** + * AHB_SLAVE_4_7 - AE210P AHB + ****************************************************************************/ + + +/***************************************************************************** + * BMC (APB Decoder)- AE210P AHB + ****************************************************************************/ + +/***************************************************************************** + * OSC - AE210P OSC + ****************************************************************************/ +/* OSC control Register (+0x00) */ +#define OSC_CTRL_OVL_SZ_SHIFT 24 +#define OSC_CTRL_OVLVALID_SHIFT 31 + +#define OSC_CTRL_OVL_SZ_MASK 0x07000000 +#define OSC_CTRL_OVLVALID_MASK 0x80000000 + +/* OSC Fixed Region Size Register (+0x04) */ +#define OSC_OVLFS_OVL_FSZ_MASK 0x000FFFFF + +/* OSC Overlay Region Base Register (+0x08) */ +#define OSC_OVLBASE_OVL_BASE_MASK 0x000FFFFF + +/* OSC Overlay Region End Register (+0x0C) */ +#define OSC_OVLEND_OVL_END_MASK 0x001FFFFF + +/***************************************************************************** + * DMAC - AE210P AHB + ****************************************************************************/ + +/***************************************************************************** + * AHB_SLAVE_0_3 - AE210P AHB + ****************************************************************************/ + +//TODO +//finish this table +/***************************************************************************** + * APBBR(N/A) - AE210P AHB to APB Bridge + ****************************************************************************/ + +/***************************************************************************** + * SMU - AE210P Core APB + ****************************************************************************/ + +/***************************************************************************** + * UARTx - AE210P Core APB + ****************************************************************************/ +/* Macros for specifying which UART to use. */ +#define UARTC_NUM_DEVICES 2 + +/* IER Register (+0x04) */ +#define UARTC_IER_RDR 0x01 /* Data Ready Enable */ +#define UARTC_IER_THRE 0x02 /* THR Empty Enable */ +#define UARTC_IER_RLS 0x04 /* Receive Line Status Enable */ +#define UARTC_CIER_MS 0x08 /* Modem Staus Enable */ + +/* IIR Register (+0x08) */ +#define UARTC_IIR_NONE 0x01 /* No interrupt pending */ +#define UARTC_IIR_RLS 0x06 /* Receive Line Status */ +#define UARTC_IIR_RDR 0x04 /* Receive Data Ready */ +#define UARTC_IIR_RTO 0x0c /* Receive Time Out */ +#define UARTC_IIR_THRE 0x02 /* THR Empty */ +#define UARTC_IIR_MODEM 0x00 /* Modem Status */ +#define UARTC_IIR_INT_MASK 0x0f /* Initerrupt Status Bits Mask */ + +#define UARTC_IIR_TFIFO_FULL 0x10 /* TX FIFO full */ +#define UARTC_IIR_FIFO_EN 0xc0 /* FIFO mode is enabled, set when FCR[0] is 1 */ + +/* FCR Register (+0x08) */ +#define UARTC_FCR_FIFO_EN 0x01 /* FIFO Enable */ +#define UARTC_FCR_RFIFO_RESET 0x02 /* Rx FIFO Reset */ +#define UARTC_FCR_TFIFO_RESET 0x04 /* Tx FIFO Reset */ +#define UARTC_FCR_DMA_EN 0x08 /* Select UART DMA mode */ + +#define UARTC_FCR_TFIFO16_TRGL1 0x00 /* TX 16-byte FIFO int trigger level - 1 char */ +#define UARTC_FCR_TFIFO16_TRGL3 0x10 /* TX 16-byte FIFO int trigger level - 3 char */ +#define UARTC_FCR_TFIFO16_TRGL9 0x20 /* TX 16-byte FIFO int trigger level - 9 char */ +#define UARTC_FCR_TFIFO16_TRGL13 0x30 /* TX 16-byte FIFO int trigger level - 13 char */ + +#define UARTC_FCR_RFIFO16_TRGL1 0x00 /* RX 16-byte FIFO int trigger level - 1 char */ +#define UARTC_FCR_RFIFO16_TRGL4 0x40 /* RX 16-byte FIFO int trigger level - 4 char */ +#define UARTC_FCR_RFIFO16_TRGL8 0x80 /* RX 16-byte FIFO int trigger level - 8 char */ +#define UARTC_FCR_RFIFO16_TRGL14 0xc0 /* RX 16-byte FIFO int trigger level - 14 char */ + +/* FCR Register (+0x08) */ +#define UARTC_FCR_FIFO_EN_MASK 0x01 /* FIFO Enable */ +#define UARTC_FCR_FIFO_EN_BIT 0 +#define UARTC_FCR_RFIFO_RESET_MASK 0x02 /* Rx FIFO Reset */ +#define UARTC_FCR_RFIFO_RESET_BIT 1 +#define UARTC_FCR_TFIFO_RESET_MASK 0x04 /* Tx FIFO Reset */ +#define UARTC_FCR_TFIFO_RESET_BIT 2 +#define UARTC_FCR_DMA_EN_MASK 0x08 /* Select UART DMA mode */ +#define UARTC_FCR_DMA_EN_BIT 3 + +#define UARTC_FCR_TXFIFO_TRGL_MASK 0x30 /* TX FIFO int trigger level */ +#define UARTC_FCR_TXFIFO_TRGL_SHIFT 4 +#define UARTC_FCR_RXFIFO_TRGL_MASK 0xc0 /* RX FIFO int trigger level */ +#define UARTC_FCR_RXFIFO_TRGL_SHIFT 6 + +/* LCR Register (+0x0c) */ +#define UARTC_LCR_BITS5 0x00 +#define UARTC_LCR_BITS6 0x01 +#define UARTC_LCR_BITS7 0x02 +#define UARTC_LCR_BITS8 0x03 +#define UARTC_LCR_STOP1 0x00 +#define UARTC_LCR_STOP2 0x04 + +#define UARTC_LCR_PARITY_EN 0x08 /* Parity Enable */ +#define UARTC_LCR_PARITY_NONE 0x00 /* No Parity Check */ +#define UARTC_LCR_PARITY_EVEN 0x18 /* Even Parity */ +#define UARTC_LCR_PARITY_ODD 0x08 /* Odd Parity */ +#if 0 +#define UARTC_LCR_PARITY_1 0x21 /* 1 Parity Bit */ +#define UARTC_LCR_PARITY_0 0x31 /* 0 Parity Bit */ +#endif +#define UARTC_LCR_SETBREAK 0x40 /* Set Break condition */ +#define UARTC_LCR_DLAB 0x80 /* Divisor Latch Access Bit */ + +/* MCR Register (+0x10) */ +#define UARTC_MCR_DTR 0x01 /* Data Terminal Ready */ +#define UARTC_MCR_RTS 0x02 /* Request to Send */ +#define UARTC_MCR_OUT1 0x04 /* output1 */ +#define UARTC_MCR_OUT2 0x08 /* output2 or global interrupt enable */ +#define UARTC_MCR_LPBK 0x10 /* loopback mode */ +#define UARTC_MCR_DMAMODE2 0x20 /* DMA mode2 */ +#define UARTC_MCR_OUT3 0x40 /* output 3 */ + +/* LSR Register (+0x14) */ +#define UARTC_LSR_RDR 0x1 /* Data Ready */ +#define UARTC_LSR_OE 0x2 /* Overrun Error */ +#define UARTC_LSR_PE 0x4 /* Parity Error */ +#define UARTC_LSR_FE 0x8 /* Framing Error */ +#define UARTC_LSR_BI 0x10 /* Break Interrupt */ +#define UARTC_LSR_THRE 0x20 /* THR/FIFO Empty */ +#define UARTC_LSR_TE 0x40 /* THR/FIFO and TFR Empty */ +#define UARTC_LSR_DE 0x80 /* FIFO Data Error */ + +/* MSR Register (+0x18) */ +#define UARTC_MSR_DELTACTS 0x1 /* Delta CTS */ +#define UARTC_MSR_DELTADSR 0x2 /* Delta DSR */ +#define UARTC_MSR_TERI 0x4 /* Trailing Edge RI */ +#define UARTC_MSR_DELTACD 0x8 /* Delta CD */ +#define UARTC_MSR_CTS 0x10 /* Clear To Send */ +#define UARTC_MSR_DSR 0x20 /* Data Set Ready */ +#define UARTC_MSR_RI 0x40 /* Ring Indicator */ +#define UARTC_MSR_DCD 0x80 /* Data Carrier Detect */ + +/* MDR register (+0x20) */ +#define UARTC_MDR_MODE_SEL_SHIFT 0 +#define UARTC_MDR_SIP_BYCPU_BIT 2 +#define UARTC_MDR_FMEND_MD_BIT 3 +#define UARTC_MDR_DMA_EN_BIT 4 +#define UARTC_MDR_FIR_INV_RX_BIT 5 +#define UARTC_MDR_IR_INV_TX_BIT 6 +#define UARTC_MDR_MODE_SEL_MASK 0x03 +#define UARTC_MDR_SIP_BYCPU_MASK 0x04 /* 0: 1.6us end pulse; 1: depends on ACR[4] */ +#define UARTC_MDR_FMEND_MD_MASK 0x08 /* 0: Frame length counter method; 1: Set end of transmission bit method */ +#define UARTC_MDR_DMA_EN_MASK 0x10 /* Enable DMA mode. (PIO int should turn off) */ +#define UARTC_MDR_FIR_INV_RX_MASK 0x20 /* (FIR only) Invert receiver input signal */ +#define UARTC_MDR_IR_INV_TX_MASK 0x40 /* (FIR/SIR) Invert pulse during transmission */ + +#define UARTC_MDR_MODE_UART 0 +#define UARTC_MDR_MODE_SIR 1 +#define UARTC_MDR_MODE_FIR 2 + +/* ACR register (+0x24) */ +#define UARTC_ACR_IR_TX_EN 0x01 +#define UARTC_ACR_IR_RX_EN 0x02 +#define UARTC_ACR_FIR_SETEOT 0x04 + +/***************************************************************************** + * PIT - AG101 Core APB + ****************************************************************************/ + +/* Interrupt Enable Register */ +#define PIT_CH_NUM_MASK 0x7 + +/* Channel & Interrupt Enable Reg */ +#define PIT_C0_TMR0_EN 0x1 +#define PIT_C0_TMR1_EN 0x2 +#define PIT_C0_TMR2_EN 0x4 +#define PIT_C0_TMR3_EN 0x8 + +#define PIT_C1_TMR0_EN 0x10 +#define PIT_C1_TMR1_EN 0x20 +#define PIT_C1_TMR2_EN 0x40 +#define PIT_C1_TMR3_EN 0x80 + +#define PIT_C2_TMR0_EN 0x100 +#define PIT_C2_TMR1_EN 0x200 +#define PIT_C2_TMR2_EN 0x400 +#define PIT_C2_TMR3_EN 0x800 + +#define PIT_C3_TMR0_EN 0x1000 +#define PIT_C3_TMR1_EN 0x2000 +#define PIT_C3_TMR2_EN 0x4000 +#define PIT_C3_TMR3_EN 0x8000 + +/* Interrupt Status Register */ +/* Clean Timer interrupt pending bit, write 1 clean */ +#define PIT_C0_TMR0_PEND_W1C 0x1 +#define PIT_C0_TMR1_PEND_W1C 0x2 +#define PIT_C0_TMR2_PEND_W1C 0x4 +#define PIT_C0_TMR3_PEND_W1C 0x8 + +#define PIT_C1_TMR0_PEND_W1C 0x10 +#define PIT_C1_TMR1_PEND_W1C 0x20 +#define PIT_C1_TMR2_PEND_W1C 0x40 +#define PIT_C1_TMR3_PEND_W1C 0x80 + +#define PIT_C2_TMR0_PEND_W1C 0x100 +#define PIT_C2_TMR1_PEND_W1C 0x200 +#define PIT_C2_TMR2_PEND_W1C 0x400 +#define PIT_C2_TMR3_PEND_W1C 0x800 + +#define PIT_C3_TMR0_PEND_W1C 0x1000 +#define PIT_C3_TMR1_PEND_W1C 0x2000 +#define PIT_C3_TMR2_PEND_W1C 0x4000 +#define PIT_C3_TMR3_PEND_W1C 0x8000 + +/* channel 0~3 control register */ +/* ChClk*/ +#define PIT_CH_CTL_APBCLK 0x8 +/* ChMode*/ +#define PIT_CH_CTL_TMR32 0x1 +#define PIT_CH_CTL_TMR16 0x2 +#define PIT_CH_CTL_TMR8 0x3 +#define PIT_CH_CTL_PWM 0x4 +#define PIT_CH_CTL_MIX16 0x6 +#define PIT_CH_CTL_MIX8 0x7 + + +/***************************************************************************** + * WDT - AG101 Core APB + ****************************************************************************/ + +//TODO +//finish this table +/***************************************************************************** + * RTC - AE210P APB + ****************************************************************************/ + + +//TODO +//Finish this table +/***************************************************************************** + * GPIO - AE210P APB + ****************************************************************************/ + +/***************************************************************************** + * I2C - AG101 Core APB + ****************************************************************************/ + +/***************************************************************************** + * SPI1 - AG101 Core APB + ****************************************************************************/ + +/***************************************************************************** + * SPI2 - AG101 Core APB + ****************************************************************************/ + +/***************************************************************************** + * APB_SLAVE_0_4 - AG101 Core APB + ****************************************************************************/ + + +/***************************************************************************** + * Interface & Definitions + ****************************************************************************/ + +/* TODO: timer-polling method */ +#if (defined(CONFIG_CPU_ICACHE_ENABLE) && defined(CONFIG_CPU_DCACHE_ENABLE)) + +#define _nds_kwait(count) \ + do { \ + volatile uint32_t i = 0; \ + while (i++ < (uint32_t)(count)) \ + ; \ + } while(0) +#else + +#define _nds_kwait(count) \ + do { \ + volatile uint32_t i = 0; \ + uint32_t c = (count > 0x10) ? count / 0x10 : 0x10; \ + while (i++ < (uint32_t)(c)) \ + ; \ + } while(0) +#endif + +#endif /* __AE210P_DEFS_H__ */ diff --git a/bsp/AE210P/board/ae210p_regs.h b/bsp/AE210P/board/ae210p_regs.h new file mode 100644 index 0000000000000000000000000000000000000000..9c2f04eb9e7cd598a2147e8fe664a658b62d51b5 --- /dev/null +++ b/bsp/AE210P/board/ae210p_regs.h @@ -0,0 +1,315 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2014 + * All Rights Reserved. + * + ****************************************************************************/ + +#ifndef __AE210P_REGS_H__ +#define __AE210P_REGS_H__ + +#ifndef __ASSEMBLER__ +#include +#include +#endif + +#if (defined(CONFIG_CPU_ICACHE_ENABLE) || defined(CONFIG_CPU_DCACHE_ENABLE)) +/* + * The NTC1 is set to noncache region and NTM1 is mapped to partition 0 (I/O region). + * Map the I/O address to NTC1 to be uncachable. + */ +#define UNCACHE_MAP(addr) ((addr) | 0x40000000) +#else +#define UNCACHE_MAP(addr) (addr) +#endif + +#define _IO_(addr) UNCACHE_MAP(addr) + + +/***************************************************************************** + * ExLM - AE210P AHB + * **************************************************************************/ +#define EILM_BASE 0x00000000 +#ifdef CONFIG_OSC_SUPPORT +#define EDLM_BASE 0x00100000 +#else +#define EDLM_BASE 0x00200000 +#endif +#define SPIAHBMEM_BASE 0x00800000 + +/***************************************************************************** + * AHBC - AE210P AHB + ****************************************************************************/ +#define AHBC_BASE_4_7 _IO_(0x00400000) /* Vendor AHB Slave 8~9 */ +#define AHBC_BASE_0_3 _IO_(0x00E20000) /* Vendor AHB Slave 0~7 */ + +/***************************************************************************** + * BMC - AE210P AHB + ****************************************************************************/ +#define BMC_BASE _IO_(0x00E00000) /* Device base address */ + +/***************************************************************************** + * OSC - AE210P OSC + ****************************************************************************/ +#define OSC_BASE _IO_(0x00E01000) + +/* OSC register */ +#define OSC_CTRL (OSC_BASE + 0x00) +#define OSC_OVLFS (OSC_BASE + 0x04) +#define OSC_OVLBASE (OSC_BASE + 0x08) +#define OSC_OVLEND (OSC_BASE + 0x0C) +#define OSC_DMAST (OSC_BASE + 0x10) + +/***************************************************************************** + * DMAC - AE210P AHB + ****************************************************************************/ +#define DMAC_BASE _IO_(0x00E0E000) /* Device base address */ + +/***************************************************************************** + * APBBRG - AE210P APB + ****************************************************************************/ +#define APBBR_BASE _IO_(0x00F00000) /* Device base address */ + +/***************************************************************************** + * SMU - AE210P + ****************************************************************************/ +#define SMU_BASE _IO_(0x00F01000) /* Device base address */ + +/***************************************************************************** + * UARTx - AE210P + ****************************************************************************/ +#define UART1_BASE _IO_(0x00F02000) /* Device base address */ +#define UART2_BASE _IO_(0x00F03000) /* Device base address */ +#define STUARTC_BASE UART2_BASE /* standard/IR UART */ + +/* UART register offsets (4~8-bit width) */ +/* SD_LCR_DLAB == 0 */ +#define UARTC_RBR_OFFSET 0x20 /* receiver biffer register */ +#define UARTC_THR_OFFSET 0x20 /* transmitter holding register */ +#define UARTC_IER_OFFSET 0x24 /* interrupt enable register */ +#define UARTC_IIR_OFFSET 0x28 /* interrupt identification register */ +#define UARTC_FCR_OFFSET 0x28 /* FIFO control register */ +#define UARTC_LCR_OFFSET 0x2c /* line control regitser */ +#define UARTC_MCR_OFFSET 0x30 /* modem control register */ +#define UARTC_LSR_OFFSET 0x34 /* line status register */ +#define UARTC_TST_OFFSET 0x34 /* testing register */ +#define UARTC_MSR_OFFSET 0x38 /* modem status register */ +#define UARTC_SPR_OFFSET 0x3c /* scratch pad register */ + +/* SD_LCR_DLAB == 0 */ +#define UARTC_DLL_OFFSET 0x20 /* baudrate divisor latch LSB */ +#define UARTC_DLM_OFFSET 0x24 /* baudrate divisor latch MSB */ +#define UARTC_PSR_OFFSET 0x28 /* prescaler register */ + + +/***************************************************************************** + * PIT - AE210P + ****************************************************************************/ +#define PIT_BASE _IO_(0x00F04000) /* Device base address */ + +/* PIT register (32-bit width) */ +#define PIT_ID_REV (PIT_BASE + 0x00 ) /* (ro) PIT ID and Revision Register */ +#define PIT_CFG (PIT_BASE + 0x10 ) /* (ro) PIT Configuration Register */ +#define PIT_INT_EN (PIT_BASE + 0x14 ) /* (rw) PIT Interrupt Enable Register*/ +#define PIT_INT_ST (PIT_BASE + 0x18 ) /* (w1c) PIT Interrupt Status Register*/ +#define PIT_CH_EN (PIT_BASE + 0x1C ) /* (rw) PIT Channel Enable Register */ + +/* _chn_ from 0 to 3*/ +/* (rw) PIT Channel x Control Register (32-bit width) */ +#define PIT_CHNx_CTL(_chn_) ( PIT_BASE + 0x20 + ( (_chn_)* 0x10) ) + +/* (rw) PIT Channel x Reload Register (32-bit width) */ +#define PIT_CHNx_LOAD(_chn_) ( PIT_BASE + 0x24 + ( (_chn_)* 0x10) ) + +/* (ro) PIT Channel x Counter Register (32-bit width) */ +#define PIT_CHNx_COUNT(_chn_) ( PIT_BASE + 0x28 + ( (_chn_)* 0x10) ) + + +/***************************************************************************** + * WDT - AE210P + ****************************************************************************/ +#define WDTC_BASE _IO_(0x00F05000) /* Device base address */ + +/***************************************************************************** + * RTC - AE210P + ****************************************************************************/ +#define RTC_BASE _IO_(0x00F06000) /* Device base address */ + +/***************************************************************************** + * GPIO - AE210P + ****************************************************************************/ +#define GPIOC_BASE _IO_(0x00F07000) /* Device base address */ + +/***************************************************************************** + * I2C - AE210P + ****************************************************************************/ +#define I2C_BASE _IO_(0x00F0A000) /* Device base address */ + +/***************************************************************************** + * SPI1 - AE210P + ****************************************************************************/ +#define SPI1_BASE _IO_(0x00F0B000) /* Device base address */ + +/***************************************************************************** + * I2S/AC97 - AE210P (SSP2) + ****************************************************************************/ +#define SPI2_BASE _IO_(0x00F0F000) /* Device base address */ + +/***************************************************************************** + * APB_SLAVE - AE210P Vender APB Slave 0~4 + ****************************************************************************/ +#define APB_SLAVE_BASE _IO_(0x00F19000) /* Device base address */ + + +/***************************************************************************** + * Macros for Register Access + ****************************************************************************/ +#define REG32(reg) ( *( (volatile uint32_t *) (reg) ) ) + +#ifdef REG_IO_HACK + +/* 8 bit access */ +//#define IN8(reg) ( *( (volatile uint8_t *) (reg) ) ) +#define OUT8(reg, data) ( (*( (volatile uint8_t *) (reg) ) ) = (uint8_t)(data) ) + +#define CLR8(reg) ( *( (volatile uint8_t *) (reg) ) = (uint8_t)0 ) +#define MASK8(reg, mask) ( *( (volatile uint8_t *) (reg) ) & (uint8_t)(mask) ) +#define UMSK8(reg, mask) ( *( (volatile uint8_t *) (reg) ) & ~( (uint8_t)(mask) ) ) + +#define SETR8SHL(reg, mask, shift, v) ( *( (volatile uint8_t *) (reg) ) = \ + ( ( *( (volatile uint8_t *) (reg) ) & ~( (uint8_t)(mask) ) ) | \ + ( ( (uint8_t)(v) << (shift) ) & (uint8_t)(mask) ) ) ) + +#define SETR8(reg, mask) ( *( (volatile uint8_t *) (reg) ) = \ + ( ( *( (volatile uint8_t *) (reg) ) & ~( (uint8_t)(mask) ) ) | (uint8_t)(mask) ) ) + +#define CLRR8(reg, mask) ( *( (volatile uint8_t *) (reg) ) &= ~( (uint8_t)(mask) ) ) + +#define SETB8(reg, bit) ( *( (volatile uint8_t *) (reg) ) |= (uint8_t)( (uint8_t)1 << (bit) ) ) +#define CLRB8(reg, bit) ( *( (volatile uint8_t *) (reg) ) &= ( ~( (uint8_t) ( (uint8_t)1 << (bit) ) ) ) ) +#define GETB8(reg, bit) ( *( (volatile uint8_t *) (reg) ) & (uint8_t) ( (uint8_t)1 << (bit) ) ) +#define GETB8SHR(reg, bit) ( (*( (volatile uint8_t *) (reg) ) & (uint8_t) ( (uint8_t)1 << (bit) )) >> (bit) ) + +/* 16 bit access */ +#define IN16(reg) ( *( (volatile uint16_t *) (reg) ) ) +#define OUT16(reg, data) ( (*( (volatile uint16_t *) (reg) ) ) = (uint16_t)(data) ) + +#define CLR16(reg) ( *( (volatile uint16_t *) (reg) ) = (uint16_t)0 ) +#define MASK16(reg, mask) ( *( (volatile uint16_t *) (reg) ) & (uint16_t)(mask) ) +#define UMSK16(reg, mask) ( *( (volatile uint16_t *) (reg) ) & ~( (uint16_t)(mask) ) ) + +#define SETR16SHL(reg, mask, shift, v) ( *( (volatile uint16_t *) (reg) ) = \ + ( ( *( (volatile uint16_t *) (reg) ) & ~( (uint16_t)(mask) ) ) | \ + ( ( (uint16_t)(v) << (shift) ) & (uint16_t)(mask) ) ) ) + +#define SETR16(reg, mask) ( *( (volatile uint16_t *) (reg) ) = \ + ( ( *( (volatile uint16_t *) (reg) ) & ~( (uint16_t)(mask) ) ) | (uint16_t)(mask) ) ) + +#define CLRR16(reg, mask) ( *( (volatile uint16_t *) (reg) ) &= ~( (uint16_t)(mask) ) ) + +#define SETB16(reg, bit) ( *( (volatile uint16_t *) (reg) ) |= (uint16_t)( (uint16_t)1 << (bit) ) ) +#define CLRB16(reg, bit) ( *( (volatile uint16_t *) (reg) ) &= ( ~( (uint16_t) ( (uint16_t)1 << (bit) ) ) ) ) +#define GETB16(reg, bit) ( *( (volatile uint16_t *) (reg) ) & (uint16_t) ( (uint16_t)1 << (bit) ) ) +#define GETB16SHR(reg, bit) ( (*( (volatile uint16_t *) (reg) ) & (uint16_t) ( (uint16_t)1 << (bit) )) >> (bit) ) + +/* 32 bit access */ +#define IN32(reg) _IN32((uint32_t)(reg)) +#define OUT32(reg, data) _OUT32((uint32_t)(reg), (uint32_t)(data)) + +#define CLR32(reg) _CLR32((uint32_t)(reg)) +#define MASK32(reg, mask) _MASK32((uint32_t)(reg), (uint32_t)(mask)) +#define UMSK32(reg, mask) _UMSK32((uint32_t)(reg), (uint32_t)(mask)) + +#define SETR32SHL(reg, mask, shift, v) _SETR32SHL((uint32_t)(reg), (uint32_t)(mask), (uint32_t)(shift), (uint32_t)(v)) +#define SETR32(reg, mask) _SETR32((uint32_t)(reg), (uint32_t)(mask)) +#define CLRR32(reg, mask) _CLRR32((uint32_t)(reg), (uint32_t)(mask)) + +#define SETB32(reg, bit) _SETB32((uint32_t)(reg), (uint32_t)(bit)) +#define CLRB32(reg, bit) _CLRB32((uint32_t)(reg), (uint32_t)(bit)) +#define GETB32(reg, bit) _GETB32((uint32_t)(reg), (uint32_t)(bit)) +#define GETB32SHR(reg, bit) _GETB32SHR((uint32_t)(reg), (uint32_t)(bit)) + +#else /* REG_IO_HACK */ + +/* 8 bit access */ +//#define IN8(reg) ( *( (volatile uint8_t *) (reg) ) ) +#define OUT8(reg, data) ( (*( (volatile uint8_t *) (reg) ) ) = (uint8_t)(data) ) + +#define CLR8(reg) ( *( (volatile uint8_t *) (reg) ) = (uint8_t)0 ) +#define MASK8(reg, mask) ( *( (volatile uint8_t *) (reg) ) & (uint8_t)(mask) ) +#define UMSK8(reg, mask) ( *( (volatile uint8_t *) (reg) ) & ~( (uint8_t)(mask) ) ) + +#define SETR8SHL(reg, mask, shift, v) ( *( (volatile uint8_t *) (reg) ) = \ + ( ( *( (volatile uint8_t *) (reg) ) & ~( (uint8_t)(mask) ) ) | \ + ( ( (uint8_t)(v) << (shift) ) & (uint8_t)(mask) ) ) ) + +#define SETR8(reg, mask) ( *( (volatile uint8_t *) (reg) ) = \ + ( ( *( (volatile uint8_t *) (reg) ) & ~( (uint8_t)(mask) ) ) | (uint8_t)(mask) ) ) + +#define CLRR8(reg, mask) ( *( (volatile uint8_t *) (reg) ) &= ~( (uint8_t)(mask) ) ) + +#define SETB8(reg, bit) ( *( (volatile uint8_t *) (reg) ) |= (uint8_t)( (uint8_t)1 << (bit) ) ) +#define CLRB8(reg, bit) ( *( (volatile uint8_t *) (reg) ) &= ( ~( (uint8_t) ( (uint8_t)1 << (bit) ) ) ) ) +#define GETB8(reg, bit) ( *( (volatile uint8_t *) (reg) ) & (uint8_t) ( (uint8_t)1 << (bit) ) ) +#define GETB8SHR(reg, bit) ( (*( (volatile uint8_t *) (reg) ) & (uint8_t) ( (uint8_t)1 << (bit) )) >> (bit) ) + +/* 16 bit access */ +#define IN16(reg) ( *( (volatile uint16_t *) (reg) ) ) +#define OUT16(reg, data) ( (*( (volatile uint16_t *) (reg) ) ) = (uint16_t)(data) ) + +#define CLR16(reg) ( *( (volatile uint16_t *) (reg) ) = (uint16_t)0 ) +#define MASK16(reg, mask) ( *( (volatile uint16_t *) (reg) ) & (uint16_t)(mask) ) +#define UMSK16(reg, mask) ( *( (volatile uint16_t *) (reg) ) & ~( (uint16_t)(mask) ) ) + +#define SETR16SHL(reg, mask, shift, v) ( *( (volatile uint16_t *) (reg) ) = \ + ( ( *( (volatile uint16_t *) (reg) ) & ~( (uint16_t)(mask) ) ) | \ + ( ( (uint16_t)(v) << (shift) ) & (uint16_t)(mask) ) ) ) + +#define SETR16(reg, mask) ( *( (volatile uint16_t *) (reg) ) = \ + ( ( *( (volatile uint16_t *) (reg) ) & ~( (uint16_t)(mask) ) ) | (uint16_t)(mask) ) ) +#define CLRR16(reg, mask) ( *( (volatile uint16_t *) (reg) ) &= ~( (uint16_t)(mask) ) ) + +#define SETB16(reg, bit) ( *( (volatile uint16_t *) (reg) ) |= (uint16_t)( (uint16_t)1 << (bit) ) ) +#define CLRB16(reg, bit) ( *( (volatile uint16_t *) (reg) ) &= ( ~( (uint16_t) ( (uint16_t)1 << (bit) ) ) ) ) +#define GETB16(reg, bit) ( *( (volatile uint16_t *) (reg) ) & (uint16_t) ( (uint16_t)1 << (bit) ) ) +#define GETB16SHR(reg, bit) ( (*( (volatile uint16_t *) (reg) ) & (uint16_t) ( (uint16_t)1 << (bit) )) >> (bit) ) + +/* 32 bit access */ +#define IN32(reg) ( *( (volatile uint32_t *) (reg) ) ) +#define OUT32(reg, data) ( (*( (volatile uint32_t *) (reg) ) ) = (uint32_t)(data) ) + +#define CLR32(reg) ( *( (volatile uint32_t *) (reg) ) = (uint32_t)0 ) +#define MASK32(reg, mask) ( *( (volatile uint32_t *) (reg) ) & (uint32_t)(mask) ) +#define UMSK32(reg, mask) ( *( (volatile uint32_t *) (reg) ) & ~( (uint32_t)(mask) ) ) + +#define SETR32SHL(reg, mask, shift, v) ( *( (volatile uint32_t *) (reg) ) = \ + ( ( *( (volatile uint32_t *) (reg) ) & ~( (uint32_t)(mask) ) ) | \ + ( ( (uint32_t)(v) << (shift) ) & (uint32_t)(mask) ) ) ) + +#define SETR32(reg, mask) ( *( (volatile uint32_t *) (reg) ) = \ + ( ( *( (volatile uint32_t *) (reg) ) & ~( (uint32_t)(mask) ) ) | (uint32_t)(mask) ) ) + +#define CLRR32(reg, mask) ( *( (volatile uint32_t *) (reg) ) &= ~( (uint32_t)(mask) ) ) + +#define SETB32(reg, bit) ( *( (volatile uint32_t *) (reg) ) |= (uint32_t)( (uint32_t)1 << (bit) ) ) +#define CLRB32(reg, bit) ( *( (volatile uint32_t *) (reg) ) &= ( ~( (uint32_t) ( (uint32_t)1 << (bit) ) ) ) ) +#define GETB32(reg, bit) ( *( (volatile uint32_t *) (reg) ) & (uint32_t) ( (uint32_t)1 << (bit) ) ) +#define GETB32SHR(reg, bit) ( (*( (volatile uint32_t *) (reg) ) & (uint32_t) ( (uint32_t)1 << (bit) )) >> (bit) ) + +#endif /* REG_IO_HACK */ + +#define SR_CLRB32(reg, bit) \ +{ \ + int mask = __nds32__mfsr(reg)& ~(1<parent.user_data; + + __drv_uart_init(uartDev->uart_base, cfg->baud_rate); + + // todo : enable FIFO threshold, enable rx & rx timeout(threshold) interrupt + + return RT_EOK; +} + +static rt_err_t __uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct uart_device *uartDev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + uartDev = (struct uart_device *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: /* disable rx irq */ + UART_DISABLE_IRQ(uartDev->irq); + break; + + case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ + UART_ENABLE_IRQ(uartDev->irq); + break; + + default: + break; + } + + return RT_EOK; +} + +static int __uart_putc(struct rt_serial_device *serial, char c) +{ + struct uart_device *uartDev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uartDev = (struct uart_device *)serial->parent.user_data; + + __drv_uart_put_char(uartDev->uart_base, c); // Transmit Data + + return 1; +} + +static int __uart_getc(struct rt_serial_device *serial) +{ + int ch = -1; + struct uart_device *uartDev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + uartDev = (struct uart_device *)serial->parent.user_data; + + ch = -1; + + if (__drv_uart_is_kbd_hit(uartDev->uart_base)) + { + ch = __drv_uart_get_char(uartDev->uart_base) & 0x00FF; + } + + return ch; +} + +static const struct rt_uart_ops __uart_ops = +{ + __uart_configure, + __uart_control, + __uart_putc, + __uart_getc, + RT_NULL +}; + +#if RT_USING_UART01 +struct uart_device uartDev01 = +{ // UART01 device driver structure + UART1_BASE, + IRQ_UART1_VECTOR +}; + +struct rt_serial_device serial01; + +void URT01_IRQHandler(void) +{ + struct uart_device *uartDev = RT_NULL; + + uartDev = &uartDev01; + + rt_interrupt_enter(); /* enter interrupt */ + +// if (uart->uart_device->Interrupt & ((1 << bsUART_TIMEOUT_INTENAB) | (1 << bsUART_RECEIVE_INTENAB))) // RX +// { +// rt_hw_serial_isr(&serial01, RT_SERIAL_EVENT_RX_IND); +// } +// +// if (uart->uart_device->Interrupt & (1 << bsUART_TRANSMIT_INTENAB)) // TX +// { +// ; +// } +// +// /* clear all interrupt */ +// uart->uart_device->IntClear = (1 << bsUART_RECEIVE_INTENAB) +// | (1 << bsUART_TRANSMIT_INTENAB) +// | (1 << bsUART_TIMEOUT_INTENAB); + + rt_interrupt_leave(); /* leave interrupt */ +} +#endif /* RT_USING_UART01 */ + +#if RT_USING_UART02 +struct uart_device uartDev02 = +{ // UART02 device driver structure + UART2_BASE, + IRQ_UATR2_VECTOR +}; + +struct rt_serial_device serial02; + +void URT02_IRQHandler(void) +{ + struct uart_device *uartDev = RT_NULL; + + uartDev = &uartDev02; + + rt_interrupt_enter(); /* enter interrupt */ + + uartDev = uartDev; + + rt_interrupt_leave(); /* leave interrupt */ +} +#endif /* RT_USING_UART02 */ + +void rt_hw_usart_init(void) +{ + struct uart_device *uartDev = RT_NULL; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#if RT_USING_UART01 + uart = &uartDev01; + config.baud_rate = BAUD_RATE_38400; + + serial01.ops = &__uart_ops; + serial01.config = config; + + // set interrupt priority level + // disable interrupt + + // register UART01 device + rt_hw_serial_register(&serial01, "uart01", + RT_DEVICE_FLAG_RDWR /*| RT_DEVICE_FLAG_INT_RX*/, + uartDev); +#endif /* RT_USING_UART01 */ + +#if RT_USING_UART02 + uartDev = &uartDev02; + + config.baud_rate = BAUD_RATE_38400; + serial02.ops = &__uart_ops; + serial02.config = config; + + // set interrupt priority level + // disable interrupt + + /* register UART02 device */ + rt_hw_serial_register(&serial02, "uart02", + RT_DEVICE_FLAG_RDWR /*| RT_DEVICE_FLAG_INT_RX*/, + uartDev); + #endif /* RT_USING_UART02 */ +} + diff --git a/bsp/AE210P/board/uart_dev.h b/bsp/AE210P/board/uart_dev.h new file mode 100644 index 0000000000000000000000000000000000000000..5cc57d04d8730574c42833e261ce3fa7d687ccb6 --- /dev/null +++ b/bsp/AE210P/board/uart_dev.h @@ -0,0 +1,23 @@ +/* + * File : uart_dev.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-01-05 Bernard the first version + */ + +#ifndef __UART_DEV_H__ +#define __UART_DEV_H__ + +#include "rthw.h" +#include "rtthread.h" + +void rt_hw_usart_init(void); + +#endif // end of "__UART_DEV_H__" diff --git a/bsp/AE210P/bsp_hal.h b/bsp/AE210P/bsp_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..c93a906c6d63c020bb961a067f2f6b45af2aef0b --- /dev/null +++ b/bsp/AE210P/bsp_hal.h @@ -0,0 +1,77 @@ +#ifndef __PLAT_HAL_H_ +#define __PLAT_HAL_H_ + +#include "inttypes.h" + + +/******************************** + * INTC HAL DEFINE + ********************************/ + +#define IRQ_EDGE_TRIGGER 1 +#define IRQ_LEVEL_TRIGGER 0 + +#define IRQ_ACTIVE_HIGH 1 +#define IRQ_ACTIVE_LOW 0 + +void hal_intc_init(); +void hal_intc_swi_enable(); +void hal_intc_swi_disable(); +void hal_intc_swi_clean(); +void hal_intc_swi_trigger(); + +/* Call by HISR. + * Since our mask/unmask are not atomic. + * And HISR is task level ISR in RTOS, we need make sure it is atomic. + * + * TODO remove gie if atomic + */ +#define HAL_INTC_IRQ_ATOMIC_DISABLE(_irq_) \ + do \ + { \ + unsigned long _gie_; \ + GIE_SAVE(&_gie_); \ + hal_intc_irq_disable(_irq_); \ + GIE_RESTORE(_gie_); \ + } while(0) + +#define HAL_INTC_IRQ_ATOMIC_ENABLE(_irq_) \ + do \ + { \ + unsigned long _gie_; \ + GIE_SAVE(&_gie_); \ + hal_intc_irq_enable(_irq_); \ + GIE_RESTORE(_gie_); \ + } while(0) + + +uint32_t hal_intc_irq_mask(int _irqs_); +void hal_intc_irq_unmask(int _irqs_); +void hal_intc_irq_clean(int _irqs_); +void hal_intc_irq_clean_all(); +void hal_intc_irq_enable(uint32_t _irqs_); +void hal_intc_irq_disable(uint32_t _irqs_); +void hal_intc_irq_disable_all(); +void hal_intc_irq_set_priority(uint32_t _prio_ ); +void hal_intc_irq_config(uint32_t _irqs_, uint32_t _edge_, uint32_t _falling_); +uint32_t hal_intc_get_all_pend(); + +/******************************** + * TIMER HAL DEFINE + ********************************/ + +uint32_t hal_timer_irq_mask(uint32_t _tmr_ ); +void hal_timer_irq_unmask(uint32_t _msk_ ); +void hal_timer_irq_clear(uint32_t _tmr_ ); +void hal_timer_start(uint32_t _tmr_); +void hal_timer_stop(uint32_t _tmr_ ); +uint32_t hal_timer_read(uint32_t _tmr_ ); +void hal_timer_set_period(uint32_t _tmr_, uint32_t _period_ ); +void hal_timer_set_upward(uint32_t _tmr_ ,uint32_t up); +void hal_timer_init(uint32_t _tmr_ ); +void hal_timer_irq_control(uint32_t _tmr_, uint32_t enable ); +uint32_t hal_timer_irq_status(uint32_t _tmr_); +void hal_timer_set_match1(uint32_t _tmr_ , uint32_t match ); +uint32_t hal_timer_count_read(uint32_t _tmr_); + +#endif diff --git a/bsp/AE210P/cache.c b/bsp/AE210P/cache.c new file mode 100644 index 0000000000000000000000000000000000000000..97cb251741ee6e0cb02612b0bb8ac4ad722b8353 --- /dev/null +++ b/bsp/AE210P/cache.c @@ -0,0 +1,273 @@ +#include "nds32.h" +#include "cache.h" +#include "string.h" + +void nds32_dcache_invalidate(void){ + +#ifdef CONFIG_CPU_DCACHE_ENABLE + __nds32__cctl_l1d_invalall(); + + __nds32__msync_store(); + __nds32__dsb(); +#endif +} + +void nds32_dcache_flush(void){ + +#ifdef CONFIG_CPU_DCACHE_ENABLE + +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + unsigned long saved_gie; +#endif + unsigned long end; + unsigned long cache_line; + + cache_line = CACHE_LINE_SIZE(DCACHE); + end = CACHE_WAY(DCACHE) * CACHE_SET(DCACHE) * cache_line; + +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + GIE_SAVE(&saved_gie); + + /* + * Use CCTL L1D_IX_WB/L1D_IX_INVAL subtype instead of combined + * L1D_IX_WBINVAL. Because only N903 supports L1D_IX_WBINVAL. + */ + do { + end -= cache_line; + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB, end); + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL, end); + } while (end > 0); + GIE_RESTORE(saved_gie); +#else + while (end > 0){ + end -= cache_line; + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL, end); + } +#endif + __nds32__msync_store(); + __nds32__dsb(); +#endif +} + +void nds32_icache_flush(void){ + +#ifdef CONFIG_CPU_ICACHE_ENABLE + unsigned long end; + unsigned long cache_line = CACHE_LINE_SIZE(ICACHE); + + end = CACHE_WAY(ICACHE) * CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE); + + do { + end -= cache_line; + __nds32__cctlidx_wbinval(NDS32_CCTL_L1I_IX_INVAL, end); + } while (end > 0); + + __nds32__isb(); +#endif +} + +#ifdef CONFIG_CHECK_RANGE_ALIGNMENT +#define chk_range_alignment(start, end, line_size) do { \ + \ + BUG_ON((start) & ((line_size) - 1)); \ + BUG_ON((end) & ((line_size) - 1)); \ + BUG_ON((start) == (end)); \ + \ +} while (0); +#else +#define chk_range_alignment(start, end, line_size) +#endif +/* ================================ D-CACHE =============================== */ +/* + * nds32_dcache_clean_range(start, end) + * + * For the specified virtual address range, ensure that all caches contain + * clean data, such that peripheral accesses to the physical RAM fetch + * correct data. + */ +void nds32_dcache_clean_range(unsigned long start, unsigned long end){ + +#ifdef CONFIG_CPU_DCACHE_ENABLE +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + chk_range_alignment(start, end, line_size); + + while (end > start){ + __nds32__cctlva_wbinval_one_lvl(NDS32_CCTL_L1D_VA_WB, (void *)start); + start += line_size; + } + + __nds32__msync_store(); + __nds32__dsb(); +#endif +#endif +} + +void nds32_dma_clean_range(unsigned long start, unsigned long end){ + + unsigned long line_size; + line_size = CACHE_LINE_SIZE(DCACHE); + start = start & (~(line_size-1)); + end = (end + line_size -1) & (~(line_size-1)); + if (start == end) + return; + + nds32_dcache_clean_range(start, end); +} + +/* + * nds32_dcache_invalidate_range(start, end) + * + * throw away all D-cached data in specified region without an obligation + * to write them back. Note however that we must clean the D-cached entries + * around the boundaries if the start and/or end address are not cache + * aligned. + */ +void nds32_dcache_invalidate_range(unsigned long start, unsigned long end){ + +#ifdef CONFIG_CPU_DCACHE_ENABLE + + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + chk_range_alignment(start, end, line_size); + + while (end > start){ + __nds32__cctlva_wbinval_one_lvl(NDS32_CCTL_L1D_VA_INVAL, (void *)start); + start += line_size; + } +#endif +} + +void nds32_dcache_flush_range(unsigned long start, unsigned long end){ + +#ifdef CONFIG_CPU_DCACHE_ENABLE + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + + while (end > start){ +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + __nds32__cctlva_wbinval_one_lvl(NDS32_CCTL_L1D_VA_WB, (void *)start); +#endif + __nds32__cctlva_wbinval_one_lvl(NDS32_CCTL_L1D_VA_INVAL, (void *)start); + start += line_size; + } +#endif +} + +void nds32_dcache_writeback_range(unsigned long start, unsigned long end){ + +#ifdef CONFIG_CPU_DCACHE_ENABLE +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + + while (end > start){ + __nds32__cctlva_wbinval_one_lvl(NDS32_CCTL_L1D_VA_WB, (void *)start); + start += line_size; + } +#endif +#endif +} +void unaligned_cache_line_move(unsigned char* src, unsigned char* dst, unsigned long len ) +{ + int i; + unsigned char* src_p = (unsigned char*)src; + unsigned char* dst_p = (unsigned char*)dst; + for( i = 0 ;i < len; ++i) + *(dst_p+i)=*(src_p+i); +} + + + +void nds32_dma_inv_range(unsigned long start, unsigned long end){ + unsigned long line_size; + unsigned long old_start=start; + unsigned long old_end=end; + line_size = CACHE_LINE_SIZE(DCACHE); + unsigned char h_buf[line_size]; + unsigned char t_buf[line_size]; + memset((void*)h_buf,0,line_size); + memset((void*)t_buf,0,line_size); + + start = start & (~(line_size-1)); + end = (end + line_size -1) & (~(line_size-1)); + if (start == end) + return; + if (start != old_start) + { + //nds32_dcache_flush_range(start, start + line_size); + unaligned_cache_line_move((unsigned char*)start, h_buf, old_start - start); + } + if (end != old_end) + { + //nds32_dcache_flush_range(end - line_size ,end); + unaligned_cache_line_move((unsigned char*)old_end, t_buf, end - old_end); + + } + nds32_dcache_invalidate_range(start, end); + + //handle cache line unaligned problem + if(start != old_start) + unaligned_cache_line_move(h_buf,(unsigned char*)start, old_start - start); + + if( end != old_end ) + unaligned_cache_line_move(t_buf,(unsigned char*)old_end, end - old_end); + +} + + +void nds32_dma_flush_range(unsigned long start, unsigned long end){ + + unsigned long line_size; + line_size = CACHE_LINE_SIZE(DCACHE); + start = start & (~(line_size-1)); + end = (end + line_size -1 ) & (~(line_size-1)); + if (start == end) + return; + + nds32_dcache_flush_range(start, end); +} + +/* ================================ I-CACHE =============================== */ +/* + * nds32_icache_invalidate_range(start, end) + * + * invalidate a range of virtual addresses from the Icache + * + * This is a little misleading, it is not intended to clean out + * the i-cache but to make sure that any data written to the + * range is made consistant. This means that when we execute code + * in that region, everything works as we expect. + * + * This generally means writing back data in the Dcache and + * write buffer and flushing the Icache over that region + * + * start: virtual start address + * end: virtual end address + */ +void nds32_icache_invalidate_range(unsigned long start, unsigned long end){ + +#ifdef CONFIG_CPU_ICACHE_ENABLE + + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(ICACHE); + //chk_range_alignment(start, end, line_size); + start &= (~(line_size-1)); + end = ( end + line_size - 1 )&(~(line_size-1)); + if (end == start) + end += line_size; + + while (end > start){ + + end -= line_size; + __nds32__cctlva_wbinval_one_lvl(NDS32_CCTL_L1I_VA_INVAL, (void *)end); + } +#endif +} diff --git a/bsp/AE210P/cache.h b/bsp/AE210P/cache.h new file mode 100644 index 0000000000000000000000000000000000000000..5ed3e6951f5864c182324c4b917d3c19a9cacf7a --- /dev/null +++ b/bsp/AE210P/cache.h @@ -0,0 +1,45 @@ +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "nds32_intrinsic.h" +#include "nds32.h" + +enum cache_t{ICACHE, DCACHE}; + +static inline unsigned long CACHE_SET(enum cache_t cache){ + + if(cache == ICACHE) + return 64 << ((__nds32__mfsr(NDS32_SR_ICM_CFG) & ICM_CFG_mskISET) >> ICM_CFG_offISET); + else + return 64 << ((__nds32__mfsr(NDS32_SR_DCM_CFG) & DCM_CFG_mskDSET) >> DCM_CFG_offDSET); +} + +static inline unsigned long CACHE_WAY(enum cache_t cache){ + + if(cache == ICACHE) + return 1 + ((__nds32__mfsr(NDS32_SR_ICM_CFG) & ICM_CFG_mskIWAY) >> ICM_CFG_offIWAY); + else + return 1 + ((__nds32__mfsr(NDS32_SR_DCM_CFG) & DCM_CFG_mskDWAY) >> DCM_CFG_offDWAY); +} + +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache){ + + if(cache == ICACHE) + return 8 << (((__nds32__mfsr(NDS32_SR_ICM_CFG) & ICM_CFG_mskISZ) >> ICM_CFG_offISZ) - 1); + else + return 8 << (((__nds32__mfsr(NDS32_SR_DCM_CFG) & DCM_CFG_mskDSZ) >> DCM_CFG_offDSZ) - 1); +} + +extern void nds32_dcache_invalidate(void); +extern void nds32_dcache_flush(void); +extern void nds32_icache_flush(void); +extern void nds32_dcache_clean_range(unsigned long start, unsigned long end); +extern void nds32_dma_clean_range(unsigned long start, unsigned long end); +extern void nds32_dcache_invalidate_range(unsigned long start, unsigned long end); +extern void nds32_dcache_flush_range(unsigned long start, unsigned long end); +extern void nds32_dcache_writeback_range(unsigned long start, unsigned long end); +extern void nds32_dma_inv_range(unsigned long start, unsigned long end); +extern void nds32_dma_flush_range(unsigned long start, unsigned long end); +extern void nds32_icache_invalidate_range(unsigned long start, unsigned long end); + +#endif /* __CACHE_H__ */ diff --git a/bsp/AE210P/config.h b/bsp/AE210P/config.h new file mode 100644 index 0000000000000000000000000000000000000000..00aa2995164a0274918c41c659f84bcdd80f5ff3 --- /dev/null +++ b/bsp/AE210P/config.h @@ -0,0 +1,48 @@ +#define CONFIG_HEARTBEAT_LED 1 + +/* + * Select Platform + */ +#ifdef AE210P +#define CONFIG_PLAT_AE210P 1 +#define IRQ_STACK_SIZE 5120 /* IRQ stack size */ +#else +#error "No valid platform is defined!" +#endif + +/* + * Platform Option + */ +#define VECTOR_BASE 0x00000000 + +#define VECTOR_NUMINTRS 32 +#define NO_EXTERNAL_INT_CTL 1 +#define XIP_MODE 1 + +#ifdef CONFIG_OSC_SUPPORT +#define OSC_EILM_SIZE 0x10000 // 64KB +#undef XIP_MODE +#endif + +#undef CONFIG_HW_PRIO_SUPPORT + +/* + * Cache Option + */ +#if (!defined(__NDS32_ISA_V3M__) && defined(CONFIG_CACHE_SUPPORT)) +#define CONFIG_CPU_ICACHE_ENABLE 1 +#define CONFIG_CPU_DCACHE_ENABLE 1 +//#define CONFIG_CPU_DCACHE_WRITETHROUGH 1 +#endif + +#undef CONFIG_CHECK_RANGE_ALIGNMENT +#undef CONFIG_CACHE_L2 +#undef CONFIG_FULL_ASSOC + +/* + * Debugging Options + */ +#undef CONFIG_DEBUG +#undef CONFIG_WERROR + +#include "ae210p.h" diff --git a/bsp/AE210P/debug.h b/bsp/AE210P/debug.h new file mode 100644 index 0000000000000000000000000000000000000000..75aeef649887693b5f7b99efedeb6f47e73ff201 --- /dev/null +++ b/bsp/AE210P/debug.h @@ -0,0 +1,78 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include + +#define DEBUG(enable, tagged, ...) \ + do \ + { \ + if (enable) \ + { \ + if (tagged) \ + fprintf(stderr, "[ %25s() ] ", __func__); \ + fprintf(stderr, __VA_ARGS__); \ + } \ + } while( 0) + +#define ERROR(...) DEBUG(1, 1, "ERROR:"__VA_ARGS__) + +#define KASSERT(cond) \ +{ \ + if (!(cond)) \ + { \ + ERROR("Failed assertion in %s:\n" \ + "%s at %s\n" \ + "line %d\n" \ + "RA=%lx\n", \ + __func__, \ + #cond, \ + __FILE__, \ + __LINE__, \ + (unsigned long)__builtin_return_address(0)); \ + \ + while (1) \ + ; \ + } \ +} + +#define KPANIC(args, ...) \ +{ \ + ERROR(args, __VA_ARGS__); \ + while (1) ; \ +} + +static inline void dump_mem(const void *mem, int count) +{ + const unsigned char *p = mem; + int i = 0; + + for(i = 0; i < count; i++) + { + if( i % 16 == 0) + DEBUG(1, 0, "\n"); + + DEBUG(1, 0, "%02x ", p[i]); + } +} + +/* help to trace back */ +static inline void dump_stack(void) +{ + unsigned long *stack; + unsigned long addr; + + __asm__ __volatile__ ("\tori\t%0, $sp, #0\n" : "=r" (stack)); + + printf("Call Trace:\n"); + addr = *stack; + while (addr) + { + addr = *stack++; + printf("[<%08lx>] ", addr); + } + printf("\n"); + + return; +} + +#endif /* __DEBUG_H__ */ diff --git a/bsp/AE210P/driver/dma/Kbuild b/bsp/AE210P/driver/dma/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..18faadf0a56e9565414e48f1da211127bde2c328 --- /dev/null +++ b/bsp/AE210P/driver/dma/Kbuild @@ -0,0 +1,2 @@ +lib-y := +lib-y += dmad.o diff --git a/bsp/AE210P/driver/dma/dmad.c b/bsp/AE210P/driver/dma/dmad.c new file mode 100644 index 0000000000000000000000000000000000000000..5aa67218c1555b0c5cca9f22db8ff4f1acdd57b4 --- /dev/null +++ b/bsp/AE210P/driver/dma/dmad.c @@ -0,0 +1,2513 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Aug.21.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * dmad.c + * + * DESCRIPTION + * + * DMA controller driver internal supplement library. + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * dmad.h + * + ****************************************************************************/ +#include "dmad.h" +#include "cache.h" +#include "bsp_hal.h" + +// #define DMAD_POLLING +#define DMAD_AHB_MAX_CHANNELS DMAC_MAX_CHANNELS +#define DMAD_APB_MAX_CHANNELS APBBR_DMA_MAX_CHANNELS +#define DMAD_DRB_POOL_SIZE 128 /* 64 // 128*/ + +//#define DMAD_HISR_PRIORITY 0 // 0: highest, 2: lowest +#define DMAD_HISR_STACK_SIZE 4096 // Please align to 32-bit + +#ifdef CONFIG_PLAT_AG101P_4GB + #define NTC0_BONDER_START 0x00000000 + #define NTC0_BONDER_END 0x40000000 +#else + #define NTC0_BONDER_START 0x00000000 + #define NTC0_BONDER_END 0x00400000 +#endif + +/* + * DMA module is shared between drivers and has no specific + * initialization entry point. For this reason, it's stack + * pool is declared in the global data or bss section. + */ +static uint32_t dmad_hisr_stack[DMAD_HISR_STACK_SIZE]; + +/* Driver data structure, one instance per system */ +typedef struct DMAD_DATA_STRUCT{ + + /* Driver data initialization flag */ + uint32_t init; /* init flag for this object */ + uint32_t drq_pool_mutex_init; /* init flag for DMA queue pool access control object */ + uint32_t ahb_lisr_registered; /* init flag for AHB DMA LISR */ + uint32_t apb_lisr_registered; /* init flag for APB DMA LISR */ + uint32_t hisr_registered; /* init flag for HISR */ + + /* DMA queue pool access control object */ + hal_mutex_t drq_pool_mutex; /* Mutex for access control of DRQ (DMA Request Queue) pool between tasks */ + + /* DMA HISR resources */ + hal_bh_t hisr; /* HISR kernel object, used to perform deffered tasks of DMA LISR */ + uint32_t hisr_as; /* HISR activation state (for the single HISR to identify who activated it) */ + +} DMAD_DATA; + +/* Driver data structure instance, one instance per system */ +static DMAD_DATA dmad; + +/* DMA request queue, one instance per channel */ +typedef struct DMAD_DRQ_STRUCT{ + + uint32_t allocated; /* Flag to indicate the channel allocation status */ + DMAD_DATA *dmad; /* Pointer to driver object (DMAD_DATA) */ + + uint32_t channel_base; /* DMA channel register base address */ + + hal_mutex_t drb_pool_mutex; /* Mutex for access control of DRB (DMA Request Block) pool between tasks */ + DMAD_DRB drb_pool[DMAD_DRB_POOL_SIZE]; /* DRB (DMA Request Block) pool for this channel */ + hal_semaphore_t drb_sem; + + uint32_t fre_head; /* Free(un-allocated, completed) DRB linked list head */ + uint32_t fre_tail; /* Free(un-allocated, completed) DRB linked list tail */ + + uint32_t rdy_head; /* Ready(allocated, un-submitted) DRB linked list head */ + uint32_t rdy_tail; /* Ready(allocated, un-submitted) DRB linked list tail */ + + uint32_t sbt_head; /* Submitted DRB linked list head */ + uint32_t sbt_tail; /* Submitted DRB linked list tail */ + + uint32_t cpl_head; /* Completed (those need to notify client) DRB linked list head */ + uint32_t cpl_tail; /* Completed (those need to notify client) DRB linked list tail */ + + /* + * cache writeback function + * + * source destination writeback invalidate function + * --------------------------------------------------------------------------------------------------- + * memory -> memory v (for src data) v (for dest readback) NDS_DCache_Invalidate_Flush() + * device -> memory v (for invalidate) v (for dest readback) NDS_DCache_Invalidate_Flush() + * memory -> device v (for src data) x NDS_DCache_Flush() + * device -> device x x null + */ + void (*dc_writeback)(unsigned long start, unsigned long end); + void (*dc_invalidate)(unsigned long start, unsigned long end); + +} DMAD_DRQ; + +/* DMA queue for AHB DMA channels */ +static DMAD_DRQ ahb_drq_pool[DMAD_AHB_MAX_CHANNELS]; + +/* DMA queue for APB DMA channels */ +static DMAD_DRQ apb_drq_pool[DMAD_APB_MAX_CHANNELS]; + +/* AHB DMAC channel re-route table structure */ +typedef struct _DMAD_AHB_CH_ROUTE { + +// uint32_t dev_reqn; /* device req/gnt number */ + uint32_t route_cr; /* routing control register address */ + +} DMAD_AHB_CH_ROUTE; + +/* AHB DMAC channel re-route table. Indexed by AHB DMAC req/ack number. */ +static DMAD_AHB_CH_ROUTE dmad_ahb_ch_route_table[] = { + { 0 }, + { PMU_CFC_REQACK_CFG }, /* CFC REQ/ACK connection configuration register */ + { PMU_SSP1_REQACK_CFG }, /* SSP1 REQ/ACK connection configuration register */ + { PMU_UART1TX_REQACK_CFG }, /* UART1 TX REQ/ACK connection configuration register */ + { PMU_UART1RX_REQACK_CFG }, /* UART1 RX REQ/ACK connection configuration register */ + { PMU_UART2TX_REQACK_CFG }, /* UART2 TX REQ/ACK connection configuration register */ + { PMU_UART2RX_REQACK_CFG }, /* UART2 RX REQ/ACK connection configuration register */ + { PMU_SDC_REQACK_CFG }, /* SDC REQ/ACK connection configuration register */ + { PMU_I2SAC97_REQACK_CFG }, /* I2S/AC97 REQ/ACK connection configuration register */ + { 0 }, + { 0 }, + { PMU_USB_REQACK_CFG }, /* USB 2.0 REQ/ACK connection configuration register */ + { 0 }, + { 0 }, + { PMU_EXT0_REQACK_CFG }, /* External device0 REQ/ACK connection configuration register */ + { PMU_EXT1_REQACK_CFG }, /* External device1 REQ/ACK connection configuration register */ +}; + +/* APB Bridge DMA request number re-route table */ +typedef struct _DMAD_APB_REQN_ROUTE{ + +// uint32_t apb_reqn; /* APB device req/gnt number */ + uint32_t ahb_reqn; /* AHB DMAC req/ack number */ + + uint32_t bus_sel; /* Address selection: APBBR_ADDRSEL_APB(0) or APBBR_ADDRSEL_AHB(1) */ +} DMAD_APB_REQN_ROUTE; + +/* APB Bridge DMA request number re-route table. Indexed by APB DMA req/gnt number. */ +static DMAD_APB_REQN_ROUTE dmad_apb_reqn_route_table[] = { + { 0x00, APBBR_ADDRSEL_AHB }, /* APBBR_REQN_NONE */ + { 0x01, APBBR_ADDRSEL_APB }, /* APBBR_REQN_CFC */ + { 0x02, APBBR_ADDRSEL_APB }, /* APBBR_REQN_SSP */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x05, APBBR_ADDRSEL_APB }, /* APBBR_REQN_BTUART (AHB TX reqn: 5, AHB RX reqn: 6) */ + { 0x07, APBBR_ADDRSEL_APB }, /* APBBR_REQN_SDC */ + { 0x08, APBBR_ADDRSEL_APB }, /* APBBR_REQN_I2SAC97 */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x03, APBBR_ADDRSEL_APB }, /* APBBR_REQN_STUART (AHB TX reqn: 3, AHB RX reqn: 4) */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved (comment out following fields to save code size) */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ + { 0x00, APBBR_ADDRSEL_AHB }, /* APB reserved */ +}; + +/* AHB DMA Request number */ +/* Used to record DMA request numbers in different platform */ +typedef struct _APB_DMA_REQN { + + uint32_t xc5_reqn; + uint32_t xc7_reqn; + +} APB_DMA_REQN; + +static APB_DMA_REQN apb_dma_reqn_table[] = { + + {APBBR_REQN_NONE, APBBR_REQN_NONE},//APB_REQN_NONE + /* REQN in XC5 */ + {XC5_APBBR_REQN_CFC, APBBR_REQN_RESERVED},//APB_REQN_CFC + {XC5_APBBR_REQN_SSP, APBBR_REQN_RESERVED},//APB_REQN_SSP + {XC5_APBBR_REQN_BTUART, APBBR_REQN_RESERVED},//APBBR_REQN_BTUART + {XC5_APBBR_REQN_I2SAC97, XC7_APBBR_REQN_I2SAC97},//APB_REQN_I2SAC97 + {XC5_APBBR_REQN_STUART, APBBR_REQN_RESERVED},//APB_REQN_STUART + {XC5_APBBR_REQN_I2S, APBBR_REQN_RESERVED},//APB_REQN_I2S + {XC5_APBBR_REQN_SSP2, APBBR_REQN_RESERVED},//APB_REQN_SSP2 + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_EXTREQ0},//APB_REQN_EXT0 + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_EXTREQ1},//APB_REQN_EXT1 + /* REQN in XC7 */ + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_SSP1TX},//APB_REQN_SSP1TX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_SSP1RX},//APB_REQN_SSP1RX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_UART2TX},//APB_REQN_UART2TX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_UART2RX},//APB_REQN_UART2RX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_UART4TX},//APB_REQN_UART4TX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_UART4RX},//APB_REQN_UART4RX + {XC5_APBBR_REQN_SDC, XC7_APBBR_REQN_SDC},//APB_REQN_SDC + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_SSP2TX},//APB_REQN_SSP2TX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_SSP2RX},//APB_REQN_SSP2RX + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_USB_2_0},//APB_REQN_USB_2_0 + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_USB_1_1_EP1},//APB_REQN_USB_1_1_EP1 + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_USB_1_1_EP2},//APB_REQN_USB_1_1_EP2 + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_USB_1_1_EP3},//APB_REQN_USB_1_1_EP3 + {APBBR_REQN_RESERVED, XC7_APBBR_REQN_USB_1_1_EP4},//AHB_REQN_USB_1_1_EP4 + {XC5_APBBR_REQN_MAX, XC7_APBBR_REQN_MAX},//APB_REQN_MAX +}; + +/* AHB DMA Request number */ +/* Used to record DMA request numbers in different platform */ +typedef struct _AHB_DMA_REQN { + + uint32_t xc5_reqn; + uint32_t xc7_reqn; + +} AHB_DMA_REQN; + +static AHB_DMA_REQN ahb_dma_reqn_table[] = { + + {AHB_REQN_NONE, AHB_REQN_NONE},//AHB_REQN_NONE + /* REQN in XC5 */ + {XC5_AHB_REQN_CFC, AHB_REQN_RESERVED},//AHB_REQN_CFC + {XC5_AHB_REQN_SSP, AHB_REQN_RESERVED},//AHB_REQN_SSP + {XC5_AHB_REQN_UART1TX, AHB_REQN_RESERVED},//AHB_REQN_UART1TX + {XC5_AHB_REQN_UART1RX, AHB_REQN_RESERVED},//AHB_REQN_UART1RX + {XC5_AHB_REQN_I2SAC97, XC7_AHB_REQN_I2SAC97},//AHB_REQN_I2SAC97 + {XC5_AHB_REQN_USB, AHB_REQN_RESERVED},//AHB_REQN_USB + {XC5_AHB_REQN_EXT0, XC7_AHB_REQN_EXTREQ0},//AHB_REQN_EXT0 + {XC5_AHB_REQN_EXT1, XC7_AHB_REQN_EXTREQ1},//AHB_REQN_EXT1 + /* REQN in XC7 */ + {AHB_REQN_RESERVED, XC7_AHB_REQN_SSP1TX},//AHB_REQN_SSP1TX + {AHB_REQN_RESERVED, XC7_AHB_REQN_SSP1RX},//AHB_REQN_SSP1RX + {AHB_REQN_RESERVED, XC7_AHB_REQN_UART2TX},//AHB_REQN_UART2TX + {AHB_REQN_RESERVED, XC7_AHB_REQN_UART2RX},//AHB_REQN_UART2RX + {AHB_REQN_RESERVED, XC7_AHB_REQN_UART4TX},//AHB_REQN_UART4TX + {AHB_REQN_RESERVED, XC7_AHB_REQN_UART4RX},//AHB_REQN_UART4RX + {XC5_AHB_REQN_SDC, XC7_AHB_REQN_SDC},//AHB_REQN_SDC + {AHB_REQN_RESERVED, XC7_AHB_REQN_SSP2TX},//AHB_REQN_SSP2TX + {AHB_REQN_RESERVED, XC7_AHB_REQN_SSP2RX},//AHB_REQN_SSP2RX + {AHB_REQN_RESERVED, XC7_AHB_REQN_USB_2_0},//AHB_REQN_USB_2_0 + {AHB_REQN_RESERVED, XC7_AHB_REQN_USB_1_1_EP1},//AHB_REQN_USB_1_1_EP1 + {AHB_REQN_RESERVED, XC7_AHB_REQN_USB_1_1_EP2},//AHB_REQN_USB_1_1_EP2 + {AHB_REQN_RESERVED, XC7_AHB_REQN_USB_1_1_EP3},//AHB_REQN_USB_1_1_EP3 + {AHB_REQN_RESERVED, XC7_AHB_REQN_USB_1_1_EP4},//AHB_REQN_USB_1_1_EP4 +}; + +/***************************************************************************** + * FUNCTION + * + * _dmad_get_reqn + * + * DESCRIPTION + * + * Get DMA request number from various platform. + * + * INPUTS + * + * dma_controller : (in) AHB or APB + * device : (in) Device and peripheral. + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +uint32_t _dmad_get_reqn(uint32_t dma_controller, uint32_t device){ + + uint32_t reqn; + uint32_t platform_id = IN32(PMU_IDNMBR0); + + if (dma_controller == DMAD_DMAC_APB_CORE){ /* APB */ + if ((platform_id & PRODUCT_ID_MASK) == AG101P_EMERALD) + reqn = apb_dma_reqn_table[device].xc7_reqn; + else + reqn = apb_dma_reqn_table[device].xc5_reqn; + } else { /* AHB */ + if ((platform_id & PRODUCT_ID_MASK) == AG101P_EMERALD) + reqn = ahb_dma_reqn_table[device].xc7_reqn; + else + reqn = ahb_dma_reqn_table[device].xc5_reqn; + } + + return reqn; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_detach_node + * + * DESCRIPTION + * + * Detach a DRB node from a specified list. The list is acknowledged in the + * form of a head node and a tail one. + * + * INPUTS + * + * drb_pool : (in) The DRB pool of a DMA queue for a DMA channel + * head : (in/out) Pointer to the head node of the list + * tail : (in/out) Pointer to the tail node of the list + * node : (in) The node to detach from the list + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static void _dmad_detach_node(DMAD_DRB *drb_pool, uint32_t *head, uint32_t *tail, uint32_t node){ + + if (drb_pool[node].prev != 0){ + + /* prev->next = this->next (= 0, if this is a tail) */ + drb_pool[drb_pool[node].prev].next = drb_pool[node].next; + } + else { + /* this node is head, move head to next node (= 0, if this is the only one node) */ + *head = drb_pool[node].next; + } + + if (drb_pool[node].next != 0){ + + /* next->prev = this->prev (= 0, if this is a head) */ + drb_pool[drb_pool[node].next].prev = drb_pool[node].prev; + } + else { + /* this node is tail, move tail to previous node (= 0, if this is the only one node) */ + *tail = drb_pool[node].prev; + } + + drb_pool[node].prev = drb_pool[node].next = 0; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_detach_head + * + * DESCRIPTION + * + * Detach a DRB node from the head of a specified list. The list is + * acknowledged in the form of a head node and a tail one. + * + * INPUTS + * + * drb_pool : (in) The DRB pool of a DMA queue for a DMA channel + * head : (in/out) Pointer to the head node of the list + * tail : (in/out) Pointer to the tail node of the list + * drb : (out) Reference to the detached node pointer + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static void _dmad_detach_head(DMAD_DRB *drb_pool, uint32_t *head, uint32_t *tail, DMAD_DRB **drb){ + + if (*head == 0){ + + *drb = HAL_NULL; + return; + } + + *drb = &drb_pool[*head]; + + if ((*drb)->next != 0){ + + /* next->prev = this->prev (= 0, if this is a head) */ + drb_pool[(*drb)->next].prev = 0; + + /* prev->next = this->next (do nothing, if this is a head) */ + + /* head = this->next */ + *head = (*drb)->next; + } + else { + /* head = tail = 0 */ + *head = 0; + *tail = 0; + } + + /* this->prev = this->next = 0 (do nothing, if save code size) */ + (*drb)->prev = (*drb)->next = 0; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_detach_tail + * + * DESCRIPTION + * + * Detach a DRB node from the tail of a specified list. The list is + * acknowledged in the form of a head node and a tail one. + * + * INPUTS + * + * drb_pool : (in) The DRB pool of a DMA queue for a DMA channel + * head : (in/out) Pointer to the head node of the list + * tail : (in/out) Pointer to the tail node of the list + * drb : (out) Reference to the detached node pointer + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static inline void _dmad_detach_tail(DMAD_DRB *drb_pool, uint32_t *head, uint32_t *tail, DMAD_DRB **drb){ + + if (*tail == 0){ + + *drb = HAL_NULL; + return; + } + + *drb = &drb_pool[*tail]; + + if ((*drb)->prev != 0){ + + /* prev->next = this->next (= 0, if this is a tail) */ + drb_pool[(*drb)->prev].next = 0; + + /* next->prev = this->prev (do nothing, if this is a tail) */ + + /* tail = this->prev */ + *tail = (*drb)->prev; + } + else { + /* head = tail = 0 */ + *head = 0; + *tail = 0; + } + + /* this->next = this->prev = 0 (do nothing, if save code size) */ + (*drb)->prev = (*drb)->next = 0; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_attach_head + * + * DESCRIPTION + * + * Attach a DRB node to the head of a specified list. The list is + * acknowledged in the form of a head node and a tail one. + * + * INPUTS + * + * drb_pool : (in) The DRB pool of a DMA queue for a DMA channel + * head : (in/out) Pointer to the head node of the list + * tail : (in/out) Pointer to the tail node of the list + * drb : (in) The node number of the node to attach + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static inline void _dmad_attach_head(DMAD_DRB *drb_pool, uint32_t *head, uint32_t *tail, uint32_t node){ + + if (*head != 0){ + + drb_pool[*head].prev = node; /* head->prev = this */ + drb_pool[node].next = *head; /* this->next = head */ + drb_pool[node].prev = 0; /* this->prev = 0 */ + *head = node; /* head = node */ + } + else { + *head = *tail = node; /* head = tail = node */ + drb_pool[node].prev = drb_pool[node].next = 0; + } +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_attach_tail + * + * DESCRIPTION + * + * Attach a DRB node to the tail of a specified list. The list is + * acknowledged in the form of a head node and a tail one. + * + * INPUTS + * + * drb_pool : (in) The DRB pool of a DMA queue for a DMA channel + * head : (in/out) Pointer to the head node of the list + * tail : (in/out) Pointer to the tail node of the list + * drb : (in) The node number of the node to attach + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static void _dmad_attach_tail(DMAD_DRB *drb_pool, uint32_t *head, uint32_t *tail, uint32_t node){ + + if (*tail != 0){ + + drb_pool[*tail].next = node; /* tail->next = this */ + drb_pool[node].prev = *tail; /* this->prev = tail */ + drb_pool[node].next = 0; /* this->next = 0 */ + *tail = node; /* tail = node */ + } + else { + *head = *tail = node; /* head = tail = node */ + drb_pool[node].prev = drb_pool[node].next = 0; + } +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_ahb_lisr + * + * DESCRIPTION + * + * This is the ISR that services all AHB DMA channels on the NDS32 + * Integrator. + * + * NOTE + * Currently this ISR processes one channel at a time. This replies the + * assumption that the ISR will be invoked again as long as it's status + * bit remains not-cleared, if interrupts for multiple channels happens + * simultaneously. + * + * [todo] Above assumption may not be the real world case. Check it and + * implement processing of multiple channels at once in the ISR, if + * necessary. + * + * INPUTS + * + * vector : Interrupt vector number + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static void _dmad_ahb_lisr(int vector){ + + DMAD_DRQ *drq; + DMAD_DRB *drb; + uint32_t channel; /* interrupt channel number */ + uint8_t tc_int = 0; /* interrupt reason is terminal count */ + uint8_t err_int = 0; /* interrupt reason is DMA error */ + //uint8_t abt_int = 0; /* interrupt reason is abort DMA transfer of this channel */ + uint32_t prv_msk = 0; + + if (vector != INTC_DMA_BIT) + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); + + + prv_msk = hal_intc_irq_mask(IRQ_DMA_VECTOR); + /* Check DMA status register to get channel number */ + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel){ + + if (GETB32(DMAC_INT_TC, channel)){ + + tc_int = 1; /* Mark as TC int */ + SETB32(DMAC_INT_TC_CLR, channel); /* DMAC INT TC status clear */ + hal_intc_irq_clean(IRQ_DMA_VECTOR); + break; + } + } + + /* Perform DMA error checking if no valid channel was found who assert the TC signal. */ + if (channel == DMAD_AHB_MAX_CHANNELS){ + + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel){ + + if (GETB32(DMAC_INT_ERRABT, channel + DMAC_INT_ERR_SHIFT)){ + + err_int = 1; /* Mark as ERR int */ + SETB32(DMAC_INT_ERRABT_CLR, channel + DMAC_INT_ERR_CLR_SHIFT); /* DMAC INT ERR status clear */ + hal_intc_irq_clean(IRQ_DMA_VECTOR); + break; + } + } + + if (channel == DMAD_AHB_MAX_CHANNELS){ + + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel){ + + if (GETB32(DMAC_INT_ERRABT, channel + DMAC_INT_ABT_SHIFT)){ + + //abt_int = 1; /* Mark as ABT int */ + SETB32(DMAC_INT_ERRABT_CLR, channel + DMAC_INT_ABT_CLR_SHIFT); /* DMAC INT ABT status clear */ + hal_intc_irq_clean(IRQ_DMA_VECTOR); + break; + } + } + + if (channel == DMAD_AHB_MAX_CHANNELS){ + + /* Unknown reason ... (check why) */ + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); /*return; */ + } + } + } + + /* Lookup channel's DRQ (DMA Request Queue) */ + drq = (DMAD_DRQ *)&ahb_drq_pool[channel]; + + /* DMAC */ + /* Stop DMA channel temporarily */ + CLRB32(drq->channel_base + DMAC_CSR_OFFSET, DMAC_CSR_CH_EN_BIT); + + /* + * Lookup/detach latest submitted DRB (DMA Request Block) from + * the DRQ (DMA Request Queue), so ISR could kick off next DRB + */ + _dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb); + if (drb == HAL_NULL){ + + /* Check why DMA is triggered while submitted list is empty. */ + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); /*return; */ + } + + /* Enable nested interrupt */ + GIE_ENABLE(); + + /* Notify that new node is going to be available in the free list */ + if (drb->completion_sem != HAL_NULL){ + + dmad.hisr_as |= (1 << channel); /* [15:0] AHB channel indicator */ + hal_raise_bh(&dmad.hisr); /* Call HISR to complete deferred tasks */ + } + /* Process DRBs according to interrupt reason */ + if (tc_int){ + + /* Mark DRB state as completed */ + drb->state = DMAD_DRB_STATE_COMPLETED; + + /* destination is memory */ + if (drq->dc_invalidate != HAL_NULL && drb->dst_index == DMAC_REQN_NONE) + drq->dc_invalidate((unsigned long)(drb->dst_addr), + (unsigned long)(drb->dst_addr) + (unsigned long)(drb->transfer_size)); + + _dmad_attach_tail(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, drb->node); + + /* Check whether there are pending requests in the DRQ */ + if (drq->sbt_head != 0){ + + drb = &drq->drb_pool[drq->sbt_head]; /* Lookup next DRB (DMA Request Block) */ + + /* pre-submission-programming */ + if (drb->psp) + drb->psp(drb->data); + + /* Kick-off DMA for next DRB */ + /* - Source and destination address */ + OUT32(drq->channel_base + DMAC_SRC_ADDR_OFFSET, drb->src_addr); + OUT32(drq->channel_base + DMAC_DST_ADDR_OFFSET, drb->dst_addr); + + /* - Transfer size (in units of source width) */ + OUT32(drq->channel_base + DMAC_SIZE_OFFSET, drb->req_size); + + /* - Re-enable DMA channel */ + SETB32(drq->channel_base + DMAC_CSR_OFFSET, DMAC_CSR_CH_EN_BIT); + } + } + else if (err_int){ + + /* Mark DRB state as error */ + drb->state = DMAD_DRB_STATE_ERROR; + + _dmad_attach_tail(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, drb->node); + + /* Check whether there are pending requests in the DRQ */ + if (drq->sbt_head != 0){ + + /* Lookup next DRB (DMA Request Block) */ + drb = &drq->drb_pool[drq->sbt_head]; + + /* pre-submission-programming */ + if (drb->psp) + drb->psp(drb->data); + + /* + * Kick-off DMA for next DRB + */ + + /* Source and destination address */ + OUT32(drq->channel_base + DMAC_SRC_ADDR_OFFSET, drb->src_addr); + OUT32(drq->channel_base + DMAC_DST_ADDR_OFFSET, drb->dst_addr); + + /* Transfer size (in units of source width) */ + OUT32(drq->channel_base + DMAC_SIZE_OFFSET, drb->req_size); + + /* Re-enable DMA channel */ + SETB32(drq->channel_base + DMAC_CSR_OFFSET, DMAC_CSR_CH_EN_BIT); + } + } + else { /* abt_int */ + + /* Remove all pending requests in the queue */ + while (1){ + + /* Mark DRB state as abort */ + drb->state = DMAD_DRB_STATE_ABORT; + + _dmad_attach_tail(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, drb->node); + + /* Detach next submitted DRB (DMA Request Block) from the DRQ (DMA Request Queue) */ + _dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb); + if (drb == HAL_NULL) + break; + } + } + +#ifdef DMAD_POLLING + if (dmad.hisr_as & 0x0000ffff){ + + while (drq->cpl_head != 0){ + + _dmad_detach_head(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, &drb); + _dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb->node); + + /* completion-of-submission-programming */ + if (drb->rcp) + drb->rcp(drb->data); + } + } +#endif + GIE_DISABLE(); + + hal_intc_irq_unmask(prv_msk); + +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_apb_lisr + * + * DESCRIPTION + * + * This is the ISR that services all APB DMA channels on the NDS32 + * Integrator. + * + * NOTE + * Currently this ISR processes one channel at a time. This replies the + * assumption that the ISR will be invoked again as long as it's status + * bit remains not-cleared, if interrupts for multiple channels happens + * simultaneously. + * + * [todo] Above assumption may not be the real world case. Check it and + * implement processing of multiple channels at once in the ISR, if + * necessary. + * + * INPUTS + * + * vector : Interrupt vector number + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static void _dmad_apb_lisr(int vector){ + + DMAD_DRQ *drq; + DMAD_DRB *drb; + uint32_t channel; /* interrupt channel number */ + uint8_t finish_int = 0; /* interrupt reason is transfer completed */ + uint8_t err_int = 0; /* interrupt reason is DMA error */ + + uint32_t prv_msk = 0; + if (vector != INTC_APB_BIT) + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); + + /* Mask priority <= apb_bridge's interrupt */ + prv_msk = hal_intc_irq_mask(IRQ_APBBRIDGE_VECTOR); + + /* Check DMA status register to get channel number & clean pending */ + for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel){ + + uint32_t channel_base = APBBR_DMA_BASE_CH(channel); + + if (GETB32(channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_FINTST_BIT)){ + + /* Mark as finish int */ + finish_int = 1; + + /* APB DMA finish int status clear */ + CLRB32(channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_FINTST_BIT); + hal_intc_irq_clean(IRQ_APBBRIDGE_VECTOR); + break; + } + } + + /* Perform DMA error checking if no valid channel was found who assert the finish signal + * & clean pending + */ + if (channel == DMAD_APB_MAX_CHANNELS){ + + for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel){ + + uint32_t channel_base = APBBR_DMA_BASE_CH(channel); + + if (GETB32(channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_ERRINTST_BIT)){ + + /* Mark as error int */ + err_int = 1; + + /* APB DMA error int status clear */ + CLRB32(channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_ERRINTST_BIT); + hal_intc_irq_clean(IRQ_APBBRIDGE_VECTOR); + break; + } + } + + if (channel == DMAD_AHB_MAX_CHANNELS) + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); + } + + /* Lookup channel's DRQ (DMA Request Queue) */ + drq = (DMAD_DRQ *)&apb_drq_pool[channel]; + + /* + * APB + */ + + /* Stop DMA channel temporarily */ + CLRB32(drq->channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_CHEN_BIT); + + /* + * Lookup/detach latest submitted DRB (DMA Request Block) from + * the DRQ (DMA Request Queue), so ISR could kick off next DRB + */ + _dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb); + if (drb == HAL_NULL){ + + /* Check why DMA is triggered while submitted list is empty. */ + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); + } + + GIE_ENABLE(); + + /* Notify that new node is going to be available in the free list */ + dmad.hisr_as |= (0x00010000 << channel); /* [31:16] APB channel indicator */ + hal_raise_bh(&dmad.hisr); /* Call HISR to complete deferred tasks */ + + /* Process DRBs according to the cause of this interrupt */ + if (finish_int){ + + /* Mark DRB state as completed */ + drb->state = DMAD_DRB_STATE_COMPLETED; + + _dmad_attach_tail(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, drb->node); + + /* destination is memory */ + if (drq->dc_invalidate != HAL_NULL && drb->dst_index == DMAC_REQN_NONE) + drq->dc_invalidate((unsigned long)(drb->dst_addr), + (unsigned long)(drb->dst_addr) + (unsigned long)(drb->transfer_size)); + + /* Check whether there are pending requests in the DRQ */ + if (drq->sbt_head != 0){ + + /* Lookup next DRB (DMA Request Block) */ + drb = &drq->drb_pool[drq->sbt_head]; + + /* pre-submission-programming */ + if (drb->psp) + drb->psp(drb->data); + + /* + * Kick-off DMA for next DRB + */ + + /* Source and destination address */ + OUT32(drq->channel_base + APBBR_DMA_SAD_OFFSET, drb->src_addr); + OUT32(drq->channel_base + APBBR_DMA_DAD_OFFSET, drb->dst_addr); + + /* - Transfer size (in units of source width) */ + OUT32(drq->channel_base + APBBR_DMA_CYC_OFFSET, drb->req_size & APBBR_DMA_CYC_MASK); + + /* - Re-enable DMA channel */ + SETB32(drq->channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_CHEN_BIT); + } + } + else if (err_int){ + + /* Remove all pending requests in the queue */ + while (1){ + + /* Mark DRB state as abort */ + drb->state = DMAD_DRB_STATE_ABORT; + + _dmad_attach_tail(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, drb->node); + _dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb); + + if (drb == HAL_NULL) + break; + } + } + +#ifdef DMAD_POLLING + if (dmad.hisr_as & 0xffff0000){ + + while (drq->cpl_head != 0){ + + _dmad_detach_head(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, &drb); + _dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb->node); + + /* completion-of-submission-programming */ + if (drb->rcp) + drb->rcp(drb->data); + } + + dmad.hisr_as &= ~(0x00010000 << channel); + } +#endif + GIE_DISABLE(); + hal_intc_irq_unmask(prv_msk); + +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_hisr + * + * DESCRIPTION + * + * This HISR performs the defferred tasks from LISR. + * + * NOTE + * + * Current task list of this HISR + * + * - Signal DRQ available event for waiting DRQ allocations. + * + * INPUTS + * + * vector : Interrupt vector number + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +static inline void _dmad_hisr(void *param){ + + DMAD_DRQ *drq; + DMAD_DRB *drb = NULL; + //uint32_t core_intl; + uint32_t channel; + + while(1){ + + hal_bh_t *bh = (hal_bh_t *)param; + hal_pend_semaphore(&bh->sem, HAL_SUSPEND); + + //core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Signal free-list available event */ + if ((dmad.hisr_as & 0xffff0000) != 0){ + + /* Disable apb_bridge interrupt to avoid race condition */ + HAL_INTC_IRQ_ATOMIC_DISABLE(IRQ_APBBRIDGE_VECTOR); + /* APB LISR */ + for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel){ + + if (dmad.hisr_as & (0x00010000 << channel)){ + + drq = (DMAD_DRQ *)&apb_drq_pool[channel]; + + while (drq->cpl_head != 0){ + + _dmad_detach_head(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, &drb); + _dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb->node); + + hal_post_semaphore(&drq->drb_sem); + + /* completion-of-submission-programming */ + if (drb->rcp) + drb->rcp(drb->data); + + if(drb->completion_sem != HAL_NULL) + { +// puts("APB DMA HISR Complete!!!\r\n"); + hal_post_semaphore(drb->completion_sem); + + } + } + + dmad.hisr_as &= ~(0x00010000 << channel); + } + } + /* Re-enable apb_bridge interrupt */ + HAL_INTC_IRQ_ATOMIC_ENABLE(IRQ_APBBRIDGE_VECTOR); + } + else if ((dmad.hisr_as & 0x0000ffff) != 0){ + /* Disable AHB_DMA interrupt to avoid race condition */ + HAL_INTC_IRQ_ATOMIC_DISABLE(IRQ_DMA_VECTOR); + + /* AHB LISR */ + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel){ + + if (dmad.hisr_as & (1 << channel)){ + + drq = (DMAD_DRQ *)&ahb_drq_pool[channel]; + + while (drq->cpl_head != 0){ + + _dmad_detach_head(drq->drb_pool, &drq->cpl_head, &drq->cpl_tail, &drb); + _dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb->node); + + hal_post_semaphore(&drq->drb_sem); + + /* completion-of-submission-programming */ + if (drb->rcp) + drb->rcp(drb->data); + } + + if (drb->completion_sem != HAL_NULL) + hal_post_semaphore(drb->completion_sem); + + dmad.hisr_as &= ~(1 << channel); + } + } + HAL_INTC_IRQ_ATOMIC_ENABLE(IRQ_DMA_VECTOR); + } + + // hal_global_int_ctl(core_intl); + } +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_channel_alloc + * + * DESCRIPTION + * + * This function allocates a DMA channel for client's request. If the + * channel is already used by other clients, then this function will + * fail the allocation. + * + * INPUTS + * + * ch_req : Pointer to the DMA request descriptor structure + * init : Specify whether to initialize the DMA channel HW if the + * allocation is successfull. Clients could also postpone + * the initialization task to the _dmad_channel_init() + * routine. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful allocation, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_channel_alloc(DMAD_CHANNEL_REQUEST_DESC *ch_req, uint8_t init){ + + uint32_t status; + DMAD_DRQ *drq_iter; + DMAD_DRB *drb_iter; + uint32_t i = 0; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + if (ch_req->controller == DMAD_DMAC_AHB_CORE) + drq_iter = ahb_drq_pool; + else if (ch_req->controller == DMAD_DMAC_APB_CORE) + drq_iter = apb_drq_pool; + else + return HAL_ERR_NOT_PRESENT; + + /* First-time initialization for DMA queue pool access control object */ + if (dmad.drq_pool_mutex_init == 0){ + + status = hal_create_mutex(&dmad.drq_pool_mutex, "drqpool"); + if (status != HAL_SUCCESS){ + + DMAD_TRACE(("[dmad] failed to create drq_pool mutex!\r\n")); + return status; + } + dmad.drq_pool_mutex_init = 1; + } + + /* Obtain exclusive access to the pool of channel queues */ + + if (hal_current() != HAL_NULL){ + + /* Suspending is only valid to the current task -- no need to lock if invoked from HISR. */ + status = hal_wait_for_mutex(&dmad.drq_pool_mutex, HAL_SUSPEND); + if (status != HAL_SUCCESS){ + + DMAD_TRACE(("[dmad] failed to lock drq_pool! status(0x%08lx)\r\n", status)); + return status; + } + } + + /* Locate an available DMA channel */ + if (ch_req->controller == DMAD_DMAC_AHB_CORE){ + +#if 0 + /* UART - TX/RX channel is limitted */ + if ((ch_req->ahbch_req.src_index == DMAC_REQN_UART1TX) || + (ch_req->ahbch_req.dst_index == DMAC_REQN_UART1TX) || + (ch_req->ahbch_req.src_index == DMAC_REQN_UART2TX) || + (ch_req->ahbch_req.dst_index == DMAC_REQN_UART2TX)) + { + /* TX channel is limitied to C/D */ + drq_iter = &ahb_drq_pool[2]; + for (i = 2; i < 4; ++i, ++drq_iter){ + if (drq_iter->allocated == 0) + break; + } + } + else if ((ch_req->ahbch_req.src_index == DMAC_REQN_UART1RX) || + (ch_req->ahbch_req.dst_index == DMAC_REQN_UART1RX) || + (ch_req->ahbch_req.src_index == DMAC_REQN_UART2RX) || + (ch_req->ahbch_req.dst_index == DMAC_REQN_UART2RX)){ + + /* RX channel is limitied to A/B */ + for (i = 0; i < 2; ++i, ++drq_iter){ + + if (drq_iter->allocated == 0) + break; + } + } + else +#endif + { + if ((ch_req->ahbch_req.src_index != DMAC_REQN_NONE) || + (ch_req->ahbch_req.dst_index != DMAC_REQN_NONE)){ + + /* + * [2007-12-03] It looks current board have problem to do dma + * traffic for APB devices on DMAC channel 0/1. Redirect all + * APB devices to start from channel 2. + * [todo] include USB controller ? + */ + drq_iter = &ahb_drq_pool[2]; + for (i = 2; i < DMAD_AHB_MAX_CHANNELS; ++i, ++drq_iter){ + + if (drq_iter->allocated == 0) + break; + } + } + else { + /* channel for other devices is free to allocate */ + for (i = 0; i < DMAD_AHB_MAX_CHANNELS; ++i, ++drq_iter){ + + if (drq_iter->allocated == 0) + break; + } + } + } + + if (i == DMAD_AHB_MAX_CHANNELS){ + + DMAD_TRACE(("out of available channels (AHB DMAC)!\r\n")); + return HAL_ERR_UNAVAILABLE; + } + + DMAD_TRACE(("allocated channel: %d (AHB DMAC)\r\n")); + } + else if (ch_req->controller == DMAD_DMAC_APB_CORE){ + + for (i = 0; i < DMAD_APB_MAX_CHANNELS; ++i, ++drq_iter){ + + if (drq_iter->allocated == 0) + break; + } + + if (i == DMAD_APB_MAX_CHANNELS){ + + DMAD_TRACE(("out of available channels (APB DMAC)!\r\n")); + return HAL_ERR_UNAVAILABLE; + } + + DMAD_TRACE(("allocated channel: %d (APB DMAC)\r\n", i)); + } + + /* Allocate the DMA channel */ + drq_iter->allocated = 1; + + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Release exclusive access to the pool of channel queues + */ + status = hal_release_mutex(&dmad.drq_pool_mutex); + if (status != HAL_SUCCESS){ + + DMAD_TRACE(("[dmad] failed to unlock drq_pool!\r\n")); + return status; + } + } + + /* Create mutex object for DMA queue access control */ + status = hal_create_mutex(&drq_iter->drb_pool_mutex, "drq"); + if (status != HAL_SUCCESS){ + + DEBUG(1, 1, "failed to create mutex for drb_pool!\n"); + return status; + } + + /* Create semaphores for free-list allocation operation */ + status = hal_create_semaphore(&drq_iter->drb_sem, DMAD_DRB_POOL_SIZE - 1, (void*)0); + if (status != HAL_SUCCESS){ + + DEBUG(1, 1, "failed to create semaphores for drb_pool!\n"); + return status; + } + + /* Record the channel number in client's struct */ + ch_req->channel = i; + + /* Record the channel's queue handle in client's struct */ + ch_req->drq = drq_iter; + + if (ch_req->controller == DMAD_DMAC_AHB_CORE){ + + //drq_iter->controller_base = DMAC_BASE; + drq_iter->channel_base = DMAC_BASE_CH(i); + } + else { + //drq_iter->controller_base = APBBR_BASE; + drq_iter->channel_base = APBBR_DMA_BASE_CH(i); + } + + /* Initialize DMA channel's DRB pool as list of free DRBs */ + drb_iter = &drq_iter->drb_pool[0]; + drb_iter->prev = 0; + drb_iter->next = 0; + drb_iter->node = 0; + //drb_iter->src_addr = 0; + //drb_iter->dst_addr = 0; + //drb_iter->req_size = 0; + ++drb_iter; + + for (i = 1; i < DMAD_DRB_POOL_SIZE; ++i, ++drb_iter){ + + drb_iter->prev = i - 1; + drb_iter->next = i + 1; + drb_iter->node = i; + //drb_iter->src_addr = 0; + //drb_iter->dst_addr = 0; + //drb_iter->req_size = 0; + } + drq_iter->drb_pool[DMAD_DRB_POOL_SIZE - 1].next = 0; + + /* Initialize DMA channel's DRB free-list, ready-list, and submitted-list */ + drq_iter->fre_head = 1; + drq_iter->fre_tail = DMAD_DRB_POOL_SIZE - 1; + drq_iter->rdy_head = drq_iter->rdy_tail = 0; + drq_iter->sbt_head = drq_iter->sbt_tail = 0; + drq_iter->cpl_head = drq_iter->cpl_tail = 0; + + /* Initialize the channel */ + if (init) + _dmad_channel_init(ch_req); + + /* Initialize cache writeback function */ +#ifndef CONFIG_CPU_DCACHE_ENABLE + drq_iter->dc_writeback = HAL_NULL; + drq_iter->dc_invalidate = HAL_NULL; +#else + drq_iter->dc_writeback = nds32_dma_flush_range; + drq_iter->dc_invalidate = nds32_dma_inv_range; +#endif + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_channel_free + * + * DESCRIPTION + * + * This function frees a DMA channel for future clients' request. + * + * INPUTS + * + * ch_req : Pointer to the DMA request descriptor structure + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful channel free, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_channel_free(const DMAD_CHANNEL_REQUEST_DESC *ch_req){ + + uint32_t status; + DMAD_DRQ *drq; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + if (drq->allocated == 0) + return HAL_ERR_INVALID_POINTER; + + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Obtain exclusive access to the pool of channel queues + */ + status = hal_wait_for_mutex(&dmad.drq_pool_mutex, HAL_SUSPEND); + if (status != HAL_SUCCESS) + return status; + } + + /* Todo: Stop/abort channel I/O if it's busy ? */ + + /* Delete mutex object of DMA queue access control */ + status = hal_destroy_mutex(&drq->drb_pool_mutex); + if (status != HAL_SUCCESS) + return status; + + /* Delete semaphores of free-list allocation operation */ + status = hal_destroy_semaphore(&drq->drb_sem); + if (status != HAL_SUCCESS) + return status; + + /* Reset HISR activation state */ + if (ch_req->controller == DMAD_DMAC_AHB_CORE) + dmad.hisr_as &= ~(1 << ch_req->channel); + else + dmad.hisr_as &= ~(1 << (ch_req->channel + 16)); + + /* Set released flag. */ + drq->allocated = 0; + + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Release exclusive access to the pool of channel queues + */ + status = hal_release_mutex(&dmad.drq_pool_mutex); + if (status != HAL_SUCCESS) + return status; + } + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_ahb_init + * + * DESCRIPTION + * + * This function performs the AHB DMAC channel initialization. + * + * INPUTS + * + * ch_req : Pointer to the DMA request descriptor structure + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _dmad_ahb_init(const DMAD_CHANNEL_REQUEST_DESC *ch_req){ + + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq = (DMAD_DRQ *)ch_req->drq; + DMAD_AHBCH_REQUEST *ahb_req = (DMAD_AHBCH_REQUEST *)(&ch_req->ahbch_req); + uint32_t channel = (uint32_t)ch_req->channel; + uint32_t channel_base = drq->channel_base; + uint32_t core_intl; + + /* Register LISR */ + if (dmad.ahb_lisr_registered == 0){ + status = hal_register_isr(IRQ_DMA_VECTOR, _dmad_ahb_lisr, (void*)0); + // status = hal_register_isr(INTC_DMA_BIT, _dmad_ahb_lisr, (void*)0); + + if (status != HAL_SUCCESS) + return status; + + dmad.ahb_lisr_registered = 1; + } + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Following code require _safe_exit return path */ + + /* INTC */ + /* Disable DMAC interrupt */ + hal_intc_irq_disable(IRQ_DMA_VECTOR); + + /* Clear DMAC interrupt status */ + hal_intc_irq_clean(IRQ_DMA_VECTOR); + + /* Setup DMAC interrupt trigger mode - level trigger */ + /* Setup DMAC interrupt trigger level - assert high */ + hal_intc_irq_config(IRQ_DMA_VECTOR, IRQ_LEVEL_TRIGGER, IRQ_ACTIVE_HIGH); + + /* Enable DMAC interrupt */ + hal_intc_irq_enable(IRQ_DMA_VECTOR); + +#if 0 +#if ( NO_EXTERNAL_INT_CTL == 1 ) + /* + * IVIC without INTC + */ + /* FIXME add trigger mode */ + /* Enable DMAC interupt */ + SR_SETB32(NDS32_SR_INT_MASK2,IRQ_DMA_VECTOR); + + +#else + /* + * INTC + */ + + /* Clear DMAC interrupt status */ + SETB32(INTC_HW1_CLR, INTC_DMA_BIT); + + /* Setup DMAC interrupt trigger mode - level trigger */ + CLRB32(INTC_HW1_TMR, INTC_DMA_BIT); + + /* Setup DMAC interrupt trigger level - assert high */ + CLRB32(INTC_HW1_TLR, INTC_DMA_BIT); + + /* Enable DMAC interrupt */ + SETB32(INTC_HW1_ER, INTC_DMA_BIT); +#endif +#endif + + /* + * PMU + */ + + /* + * Route APB device DMA to an AHB DMAC channel and specify the channel + * number. (connection status could be read back from PMU_AHBDMA_REQACK + * register) + * Note: Only one device is routed per AHB DMA channel, the other target + * should be either (1) the same device (same reqn), or (2) the AHB + * device (reqn = 0). + */ + if (ahb_req->dst_index != PMU_REQN_NONE){ + + /* DMA transfer to device */ + if ((ahb_req->dst_index > PMU_REQN_EXT1) || + (dmad_ahb_ch_route_table[ahb_req->dst_index].route_cr == 0)){ + + status = HAL_ERR_NOT_PRESENT; + goto _safe_exit; + } + + OUT32(dmad_ahb_ch_route_table[ahb_req->dst_index].route_cr, + PMU_DMACUSED_MASK | ((ahb_req->dst_reqn << PMU_CHANNEL_SHIFT) & PMU_CHANNEL_MASK)); + } + else if (ahb_req->src_index != PMU_REQN_NONE){ + + /* DMA transfer from device */ + if ((ahb_req->src_index > PMU_REQN_EXT1) || + (dmad_ahb_ch_route_table[ahb_req->src_index].route_cr == 0)){ + + status = HAL_ERR_NOT_PRESENT; + goto _safe_exit; + } + + OUT32(dmad_ahb_ch_route_table[ahb_req->src_index].route_cr, + PMU_DMACUSED_MASK | ((ahb_req->src_reqn << PMU_CHANNEL_SHIFT) & PMU_CHANNEL_MASK)); + } + + + /* + * DMAC (Controller Setting) + * Note: Controller global setting actually should not placed in this channel + * specific setup routine. However, currently the only global setting + * is a fixed value, so it is ok to set it here. In this way, we save + * the effert to setup the global parameters elsewhere. + */ + + /* INT TC/ERR/ABT status clear */ + SETB32(DMAC_INT_TC_CLR, channel); /* TC clear */ + SETB32(DMAC_INT_ERRABT_CLR, channel + DMAC_INT_ERR_CLR_SHIFT); /* ERR clear */ + SETB32(DMAC_INT_ERRABT_CLR, channel + DMAC_INT_ABT_CLR_SHIFT); /* ABT clear */ + + /* CSR (enable DMAC, set M0 & M1 endian default to little endian transfer) */ + OUT32(DMAC_CSR, DMAC_DMACEN_MASK | + ((DMAC_ENDIAN_LITTLE << DMAC_M0ENDIAN_BIT) & DMAC_M0ENDIAN_MASK) | + ((DMAC_ENDIAN_LITTLE << DMAC_M1ENDIAN_BIT) & DMAC_M1ENDIAN_MASK)); + + /* DMAC (Channel-Specific Setting) */ + /* SYNC */ + if (ahb_req->sync) + SETB32(DMAC_SYNC, channel); + else + CLRB32(DMAC_SYNC, channel); + + /* + * Channel CSR + * CH_EN : 0 (disable) + * DST_SEL : 0 (Master 0) + * SRC_SEL : 0 (Master 0) + * DSTAD_CTL : ahb_req->dst_addr_ctrl + * SRCAD_CTL : ahb_req->src_addr_ctrl + * MODE : 0 (normal) + * DST_WIDTH : ahb_req->dst_width + * SRC_WIDTH : ahb_req->src_width + * ABT : 0 (not abort) + * SRC_SIZE : 0 (burst size = 1 byte) + * PROT1 : 0 (user mode) + * PROT2 : 0 (bot bufferable) + * PROT3 : 0 (not cacheable) + * CHPRI : ahb_req->priority + * DMA_FF_TH : 0 (FIA320 only, threshold = 1) + * TC_MSK : 0 (TC counter status enable) + */ + OUT32(channel_base + DMAC_CSR_OFFSET, + ((ahb_req->src_width << DMAC_CSR_SRC_WIDTH_SHIFT) & DMAC_CSR_SRC_WIDTH_MASK) | + ((ahb_req->src_addr_ctrl << DMAC_CSR_SRCAD_CTL_SHIFT) & DMAC_CSR_SRCAD_CTL_MASK) | + ((ahb_req->dst_width << DMAC_CSR_DST_WIDTH_SHIFT) & DMAC_CSR_DST_WIDTH_MASK) | + ((ahb_req->dst_addr_ctrl << DMAC_CSR_DSTAD_CTL_SHIFT) & DMAC_CSR_DSTAD_CTL_MASK) | + ((ahb_req->priority << DMAC_CSR_CHPRI_SHIFT) & DMAC_CSR_CHPRI_MASK)); + + /* Channel CFG + * INT_TC_MSK : 0 (enable TC int) + * INT_ERR_MSK : 0 (enable ERR int) + * INT_ABT_MSK : 0 (enable ABT int) + * SRC_RS : 0 + * SRC_HE : 0 + * BUSY : r/o + * DST_RS : 0 + * DST_HE : 0 + * LLP_CNT : r/o + */ + OUT32(channel_base + DMAC_CFG_OFFSET, 0); + /*(DMAC_CFG_INT_TC_MSK | DMAC_CFG_INT_ERR_MSK | DMAC_CFG_INT_ABT_MSK)); */ + +#if 1 /* (Not found in AG101 spec -- has removed this setting?) */ + /* - HW handshake mode: CSR & CFG */ + if (ahb_req->hw_handshake != 0){ + + /* Channel CFG - Device REQN and HW-handshake mode */ + uint32_t cfg = IN32(channel_base + DMAC_CFG_OFFSET); + + if (ahb_req->src_index != DMAC_REQN_NONE){ + + OUT32(channel_base + DMAC_CFG_OFFSET, cfg | + ((ahb_req->src_reqn << DMAC_CFG_INT_SRC_RS_SHIFT) & DMAC_CFG_INT_SRC_RS_MASK) | + ((1 << DMAC_CFG_INT_SRC_HE_BIT) & DMAC_CFG_INT_SRC_HE_MASK) | + ((0 << DMAC_CFG_INT_DST_RS_SHIFT) & DMAC_CFG_INT_DST_RS_MASK) | + ((0 << DMAC_CFG_INT_DST_HE_BIT) & DMAC_CFG_INT_DST_HE_MASK)); + } + else { + OUT32(channel_base + DMAC_CFG_OFFSET, cfg | + ((0 << DMAC_CFG_INT_SRC_RS_SHIFT) & DMAC_CFG_INT_SRC_RS_MASK) | + ((0 << DMAC_CFG_INT_SRC_HE_BIT) & DMAC_CFG_INT_SRC_HE_MASK) | + ((ahb_req->dst_reqn << DMAC_CFG_INT_DST_RS_SHIFT) & DMAC_CFG_INT_DST_RS_MASK) | + ((1 << DMAC_CFG_INT_DST_HE_BIT) & DMAC_CFG_INT_DST_HE_MASK)); + } + + /* Channel CSR - Enable HW-handshake mode */ + SETB32(channel_base + DMAC_CSR_OFFSET, DMAC_CSR_MODE_BIT); + } +#endif + /* SRC_ADDR and DST_ADDR - not now */ + + /* LLP */ + OUT32(channel_base + DMAC_LLP_OFFSET, 0); + + /* TOT_SIZE - not now */ + +_safe_exit: + hal_global_int_ctl(core_intl); + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_apb_init + * + * DESCRIPTION + * + * This function performs the APB bridge DMA channel initialization. + * + * INPUTS + * + * ch_req : Pointer to the DMA request descriptor structure + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _dmad_apb_init(const DMAD_CHANNEL_REQUEST_DESC *ch_req){ + + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq = (DMAD_DRQ *)ch_req->drq; + DMAD_APBCH_REQUEST *apb_req = (DMAD_APBCH_REQUEST *)(&ch_req->apbch_req); + uint32_t channel = (uint32_t)ch_req->channel; + uint32_t channel_base = drq->channel_base; + uint32_t channel_cmd = 0; + uint32_t core_intl; + uint32_t dst_bus_sel; + uint32_t src_bus_sel; + + /* Register LISR */ + if (dmad.apb_lisr_registered == 0){ + status = hal_register_isr(IRQ_APBBRIDGE_VECTOR , _dmad_apb_lisr, (void*)0); + + if (status != HAL_SUCCESS) + return status; + + dmad.apb_lisr_registered = 1; + } + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Following code require _safe_exit return path */ + + /* INTC */ + /* Disable APB Bridge interrupt */ + hal_intc_irq_disable(IRQ_APBBRIDGE_VECTOR); + + /* Clear APB Bridge interrupt status */ + hal_intc_irq_clean(IRQ_APBBRIDGE_VECTOR); + + /* Setup APB Bridge interrupt trigger mode - level trigger */ + /* Setup APB Bridge interrupt trigger level - assert high */ + hal_intc_irq_config(IRQ_APBBRIDGE_VECTOR, IRQ_LEVEL_TRIGGER, IRQ_ACTIVE_HIGH); + + /* Enable APB Bridge interrupt */ + hal_intc_irq_enable(IRQ_APBBRIDGE_VECTOR); + +#if 0 +#if ( NO_EXTERNAL_INT_CTL == 1 ) + /* + * IVIC without INTC + */ + /* FIXME add trigger mode */ + /* Enable APB Bridge interrupt */ + SR_SETB32(NDS32_SR_INT_MASK2,IRQ_APBBRIDGE_VECTOR); +#else + /* + * INTC + */ + + /* Clear APB Bridge interrupt status */ + SETB32(INTC_HW1_CLR, INTC_APB_BIT); + + /* Setup APB Bridge interrupt trigger mode - level trigger */ + CLRB32(INTC_HW1_TMR, INTC_APB_BIT); + + /* Setup APB Bridge interrupt trigger level - assert high */ + CLRB32(INTC_HW1_TLR, INTC_APB_BIT); + + /* Enable APB Bridge interrupt */ + SETB32(INTC_HW1_ER, INTC_APB_BIT); +#endif +#endif + /* PMU */ + + /* Check platform version */ + uint32_t max_reqn = _dmad_get_reqn(DMAD_DMAC_APB_CORE, APB_MAX); + + /* + * Undo APB device DMA to AHB DMAC channel routing. (connection status + * is obtained from reading back the PMU_AHBDMA_REQACK register) + */ + + if ((apb_req->src_index > max_reqn) || + (apb_req->dst_index > max_reqn)){ + + status = HAL_ERR_NOT_PRESENT; + goto _safe_exit; + } + + if (apb_req->src_index != APBBR_REQN_NONE){ /* quick filter out non-APB reqn */ + + uint32_t ahb_ch; + + /* Search for source device whether it is re-routed to AHB DMA channel */ + for (ahb_ch = 0; ahb_ch < DMAD_AHB_MAX_CHANNELS; ++ahb_ch){ + + uint32_t ahb_reqn = (IN32(PMU_AHBDMA_REQACK) >> (ahb_ch << 2)) & 0x0000000f; + + if ((ahb_reqn != APBBR_REQN_NONE) && + (ahb_reqn == dmad_apb_reqn_route_table[apb_req->src_index].ahb_reqn)){ + + DMAD_TRACE(("src: re-route DMAC ch %2d to APB.\r\n", ahb_ch)); + + /* got it! un-route from AHB back to APB */ + OUT32(dmad_ahb_ch_route_table[ahb_reqn].route_cr, + ((channel << PMU_CHANNEL_SHIFT) & PMU_CHANNEL_MASK)); + break; + } + } + } + + if (apb_req->dst_index != APBBR_REQN_NONE){ /* quick filter out non-APB reqn */ + + uint32_t ahb_ch; + + /* Search for source device whether it is re-routed to AHB DMA channel */ + for (ahb_ch = 0; ahb_ch < DMAD_AHB_MAX_CHANNELS; ++ahb_ch){ + + uint32_t ahb_reqn = (IN32(PMU_AHBDMA_REQACK) >> (ahb_ch << 2)) & 0x0000000f; + + if ((ahb_reqn != APBBR_REQN_NONE) && + (ahb_reqn == dmad_apb_reqn_route_table[apb_req->dst_index].ahb_reqn)){ + + DMAD_TRACE(("dst: re-route DMAC ch %2d to APB.\r\n", ahb_ch)); + + /* got it! un-route from AHB back to APB */ + OUT32(dmad_ahb_ch_route_table[ahb_reqn].route_cr, + ((channel << PMU_CHANNEL_SHIFT) & PMU_CHANNEL_MASK)); + break; + } + } + } + + /* APB Bridge DMA (Channel Setting) */ + + /* + * - CMD + * ENBDIS : 0 (disable for now) + * FININTSTS : 0 (clear finishing interrupt status) + * FININTENB : 1 (enable finishing interrupt) + * BURMOD : apb_req->burst_mode + * ERRINTSTS : 0 (clear error interrupt status) + * ERRINTENB : 1 (enable error interrupt) + * SRCADRSEL : AHB/APB, driver auto-conf according to apb_req->src_index + * DESADRSEL : AHB/APB, driver auto-conf according to apb_req->dst_index + * SRCADR : apb_req->src_addr_ctrl + * DESADR : apb_req->dst_addr_ctrl + * REQSEL : apb_req->src_index (? a "req/gnt" device looks to be a src... check to use reqn of src or dst) + * DATAWIDTH : apb_req->data_width + */ + + /* + * - CMD + * ENBDIS + * FININTSTS + * FININTENB + * BURMOD + * ERRINTSTS + * ERRINTENB + * SRCADR + * DESADR + * DATAWIDTH + */ + channel_cmd = ((uint32_t)APBBR_DMA_FINTEN_MASK | APBBR_DMA_ERRINTEN_MASK | + ((apb_req->burst_mode << APBBR_DMA_BURST_BIT) & APBBR_DMA_BURST_MASK) | + ((apb_req->src_addr_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) & APBBR_DMA_SRCADDRINC_MASK) | + ((apb_req->dst_addr_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) & APBBR_DMA_DSTADDRINC_MASK) | + ((apb_req->data_width << APBBR_DMA_DATAWIDTH_SHIFT) & APBBR_DMA_DATAWIDTH_MASK)); + + /* + * - CMD + * DSTADRSEL + * DREQSEL (todo: this is FIA320 bit-mask, check AG101 bit-mask location) + */ + if (apb_req->dst_index != APBBR_REQN_NONE) + dst_bus_sel = APBBR_ADDRSEL_APB; + else + dst_bus_sel = APBBR_ADDRSEL_AHB; + + channel_cmd |= ((uint32_t)(APBBR_DMA_DSTADDRSEL_MASK & + (dst_bus_sel << APBBR_DMA_DSTADDRSEL_BIT)) | + (((uint32_t)apb_req->dst_index << APBBR_DMA_DREQSEL_SHIFT) & APBBR_DMA_DREQSEL_MASK)); + + /* + * - CMD + * SRCADRSEL + * SREQSEL (todo: this is FIA320 bit-mask, check AG101 bit-mask location) + */ + if (apb_req->src_index != APBBR_REQN_NONE) + src_bus_sel = APBBR_ADDRSEL_APB; + else + src_bus_sel = APBBR_ADDRSEL_AHB; + + channel_cmd |= ((uint32_t)(APBBR_DMA_SRCADDRSEL_MASK & + (src_bus_sel << APBBR_DMA_SRCADDRSEL_BIT)) | + (((uint32_t)apb_req->src_index << APBBR_DMA_SREQSEL_SHIFT) & APBBR_DMA_SREQSEL_MASK)); + + /* - CMD outport */ + OUT32(channel_base + APBBR_DMA_CMD_OFFSET, channel_cmd); + + /* SRCADR and DESADR - not now */ + + /* CYC - not now */ + +_safe_exit: + hal_global_int_ctl(core_intl); + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_channel_init + * + * DESCRIPTION + * + * This function performs the DMA channel HW initialization abstraction. + * The real initialization task is dispatched according to the requested + * DMA controller type (AHB DMAC or APB bridge DMA controller). + * + * INPUTS + * + * ch_req : Pointer to the DMA request descriptor structure + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_channel_init(const DMAD_CHANNEL_REQUEST_DESC *ch_req){ + + uint32_t status; + + DMAD_TRACE(("_dmad_channel_init\r\n")); + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + if (ch_req->drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + /* Initialize DMA controller */ + if (ch_req->controller == DMAD_DMAC_AHB_CORE) + status = _dmad_ahb_init(ch_req); + else + status = _dmad_apb_init(ch_req); + + /* Register HISR to perform deffered DMA ISR tasks */ + if (dmad.hisr_registered == 0){ + printf("_dmad_channel_init Register HISR\n"); + + dmad.hisr.th.fn = _dmad_hisr; + dmad.hisr.th.arg = &dmad.hisr; + dmad.hisr.th.prio = CONFIG_DMAD_HISR_PRIORITY; + dmad.hisr.th.ptos = &dmad_hisr_stack[DMAD_HISR_STACK_SIZE]; + dmad.hisr.th.stack_size = sizeof(dmad_hisr_stack); + dmad.hisr.th.name = "DMA BH"; + + status = hal_create_bh(&dmad.hisr); + if (status != HAL_SUCCESS) + return status; + + + dmad.hisr_registered = 1; + } + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_channel_enable + * + * DESCRIPTION + * + * This function is a abstraction routine to enable or disable a DMA + * channel. + * + * INPUTS + * + * ch_req : Pointer to the DMA request descriptor structure + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful enable/disable, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_channel_enable(const DMAD_CHANNEL_REQUEST_DESC *ch_req, uint8_t enable){ + + DMAD_DRQ *drq; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + /* Enable/disable DMA channel */ + if (ch_req->controller == DMAD_DMAC_AHB_CORE){ + + if (enable) + SETB32(drq->channel_base + DMAC_CSR_OFFSET, DMAC_CSR_CH_EN_BIT); + else + CLRB32(drq->channel_base + DMAC_CSR_OFFSET, DMAC_CSR_CH_EN_BIT); + } + else { /* APB */ + + if (enable) + SETB32(drq->channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_CHEN_BIT); + else + CLRB32(drq->channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_CHEN_BIT); + } + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_alloc_drb + * + * DESCRIPTION + * + * This function is used to allocate a DRB (DMA request block) within a DMA + * channel. DRB is used to queue all DMA submission requests for the + * channel. Allocated DRB node is moved from the free-list to the ready- + * list. + * + * INPUTS + * + * ch_req : (in) Pointer to the DMA request descriptor structure + * drb : (out) Reference to the pointer of allocated DRB. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful allocation, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +volatile int taskId=0; +uint32_t _dmad_alloc_drb(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB **drb){ + + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq; + uint32_t core_intl; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + /* Obtain exclusive access to the drq from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Lock DMA queue to prevent been updated by other tasks + */ + status = hal_wait_for_mutex(&drq->drb_pool_mutex, HAL_SUSPEND); + if (status != HAL_SUCCESS) + return status; + } + + /* Initialize drb ptr in case of fail allocation */ + *drb = HAL_NULL; + +#ifdef DMAD_POLLING + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + while (drq->fre_head == 0){ + + /* Wait for free urbs. Sleep for 50 ms before polling again. */ + hal_global_int_ctl(core_intl); + hal_sleep(50); + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + } +#else + status = hal_pend_semaphore(&drq->drb_sem, HAL_SUSPEND); + + if (status == HAL_ERR_TIMEOUT){ + + status = HAL_ERR_NO_MEMORY; + goto _safe_exit; + } + else if (status != HAL_SUCCESS){ + + goto _safe_exit; + } + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); +#endif + _dmad_detach_head(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb); + + hal_global_int_ctl(core_intl); + + _dmad_attach_tail(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail, (*drb)->node); + (*drb)->state = DMAD_DRB_STATE_READY; + (*drb)->completion_sem = HAL_NULL; + (*drb)->psp = HAL_NULL; + (*drb)->rcp = HAL_NULL; + if (ch_req->controller == DMAD_DMAC_AHB_CORE) { + (*drb)->src_index = ch_req->ahbch_req.src_index; + (*drb)->dst_index = ch_req->ahbch_req.dst_index; + } else if (ch_req->controller == DMAD_DMAC_APB_CORE) { + (*drb)->src_index = ch_req->apbch_req.src_index; + (*drb)->dst_index = ch_req->apbch_req.dst_index; + } else + status = HAL_ERR_NOT_PRESENT; + + goto _safe_exit; + +_safe_exit: + + /* Release locking of this function from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Unlock DMA queue to allow its access from other tasks + */ + hal_release_mutex(&drq->drb_pool_mutex); + } + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_free_drb + * + * DESCRIPTION + * + * This function is used to free a DRB (DMA request block) within a DMA + * channel. DRB is used to queue all DMA submission requests for the + * channel. Freed DRB node is moved from the ready-list to the free- + * list. + * + * INPUTS + * + * ch_req : (in) Pointer to the DMA request descriptor structure + * drb : (in) Pointer of a DRB struct to be freed. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful freeing, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_free_drb(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb){ + + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq; + uint32_t core_intl; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + /* Obtain exclusive access to the drq from other tasks */ + if (hal_current() != HAL_NULL){ + + /* Suspending is only valid to the current task -- no need to lock if invoked from HISR. */ + status = hal_wait_for_mutex(&drq->drb_pool_mutex, HAL_SUSPEND); + if (status != HAL_SUCCESS) + return status; + } + + /* Following code require _safe_exit return path */ + + if ((drq->rdy_head == 0) || (drb->node == 0) || + (drb->node >= DMAD_DRB_POOL_SIZE)){ + + DMAD_TRACE(("Ready-queue is empty or invalid node!\r\n")); + /* Unlock DMA queue to allow its access from other tasks */ + status = HAL_ERR_INVALID_ENTRY; + goto _safe_exit; + } + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + _dmad_detach_node(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail, drb->node); + _dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb->node); + + hal_global_int_ctl(core_intl); + + drb->state = DMAD_DRB_STATE_FREE; + drb->completion_sem = HAL_NULL; + +_safe_exit: + + /* Release locking of this function from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR + * Unlock DMA queue to allow its access from other tasks + */ + hal_release_mutex(&drq->drb_pool_mutex); + } + + return status; +} + + +int dmad_apb_config_dir(const DMAD_CHANNEL_REQUEST_DESC *ch_req, uint8_t dir) +{ + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq = (DMAD_DRQ *)ch_req->drq; + DMAD_APBCH_REQUEST *apb_req = (DMAD_APBCH_REQUEST *)(&ch_req->apbch_req); + uint32_t channel_base = drq->channel_base; + uint32_t channel_cmd = 0; + uint32_t dst_bus_sel; + uint32_t src_bus_sel; + + channel_cmd = IN32(channel_base + APBBR_DMA_CMD_OFFSET); + channel_cmd &= ~(uint32_t) + (APBBR_DMA_SRCADDRINC_MASK | APBBR_DMA_DSTADDRINC_MASK | + APBBR_DMA_DSTADDRSEL_MASK | APBBR_DMA_DREQSEL_MASK | + APBBR_DMA_SRCADDRSEL_MASK | APBBR_DMA_SREQSEL_MASK); + if( dir == 0){ + channel_cmd = ((uint32_t)APBBR_DMA_FINTEN_MASK | APBBR_DMA_ERRINTEN_MASK | + ((apb_req->src_addr_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) & APBBR_DMA_SRCADDRINC_MASK) | + ((apb_req->dst_addr_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) & APBBR_DMA_DSTADDRINC_MASK)); + + /* + * - CMD + * DSTADRSEL + * DREQSEL (todo: this is FIA320 bit-mask, check AG101 bit-mask location) + */ + if (apb_req->dst_index != APBBR_REQN_NONE) + dst_bus_sel = APBBR_ADDRSEL_APB; + else + dst_bus_sel = APBBR_ADDRSEL_AHB; + + channel_cmd |= ((uint32_t)(APBBR_DMA_DSTADDRSEL_MASK & + (dst_bus_sel << APBBR_DMA_DSTADDRSEL_BIT)) | + (((uint32_t)apb_req->dst_index << APBBR_DMA_DREQSEL_SHIFT) & APBBR_DMA_DREQSEL_MASK)); + + /* + * - CMD + * SRCADRSEL + * SREQSEL (todo: this is FIA320 bit-mask, check AG101 bit-mask location) + */ + if (apb_req->src_index != APBBR_REQN_NONE) + src_bus_sel = APBBR_ADDRSEL_APB; + else + src_bus_sel = APBBR_ADDRSEL_AHB; + + channel_cmd |= ((uint32_t)(APBBR_DMA_SRCADDRSEL_MASK & + (src_bus_sel << APBBR_DMA_SRCADDRSEL_BIT)) | + (((uint32_t)apb_req->src_index << APBBR_DMA_SREQSEL_SHIFT) & APBBR_DMA_SREQSEL_MASK)); + + /* - CMD outport */ + OUT32(channel_base + APBBR_DMA_CMD_OFFSET, channel_cmd); + + } else { + channel_cmd = ((uint32_t)APBBR_DMA_FINTEN_MASK | APBBR_DMA_ERRINTEN_MASK | + ((apb_req->dst_addr_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) & APBBR_DMA_SRCADDRINC_MASK) | + ((apb_req->src_addr_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) & APBBR_DMA_DSTADDRINC_MASK)); + + /* + * - CMD + * DSTADRSEL + * DREQSEL (todo: this is FIA320 bit-mask, check AG101 bit-mask location) + */ + if (apb_req->src_index != APBBR_REQN_NONE) + src_bus_sel = APBBR_ADDRSEL_APB; + else + src_bus_sel = APBBR_ADDRSEL_AHB; + + channel_cmd |= ((uint32_t)(APBBR_DMA_DSTADDRSEL_MASK & + (src_bus_sel << APBBR_DMA_DSTADDRSEL_BIT)) | + (((uint32_t)apb_req->src_index << APBBR_DMA_DREQSEL_SHIFT) & APBBR_DMA_DREQSEL_MASK)); + + /* + * - CMD + * SRCADRSEL + * SREQSEL (todo: this is FIA320 bit-mask, check AG101 bit-mask location) + */ + if (apb_req->dst_index != APBBR_REQN_NONE) + dst_bus_sel = APBBR_ADDRSEL_APB; + else + dst_bus_sel = APBBR_ADDRSEL_AHB; + + channel_cmd |= ((uint32_t)(APBBR_DMA_SRCADDRSEL_MASK & + (dst_bus_sel << APBBR_DMA_SRCADDRSEL_BIT)) | + (((uint32_t)apb_req->dst_index << APBBR_DMA_SREQSEL_SHIFT) & APBBR_DMA_SREQSEL_MASK)); + + /* - CMD outport */ + OUT32(channel_base + APBBR_DMA_CMD_OFFSET, channel_cmd); + + } + return status; + +} +void set_drq_transfer_size(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb) +{ + int data_width = -1; + if (ch_req->controller == DMAD_DMAC_AHB_CORE) { + /* AHB DMA */ + DMAD_AHBCH_REQUEST *ahb_req = (DMAD_AHBCH_REQUEST *)(&ch_req->ahbch_req); + if (drb->src_index == DMAC_REQN_NONE && drb->src_index == DMAC_REQN_NONE) + data_width = 0; + else { + if (drb->src_index != DMAC_REQN_NONE) + data_width = 2 - ahb_req->src_width; + else if (drb->dst_index != DMAC_REQN_NONE) + data_width = 2 - ahb_req->dst_width; + } + } else { + /* APB DMA */ + DMAD_APBCH_REQUEST *apb_req = (DMAD_APBCH_REQUEST *)(&ch_req->apbch_req); + data_width = 2 - apb_req->data_width; + } + if (data_width < 0) + KASSERT(1); + + drb->transfer_size = drb->req_size << data_width; +} +/***************************************************************************** + * FUNCTION + * + * _dmad_submit_request + * + * DESCRIPTION + * + * This function is used to submit a DRB (DMA request block) to a DMA + * channel. DRB is used to queue all DMA submission requests for the + * channel. Submitted DRB node is moved from the ready-list to the + * submitted-list. DMA kick-off is performed automatically if the DMA + * transaction has not started. When the DRB is completed, it will be + * removed from the submittied-list to the free-list in the DMA ISR. + * + * INPUTS + * + * ch_req : (in) Pointer to the DMA request descriptor structure + * drb : (in) Pointer of a DRB struct to be submitted. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful submission, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_submit_request(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb){ + + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq; + uint32_t core_intl; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + /* Obtain exclusive access to the drq from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR + * Lock DMA queue to prevent been updated by other tasks + */ + status = hal_wait_for_mutex(&drq->drb_pool_mutex, HAL_SUSPEND); + if (status != HAL_SUCCESS) + return status; + } + + /* Following code require _safe_exit return path */ + if ((drq->rdy_head == 0) || (drb->node == 0) || (drb->node >= DMAD_DRB_POOL_SIZE)){ + + status = HAL_ERR_INVALID_ENTRY; + goto _safe_exit; + } + + _dmad_detach_node(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail, drb->node); + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* + * writeback d-cache if necessary + * + * Note: Here we take the assumption that, after writeback, the memory + * contents is in physical ram and valid for for dma transfer. + * Hence, we only need to do writeback at the beginning of the drb + * submission, and ignore the writeback before kicking off every + * drb in isr. + * + * Place writeback code before interrupt-disable to shorten the + * disable time. This might generate a penalty of cache-miss + * if the writeback routine also invalidated the cache contents. + */ + + set_drq_transfer_size(ch_req, drb); +#if ( defined(CONFIG_CPU_DCACHE_ENABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH) ) + /* source is memory */ + //if (drq->dc_writeback != HAL_NULL && drb->src_index == DMAC_REQN_NONE) + if ( (unsigned long)drb->src_addr >= NTC0_BONDER_START && (unsigned long)drb->src_addr < NTC0_BONDER_END )//JUNIOR@2013/05/16 + drq->dc_writeback((unsigned long)(drb->src_addr),(unsigned long)(drb->src_addr) + (unsigned long)(drb->transfer_size)); +#endif + /* Check if submission is performed to an empty queue */ + if (drq->sbt_head == 0){ + + _dmad_attach_tail(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, drb->node); + drb->state = DMAD_DRB_STATE_SUBMITTED; + + hal_global_int_ctl(core_intl); + + /* pre-submission-programming */ + if (drb->psp) + drb->psp(drb->data); + + /* DMA is not running, so kick off transmission */ + if (ch_req->controller == DMAD_DMAC_AHB_CORE){ /* AHB */ + + /* Source and destination address */ + OUT32(drq->channel_base + DMAC_SRC_ADDR_OFFSET, drb->src_addr); + OUT32(drq->channel_base + DMAC_DST_ADDR_OFFSET, drb->dst_addr); + + /* Transfer size (in units of source width) */ + OUT32(drq->channel_base + DMAC_SIZE_OFFSET, drb->req_size); + + /* Enable DMA channel (Kick off transmission when client enable it's transfer state) */ + SETB32(drq->channel_base + DMAC_CSR_OFFSET, DMAC_CSR_CH_EN_BIT); + } + else { /* APB */ + + /* Source and destination address */ + OUT32(drq->channel_base + APBBR_DMA_SAD_OFFSET, drb->src_addr); + OUT32(drq->channel_base + APBBR_DMA_DAD_OFFSET, drb->dst_addr); + + /* Transfer size (in units of source width) */ + OUT32(drq->channel_base + APBBR_DMA_CYC_OFFSET, drb->req_size & APBBR_DMA_CYC_MASK); + + /* Enable DMA channel (Kick off transmission when client enable it's transfer state) */ + SETB32(drq->channel_base + APBBR_DMA_CMD_OFFSET, APBBR_DMA_CHEN_BIT); + } + } + else { + /* DMA is already running, so only queue DRB to the end of the list */ + _dmad_attach_tail(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, drb->node); + drb->state = DMAD_DRB_STATE_SUBMITTED; + + hal_global_int_ctl(core_intl); + } + +_safe_exit: + + /* Release locking of this function from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR + * Unlock DMA queue to allow its access from other tasks + */ + hal_release_mutex(&drq->drb_pool_mutex); + } + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _dmad_cancel_request + * + * DESCRIPTION + * + * This function is used to cancel a submitted DRB (DMA request block) + * of a DMA channel. DRB is used to queue all DMA submission requests for + * the channel. Submitted DRB node is moved from the ready-list to the + * submitted-list. Cancellation will fail if the DRB has already been + * kicked off and is waiting to be completed. + * + * INPUTS + * + * ch_req : (in) Pointer to the DMA request descriptor structure + * drb : (in) Pointer of a DRB struct to be cancelled. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful cancellation, + * else positive value is DMAD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _dmad_cancel_request(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb){ + + DMAD_DRQ *drq;; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + if (drq->sbt_head == 0) + return HAL_ERR_INVALID_ENTRY; + + if ((drb->node == 0) || (drb->node >= DMAD_DRB_POOL_SIZE)) + return HAL_ERR_INVALID_ENTRY; + + if (drb->completion_sem != HAL_NULL) + hal_destroy_semaphore(drb->completion_sem); + + // NDS_DCache_Enable(); + + return HAL_ERR_UNAVAILABLE; +} + +uint32_t _dmad_wait(DMAD_CHANNEL_REQUEST_DESC *ch_req){ + + uint32_t status = HAL_SUCCESS; + DMAD_DRQ *drq; + uint32_t core_intl; + + if (ch_req == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + drq = (DMAD_DRQ *)ch_req->drq; + + if (drq == HAL_NULL) + return HAL_ERR_INVALID_POINTER; + + /* Obtain exclusive access to the drq from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Lock DMA queue to prevent been updated by other tasks + */ + status = hal_wait_for_mutex(&drq->drb_pool_mutex, HAL_SUSPEND); + if (status != HAL_SUCCESS) + return status; + } + +#ifdef DMAD_POLLING + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + while (drq->sbt_head != 0){ + + hal_global_int_ctl(core_intl); + hal_sleep(50); + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + } +#else + status = hal_pend_semaphore(&drq->drb_sem, 300); + + if (status == HAL_ERR_TIMEOUT){ + + status = HAL_ERR_NO_MEMORY; + goto _safe_exit; + } + else if (status != HAL_SUCCESS){ + + goto _safe_exit; + } + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); +#endif + hal_global_int_ctl(core_intl); + goto _safe_exit; + +_safe_exit: + + /* Release locking of this function from other tasks */ + if (hal_current() != HAL_NULL){ + + /* + * Suspending is only valid to the current task -- no need to lock if invoked from HISR. + * Unlock DMA queue to allow its access from other tasks + */ + hal_release_mutex(&drq->drb_pool_mutex); + } + + return status; +} diff --git a/bsp/AE210P/driver/dma/dmad.h b/bsp/AE210P/driver/dma/dmad.h new file mode 100644 index 0000000000000000000000000000000000000000..3710753d747a077a80c5be2fe9f79898236e9039 --- /dev/null +++ b/bsp/AE210P/driver/dma/dmad.h @@ -0,0 +1,275 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Aug.21.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * dmad.h + * + * DESCRIPTION + * + * DMA controller driver internal supplement library. + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * ag101regs.h + * ag101defs.h + * + ****************************************************************************/ +#ifndef __DMAD_H__ +#define __DMAD_H__ + +#include + +/***************************************************************************** + * Configuration section + ****************************************************************************/ +/* Code size control */ +#define DMAD_SMALL_FOOTPRINT 0 /* non-zero to disable extra features for small footprint */ + +/* Debug trace enable switch */ +#define DMAD_DEBUG_TRACE 0 /* non-zero to enable debug trace message */ + +/* DMAD globals section */ +enum DMAD_DMAC_CORE { DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE }; + +/* + * AHB Channel Request + * + * Notes for developers: + * These should be channel-only properties. Controller-specific properties + * should be separated as other driver structure or driver buildin-hardcode. + * If controller properties are embeded in this union, request for a channel + * may unexpectedly override the controller setting of the request of other + * channels. + */ +typedef struct DMAD_AHBCH_REQUEST_STRUCT{ + + /* controller property (removed! should not exist in this struct) */ + // uint8_t big_endian; /* (in) currently only M0 is designed, and transfer endian is default to little */ + + /* channel property */ + uint32_t sync; /* (in) non-zero if src and dst have different clock domain */ + uint32_t priority; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */ + uint32_t hw_handshake; /* (in) non-zero to enable hardware handshake mode */ + /* (required when need multiple bursts or in chain mode?) */ + uint32_t burst_size; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */ + + /* source property */ + uint32_t src_width; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */ + uint32_t src_addr_ctrl; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */ + uint32_t src_reqn; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */ + uint32_t src_index; + + /* destination property */ + uint32_t dst_width; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */ + uint32_t dst_addr_ctrl; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */ + uint32_t dst_reqn; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */ + uint32_t dst_index; + +} DMAD_AHBCH_REQUEST; + +/* + * APB Channel Request + * + * Notes for developers: + * These should be channel-only properties. Controller-specific properties + * should be separated as other driver structure or driver buildin-hardcode. + * If controller properties are embeded in this union, request for a channel + * may unexpectedly override the controller setting of the request of other + * channels. + */ +typedef struct DMAD_APBCH_REQUEST_STRUCT{ + + /* controller property (removed! should not exist in this struct) */ + + /* channel property */ + uint32_t burst_mode; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */ + uint32_t data_width; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */ + + /* source property */ + uint32_t src_addr_ctrl; /* (in) APBBR_ADDRINC_xxx */ + uint32_t src_reqn; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */ + uint32_t src_index; + + /* destination property */ + uint32_t dst_addr_ctrl; /* (in) APBBR_ADDRINC_xxx */ + uint32_t dst_reqn; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */ + uint32_t dst_index; + +} DMAD_APBCH_REQUEST; + +/* Channel Request Descriptor */ +typedef struct DMAD_CHANNEL_REQUEST_DESC_STRUCT{ + + uint32_t controller; /* (in) Use DMA controller in AHB or APB - one of the enum value of DMAD_DMAC_CORE */ + uint32_t channel; /* (out) Allocated/granted channel */ + + void *drq; /* (out) Handle to DMA request queue (ptr to DMAD_DRQ, internal use) */ + + /* + * Properties for channel-alloc request + * Notes for developers: + * These should be channel-only properties. Controller-specific properties + * should be separated as other driver structure or driver buildin-hardcode. + * If controller properties are embeded in this union, request for a channel + * may unexpectedly override the controller setting of the request of other + * channels. + */ + union { + DMAD_AHBCH_REQUEST ahbch_req; /* (in) parameters for AHB DMAC channel request */ + DMAD_APBCH_REQUEST apbch_req; /* (in) parameters for APB Bridge embeded DMA conteoller channel request */ + }; + +} DMAD_CHANNEL_REQUEST_DESC; + + +enum DMAD_DRB_STATE{ + + DMAD_DRB_STATE_FREE = 0, + DMAD_DRB_STATE_READY, + DMAD_DRB_STATE_SUBMITTED, + DMAD_DRB_STATE_TRANSFERRING, + DMAD_DRB_STATE_COMPLETED, + DMAD_DRB_STATE_ERROR, + DMAD_DRB_STATE_ABORT, +}; + +/* DMA request block */ +typedef struct DMAD_DRB_STRUCT{ + + uint32_t prev; /* (internal) Linked list previous node */ + uint32_t next; /* (internal) Linked list next node */ + uint32_t node; /* (internal) Linked list this node */ + + uint32_t state; /* (out) DRB's current state in the whole submission cycle. */ + + void *src_addr; /* (in) Source address in this request */ + + void *dst_addr; /* (in) Destination address in this submission request */ + + uint32_t req_size; /* (in) AHB DMA (12 bits): 0 ~ 4095, unit is number of "data width" */ + /* APB DMA (24 bits): 0 ~ 16M-1, unit is number of "data width * burst size" */ + uint32_t transfer_size; /* req_size * data_width*/ + hal_semaphore_t *completion_sem;/* (in) Application supplied semaphore to signal completion of this */ + /* DMA request block. Specify null to by-pass this mechanism. */ + void (*psp)(void*); /* pre-submission programming */ + void (*rcp)(void*); /* completion-of-submission programming */ + void *data; + uint32_t src_index; /* to indicate it's device or memory */ + uint32_t dst_index; /* to indicate it's device or memory */ +// uint32_t src_reqn; /* to indicate it's device or memory */ +// uint32_t dst_reqn; /* to indicate it's device or memory */ + +} DMAD_DRB; + +enum DMAD_CHDIR +{ + DMAD_DIR_A0_TO_A1 = 0, + DMAD_DIR_A1_TO_A0 = 1, +}; +/* Debug Trace Mechanism */ +#if (DMAD_DEBUG_TRACE) + +#define DMAD_TRACE(x) printf x +#define DMAD_STRACE(x) printf x + +#else /* DMAD_DEBUG_TRACE */ + +#define DMAD_TRACE(x) +#define DMAD_STRACE(x) + +#endif /* DMAD_DEBUG_TRACE */ + + +/***************************************************************************** + * DMAD Driver Interface + * + * [Structures] + * + * [Functions] + * + * + ****************************************************************************/ + +extern uint32_t _dmad_channel_alloc(DMAD_CHANNEL_REQUEST_DESC *ch_req, uint8_t init); +extern uint32_t _dmad_channel_free(const DMAD_CHANNEL_REQUEST_DESC *ch_req); +extern uint32_t _dmad_channel_init(const DMAD_CHANNEL_REQUEST_DESC *ch_req); +extern uint32_t _dmad_channel_enable(const DMAD_CHANNEL_REQUEST_DESC *ch_req, uint8_t enable); + +extern uint32_t _dmad_alloc_drb(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB **drb); +extern uint32_t _dmad_free_drb(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb); + +extern uint32_t _dmad_submit_request(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb); +extern uint32_t _dmad_cancel_request(DMAD_CHANNEL_REQUEST_DESC *ch_req, DMAD_DRB *drb); +extern uint32_t _dmad_wait(DMAD_CHANNEL_REQUEST_DESC *ch_req); + +extern uint32_t _dmad_get_reqn(uint32_t dma_controller, uint32_t device); + +enum ahp_reqn_index_t { + AHB_NONE, + AHB_CFC, + AHB_SSP, + AHB_UART1TX, + AHB_UART1RX, + AHB_I2SAC97, + AHB_USB, + AHB_EXT0, + AHB_EXT1, + AHB_SSP1TX, + AHB_SSP1RX, + AHB_UART2TX, + AHB_UART2RX, + AHB_UART4TX, + AHB_UART4RX, + AHB_SDC, + AHB_SSP2TX, + AHB_SSP2RX, + AHB_USB_2_0, + AHB_USB_1_1_EP1, + AHB_USB_1_1_EP2, + AHB_USB_1_1_EP3, + AHB_USB_1_1_EP4 +}; + +enum apb_reqn_index_t { + APB_NONE, + APB_CFC, + APB_SSP, + APB_BTUART, + APB_I2SAC97, + APB_STUART, + APB_I2S, + APB_SSP2, + APB_EXT0, + APB_EXT1, + APB_SSP1TX, + APB_SSP1RX, + APB_UART2TX, + APB_UART2RX, + APB_UART4TX, + APB_UART4RX, + APB_SDC, + APB_SSP2TX, + APB_SSP2RX, + APB_USB_2_0, + APB_USB_1_1_EP1, + APB_USB_1_1_EP2, + APB_USB_1_1_EP3, + APB_USB_1_1_EP4, + APB_MAX +}; + +#endif /* __DMAD_H__ */ diff --git a/bsp/AE210P/driver/gpio/gpio.c b/bsp/AE210P/driver/gpio/gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..add7e79cc064c0b679e90d5d6317418912af7074 --- /dev/null +++ b/bsp/AE210P/driver/gpio/gpio.c @@ -0,0 +1,86 @@ +#include "gpio.h" +//#include "hal.h" +#include "bsp_hal.h" + +struct gpio_dev_t *gpio_p; + +//static void _gpio_lisr(int vector) +//{ +// DEBUG(0, 1, "Enter\n"); +// if (vector != IRQ_GPIO_VECTOR) +// hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); +// +// /* Disable GPIO interrupt */ +// uint32_t prv_msk = hal_intc_irq_mask(IRQ_GPIO_VECTOR); +// +// /* Get int state and then clear it */ +// unsigned int int_sr = IN32(GPIOC_INT_RAW_STATE); +// gpio_p->int_data = int_sr; +// OUT32(GPIOC_INT_CLEAR, int_sr); +// +// /* Clean GPIO pending */ +// hal_intc_irq_clean(IRQ_GPIO_VECTOR); +// +// /* Enable higher priority interrupt */ +// /* comment it to disable nested interrupt */ +// GIE_ENABLE(); +// hal_raise_bh(&gpio_p->hisr); +// +// GIE_DISABLE(); +// /* - Enable GPIO interrupt */ +// hal_intc_irq_unmask(prv_msk); +//} + +int gpio_init(struct gpio_dev_t *gpio) +{ +// int status = HAL_SUCCESS; +// int core_intl; +// +// /* initialize global gpio pointer */ +// gpio_p = gpio; +// core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); +// +// /* INTC */ +// // - Disable GPIO interrupt +// hal_intc_irq_disable(IRQ_GPIO_VECTOR); +// // - Clear GPIO interrupt status +// hal_intc_irq_clean(IRQ_GPIO_VECTOR); +// // - Setup #PENIRQ trigger mode - edge trigger +// // - Setup #PENIRQ trigger level - active high +// hal_intc_irq_config(IRQ_GPIO_VECTOR, IRQ_EDGE_TRIGGER, IRQ_ACTIVE_HIGH); +// +// +// /* GPIO */ +// /* falling, interrupt when pressed */ +// //OUT32(GPIOC_INT_RISE_NEG, 0xFFFFFFFF); +// /* rising, interrupt when released */ +// OUT32(GPIOC_INT_RISE_NEG, 0x0); +// /* enable all gpio interrupt GPIO1-5*/ +// OUT32(GPIOC_INT_ENABLE, 0x3E); +// /* set the max value to debounce */ +// OUT32(GPIOC_INT_BOUNCE_PRESCALE, 0xFFFF); +// /* enable debounce */ +// OUT32(GPIOC_INT_BOUNCE_ENABLE, 0x3E); +// +// status = hal_register_isr(IRQ_GPIO_VECTOR, _gpio_lisr, (void*)0); +// +// if (status != HAL_SUCCESS){ +// DEBUG(1, 1, "Failed to register GPIO driver LISR!\n"); +// return status; +// } +// +// status = hal_create_bh(&gpio->hisr); +// if (status != HAL_SUCCESS){ +// DEBUG(1, 1, "Failed to create GPIO driver HISR!\n"); +// return status; +// } +// +// // - Enable GPIO interrupt +// hal_intc_irq_enable(IRQ_GPIO_VECTOR); +// +// /* Restore CPU interrupt controller to previous level */ +// hal_global_int_ctl(core_intl); +// return status; + + return 0; +} diff --git a/bsp/AE210P/driver/gpio/gpio.h b/bsp/AE210P/driver/gpio/gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..6758891810b40c689c0ffa650145f1fded5309a2 --- /dev/null +++ b/bsp/AE210P/driver/gpio/gpio.h @@ -0,0 +1,52 @@ +#ifndef __AG101_GPIOC_INC__ +#define __AG101_GPIOC_INC__ + +//#include "hal.h" + +// GPIO port name definition +typedef enum GPIOD_PORTS +{ + GPIO0 = 0x00000001, + GPIO1 = 0x00000002, + GPIO2 = 0x00000004, + GPIO3 = 0x00000008, + GPIO4 = 0x00000010, + GPIO5 = 0x00000020, + GPIO6 = 0x00000040, + GPIO7 = 0x00000080, + + GPIO8 = 0x00000100, + GPIO9 = 0x00000200, + GPIO10 = 0x00000400, + GPIO11 = 0x00000800, + GPIO12 = 0x00001000, + GPIO13 = 0x00002000, + GPIO14 = 0x00004000, + GPIO15 = 0x00008000, + + GPIO16 = 0x00010000, + GPIO17 = 0x00020000, + GPIO18 = 0x00040000, + GPIO19 = 0x00080000, + GPIO20 = 0x00100000, + GPIO21 = 0x00200000, + GPIO22 = 0x00400000, + GPIO23 = 0x00800000, + + GPIO24 = 0x01000000, + GPIO25 = 0x02000000, + GPIO26 = 0x04000000, + GPIO27 = 0x08000000, + GPIO28 = 0x10000000, + GPIO29 = 0x20000000, + GPIO30 = 0x40000000, + GPIO31 = 0x80000000, + +} GPIOD_PORTS; + +struct gpio_dev_t +{ +// hal_bh_t hisr; + unsigned int int_data; +}; +#endif // __AG101_GPIOC_INC__ diff --git a/bsp/AE210P/driver/lcd/Kbuild b/bsp/AE210P/driver/lcd/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..0d69174510d146c340539bf8577ff87834acf686 --- /dev/null +++ b/bsp/AE210P/driver/lcd/Kbuild @@ -0,0 +1 @@ +lib-${CONFIG_FB_FTLCDC100} += font.o lcd.o diff --git a/bsp/AE210P/driver/lcd/font.c b/bsp/AE210P/driver/lcd/font.c new file mode 100644 index 0000000000000000000000000000000000000000..eb1428c5361165f161d4dc3c6c107660424123d6 --- /dev/null +++ b/bsp/AE210P/driver/lcd/font.c @@ -0,0 +1,248 @@ +#include "lcd/lcd.h" + +/* + * Due to legal issue, this section is disabled and only available to the + * usage of internal developement and testing. + * + * Build-in OSD 12x16 font table (sizeof(UINT16) * 16 per font) + * LCDC maximum number of fonts = 256 + * + * Font Name : Courier New (C) Microsoft + * + * ASCII Code Range : (0x20~0x7e, and 0x7f is a special symbol looks like 'v') + * " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~v" + */ + +uint16_t drv_lcd_font_table[] __attribute__((aligned(4))) = { + + /* ASCII 0x20 ~ 0x2F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0000, 0x0000, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01b0, 0x01b0, 0x0120, 0x0120, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0090, 0x0090, 0x0120, 0x03f0, 0x0120, + 0x0120, 0x03f0, 0x0120, 0x0240, 0x0240, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0040, 0x00e0, 0x0120, 0x0100, 0x00c0, + 0x0020, 0x0120, 0x01c0, 0x0040, 0x0040, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00c0, 0x0120, 0x0120, 0x00c0, 0x01f0, + 0x0060, 0x0090, 0x0090, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0040, 0x0040, 0x0040, 0x0040, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0040, 0x0040, 0x0040, 0x0020, 0x0020, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0100, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, 0x03e0, 0x0080, 0x0140, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0040, 0x0040, 0x0040, 0x03f8, + 0x0040, 0x0040, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x00c0, 0x0080, 0x0180, 0x0100, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x00c0, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0010, 0x0010, 0x0020, 0x0020, 0x0040, 0x0040, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0200, 0x0000, 0x0000, 0x0000, + + /* ASCII 0x30 ~ 0x3F */ + 0x0000, 0x0000, 0x0000, 0x01e0, 0x0210, 0x0210, 0x0210, 0x0210, + 0x0210, 0x0210, 0x0210, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0040, 0x01c0, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0040, 0x0040, 0x01f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01c0, 0x0220, 0x0020, 0x0040, 0x0040, + 0x0080, 0x0100, 0x0220, 0x03e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01c0, 0x0220, 0x0020, 0x0020, 0x00c0, + 0x0020, 0x0020, 0x0220, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0060, 0x00a0, 0x00a0, 0x0120, 0x0120, + 0x03f0, 0x0020, 0x0020, 0x0070, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01f0, 0x0100, 0x0100, 0x01e0, 0x0010, + 0x0010, 0x0010, 0x0210, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0070, 0x0080, 0x0100, 0x0100, 0x01e0, + 0x0110, 0x0110, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x03f0, 0x0210, 0x0010, 0x0020, 0x0020, + 0x0020, 0x0040, 0x0040, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01c0, 0x0220, 0x0220, 0x0220, 0x01c0, + 0x0220, 0x0220, 0x0220, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01e0, 0x0210, 0x0210, 0x0210, 0x0210, + 0x01f0, 0x0010, 0x0020, 0x03c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00c0, 0x00c0, + 0x0000, 0x0000, 0x00c0, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00c0, 0x00c0, + 0x0000, 0x0000, 0x00c0, 0x0080, 0x0180, 0x0100, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0018, 0x0060, 0x0080, + 0x0300, 0x0080, 0x0060, 0x0018, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07f0, 0x0000, 0x0000, + 0x07f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0300, 0x00c0, 0x0020, + 0x0018, 0x0020, 0x00c0, 0x0300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01c0, 0x0220, 0x0020, 0x0020, + 0x0040, 0x0080, 0x0000, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, + + /* ASCII 0x40 ~ 0x4F */ + 0x0000, 0x0000, 0x0000, 0x00e0, 0x0110, 0x0210, 0x0270, 0x0290, + 0x0290, 0x0270, 0x0200, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01c0, 0x00c0, 0x00c0, 0x0120, + 0x0120, 0x01e0, 0x0210, 0x0738, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03e0, 0x0110, 0x0110, 0x01e0, + 0x0110, 0x0110, 0x0110, 0x03e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x00d0, 0x0130, 0x0200, 0x0200, + 0x0200, 0x0200, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03c0, 0x0120, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0120, 0x03c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x0110, 0x0120, 0x01e0, + 0x0120, 0x0100, 0x0110, 0x03f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x0110, 0x0150, 0x01c0, + 0x0140, 0x0100, 0x0100, 0x03c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x00d0, 0x0130, 0x0200, 0x0200, + 0x0278, 0x0210, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0110, 0x0110, 0x01f0, + 0x0110, 0x0110, 0x0110, 0x03b8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01f0, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0040, 0x0040, 0x01f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01f8, 0x0020, 0x0020, 0x0020, + 0x0220, 0x0220, 0x0220, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0120, 0x0140, 0x0180, + 0x01c0, 0x0120, 0x0110, 0x0398, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x07c0, 0x0100, 0x0100, 0x0100, + 0x0110, 0x0110, 0x0110, 0x07f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0718, 0x0318, 0x02a8, 0x02a8, + 0x02a8, 0x0248, 0x0208, 0x0718, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0190, 0x0190, 0x0150, + 0x0150, 0x0150, 0x0130, 0x03b0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x00e0, 0x0110, 0x0208, 0x0208, + 0x0208, 0x0208, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, + + /* ASCII 0x50 ~ 0x5F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x03e0, 0x0110, 0x0110, 0x0110, + 0x01e0, 0x0100, 0x0100, 0x03c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x00e0, 0x0110, 0x0208, 0x0208, + 0x0208, 0x0208, 0x0110, 0x00e0, 0x00f8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03e0, 0x0110, 0x0110, 0x0110, + 0x01e0, 0x0120, 0x0110, 0x0388, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01d0, 0x0230, 0x0200, 0x01e0, + 0x0010, 0x0010, 0x0310, 0x02e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03f8, 0x0248, 0x0248, 0x0040, + 0x0040, 0x0040, 0x0040, 0x01f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0738, 0x0210, 0x0120, 0x0120, + 0x0120, 0x00c0, 0x00c0, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0718, 0x0208, 0x0248, 0x0248, + 0x02a8, 0x02a8, 0x02a8, 0x0110, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0110, 0x00a0, 0x0040, + 0x0040, 0x00a0, 0x0110, 0x03b8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0110, 0x00a0, 0x00a0, + 0x0040, 0x0040, 0x0040, 0x01f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x0210, 0x0020, 0x0040, + 0x0080, 0x0110, 0x0210, 0x03f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00e0, 0x0080, 0x0080, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x00e0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0100, 0x0100, 0x0100, 0x0080, 0x0080, + 0x0040, 0x0040, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01c0, 0x0040, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x01c0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, 0x0140, 0x0220, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07f8, + + /* ASCII 0x60 ~ 0x6F */ + 0x0000, 0x0000, 0x0000, 0x0080, 0x0040, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01e0, 0x0210, + 0x01f0, 0x0210, 0x0230, 0x01d8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0600, 0x0200, 0x0200, 0x02e0, 0x0310, + 0x0210, 0x0210, 0x0310, 0x06e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01d0, 0x0230, + 0x0200, 0x0200, 0x0210, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0030, 0x0010, 0x0010, 0x01d0, 0x0230, + 0x0210, 0x0210, 0x0210, 0x01f8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01e0, 0x0210, + 0x03f0, 0x0200, 0x0200, 0x01f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0070, 0x0080, 0x0080, 0x03f0, 0x0080, + 0x0080, 0x0080, 0x0080, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01d8, 0x0230, + 0x0210, 0x0210, 0x0230, 0x01d0, 0x0010, 0x0010, 0x01e0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0300, 0x0100, 0x0100, 0x0160, 0x0190, + 0x0110, 0x0110, 0x0110, 0x03b8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0040, 0x0000, 0x01c0, 0x0040, + 0x0040, 0x0040, 0x0040, 0x03f8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0040, 0x0000, 0x03e0, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x03c0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0300, 0x0100, 0x0100, 0x0170, 0x0140, + 0x0180, 0x0140, 0x0120, 0x0338, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00c0, 0x0040, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0040, 0x0040, 0x03f8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0690, 0x0368, + 0x0248, 0x0248, 0x0248, 0x0768, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0360, 0x0190, + 0x0110, 0x0110, 0x0110, 0x03b8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01e0, 0x0210, + 0x0210, 0x0210, 0x0210, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000, + + /* ASCII 0x70 ~ 0x7F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0360, 0x0190, + 0x0110, 0x0110, 0x0110, 0x01e0, 0x0100, 0x0100, 0x0380, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01d8, 0x0230, + 0x0210, 0x0210, 0x0230, 0x01d0, 0x0010, 0x0010, 0x0038, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0370, 0x0180, + 0x0100, 0x0100, 0x0100, 0x03e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01f0, 0x0210, + 0x01e0, 0x0010, 0x0210, 0x03e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x03f0, 0x0100, + 0x0100, 0x0100, 0x0110, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0330, 0x0110, + 0x0110, 0x0110, 0x0130, 0x00d8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0738, 0x0210, + 0x0120, 0x0120, 0x00c0, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0718, 0x0208, + 0x0248, 0x02a8, 0x02a8, 0x0110, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0330, 0x0120, + 0x00c0, 0x00c0, 0x0120, 0x0330, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03b8, 0x0110, + 0x0110, 0x00a0, 0x00a0, 0x0040, 0x0040, 0x0080, 0x01c0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01f0, 0x0120, + 0x0040, 0x0080, 0x0110, 0x01f0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0020, 0x0040, 0x0040, 0x0040, 0x0040, + 0x0080, 0x0040, 0x0040, 0x0040, 0x0040, 0x0020, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, + 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0100, 0x0080, 0x0080, 0x0080, 0x0080, + 0x0040, 0x0080, 0x0080, 0x0080, 0x0080, 0x0100, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0190, + 0x0260, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0010, 0x0010, + 0x0320, 0x0120, 0x00c0, 0x0040, 0x0040, 0x0000, 0x0000, 0x0000, +}; + +int width = 12; +int height = 16; + +void draw_font(int x, int y, int ascii) +{ + uint16_t *idx; + int i, j; + + if (ascii < 0 || ascii > (sizeof(drv_lcd_font_table) / sizeof(uint16_t))) + return; + + idx = &drv_lcd_font_table[(ascii - ' ') * 16]; + +// drv_lcd_erase_rect(x, width, y, height); + + for (j = 0; j < height; j++) { + + for (i = 0; i < width; i++) { + + if (*idx & (1 << i)) + drv_lcd_draw_rect(x + width - i , 1, y + j, 1, 0xff, 0, 0xff); + } + + idx++; + } +} diff --git a/bsp/AE210P/driver/lcd/lcd-info.h b/bsp/AE210P/driver/lcd/lcd-info.h new file mode 100644 index 0000000000000000000000000000000000000000..eccaade871e96a83a50efd1a395014d89abd4bf0 --- /dev/null +++ b/bsp/AE210P/driver/lcd/lcd-info.h @@ -0,0 +1,114 @@ +#ifndef __LCD_INFO_H__ +#define __LCD_INFO_H__ + +/* + * HBP : Horizontal Back Porch + * HFP : Horizontal Front Porch + * HSPW: Horizontal Sync. Pulse Width + * PPL : Pixels-per-line = 16(PPL+1) + */ +#define ENC_PARAM_TIME0(HBP, HFP, HSPW, PPL) \ + ((((HBP) - 1) << 24) | \ + (((HFP) - 1) << 16) | \ + (((HSPW) - 1) << 8 ) | \ + ((((PPL) >> 4) - 1) << 2 )) + +/* + * HBP : Vertical Back Porch + * HFP : Vertical Front Porch + * HSPW: Vertical Sync. Pulse Width + * LPP : Lines-per-panel = LPP + 1 + */ +#define ENC_PARAM_TIME1(VBP, VFP, VSPW, LPP) \ + ((((VBP) ) << 24) | \ + (((VFP) ) << 16) | \ + (((VSPW) - 1) << 10) | \ + (((LPP) - 1) )) + +/* + * PRA : Pixel Rate Adaptive + * IOE : Invert Panel Output Enable + * IPC : Invert Panel Clock (Test Chip Testing) + * IHS : Invert Horisontal Sync. + * IVS : Invert Versical Sync. + * PCD : Panel Clock Divisor + */ +#define ENC_PARAM_TIME2(PRA, IOE, IPC, IHS, IVS, PCD) \ + (((PRA) << 15) | \ + ((IOE) << 14) | \ + ((IPC) << 13) | \ + ((IHS) << 12) | \ + ((IVS) << 11) | \ + (((PCD) - 1) )) + +/* + * Enable YCbCr + * Enable YCbCr422 + * FIFO threadhold + * Panel type, 0-6bit, 1-8bit + * LcdVComp, when to generate interrupt, 1: start of back_porch + * Power Enable + * Big Endian Pixel/Byte Ordering + * BGR + * TFT + * LCD bits per pixel + * Controller Enable + */ +#define ENC_PARAM_CTRL(ENYUV, ENYUV422, FIFOTH, PTYPE, VCOMP, LCD_ON, ENDIAN, BGR, TFT, BPP, LCD_EN) \ + ((ENYUV << 18) | \ + (ENYUV422 << 17) | \ + (FIFOTH << 16) | \ + (PTYPE << 15) | \ + (VCOMP << 12) | \ + (LCD_ON << 11) | \ + (ENDIAN << 9) | \ + (BGR << 8) | \ + (TFT << 5) | \ + (BPP << 1) | \ + (LCD_EN)) + +#if defined(CONFIG_COLOR_DEPTH16) +#define LCD_COLOR_DEPTH 0x4 +#define LCD_PANEL_BPP 16 +#elif defined(CONFIG_COLOR_DEPTH24) +#define LCD_COLOR_DEPTH 0x5 +#define LCD_PANEL_BPP 24 +#else +#define LCD_COLOR_DEPTH 0x5 +#define LCD_PANEL_BPP 24 +#endif + +#ifdef CONFIG_PANEL_AUA036QN01 + +#define LCD_PANEL_WIDTH 320 +#define LCD_PANEL_HEIGHT 240 + +#define LCD_TIME0 ENC_PARAM_TIME0(7, 6, 1, 320) /* 0x0605004c */ +#define LCD_TIME1 ENC_PARAM_TIME1(1, 1, 1, 240) /* 0x010100ef */ +#define LCD_TIME2 ENC_PARAM_TIME2(0, 0, 1, 1, 1, 0x7) /* 0x00003806 */ +#define LCD_CTRL ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, LCD_COLOR_DEPTH, 1) /* 0x0001b928 */ + +#endif + +#ifdef CONFIG_PANEL_AUA070VW04 + +#define LCD_PANEL_WIDTH 800 +#define LCD_PANEL_HEIGHT 480 + +#define LCD_TIME0 ENC_PARAM_TIME0(88, 40, 128, 800) +#define LCD_TIME1 ENC_PARAM_TIME1(21, 1, 3, 480) +#define LCD_TIME2 ENC_PARAM_TIME2(0, 1, 1, 1, 1, 0x7) +#define LCD_CTRL ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, LCD_COLOR_DEPTH, 1) + +#endif + +#ifdef CONFIG_PANEL_CH7013A + +#define LCD_TIME0 ENC_PARAM_TIME0(42, 10, 96, 640) +#define LCD_TIME1 ENC_PARAM_TIME1(28, 5, 2, 480) +#define LCD_TIME2 ENC_PARAM_TIME2(0, 1, 1, 0, 0, 0x3) +#define LCD_CTRL ENC_PARAM_CTRL(0, 0, 1, 0, 0x3, 1, 0x0, 1, 1, LCD_COLOR_DEPTH, 1) + +#endif /* CONFIG_CH7013A */ + +#endif /* __LCD_INFO_H__ */ diff --git a/bsp/AE210P/driver/lcd/lcd.c b/bsp/AE210P/driver/lcd/lcd.c new file mode 100644 index 0000000000000000000000000000000000000000..022a2838dd2c4094d7885ae6bcb6ce8940ba683f --- /dev/null +++ b/bsp/AE210P/driver/lcd/lcd.c @@ -0,0 +1,142 @@ +#include "hal.h" +#include "lcd/lcd.h" +#include "lcd-info.h" + +#ifdef CONFIG_PLAT_AG101P_16MB + #define LCD_BASE 0x00e10000 +#else + #define LCD_BASE 0x90600000 +#endif + +#define LCD_TIME0_OFFSET 0x00 +#define LCD_TIME1_OFFSET 0x04 +#define LCD_TIME2_OFFSET 0x08 +#define LCD_BASE_OFFSET 0x10 +#define LCD_INT_EN_OFFSET 0x18 +#define LCD_CTRL_OFFSET 0x1C +#define LCD_INT_CLR_OFFSET 0x20 +#define LCD_INT_MSK_OFFSET 0x24 + +static pixel_t _drv_lcd_fb[ LCD_PANEL_WIDTH * LCD_PANEL_HEIGHT] __attribute__((aligned (64))); +static pixel_t _drv_lcd_bg[ LCD_PANEL_WIDTH * LCD_PANEL_HEIGHT] __attribute__((aligned (64))); + +static pixel_t *drv_lcd_fb = _drv_lcd_fb; +static pixel_t *drv_lcd_bg = _drv_lcd_bg; +extern void nds32_dcache_flush(); + +void drv_lcd_flip(void) +{ + pixel_t *tmp = drv_lcd_fb; + + drv_lcd_fb = drv_lcd_bg; + drv_lcd_bg = tmp; + + OUT32(LCD_BASE + LCD_BASE_OFFSET, drv_lcd_fb); +} + +pixel_t *drv_lcd_get_fb(void) +{ + return drv_lcd_fb; +} + +pixel_t *drv_lcd_get_bg(void) +{ + return drv_lcd_bg; +} + +void drv_lcd_get_param(int *width, int *height, int *bpp) +{ + if (width) + *width = LCD_PANEL_WIDTH; + + if (height) + *height = LCD_PANEL_HEIGHT; + + if (bpp) + *bpp = LCD_PANEL_BPP; +} + +void drv_lcd_fill_bg(void) +{ + pixel_t *base = drv_lcd_bg; + + int i, j; + for (i = j = 0; j < LCD_PANEL_HEIGHT; j++) { + for (i = 0; i < LCD_PANEL_WIDTH; i++) { +#if defined(CONFIG_COLOR_DEPTH16) + if (i == 0 || i == (LCD_PANEL_WIDTH - 1) || j == 0 || j == (LCD_PANEL_HEIGHT - 1)) + *base++ = 0xFFFFu; + else + *base++ = 0x0000u; +#elif defined(CONFIG_COLOR_DEPTH24) + if (i == 0 || i == (LCD_PANEL_WIDTH - 1) || j == 0 || j == (LCD_PANEL_HEIGHT - 1)) + *base++ = 0x00FFFFFFu; + else + *base++ = 0x00000000u; +#else +#error "COLOR DEPTH not supported!" +#endif + } + } +} + +void drv_lcd_draw_bg(void) +{ + pixel_t *src = drv_lcd_bg; + pixel_t *dst = drv_lcd_fb; + + int i = 0; + while (i++ < LCD_PANEL_WIDTH * LCD_PANEL_HEIGHT) + *dst++ = *src++; +} + +static void _drv_lcd_init(void) +{ + OUT32(LCD_BASE + LCD_TIME0_OFFSET, LCD_TIME0); + OUT32(LCD_BASE + LCD_TIME1_OFFSET, LCD_TIME1); + OUT32(LCD_BASE + LCD_TIME2_OFFSET, LCD_TIME2); + OUT32(LCD_BASE + LCD_CTRL_OFFSET, LCD_CTRL); + + OUT32(LCD_BASE + LCD_BASE_OFFSET, drv_lcd_fb); +} + +void drv_lcd_draw_rect(int x, int w, int y, int h, int r, int g, int b) +{ + pixel_t *base = drv_lcd_fb; + + int i, j; + for (i = y; i < y + h; i++) + for (j = x; j < x + w; j++) +#if defined(CONFIG_COLOR_DEPTH16) + base[ i * LCD_PANEL_WIDTH + j] = (pixel_t)(((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0)); +#elif defined(CONFIG_COLOR_DEPTH24) + base[ i * LCD_PANEL_WIDTH + j] = (pixel_t)((r << 16) | (g << 8) | b); +#endif + nds32_dcache_flush(); /* undefine CONFIG_CPU_DCACHE_WRITETHROUGH ,flush DCACHE for lcd screen */ +} + +void drv_lcd_erase_rect(int x, int w, int y, int h) +{ + pixel_t *base = drv_lcd_fb; + + int i, j; + for (i = y; i < y + h; i++) + for (j = x; j < x + w; j++) + base[ i * LCD_PANEL_WIDTH + j] = drv_lcd_bg[ i * LCD_PANEL_WIDTH + j]; +} + +void draw_blk(int x, int y, int sz, int border, int r, int g, int b) +{ + drv_lcd_draw_rect(x, sz, y, sz, r, g, b); + drv_lcd_draw_rect(x + border, sz - 2 * border, y + border, sz - 2 * border, r ^ 0xff, g ^ 0xff, b ^ 0xff); +} + +int drv_lcd_init(void) +{ + _drv_lcd_init(); + drv_lcd_fill_bg(); + drv_lcd_draw_bg(); + drv_lcd_flip(); + + return 0; +} diff --git a/bsp/AE210P/driver/lcd/lcd.h b/bsp/AE210P/driver/lcd/lcd.h new file mode 100644 index 0000000000000000000000000000000000000000..31b997269b266892dfc688689489b532223e893a --- /dev/null +++ b/bsp/AE210P/driver/lcd/lcd.h @@ -0,0 +1,29 @@ +#ifndef __LCD_H__ +#define __LCD_H__ + +#include +#include "lcd-info.h" + +#if defined(CONFIG_COLOR_DEPTH16) + typedef uint16_t pixel_t; +#elif defined(CONFIG_COLOR_DEPTH24) + typedef uint32_t pixel_t; +#else + #error "Unsupported COLOR_DEPTH!" + typedef int pixel_t; +#endif + +extern void drv_lcd_flip(void); +extern pixel_t *drv_lcd_get_fb(void); +extern pixel_t *drv_lcd_get_bg(void); +extern void drv_lcd_get_param(int *width, int *height, int *bpp); +extern void drv_lcd_fill_bg(void); +extern void drv_lcd_draw_bg(void); +extern void drv_lcd_draw_rect(int x, int w, int y, int h, int r, int g, int b); +extern void drv_lcd_erase_rect(int x, int w, int y, int h); +extern void draw_blk(int x, int y, int sz, int border, int r, int g, int b); +extern int drv_lcd_init(void); + +extern void draw_font(int x, int y, int ascii); + +#endif /* __LCD_H__ */ diff --git a/bsp/AE210P/driver/osc/osc.c b/bsp/AE210P/driver/osc/osc.c new file mode 100644 index 0000000000000000000000000000000000000000..91316ea889cfeb0e6572e1f06449ef69985b0583 --- /dev/null +++ b/bsp/AE210P/driver/osc/osc.c @@ -0,0 +1,74 @@ +#include "hal.h" +#include "uart/uart.h" +#include "osc.h" +#include "os_except.h" + +#define osc_hisr_TASK_PRIORITY 31 // osc_hisr must be the highest priority task of all tasks. + +/* + ********************************************************************************************************* + * Overlay SRAM Controller (OSC) initialize + * + * Description : This function is called to initialize overlay SRAM controller, + * including setting upfixed region size and overlay region base. + * + * Arguments : + * + * Notes : + ********************************************************************************************************* + */ +void _osc_init(void) +{ + register unsigned int ovly_region_szie; + register unsigned int fix_regiion_size; + register unsigned int ovly_region_base_addr; + + /* Read the initial OSC overlay region size. */ + ovly_region_szie = (REG32(OSC_CTRL) & OSC_CTRL_OVL_SZ_MASK) >> 12; + + /* Initialize OSC fix region size */ + fix_regiion_size = OSC_EILM_SIZE - ovly_region_szie; + REG32(OSC_OVLFS) = fix_regiion_size; + + /* Initialize OSC overlay region to the end of all overlay text. */ + ovly_region_base_addr = fix_regiion_size + ovly_region_szie * _novlys; + REG32(OSC_OVLBASE) = ovly_region_base_addr; +} + +int _osc_drv_init(void (*handler)(unsigned int ipc), + void (*osc_hisr)(void *arg), + OSC_DRV_INFO *osc_info) +{ + hal_queue_t *queue = &osc_info->queue; + hal_thread_t *th = &osc_info->th; + + // Initial the Fixed/Overlap regions. + _osc_init(); + + // Register a user-define handler which is called from OSC exception handler. + register_exception_handler(GE_RESERVED_INST, handler); + + // Register a user-define hisr which will be woken up by lisr sending msg to queue. + th->fn = osc_hisr; + th->name = "bh_osc"; + th->stack_size = 0x400; + th->arg = queue; + th->prio = osc_hisr_TASK_PRIORITY; + th->task = NULL; + th->ptos = NULL; + + // Create a bottom half. + // The bottom half is a thread task with a sync queue. + queue->size = 1; + + if(hal_create_queue(queue) == HAL_FAILURE) + return HAL_FAILURE; + + if(hal_create_thread(th) != HAL_SUCCESS) + return HAL_FAILURE; + + puts("OSC driver init success!\n"); + + return HAL_SUCCESS; +} + diff --git a/bsp/AE210P/driver/osc/osc.h b/bsp/AE210P/driver/osc/osc.h new file mode 100644 index 0000000000000000000000000000000000000000..898b392f9d05a509814dd0beed3c0ab0a1713304 --- /dev/null +++ b/bsp/AE210P/driver/osc/osc.h @@ -0,0 +1,77 @@ +#ifndef __OSC_H__ +#define __OSC_H__ + +#include "hal.h" + +#define OVLY_SEG(NAME) __attribute__((section(#NAME))) + +/* + TYPES OF GENERAL EXCEPTION +*/ +#define GE_ALIGN_CHECK 0 +#define GE_RESERVED_INST 1 +#define GE_TRAP 2 +#define GE_ARITHMETIC 3 +#define GE_PRECISE_BUS_ERR 4 +#define GE_INPRECISE_BUS_ERR 5 +#define GE_COPROCESSOR 6 +#define GE_PRIVILEGE_INST 7 +#define GE_RESERVED_VALUE 8 +#define GE_NON_EXIST_LOCAL_MEM 9 +#define GE_MPZIU_CTRL 10 + +/* + structure of overlay control registers + Please define this structure based on your hardware design +*/ +typedef struct +{ + unsigned int reserved ; + unsigned int root_size ; + unsigned int base_addr ; + unsigned int end_addr ; + volatile unsigned int dma ; +} OVLY_REGS ; + +typedef struct +{ + unsigned long vma; + unsigned long size; + unsigned long lma; + unsigned long mapped; +} OVLY_TABLE ; + +typedef struct +{ + unsigned int ipc; + OVLY_REGS *povl; + +} OVL_CTRL; + +typedef struct { + + hal_queue_t queue; + hal_thread_t th; + + OVL_CTRL povl_ctrl; + +} OSC_DRV_INFO; + +/* _novlys from overlay table in linker script stands for number of overlay regions. */ +extern int _novlys; +extern OVLY_TABLE _ovly_table[] ; +extern char __ovly_lmastart_OVL_RAM; + +static volatile int overlay_busy = 0; + +void __attribute__((no_prologue)) osc_init(); +int _osc_drv_init(void (*handler)(unsigned int ipc), + void (*osc_hisr)(void *arg), + OSC_DRV_INFO *osc_info); + +#ifdef CONFIG_OSC_DEBUG_SUPPORT +#define OVLY_DEBUG +#endif + + +#endif diff --git a/bsp/AE210P/driver/sd/Kbuild b/bsp/AE210P/driver/sd/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..2744f13dd1b7266364215f80313842ad3b639787 --- /dev/null +++ b/bsp/AE210P/driver/sd/Kbuild @@ -0,0 +1,3 @@ +lib-y += +lib-y += sdd.o +lib-y += sdd_sd.o diff --git a/bsp/AE210P/driver/sd/sd.h b/bsp/AE210P/driver/sd/sd.h new file mode 100644 index 0000000000000000000000000000000000000000..3c7d9dc592a83135ecc82d15048cc3141c79acbd --- /dev/null +++ b/bsp/AE210P/driver/sd/sd.h @@ -0,0 +1,143 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Aug.21.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sd.h + * + * DESCRIPTION + * + * SD controller driver interfaces for client applications. + * (Nucleus I/O Driver Architecture) + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * ag101regs.h + * ag101defs.h + * + ****************************************************************************/ +#ifndef __SD_H__ +#define __SD_H__ + +#include +/* + * SDD I/O control code, used for clients not using driver wrapper routines, + * i.e., when not using middle-ware interfaces. Driver implementation target + * is that almost every IOCTL should exist a corresponding wrapper routine. + */ +typedef enum SDD_IOCTL { + SDD_IOCTL_READ_SECTORS, /* Parameter: pointer to SDD_IOCTL_READ_SECTORS_PARAM struct */ + SDD_IOCTL_WRITE_SECTORS, /* Parameter: pointer to SDD_IOCTL_WRITE_SECTORS_PARAM struct */ +} SDD_IOCTL; + +/* Parameter struct for SDD_IOCTL_ */ +typedef struct _SDD_IOCTL_READ_SECTORS_PARAM { + + uint32_t lba_sector; /* start sector number */ + uint32_t sector_count; /* number of sectors included in this operation */ + uint32_t sector_size; /* sector size in bytes */ + void *io_buff; /* buffer pointer */ + +} SDD_IOCTL_READ_SECTORS_PARAM; + +typedef struct _SDD_IOCTL_WRITE_SECTORS_PARAM { + + uint32_t lba_sector; /* start sector number */ + uint32_t sector_count; /* number of sectors included in this operation */ + uint32_t sector_size; /* sector size in bytes */ + void *io_buff; /* buffer pointer */ + +} SDD_IOCTL_WRITE_SECTORS_PARAM; + +typedef enum SDD_EVENTS { + + SDD_EVENT_CD = 0x00000001, /* Card-detection event. Event parameter: SDD_CD_EVENT */ + +} SDD_EVENTS; + +typedef enum SDD_CD_EVENT_PARAM { + SDD_CD_CARD_INSERTED = 1, + SDD_CD_CARD_REMOVED = 0, + +} SDD_CD_EVENT_PARAM; + +typedef enum SDD_DMA_MODE { + SDD_DMA_NONE = 0, /* no dma, deivce i/o is through pio */ + SDD_DMA_DCH = 1, /* dma channel is dynamically allocated on i/o request and get free after dma. */ + SDD_DMA_SCH = 2, /* dma channel is allocated and occupied during device initialization. */ + +} SDD_DMA_MODE; + +/* Define data structures for management of CF device. */ +typedef struct SDD_DEVICE_STRUCT { + + void *bdev_id; /* (reserved) The block device context. This field is reserved by the driver. */ + uint8_t dma; /* (in) one of the enum value in SDD_DMA_MODE. */ + uint8_t func; /* (in) (Reserved currently) Preferred SD card function mode (SD Memory, SD/IO, SPI) */ + uint8_t padding[2]; /* stuff bytes */ + +} SDD_DEVICE; + +/***************************************************************************** + * Note: Everything below is designed as an interface wrapper to access + * SD driver. + * + * [Structures] + * + * [Functions] + * + * + ****************************************************************************/ + +/* driver generic error code for SDC */ +#define SDD_SUCCESS 0x00 +#define SDD_INVALID_INIT 0x01 +#define SDD_INVALID_REQUEST 0x02 +#define SDD_NOT_SUPPORTED 0x03 + +#define SDD_INVALID_FUNCTION 0x11 +#define SDD_INVALID_PARAMETER 0x12 +#define SDD_CARD_REMOVED 0x13 +#define SDD_INVALID_MEDIA 0x14 +#define SDD_INVALID_IOCTL 0x15 +#define SDD_WRITE_DATA_ERROR 0x16 +#define SDD_READ_DATA_ERROR 0x17 +#define SDD_INVLAID_ADDRESS 0x18 +#define SDD_INVLAID_ADDR_RANGE 0x19 + +#define SDD_CMD_TIMEOUT 0x21 +#define SDD_CMD_ERROR 0x22 +#define SDD_RSP_TIMEOUT 0x23 +#define SDD_RSP_CRC_ERROR 0x24 +#define SDD_NOT_SUPPORT_ACMD 0x25 +#define SDD_CSR_ERROR 0x26 +#define SDD_INVALID_STATE 0x27 +#define SDD_WAIT_TIMEOUT 0x28 +#define SDD_WRITE_PROTECTED 0x29 +#define SDD_CARD_LOCKED 0x30 + +extern void _sdd_lisr(int vector); +extern void _sdd_hisr(void *param); +extern uint32_t NDS_SD_Init(SDD_DEVICE * sdd_dev); +extern void NDS_SD_Unload(void); +extern uint32_t NDS_SD_ReadSectors(SDD_DEVICE * sdd_dev, uint32_t sector, + uint32_t sector_count, uint32_t sector_size, + void *buffer); +extern uint32_t NDS_SD_WriteSectors(SDD_DEVICE * sdd_dev, uint32_t sector, + uint32_t sector_count, uint32_t sector_size, + void *buffer); + +#endif /* __SD_H__ */ diff --git a/bsp/AE210P/driver/sd/sdd.c b/bsp/AE210P/driver/sd/sdd.c new file mode 100644 index 0000000000000000000000000000000000000000..04239dca76d9faed6af1edecc95892bce16f43a7 --- /dev/null +++ b/bsp/AE210P/driver/sd/sdd.c @@ -0,0 +1,2951 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Aug.21.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sdd.c + * + * DESCRIPTION + * + * SD driver implementation. (Nucleus I/O Driver Architecture) + * + * SDC CONTROL LOGIC + * + * ------------------------------------------------------------------------- + * SDC controls <-> SDC Registers <-> SD In-Card Controller + * ------------------------------------------------------------------------- + * SD commands <-> SDC CMD/RSP reg <-> SD Command/Data Line + * ------------------------------------------------------------------------- + * SD data <-> SDC Data Window <-> SD Memory + * ------------------------------------------------------------------------- + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * sdd.h SD driver common header file + * + ****************************************************************************/ +#include "sdd.h" +#include "sdd_sd.h" +#include "../../library/ndsvfs/sys_arch.h" +#include "../../library/ndsvfs/include/ndsbdev.h" +#include "bsp_hal.h" + +static uint32_t sdd_hisr_stack[SDD_HISR_STACK_SIZE]; +/* driver context */ +static SDD_DATA sdd __attribute__ ((aligned(4))) = { 0}; +#if (SDD_VFS_SUPPORT) +// sdc block device context +static NDS_BDEV sdd_bdev __attribute__((aligned(4))) = {0}; +#endif // SDD_VFS_SUPPORT + +/***************************************************************************** + * FUNCTION + * + * _sdd_alloc_dma_channel + * + * DESCRIPTION + * + * + * This function allocate a dma channel for use of sd data transfer. + * + * NOTE + * + * + * INPUTS + * + * None + * + * OUTPUTS + * + * None + * + ****************************************************************************/ +static inline uint32_t _sdd_alloc_dma_channel(void) +{ + uint32_t status = HAL_SUCCESS; + + /* + * This is function is for code path simplification so it will not + * check validity of sdd struct again. + */ + + /* Try APB DMA first ... */ + + /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */ + sdd.dma_ch.controller = DMAD_DMAC_APB_CORE; + + /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */ + sdd.dma_ch.apbch_req.burst_mode = 0; + + /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */ + sdd.dma_ch.apbch_req.data_width = APBBR_DATAWIDTH_4; + + /* (in) APBBR_ADDRINC_xxx */ + sdd.dma_ch.apbch_req.src_addr_ctrl = APBBR_ADDRINC_FIXED; + + /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */ + sdd.dma_ch.apbch_req.src_index = _dmad_get_reqn(sdd.dma_ch.controller, APB_SDC); + + /* (in) APBBR_ADDRINC_xxx */ + sdd.dma_ch.apbch_req.dst_addr_ctrl = APBBR_ADDRINC_I4X; + + /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */ + sdd.dma_ch.apbch_req.dst_index = APBBR_REQN_NONE; + + status = _dmad_channel_alloc(&sdd.dma_ch, HAL_TRUE); + + if (status != HAL_SUCCESS) { + + if (status != HAL_ERR_UNAVAILABLE) + return status; + + /* Try AHB DMAC again for lucky ... */ + /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */ + sdd.dma_ch.controller = DMAD_DMAC_AHB_CORE; + + /* (in) non-zero if src and dst have different clock domain */ + sdd.dma_ch.ahbch_req.sync = 1; + + /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */ + sdd.dma_ch.ahbch_req.priority = DMAC_CSR_CHPRI_0; + + /* (in) non-zero to enable hardware handshake mode */ + sdd.dma_ch.ahbch_req.hw_handshake = 1; + + /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */ + sdd.dma_ch.ahbch_req.burst_size = DMAC_CSR_SIZE_1; + + /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */ + sdd.dma_ch.ahbch_req.src_width = DMAC_CSR_WIDTH_32; + + /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */ + sdd.dma_ch.ahbch_req.src_addr_ctrl = DMAC_CSR_AD_FIX; + + /* (in) DMAC_REQN_xxx (also used to help determine channel number) */ + sdd.dma_ch.ahbch_req.src_index = DMAC_REQN_SDC; + + sdd.dma_ch.ahbch_req.src_reqn = _dmad_get_reqn(sdd.dma_ch.controller, AHB_SDC); + + /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */ + sdd.dma_ch.ahbch_req.dst_width = DMAC_CSR_WIDTH_32; + + /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */ + sdd.dma_ch.ahbch_req.dst_addr_ctrl = DMAC_CSR_AD_INC; + + /* (in) DMAC_REQN_xxx (also used to help determine channel number) */ + sdd.dma_ch.ahbch_req.dst_index = DMAC_REQN_NONE; + sdd.dma_ch.ahbch_req.dst_reqn = AHB_REQN_NONE; + + status = _dmad_channel_alloc(&sdd.dma_ch, HAL_TRUE); + } + + SDD_TRACE(("sdd dma channel(%d) controller(%d)\r\n", + sdd.dma_ch.channel, sdd.dma_ch.controller)); + + return status; +} + +static inline void _sdd_free_dma_channel(void) +{ + _dmad_channel_free(&sdd.dma_ch); +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_cd_reset + * + * DESCRIPTION + * + * This function performs card-detection initialization and card remove + * clean-up tasks. + * + * NOTE + * + * + * INPUTS + * + * insert : non-zero to perform card-inserting tasks, zero for removing. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_cd_reset(uint8_t insert) +{ + uint32_t status = HAL_SUCCESS; /* Return status code */ + SD_R32 sd_rsp32; /* SD card command response 32-bit */ + SD_R128 sd_rsp128; /* SD card command response 128-bit */ + char *tmp_str; + uint32_t tmp_val; + + SDD_TRACE(("_sdd_cd_reset\r\n")); + /* ------------ */ + /* Reset host SDC */ + SETB32(SDC_CMD, SDC_SDC_RST_BIT); + while (GETB32(SDC_CMD, SDC_SDC_RST_BIT) != 0) ; + + /* Perform card removal tasks */ + if (insert != HAL_TRUE) { + /* Stop pending DMA ? */ + + /* Turn off SD bus power */ + CLRB32(SDC_PWR_CTL, SDC_SD_POWER_ON_BIT); + + /* Turn off SD bus clock */ + SETB32(SDC_CLK_CTL, SDC_CLK_DIS_BIT); + + /* Setup removed flag */ + sdd.card_desc.rca = 0; + +#if (SDD_VFS_SUPPORT) + // notify file system layer, if any ... + if (sdd_bdev.propagate_event != HAL_NULL) + sdd_bdev.propagate_event(&sdd_bdev, NDSBDEV_DEVICE_UNPLUG, HAL_NULL); +#endif // SDD_VFS_SUPPORT + return HAL_SUCCESS; + } + + /* ------------ */ + /* Turn on SD card power using default voltage level */ + SETB32(SDC_PWR_CTL, SDC_SD_POWER_ON_BIT); + _nds_kwait(0x1000); + + /* ------------ */ + /* Turn on SD bus clock, apply max freq-division value (smallest frequency) */ + OUT32(SDC_CLK_CTL, (SDC_CLK_ON << SDC_CLK_DIS_BIT) | + (SDC_CLK_SD << SDC_CLK_SD_BIT) | SDC_CLK_DIV_MASK); + + _nds_kwait(0x1000); + + SDD_TRACE(("power-on & clock-on!\r\n")); + + /* Perform card initialization & identification process */ + + /* Idle State -> Ready State */ + /* - CMD0 */ + SDD_TRACE(("CMD0\r\n")); + status = _sd_cmd0(); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* - CMD8 */ + SDD_TRACE(("CMD8\r\n")); + status = _sd_cmd8(SD_CMD8_MAKE_ARG(SD_VHS_2_7V_3_6V, SD_CMD8_DEFAULT_PTN), &sd_rsp32); + + if (status != HAL_SUCCESS) { + + if ((status != SDD_RSP_TIMEOUT) && (status != SDD_CMD_TIMEOUT)) + goto _err_exit; + + sdd.card_desc.version = SDD_SPEC_1XX; + } + else { + /* version 2.0 or later card */ + + /* validates CMD8 response */ + if ((SD_R7_GET_PTN(sd_rsp32) != 0xaa) || (SD_R7_GET_VHS(sd_rsp32) == 0x00)) { + + /* unusable card */ + status = SDD_INVALID_MEDIA; + goto _err_exit; + } + + sdd.card_desc.version = SDD_SPEC_200; + } + + /* - ACMD41 */ + SDD_TRACE(("ACMD41\r\n")); + { + uint32_t retry = 0; + uint32_t timeout = 1; + uint32_t sd_hcs = SD_HCS_SD; /* SD(0) or SDHC(1) for ACMD41 */ + + /* + * HCS should be 0 if CMD8 does not response. + * HCS is 1 if host supports SDHC (AG101 does not support SDHC). + */ + + if (sdd.card_desc.version == SDD_SPEC_200) + { + sd_hcs = SD_HCS_SDHC; + } + + /* issue ACMD41 to get OCR */ + while (retry++ < SD_ACMD41_MAX_RETRY_COUNT) { + + /* cases: */ + /* - v2.0 or latter SD memory card - voltage mismatch */ + /* - v1.x SD memory card */ + /* - not SD memory card */ + SDD_TRACE(("cmd55\r\n")); + + /* notify card we're going to send an ACMD, RCA is 0x00 in card's idle state */ + status = _sd_cmd55(0x00, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + if (SD_CSR_GET_APP_CMD(sd_rsp32) == 0) { + + /* error if card was not expecting ACMD */ + status = SDD_NOT_SUPPORT_ACMD; + goto _err_exit; + } + + SDD_TRACE(("acmd41\r\n")); + status = _sd_acmd41(SD_ACMD41_MAKE_ARG(sd_hcs), &sd_rsp32); + if (status != HAL_SUCCESS) { + + /* no response - not a SD memory card */ + goto _err_exit; + } + + /* Continue if the OCR power state is not ready yet */ + if (SD_OCR_GET_BUSY(sd_rsp32) == 1) { + + /* card power up status is ready */ + sdd.card_desc.card_ccs = + ((SD_OCR_GET_CCS(sd_rsp32) == SD_CCS_SDHC) ? SDD_CCS_SDHC : SDD_CCS_SD); + + sdd.card_desc.vdd_window = SD_OCR_GET_VDD(sd_rsp32); + + timeout = 0; + break; + } + } + + if (timeout) { + + /* + * unusable card + * - no compatible voltage range (go to inactive state) + * - timeout (no resposne or timeout) + */ + SDD_TRACE(("timeout!\r\n")); + status = SDD_INVALID_MEDIA; + goto _err_exit; + } + } + + /* Ready State -> Identification State */ + /* - CMD2 */ + SDD_TRACE(("CMD2\r\n")); + status = _sd_cmd2(&sd_rsp128); + if (status != HAL_SUCCESS) + goto _err_exit; + + sdd.card_desc.mfg_id = SD_CID_GET_MID(sd_rsp128); /* ID */ + + tmp_str = (char *)SD_CID_GET_OID_PTR(sd_rsp128); /* string */ + sdd.card_desc.oem_id[0] = tmp_str[0]; + sdd.card_desc.oem_id[1] = tmp_str[1]; + sdd.card_desc.oem_id[2] = 0x00; + + tmp_str = (char *)SD_CID_GET_PNM_PTR(sd_rsp128); /* string */ + sdd.card_desc.prod_name[0] = tmp_str[0]; + sdd.card_desc.prod_name[1] = tmp_str[1]; + sdd.card_desc.prod_name[2] = tmp_str[2]; + sdd.card_desc.prod_name[3] = tmp_str[3]; + sdd.card_desc.prod_name[4] = tmp_str[4]; + sdd.card_desc.prod_name[5] = 0x00; + + tmp_val = (uint32_t) SD_CID_GET_PRV(sd_rsp128); /* BCD */ + sdd.card_desc.prod_rev[0] = (char)((tmp_val >> 4) + 0x30); + sdd.card_desc.prod_rev[1] = (char)'.'; + sdd.card_desc.prod_rev[2] = (char)((tmp_val & 0x0f) + 0x30); + sdd.card_desc.prod_rev[3] = 0x00; + + sdd.card_desc.prod_sn = (uint32_t) SD_CID_GET_PSN(sd_rsp128); /* 32-bit word value */ + + tmp_val = (uint32_t) SD_CID_GET_MDT(sd_rsp128); /* 12-bit value */ + sdd.card_desc.mfg_year = (uint16_t) (tmp_val >> 4) + 2000; + sdd.card_desc.mfg_month = (uint16_t) (tmp_val & 0x0f); + + SDD_TRACE(("oem_id : 0x%081x\r\n", sdd.card_desc.oem_id)); + + SDD_TRACE(("prod_name : %s\r\n", sdd.card_desc.prod_name)); + + SDD_TRACE(("prod_rev : 0x%081x\r\n",sdd.card_desc.prod_rev)); + + SDD_TRACE(("prod_sn : 0x%08lx\r\n", sdd.card_desc.prod_sn)); + SDD_TRACE(("mfg_year : %d\r\n", sdd.card_desc.mfg_year)); + SDD_TRACE(("mfg_month : %d\r\n", sdd.card_desc.mfg_month)); + + /* Identification -> Standby State */ + + /* - CMD3 */ + SDD_TRACE(("CMD3\r\n")); + status = _sd_cmd3(&sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + if (SD_R6_GET_CSR_ERR(sd_rsp32)) { + + status = SDD_CMD_ERROR; + goto _err_exit; + } + + sdd.card_desc.rca = SD_R6_GET_RCA(sd_rsp32); + SDD_TRACE(("New RCA: 0x%08lx\r\n", sdd.card_desc.rca)); + + /* + * Get CSD register (Standby -> Standby) + * (Majorly we need the data access timing and SD bus clock) + */ + + /* - CMD9 */ + SDD_TRACE(("Get CSD (CMD9)\r\n")); + status = _sd_cmd9(sdd.card_desc.rca, &sd_rsp128); + if (status != HAL_SUCCESS) + goto _err_exit; + + tmp_val = SD_CSD_GET_CSD_STRUCTURE(sd_rsp128); + + SDD_TRACE(("CSD r0: 0x%08lx\r\n", sd_rsp128.r[0])); + SDD_TRACE(("CSD r1: 0x%08lx\r\n", sd_rsp128.r[1])); + SDD_TRACE(("CSD r2: 0x%08lx\r\n", sd_rsp128.r[2])); + SDD_TRACE(("CSD r3: 0x%08lx\r\n", sd_rsp128.r[3])); + + { + static uint32_t taac_tu2ns[] = { + /* + * Note: Due to minimum is 1, taac did not divided by 10 initially. + * Values derived from this taac has to be divided by 10. + */ + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 + }; + + static uint32_t ts_tu2bps[] = { + /* + * Note: Reserved index (4~7) will map to 0, + * others are divided by 10 to avoid floating point operation. + */ + 1000, 100000, 1000000, 10000000, 0, 0, 0, 0 + }; + + static uint32_t taac_ts_tv2flt[] = { + /* + * Note: Reserved index (0) will map to 0, + * other value are multiplied with 10 to avoid floating point operation. + */ + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, + 70, 80 + }; + + if (tmp_val == 0x00) { + + /* Standard SD */ + float sdc_clk_ns; /* SDC to card bus clock */ + float sdc_read_to_ns, sdc_write_to_ns; /* read/write timeout (ns) */ + + SDD_TRACE(("CSD v1.0\r\n")); + SDD_TRACE(("taac : 0x%08lx\r\n", SD_CSD_GET_TAAC(sd_rsp128))); + SDD_TRACE(("nsac : 0x%08lx\r\n", SD_CSD_GET_NSAC(sd_rsp128))); + + /* CSD structure version */ + sdd.card_desc.csd_ver = 0x01; + + /* obtain card maximum transfer speed (bps) */ + tmp_val = SD_CSD_GET_TRAN_SPEED(sd_rsp128); + + sdd.card_desc.max_dataline_rate = + (taac_ts_tv2flt[SD_TRAN_SPEED_TV(tmp_val)] * + ts_tu2bps[SD_TRAN_SPEED_TU(tmp_val)]); + + SDD_TRACE(("line_speed : 0x%08lx (bps)\r\n", sdd.card_desc.max_dataline_rate)); + + /* AG101 SDC transfer speed limits */ + + // if (sdd.card_desc.max_dataline_rate > 25000000) + // sdd.card_desc.max_dataline_rate = 25000000; + + /* + * assume we would like to reach the maximum transfer speed, + * backward derive SDC_CLK_DIC ... + */ + sdd.card_desc.sdc_clk_div = + MB_PCLK / (sdd.card_desc.max_dataline_rate << 1); + if (sdd.card_desc.sdc_clk_div > 0) + sdd.card_desc.sdc_clk_div -= 1; + + /* obtain real SDC clock frequency */ + sdd.card_desc.sdc_clk_freq = + MB_PCLK / ((sdd.card_desc.sdc_clk_div + 1) << 1); + + /* + * obtain card read access time 1 (TAAC, ns) + * note that this is 10x value, use of taac has to be divide by 10. + */ + tmp_val = SD_CSD_GET_TAAC(sd_rsp128); + + sdd.card_desc.async_access_time = + taac_ts_tv2flt[SD_TAAC_TV(tmp_val)] * + taac_tu2ns[SD_TAAC_TU(tmp_val)]; + + /* obtain card read access time 2 (NSAC * 100, clocks) */ + sdd.card_desc.read_access_clks = SD_CSD_GET_NSAC(sd_rsp128) * 100; /* (NSAC * 100) Hz */ + + /* obtain programming time multiplication factor */ + sdd.card_desc.prog_factor = (1 << SD_CSD_GET_R2W_FACTOR(sd_rsp128)); + + /* obtain total read (TAAC + NSAC) & write (R2W * read) access timeout (x100) */ + sdc_clk_ns = 1000000000.0f / (float)sdd.card_desc.sdc_clk_freq; /* SDC clock period (ns) */ + sdc_read_to_ns = + (float)sdd.card_desc.read_access_clks * sdc_clk_ns * 100.0f + + (float)sdd.card_desc.async_access_time * 10.0f; + + sdc_write_to_ns = (float)sdd.card_desc.prog_factor * sdc_read_to_ns; + + /* obtain read and write timeout value */ + /* read_timeout = min(100ms, 100 x read_access_time_ms) */ + if (sdc_read_to_ns > 100000000.0f) + sdc_read_to_ns = 100000000.0f; + + sdd.card_desc.read_timeout_clks = (uint32_t) (sdc_read_to_ns / sdc_clk_ns); + + /* write_timeout = min(100ms, 100 x write_access_time_ms) */ + if (sdc_write_to_ns > 100000000.0f) + sdc_write_to_ns = 100000000.0f; + + sdd.card_desc.write_timeout_clks = (uint32_t) (sdc_write_to_ns / sdc_clk_ns); + + /* command class support list */ + sdd.card_desc.cmd_class = SD_CSD_GET_CCC(sd_rsp128); + + /* read parameters */ + + /* should be 512, 1024, or 2048 */ + sdd.card_desc.max_read_block_len = (uint16_t) (1 << SD_CSD_GET_READ_BL_LEN(sd_rsp128)); + + /* should be 1 for SD memory card */ + sdd.card_desc.partial_block_read = (uint8_t) SD_CSD_GET_READ_BL_PARTIAL(sd_rsp128); + sdd.card_desc.read_block_misalign = (uint8_t) SD_CSD_GET_READ_BLK_MISALIGN(sd_rsp128); /* 0 or 1 */ + + /* write parameters */ + sdd.card_desc.max_write_block_len = (uint16_t) (1 << SD_CSD_GET_WRITE_BL_LEN(sd_rsp128)); /* should be same as read-block size in SD memory card */ + sdd.card_desc.partial_block_write = (uint8_t) SD_CSD_GET_WRITE_BL_PARTIAL(sd_rsp128); /* 0 or 1 */ + sdd.card_desc.write_block_misalign = (uint8_t) SD_CSD_GET_WRITE_BLK_MISALIGN(sd_rsp128); /* 0 or 1 */ + + /* erase parameters */ + sdd.card_desc.erase_single_block = (uint8_t) SD_CSD_GET_ERASE_BLK_EN(sd_rsp128); /* 0 or 1 */ + sdd.card_desc.erase_sector_size = (uint8_t) SD_CSD_GET_SECTOR_SIZE(sd_rsp128); /* 0~127 means 1~128 number of write block size */ + sdd.card_desc.file_format = (uint8_t) SD_CSD_GET_FILE_FORMAT(sd_rsp128); + + /* write protect parameters */ + sdd.card_desc.wp_group_size = (uint8_t) SD_CSD_GET_WP_GRP_SIZE(sd_rsp128); /* 0~127 means 1~128 number of erase sector size */ + sdd.card_desc.wp_group_enable = (uint8_t) SD_CSD_GET_WP_GRP_ENABLE(sd_rsp128); /* 0 or 1 */ + sdd.card_desc.wp_permanent = (uint8_t) SD_CSD_GET_PERM_WRITE_PROTECT(sd_rsp128); /* 0 or 1 */ + sdd.card_desc.wp_temp = (uint8_t) SD_CSD_GET_TMP_WRITE_PROTECT(sd_rsp128); /* 0 or 1 */ + + /* other parameters */ + sdd.card_desc.copy = (uint8_t) SD_CSD_GET_COPY(sd_rsp128); /* 0 or 1 */ + sdd.card_desc.dsr_imp = (uint8_t) SD_CSD_GET_DSR_IMP(sd_rsp128); /* 0 or 1 */ + + /* card capacity parameters */ + sdd.card_desc.c_size = (uint32_t) SD_CSD1_GET_C_SIZE(sd_rsp128); /* 12-bit value */ + sdd.card_desc.c_size_mult = (uint32_t) SD_CSD1_GET_C_SIZE_MULT(sd_rsp128); /* 3-bit value */ + + /* calculate card capacity of user data (unit of 512-bytes) */ + sdd.card_desc.card_capacity = + ((sdd.card_desc.c_size + + 1) * (1 << (sdd.card_desc.c_size_mult + 2))) >> 9; + sdd.card_desc.card_capacity *= + sdd.card_desc.max_read_block_len; + } + else if (tmp_val == 0x01) { + /* SDHC (or Standard SD with CSD 2.0?) */ + /*static uint32_t soc_pclk = 50000000; // (assume PCLK 50M) todo: fix it! */ + float sdc_clk_ns; + + SDD_TRACE(("CSD v2.0\r\n")); + SDD_TRACE(("taac(r/o) : 0x%08lx\r\n", + SD_CSD_GET_TAAC(sd_rsp128))); + SDD_TRACE(("nsac(r/o) : 0x%08lx\r\n", + SD_CSD_GET_NSAC(sd_rsp128))); + + /* CSD structure version */ + sdd.card_desc.csd_ver = 0x02; + + /* obtain card maximum transfer speed (bps) */ + tmp_val = SD_CSD_GET_TRAN_SPEED(sd_rsp128); /* same as 1.0 */ + sdd.card_desc.max_dataline_rate = + (taac_ts_tv2flt[SD_TRAN_SPEED_TV(tmp_val)] * + ts_tu2bps[SD_TRAN_SPEED_TU(tmp_val)]); + SDD_TRACE(("line_speed : 0x%08lx (bps)\r\n", + sdd.card_desc.max_dataline_rate)); + + /* AG101 SDC transfer speed limits */ + // if (sdd.card_desc.max_dataline_rate > 25000000) + // sdd.card_desc.max_dataline_rate = 25000000; + + /* + * assume we would like to reach the maximum transfer speed, + * backward derive SDC_CLK_DIC ... + */ + sdd.card_desc.sdc_clk_div = + MB_PCLK / (sdd.card_desc.max_dataline_rate << 1); + if (sdd.card_desc.sdc_clk_div > 0) + sdd.card_desc.sdc_clk_div -= 1; + + /* obtain real SDC clock frequency */ + sdd.card_desc.sdc_clk_freq = + MB_PCLK / ((sdd.card_desc.sdc_clk_div + 1) << 1); + + /* obtain card read access time 1 (TAAC, ns) */ + /* note that this is 10x value, use of taac has to be divide by 10. */ + + // tmp_val = SD_CSD_GET_TAAC(sd_rsp128); + // sdd.card_desc.async_access_time = + // taac_ts_tv2flt[SD_TAAC_TV(tmp_val)] * taac_tu2ns[SD_TAAC_TU(tmp_val)]; + + /* obtain card read access time 2 (NSAC * 100, clocks) */ + // sdd.card_desc.read_access_clks = SD_CSD_GET_NSAC(sd_rsp128) * 100; // (NSAC * 100) Hz */ + + /* obtain programming time multiplication factor */ + sdd.card_desc.prog_factor = (1 << SD_CSD_GET_R2W_FACTOR(sd_rsp128)); /* should be 4 */ + + /* obtain total read (TAAC + NSAC) & write (R2W * read) access timeout (x100) */ + sdc_clk_ns = 1000000000.0f / (float)sdd.card_desc.sdc_clk_freq; /* SDC clock period (ns) */ + + /* obtain read and write timeout value */ + sdd.card_desc.read_timeout_clks = (uint32_t) (100000000.0f / sdc_clk_ns); /* 100ms according to spec 2.0 */ + sdd.card_desc.write_timeout_clks = (uint32_t) (250000000.0f / sdc_clk_ns); /* 250ms according to spec 2.0 */ + + /* command class support list */ + sdd.card_desc.cmd_class = SD_CSD_GET_CCC(sd_rsp128); /* same as 1.0 */ + + /* read parameters */ + sdd.card_desc.max_read_block_len = (uint16_t) (1 << SD_CSD_GET_READ_BL_LEN(sd_rsp128)); /* should be 512 bytes */ + sdd.card_desc.partial_block_read = (uint8_t) SD_CSD_GET_READ_BL_PARTIAL(sd_rsp128); /* should be 0 */ + sdd.card_desc.read_block_misalign = (uint8_t) SD_CSD_GET_READ_BLK_MISALIGN(sd_rsp128); /* should be 0 */ + + /* write parameters */ + sdd.card_desc.max_write_block_len = (uint16_t) (1 << SD_CSD_GET_WRITE_BL_LEN(sd_rsp128)); /* should be 512 bytes */ + sdd.card_desc.partial_block_write = (uint8_t) SD_CSD_GET_WRITE_BL_PARTIAL(sd_rsp128); /* should be 0 */ + sdd.card_desc.write_block_misalign = (uint8_t) SD_CSD_GET_WRITE_BLK_MISALIGN(sd_rsp128); /* should be 0 */ + + /* erase parameters */ + sdd.card_desc.erase_single_block = (uint8_t) SD_CSD_GET_ERASE_BLK_EN(sd_rsp128); /* should be 1 */ + sdd.card_desc.erase_sector_size = (uint8_t) SD_CSD_GET_SECTOR_SIZE(sd_rsp128); /* should be 64 KBytes (not relate to erase) */ + sdd.card_desc.file_format = (uint8_t) SD_CSD_GET_FILE_FORMAT(sd_rsp128); /* should be 0 */ + + /* write protect parameters */ + sdd.card_desc.wp_group_size = (uint8_t) SD_CSD_GET_WP_GRP_SIZE(sd_rsp128); /* should be 0 */ + sdd.card_desc.wp_group_enable = (uint8_t) SD_CSD_GET_WP_GRP_ENABLE(sd_rsp128); /* should be 0 */ + sdd.card_desc.wp_permanent = (uint8_t) SD_CSD_GET_PERM_WRITE_PROTECT(sd_rsp128); /* same as 1.0 */ + sdd.card_desc.wp_temp = (uint8_t) SD_CSD_GET_TMP_WRITE_PROTECT(sd_rsp128); /* same as 1.0 */ + + /* other parameters */ + sdd.card_desc.copy = (uint8_t) SD_CSD_GET_COPY(sd_rsp128); /* same as 1.0 */ + sdd.card_desc.dsr_imp = (uint8_t) SD_CSD_GET_DSR_IMP(sd_rsp128); /* same as 1.0 */ + + /* card capacity parameters */ + sdd.card_desc.c_size = + (uint32_t) SD_CSD2_GET_C_SIZE(sd_rsp128); + + /* calculate card capacity of user data (unit of 512-bytes) */ + sdd.card_desc.card_capacity = sdd.card_desc.c_size + 1; /* (c_size + 1) * 512 / 512 (KBytes) */ + sdd.card_desc.card_capacity *= + sdd.card_desc.max_read_block_len; + } + else { + SDD_TRACE(("Unknown CSD version!\r\n")); + + sdd.card_desc.csd_ver = 0x00; + status = SDD_INVALID_MEDIA; + goto _err_exit; + } + } + + SDD_TRACE(("card_capacity: 0x%08lx (KB)\r\n", sdd.card_desc.card_capacity)); + SDD_TRACE(("clk_div: 0x%08lx\r\n", sdd.card_desc.sdc_clk_div)); + SDD_TRACE(("clk_freq: %d Hz\r\n", sdd.card_desc.sdc_clk_freq)); + SDD_TRACE(("read_timeout_clks: 0x%08lx\r\n", sdd.card_desc.read_timeout_clks)); + SDD_TRACE(("write_timeout_clks: 0x%08lx\r\n", sdd.card_desc.write_timeout_clks)); + + /* ------------ */ + /* Now we know how to setup SD bus clock for maximum data transfer rate ... */ + OUT32(SDC_CLK_CTL, (SDC_CLK_ON << SDC_CLK_DIS_BIT) | (SDC_CLK_SD << SDC_CLK_SD_BIT) | + ((sdd.card_desc.sdc_clk_div << SDC_CLK_DIV_SHIFT) & SDC_CLK_DIV_MASK)); + _nds_kwait(0x1000); + + /* ------------ */ + /* + * Get SCR register (Standby -> Transfer -> Standby) + * (Majorly we need the data bus width) + */ + SDD_TRACE(("Get SCR\r\n")); + status = _sd_select_card(sdd.card_desc.rca); /* standby -> transfer */ + if (status != HAL_SUCCESS) + goto _err_exit; + + /* + * send SD command to setup read-block-size + * (SD memory card read block size could smaller than 512) + */ + SDD_TRACE(("cmd16\r\n")); + status = _sd_cmd16(8, &sd_rsp32); /* read 64 bits data */ + if (status != HAL_SUCCESS) + goto _err_exit; + + /* set SDC data timeout register */ + // OUT32(SDC_DATA_TIMER, 0xffffffff); /* use sdd.card_desc.read_timeout_clks ? */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.read_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, 8); /* read 64 bits data */ + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | ((3 << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^3 = 8 bytes */ + + /* send SD command to readback SCR register */ + SDD_TRACE(("cmd55\r\n")); + status = _sd_cmd55(sdd.card_desc.rca, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("acmd51\r\n")); + status = _sd_acmd51(&sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* pio-mode read-back */ + tmp_val = 0; + while (tmp_val++ < SD_READ_MAX_RETRY_COUNT) { + + uint32_t sdc_status = IN32(SDC_STATUS); + + if (sdc_status & (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK | SDC_SR_DATA_CRC_FAIL_MASK)) { + + status = SDD_READ_DATA_ERROR; + goto _err_exit; + } + + if (sdc_status & (SDC_SR_FIFO_ORUN_MASK | SDC_SR_DATA_END_MASK)) + break; + } + + /* ACMD51/ACMD13 data are MSB first (big-endian) */ + sd_rsp128.r[3] = IN32(SDC_DATA_WIN); /* [63:32] BE */ + sd_rsp128.r[2] = IN32(SDC_DATA_WIN); /* [31:00] BE */ + + /* reorder byte endian inside the 32-bit word */ + sd_rsp128.b[0] = sd_rsp128.b[11]; + sd_rsp128.b[1] = sd_rsp128.b[10]; + sd_rsp128.b[2] = sd_rsp128.b[9]; + sd_rsp128.b[3] = sd_rsp128.b[8]; + sd_rsp128.b[4] = sd_rsp128.b[15]; + sd_rsp128.b[5] = sd_rsp128.b[14]; + sd_rsp128.b[6] = sd_rsp128.b[13]; + sd_rsp128.b[7] = sd_rsp128.b[12]; + + sdd.card_desc.scr_ver = (uint8_t) SD_SCR_GET_SCR_STRUCTURE(sd_rsp128); + sdd.card_desc.spec_ver = (uint8_t) SD_SCR_GET_SD_SPEC(sd_rsp128); + sdd.card_desc.erase_val = (uint8_t) SD_SCR_GET_DATA_STAT_AFTER_ERASE(sd_rsp128); + sdd.card_desc.security_ver = (uint8_t) SD_SCR_GET_SD_SECURITY(sd_rsp128); + sdd.card_desc.bus_width = (uint8_t) SD_SCR_GET_SD_BUS_WIDTHS(sd_rsp128); + + SDD_TRACE(("lw : 0x%08lx\r\n", sd_rsp128.r[2])); + SDD_TRACE(("hw : 0x%08lx\r\n", sd_rsp128.r[3])); + SDD_TRACE(("SCR_ver : 0x%08lx\r\n", sdd.card_desc.scr_ver)); + SDD_TRACE(("spec_ver : 0x%08lx\r\n", sdd.card_desc.spec_ver)); + SDD_TRACE(("erase_val: 0x%08lx\r\n", sdd.card_desc.erase_val)); + SDD_TRACE(("secu_ver : 0x%08lx\r\n", sdd.card_desc.security_ver)); + SDD_TRACE(("bus_width: 0x%08lx\r\n", sdd.card_desc.bus_width)); + + if ((IN32(SDC_BUS_WIDTH) & SDC_WIDE_BUS_SUPPORT_MASK) && + (sdd.card_desc.bus_width & 0x04)) { + + SDD_TRACE(("SDC configured to wide bus!\r\n")); + + SDD_TRACE(("cmd55\r\n")); + status = _sd_cmd55(sdd.card_desc.rca, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("acmd6\r\n")); + status = _sd_acmd6(SD_ACMD6_MAKE_ARG(SD_BUS_WIDTH_ARG_4BIT), &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("sdc_bus_width\r\n")); + OUT32(SDC_BUS_WIDTH, SDC_WIDE_BUS_SUPPORT_MASK | SDC_WIDE_BUS_MASK); + } + else { + SDD_TRACE(("SDC configured to single bus!\r\n")); + + SDD_TRACE(("cmd55\r\n")); + status = _sd_cmd55(sdd.card_desc.rca, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("acmd6\r\n")); + status = _sd_acmd6(SD_ACMD6_MAKE_ARG(SD_BUS_WIDTH_ARG_1BIT), &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + OUT32(SDC_BUS_WIDTH, SDC_WIDE_BUS_SUPPORT_MASK | SDC_SINGLE_BUS_MASK); + } + + /* transfer -> standby */ + // status = _sd_deselect_card(sdd.card_desc.rca); + // if (status != HAL_SUCCESS) + // goto _err_exit; + + /* + * Turn on SD card power using voltage level obtained from card OCR + * todo: use default? flib doesn't setup voltage value? + */ + // SETB32(SDC_PWR_CTL, SDC_SD_POWER_ON_BIT); + // _nds_kwait(0x1000); + + return HAL_SUCCESS; + +_err_exit: + + SDD_TRACE(("_err_exit!\r\n")); + + /* Turn off SD bus power */ + CLRB32(SDC_PWR_CTL, SDC_SD_POWER_ON_BIT); + + /* Turn off SD bus clock */ + SETB32(SDC_CLK_CTL, SDC_CLK_DIS_BIT); + + /* Setup removed flag */ + sdd.card_desc.rca = 0; +#if (SDD_VFS_SUPPORT) + // notify file system layer, if any ... + if (sdd_bdev.propagate_event != HAL_NULL) + sdd_bdev.propagate_event(&sdd_bdev, NDSBDEV_DEVICE_UNPLUG, HAL_NULL); +#endif // SDD_VFS_SUPPORT + + return status; +} + +#if 0 +/***************************************************************************** + * FUNCTION + * + * _sdd_read_sector_pio + * + * DESCRIPTION + * + * This function performs a sector of data PIO transfer from the SD memory + * card. + * + * NOTE + * + * + * INPUTS + * + * sector : + * sector_cnt : + * io_buff : + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sdd_read_sector_pio(uint32_t sector, uint8_t * io_buff) +{ + uint32_t status = SDD_INVALID_FUNCTION; + uint32_t sdc_status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + uint32_t word_cnt; + uint32_t fifo_depth; + + SDD_TRACE(("\r\n_sdd_read_sector_pio\r\n")); + + if (sector > (sdd.card_desc.card_capacity << 1)) { + SDD_TRACE(("Invalid sector address!\r\n")); + return SDD_INVLAID_ADDRESS; + } + + /* todo: sector size */ + + /* standby -> transfer */ + SDD_TRACE(("- select_card\r\n")); + status = _sd_select_card(sdd.card_desc.rca); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* send SD command to setup read-block-size */ + /* todo: assume sector size is 512 bytes */ + SDD_TRACE(("- cmd16\r\n")); + status = _sd_cmd16(SDD_SECTOR_SIZE, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* set SDC data timeout register */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.read_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, SDD_SECTOR_SIZE); + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | ((SDD_POWER_OF_SECTOR_SIZE << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^9 = 512 bytes */ + + /* send SD command to readback data */ + SDD_TRACE(("- cmd17\r\n")); + if (sdd.card_desc.card_ccs == SDD_CCS_SD) + status = _sd_cmd17(sector * SDD_SECTOR_SIZE, &sd_rsp32); /* address unit is byte for SD */ + else + status = _sd_cmd17(sector, &sd_rsp32); /* address unit is 512 bytes for SDHC */ + + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("- wait until card is sending out data\r\n")); + _nds_kwait(0x1000); /* hw need delay ? */ + /*status = _sd_wait_sending_state(sdd.card_desc.rca); */ + /*if (status != HAL_SUCCESS) */ + /* goto _err_exit; */ + + SDD_TRACE(("- read back data\r\n")); + + /* per 32-bit word read back */ + word_cnt = SDD_SECTOR_SIZE >> 2; + while (word_cnt > 0) { + retry = 0; + while (retry++ < SD_READ_MAX_RETRY_COUNT) { + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK + | SDC_SR_DATA_CRC_FAIL_MASK)) { + SDD_TRACE(("- data error/timeout or card removed, sdc_status: 0x%08lx\r\n", sdc_status)); + status = SDD_READ_DATA_ERROR; + goto _err_exit; + } + if (sdc_status & + (SDC_SR_FIFO_ORUN_MASK | SDC_SR_DATA_END_MASK)) { + SETB32(SDC_CLEAR, SDC_FIFO_ORUN_BIT); + retry = 0xffffffff; /* success */ + break; + } + } + + if (retry != 0xffffffff) { + /* wait data timeout */ + SDD_TRACE(("- timeout, sdc_status: 0x%08lx\r\n", + sdc_status)); + status = SDD_READ_DATA_ERROR; + goto _err_exit; + } + + fifo_depth = SDC_FIFO_WORD_DEPTH; + while (fifo_depth-- > 0) { + /* CMD17/18/24/25 ACMD18/25 data are LSB first (little-endian) */ + *((uint32_t *) io_buff) = IN32(SDC_DATA_WIN); /* just mem-move so no data endian issue. */ + + io_buff += 4; + if (--word_cnt == 0) + break; + } + } + + SDD_TRACE(("- data read completed\r\n")); + return HAL_SUCCESS; + +_err_exit: + + SDD_TRACE(("- error on data read\r\n")); + return status; +} +#endif + +/***************************************************************************** + * FUNCTION + * + * _sdd_read_sectors_pio + * + * DESCRIPTION + * + * This function performs PIO data transfer from the SD memory card in + * multiple unit of sectors. + * + * NOTE + * + * + * INPUTS + * + * sector : + * sector_cnt : + * io_buff : + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_read_sectors_pio(uint32_t sector, uint32_t sector_cnt, + uint8_t * io_buff) +{ + uint32_t status = SDD_INVALID_FUNCTION; + uint32_t sdc_status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + uint32_t word_cnt; + uint32_t fifo_depth; + + SDD_TRACE(("\r\n_sdd_read_sectors_pio\r\n")); + + if (sector > (sdd.card_desc.card_capacity << 1)) { + + SDD_TRACE(("Invalid sector address!\r\n")); + return SDD_INVLAID_ADDRESS; + } + + if ((sector_cnt == 0) || (((sector + sector_cnt) > (sdd.card_desc.card_capacity << 1)))) { + + SDD_TRACE(("Invalid sector address range!\r\n")); + return SDD_INVLAID_ADDR_RANGE; + } + + /* todo: sector size */ + + /* standby -> transfer */ + SDD_TRACE(("- select_card\r\n")); + status = _sd_select_card(sdd.card_desc.rca); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* send SD command to setup read-block-size */ + /* todo: assume sector size is 512 bytes */ + SDD_TRACE(("- cmd16\r\n")); + status = _sd_cmd16(SDD_SECTOR_SIZE, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* set SDC data timeout register */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.read_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, sector_cnt * SDD_SECTOR_SIZE); + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | ((SDD_POWER_OF_SECTOR_SIZE << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^9 = 512 bytes */ + + /* send SD command to readback data */ + SDD_TRACE(("- cmd18\r\n")); + if (sdd.card_desc.card_ccs == SDD_CCS_SD) + status = _sd_cmd18(sector * SDD_SECTOR_SIZE, &sd_rsp32); /* address unit is byte for SD */ + else + status = _sd_cmd18(sector, &sd_rsp32); /* address unit is 512 bytes for SDHC */ + + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("- wait until card is sending out data\r\n")); + _nds_kwait(0x1000); /* hw need delay ? */ + + /* This method will dirty SDC_STATUS so not been used. */ + // status = _sd_wait_sending_state(sdd.card_desc.rca); + // if (status != HAL_SUCCESS) + // goto _err_exit; + + /* per sector PIO read back */ + OUT32(SDC_CLEAR, 0x3ff); + SDD_TRACE(("- read back data\r\n")); + while (sector_cnt-- > 0) { + + /* per 32-bit word read back */ + word_cnt = SDD_SECTOR_SIZE >> 2; + while (word_cnt > 0) { + retry = 0; + while (retry++ < SD_READ_MAX_RETRY_COUNT) { + + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | + SDC_SR_DATA_TIMEOUT_MASK | + SDC_SR_DATA_CRC_FAIL_MASK)) { + SDD_TRACE(("- data error/timeout or card removed, sdc_status: 0x%08lx\r\n", sdc_status)); + status = SDD_READ_DATA_ERROR; + goto _err_exit; + } + if (sdc_status & (SDC_SR_FIFO_ORUN_MASK | SDC_SR_DATA_END_MASK)) { + + retry = 0xffffffff; /* success */ + break; + } + } + + if (retry != 0xffffffff) { + + /* wait data timeout */ + SDD_TRACE(("- timeout, sdc_status: 0x%08lx\r\n", sdc_status)); + status = SDD_READ_DATA_ERROR; + goto _err_exit; + } + + fifo_depth = SDC_FIFO_WORD_DEPTH; + SETB32(SDC_CLEAR, SDC_FIFO_ORUN_BIT); + while (fifo_depth-- > 0) { + + /* CMD17/18/24/25 ACMD18/25 data are LSB first (little-endian) */ + *((uint32_t *) io_buff) = IN32(SDC_DATA_WIN); /* just mem-move so no data endian issue. */ + + io_buff += 4; + if (--word_cnt == 0) + break; + } + } + } + + _nds_kwait(0x1000); /* hw need delay ? */ + + /* Stop data transmission */ + SDD_TRACE(("- stop transmission\r\n")); + status = _sd_stop_transmission(sdd.card_desc.rca); + /* FIXME this part is marked for qemu */ +#if 0 + if (status != HAL_SUCCESS) + goto _err_exit; +#endif + SDD_TRACE(("- data read completed\r\n")); + return HAL_SUCCESS; + +_err_exit: + + SDD_TRACE(("- error on data read! status(0x%08lx)\r\n", status)); + return status; +} + +extern int dmad_apb_config_dir(const DMAD_CHANNEL_REQUEST_DESC *ch_req, uint8_t dir); +/***************************************************************************** + * FUNCTION + * + * _sdd_read_sectors_dma + * + * DESCRIPTION + * + * This function performs DMA data transfer from the SD memory card in + * multiple unit of sectors. + * + * NOTE + * + * + * INPUTS + * + * sector : + * sector_cnt : + * io_buff : + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_read_sectors_dma(uint32_t sector, uint32_t sector_cnt, + uint8_t * io_buff) +{ + uint32_t status = SDD_INVALID_FUNCTION; + SD_R32 sd_rsp32; + DMAD_DRB *drb; + + SDD_TRACE(("\r\n_sdd_read_sectors_dma\r\n")); + if (sector > (sdd.card_desc.card_capacity << 1)) { + + SDD_TRACE(("Invalid sector address!\r\n")); + return SDD_INVLAID_ADDRESS; + } + + if ((sector_cnt == 0) || (((sector + sector_cnt) > (sdd.card_desc.card_capacity << 1)))) { + + SDD_TRACE(("Invalid sector address range!\r\n")); + return SDD_INVLAID_ADDR_RANGE; + } + /* todo: sector size */ + + /* standby -> transfer */ + SDD_TRACE(("- select_card\r\n")); + status = _sd_select_card(sdd.card_desc.rca); + if (status != HAL_SUCCESS) + goto _safe_exit; + + /* send SD command to setup read-block-size */ + /* todo: assume sector size is 512 bytes */ + SDD_TRACE(("- cmd16\r\n")); + status = _sd_cmd16(SDD_SECTOR_SIZE, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _safe_exit; + + /* set SDC data timeout register */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.read_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, sector_cnt * SDD_SECTOR_SIZE); + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | SDC_DMA_EN_MASK | ((SDD_POWER_OF_SECTOR_SIZE << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^9 = 512 bytes */ + + /* send SD command to readback data */ + SDD_TRACE(("- cmd18\r\n")); + if (sdd.card_desc.card_ccs == SDD_CCS_SD) + status = _sd_cmd18(sector * SDD_SECTOR_SIZE, &sd_rsp32); /* address unit is byte for SD */ + else + status = _sd_cmd18(sector, &sd_rsp32); /* address unit is 512 bytes for SDHC */ + + if (status != HAL_SUCCESS) + goto _safe_exit; + + SDD_TRACE(("- wait until card is sending out data\r\n")); + // _nds_kwait(0x1000); /* hw need delay ? */ + + /* This method will dirty SDC_STATUS so not been used. */ + // status = _sd_wait_sending_state(sdd.card_desc.rca); + // if (status != HAL_SUCCESS) + // goto _err_exit; + + /* per sector DMA read back */ + /* CMD17/18/24/25 ACMD18/25 data are LSB first (little-endian) */ + SDD_TRACE(("- read back data\r\n")); + + dmad_apb_config_dir(&sdd.dma_ch,DMAD_DIR_A0_TO_A1); + + while (sector_cnt-- > 0) { + + status = _dmad_alloc_drb(&sdd.dma_ch, &drb); + if (status != HAL_SUCCESS) + goto _safe_exit; + + drb->src_addr = (void *)SDC_DATA_WIN; + drb->dst_addr = (void *)io_buff; + drb->req_size = SDD_SECTOR_SIZE >> 2; /* multiple counts of transfer width */ + + if (sector_cnt == 0) + drb->completion_sem = &sdd.dma_sem; + + /* Submit DRB */ + status = _dmad_submit_request(&sdd.dma_ch, drb); + if (status != HAL_SUCCESS) + goto _safe_exit; + + /* Point to next buffer location */ + io_buff += SDD_SECTOR_SIZE; + } + + /* Wait DMA completion */ + /* - method 1: sync with semaphore */ + /* - method 2: check SDC status register SDC_STATUS[7] */ + if (1){ + + DEBUG(0, 1, "- wait dma completion ...\n"); + status = hal_pend_semaphore(&sdd.dma_sem, 300); + + if (status == HAL_ERR_TIMEOUT) { + + DEBUG(1, 1, "- wait dma completion timeout (might not an error)\n"); + goto _safe_exit; + } + else if (status != HAL_SUCCESS) { + + DEBUG(1, 1, "- wait dma completion failed! (0x%08lx)\n", status); + goto _safe_exit; + } + } + else { + uint32_t retry = 0; + uint32_t sdc_status; + + SDD_TRACE(("- polling dma completion status ...\r\n")); + while (retry++ < SD_READ_MAX_RETRY_COUNT) { + + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK + | SDC_SR_DATA_CRC_FAIL_MASK)) { + + SDD_TRACE(("- data error/timeout or card removed, sdc_status: 0x%08lx\r\n", sdc_status)); + status = SDD_READ_DATA_ERROR; + break; /* todo: report error to upper layer? */ + } + if (sdc_status & (SDC_SR_FIFO_ORUN_MASK | SDC_SR_DATA_END_MASK)) { + + SETB32(SDC_CLEAR, SDC_FIFO_ORUN_BIT); + retry = 0xffffffff; /* success */ + break; + } + } + } + + /* Stop data transmission anyway after waiting. */ + SDD_TRACE(("- stop transmission\r\n")); + status = _sd_stop_transmission(sdd.card_desc.rca); + /* FIXME this part is marked for qemu */ +#if 0 + if (status != HAL_SUCCESS) + goto _safe_exit; +#endif + status = HAL_SUCCESS; +_safe_exit: + +#if (SDD_DEBUG_TRACE) + if (status == HAL_SUCCESS) + SDD_TRACE(("- data read completed\r\n")); + else + SDD_TRACE(("- error on data read\r\n")); +#endif /* SDD_DEBUG_TRACE */ + + return status; +} + +#if 0 +/***************************************************************************** + * FUNCTION + * + * _sdd_write_sector_pio + * + * DESCRIPTION + * + * This function performs a sector of data PIO transfer to the SD memory + * card. + * + * NOTE + * + * + * INPUTS + * + * sector : + * io_buff : + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sdd_write_sector_pio(uint32_t sector, uint8_t * io_buff) +{ + uint32_t status = SDD_INVALID_FUNCTION; + uint32_t sdc_status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + uint32_t word_cnt; + uint32_t fifo_depth; + + SDD_TRACE(("\r\n_sdd_write_sector_pio\r\n")); + + if (sector > (sdd.card_desc.card_capacity << 1)) { + SDD_TRACE(("Invalid sector address!\r\n")); + return SDD_INVLAID_ADDRESS; + } + + if (GETB32(SDC_STATUS, SDC_SR_WRITE_PROT_BIT)) { + SDD_TRACE(("Card is write protected!\r\n")); + return SDD_WRITE_PROTECTED; + } + + /* todo: sector size */ + + /* standby -> transfer */ + SDD_TRACE(("- select_card\r\n")); + status = _sd_select_card(sdd.card_desc.rca); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* send SD command to setup write-block-size */ + /* todo: assume sector size is 512 bytes */ + SDD_TRACE(("- cmd16\r\n")); + status = _sd_cmd16(SDD_SECTOR_SIZE, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* set SDC data timeout register */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.write_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, SDD_SECTOR_SIZE); + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | SDC_DATA_WRITE_MASK | ((SDD_POWER_OF_SECTOR_SIZE << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^9 = 512 bytes */ + + /* send SD command to write data */ + SDD_TRACE(("- cmd24\r\n")); + if (sdd.card_desc.card_ccs == SDD_CCS_SD) + status = _sd_cmd24(sector * SDD_SECTOR_SIZE, &sd_rsp32); /* address unit is byte for SD */ + else + status = _sd_cmd24(sector, &sd_rsp32); /* address unit is 512 bytes for SDHC */ + + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("- wait ready to write out data\r\n")); + _nds_kwait(0x1000); /* hw need delay ? */ + /*status = _sd_wait_receiving_state(sdd.card_desc.rca); // This method look not necessary for writing. */ + /*if (status != HAL_SUCCESS) */ + /* goto _err_exit; */ + + /* per sector PIO write out */ + SDD_TRACE(("- write out data\r\n")); + + /* clear SDC status bits before sending data */ + OUT32(SDC_CLEAR, SDC_CLEAR_ALL); + + /* per 32-bit word write out */ + word_cnt = SDD_SECTOR_SIZE >> 2; + while (word_cnt > 0) { + fifo_depth = SDC_FIFO_WORD_DEPTH; + while (fifo_depth-- > 0) { + /* CMD17/18/24/25 ACMD18/25 data are LSB first (little-endian) */ + OUT32(SDC_DATA_WIN, *((uint32_t *) io_buff)); /* just mem-move so no data endian issue. */ + + io_buff += 4; + if (--word_cnt == 0) + goto _complete_exit; + } + + retry = 0; + while (retry++ < SD_WRITE_MAX_RETRY_COUNT) { + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK + | SDC_SR_DATA_CRC_FAIL_MASK)) { + status = SDD_WRITE_DATA_ERROR; + goto _err_exit; + } + if (sdc_status & + (SDC_SR_FIFO_URUN_MASK | SDC_SR_DATA_END_MASK)) { + SETB32(SDC_CLEAR, SDC_FIFO_URUN_BIT); + retry = 0xffffffff; /* success */ + break; + } + } + + if (retry != 0xffffffff) { + /* wait data timeout */ + SDD_TRACE(("- timeout, sdc_status: 0x%08lx\r\n", + sdc_status)); + + /*SDD_TRACE(("- wait again by polling CSR\r\n")); */ + /*status = _sd_wait_receiving_state(sdd.card_desc.rca); */ + /*if (status != HAL_SUCCESS) */ + goto _err_exit; + + /*SDD_TRACE(("- card ready, sdc_status: 0x%08lx\r\n", IN32(SDC_STATUS))); */ + } + } + +_complete_exit: + + /* Wait host SDC shift-out FIFO data */ + SDD_TRACE(("- final check sdc_status\r\n")); + retry = 0; + while (retry++ < SD_WRITE_MAX_RETRY_COUNT) { + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK | + SDC_SR_DATA_CRC_FAIL_MASK)) { + status = SDD_WRITE_DATA_ERROR; + goto _err_exit; + } + if ((sdc_status == 0) || (sdc_status & SDC_SR_DATA_END_MASK)) { + break; + } + } + + SDD_TRACE(("- data write completed\r\n")); + return HAL_SUCCESS; + +_err_exit: + + SDD_TRACE(("- error on data write\r\n")); + return status; +} +#endif + +/***************************************************************************** + * FUNCTION + * + * _sdd_write_sectors_pio + * + * DESCRIPTION + * + * This function performs PIO data transfer to the SD memory card in + * multiple unit of sectors. + * + * NOTE + * + * + * INPUTS + * + * sector : + * sector_cnt : + * io_buff : + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_write_sectors_pio(uint32_t sector, uint32_t sector_cnt, + uint8_t * io_buff) +{ + uint32_t status = SDD_INVALID_FUNCTION; + uint32_t sdc_status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + uint32_t word_cnt; + uint32_t fifo_depth; + + if (sector > (sdd.card_desc.card_capacity << 1)) { + + SDD_TRACE(("Invalid sector address!\r\n")); + return SDD_INVLAID_ADDRESS; + } + + if ((sector_cnt == 0) || (((sector + sector_cnt) > (sdd.card_desc.card_capacity << 1)))) { + + SDD_TRACE(("Invalid sector address range!\r\n")); + return SDD_INVLAID_ADDR_RANGE; + } + + if (GETB32(SDC_STATUS, SDC_SR_WRITE_PROT_BIT)) { + + SDD_TRACE(("Card is write protected!\r\n")); + return SDD_WRITE_PROTECTED; + } + + /* todo: sector size */ + + /* standby -> transfer */ + SDD_TRACE(("- select_card\r\n")); + status = _sd_select_card(sdd.card_desc.rca); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* send SD command to setup write-block-size */ + /* todo: assume sector size is 512 bytes */ + SDD_TRACE(("- cmd16\r\n")); + status = _sd_cmd16(SDD_SECTOR_SIZE, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _err_exit; + + /* set SDC data timeout register */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.write_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, sector_cnt * SDD_SECTOR_SIZE); + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | SDC_DATA_WRITE_MASK | ((SDD_POWER_OF_SECTOR_SIZE << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^9 = 512 bytes */ + + /* send SD command to write data */ + SDD_TRACE(("- cmd25\r\n")); + if (sdd.card_desc.card_ccs == SDD_CCS_SD) + status = _sd_cmd25(sector * SDD_SECTOR_SIZE, &sd_rsp32); /* address unit is byte for SD */ + else + status = _sd_cmd25(sector, &sd_rsp32); /* address unit is 512 bytes for SDHC */ + + if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("- wait ready to write out data\r\n")); + _nds_kwait(0x1000); /* hw need delay ? */ + + /* This method look not necessary for writing. */ + // status = _sd_wait_receiving_state(sdd.card_desc.rca); + // if (status != HAL_SUCCESS) */ + // goto _err_exit; */ + + /* per sector PIO write out */ + OUT32(SDC_CLEAR, 0x3ff); + SDD_TRACE(("- write out data\r\n")); + while (sector_cnt-- > 0) { + + /* per 32-bit word write out */ + word_cnt = SDD_SECTOR_SIZE >> 2; + while (word_cnt > 0) { + + SDD_TRACE(("- word_cnt: 0x%08lx\r\n", word_cnt)); + + fifo_depth = SDC_FIFO_WORD_DEPTH; + while ((fifo_depth-- > 0) && (word_cnt-- > 0)) { + + /* CMD17/18/24/25 ACMD18/25 data are LSB first (little-endian) */ + OUT32(SDC_DATA_WIN, *((uint32_t *) io_buff)); /* just mem-move so no data endian issue. */ + + io_buff += 4; + } + + if (word_cnt == 0) + break; + + retry = 0; + while (retry++ < SD_WRITE_MAX_RETRY_COUNT) { + + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | + SDC_SR_DATA_TIMEOUT_MASK | + SDC_SR_DATA_CRC_FAIL_MASK)) { + status = SDD_WRITE_DATA_ERROR; + goto _err_exit; + } + if (sdc_status & + (SDC_SR_FIFO_URUN_MASK | + SDC_SR_DATA_END_MASK)) { + SETB32(SDC_CLEAR, SDC_FIFO_URUN_BIT); + retry = 0xffffffff; /* success */ + break; + } + } + + if (retry != 0xffffffff) { + /* wait data timeout */ + SDD_TRACE(("- timeout, sdc_status: 0x%08lx\r\n", sdc_status)); + + // SDD_TRACE(("- wait again by polling CSR\r\n")); + // status = _sd_wait_receiving_state(sdd.card_desc.rca); + // if (status != HAL_SUCCESS) + goto _err_exit; + + SDD_TRACE(("- card ready, sdc_status: 0x%08lx\r\n", IN32(SDC_STATUS))); + } + } + } + + /* Wait host SDC shift-out FIFO data */ + SDD_TRACE(("- final check sdc_status\r\n")); + retry = 0; + while (retry++ < SD_WRITE_MAX_RETRY_COUNT) { + + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK | + SDC_SR_DATA_CRC_FAIL_MASK)) { + + status = SDD_WRITE_DATA_ERROR; + goto _err_exit; + } + if ((sdc_status == 0) || (sdc_status & SDC_SR_DATA_END_MASK)) + break; + } + + /* Stop data transmission */ + SDD_TRACE(("- stop transmission\r\n")); + status = _sd_stop_transmission(sdd.card_desc.rca); + /* FIXME this part is marked for qemu */ +#if 0 + if (status != HAL_SUCCESS) + goto _err_exit; +#endif + SDD_TRACE(("- data write completed\r\n")); + return HAL_SUCCESS; + +_err_exit: + + SDD_TRACE(("- error on data write\r\n")); + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_write_sectors_dma + * + * DESCRIPTION + * + * This function performs DMA data transfer to the SD memory card in + * multiple unit of sectors. + * + * NOTE + * + * + * INPUTS + * + * sector : + * sector_cnt : + * io_buff : + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SSPD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_write_sectors_dma(uint32_t sector, uint32_t sector_cnt, + uint8_t * io_buff) +{ + uint32_t status = SDD_INVALID_FUNCTION; + SD_R32 sd_rsp32; + uint32_t retry; + uint32_t sdc_status; + DMAD_DRB *drb; +#if 0 + if (sector > (sdd.card_desc.card_capacity << 1)) { + + SDD_TRACE(("Invalid sector address!\r\n")); + return SDD_INVLAID_ADDRESS; + } + + if ((sector_cnt == 0) || (((sector + sector_cnt) > (sdd.card_desc.card_capacity << 1)))) { + + SDD_TRACE(("Invalid sector address range!\r\n")); + return SDD_INVLAID_ADDR_RANGE; + } +#endif + if (GETB32(SDC_STATUS, SDC_SR_WRITE_PROT_BIT)) { + SDD_TRACE(("Card is write protected!\r\n")); + return SDD_WRITE_PROTECTED; + } + + /* todo: sector size */ + + /* reset dam wait event */ +// hal_set_semaphore(&sdd.dma_sem, 0); + + /* standby -> transfer */ + SDD_TRACE(("- select_card\r\n")); + status = _sd_select_card(sdd.card_desc.rca); + if (status != HAL_SUCCESS) + goto _safe_exit; + + /* send SD command to setup write-block-size */ + /* todo: assume sector size is 512 bytes */ + SDD_TRACE(("- cmd16\r\n")); + status = _sd_cmd16(SDD_SECTOR_SIZE, &sd_rsp32); + if (status != HAL_SUCCESS) + goto _safe_exit; + + /* set SDC data timeout register */ + OUT32(SDC_DATA_TIMER, sdd.card_desc.write_timeout_clks); + + /* set SDC data length register */ + OUT32(SDC_DATA_LEN, sector_cnt * SDD_SECTOR_SIZE); + + /* set SDC data control register */ + OUT32(SDC_DATA_CR, SDC_DATA_EN_MASK | SDC_DATA_WRITE_MASK | SDC_DMA_EN_MASK | ((SDD_POWER_OF_SECTOR_SIZE << SDC_BLK_SIZE_SHIFT) & SDC_BLK_SIZE_MASK)); /* 2^9 = 512 bytes */ + + /* send SD command to write data */ + SDD_TRACE(("- cmd25\r\n")); + if (sdd.card_desc.card_ccs == SDD_CCS_SD) + status = _sd_cmd25(sector * SDD_SECTOR_SIZE, &sd_rsp32); /* address unit is byte for SD */ + else + status = _sd_cmd25(sector, &sd_rsp32); /* address unit is 512 bytes for SDHC */ + + if (status != HAL_SUCCESS) + goto _safe_exit; + + SDD_TRACE(("- wait ready to write out data\r\n")); + _nds_kwait(0x1000); /* hw need delay ? */ + + /* This method look not necessary for writing. */ + // status = _sd_wait_receiving_state(sdd.card_desc.rca); + // if (status != HAL_SUCCESS) */ + // goto _err_exit; */ + + /* per sector DMA write out */ + SDD_TRACE(("- write out data\r\n")); + + dmad_apb_config_dir(&sdd.dma_ch, DMAD_DIR_A1_TO_A0); + + if(hal_create_semaphore(&sdd.dma_sem, 0, 0) == HAL_FAILURE) + SDD_TRACE(("Failed to create dma semaphore\r\n")); + + while (sector_cnt-- > 0) { + + SDD_TRACE(("sector_cnt: %ld\r\n", sector_cnt)); + + /* Prepare DRB */ + status = _dmad_alloc_drb(&sdd.dma_ch, &drb); + if (status != HAL_SUCCESS) + goto _safe_exit; + + drb->src_addr = (void *)io_buff; + drb->dst_addr = (void *)SDC_DATA_WIN; + drb->req_size = SDD_SECTOR_SIZE >> 2; /* multiple counts of transfer width */ + + if (sector_cnt == 0) + drb->completion_sem = &sdd.dma_sem; /* Register DMA completion notification */ + + /* Submit DRB */ + status = _dmad_submit_request(&sdd.dma_ch, drb); + if (status != HAL_SUCCESS) + goto _safe_exit; + + /* Point to next buffer location */ + io_buff += SDD_SECTOR_SIZE; + } + + /* + * Wait DMA completion + * - method 1: sync with semaphore + * - method 2: check SDC status register SDC_STATUS[7] + */ + status = hal_pend_semaphore(&sdd.dma_sem, 600); /* 6 sec */ + + /* Check waiting status */ + if (status == HAL_ERR_TIMEOUT) { + + SDD_TRACE(("- wait dma completion timeout (might not an error)\r\n")); + goto _safe_exit; + } + else if (status != HAL_SUCCESS) { + + SDD_TRACE(("- wait dma completion failed\r\n")); + goto _safe_exit; + } + + /* Wait host SDC shift-out FIFO data */ + SDD_TRACE(("- final check sdc_status\r\n")); + retry = 0; + while (retry++ < SD_WRITE_MAX_RETRY_COUNT) { + + sdc_status = IN32(SDC_STATUS); + if (sdc_status & + (SDC_SR_CARD_DETECT_MASK | SDC_SR_DATA_TIMEOUT_MASK | + SDC_SR_DATA_CRC_FAIL_MASK)) { + status = SDD_WRITE_DATA_ERROR; + goto _safe_exit; + } + if ((sdc_status == 0) || (sdc_status & SDC_SR_DATA_END_MASK)) + break; + } + + /* Stop data transmission */ + SDD_TRACE(("- stop transmission\r\n")); + status = _sd_stop_transmission(sdd.card_desc.rca); + /* FIXME this part is marked for qemu */ +#if 0 + if (status != HAL_SUCCESS) + goto _safe_exit; +#endif + status = HAL_SUCCESS; + +_safe_exit: + +#if (SDD_DEBUG_TRACE) + if (status == HAL_SUCCESS) + SDD_TRACE(("- data read completed\r\n")); + else + SDD_TRACE(("- error on data read\r\n")); +#endif /* SDD_DEBUG_TRACE */ + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_lisr + * + * DESCRIPTION + * + * This is the ISR that services SD card detection interrupt on the NDS32 + * evb platform. + * + * NOTE + * + * Card Detection Procedures (LISR) + * LISR set HISR activation state flag + * LISR activates HISR + * call _sdd_cd_reset() to perform card insertion or removal tasks. + * + * Card Detection Procedures (_sdd_init) + * Perform basic SD controller register setup + * Checks SDC_SR_CARD_DETECT_BIT bit + * call _sdd_cd_reset() to perform card insertion or removal tasks. + * + * INPUTS + * + * vector : Interrupt vector number + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +void _sdd_lisr(int vector) +{ + DEBUG(1, 1, "_sdd_lisr\r\n"); + printf("hal_raise_bh0\n"); + /* Fault invocation checking */ + if (vector != IRQ_SDC_VECTOR ) + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); + + /* Mask : Disable SDC interrupt */ + hal_intc_irq_disable(IRQ_SDC_VECTOR); + /* Ack : Clean SDC interrupt pending */ + hal_intc_irq_clean(IRQ_SDC_VECTOR); + + printf("hal_raise_bh1\n"); + if (GETB32(SDC_STATUS, SDC_SR_CARD_CHANGE_BIT)) { + + SETB32(SDC_CLEAR, SDC_CARD_CHANGE_BIT); + + /* Set HISR status register to get channel number */ + sdd.hisr_as |= SDD_HISR_AS_CD; + printf("hal_raise_bh2\n"); + hal_raise_bh(&sdd.hisr); /* Activate HISR to complete deferred tasks */ + } + else { + printf("hal_raise_bh3\n"); + /* todo: handle other interrupts. */ + OUT32(SDC_CLEAR, SDC_CLEAR_ALL); + } + + /* Unmask : Enable SDC interrupt */ + hal_intc_irq_enable(IRQ_SDC_VECTOR); +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_hisr + * + * DESCRIPTION + * + * This is the HISR that services SD card detection interrupt on the NDS32 + * evb platform. + * + * NOTE + * + * + * INPUTS + * + * + * + * OUTPUTS + * + * none + * + ****************************************************************************/ +void _sdd_hisr(void *param) +{ + hal_bh_t *bh = (hal_bh_t *)param; + + uint32_t core_intl; + uint8_t hisr_as; /* HISR activation state - Card Detection */ + while (1){ + + DEBUG(1, 1, "_sdd_hisr before\n"); + hal_pend_semaphore(&bh->sem, HAL_SUSPEND); + + /* + * Disable CPU interrupt + * Todo: frequently int-disable due to frequently HISR-call may cause problems? + */ + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Clone HISR activation state */ + hisr_as = sdd.hisr_as; + sdd.hisr_as &= ~(uint32_t) SDD_HISR_AS_CD; + + /* Enable CPU interrupt */ + hal_global_int_ctl(core_intl); + + /* Card detect initialization */ + if (hisr_as & SDD_HISR_AS_CD) { + + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) { + + SDD_TRACE(("SD card removed!\r\n")); + + /* Perform card-remove tasks (turn off clock ...) */ + _sdd_cd_reset(HAL_FALSE); + } + else { + SDD_TRACE(("SD card inserted!\r\n")); + /* Reset card and get device parameters */ + _sdd_cd_reset(HAL_TRUE); + } + } + } +} + +#if (SDD_VFS_SUPPORT) +//STATUS _sdd_read_sectors(SDD_IOCTL_READ_SECTORS_PARAM *iop); + +STATUS _sdd_read_sectors_bdev(NDS_BDEV *bdev, UINT32 sector, UINT32 sector_count, void *buffer) +{ + STATUS io_status; + SDD_DEVICE sdd_dev; // FIXME, NDS_SD_ReadSectors doesn't use this argument actully + + BDEV_TRACE(("_sdd_read_sectors_bdev()\r\n")); + BDEV_TRACE((" read start at sector (0x%08lx + 0x%08lx = 0x%08lx) count (0x%08lx)\r\n", + bdev->start, sector, bdev->start + sector, sector_count)); +#ifndef CONFIG_PLAT_QEMU + io_status = NDS_SD_ReadSectors(&sdd_dev, bdev->start + sector, sector_count, 512, buffer); +#else + io_status = NDS_SD_ReadSectors(&sdd_dev, sector, sector_count, 512, buffer); +#endif +#if 0 + if (NU_Current_Task_Pointer() != HAL_NULL) + { + // obtain exclusive access to driver + request.nu_function = NU_ASSIGN; + request.nu_timeout = NU_SUSPEND; + status = NU_Request_Driver(&sdd_dcb, &request); + if (status != NU_SUCCESS) + return status; + } + // perform i/o operation + BDEV_TRACE((" read start at sector (0x%08lx + 0x%08lx = 0x%08lx) count (0x%08lx)\r\n", + bdev->start, sector, bdev->start + sector, sector_count)); + iop.lba_sector = bdev->start + sector; + iop.sector_count = sector_count; + iop.sector_size = SDD_SECTOR_SIZE; + iop.io_buff = buffer; + io_status = _sdd_read_sectors(&iop); + if (NU_Current_Task_Pointer() != HAL_NULL) + { + // release exclusive access to driver + request.nu_function = NU_RELEASE; + status = NU_Request_Driver(&sdd_dcb, &request); + if (status != NU_SUCCESS) + return status; + } +#endif + return io_status; +} + +//STATUS _sdd_write_sectors(SDD_IOCTL_WRITE_SECTORS_PARAM *iop); + +STATUS _sdd_write_sectors_bdev(NDS_BDEV *bdev, UINT32 sector, UINT32 sector_count, void *buffer) +{ + STATUS io_status; + SDD_DEVICE sdd_dev; // FIXME, NDS_SD_ReadSectors doesn't use this argument actully + + BDEV_TRACE(("_sdd_write_sectors_bdev()\r\n")); +#ifndef CONFIG_PLAT_QEMU + io_status = NDS_SD_WriteSectors(&sdd_dev, bdev->start + sector, sector_count, 512, buffer); +#else + io_status = NDS_SD_WriteSectors(&sdd_dev, sector, sector_count, 512, buffer); +#endif +#if 0 + if (NU_Current_Task_Pointer() != HAL_NULL) + { + // obtain exclusive access to driver + request.nu_function = NU_ASSIGN; + request.nu_timeout = NU_SUSPEND; + status = NU_Request_Driver(&sdd_dcb, &request); + if (status != NU_SUCCESS) + return status; + } + + // perform i/o operation + BDEV_TRACE((" write start at sector (0x%08lx + 0x%08lx = 0x%08lx) count (0x%08lx)\r\n", + bdev->start, sector, bdev->start + sector, sector_count)); + iop.lba_sector = bdev->start + sector; + iop.sector_count = sector_count; + iop.sector_size = SDD_SECTOR_SIZE; + iop.io_buff = buffer; + io_status = _sdd_write_sectors(&iop); + + if (NU_Current_Task_Pointer() != HAL_NULL) + { + // release exclusive access to driver + request.nu_function = NU_RELEASE; + status = NU_Request_Driver(&sdd_dcb, &request); + if (status != NU_SUCCESS) + return status; + } +#endif + BDEV_TRACE((" status (0x%08lx)\r\n", io_status)); + return io_status; +} +#endif // SDD_VFS_SUPPORT +/***************************************************************************** + * FUNCTION + * + * _sdd_init + * + * DESCRIPTION + * + * This function initializes the SDC device. + * + * NOTE + * + * SD/MEM : PC-Card Memory mode, PC-Card I/O mode, True-IDE. + * SDIO : Todo. + * SDHC : Not supported. + * MMC : Todo. + * + * Todo : Resource leaks is not recovered if error happens + * during init process. Client currently has to do + * TERMINATE request anyway, if driver load/unload + * resource control is a necessary, no-matter the + * initialization process is successful or not. + * + * INPUTS + * + * sdd_dev : user device struct + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_init(SDD_DEVICE * sdd_dev) +{ + uint32_t status = HAL_SUCCESS; + uint32_t core_intl; + + SDD_TRACE(("_sdd_init()\r\n")); + + /* Perform Parameter Checking */ + +#if (!SDD_SMALL_FOOTPRINT) + /* Check supplemental init structure */ + if (sdd_dev == HAL_NULL) { + + SDD_TRACE(("null sdd_dev!\r\n")); + return HAL_ERR_INVALID_POINTER; + } + + /* Check duplicated device initialization */ + if (sdd.valid != 0) { + + /* Error if the device has been initialized */ + SDD_TRACE(("sdd.valid is non-zero!\r\n")); + return SDD_INVALID_INIT; + } +#endif /* (!SDD_SMALL_FOOTPRINT) */ + + /* Initialize SDC driver resources */ + + /* Allocate DMA channel if user requested static DMA channel mode */ + switch (sdd_dev->dma) { + case SDD_DMA_NONE: + case SDD_DMA_DCH: + break; + case SDD_DMA_SCH: + status = _sdd_alloc_dma_channel(); + if (status != HAL_SUCCESS) + return status; + break; + default: + return SDD_INVALID_PARAMETER; + } + + sdd.dma = sdd_dev->dma; + + /* + * Allocate mutex (a semaphore with init count == 1) + * for driver access control + */ + status = hal_create_mutex(&sdd.semaphore, "sdd_sem"); + if (status != HAL_SUCCESS) { + + SDD_TRACE(("Failed to create SD driver semaphore!\r\n")); + return status; + } + + /* + * Allocate synchronization object for SDD to receive DMA completion notfication + * (init count is 0 so any obtain have to wait first) + */ + status = hal_create_semaphore(&sdd.dma_sem, 0, 0); + if (status != HAL_SUCCESS) { + + SDD_TRACE(("Failed to allocate SD driver dma semaphore!\r\n")); + hal_destroy_mutex(&sdd.semaphore); + return status; + } + + /* Register LISR to receive SDC events */ + if (sdd.lisr_registered == 0) { + + /* Register LISR for SDC events interrupt */ + status = hal_register_isr(IRQ_SDC_VECTOR, _sdd_lisr, (void*)0); + + if (status != HAL_SUCCESS) { + + SDD_TRACE(("Failed to register SD driver LISR!\r\n")); + hal_destroy_mutex(&sdd.semaphore); + hal_destroy_semaphore(&sdd.dma_sem); + return status; + } + + sdd.lisr_registered = 1; + } + + /* Register HISR to perform deferred SDC ISR tasks */ + if (sdd.hisr_registered == 0) { + sdd.hisr.th.fn = _sdd_hisr; + sdd.hisr.th.arg = &sdd.hisr; + sdd.hisr.th.ptos = &sdd_hisr_stack[SDD_HISR_STACK_SIZE]; + sdd.hisr.th.stack_size = sizeof(sdd_hisr_stack); + sdd.hisr.th.prio = CONFIG_SDD_HISR_PRIORITY; + sdd.hisr.th.name = "SD BH"; + + status = hal_create_bh(&sdd.hisr); + if (status != HAL_SUCCESS) { + DEBUG(1, 1, "Failed to create SD driver HISR!\r\n"); + hal_destroy_mutex(&sdd.semaphore); + hal_destroy_semaphore(&sdd.dma_sem); + return status; + } + sdd.hisr_registered = 1; + } + + /* Update driver data */ +#if (SDD_VFS_SUPPORT) + // Init SDD-specific bdev object + sdd_bdev.next = HAL_NULL; + sdd_bdev.dev_id = 0; + sdd_bdev.vol_id = 0; + sdd_bdev.type = 0; + sdd_bdev.start = 0; + sdd_bdev.blocks = 0; + sdd_bdev.propagate_event = HAL_NULL; + sdd_bdev.read_sectors = _sdd_read_sectors_bdev; + sdd_bdev.write_sectors = _sdd_write_sectors_bdev; + sdd_dev->bdev_id = &sdd_bdev; +#endif // SDD_VFS_SUPPORT + + /* + * Initialize SDC device + * + * SD card initialization and identification are performed either at + * - when the card was inserted (i.e., triggered from ISR and HISR), or + * - when this init routine was invoked and the card was already in the slot. + */ + + /* Disable CPU interrupt */ + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* - Disable SDC interrupt */ + hal_intc_irq_disable(IRQ_SDC_VECTOR); + + /* - Clear SDC interrupt status */ + hal_intc_irq_clean(IRQ_SDC_VECTOR); + + /* - Setup SDC interrupt trigger mode - level trigger */ + /* - Setup SDC interrupt trigger level - assert high */ + hal_intc_irq_config(IRQ_SDC_VECTOR,IRQ_LEVEL_TRIGGER, IRQ_ACTIVE_HIGH); + + /* - Enable SDC interrupt */ + hal_intc_irq_enable(IRQ_SDC_VECTOR); + +#if 0 +#if(NO_EXTERNAL_INT_CTL==1) + /* FIXME + * - Setup SDC interrupt trigger mode */ + /* - Enable SDC interrupt */ + SR_SETB32(NDS32_SR_INT_MASK2,IRQ_SDC_VECTOR ); +#else + /* INTC */ + /* - Disable SDC interrupt */ + CLRB32(INTC_HW1_ER, IRQ_SDC_VECTOR); + + /* - Clear SDC interrupt status */ + SETB32(INTC_HW1_CLR, IRQ_SDC_VECTOR); + + /* - Setup SDC interrupt trigger mode - level trigger */ + CLRB32(INTC_HW1_TMR, IRQ_SDC_VECTOR); + + /* - Setup SDC interrupt trigger level - assert high */ + CLRB32(INTC_HW1_TLR, IRQ_SDC_VECTOR); + + /* - Enable SDC interrupt */ + SETB32(INTC_HW1_ER, IRQ_SDC_VECTOR); +#endif +#endif + + /* APBMCLKOFF */ + /* todo */ + + /* + * SDC_PWR_CTL + * SD_POWER 0 (default: 0x00) (leave bootup default?) + * SD_POWER_ON 0 (off) (default: 0x10) + */ + CLRB32(SDC_PWR_CTL, SDC_SD_POWER_ON_BIT); + _nds_kwait(0x4000); + + /* + * SDC_CLK_CTL + * CLK_DIV 0x7f (default: 0x7f, result in 97.66K ~ 683.59K SD bus freq) + * CLK_SD 1 (default: 1 (SD)) + * CLK_DIS 1 (off) (default: 0x01) + */ + OUT32(SDC_CLK_CTL, (SDC_CLK_OFF << SDC_CLK_DIS_BIT) | + (SDC_CLK_SD << SDC_CLK_SD_BIT) | SDC_CLK_DIV_MASK); + + /* + * SDC_MASK (note: spec "mask" means "enable", spec uses wrong term to describe this register) + * RSP_CRC_FAIL mask int + * DATA_CRC_FAIL mask int + * RSP_TIMEOUT mask int + * DATA_TIMEOUT mask int + * RSP_CRC_OK mask int + * DATA_CRC_OK mask int + * CMD_SENT mask int + * DATA_END mask int + * FIFO_U_RUN mask int + * FIFO_O_RUN mask int + * CARD_CHANGE enable int + */ + OUT32(SDC_MASK, SDC_CARD_CHANGE_MASK); + + /* SDC_CLEAR */ + /* Clear all */ + OUT32(SDC_CLEAR, SDC_CLEAR_ALL); + + /* + * Following host controller register register setting needs information + * from the card, hence is postponed in the card initialization and + * identification routine. + * + * Data setup (need CSD/SCR) + * + * SDC_DATA_CR (setup before data transfer) + * SDC_DATA_TIMER (TAAC/NSAC) + * SDC_DATA_LEN (READ/WRITE/ERASE_BL_LEN, SECTOR_SIZE) + * SDC_BUS_WIDTH (SCR::SD_BUS_WIDTHS) + * + * Power/Clock settings (need OCR) + * + * SDC_PWR_CTL (OCR::Vdd) + * SDC_CLK_CTL (fod, fpp) + */ + + /* + * Detect card and perform card-detection initialization, if the is + * already in the slot before we re-enable interrupt. + */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) { + /* Perform card-remove tasks (turn off clock ...) */ + SDD_TRACE(("SD card is not in slot!\r\n")); + _sdd_cd_reset(HAL_FALSE); + } + else { + /* Reset card and get device parameters */ + SDD_TRACE(("SD card is in slot!\r\n")); + _sdd_cd_reset(HAL_TRUE); + //_sdd_cd_reset(HAL_TRUE); + //_sdd_cd_reset(HAL_TRUE); + //_sdd_cd_reset(HAL_TRUE); + // FIXME + } + + /* Restore CPU interrupt controller to previous level */ + hal_global_int_ctl(core_intl); + + /* Mark driver state as valid */ + sdd.valid = 1; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_unload + * + * DESCRIPTION + * + * Remove all the device resource so the driver could be removed safely. + * + * NOTE + * + * INPUTS + * + * none + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_unload(void) +{ + uint32_t status; + +#if (!SDD_SMALL_FOOTPRINT) + /* Validate to terminate an already initialized driver state */ + if (sdd.valid == 0) + return HAL_ERR_INVALID_DRIVER; +#endif /* (!SDD_SMALL_FOOTPRINT) */ + + // Notify file system +#if (SDD_VFS_SUPPORT) + if (sdd_bdev.propagate_event != HAL_NULL) + sdd_bdev.propagate_event(&sdd_bdev, NDSBDEV_DEVICE_UNPLUG, HAL_NULL); + + sdd_bdev.next = HAL_NULL; + sdd_bdev.dev_id = 0; + sdd_bdev.vol_id = 0; + sdd_bdev.type = 0; + sdd_bdev.start = 0; + sdd_bdev.blocks = 0; + sdd_bdev.propagate_event = HAL_NULL; + sdd_bdev.read_sectors = HAL_NULL; + sdd_bdev.write_sectors = HAL_NULL; +#endif // SDD_VFS_SUPPORT + /* Shutdown device operation */ + + /* Release driver resources */ + if (sdd.dma == SDD_DMA_SCH) + _sdd_free_dma_channel(); + + status = hal_destroy_bh(&sdd.hisr); + if (status != HAL_SUCCESS) + return status; + + status = hal_destroy_semaphore(&sdd.dma_sem); + if (status != HAL_SUCCESS) + return status; + + status = hal_destroy_mutex(&sdd.semaphore); + if (status != HAL_SUCCESS) + return status; + + sdd.valid = 0; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_lock + * + * DESCRIPTION + * + * Obtain exclusive access to the devcie driver. + * + * NOTE + * + * INPUTS + * + * none + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static inline uint32_t _sdd_lock(void) +{ +#if (!SDD_SMALL_FOOTPRINT) + if (sdd.valid == 0) + return HAL_ERR_INVALID_DRIVER; +#endif /* (!SDD_SMALL_FOOTPRINT) */ + + return hal_wait_for_mutex(&sdd.semaphore, HAL_SUSPEND); +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_unlock + * + * DESCRIPTION + * + * Release exclusive access to the device driver. + * + * NOTE + * + * INPUTS + * + * none + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static inline uint32_t _sdd_unlock(void) +{ +#if (!SDD_SMALL_FOOTPRINT) + if (sdd.valid == 0) + return HAL_ERR_INVALID_DRIVER; +#endif /* (!SDD_SMALL_FOOTPRINT) */ + + return hal_release_mutex(&sdd.semaphore); +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_read_sectors + * + * DESCRIPTION + * + * Read sectors of data from the card. This is the DMA/PIO mode data- + * read dispatch function for client IOCTL request. + * + * NOTE + * + * INPUTS + * + * iop : pointer to SDD_IOCTL_READ_SECTORS_PARAM struct which + * specifies the IOCTL parameters. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_read_sectors(SDD_IOCTL_READ_SECTORS_PARAM * iop) +{ + uint32_t sector = iop->lba_sector; + uint32_t sector_cnt = iop->sector_count; + uint8_t *io_buff = (uint8_t *) iop->io_buff; + uint32_t status; + uint32_t core_intl; + uint32_t rca = 0; + + SDD_TRACE(("\r\n_sdd_read_sectors\r\n")); + + /* Disable CPU interrupt */ + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Check if SD card has been initialized to transfer state */ + rca = sdd.card_desc.rca; + + /* Restore CPU interrupt controller to previous level */ + hal_global_int_ctl(core_intl); + + /* Reject if SD card is not initialized to transfer state */ + if (rca == 0) + return SDD_INVALID_INIT; + + /* Data transfer ... */ + if ((sdd.dma != SDD_DMA_NONE) /* && (hal_current() != HAL_NULL) */ ) { + SDD_TRACE(("dma - sector(%ld) counts(%ld)\r\n", sector, + sector_cnt)); + + if (sdd.dma == SDD_DMA_DCH) { + + status = _sdd_alloc_dma_channel(); + if (status != HAL_SUCCESS) + return status; + } + + while (sector_cnt > 0) { + /* + * SDC data length register max is 24 bits (32768 sectors). + * Divided by 2 for safe in case sector size is larger than 512 bytes. + * (so max sector size should be less than 1024 bytes) + */ + if (sector_cnt >= 16384) { + + /* Use SD multiple block transfer for sectors. */ + status = _sdd_read_sectors_dma(sector, 16384, io_buff); + + if (status != HAL_SUCCESS) { + + /* Release DMA channel */ + if (sdd.dma == SDD_DMA_DCH) + _sdd_free_dma_channel(); + return status; + } + + sector += 16384; + sector_cnt -= 16384; + io_buff += SDD_SECTOR_SIZE * 16384; + } + else { + /* Use SD multiple block transfer for all sectors. */ + status = _sdd_read_sectors_dma(sector, sector_cnt, io_buff); + sector_cnt = 0; + } + } + + /* Wait for DMA completion signal */ + + /* Release DMA channel */ + if (sdd.dma == SDD_DMA_DCH) + _sdd_free_dma_channel(); + } + else { + /* PIO mode data transfer */ + SDD_TRACE(("pio - sector(%ld) counts(%ld)\r\n", sector, sector_cnt)); + + while (sector_cnt > 0) { + /* + * SDC data length register max is 24 bits (32768 sectors). + * Divided by 2 for safe in case sector size is larger than 512 bytes. + * (so max sector size should be less than 1024 bytes) + */ + if (sector_cnt >= 16384) { + /* Use SD multiple block transfer for sectors. */ + status = _sdd_read_sectors_pio(sector, 16384, io_buff); + + if (status != HAL_SUCCESS) + return status; + + sector += 16384; + sector_cnt -= 16384; + io_buff += SDD_SECTOR_SIZE * 16384; + } + else { + /* Use SD multiple block transfer for all sectors. */ + status = _sdd_read_sectors_pio(sector, sector_cnt, io_buff); + sector_cnt = 0; + } + } + } + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_write_sectors + * + * DESCRIPTION + * + * Write sectors of data to the card. This is the DMA/PIO mode data- + * write dispatch function for client IOCTL request. + * + * NOTE + * + * INPUTS + * + * iop : pointer to SDD_IOCTL_READ_SECTORS_PARAM struct which + * specifies the IOCTL parameters. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static uint32_t _sdd_write_sectors(SDD_IOCTL_WRITE_SECTORS_PARAM * iop) +{ + uint32_t sector = iop->lba_sector; + uint32_t sector_cnt = iop->sector_count; + uint8_t *io_buff = (uint8_t *) iop->io_buff; + uint32_t status; + uint32_t core_intl; + uint32_t rca = 0; + + SDD_TRACE(("\r\n_sdd_write_sectors\r\n")); + + /* Disable CPU interrupt */ + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Check if SD card has been initialized to transfer state */ + rca = sdd.card_desc.rca; + + /* Restore CPU interrupt controller to previous level */ + hal_global_int_ctl(core_intl); + + /* Reject if SD card is not initialized to transfer state */ + if (rca == 0) + return SDD_INVALID_INIT; + + /* Data transfer ... */ + if ((sdd.dma != SDD_DMA_NONE) /* && (hal_current() != HAL_NULL) */ ) { + SDD_TRACE(("dma - sector(%ld) counts(%ld)\r\n", sector, + sector_cnt)); + + if (sdd.dma != SDD_DMA_SCH) { + + status = _sdd_alloc_dma_channel(); + if (status != HAL_SUCCESS) + return status; + } + + while (sector_cnt > 0) { + /* + * SDC data length register max is 24 bits (32768 sectors). + * Divided by 2 for safe in case sector size is larger than 512 bytes. + * (so max sector size should be less than 1024 bytes) + */ + if (sector_cnt >= 16384) { + /* Use SD multiple block transfer for sectors. */ + status = _sdd_write_sectors_dma(sector, 16384, io_buff); + + if (status != HAL_SUCCESS) { + + if (sdd.dma == SDD_DMA_DCH) + _sdd_free_dma_channel(); + + return status; + } + + sector += 16384; + sector_cnt -= 16384; + io_buff += SDD_SECTOR_SIZE * 16384; + } + else { + /* Use SD multiple block transfer for all sectors. */ + status = _sdd_write_sectors_dma(sector, sector_cnt, io_buff); + sector_cnt = 0; + } + } + + /* Wait for DMA completion signal */ + + /* Release DMA channel */ + if (sdd.dma == SDD_DMA_DCH) + _sdd_free_dma_channel(); + } + else { + /* PIO mode data transfer */ + SDD_TRACE(("pio - sector(%ld) counts(%ld)\r\n", sector, + sector_cnt)); + + while (sector_cnt > 0) { + /* + * SDC data length register max is 24 bits (32768 sectors). + * Divided by 2 for safe in case sector size is larger than 512 bytes. + * (so max sector size should be less than 1024 bytes) + */ + if (sector_cnt >= 16384) { + /* Use SD multiple block transfer for sectors. */ + status = _sdd_write_sectors_pio(sector, 16384, io_buff); + + if (status != HAL_SUCCESS) + return status; + + sector += 16384; + sector_cnt -= 16384; + io_buff += SDD_SECTOR_SIZE * 16384; + } + else { + /* Use SD multiple block transfer for all sectors. */ + status = _sdd_write_sectors_pio(sector, sector_cnt, io_buff); + sector_cnt = 0; + } + } + } + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sdd_ioctl + * + * DESCRIPTION + * + * This function execute I/O control commands to SDC driver. + * + * NOTE + * + * + * INPUTS + * + * driver : device object/control_block + * request : request function and supplemental parameters + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +static inline uint32_t _sdd_ioctl(uint32_t ioctl, void *param) +{ + uint32_t status = HAL_SUCCESS; + +#if (!SDD_SMALL_FOOTPRINT) + /* Validate to terminate an already initialized driver state */ + if (sdd.valid == 0) + return HAL_ERR_INVALID_DRIVER; +#endif /* (!UARTD_SMALL_FOOTPRINT) */ + + if (param == HAL_NULL) + return SDD_INVALID_PARAMETER; + + switch (ioctl) { + case SDD_IOCTL_READ_SECTORS: + /* Parameter: pointer to SDD_IOCTL_READ_SECTORS_PARAM struct */ + status = _sdd_read_sectors((SDD_IOCTL_READ_SECTORS_PARAM *) param); + break; + + case SDD_IOCTL_WRITE_SECTORS: + /* Parameter: pointer to SDD_IOCTL_READ_SECTORS_PARAM struct */ + status = _sdd_write_sectors((SDD_IOCTL_WRITE_SECTORS_PARAM *) param); + break; + + default: + status = SDD_INVALID_IOCTL; + break; + } + + return status; +} + +/***************************************************************************** + * FUNCTION + * + * NDS_SD_Init + * + * DESCRIPTION + * + * This function initializes the SD device. + * + * INPUTS + * + * sdd_dev : User mode SDD device structure. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else a negative value is returned. + * + ****************************************************************************/ +uint32_t NDS_SD_Init(SDD_DEVICE * sdd_dev) +{ + return _sdd_init(sdd_dev); +} + +/***************************************************************************** + * FUNCTION + + * NDS_SD_Unload + * + * DESCRIPTION + * + * This function terminates all SD transaction and unload the driver. + * + * INPUTS + * + * None. + * + * OUTPUTS + * + * None. + * + ****************************************************************************/ +void NDS_SD_Unload() +{ + _sdd_unload(); +} + +/***************************************************************************** + * FUNCTION + * + * NDS_SD_ReadSectors + * + * DESCRIPTION + * + * This function read sectors of data from the SD memory card. + * + * INPUTS + * + * sdd_dev : User mode SDD device structure. + * sector : The starting LBA sector number. + * sector_count : Number of sectors to read. + * sector_size : Size of a sector in bytes. + * buffer : Pointer to a user buffer to hold the readback data. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else a negative value is returned. + * + ****************************************************************************/ +uint32_t NDS_SD_ReadSectors(SDD_DEVICE * sdd_dev, uint32_t sector, + uint32_t sector_count, uint32_t sector_size, + void *buffer) +{ + uint32_t status; + uint32_t io_status; + SDD_IOCTL_READ_SECTORS_PARAM iop; + + status = _sdd_lock(); + if (status != HAL_SUCCESS) + hal_system_error(status); + + iop.lba_sector = sector; + iop.sector_count = sector_count; + iop.sector_size = sector_size; + iop.io_buff = buffer; + + io_status = _sdd_read_sectors(&iop); + + status = _sdd_unlock(); + if (status != HAL_SUCCESS) + hal_system_error(status); + + return io_status; +} + +/***************************************************************************** + * FUNCTION + * + * NDS_SD_WriteSectors + * + * DESCRIPTION + * + * This function write sectors of data to the SD memory card. + * + * INPUTS + * + * sdd_dev : User mode SDD device structure. + * sector : The starting LBA sector number. + * sector_count : Number of sectors to write. + * sector_size : Size of a sector in bytes. + * buffer : Pointer to a user buffer of data to be written to the card. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful initialization, + * else a negative value is returned. + * + ****************************************************************************/ +uint32_t NDS_SD_WriteSectors(SDD_DEVICE * sdd_dev, uint32_t sector, + uint32_t sector_count, uint32_t sector_size, + void *buffer) +{ + uint32_t status; + uint32_t io_status; + SDD_IOCTL_WRITE_SECTORS_PARAM iop; + status = _sdd_lock(); + if (status != HAL_SUCCESS) + hal_system_error(status); + + iop.lba_sector = sector; + iop.sector_count = sector_count; + iop.sector_size = sector_size; + iop.io_buff = buffer; + + io_status = _sdd_write_sectors(&iop); + + status = _sdd_unlock(); + if (status != HAL_SUCCESS) + hal_system_error(status); + + return io_status; +} diff --git a/bsp/AE210P/driver/sd/sdd.h b/bsp/AE210P/driver/sd/sdd.h new file mode 100644 index 0000000000000000000000000000000000000000..bde31dd0b24182bc30f9c929043131ef343432ee --- /dev/null +++ b/bsp/AE210P/driver/sd/sdd.h @@ -0,0 +1,219 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Aug.21.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sdd.h + * + * DESCRIPTION + * + * SD driver implementation kernel mode header file. + * (Nucleus I/O Driver Architecture) + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * sd.h SD driver interface exported to user applications + * ag101regs.h SoC register address header file + * ag101defs.h SoC register constant definition header file + * + ****************************************************************************/ +#ifndef __SDD_H__ +#define __SDD_H__ + +#include +#include +#include "sd.h" + +/* configuration section */ +/* Note: SD clock -- please check "ag101defs.h". */ +#define SDD_SMALL_FOOTPRINT 0 /* non-zero to disable extra features for small footprint */ +#define SDD_SMALL_SD_FOOTPRINT 0 /* non-zero to skip compiling and linking of unsed SD command routines. */ +#define SDD_DEBUG_TRACE 0 /* non-zero to enable debug trace message */ +#define SDD_VFS_SUPPORT 1 /* non-zero to enable VFS support */ + +/* Define sector size that should be common for all file systems. */ +/* Todo: Check if this the common case. */ +#define SDD_SECTOR_SIZE 512 +#define SDD_POWER_OF_SECTOR_SIZE 9 +#define SDD_BYTES_TO_SECTORS(b) ((uint32_t)(b) >> 9) + +/* SDD enums */ +typedef enum _SDD_CARD_SPEC { + + SDD_SPEC_1XX, /* the card is a spec 1.x implementation */ + SDD_SPEC_200 /* the card is a spec 2.0 implementation */ + +} SDD_CARD_SPEC; + +typedef enum _SDD_CARD_CCS { + + SDD_CCS_SD, /* the card is a standard capacity card */ + SDD_CCS_SDHC /* the card is a high capacity card */ + +} SDD_CARD_CCS; + +typedef enum _SDD_VDD_WINDOW { + + SDD_VDD_2_7 = 0x00008000, /* VDD 2.7 ~ 2.8 */ + SDD_VDD_2_8 = 0x00010000, /* VDD 2.8 ~ 2.9 */ + SDD_VDD_2_9 = 0x00020000, /* VDD 2.9 ~ 3.0 */ + SDD_VDD_3_0 = 0x00040000, /* VDD 3.0 ~ 3.1 */ + SDD_VDD_3_1 = 0x00080000, /* VDD 3.1 ~ 3.2 */ + SDD_VDD_3_2 = 0x00100000, /* VDD 3.2 ~ 3.3 */ + SDD_VDD_3_3 = 0x00200000, /* VDD 3.3 ~ 3.4 */ + SDD_VDD_3_4 = 0x00400000, /* VDD 3.4 ~ 3.5 */ + SDD_VDD_3_5 = 0x00800000, /* VDD 3.5 ~ 3.6 */ + +} SDD_VDD_WINDOW; + +/* + * SD card device parameters + * Note: + * 1. This struct supports a single card. + * 2. Watch out 32-bit alignment after remarking unnecessary fields. + */ +typedef struct _SDD_CARD_DESC { + + /* OCR (acmd41) */ + uint8_t version; /* one of the enum value of SDD_CARD_SPEC */ + uint8_t card_ccs; /* one of the enum value of SDD_CARD_CCS */ + uint8_t padding1[2]; + uint32_t vdd_window; /* one of the mask bits defined in SDD_VDD_WINDOW */ + + /* CID (cmd2) */ + uint8_t mfg_id; /* Manufacturer ID */ + char oem_id[3]; /* OEM/Application ID (2 char + 1 null-sz) */ + char prod_name[6]; /* Product name (5 char + 1 null-sz) */ + char prod_rev[4]; /* Product revision (x.y + 1 null-sz) */ + uint8_t padding2[2]; + uint32_t prod_sn; /* Product serial number */ + uint16_t mfg_year; /* Manufacturing date */ + uint16_t mfg_month; + + /* RCA (cmd3) */ + uint32_t rca; /* [31:16] RCA, [15:0] zero. */ + + /* + * Driver will check this before data transfer. */ + /* CSD (cmd9) */ + /* Todo: This is a tedious list and most fields are only for information purpose. */ + /* Remove unnecessary fields after debugging. */ + uint8_t csd_ver; /* CSD version */ + uint8_t padding3[3]; + + uint32_t async_access_time; /* data read access time 1 (TAAC, x10, unit of ns) (2.0 is fixed value) */ + uint32_t read_access_clks; /* data read access time 2 (NSAC, clock cycles) (2.0 is fixed value) */ + uint32_t prog_factor; /* multiplication factor of time for typical block program (2.0 is fixed value) */ + uint32_t max_dataline_rate; /* max data transfer rate (unit of kbps) (2.0 is fixed value) */ + + uint32_t cmd_class; /* card command classes */ + + uint16_t max_read_block_len; /* read block length in bytes (2.0 is fixed value) */ + uint8_t partial_block_read; /* non-zero if the card supports small block size (minimum to 1 bytes) (2.0 is fixed value) */ + uint8_t read_block_misalign; /* capability to read accross physical blocks (2.0 is fixed value) */ + + uint16_t max_write_block_len; /* write block length in bytes (2.0 is fixed value) */ + uint8_t partial_block_write; /* non-zero if the card supports small block size (minimum to 1 bytes) (2.0 is fixed value) */ + uint8_t write_block_misalign; /* capability to write accross physical blocks (2.0 is fixed value) */ + + uint8_t erase_single_block; /* non-zero if able to erase single block (2.0 is fixed value) */ + uint8_t erase_sector_size; /* erase unit, number of write block size (not the meaning of disk sectors) (2.0 is fixed value) */ + uint8_t file_format; /* enum of SDD_FILE_FORMAT (2.0 is fixed value) */ + uint8_t padding4; + + uint8_t wp_group_size; /* write protect group size, number of erase sector size. (2.0 is fixed value) */ + uint8_t wp_group_enable; /* zero means no group write protection possible (2.0 is fixed value) */ + uint8_t wp_permanent; /* card is permanently write protected */ + uint8_t wp_temp; /* card is temporarily write protected */ + + uint8_t copy; /* indicates if the content is original (0) or copied (1 for OTP/MTP devices) */ + uint8_t dsr_imp; /* non-zero if configurable driver stage register is supported */ + uint32_t c_size; /* C_SIZE */ + uint32_t c_size_mult; /* C_SIZE_MULT (2.0 is obsolete) */ + +#if 0 + uint8_t max_c_read_at_vdd_min; /* max read current at vdd min (2.0 is obsolete) */ + uint8_t max_c_read_at_vdd_max; /* max read current at vdd max (2.0 is obsolete) */ + uint8_t max_c_write_at_vdd_min; /* max write current at vdd min (2.0 is obsolete) */ + uint8_t max_c_write_at_vdd_max; /* max write current at vdd max (2.0 is obsolete) */ +#endif + + /* SCR (acmd51) */ + uint8_t scr_ver; /* SCR version */ + uint8_t spec_ver; /* SD memory card spec version */ + uint8_t erase_val; /* data status after erase (0 or 1) */ + uint8_t security_ver; /* security specification version */ + uint8_t bus_width; /* data bus width, 1 or 4. */ + + /* derived fields */ + uint32_t card_capacity; /* card size, in unit of 512-bytes */ + uint32_t sdc_clk_div; /* clock division value to setup SDC SDC_CLK_DIV register */ + uint32_t sdc_clk_freq; /* SDC clock frequency (info only) */ + uint32_t read_timeout_clks; /* read timeout value to setup SDC DATA_TIMER register (fixed 100ms for SDHC) */ + uint32_t write_timeout_clks; /* write timeout value to setup SDC DATA_TIMER register (fixed 250ms for SDHC) */ + +} SDD_CARD_DESC; + +/* HISR definitions */ +#define SDD_HISR_PRIORITY 0 /* 0: highest, 2: lowest */ +#define SDD_HISR_STACK_SIZE 2048 /* Please align to 32-bit */ + +enum SDD_HISR_AS { + + SDD_HISR_AS_CD = 0x00000001, /* Card Detect */ + +}; + +/* Driver data structure, one instance per system */ +typedef struct SDD_DATA_STRUCT { + + uint8_t valid; /* Indicates whether the device driver is instanciated or not */ + uint8_t lisr_registered; /* SD cd LISR registeration status */ + uint8_t hisr_registered; /* SD cd HISR registeration status */ + uint8_t dma; /* One of the enum value in SDD_DMA_MODE for SD data transfer */ + + SDD_CARD_DESC card_desc; /* SD card parameters obtained from various card registers. */ + + hal_mutex_t semaphore; /* control exclusive access to driver */ + hal_semaphore_t dma_sem; /* obtain dma completion notification from DMA hisr */ + + /* HISR resources */ + hal_bh_t hisr; /* HISR kernel object, used to perform deffered tasks of LISR */ + uint32_t hisr_as; /* HISR activation state (for the single HISR to identify why activated it) */ + + /* DMA resources */ + DMAD_CHANNEL_REQUEST_DESC dma_ch; /* DMA channel descriptor initialized before data transfer */ + +} SDD_DATA; + +/* Driver-occupied memory pool definitions */ +#define SDD_MEM_POOL_BASE_SIZE 40960 /* base pool size for driver before counting size of ? */ +#define SDD_MEM_ALLOC_GRANULARITY 8 + +/* Debug trace mechanism */ +#if (SDD_DEBUG_TRACE) + +#define SDD_TRACE(x) printf x +#define SDD_STRACE(x) printf x + +#else /* SDD_DEBUG_TRACE */ + +#define SDD_TRACE(x) +#define SDD_STRACE(x) + +#endif /* SDD_DEBUG_TRACE */ + +#endif /* __SDD_H__ */ diff --git a/bsp/AE210P/driver/sd/sdd_sd.c b/bsp/AE210P/driver/sd/sdd_sd.c new file mode 100644 index 0000000000000000000000000000000000000000..f557fa569b5616bb1b9e1d4f58487777496115b2 --- /dev/null +++ b/bsp/AE210P/driver/sd/sdd_sd.c @@ -0,0 +1,2662 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Sep.26.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sdd_sd.c + * + * DESCRIPTION + * + * Secure digital card specification 2.0 definition. + * + * Currently only Secure Digital Memory standards are well-defined. + * Remaining spec mostly are left for future developers. + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * None + * + ****************************************************************************/ +#include "sdd.h" +#include "sdd_sd.h" + +/* + * If SDD_SMALL_FOOTPRINT is defined, SD command routines are defined as + * macros which will be redirect to a general command issuing routine. + * + * If performance is required, set SDD_SMALL_FOOTPRINT to 0. The SD command + * issuing routines are then a set of expanded code. + */ +#if (SDD_SMALL_FOOTPRINT) +#define SDC_INLINE static _inline +#else /* SDD_SMALL_FOOTPRINT */ +#define SDC_INLINE static +#endif /* SDD_SMALL_FOOTPRINT */ + +/* Local Helper Routines */ +SDC_INLINE uint32_t _sd_cmd(uint32_t cmd) +{ + uint32_t retry_cnt = 0; + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Clear SDC status bits */ + OUT32(SDC_CLEAR, SDC_RSP_CRC_FAIL_MASK | SDC_RSP_TIMEOUT_MASK | + SDC_RSP_CRC_OK_MASK | SDC_CMD_SENT_MASK); + /*OUT32(SDC_CLEAR, SDC_CLEAR_ALL); */ + + /* Send command */ + OUT32(SDC_CMD, cmd); + + /* Wait until the command is on the way to the card ... */ + while (retry_cnt++ < SD_CMD_MAX_RETRY_COUNT) { + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Get new status of SDC */ + if (GETB32(SDC_STATUS, SDC_SR_CMD_SENT_BIT) != 0) + return HAL_SUCCESS; + } + + return SDD_CMD_TIMEOUT; +} + +SDC_INLINE uint32_t _sd_cmd_arg(uint32_t cmd, uint32_t arg) +{ + uint32_t retry_cnt = 0; + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Clear SDC status bits */ + OUT32(SDC_CLEAR, SDC_RSP_CRC_FAIL_MASK | SDC_RSP_TIMEOUT_MASK | + SDC_RSP_CRC_OK_MASK | SDC_CMD_SENT_MASK); + /*OUT32(SDC_CLEAR, SDC_CLEAR_ALL); */ + + /* Prepare Argument */ + OUT32(SDC_CMD_ARG, arg); + + /* Send command */ + OUT32(SDC_CMD, cmd); + + /* Wait until the command is on the way to the card ... */ + while (retry_cnt++ < SD_CMD_MAX_RETRY_COUNT) { + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Get new status of SDC */ + if (GETB32(SDC_STATUS, SDC_SR_CMD_SENT_BIT) != 0) + return HAL_SUCCESS; + } + + return SDD_CMD_TIMEOUT; +} + +SDC_INLINE uint32_t _sd_cmd_r32(uint32_t cmd, SD_R32 * rsp) +{ + uint32_t retry_cnt = 0; + uint32_t sdc_sr = 0; + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Clear SDC status bits */ + OUT32(SDC_CLEAR, SDC_RSP_CRC_FAIL_MASK | SDC_RSP_TIMEOUT_MASK | + SDC_RSP_CRC_OK_MASK | SDC_CMD_SENT_MASK); + /*OUT32(SDC_CLEAR, SDC_CLEAR_ALL); */ + + /* Send command */ + OUT32(SDC_CMD, cmd); + + /* Wait until the command is responsed ... */ + while (retry_cnt++ < SD_CMD_MAX_RETRY_COUNT) { + + sdc_sr = IN32(SDC_STATUS); + + /* Make sure card exists */ + if (sdc_sr & SDC_SR_CARD_DETECT_BIT) + return SDD_CARD_REMOVED; + + /* Check error status */ + if (sdc_sr & SDC_SR_RSP_CRC_OK_MASK) { + + rsp->r[0] = IN32(SDC_R0); + return HAL_SUCCESS; + } + else if (sdc_sr & SDC_SR_RSP_CRC_FAIL_MASK) { + + return SDD_RSP_CRC_ERROR; + } + else if (sdc_sr & SDC_SR_RSP_TIMEOUT_MASK) { + + return SDD_RSP_TIMEOUT; + } + } + + return SDD_CMD_TIMEOUT; +} + +SDC_INLINE uint32_t _sd_cmd_arg_r32(uint32_t cmd, uint32_t arg, SD_R32 * rsp) +{ + uint32_t sdc_sr = 0; + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Clear SDC status bits */ + OUT32(SDC_CLEAR, SDC_RSP_CRC_FAIL_MASK | SDC_RSP_TIMEOUT_MASK | + SDC_RSP_CRC_OK_MASK); + /*OUT32(SDC_CLEAR, SDC_CLEAR_ALL); */ + + /* Prepare Argument */ + OUT32(SDC_CMD_ARG, arg); + + /* Send command */ + OUT32(SDC_CMD, cmd); + + /* Wait until the command is responsed ... */ + while (1) { + +// _nds_kwait(0x1000); /* hw need delay ? */ + + sdc_sr = IN32(SDC_STATUS); + + /* Make sure card exists */ + if (sdc_sr & SDC_SR_CARD_DETECT_BIT) + return SDD_CARD_REMOVED; + + /* Check error status */ + if (sdc_sr & SDC_SR_RSP_CRC_OK_MASK) { + + rsp->r[0] = IN32(SDC_R0); + return HAL_SUCCESS; + } + else if (sdc_sr & SDC_SR_RSP_CRC_FAIL_MASK) { + + return SDD_RSP_CRC_ERROR; + } + else if (sdc_sr & SDC_SR_RSP_TIMEOUT_MASK) { + + return SDD_RSP_TIMEOUT; + } + } + + return SDD_CMD_TIMEOUT; +} + +SDC_INLINE uint32_t _sd_cmd_r128(uint32_t cmd, SD_R128 * rsp) +{ + uint32_t retry_cnt = 0; + uint32_t sdc_sr = 0; + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Clear SDC status bits */ + OUT32(SDC_CLEAR, SDC_RSP_CRC_FAIL_MASK | SDC_RSP_TIMEOUT_MASK | + SDC_RSP_CRC_OK_MASK | SDC_CMD_SENT_MASK); + /*OUT32(SDC_CLEAR, SDC_CLEAR_ALL); */ + + /* Send command */ + OUT32(SDC_CMD, cmd); + + /* Wait until the command is responsed ... */ + while (retry_cnt++ < SD_CMD_MAX_RETRY_COUNT) { + + sdc_sr = IN32(SDC_STATUS); + + /* Make sure card exists */ + if (sdc_sr & SDC_SR_CARD_DETECT_BIT) + return SDD_CARD_REMOVED; + + /* Check error status */ + if (sdc_sr & SDC_SR_RSP_CRC_OK_MASK) { + + rsp->r[0] = IN32(SDC_R0); + rsp->r[1] = IN32(SDC_R1); + rsp->r[2] = IN32(SDC_R2); + rsp->r[3] = IN32(SDC_R3); + + return HAL_SUCCESS; + } + else if (sdc_sr & SDC_SR_RSP_CRC_FAIL_MASK) { + + return SDD_RSP_CRC_ERROR; + } + else if (sdc_sr & SDC_SR_RSP_TIMEOUT_MASK) { + + return SDD_RSP_TIMEOUT; + } + } + + return SDD_CMD_TIMEOUT; +} + +SDC_INLINE uint32_t _sd_cmd_arg_r128(uint32_t cmd, uint32_t arg, SD_R128 * rsp) +{ + uint32_t retry_cnt = 0; + uint32_t sdc_sr = 0; + + /* Make sure card exists */ + if (GETB32(SDC_STATUS, SDC_SR_CARD_DETECT_BIT)) + return SDD_CARD_REMOVED; + + /* Clear SDC status bits */ + OUT32(SDC_CLEAR, SDC_RSP_CRC_FAIL_MASK | SDC_RSP_TIMEOUT_MASK | + SDC_RSP_CRC_OK_MASK | SDC_CMD_SENT_MASK); + /*OUT32(SDC_CLEAR, SDC_CLEAR_ALL); */ + + /* Prepare Argument */ + OUT32(SDC_CMD_ARG, arg); + + /* Send command */ + OUT32(SDC_CMD, cmd); + + /* Wait until the command is responsed ... */ + while (retry_cnt++ < SD_CMD_MAX_RETRY_COUNT) { + + sdc_sr = IN32(SDC_STATUS); + + /* Make sure card exists */ + if (sdc_sr & SDC_SR_CARD_DETECT_BIT) + return SDD_CARD_REMOVED; + + /* Check error status */ + if (sdc_sr & SDC_SR_RSP_CRC_OK_MASK) { + + rsp->r[0] = IN32(SDC_R0); + rsp->r[1] = IN32(SDC_R1); + rsp->r[2] = IN32(SDC_R2); + rsp->r[3] = IN32(SDC_R3); + + return HAL_SUCCESS; + } + else if (sdc_sr & SDC_SR_RSP_CRC_FAIL_MASK) { + + return SDD_RSP_CRC_ERROR; + } + else if (sdc_sr & SDC_SR_RSP_TIMEOUT_MASK) { + + return SDD_RSP_TIMEOUT; + } + } + + return SDD_CMD_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd0 + * + * DESCRIPTION + * + * This function issues SD command GO_IDLE_STATE: Reset all cards to idle + * state. + * + * Class: 0 (basic commands) + * + * State Transition: + * idle -> idle + * + * Argument: + * [31:0] stuff bits + * + * Response: + * None + * + * INPUTS + * + * None. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd0(void) +{ + return _sd_cmd(SDC_CMD0_GO_IDLE_STATE); +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd2 + * + * DESCRIPTION + * + * This function issues SD command ALL_SEND_CID: Ask any card to send the + * CID numbers + * + * Class: 0 (basic commands) + * + * State Transition: + * ready -> identification + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R2 [127:1] CID + * + * INPUTS + * + * cid : Pointer to SD_CID struct. + * + * OUTPUTS + * + * cid : SD_CID struct which holds the card's CID register value. + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd2(SD_CID * cid) +{ + return _sd_cmd_r128(SDC_CMD2_ALL_SEND_CID, cid); +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd3 + * + * DESCRIPTION + * + * This function issues SD command SEND_RELATIVE_ADDR: Ask the card to + * publish a new RCA. + * + * Class: 0 (basic commands) + * + * State Transition: + * identification -> standby + * standy -> standby + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R6 [23:08] card status bits: 23, 22, 19, 12:0 + * [39:24] New publishded RCA + * + * INPUTS + * + * rca : Pointer to SD_R32 struct to receive RCA. + * + * OUTPUTS + * + * rca : SD_R32 struct where RCA will be placed at [31:16]. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd3(SD_R32 * rca) +{ + return _sd_cmd_r32(SDC_CMD3_SEND_RELATIVE_ADDR, rca); +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd4 + * + * DESCRIPTION + * + * This function issues SD command SET_DSR: Program DSR of all cards. + * + * Class: 0 (basic commands) + * + * State Transition: + * standy -> standby + * + * Argument: + * [31:16] DSR + * + * Response: + * None + * + * INPUTS + * + * dsr : uint32_t value where DSR is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd4(uint32_t dsr) +{ + return _sd_cmd_arg(SDC_CMD4_SET_DSR, dsr); +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd7 + * + * DESCRIPTION + * + * This function issues SD command SELECT/DESELECT_CARD: Toggles between + * standby and transfer states or between programming and disconnect + * states. Cards with matching RCA is selected, otherwise deselected. + * + * Class: 0 (basic commands) + * + * State Transition: + * selected card: + * standby -> transfer + * disconnected -> programming + * deselected card + * standby -> standby + * transfer -> standby + * sending-data -> standby + * programming -> disconnected + * + * Argument: + * [31:16] RCA + * + * Response: + * R1b [39:8] card status + * DAT0 busy signal + * + * INPUTS + * + * rca : SD_R32 struct where RCA is at [31:16]. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd7(uint32_t rca, SD_R32 * csr) +{ + uint32_t status = _sd_cmd_arg_r32(SDC_CMD7_SELECT_DESELECT_CARD, rca, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd8 + * + * DESCRIPTION + * + * This function issues SD command SEND_IF_COND: Send VHS to SD card before + * issuing ACMD41 during initialization and identification process. + * + * Class: 0 (basic commands) + * + * State Transition: + * idle -> idle + * + * Argument: + * [11:8] VHS (see R7 bellow) + * [ 7:0] Arbitrary Check Pattern (10101010b(0xaa) is suggested) + * + * Response: + * R7 [19:16] voltage accepted (VHS) + * 0001b (0x01) -> 2.7-3.6v + * others are reserved or undefined + * + * INPUTS + * + * vhs_arg: uint32_t value with VHS at [11:8] and check-ptn at [7:0]. + * vhs_rsp: Pointer to SD_R32 struct to hold the response. + * + * OUTPUTS + * + * vhs_rsp: SD_R32 struct with VHS at [11:8] and check-ptn at [7:0]. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd8(uint32_t vhs_arg, SD_R32 * vhs_rsp) +{ + return _sd_cmd_arg_r32(SDC_CMD8_SEND_IF_COND, vhs_arg, vhs_rsp); +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd9 + * + * DESCRIPTION + * + * This function issues SD command SEND_CSD: Ask addressed card to send its + * CSD on the command line. + * + * Class: 0 (basic commands) + * + * State Transition: + * standby -> standby + * + * Argument: + * [31:16] RCA + * + * Response: + * R2 [127:1] CSD + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * csd : Pointer to SD_CSD struct. + * + * OUTPUTS + * + * csd : SD_CSD struct which contains CSD response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd9(uint32_t rca, SD_CSD * csd) +{ + return _sd_cmd_arg_r128(SDC_CMD9_SEND_CSD, rca, csd); +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd10 + * + * DESCRIPTION + * + * This function issues SD command SEND_CID: Ask addressed card to send its + * CID on the command line. + * + * Class: 0 (basic commands) + * + * State Transition: + * standby -> standby + * + * Argument: + * [31:16] RCA + * + * Response: + * R2 [127:1] CID + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * cid : Pointer to SD_CID struct. + * + * OUTPUTS + * + * cid : SD_CID struct which contains CID response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd10(uint32_t rca, SD_CID * cid) +{ + return _sd_cmd_arg_r128(SDC_CMD10_SEND_CID, rca, cid); +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd12 + * + * DESCRIPTION + * + * This function issues SD command STOP_TRANSMISSION: Forces the card to + * stop transmission. + * + * Class: 0 (basic commands) + * + * State Transition: + * snedning-data -> transfer + * receiving-data -> programming + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R1b [39:8] card status + * DAT0 busy signal + * + * INPUTS + * + * csr : Pointer to SD_R32 value. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd12(SD_R32 * csr) +{ + uint32_t status = _sd_cmd_r32(SDC_CMD12_STOP_TRANSMISSION, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) /* todo: ok to check all error bits */ + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd13 + * + * DESCRIPTION + * + * This function issues SD command SEND_STATUS: Ask the card to send its + * card status. + * + * Class: 0 (basic commands) + * + * State Transition: + * standby -> standby + * transfer -> transfer + * sending-data -> sending-data + * receiving-data -> receieving-data + * programming -> programming + * disconnect -> disconnect + * + * Argument: + * [31:16] RCA + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * csr : Pointer to SD_R32 to receive CSR. + * + * OUTPUTS + * + * csr : SD_R32 which holds the received CSR. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd13(uint32_t rca, SD_R32 * csr) +{ + uint32_t status = _sd_cmd_arg_r32(SDC_CMD13_SEND_STATUS, rca, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd15 + * + * DESCRIPTION + * + * This function issues SD command GO_INACTIVE_STATE: Inactivate the + * addressed card to inactive state. + * + * Class: 0 (basic commands) + * + * State Transition: + * standby -> inactive + * transfer -> inactive + * sending-data -> inactive + * receiving-data -> inactive + * programming -> inactive + * disconnect -> inactive + * + * Argument: + * [31:16] RCA + * [15: 0] Should be 0! + * + * Response: + * None + * + * INPUTS + * + * rca : uint32_t value with RCA at [31:16], 0 at [15:0]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd15(uint32_t rca) +{ + return _sd_cmd_arg(SDC_CMD15_GO_INACTIVE_STATE, rca); +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd16 + * + * DESCRIPTION + * + * This function issues SD command SET_BLOCKLEN: Set block length (bytes) + * for standard capacity SD cards. SDHC is fixed to 512 bytes and ignores + * this field except the LOCK_UNLOCK command. + * + * Class: 2/4/7 (block-oriented read/write/lock_unlock commands) + * + * State Transition: + * transfer -> transfer + * + * Argument: + * [31:0] block length + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * blk_len: uint32_t block length value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd16(uint32_t blk_len, SD_R32 * csr) +{ + uint32_t status = _sd_cmd_arg_r32(SDC_CMD16_SET_BLOCKLEN, blk_len, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd17 + * + * DESCRIPTION + * + * This function issues SD command READ_SINGLE_BLOCK: Reads a single block + * size of data. + * + * Class: 2 (block-oriented read commands) + * + * State Transition: + * transfer -> sending-data + * + * Argument: + * [31:0] data address (byte-unit for SD, block unit for SDHC) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd17(uint32_t addr, SD_R32 * csr) +{ +#if 0 + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { +#endif + /* Send SD command */ + uint32_t status = + _sd_cmd_arg_r32(SDC_CMD17_READ_SINGLE_BLOCK, addr, csr); + if (status != HAL_SUCCESS) { + return status; + } + + /* Check error status */ + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; +#if 0 + /* Check whether make transition to sending-data state */ + switch (SD_CSR_GET_CURRENT_STATE(*csr)) { + case SD_STATE_DATA: + /* The card is ready to send out data */ + return HAL_SUCCESS; + case SD_STATE_TRAN: + /* Repeat previous command until the card get to the state */ + break; + case SD_STATE_STBY: + case SD_STATE_RCV: + case SD_STATE_PRG: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DIS: + default: + /* Invalid current state before deselecting the card. */ + return SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +#else + return HAL_SUCCESS; +#endif +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd18 + * + * DESCRIPTION + * + * This function issues SD command READ_MULTIPLE_BLOCK: Reads blocks of data + * from card continuously until a STOP_TRANSMISSION command. + * + * Class: 2 (block-oriented read commands) + * + * State Transition: + * transfer -> sending-data + * + * Argument: + * [31:0] data address (byte-unit for SD, block unit for SDHC) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd18(uint32_t addr, SD_R32 * csr) { +#if 0 + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { +#endif + /* Send SD command */ + uint32_t status = + _sd_cmd_arg_r32(SDC_CMD18_READ_MULTIPLE_BLOCK, addr, + csr); + if (status != HAL_SUCCESS) { + return status; + } + + /* Check error status */ + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; +#if 0 + /* Check whether make transition to sending-data state */ + switch (SD_CSR_GET_CURRENT_STATE(*csr)) { + case SD_STATE_DATA: + /* The card is ready to send out data */ + return HAL_SUCCESS; + case SD_STATE_TRAN: + /* Repeat previous command until the card get to the state */ + break; + case SD_STATE_STBY: + case SD_STATE_RCV: + case SD_STATE_PRG: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DIS: + default: + /* Invalid current state before deselecting the card. */ + return SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +#else + return HAL_SUCCESS; +#endif +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd24 + * + * DESCRIPTION + * + * This function issues SD command WRITE_SINGLE_BLOCK: Writes a single + * block size of data. + * + * Class: 2 (block-oriented write commands) + * + * State Transition: + * transfer -> receiving-data + * + * Argument: + * [31:0] data address (byte-unit for SD, block unit for SDHC) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd24(uint32_t addr, SD_R32 * csr) { +#if 0 + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { +#endif + /* Send SD command */ + uint32_t status = _sd_cmd_arg_r32(SDC_CMD24_WRITE_BLOCK, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + /* Check error status */ + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; +#if 0 + /* Check whether make transition to sending-data state */ + switch (SD_CSR_GET_CURRENT_STATE(*csr)) { + case SD_STATE_RCV: + /* The card is ready to send out data */ + return HAL_SUCCESS; + case SD_STATE_TRAN: + /* Repeat previous command until the card get to the state */ + break; + case SD_STATE_STBY: + case SD_STATE_DATA: + case SD_STATE_PRG: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DIS: + default: + /* Invalid current state before deselecting the card. */ + return SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +#else + return HAL_SUCCESS; +#endif +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd25 + * + * DESCRIPTION + * + * This function issues SD command WRITE_MULTIPLE_BLOCK: Writes blocks of + * data to the card continuously until a STOP_TRANSMISSION command. + * + * Class: 2 (block-oriented write commands) + * + * State Transition: + * transfer -> receiving-data + * + * Argument: + * [31:0] data address (byte-unit for SD, block unit for SDHC) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd25(uint32_t addr, SD_R32 * csr) { +#if 0 + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { +#endif + /* Send SD command */ + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD25_WRITE_MULTIPLE_BLOCK, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + /* Check error status */ + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; +#if 0 + /* Check whether make transition to sending-data state */ + switch (SD_CSR_GET_CURRENT_STATE(*csr)) { + case SD_STATE_RCV: + /* The card is ready to send out data */ + return HAL_SUCCESS; + case SD_STATE_TRAN: + /* Repeat previous command until the card get to the state */ + break; + case SD_STATE_STBY: + case SD_STATE_DATA: + case SD_STATE_PRG: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DIS: + default: + /* Invalid current state before deselecting the card. */ + return SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +#else + return HAL_SUCCESS; +#endif +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd27 + * + * DESCRIPTION + * + * This function issues SD command PROGRAM_CSD: Programming the + * programmable bits of the CSD (using DATx lines). + * + * Class: 2 (block-oriented write commands) + * + * State Transition: + * transfer -> receiving-data + * + * Argument: + * [31:0] stufing bits + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd27(SD_R32 * csr) { + + uint32_t status = _sd_cmd_r32(SDC_CMD27_PROGRAM_CSD, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd28 + * + * DESCRIPTION + * + * This function issues SD command SET_WRITE_PROT: Sets the write protection + * bits of the addressed group, if supported. (Not supported in SDHC) + * + * Class: 6 (block-oriented write protection commands) + * + * State Transition: + * transfer -> programming + * + * Argument: + * [31:0] data address (byte unit) + * + * Response: + * R1b [39:8] card status + * DAT0 busy signal + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd28(uint32_t addr, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD28_SET_WRITE_PROT, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd29 + * + * DESCRIPTION + * + * This function issues SD command CLR_WRITE_PROT: Clears the write + * protection bits of the addressed group, if supported. + * (Not supported in SDHC) + * + * Class: 6 (block-oriented write protection commands) + * + * State Transition: + * transfer -> programming + * + * Argument: + * [31:0] data address (byte unit) + * + * Response: + * R1b [39:8] card status + * DAT0 busy signal + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd29(uint32_t addr, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD29_CLR_WRITE_PROT, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd30 + * + * DESCRIPTION + * + * This function issues SD command SEND_WRITE_PROT: Ask the card to send + * the status of the protection bits of the addressed group, if supported. + * (Not supported in SDHC) + * + * Class: 6 (block-oriented write protection commands) + * + * State Transition: + * transfer -> receiving-data + * + * Argument: + * [31:0] data address (byte unit) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd30(uint32_t addr, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD30_SEND_WRITE_PROT, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd32 + * + * DESCRIPTION + * + * This function issues SD command ERASE_WR_BLK_START: Sets the address of + * the first write block to be erased. + * + * Class: 5 (erase commands) + * + * State Transition: + * transfer -> transfer + * + * Argument: + * [31:0] data address (SD: byte unit, SDHC: block unit) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd32(uint32_t addr, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD32_ERASE_WR_BLK_START, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd33 + * + * DESCRIPTION + * + * This function issues SD command ERASE_WR_BLK_END: Sets the address of + * the last write block of a continuous range to be erased. + * + * Class: 5 (erase commands) + * + * State Transition: + * transfer -> transfer + * + * Argument: + * [31:0] data address (SD: byte unit, SDHC: block unit) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd33(uint32_t addr, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD33_ERASE_WR_BLK_END, addr, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd38 + * + * DESCRIPTION + * + * This function issues SD command ERASE: Erase all previously selected + * write blocks. + * + * Class: 5 (erase commands) + * + * State Transition: + * transfer -> programming + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R1 [39:8] card status + * DAT0 busy signal + * + * INPUTS + * + * addr : uint32_t address value. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd38(SD_R32 * csr) { + + uint32_t status = _sd_cmd_r32(SDC_CMD38_ERASE, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd42 + * + * DESCRIPTION + * + * This function issues SD command LOCK_UNLOCK: Set/reset the password or + * lock/unlock the card. + * + * Class: 7 (lock card) + * + * State Transition: + * transfer -> receiving-data + * + * Argument: + * [31:0] should be all 0! + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd42(SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD42_LOCK_UNLOCK, 0, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd55 + * + * DESCRIPTION + * + * This function issues SD command APP_CMD: Indicates the next command is + * an application specific command. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * idle -> idle + * standby -> standby + * transfer -> transfer + * sending-data -> sending-data + * receiving-data -> receiving-data + * programming -> programming + * disconnected -> disconnected + * + * Argument: + * [31:16] RCA + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_cmd55(uint32_t rca, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32(SDC_CMD55_APP_CMD, rca, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd56 + * + * DESCRIPTION + * + * This function issues SD command GEN_CMD: To transfer data block from/to + * the card for general-purpose/application-specific commands. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * RD/WR = 0 (write) + * transfer -> receiving-data + * RD/WR = 1 (read) + * transfer -> sending-data + * + * Argument: + * [31: 1] stuff bits + * [0] RD/WR + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * rdwr : uint32_t value where bit [0] is RD/WR. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd56(uint32_t rdwr, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32(SDC_CMD56_GEN_CMD, rdwr, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd6 + * + * DESCRIPTION + * + * This function issues SD command SET_BUS_WIDTH: Defines the data bus + * width to be used for data transfer. The allowed bus widths are given + * in the SCR register. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> transfer + * + * Argument: + * [31:2] stuff bits + * [ 1:0] bus width (00b -> 1bit, 10b -> 4bits) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * bw : uint32_t value where bit [1:0] is bus width. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_acmd6(uint32_t bw, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_ACMD6_SET_BUS_WIDTH, bw, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd13 + * + * DESCRIPTION + * + * This function issues SD command SD_STATUS: Send the SD status. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> sending-data + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_acmd13(SD_R32 * csr) { + + uint32_t status = _sd_cmd_r32(SDC_ACMD13_SD_STATUS, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd22 + * + * DESCRIPTION + * + * This function issues SD command SEND_NUM_WR_BLOCKS: Send the number of + * non-error write blocks. + * + * If (WRITE_BL_PARTIAL == 0) + * unit of ACMD22 is 512 bytes + * else + * unit of ACMD22 is a block length of write command + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> sending-data + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_acmd22(SD_R32 * csr) { + + uint32_t status = _sd_cmd_r32 (SDC_ACMD22_SEND_NUM_WR_BLOCKS, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd23 + * + * DESCRIPTION + * + * This function issues SD command SET_WR_BLK_ERASE_COUNT: Send the number + * of write blocks to be pre-erased before writing (for faster multiple- + * block-WR command). Default is 1. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> transfer + * + * Argument: + * [31:23] stuff bits + * [22: 0] number of blocks + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * blocks : uint32_t value represents the number of blocks. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_acmd23(uint32_t blocks, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_ACMD23_SET_WR_BLK_ERASE_COUNT, blocks, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd41 + * + * DESCRIPTION + * + * This function issues SD command SD_SEND_OP_COND: Send HCS and get OCR + * during the initialization and identification process. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * idle -> ready (OCR check OK and card is not busy) + * idle -> idle (OCR check OK and card is busy) + * idle -> inactive (OCR check fails) + * idle -> idle (query mode) + * + * Argument: + * [30] HCS (OCR[32]) + * [23:0] Vdd voltage window (OCR[23:0]) + * + * Response: + * R3 [39:8] OCR + * + * INPUTS + * + * hcs : uint32_t value represents the host capacity support information. + * ocr : Pointer to SD_OCR struct. + * + * OUTPUTS + * + * ocr : SD_OCR struct which holds the R3/OCR response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_acmd41(uint32_t hcs, SD_OCR * ocr) { + + return _sd_cmd_arg_r32 (SDC_ACMD41_SD_SEND_OP_COND, hcs, ocr); +} + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd42 + * + * DESCRIPTION + * + * This function issues SD command SET_CLR_CARD_DETECT: Connect/Disconnect + * the 50 KOmh pull-up resister on CD/DAT3 (pin1) of the card. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> transfer + * + * Argument: + * [0] set_cd (1: connect, 0: disconnect) + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * conn : uint32_t value where [0] denotes set_cd. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_acmd42(uint32_t conn, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_ACMD42_SET_CLR_CARD_DETECT, conn, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +/***************************************************************************** + * FUNCTION + * + * _sd_acmd51 + * + * DESCRIPTION + * + * This function issues SD command SEND_SCR: Reads the SD configuration + * register (SCR). + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> sending-data + * + * Argument: + * [31:0] stuff bits + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_acmd51(SD_R32 * csr) { + + uint32_t status = _sd_cmd_r32(SDC_ACMD51_SEND_SCR, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_cmd6 + * + * DESCRIPTION + * + * This function issues SD command SWITCH_FUNC: Check switchable function + * or switch card function. + * + * Class: 8 (application-specific commands) + * + * State Transition: + * transfer -> sending-data + * + * Argument: + * [31] mode (0: check, 1: switch) + * [30:24] should be 0 + * [23:20] 00h or 0fh (reserved for function group 6) + * [19:16] 00h or 0fh (reserved for function group 5) + * [15:12] 00h or 0fh (reserved for function group 4) + * [11: 8] 00h or 0fh (reserved for function group 3) + * [ 7: 4] function group 2 for command system + * [ 3: 0] function group 1 for access mode + * + * Response: + * R1 [39:8] card status + * + * INPUTS + * + * mode : uint32_t value which holds the function mode. + * csr : Pointer to SD_R32 struct. + * + * OUTPUTS + * + * csr : SD_R32 struct which holds the R1 response. + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +uint32_t _sd_cmd6(uint32_t mode, SD_R32 * csr) { + + uint32_t status = _sd_cmd_arg_r32 (SDC_CMD6_SWITCH_FUNC, mode, csr); + + if (status != HAL_SUCCESS) + return status; + + if (SD_CSR_CHECK_ERROR_BITS(*csr)) + return SDD_CSR_ERROR; + + return HAL_SUCCESS; +} +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +#if 0 +/***************************************************************************** + * FUNCTION + * + * _sd_wait_sending_state + * + * DESCRIPTION + * + * This function waits the transfer state make transition to the sending- + * data state. This is equivalent to waiting for the card start to send + * out data after cmd17 or cmd18. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_wait_sending_state(uint32_t rca) { + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < + SD_TRANSFER_MAX_RETRY_COUNT) { + /* Get current state */ + status = + _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + switch (SD_CSR_GET_CURRENT_STATE + (sd_rsp32)) { + case SD_STATE_DATA: + return HAL_SUCCESS; + case SD_STATE_TRAN: + break; + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_STBY: + case SD_STATE_RCV: + case SD_STATE_DIS: + case SD_STATE_PRG: + default: + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_wait_receiving_state + * + * DESCRIPTION + * + * This function waits the transfer state make transition to the receiving- + * data state. This is equivalent to waiting for the card start to receive + * data after cmd24/25/27/42/56. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_wait_receiving_state(uint32_t rca) { + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < + SD_TRANSFER_MAX_RETRY_COUNT) { + /* Get current state */ + status = + _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + switch (SD_CSR_GET_CURRENT_STATE + (sd_rsp32)) { + case SD_STATE_RCV: + if (SD_CSR_GET_READY_FOR_DATA(sd_rsp32)) + return + HAL_SUCCESS; + break; + case SD_STATE_TRAN: + break; + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_STBY: + case SD_STATE_DATA: + case SD_STATE_DIS: + case SD_STATE_PRG: + default: + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} +#endif /* 0 */ + +/***************************************************************************** + * FUNCTION + * + * _sd_wait_programmed + * + * DESCRIPTION + * + * This function waits the disconnected state make transition to the + * standby state or the transfer state. This is equivalent to waiting for + * the completion of programming. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_wait_programmed(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < SD_TRANSFER_MAX_RETRY_COUNT) { + + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + switch (SD_CSR_GET_CURRENT_STATE + (sd_rsp32)) { + case SD_STATE_STBY: + case SD_STATE_TRAN: + return HAL_SUCCESS; + case SD_STATE_DIS: + case SD_STATE_PRG: + break; + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DATA: + case SD_STATE_RCV: + default: + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_wait_transferred + * + * DESCRIPTION + * + * This function waits the data/rcv/prog state make transition to the + * transfer state. This is equivalent to waiting for the + * completion of all current data transfer traffic. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_wait_transferred(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < SD_TRANSFER_MAX_RETRY_COUNT) { + + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + switch (SD_CSR_GET_CURRENT_STATE (sd_rsp32)) { + + case SD_STATE_TRAN: + return HAL_SUCCESS; + case SD_STATE_DATA: + case SD_STATE_RCV: + case SD_STATE_PRG: + break; + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_STBY: + case SD_STATE_DIS: + default: + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_disconnect + * + * DESCRIPTION + * + * This function forces the prog state make transition to the + * disconnect state. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_disconnect(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + /* Perform state transition according to spec 2.0 fig 4-3. */ + switch (SD_CSR_GET_CURRENT_STATE (sd_rsp32)) { + + case SD_STATE_STBY: + case SD_STATE_DIS: + /* The card with the target rca is already disconnected. Just */ + /* return that the card is disconnected successfully. */ + return HAL_SUCCESS; + case SD_STATE_PRG: + /* Try to enter disconnected state ... */ + status = _sd_cmd7(rca, &sd_rsp32); /* disconnect the card */ + if (status != HAL_SUCCESS) + return status; + break; + case SD_STATE_TRAN: + case SD_STATE_DATA: + case SD_STATE_RCV: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + default: + /* Invalid current state before disconnect the card. */ + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_connect + * + * DESCRIPTION + * + * This function forces the disconnect state make transition to the + * programming state. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_connect(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { + + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + /* Perform state transition according to spec 2.0 fig 4-3. */ + switch (SD_CSR_GET_CURRENT_STATE (sd_rsp32)) { + case SD_STATE_PRG: + case SD_STATE_TRAN: + /* + * The card with the target rca is already connected. Just + * return that the card is connected successfully. + */ + return HAL_SUCCESS; + case SD_STATE_DIS: + /* Try to enter programming state ... */ + status = _sd_cmd7(rca, &sd_rsp32); /* connect the card */ + if (status != HAL_SUCCESS) + return status; + break; + case SD_STATE_STBY: + case SD_STATE_DATA: + case SD_STATE_RCV: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + default: + /* Invalid current state before connect the card. */ + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_deselect_card + * + * DESCRIPTION + * + * This function forces the transfer state make transition to the + * standby state. + * + * If the card is currently in data or transfer state, the function will + * issue trnasition command and continue loop until the card enters standby + * state. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_deselect_card(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + /* Perform state transition according to spec 2.0 fig 4-3. */ + switch (SD_CSR_GET_CURRENT_STATE (sd_rsp32)) { + + case SD_STATE_STBY: + /* + * The card with the target rca is already deselected. Just + * return that the card is deselected successfully. + */ + return HAL_SUCCESS; + case SD_STATE_TRAN: + case SD_STATE_DATA: + /* Try to enter standby state ... */ + status = _sd_cmd7(rca, &sd_rsp32); /* deselect the card */ + if (status != HAL_SUCCESS) + return status; + break; + case SD_STATE_RCV: + case SD_STATE_PRG: + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DIS: + default: + /* Invalid current state before deselecting the card. */ + return + SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_select_card + * + * DESCRIPTION + * + * This function forces the standby state make transition to the + * transfer state. + * + * If the card is currently in data/rcv state, the function will wait for + * a limitted time. After timeout, it forces to stop the current + * operation and try to make transition back to standby state. + * + * If the card is currently in the prog state, the function will wait for + * a limitted time. If timeout then it will return that failed to make + * the desired state transition. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_select_card(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + uint32_t retry = 0; + + while (retry++ < SD_STATE_MAX_RETRY_COUNT) { + + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + /* Perform state transition according to spec 2.0 fig 4-3. */ + switch (SD_CSR_GET_CURRENT_STATE (sd_rsp32)) { + + case SD_STATE_TRAN: + /* + * The card with the target rca is already selected. Just + * return that the card is selected successfully. + */ + return HAL_SUCCESS; + case SD_STATE_STBY: + /* Try to enter transfer state ... */ + status = _sd_cmd7(rca, &sd_rsp32); /* select the card */ + if (status != HAL_SUCCESS) + return status; + break; + case SD_STATE_DATA: + case SD_STATE_RCV: + /* + * The card is still transferring data or programming. + * Wait a short period for transfer completion. The + * card will back to transfer state after operation + * completion. + */ + status = _sd_wait_transferred (rca); + + if (status == HAL_SUCCESS) { + + return HAL_SUCCESS; + } + else if (status == SDD_WAIT_TIMEOUT) + { + /* + * Stop the current transmission after waiting timeout. Then + * continue status check loop to fall back to transfer state. + */ + status = _sd_cmd12(&sd_rsp32); /* stop transmission */ + if (status != HAL_SUCCESS) + return status; + } + else { + return status; + } + break; + case SD_STATE_PRG: + + status = _sd_wait_transferred (rca); + if (status != HAL_SUCCESS) + return status; + + break; + case SD_STATE_DIS: + /* Continue status check loop to fall back to standby state. */ + break; + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + default: + /* Invalid current state before selecting the card. */ + return SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} + +/***************************************************************************** + * FUNCTION + * + * _sd_stop_transmission + * + * DESCRIPTION + * + * This function forces the data/rcv/prog state make transition to the + * transfer state. + * + * If the card is currently in data/rcv state, the function will issue + * stop command directly. Then continue check loop to wait for back to + * the transfer or standby state. + * + * If the card is currently in the prog state, the function will wait for + * a limitted time. If timeout then it will return that failed to make + * the desired state transition. + * + * INPUTS + * + * rca : uint32_t value where RCA is at [31:16]. + * + * OUTPUTS + * + * uint32_t : Returns HAL_SUCCESS if successful, + * else positive value is SDD-specific error code, + * else negative value is NU system error code. + * + ****************************************************************************/ +uint32_t _sd_stop_transmission(uint32_t rca) { + + uint32_t status; + SD_R32 sd_rsp32; + + while (1) { + + // _nds_kwait(0x1000); + + /* Get current state */ + status = _sd_cmd13(rca, &sd_rsp32); + if (status != HAL_SUCCESS) + return status; + + /* Perform state transition according to spec 2.0 fig 4-3. */ + switch (SD_CSR_GET_CURRENT_STATE (sd_rsp32)) { + + case SD_STATE_STBY: + case SD_STATE_TRAN: + /* The card with the target rca is already stopped. Just */ + /* return that the card is stopped successfully. */ + return HAL_SUCCESS; + case SD_STATE_DATA: + case SD_STATE_RCV: + /* Try to back to transfer state ... */ + status = _sd_cmd12(&sd_rsp32); /* stop transmission */ + if (status != HAL_SUCCESS) + return status; + break; + case SD_STATE_PRG: + /* The card is still transferring data or programming. */ + /* Wait a short period for transfer completion. The */ + /* card will back to transfer state after operation */ + /* completion. */ + status = _sd_wait_transferred (rca); + if (status != HAL_SUCCESS) + return status; + + break; + case SD_STATE_IDLE: + case SD_STATE_READY: + case SD_STATE_IDENT: + case SD_STATE_DIS: + default: + /* Invalid current state before selecting the card. */ + return SDD_INVALID_STATE; + } + } + + return SDD_WAIT_TIMEOUT; +} diff --git a/bsp/AE210P/driver/sd/sdd_sd.h b/bsp/AE210P/driver/sd/sdd_sd.h new file mode 100644 index 0000000000000000000000000000000000000000..cefd1c2b894d170f3b865c3e6fba1f8846b56502 --- /dev/null +++ b/bsp/AE210P/driver/sd/sdd_sd.h @@ -0,0 +1,927 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Sep.26.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sdd_sd.h + * + * DESCRIPTION + * + * Secure digital card specification 2.0 definition. + * + * Currently only Secure Digital Memory standards are well-defined. + * Remaining spec mostly are left for future developers. + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * None + * + ****************************************************************************/ +#ifndef __SDD_SD_H__ +#define __SDD_SD_H__ + +#include + +/***************************************************************************** + * Secure Digital Memory Card Register Definitions + * + * Summary: + * read program + * ---- -------- ---------------------------------------------- --------------------- + * OCR 32 bits CMD8_SEND_IF_COND/R7 ACMD41_SD_SEND_OP_COND/R3 + * CID 128 bits CMD2_ALL_SEND_CIS/R2 CMD10_SEND_CID/R2 + * CSD 128 bits CMD9_SEND_CSD/R2 CMD27_PROGRAM_CSD/R1 + * SCR 64 bits ACMD51_SEND_SCR/R1 + * RCA 16 bits CMD3_SEND_RELATIVE_ADDR/R6 + * DSR 16 bits CMD4_SET_DSR + * CSR 32 bits CMD13_SEND_STATUS/R1 + * SSR 512 bits ACMD13_SD_STATUS/R1 + * + * Responses: + * R1 48 bits (cmd) (normal response reg) + * [45:40] cmd_idx [39:08] CSR [7:1] CRC + * R1b 48 bits (cmd) busy signal (dat) + * [45:40] cmd_idx [39:08] CSR [7:1] CRC + * R2 136 bits (cmd) (CID, CSD reg) + * [127:1] CID/CSD (CRC included) + * R3 48 bits (cmd) (OCR reg)) + * [39:8] OCR + * R6 48 bits (cmd) (RCA reg) + * [45:40] cmd_idx (0x03 CMD3) [39:24] New published RCA [23:8] CSR 23,22,19,12-0 + * R7 48 bits (cmd) (card interface condition reg) + * [45:40] cmd_idx [19:16] voltage (0x01: 2.7~3.6V) [15:8] check-echo [7:1] CRC + * + ****************************************************************************/ + +/* General Form 32-bit Response */ +typedef struct _SD_R32 { + /* + * Note: The bitfields definition was not applied due to that the + * core architecture may be switched between big-endian + * and little endian. We don't want to define two structures + * to switch between the two endain architectures. Users + * could use following macros to extract the target member. + */ + union { + uint32_t r[1]; + uint8_t b[4]; + }; +} SD_R32; + +/* General Form 128-bit Response */ +typedef struct _SD_R128 { + /* + * Note: The bitfields definition was not applied due to that the + * core architecture may be switched between big-endian + * and little endian. We don't want to define two structures + * to switch between the two endain architectures. Users + * could use following macros to extract the target member. + */ + union { + uint32_t r[4]; + uint8_t b[16]; + }; +} SD_R128; + +/* R6 Response Fields (Width: 32 bits) */ +#define SD_R6_GET_RCA(r32) ((uint32_t)((r32).r[0]) & 0xffff0000) +#define SD_R6_GET_CSR(r32) ((uint32_t)((r32).r[0]) & 0x0000ffff) +#define SD_R6_GET_CSR_ERR(r32) ((uint32_t)((r32).r[0]) & 0x0000e000) + +/* R7 Response Fields (Width: 32 bits) */ +#define SD_R7_GET_VHS(r32) (((uint32_t)((r32).r[0]) >> 8) & 0x0f) +#define SD_R7_GET_PTN(r32) ((uint32_t)((r32).r[0]) & 0xff) + +/* OCR - Operation Condition Register (Width: 32 bits */ +/* Readback: ACMD41_SD_SEND_OP_COND/R3 */ +typedef SD_R32 SD_OCR; + +#define SD_OCR_VDD_MASK 0x00ffffff /* VDD voltage window */ +#define SD_OCR_VDD_SHIFT 0 +#define SD_OCR_VDD_2_7 0x00008000 /* VDD 2.7 ~ 2.8 */ +#define SD_OCR_VDD_2_8 0x00010000 /* VDD 2.8 ~ 2.9 */ +#define SD_OCR_VDD_2_9 0x00020000 /* VDD 2.9 ~ 3.0 */ +#define SD_OCR_VDD_3_0 0x00040000 /* VDD 3.0 ~ 3.1 */ +#define SD_OCR_VDD_3_1 0x00080000 /* VDD 3.1 ~ 3.2 */ +#define SD_OCR_VDD_3_2 0x00100000 /* VDD 3.2 ~ 3.3 */ +#define SD_OCR_VDD_3_3 0x00200000 /* VDD 3.3 ~ 3.4 */ +#define SD_OCR_VDD_3_4 0x00400000 /* VDD 3.4 ~ 3.5 */ +#define SD_OCR_VDD_3_5 0x00800000 /* VDD 3.5 ~ 3.6 */ +#define SD_OCR_VDD_2_7V_3_6V (SD_OCR_VDD_2_7 | SD_OCR_VDD_2_8 | SD_OCR_VDD_2_9 | SD_OCR_VDD_3_0 | \ + SD_OCR_VDD_3_1 | SD_OCR_VDD_3_2 | SD_OCR_VDD_3_3 | SD_OCR_VDD_3_4 | SD_OCR_VDD_3_5) + +#define SD_OCR_CCS_MASK 0x40000000 /* Card capacity status */ +#define SD_OCR_CCS_SHIFT 30 +#define SD_CCS_SD 0 +#define SD_CCS_SDHC 1 + +#define SD_OCR_BUSY_MASK 0x80000000 /* Card power up status bit */ +#define SD_OCR_BUSY_SHIFT 31 +#define SD_BUSY 0 +#define SD_POWERUP 1 + +#define SD_OCR_GET_VDD(ocr) (((uint32_t)((ocr).r[0]) & SD_OCR_VDD_MASK) >> SD_OCR_VDD_SHIFT) +#define SD_OCR_GET_CCS(ocr) (((uint32_t)((ocr).r[0]) & SD_OCR_CCS_MASK) >> SD_OCR_CCS_SHIFT) +#define SD_OCR_GET_BUSY(ocr) (((uint32_t)((ocr).r[0]) & SD_OCR_BUSY_MASK) >> SD_OCR_BUSY_SHIFT) + +/* CID - Card Identification Register (Width: 128 bits) */ +/* Readback: CMD10_SEND_CID/R2 */ +typedef SD_R128 SD_CID; + +/* Manufacture ID */ +#define SD_CID_GET_MID(cid) ((uint32_t)((cid).r[3]) >> 24) +#define SD_CID_GET_MID_FROM_R3(r) ((uint32_t)(r) >> 24) + +/* OEM/Application ID */ +#define SD_CID_GET_OID_PTR(cid) ((uint8_t*)&((cid).b[13])) + +/* Product name */ +#define SD_CID_GET_PNM_PTR(cid) ((uint8_t*)&((cid).b[8])) + +/* Product revision (BCD coding) */ +#define SD_CID_GET_PRV(cid) ((uint32_t)((cid).r[1]) >> 24) +#define SD_CID_GET_PRV_FROM_R1(r) ((uint32_t)(r) >> 24) + +/* Product serial number */ +#define SD_CID_GET_PSN(cid) (((uint32_t)((cid).r[1]) << 8) | ((uint32_t)((cid).r[0]) >> 24)) +#define SD_CID_GET_PSN_FROM_R0R1(r0, r1) (((uint32_t)(r1) << 8) | ((uint32_t)(r0) >> 24)) + +/* Manufacturing date (0x0yym, year = 2000 + yy, month = m) */ +#define SD_CID_GET_MDT(cid) (((uint32_t)((cid).r[0]) >> 8) & 0x0fff) +#define SD_CID_GET_MDT_FROM_R0(r) (((uint32_t)(r) >> 8) & 0x0fff) + +/* CRC7 checksum */ +#define SD_CID_GET_CRC(cid) (((uint32_t)((cid).r[0]) >> 1) & 0x007f) +#define SD_CID_GET_CRC_FROM_R0(r) (((uint32_t)(r) >> 1) & 0x007f) + +/* + * CSD - Card-Specific Data Register (Width: 128 bits) + * Readback: CMD9_SEND_CSD/R2 + * Program : CMD27_PROGRAM_CSD/R1 + */ +typedef SD_R128 SD_CSD; + +/* -------------------------- */ +/* CSD v1.0 definitions */ +/* CRC (R/W) */ +#define SD_CSD_GET_CRC(csd) (((uint32_t)((csd).r[0]) >> 1) & 0x0000007f) +#define SD_CSD_GET_CRC_FROM_R0(r) (((uint32_t)(r) >> 1) & 0x0000007f) +#define SD_CSD_SET_CRC(csd,v) ((uint32_t)((csd).r[0]) |= (((uint32_t)(v) & 0x7f) << 1)) +#define SD_CSD_SET_CRC_TO_R0(r,v) ((uint32_t)(r) |= (((uint32_t)(v) & 0x7f) << 1)) + +/* File format (R/W1, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_FILE_FORMAT(csd) (((uint32_t)((csd).r[0]) >> 10) & 0x00000003) +#define SD_CSD_GET_FILE_FORMAT_FROM_R0(r) (((uint32_t)(r) >> 10) & 0x00000003) +#define SD_CSD_SET_FILE_FORMAT(csd,v) ((uint32_t)((csd).r[0]) |= (((uint32_t)(v) & 0x03) << 10)) +#define SD_CSD_SET_FILE_FORMAT_TO_R0(r,v) ((uint32_t)(r) |= (((uint32_t)(v) & 0x03) << 10)) + +#define SD_FILE_FORMAT_HDD 0 /* Hard disk like file system with partition table */ +#define SD_FILE_FORMAT_FLOPPY 1 /* DOS FAT (floppy like) with boot sector only (no partition table) */ +#define SD_FILE_FORMAT_UNIVERSAL 2 /* Universal file format */ +#define SD_FILE_FORMAT_OTHERS 3 /* Others/Unknown */ + +/* Temporary write protection (R/W) */ +#define SD_CSD_GET_TMP_WRITE_PROTECT(csd) (((uint32_t)((csd).r[0]) >> 12) & 0x00000001) +#define SD_CSD_GET_TMP_WRITE_PROTECT_FROM_R0(r) (((uint32_t)(r) >> 12) & 0x00000001) +#define SD_CSD_SET_TMP_WRITE_PROTECT(csd,v) ((uint32_t)((csd).r[0]) |= (((uint32_t)(v) & 0x01) << 12)) +#define SD_CSD_SET_TMP_WRITE_PROTECT_TO_R0(r,v) ((uint32_t)(r) |= (((uint32_t)(v) & 0x01) << 12)) + +/* Permanent write protection (R/W1) */ +#define SD_CSD_GET_PERM_WRITE_PROTECT(csd) (((uint32_t)((csd).r[0]) >> 13) & 0x00000001) +#define SD_CSD_GET_PERM_WRITE_PROTECT_FROM_R0(r) (((uint32_t)(r) >> 13) & 0x00000001) +#define SD_CSD_SET_PERM_WRITE_PROTECT(csd,v) ((uint32_t)((csd).r[0]) |= (((uint32_t)(v) & 0x01) << 13)) +#define SD_CSD_SET_PERM_WRITE_PROTECT_TO_R0(r,v) ((uint32_t)(r) |= (((uint32_t)(v) & 0x01) << 13)) + +/* Copy flag (R/W1) */ +#define SD_CSD_GET_COPY(csd) (((uint32_t)((csd).r[0]) >> 14) & 0x00000001) +#define SD_CSD_GET_COPY_FROM_R0(r) (((uint32_t)(r) >> 14) & 0x00000001) +#define SD_CSD_SET_COPY(csd,v) ((uint32_t)((csd).r[0]) |= (((uint32_t)(v) & 0x01) << 14)) +#define SD_CSD_SET_COPY_TO_R0(r,v) ((uint32_t)(r) |= (((uint32_t)(v) & 0x01) << 14)) + +/* File format group (R/W1, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_FILE_FORMAT_GRP(csd) (((uint32_t)((csd).r[0]) >> 15) & 0x00000001) +#define SD_CSD_GET_FILE_FORMAT_GRP_FROM_R0(r) (((uint32_t)(r) >> 15) & 0x00000001) +#define SD_CSD_SET_FILE_FORMAT_GRP(csd,v) ((uint32_t)((csd).r[0]) |= (((uint32_t)(v) & 0x01) << 15)) +#define SD_CSD_SET_FILE_FORMAT_GRP_TO_R0(r,v) ((uint32_t)(r) |= (((uint32_t)(v) & 0x01) << 15)) + +/* Partial blocks for write allowed (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_WRITE_BL_PARTIAL(csd) (((uint32_t)((csd).r[0]) >> 21) & 0x00000001) +#define SD_CSD_GET_WRITE_BL_PARTIAL_FROM_R0(r) (((uint32_t)(r) >> 21) & 0x00000001) + +/* Max write data block length (R, fixed to 9 in 2.0) */ +#define SD_CSD_GET_WRITE_BL_LEN(csd) (((uint32_t)((csd).r[0]) >> 22) & 0x0000000f) +#define SD_CSD_GET_WRITE_BL_LEN_FROM_R0(r) (((uint32_t)(r) >> 22) & 0x0000000f) + +/* Write speed factor (R, fixed to 0x02 in 2.0) */ +#define SD_CSD_GET_R2W_FACTOR(csd) (((uint32_t)((csd).r[0]) >> 26) & 0x00000007) +#define SD_CSD_GET_R2W_FACTOR_FROM_R0(r) (((uint32_t)(r) >> 26) & 0x00000007) + +/* Write protect group enable (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_WP_GRP_ENABLE(csd) ((uint32_t)((csd).r[0]) >> 31) +#define SD_CSD_GET_WP_GRP_ENABLE_FROM_R0(r) ((uint32_t)(r) >> 31) + +/* Write protect group size (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_WP_GRP_SIZE(csd) (((uint32_t)((csd).r[1]) >> 0) & 0x0000007f) +#define SD_CSD_GET_WP_GRP_SIZE_FROM_R1(r) (((uint32_t)(r) >> 0) & 0x0000007f) + +/* Erase sector size (R, fixed to 0x7f in 2.0) */ +#define SD_CSD_GET_SECTOR_SIZE(csd) (((uint32_t)((csd).r[1]) >> 7) & 0x0000007f) +#define SD_CSD_GET_SECTOR_SIZE_FROM_R1(r) (((uint32_t)(r) >> 7) & 0x0000007f) + +/* Erase single block enable (R, fixed to 0x01 in 2.0) */ +#define SD_CSD_GET_ERASE_BLK_EN(csd) (((uint32_t)((csd).r[1]) >> 14) & 0x00000001) +#define SD_CSD_GET_ERASE_BLK_EN_FROM_R1(r) (((uint32_t)(r) >> 14) & 0x00000001) + +/* Device size multiplier (R, obsolete in 2.0) */ +#define SD_CSD1_GET_C_SIZE_MULT(csd) (((uint32_t)((csd).r[1]) >> 15) & 0x00000007) +#define SD_CSD1_GET_C_SIZE_MULT_FROM_R1(r) (((uint32_t)(r) >> 15) & 0x00000007) + +/* Max write current at VDD max (R, obsolete in 2.0) */ +#define SD_CSD1_GET_VDD_W_CURR_MAX(csd) (((uint32_t)((csd).r[1]) >> 18) & 0x00000007) +#define SD_CSD1_GET_VDD_W_CURR_MAX_FROM_R1(r) (((uint32_t)(r) >> 18) & 0x00000007) + +/* Max write current at VDD min (R, obsolete in 2.0) */ +#define SD_CSD1_GET_VDD_W_CURR_MIN(csd) (((uint32_t)((csd).r[1]) >> 21) & 0x00000007) +#define SD_CSD1_GET_VDD_W_CURR_MIN_FROM_R1(r) (((uint32_t)(r) >> 21) & 0x00000007) + +/* Max read current at VDD max (R, obsolete in 2.0) */ +#define SD_CSD1_GET_VDD_R_CURR_MAX(csd) (((uint32_t)((csd).r[1]) >> 24) & 0x00000007) +#define SD_CSD1_GET_VDD_R_CURR_MAX_FROM_R1(r) (((uint32_t)(r) >> 24) & 0x00000007) + +/* Max read current at VDD min (R, obsolete in 2.0) */ +#define SD_CSD1_GET_VDD_R_CURR_MIN(csd) (((uint32_t)((csd).r[1]) >> 27) & 0x00000007) +#define SD_CSD1_GET_VDD_R_CURR_MIN_FROM_R1(r) (((uint32_t)(r) >> 27) & 0x00000007) + +#define SD_VDD_CURR_MIN_0P5MA 0 +#define SD_VDD_CURR_MIN_1MA 1 +#define SD_VDD_CURR_MIN_5MA 2 +#define SD_VDD_CURR_MIN_10MA 3 +#define SD_VDD_CURR_MIN_25MA 4 +#define SD_VDD_CURR_MIN_35MA 5 +#define SD_VDD_CURR_MIN_60MA 6 +#define SD_VDD_CURR_MIN_100MA 7 + +#define SD_VDD_CURR_MAX_1MA 0 +#define SD_VDD_CURR_MAX_5MA 1 +#define SD_VDD_CURR_MAX_10MA 2 +#define SD_VDD_CURR_MAX_25MA 3 +#define SD_VDD_CURR_MAX_35MA 4 +#define SD_VDD_CURR_MAX_45MA 5 +#define SD_VDD_CURR_MAX_80MA 6 +#define SD_VDD_CURR_MAX_200MA 7 + +/* Device size (R) */ +#define SD_CSD1_GET_C_SIZE(csd) ((((uint32_t)((csd).r[2]) << 2) & 0x00000fff) | (((uint32_t)((csd).r[1]) >> 30) & 0x00000003)) +#define SD_CSD1_GET_C_SIZE_FROM_R1R2(r1, r2) ((((uint32_t)(r2) << 2) & 0x00000fff) | (((uint32_t)(r1) >> 30) & 0x00000003)) + +/* DSR implemented (R) */ +#define SD_CSD_GET_DSR_IMP(csd) (((uint32_t)((csd).r[2]) >> 12) & 0x00000001) +#define SD_CSD_GET_DSR_IMP_FROM_R2(r) (((uint32_t)(r) >> 12) & 0x00000001) + +/* Read block misaligned (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_READ_BLK_MISALIGN(csd) (((uint32_t)((csd).r[2]) >> 13) & 0x00000001) +#define SD_CSD_GET_READ_BLK_MISALIGN_FROM_R2(r) (((uint32_t)(r) >> 13) & 0x00000001) + +/* Write block misaligned (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_WRITE_BLK_MISALIGN(csd) (((uint32_t)((csd).r[2]) >> 14) & 0x00000001) +#define SD_CSD_GET_WRITE_BLK_MISALIGN_FROM_R2(r) (((uint32_t)(r) >> 14) & 0x00000001) + +/* Partial blocks for read allowed (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_READ_BL_PARTIAL(csd) (((uint32_t)((csd).r[2]) >> 15) & 0x00000001) +#define SD_CSD_GET_READ_BL_PARTIAL_FROM_R2(r) (((uint32_t)(r) >> 15) & 0x00000001) + +/* Max read data block length (R, fixed to 9 in 2.0) */ +#define SD_CSD_GET_READ_BL_LEN(csd) (((uint32_t)((csd).r[2]) >> 16) & 0x0000000f) +#define SD_CSD_GET_READ_BL_LEN_FROM_R2(r) (((uint32_t)(r) >> 16) & 0x0000000f) + +#define SD_BL_LEN_512 9 /* 2^9 */ +#define SD_BL_LEN_1024 10 /* 2^10 */ +#define SD_BL_LEN_2048 11 /* 2^11 */ + +/* Card command classes (R) */ +#define SD_CSD_GET_CCC(csd) (((uint32_t)((csd).r[2]) >> 20) & 0x00000fff) +#define SD_CSD_GET_CCC_FROM_R2(r) (((uint32_t)(r) >> 20) & 0x00000fff) + +#define SD_CCC_CLASS0 0 +#define SD_CCC_CLASS1 1 +#define SD_CCC_CLASS2 2 +#define SD_CCC_CLASS3 3 +#define SD_CCC_CLASS4 4 +#define SD_CCC_CLASS5 5 +#define SD_CCC_CLASS6 6 +#define SD_CCC_CLASS7 7 +#define SD_CCC_CLASS8 8 +#define SD_CCC_CLASS9 9 +#define SD_CCC_CLASS10 10 +#define SD_CCC_CLASS11 11 + +/* Max data transfer rate (R, fixed to 0x32 or 0x5a in 2.0) */ +#define SD_CSD_GET_TRAN_SPEED(csd) ((uint32_t)((csd).r[3]) & 0x000000ff) +#define SD_CSD_GET_TRAN_SPEED_FROM_R3(r) ((uint32_t)(r) & 0x000000ff) + +#define SD_TRAN_SPEED_TU(ts) ((uint32_t)(ts) & 0x07) +#define SD_TRAN_SPEED_TV(ts) (((uint32_t)(ts) >> 3) & 0x0f) + +#define SD_TS_TU_100KBPS 0 +#define SD_TS_TU_1MBPS 1 +#define SD_TS_TU_10MBPS 2 +#define SD_TS_TU_100MBPS 3 + +#define SD_TS_TV_1P0 1 +#define SD_TS_TV_1P2 2 +#define SD_TS_TV_1P3 3 +#define SD_TS_TV_1P5 4 +#define SD_TS_TV_2P0 5 +#define SD_TS_TV_2P5 6 +#define SD_TS_TV_3P0 7 +#define SD_TS_TV_3P5 8 +#define SD_TS_TV_4P0 9 +#define SD_TS_TV_4P5 10 +#define SD_TS_TV_5P0 11 +#define SD_TS_TV_5P5 12 +#define SD_TS_TV_6P0 13 +#define SD_TS_TV_7P0 14 +#define SD_TS_TV_8P0 15 + +/* Data read access-time-2 in CLK cycles (NSAC * 100) (R, fixed to 0x00 in 2.0) */ +#define SD_CSD_GET_NSAC(csd) (((uint32_t)((csd).r[3]) >> 8) & 0x000000ff) +#define SD_CSD_GET_NSAC_FROM_R3(r) (((uint32_t)(r) >> 8) & 0x000000ff) + +/* Data read access-time-1 (R, fixed to 0x0e in 2.0) */ +#define SD_CSD_GET_TAAC(csd) (((uint32_t)((csd).r[3]) >> 16) & 0x0000ffff) +#define SD_CSD_GET_TAAC_FROM_R3(r) (((uint32_t)(r) >> 16) & 0x0000ffff) + +#define SD_TAAC_TU(ac) ((uint32_t)(ac) & 0x07) +#define SD_TAAC_TV(ac) (((uint32_t)(ac) >> 3) & 0x0f) + +#define SD_TAAC_TU_1NS 0 +#define SD_TAAC_TU_10NS 1 +#define SD_TAAC_TU_100NS 2 +#define SD_TAAC_TU_1US 3 +#define SD_TAAC_TU_10US 4 +#define SD_TAAC_TU_100US 5 +#define SD_TAAC_TU_1MS 6 +#define SD_TAAC_TU_10MS 7 + +#define SD_TAAC_TV_1P0 1 +#define SD_TAAC_TV_1P2 2 +#define SD_TAAC_TV_1P3 3 +#define SD_TAAC_TV_1P5 4 +#define SD_TAAC_TV_2P0 5 +#define SD_TAAC_TV_2P5 6 +#define SD_TAAC_TV_3P0 7 +#define SD_TAAC_TV_3P5 8 +#define SD_TAAC_TV_4P0 9 +#define SD_TAAC_TV_4P5 10 +#define SD_TAAC_TV_5P0 11 +#define SD_TAAC_TV_5P5 12 +#define SD_TAAC_TV_6P0 13 +#define SD_TAAC_TV_7P0 14 +#define SD_TAAC_TV_8P0 15 + +/* CSD structure (R) */ +#define SD_CSD_GET_CSD_STRUCTURE(csd) ((uint32_t)((csd).r[3]) >> 30) +#define SD_CSD_GET_CSD_STRUCTURE_FROM_R3(r) ((uint32_t)(r) >> 30) + +/* Get user data size (card memory capacity, not include security protected area) */ +#if 0 +#define SD_CSD1_GET_CAPACITY(csd) (SD_CSD1_GET_C_SIZE(csd) + 1) * \ + (1 << (SD_CSD1_GET_C_SIZE_MULT(csd) + 2)) * \ + (1 << SD_CSD_GET_READ_BL_LEN(csd)) + +#define SD_CSD1_GET_CAPACITY_R1R2(r1,r2) (SD_CSD1_GET_C_SIZE_FROM_R1R2(r1,r2) + 1) * \ + (1 << (SD_CSD1_GET_C_SIZE_MULT_FROM_R1(r1) + 2)) * \ + (1 << SD_CSD_GET_READ_BL_LEN_FROM_R2(r2)) +#endif + +/* -------------------------- */ +/* CSD v2.0 definitions */ +/* */ +/* Device size (R) */ +#define SD_CSD2_GET_C_SIZE(csd) ((((uint32_t)((csd).r[2]) << 16) & 0x003f0000) | ((uint32_t)((csd).r[1]) >> 16)) +#define SD_CSD2_GET_C_SIZE_FROM_R1R2(r1,r2) ((((uint32_t)(r2) << 16) & 0x003f0000) | ((uint32_t)(r1) >> 16)) + +/* Get user data size (card memory capacity, not include security protected area) */ +// #define SD_CSD2_GET_CAPACITY_KB(csd) ((SD_CSD2_GET_C_SIZE(csd) + 1) * 512) +// #define SD_CSD2_GET_CAPACITY_KB_R1R2(r1,r2) ((SD_CSD2_GET_C_SIZE_FROM_R1R2(csd) + 1) * 512) + +/* + * SCR - SD Card Configuration Register + * Width: 64 bits + * Readback: ACMD51_SEND_SCR/R1 + */ +typedef struct _SD_SCR { + /* Note: The bitfields definition was not applied due to that the */ + /* core architecture may be switched between big-endian */ + /* and little endian. We don't want to define two structures */ + /* to switch between the two endain architectures. Users */ + /* could use following macros to extract the target member. */ + union { + uint32_t r[2]; + uint8_t b[8]; + }; +} SD_SCR; + +/* DAT bus widths supported */ +#define SD_SCR_GET_SD_BUS_WIDTHS(scr) (((uint32_t)((scr).r[1]) >> 16) & 0x0000000f) +#define SD_SCR_GET_SD_BUS_WIDTHS_FROM_R1(r) (((uint32_t)(r) >> 16) & 0x0000000f) + +#define SD_BUS_WIDTH_1BIT 1 /* DAT0 */ +#define SD_BUS_WIDTH_4BIT 4 /* DAT0 ~ DAT3 */ + +/* SD security support */ +#define SD_SCR_GET_SD_SECURITY(scr) (((uint32_t)((scr).r[1]) >> 20) & 0x00000007) +#define SD_SCR_GET_SD_SECURITY_FROM_R1(r) (((uint32_t)(r) >> 20) & 0x00000007) + +#define SD_SECURITY_NONE 0 /* no security */ +#define SD_SECURITY_1_01 2 /* version 1.01 */ +#define SD_SECURITY_2_0 3 /* version 2.00 */ + +/* Data status after erases */ +#define SD_SCR_GET_DATA_STAT_AFTER_ERASE(scr) (((uint32_t)((scr).r[1]) >> 23) & 0x00000001) +#define SD_SCR_GET_DATA_STAT_AFTER_ERASE_FROM_R1(r) (((uint32_t)(r) >> 23) & 0x00000001) + +/* SD memory card spec version */ +#define SD_SCR_GET_SD_SPEC(scr) (((uint32_t)((scr).r[1]) >> 24) & 0x0000000f) +#define SD_SCR_GET_SD_SPEC_FROM_R1(r) (((uint32_t)(r) >> 24) & 0x0000000f) + +#define SD_SPEC_1_0 0 /* version 1.0 ~ 1.01 */ +#define SD_SPEC_1_1 1 /* version 1.10 */ +#define SD_SPEC_2_0 2 /* version 2.00 */ + +/* SCR structure */ +#define SD_SCR_GET_SCR_STRUCTURE(scr) (((uint32_t)((scr).r[1]) >> 28) & 0x0000000f) +#define SD_SCR_GET_SCR_STRUCTURE_FROM_R1(r) (((uint32_t)(r) >> 28) & 0x0000000f) + +#define SD_SCR_VERSION_1_0 0 + +/* + * CSR - Card Status Register + * Width: 32 bits + * Readback: CMD13_SEND_STATUS/R1 + */ +typedef SD_R32 SD_CSR; + +/* Bit field defines of CSR */ +#define SD_CSR_AKE_SEQ_ERROR 0x00000008 /* error in the sequence of authentication */ +#define SD_CSR_APP_CMD 0x00000020 /* card expects ACMD or the command has been interpreted as ACMD */ +#define SD_CSR_READY_FOR_DATA 0x00000100 /* buffer empty signaling on the bus */ +#define SD_CSR_CURRENT_STATE_MASK 0x00001e00 /* the state of the card when receiving the command */ +#define SD_CSR_CURRENT_STATE_SHIFT 9 +#define SD_CSR_ERASE_RESET 0x00002000 /* a erase sequence was cleared before execution due to out of erase sequence commands */ +#define SD_CSR_CARD_ECC_DISABLE 0x00004000 /* command was executed without using internal ECC */ +#define SD_CSR_WP_ERASE_SKIP 0x00008000 /* attempt to partial erase of write protected blocks */ +#define SD_CSR_CSD_OVERWRITE 0x00010000 /* attempt to 1) CSD ro fields mismatch, 2) reverse copy or perm wp bits */ +#define SD_CSR_ERROR 0x00080000 /* general error */ +#define SD_CSR_CC_ERROR 0x00100000 /* internal card controller error */ +#define SD_CSR_CARD_ECC_FAILED 0x00200000 /* card internal ECC was applied but failed to correct the data */ +#define SD_CSR_ILLEGAL_COMMAND 0x00400000 /* command illegal for the card state */ +#define SD_CSR_COM_CRC_ERROR 0x00800000 /* command crc check failed */ +#define SD_CSR_LOCK_UNLOCK_FAILED 0x01000000 /* password error in lock/unlock command */ +#define SD_CSR_CARD_IS_LOCKED 0x02000000 /* card is locked by the host */ +#define SD_CSR_WP_VIOLATION 0x04000000 /* attempts to write a protected block */ +#define SD_CSR_ERASE_PARAM 0x08000000 /* invlaid selection of write blocks for erase */ +#define SD_CSR_ERASE_SEQ_ERROR 0x10000000 /* error in erase command sequence */ +#define SD_CSR_BLOCK_LEN_ERROR 0x20000000 /* transferred block length is not allowed or transferred bytes mismatch the block length */ +#define SD_CSR_ADDRESS_ERROR 0x40000000 /* misaligned address which did not match the block length */ +#define SD_CSR_OUT_OF_RANGE 0x80000000 /* command argument was out of allowed range */ + +/* Error in the sequence of the authentication process */ +#define SD_CSR_GET_AKE_SEQ_ERROR(csr) (((uint32_t)((csr).r[0]) >> 3) & 0x00000001) +#define SD_CSR_GET_AKE_SEQ_ERROR_FROM_R(r) (((uint32_t)(r) >> 3) & 0x00000001) + +/* Card is now expect ACMD, or the command has been interpreted as ACMD */ +#define SD_CSR_GET_APP_CMD(csr) (((uint32_t)((csr).r[0]) >> 5) & 0x00000001) +#define SD_CSR_GET_APP_CMD_FROM_R(r) (((uint32_t)(r) >> 5) & 0x00000001) + +/* Corresponds to buffer empty signaling on the bus */ +#define SD_CSR_GET_READY_FOR_DATA(csr) (((uint32_t)((csr).r[0]) >> 8) & 0x00000001) +#define SD_CSR_GET_READY_FOR_DATA_FROM_R(r) (((uint32_t)(r) >> 8) & 0x00000001) + +/* + * The state of the card when receiving the the command + * (visible in the response of the next command) + */ +#define SD_CSR_GET_CURRENT_STATE(csr) (((uint32_t)((csr).r[0]) >> 9) & 0x0000000f) +#define SD_CSR_GET_CURRENT_STATE_FROM_R(r) (((uint32_t)(r) >> 9) & 0x0000000f) + +#define SD_STATE_IDLE 0 +#define SD_STATE_READY 1 +#define SD_STATE_IDENT 2 +#define SD_STATE_STBY 3 +#define SD_STATE_TRAN 4 +#define SD_STATE_DATA 5 +#define SD_STATE_RCV 6 +#define SD_STATE_PRG 7 +#define SD_STATE_DIS 8 + +/* An erase sequence was cleared due to out of erase sequence command */ +#define SD_CSR_GET_ERASE_RESET(csr) (((uint32_t)((csr).r[0]) >> 13) & 0x00000001) +#define SD_CSR_GET_ERASE_RESET_FROM_R(r) (((uint32_t)(r) >> 13) & 0x00000001) + +/* The command has been executed without using internal ECC */ +#define SD_CSR_GET_CARD_ECC_DISABLED(csr) (((uint32_t)((csr).r[0]) >> 14) & 0x00000001) +#define SD_CSR_GET_CARD_ECC_DISABLED_FROM_R(r) (((uint32_t)(r) >> 14) & 0x00000001) + +/* Set only when partial address erase was erased due to write protected (tmp/perm) blocks */ +#define SD_CSR_GET_WP_ERASE_SKIP(csr) (((uint32_t)((csr).r[0]) >> 15) & 0x00000001) +#define SD_CSR_GET_WP_ERASE_SKIP_FROM_R(r) (((uint32_t)(r) >> 15) & 0x00000001) + +/* Set when 1) read-only section of the CSD mismatch, 2) attempt to reverse copy or permanent WP bits */ +#define SD_CSR_GET_CSD_OVERWRITE(csr) (((uint32_t)((csr).r[0]) >> 16) & 0x00000001) +#define SD_CSR_GET_CSD_OVERWRITE_FROM_R(r) (((uint32_t)(r) >> 16) & 0x00000001) + +/* General error or unknown error */ +#define SD_CSR_GET_ERROR(csr) (((uint32_t)((csr).r[0]) >> 19) & 0x00000001) +#define SD_CSR_GET_ERROR_FROM_R(r) (((uint32_t)(r) >> 19) & 0x00000001) + +/* Internal card controller error */ +#define SD_CSR_GET_CC_ERROR(csr) (((uint32_t)((csr).r[0]) >> 20) & 0x00000001) +#define SD_CSR_GET_CC_ERROR_FROM_R(r) (((uint32_t)(r) >> 20) & 0x00000001) + +/* Card internal ECC was applied but failed to correct the data */ +#define SD_CSR_GET_CARD_ECC_FAILED(csr) (((uint32_t)((csr).r[0]) >> 21) & 0x00000001) +#define SD_CSR_GET_CARD_ECC_FAILED_FROM_R(r) (((uint32_t)(r) >> 21) & 0x00000001) + +/* Command not legalfor the card state */ +#define SD_CSR_GET_ILLEGAL_COMMAND(csr) (((uint32_t)((csr).r[0]) >> 22) & 0x00000001) +#define SD_CSR_GET_ILLEGAL_COMMAND_FROM_R(r) (((uint32_t)(r) >> 22) & 0x00000001) + +/* The CRC check of previous command failed */ +#define SD_CSR_GET_COM_CRC_ERROR(csr) (((uint32_t)((csr).r[0]) >> 23) & 0x00000001) +#define SD_CSR_GET_COM_CRC_ERROR_FROM_R(r) (((uint32_t)(r) >> 23) & 0x00000001) + +/* Set when a sequece or password error has been detected in lock/unlock card command */ +#define SD_CSR_GET_LOCK_UNLOCK_FAILED(csr) (((uint32_t)((csr).r[0]) >> 24) & 0x00000001) +#define SD_CSR_GET_LOCK_UNLOCK_FAILED_FROM_R(r) (((uint32_t)(r) >> 24) & 0x00000001) + +/* Signals that the card is locked by the host */ +#define SD_CSR_GET_CARD_IS_LOCKED(csr) (((uint32_t)((csr).r[0]) >> 25) & 0x00000001) +#define SD_CSR_GET_CARD_IS_LOCKED_FROM_R(r) (((uint32_t)(r) >> 25) & 0x00000001) + +/* Set when the host attempts to write protected block or tmp/perm protected card */ +#define SD_CSR_GET_WP_VIOLATION(csr) (((uint32_t)((csr).r[0]) >> 26) & 0x00000001) +#define SD_CSR_GET_WP_VIOLATION_FROM_R(r) (((uint32_t)(r) >> 26) & 0x00000001) + +/* An invalid selection of write-blocks for erase occured */ +#define SD_CSR_GET_ERASE_PARAM(csr) (((uint32_t)((csr).r[0]) >> 27) & 0x00000001) +#define SD_CSR_GET_ERASE_PARAM_FROM_R(r) (((uint32_t)(r) >> 27) & 0x00000001) + +/* An error in the sequence of erase commands occured */ +#define SD_CSR_GET_ERASE_SEQ_ERROR(csr) (((uint32_t)((csr).r[0]) >> 28) & 0x00000001) +#define SD_CSR_GET_ERASE_SEQ_ERROR_FROM_R(r) (((uint32_t)(r) >> 28) & 0x00000001) + +/* Transferred block length is not allowed or transferred length does not match block length */ +#define SD_CSR_GET_BLOCK_LEN_ERROR(csr) (((uint32_t)((csr).r[0]) >> 29) & 0x00000001) +#define SD_CSR_GET_BLOCK_LEN_ERROR_FROM_R(r) (((uint32_t)(r) >> 29) & 0x00000001) + +/* Misaligned address which did not match the block length was used in the command */ +#define SD_CSR_GET_ADDRESS_ERROR(csr) (((uint32_t)((csr).r[0]) >> 30) & 0x00000001) +#define SD_CSR_GET_ADDRESS_ERROR_FROM_R(r) (((uint32_t)(r) >> 30) & 0x00000001) + +/* Command argument out of range or this card */ +#define SD_CSR_GET_OUT_OF_RANGE(csr) (((uint32_t)((csr).r[0]) >> 31) & 0x00000001) +#define SD_CSR_GET_OUT_OF_RANGE_FROM_R(r) (((uint32_t)(r) >> 31) & 0x00000001) + +/* Check all data error bits at once */ +#define SD_CSR_CHECK_ERROR_BITS(csr) ((uint32_t)((csr).r[0]) & (SD_CSR_AKE_SEQ_ERROR | SD_CSR_ERASE_RESET | \ + SD_CSR_WP_ERASE_SKIP | SD_CSR_CSD_OVERWRITE | \ + SD_CSR_ERROR | SD_CSR_CC_ERROR | SD_CSR_CARD_ECC_FAILED | \ + /*SD_CSR_ILLEGAL_COMMAND |*/ SD_CSR_COM_CRC_ERROR | SD_CSR_LOCK_UNLOCK_FAILED | \ + SD_CSR_CARD_IS_LOCKED | SD_CSR_WP_VIOLATION | SD_CSR_ERASE_PARAM | \ + SD_CSR_ERASE_SEQ_ERROR | SD_CSR_BLOCK_LEN_ERROR | SD_CSR_ADDRESS_ERROR | \ + SD_CSR_OUT_OF_RANGE)) +/* + * SSR - SD Status Register + * Width: 512 bits + * Readback: ACMD13_SD_STATUS/DAT0 + */ +#if 0 +typedef struct _SD_SSR { + /* + * Note: The bitfields definition was not applied due to that the + * core architecture may be switched between big-endian + * and little endian. We don't want to define two structures + * to switch between the two endain architectures. Users + * could use following macros to extract the target member. + */ + union { + uint32_t r[16]; + uint8_t b[64]; + }; +} SD_SSR; +#endif + +/* Fixed offset value added to erase time */ +#define SD_SSR_GET_ERASE_OFFSET(ssr) (((uint32_t)((csr).b[50]) >> 0) & 0x00000003) + +/* Timeout value for erasing areas specified by UINT_OF_ERASE_AU */ +#define SD_SSR_GET_ERASE_TIMEOUT(ssr) (((uint32_t)((csr).b[50]) >> 2) & 0x0000003f) + +/* Number of AUs to be erased at a time */ +#define SD_SSR_GET_ERASE_SIZE(ssr) (((uint32_t)((csr).b[52]) << 8) | (uint32_t)((csr).b[51])) + +/* Size of AU */ +#define SD_SSR_GET_AU_SIZE(ssr) ((uint32_t)((csr).b[53]) >> 4) + +#define SD_AU_SIZE_NONE 0x00 +#define SD_AU_SIZE_16KB 0x01 +#define SD_AU_SIZE_32KB 0x02 +#define SD_AU_SIZE_64KB 0x03 +#define SD_AU_SIZE_128KB 0x04 +#define SD_AU_SIZE_256KB 0x05 +#define SD_AU_SIZE_512KB 0x06 +#define SD_AU_SIZE_1MB 0x07 +#define SD_AU_SIZE_2MB 0x08 +#define SD_AU_SIZE_4MB 0x09 + +/* Performance of move indicated by 1 MB/s step */ +#define SD_SSR_GET_PERFORMANCE_MOVE(ssr) ((uint32_t)((csr).b[54])) + +/* Speed class of the card */ +#define SD_SSR_GET_SPEED_CLASS(ssr) ((uint32_t)((csr).b[55])) + +#define SD_SPEED_CLASS_0 0x00 +#define SD_SPEED_CLASS_2 0x01 +#define SD_SPEED_CLASS_4 0x02 +#define SD_SPEED_CLASS_6 0x03 + +/* Size of protected area */ +#define SD_SSR_GET_SIZE_OF_PROTECTED_AREA(ssr) ((uint32_t)((csr).r[14])) + +/* SD memory card type */ +#define SD_SSR_GET_SD_CARD_TYPE(ssr) (((uint32_t)((csr).r[15]) >> 0) & 0x0000ffff) + +#define SD_CARD_TYPE_REGULAR 0x0000 +#define SD_CARD_TYPE_ROM 0x0001 + +/* Card in secured mode operation */ +#define SD_SSR_GET_SECURED_MODE(ssr) (((uint32_t)((csr).b[63]) >> 5) & 0x00000001) + +/* Shows the current defined data bus width defined by ACMD6_SET_BUS_WIDTH */ +#define SD_SSR_GET_DAT_BUS_WIDTH(ssr) (((uint32_t)((csr).b[63]) >> 6) & 0x00000003) + +/***************************************************************************** + * Secure Digital Memory Card Command Definitions + * + ****************************************************************************/ + +/* + * Class 0 - Basic Commands + * Responses: + * R1-R3, R6 + * Registers: + * CID, CSD, DSR + */ +#define SD_CMD0_GO_IDLE_STATE 0 /* Resets all cards to idle state */ +#define SD_CMD2_ALL_SEND_CID 2 /* Ask any card to send the CID numbers */ +#define SD_CMD3_SEND_RELATIVE_ADDR 3 /* Ask the card to publish a new relative address */ +#define SD_CMD4_SET_DSR 4 /* Programs the DSR of of all cards */ +#define SD_CMD7_SELECT_DESELECT_CARD 7 /* Selected (its own relative address), deselected (other address) */ + +#define SD_CMD8_SEND_IF_COND 8 /* Sends SD Memory Card interface condition */ +#define SD_CMD8_MAKE_ARG(vhs, ptn) ((((uint32_t)(vhs) & 0x0f) << 8) | ((uint32_t)(ptn) & 0xff)) +#define SD_VHS_2_7V_3_6V 0x01 +#define SD_VHS_LOW_VOLTAGE 0x02 +#define SD_CMD8_DEFAULT_PTN 0xaa /* spec 20 suggested test pattern */ + +#define SD_CMD9_SEND_CSD 9 /* Addressed card sends its card-specific data (CSD) on the cmd line */ +#define SD_CMD10_SEND_CID 10 /* Addressed card send its card-identification (CID) on the cmd line */ +#define SD_CMD12_STOP_TRANSMISSION 12 /* Forces the card to stop transmission */ +#define SD_CMD13_SEND_STATUS 13 /* Addressed card sends its status register */ +#define SD_CMD15_GO_INACTIVE_STATE 15 /* Sends an addressed card into the inactive state */ + +/* + * Class 2 - Block-Oriented Read Commands + * Responses: + * R1 + */ +#define SD_CMD16_SET_BLOCKLEN 16 /* Sets the block length for all following block commands (std cap.: read/write/lock, high cap.: lock) */ +#define SD_CMD17_READ_SINGLE_BLOCK 17 /* Reads a block of size (std: SET_BLOCKLEN, high: 512) */ +#define SD_CMD18_READ_MULTIPLE_BLOCK 18 /* Continuously transfers data from card to host until interrupted by a STOP_TRANSMISSION command */ + +/* + * Class 4 - Block-Oriented Write Commands + * Responses: + * R1 + * Registers: + * CSD + */ +#define SD_CMD24_WRITE_BLOCK 24 /* Writes a block of the size (srd: SET_BLOCKLEN, high: 512) */ +#define SD_CMD25_WRITE_MULTIPLE_BLOCK 25 /* Continuously writes block of data until interrupted by a STOP_TRANSMISSION command */ +#define SD_CMD27_PROGRAM_CSD 27 /* Programming of the programmable bits of the CSD */ + +/* + * Class 6 - Block-Oriented Write Protection Commands + * Responses: + * R1 + */ +#define SD_CMD28_SET_WRITE_PROT 28 /* Std: Sets the write protection bit of the addressed group, high: not supported */ +#define SD_CMD29_CLR_WRITE_PROT 29 /* Std: clears the write protection bit of the addressed group, high: not supported */ +#define SD_CMD30_SEND_WRITE_PROT 30 /* Std: ask the card to send the status of the write protection bits, high: not supported */ + +/* + * Class 5 - Erase Commands + * Responses: + * R1 + */ +#define SD_CMD32_ERASE_WR_BLK_START 32 /* Sets the address of the first write block to be erased */ +#define SD_CMD33_ERASE_WR_BLK_END 33 /* Sets the address of the last write block of the continuous range to be erased */ +#define SD_CMD38_ERASE 38 /* Erase all previously selected write blocks */ + +/* + * Class 7 - Lock Card Commands + * Responses: + * R1 + */ +#define SD_CMD42_LOCK_UNLOCK 42 /* To set/reset the password or lock/unlock the card (SET_BLOCKLEN) */ + +/* + * Class 8 - Application Specific Commands + * Responses: + * R1 + * Registers: + * SCR + */ +#define SD_CMD55_APP_CMD 55 /* Indicates to the card that the next command is an application specific command */ +#define SD_CMD56_GEN_CMD 56 /* Used to transfer/get a data block to/from the card for general purpose/application specific commands (SET_BLOCKLEN) */ + +#define SD_ACMD6_SET_BUS_WIDTH 6 /* Defines the data bus width to be used for data thransfer (allowed: SCR) */ +#define SD_BUS_WIDTH_ARG_1BIT 0 +#define SD_BUS_WIDTH_ARG_4BIT 2 +#define SD_ACMD6_MAKE_ARG(bw) ((uint32_t)(bw) & 0x00000003) + +#define SD_ACMD13_SD_STATUS 13 /* Send the SD status (table 4-37) */ +#define SD_ACMD22_SEND_NUM_WR_BLOCKS 22 /* Send the number of the written write blocks */ +#define SD_ACMD23_SET_WR_BLK_ERASE_COUNT 23 /* Set the number of write blocks to be preerased before writing */ + +#define SD_ACMD41_SD_SEND_OP_COND 41 /* Sends host capacity support information (HCS) and asks operating condition register (OCR) */ +#define SD_ACMD41_MAKE_ARG(hcs) ((((uint32_t)(hcs) << SD_OCR_CCS_SHIFT) & SD_OCR_CCS_MASK) | SD_OCR_VDD_2_7V_3_6V) +#define SD_HCS_SD 0 /* (Host Capacity Support) Denotes not supporting SDHC */ +#define SD_HCS_SDHC 1 /* (Host Capacity Support) Denotes SDHC support */ + +#define SD_ACMD42_SET_CLR_CARD_DETECT 42 /* Connect/Disconnect the 50KOhm pull-up resister on CD/DAT3 of the card */ +#define SD_ACMD51_SEND_SCR 51 /* Reads the SD configuration register (SCR) */ + +/* + * Class 10 - Application Specific Commands + * Responses: + * R1 + */ +#define SD_CMD6_SWITCH_FUNC 6 /* Checks switchable function (mode 0) and switch card function (mode 1) */ + +/***************************************************************************** + * SD Internal Programming Interfaces + * + ****************************************************************************/ + +/* PIO SD command retry counts */ +#define SD_CMD_MAX_RETRY_COUNT 0x10000 +#define SD_ACMD41_MAX_RETRY_COUNT 0x100 +#define SD_READ_MAX_RETRY_COUNT 0x1000 +#define SD_WRITE_MAX_RETRY_COUNT 0x2000 +#define SD_STATE_MAX_RETRY_COUNT 0x1000 +#define SD_TRANSFER_MAX_RETRY_COUNT 0x1000 + +/* SD command predefined to be sent to the SDC */ +/* Class 0 - Basic Commands */ +#define SDC_CMD0_GO_IDLE_STATE \ + ((SD_CMD0_GO_IDLE_STATE & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK) +#define SDC_CMD2_ALL_SEND_CID \ + ((SD_CMD2_ALL_SEND_CID & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_LONG_RSP_MASK) +#define SDC_CMD3_SEND_RELATIVE_ADDR \ + ((SD_CMD3_SEND_RELATIVE_ADDR & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD4_SET_DSR \ + ((SD_CMD4_SET_DSR & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK) +#define SDC_CMD7_SELECT_DESELECT_CARD \ + ((SD_CMD7_SELECT_DESELECT_CARD & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD8_SEND_IF_COND \ + ((SD_CMD8_SEND_IF_COND & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD9_SEND_CSD \ + ((SD_CMD9_SEND_CSD & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_LONG_RSP_MASK) +#define SDC_CMD10_SEND_CID \ + ((SD_CMD10_SEND_CID & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_LONG_RSP_MASK) +#define SDC_CMD12_STOP_TRANSMISSION \ + ((SD_CMD12_STOP_TRANSMISSION & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD13_SEND_STATUS \ + ((SD_CMD13_SEND_STATUS & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD15_GO_INACTIVE_STATE \ + ((SD_CMD15_GO_INACTIVE_STATE & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK) +/* Class 2 - Block-Oriented Read Commands */ +#define SDC_CMD16_SET_BLOCKLEN \ + ((SD_CMD16_SET_BLOCKLEN & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD17_READ_SINGLE_BLOCK \ + ((SD_CMD17_READ_SINGLE_BLOCK & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD18_READ_MULTIPLE_BLOCK \ + ((SD_CMD18_READ_MULTIPLE_BLOCK & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +/* Class 4 - Block-Oriented Write Commands */ +#define SDC_CMD24_WRITE_BLOCK \ + ((SD_CMD24_WRITE_BLOCK & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD25_WRITE_MULTIPLE_BLOCK \ + ((SD_CMD25_WRITE_MULTIPLE_BLOCK & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD27_PROGRAM_CSD \ + ((SD_CMD27_PROGRAM_CSD & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +/* Class 6 - Block-Oriented Write Protection Commands */ +#define SDC_CMD28_SET_WRITE_PROT \ + ((SD_CMD28_SET_WRITE_PROT & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD29_CLR_WRITE_PROT \ + ((SD_CMD29_CLR_WRITE_PROT & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD30_SEND_WRITE_PROT \ + ((SD_CMD30_SEND_WRITE_PROT & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +/* Class 5 - Erase Commands */ +#define SDC_CMD32_ERASE_WR_BLK_START \ + ((SD_CMD32_ERASE_WR_BLK_START & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD33_ERASE_WR_BLK_END \ + ((SD_CMD33_ERASE_WR_BLK_END & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD38_ERASE \ + ((SD_CMD38_ERASE & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +/* Class 7 - Lock Card Commands */ +#define SDC_CMD42_LOCK_UNLOCK \ + ((SD_CMD42_LOCK_UNLOCK & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +/* Class 8 - Application Specific Commands */ +#define SDC_CMD55_APP_CMD \ + ((SD_CMD55_APP_CMD & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_CMD56_GEN_CMD \ + ((SD_CMD56_GEN_CMD & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) +#define SDC_ACMD6_SET_BUS_WIDTH \ + ((SD_ACMD6_SET_BUS_WIDTH & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +#define SDC_ACMD13_SD_STATUS \ + ((SD_ACMD13_SD_STATUS & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +#define SDC_ACMD22_SEND_NUM_WR_BLOCKS \ + ((SD_ACMD22_SEND_NUM_WR_BLOCKS & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +#define SDC_ACMD23_SET_WR_BLK_ERASE_COUNT \ + ((SD_ACMD23_SET_WR_BLK_ERASE_COUNT & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +#define SDC_ACMD41_SD_SEND_OP_COND \ + ((SD_ACMD41_SD_SEND_OP_COND & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +#define SDC_ACMD42_SET_CLR_CARD_DETECT \ + ((SD_ACMD42_SET_CLR_CARD_DETECT & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +#define SDC_ACMD51_SEND_SCR \ + ((SD_ACMD51_SEND_SCR & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK | SDC_APP_CMD_MASK) +/* Class 10 - Application Specific Commands */ +#define SDC_CMD6_SWITCH_FUNC \ + ((SD_CMD6_SWITCH_FUNC & SDC_CMD_IDX_MASK) | SDC_CMD_EN_MASK | SDC_NEED_RSP_MASK) + +/* SD command interfaces */ +#if (SDD_SMALL_SD_FOOTPRINT == 0) +extern uint32_t _sd_cmd0(void); +extern uint32_t _sd_cmd4(uint32_t dsr); +extern uint32_t _sd_cmd10(uint32_t rca, SD_CID * cid); +extern uint32_t _sd_cmd15(uint32_t rca); +extern uint32_t _sd_cmd17(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd24(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd27(SD_R32 * csr); +extern uint32_t _sd_cmd28(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd29(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd30(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd32(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd33(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd38(SD_R32 * csr); +extern uint32_t _sd_cmd42(SD_R32 * csr); +extern uint32_t _sd_cmd56(uint32_t rdwr, SD_R32 * csr); +extern uint32_t _sd_acmd22(SD_R32 * csr); +extern uint32_t _sd_acmd23(uint32_t blocks, SD_R32 * csr); +extern uint32_t _sd_acmd42(uint32_t conn, SD_R32 * csr); +extern uint32_t _sd_cmd6(uint32_t mode, SD_R32 * csr); +#endif /* (SDD_SMALL_SD_FOOTPRINT == 0) */ + +extern uint32_t _sd_cmd2(SD_CID * cid); +extern uint32_t _sd_cmd3(SD_R32 * rca); +extern uint32_t _sd_cmd7(uint32_t rca, SD_R32 * csr); +extern uint32_t _sd_cmd8(uint32_t vhs_arg, SD_R32 * vhs_rsp); +extern uint32_t _sd_cmd9(uint32_t rca, SD_CSD * csd); +extern uint32_t _sd_cmd12(SD_R32 * csr); +extern uint32_t _sd_cmd13(uint32_t rca, SD_R32 * csr); +extern uint32_t _sd_cmd16(uint32_t blk_len, SD_R32 * csr); +extern uint32_t _sd_cmd18(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd25(uint32_t addr, SD_R32 * csr); +extern uint32_t _sd_cmd55(uint32_t rca, SD_R32 * csr); +extern uint32_t _sd_acmd6(uint32_t bw, SD_R32 * csr); +extern uint32_t _sd_acmd13(SD_R32 * csr); +extern uint32_t _sd_acmd41(uint32_t hcs, SD_OCR * ocr); +extern uint32_t _sd_acmd51(SD_R32 * csr); + +/* Data transfer mode state transition routines */ +// extern uint32_t _sd_wait_sending_state(uint32_t rca); +// extern uint32_t _sd_wait_receiving_state(uint32_t rca); +extern uint32_t _sd_wait_programmed(uint32_t rca); +extern uint32_t _sd_wait_transferred(uint32_t rca); +extern uint32_t _sd_disconnect(uint32_t rca); +extern uint32_t _sd_connect(uint32_t rca); +extern uint32_t _sd_deselect_card(uint32_t rca); +extern uint32_t _sd_select_card(uint32_t rca); +extern uint32_t _sd_stop_transmission(uint32_t rca); + +#endif /* __SDD_SD_H__ */ diff --git a/bsp/AE210P/driver/ssp/Kbuild b/bsp/AE210P/driver/ssp/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..5378bb007514cb07e5a2f5509c6ddbc2663a92de --- /dev/null +++ b/bsp/AE210P/driver/ssp/Kbuild @@ -0,0 +1 @@ +lib-${CONFIG_FTSSP010} := sspd_ac97.o sspd_rts.o diff --git a/bsp/AE210P/driver/ssp/sspd_ac97.c b/bsp/AE210P/driver/ssp/sspd_ac97.c new file mode 100644 index 0000000000000000000000000000000000000000..1425d2340133a78ae1e592e4c70f7553f45ee917 --- /dev/null +++ b/bsp/AE210P/driver/ssp/sspd_ac97.c @@ -0,0 +1,300 @@ +#include "hal.h" +#include "dma/dmad.h" + +#include "sspd_ac97.h" + +/* SSP FIFO properties */ +#define SSPD_HW_TXFIFO_DEPTH 16 /* TX FIFO size, units of 32bit (todo: HW readback?) */ +#define SSPD_HW_RXFIFO_DEPTH 16 /* RX FIFO size, units of 32bit (todo: HW readback?) */ + +/***************************************************************************** + * Data size for each each DMA request + * + * Adjust hint: + * + * AC97DMA_REQ_FRAMES sampling_rate effective data_size(2ch) data_size(6ch) + * ------------------------------------------------------------------------------ + * 4096 48k (ac97-fix) 85.33 ms 32768 bytes 98304 bytes + * 8192 48k (ac97-fix) 170.66 ms 65536 bytes 196608 bytes + * 10240 48k (ac97-fix) 213.33 ms 81920 bytes 245760 bytes + * 12288 48k (ac97-fix) 256.00 ms 98304 bytes 294912 bytes + * 20480 48k (ac97-fix) 426.66 ms 163840 bytes 491520 bytes + ****************************************************************************/ +#define AC97DMA_REQ_FRAMES (20480) /* number of frames */ + +#define AC97_RESET_WAIT (0x600000) /* polling loop counter for waiting hw-reset */ + +enum SSPD_AC97_RESET { + + SSPD_AC97_COLDRESET, /* All AC97 logic is initialized to its default state */ + SSPD_AC97_WARMRESET, /* Contents of AC97 registers are left unaltered */ + SSPD_AC97_REGRESET, /* Only Initialize the AC97 registers to their default states */ +}; + +void sspd_ac97_sdata_out(uint32_t *txb, int cnt) +{ + while (cnt > 0) { + + uint32_t tfve; + + /* Check room in TX FIFO */ + tfve = MASK32(I2SAC97_SR, SSPC_SR_TFVE_MASK) >> SSPC_SR_TFVE_SHIFT; + + /* Burst send to TX FIFO */ + while (tfve++ < SSPD_HW_TXFIFO_DEPTH) { + + /* Send one 32-bit word to TX FIFO */ + OUT32(I2SAC97_DR, *txb++); + + if (--cnt == 0) + break; + } + } +} + +void sspd_ac97_cmd_out(int regidx, uint32_t data) +{ + uint32_t txb[16]; + + /* Prepare AC97 write register address (slot1) and data (slot2) */ + AC97_MAKE_WCMD(txb, regidx, data); + + /* Clear SSP FIFO garbage */ + SETR32(I2SAC97_CR2, SSPC_C2_RXFCLR_MASK | SSPC_C2_TXFCLR_MASK); + + /* Set frame-tag slot-valid bits */ + OUT32(I2SAC97_ACLINK, SSPC_AC97_WCMD_SLOTS_MASK | SSPC_AC97_MAKE_CODECID(0)); + + /* Feed data to TX FIFO -- AC97 CR-write contains 2 slots */ + + /* + * [??] According to AC97 2.1 spec, stuff bits with 0 has to be at their + * position during the slot's active time. SSP will smart enough to + * identify giving valid slots and auto stuffs 0s to empty slots in TX + * mode? And whot about the same question in RX mode? + */ + + sspd_ac97_sdata_out(txb, SSPC_AC97_WCMD_SLOTS); + + /* Enable SSP TX data out */ + SETR32(I2SAC97_CR2, SSPC_C2_TXDOE_MASK | SSPC_C2_SSPEN_MASK); + + while (MASK32(I2SAC97_SR, SSPC_SR_TFVE_MASK)) + ; + + /* Disable SSP TX data out */ + CLRR32(I2SAC97_CR2, SSPC_C2_TXDOE_MASK | SSPC_C2_SSPEN_MASK); +} + +void sspd_ac97_reset(enum SSPD_AC97_RESET rest_type) +{ + uint32_t core_intl; + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Disable SSP interrupts */ + CLRR32(I2SAC97_INTCR, SSPC_INTCR_RFORIEN_MASK | SSPC_INTCR_TFURIEN_MASK | + SSPC_INTCR_RFTHIEN_MASK | SSPC_INTCR_TFTHIEN_MASK | + SSPC_INTCR_RFDMAEN_MASK | SSPC_INTCR_TFDMAEN_MASK | + SSPC_INTCR_AC97FCEN_MASK); + + /* Disable SSP data out */ + CLRR32(I2SAC97_CR2, SSPC_C2_SSPEN_MASK | SSPC_C2_TXDOE_MASK); + + /* Disable DMA request FIFO trigger */ + CLRR32(I2SAC97_INTCR, SSPC_INTCR_TFDMAEN_MASK | SSPC_INTCR_RFDMAEN_MASK); + + /* Clear FIFO garbage */ + SETR32(I2SAC97_CR2, SSPC_C2_RXFCLR_MASK | SSPC_C2_TXFCLR_MASK); + + /* Set SSP frame format as AC97 */ + SETR32SHL(I2SAC97_CR0, SSPC_C0_FFMT_MASK, SSPC_C0_FFMT_SHIFT, SSPC_INTEL_ACLINK); + + switch (rest_type) { + + case SSPD_AC97_COLDRESET: /* All AC97 logic is initialized to its default state */ + + /* (reset time: SSPCLK * SCLK_DIV) */ + DEBUG(1, 1, "SSPD_AC97_COLDRESET\n"); + SETB32(I2SAC97_CR2, SSPC_C2_ACCRST_BIT); + + while (GETB32(I2SAC97_CR2, SSPC_C2_ACCRST_BIT)) + ; + _nds_kwait(AC97_RESET_WAIT); + + break; + case SSPD_AC97_WARMRESET: /* Contents of AC97 registers are left unaltered */ + + /* (reset time: SSPCLK * SCLK_DIV, or wait ACWRST cleared) */ + DEBUG(1, 1, "SSPD_AC97_WARMRESET\n"); + SETB32(I2SAC97_CR2, SSPC_C2_ACWRST_BIT); + + while (GETB32(I2SAC97_CR2, SSPC_C2_ACWRST_BIT)) + ; + + break; + case SSPD_AC97_REGRESET: /* Only Initialize the AC97 registers to their default states */ + + DEBUG(1, 1, "SSPD_AC97_REGRESET\n"); + + /* Write AC97 reset register to do codec register reset */ + sspd_ac97_cmd_out(AC97_CRIDX_RESET, 0); + _nds_kwait(AC97_RESET_WAIT); + + break; + default: + DEBUG(1, 1, "Invalid reset method!\n"); + } + + hal_global_int_ctl(core_intl); +} + +void sspd_ac97_init(void) +{ + uint32_t core_intl; + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* + * Change AC97 codec & SSP clock source + * + * PMU_AC97PINSEL: MFPSR[3] + * 0: X_I2Ssclkout/I2SCLK + * 1: X_ac97_resetn/50MHz in AG101 + * PMU_AC97CLKSEL: MFPSR[4] + * 0: AC97CLK (Set AC97 XTL_IN source is from internal PLL. BIT_CLK is XTL_IN / 2) + * 1: GPIO22 + * PMU_SSPCLKSEL: MFPSR[6] + * 0: SSPCLK + * 1: GPIO25 + * PMU_AC97CLKOUTSEL: MFPSR[13] + * 0: GPIO + * 1: AC97CLK out + */ + + // SETR32(PMU_MFPSR, PMU_AC97PINSEL_MASK | PMU_AC97CLKSEL_MASK | PMU_SSPCLKSEL_MASK | PMU_AC97CLKOUTSEL_MASK); + // SETR32(PMU_MFPSR, PMU_AC97PINSEL_MASK | PMU_AC97CLKOUTSEL_MASK); + // SETB32(PMU_MFPSR, PMU_AC97CLKSEL_BIT); + +#if (MB_AC97_EXT_CLK) + DEBUG(1, 1, "AC97CLK: GPIO22\n"); + SETR32(PMU_MFPSR, PMU_AC97PINSEL_MASK | PMU_AC97CLKSEL_MASK | PMU_AC97CLKOUTSEL_MASK); +#else /* MB_AC97_EXT_CLK */ + DEBUG(1, 1, "AC97CLK: PLL\n"); + SETR32(PMU_MFPSR, PMU_AC97PINSEL_MASK | PMU_AC97CLKOUTSEL_MASK); + CLRB32(PMU_MFPSR, PMU_AC97CLKSEL_BIT); +#endif /* MB_AC97_EXT_CLK */ + + sspd_ac97_reset(SSPD_AC97_COLDRESET); + + /* Setup DMA FIFO trigger threshold */ + SETR32SHL(I2SAC97_INTCR, SSPC_INTCR_TFTHOD_MASK, SSPC_INTCR_TFTHOD_SHIFT, 0); + SETR32SHL(I2SAC97_INTCR, SSPC_INTCR_RFTHOD_MASK, SSPC_INTCR_RFTHOD_SHIFT, 0); + + /* SSP AC97 codec initialization */ + + /* + * Default master volume? + * Default mixer-in gain? + * Default record input selection? + */ + //sspd_ac97_cmd_out(AC97_CRIDX_MASTER_VOLUME, 0); + + hal_global_int_ctl(core_intl); +} + +void sspd_ac97_terminate(void) +{ + uint32_t core_intl; + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* Disable SSP interrupts */ + CLRR32(I2SAC97_INTCR, SSPC_INTCR_RFORIEN_MASK | SSPC_INTCR_TFURIEN_MASK | + SSPC_INTCR_RFTHIEN_MASK | SSPC_INTCR_TFTHIEN_MASK | + SSPC_INTCR_RFDMAEN_MASK | SSPC_INTCR_TFDMAEN_MASK | + SSPC_INTCR_AC97FCEN_MASK); + + /* Disable SSP data out */ + CLRR32(I2SAC97_CR2, SSPC_C2_SSPEN_MASK | SSPC_C2_TXDOE_MASK); + + /* Cold reset AC97 codec */ + SETB32(I2SAC97_CR2, SSPC_C2_ACCRST_BIT); + while (GETB32(I2SAC97_CR2, SSPC_C2_ACCRST_BIT)) + ; + + /* Clear FIFO garbage */ + SETR32(I2SAC97_CR2, SSPC_C2_RXFCLR_MASK | SSPC_C2_TXFCLR_MASK); + + hal_global_int_ctl(core_intl); +} + +void ac97_init(void) +{ + sspd_ac97_init(); + + sspd_ac97_cmd_out(AC97_CRIDX_RESET, 0); + _nds_kwait(AC97_RESET_WAIT); + + sspd_ac97_cmd_out(AC97_CRIDX_PCMOUT_GAIN, + AC97_MIXER_GAIN(AC97_MIXER_MAX, AC97_MIXER_MAX)); + + sspd_ac97_cmd_out(AC97_CRIDX_MASTER_VOLUME, + AC97_STEREO_VOLUME(AC97_VOLUME_MAX - 0x30, AC97_VOLUME_MAX - 0x30)); + + SETR32SHL(I2SAC97_INTCR, SSPC_INTCR_TFTHOD_MASK, SSPC_INTCR_TFTHOD_SHIFT, 4); + SETR32SHL(I2SAC97_INTCR, SSPC_INTCR_RFTHOD_MASK, SSPC_INTCR_RFTHOD_SHIFT, 4); + OUT32(I2SAC97_ACLINK, SSPC_AC97_PCM_SLOTS_MASK | SSPC_AC97_MAKE_CODECID(0)); + SETR32(I2SAC97_INTCR, SSPC_INTCR_TFDMAEN_MASK); + SETR32(I2SAC97_CR2, SSPC_C2_TXDOE_MASK | SSPC_C2_SSPEN_MASK); + SETR32(I2SAC97_CR2, SSPC_C2_RXFCLR_MASK | SSPC_C2_TXFCLR_MASK); +} + +volatile int g_buffered_frames; + +/* No use and marked by KCLin */ +/* +static void psp(void *data) +{ + g_buffered_frames -= *(int*)data; + free(data); + +} +*/ + +static void rcp(void *data) +{ + g_buffered_frames -= *(int*)data; + free(data); +} +extern int ring_idx; +void ac97_play(int frames, uint32_t *pcm_data, void *ac97_data) +{ + DMAD_CHANNEL_REQUEST_DESC *ch_req = ac97_data; + + while (frames > 0){ + + int f; + int *data; + DMAD_DRB *drb; + + f = (frames < AC97DMA_REQ_FRAMES) ? frames : AC97DMA_REQ_FRAMES; + data = malloc(sizeof(int)); + KASSERT(data); + *data = f; + + _dmad_alloc_drb(ch_req, &drb); + + drb->src_addr = pcm_data; + drb->dst_addr = (void *)I2SAC97_DR; + drb->req_size = (f << 1); /* units of data width (32bit for AC97) */ + drb->rcp = rcp; + drb->data = data; + + pcm_data += (f << 1); + g_buffered_frames += f; +// DEBUG(1, 1, "FRAME: %d,%d\n", g_buffered_frames,ring_idx); + _dmad_submit_request(ch_req, drb); + frames -= f; + } +} diff --git a/bsp/AE210P/driver/ssp/sspd_ac97.h b/bsp/AE210P/driver/ssp/sspd_ac97.h new file mode 100644 index 0000000000000000000000000000000000000000..dfeeeab70dfbaf58cfb0770e8dead4c2ffe2abfe --- /dev/null +++ b/bsp/AE210P/driver/ssp/sspd_ac97.h @@ -0,0 +1,444 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Aug.21.2007 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sspd_ac97.c + * + * DESCRIPTION + * + * AC97 codec digital serial interface protocol implementation. + * A SSP AC-link & AC97 controller driver supplement. + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * None + * + ****************************************************************************/ +#ifndef __SSPD_AC97_H__ +#define __SSPD_AC97_H__ + +/***************************************************************************** + * AC97 Audio Frame Definitions + * + ****************************************************************************/ + +/***************************************************************************** + * Definitions for SDATA_OUT frame slots + ****************************************************************************/ +/* Command address port (slot1) */ +#define AC97_CMDADDR_RW_MASK 0x00080000 /* AC97 read/write command */ +#define AC97_CMDADDR_RW_BIT 19 + #define AC97_CMD_WRITE 0 + #define AC97_CMD_READ 1 + +#define AC97_CMDADDR_CRIDX_MASK 0x0007f000 /* AC97 control register index (even addressed) */ +#define AC97_CMDADDR_CRIDX_SHIFT 12 + +/* Command data port (slot2) */ +#define AC97_CMDDATA_MASK 0x000ffff0 /* AC97 command data (16 bits) */ +#define AC97_CMDDATA_SHIFT 4 + +/***************************************************************************** + * Definitions for SDATA_IN frame slots + ****************************************************************************/ +/* Status address port (slot1) */ +#define AC97_STADDR_CRIDX_MASK 0x0007f000 /* Echo of AC97 control register index */ +#define AC97_STADDR_CRIDX_SHIFT 12 + +#define AC97_STADDR_SLOTREQ_MASK 0x00000ffc /* AC97 2.0 Appendex A SLOTREQ bit definitions */ +#define AC97_STADDR_SLOTREQ_SHIFT 2 + +/* Command data port (slot2) */ +#define AC97_STDATA_MASK 0x000ffff0 +#define AC97_STDATA_SHIFT 4 + +/***************************************************************************** + * Definitions for PCM sampling data + ****************************************************************************/ +/* PCM sampling resolution */ +#define AC97_PCM_SR16_MASK 0x000ffff0 /* 16-bit sampling resolution */ +#define AC97_PCM_SR16_SHIFT 4 +#define AC97_PCM_SR18_MASK 0x000ffffc /* 18-bit sampling resolution */ +#define AC97_PCM_SR18_SHIFT 2 +#define AC97_PCM_SR20_MASK 0x000fffff /* 20-bit sampling resolution */ +#define AC97_PCM_SR20_SHIFT 0 + + +/***************************************************************************** + * AC97 Control Register Definitions + ****************************************************************************/ +/* Reset register (index 0x00) */ +#define AC97_CRIDX_RESET 0x00 /* Write any value to do register rest, */ + /* read will return feature implementation id. */ +/* Reset register definitions */ +#define AC97_ID0_DEDICATED_MIC_MASK 0x0001 /* Dedicated mic PCM in channel */ +#define AC97_ID0_DEDICATED_MIC_BIT 0 +#define AC97_ID1_RESERVED_MASK 0x0002 /* Reserved (was modem line codec support) */ +#define AC97_ID1_RESERVED_BIT 1 +#define AC97_ID2_BASE_TREBLE_CTRL_MASK 0x0004 /* Bass and Treble control */ +#define AC97_ID2_BASE_TREBLE_CTRL_BIT 2 +#define AC97_ID3_SIMULATED_STEREO_MASK 0x0008 /* Simulated stereo */ +#define AC97_ID3_SIMULATED_STEREO_BIT 3 +#define AC97_ID4_HEADPHONE_OUT_MASK 0x0010 /* Headphone out support */ +#define AC97_ID4_HEADPHONE_OUT_BIT 4 +#define AC97_ID5_LAUDNESS_MASK 0x0020 /* Loudness (bass boost) support */ +#define AC97_ID5_LAUDNESS_BIT 5 +#define AC97_ID6_18BIT_DAC_MASK 0x0040 /* 18 bit DAC resolution */ +#define AC97_ID6_18BIT_DAC_BIT 6 +#define AC97_ID7_20BIT_DAC_MASK 0x0080 /* 20 bit DAC resolution */ +#define AC97_ID7_20BIT_DAC_BIT 7 +#define AC97_ID8_18BIT_ADC_MASK 0x0100 /* 18 bit ADC resolution */ +#define AC97_ID8_18BIT_ADC_BIT 8 +#define AC97_ID9_20BIT_ADC_MASK 0x0200 /* 20 bit ADC resolution */ +#define AC97_ID9_20BIT_ADC_BIT 9 + +#define AC97_SE_MASK 0x7c /* 3D Stereo Enhancement Technique */ +#define AC97_SE_SHIFT 10 + #define AC97_SE_NONE 0 + #define AC97_SE_PHAT 1 + #define AC97_SE_CREATIVE 2 + #define AC97_SE_NS3D 3 + #define AC97_SE_YMERSION 4 + #define AC97_SE_BBE3D 5 + #define AC97_SE_CRYSTAL3D 6 + #define AC97_SE_QXPANDER 7 + #define AC97_SE_SPATIALIZER3D 8 + #define AC97_SE_SRS3D 9 + #define AC97_SE_PLATFORMTECH3D 10 + #define AC97_SE_AKM3D 11 + #define AC97_SE_AUREAL 12 + #define AC97_SE_AZTECH3D 13 + #define AC97_SE_BINAURA3D 14 + #define AC97_SE_ESS 15 + #define AC97_SE_VMAX 16 + #define AC97_SE_NVIDEA3D 17 + #define AC97_SE_INCREDIBLE 18 + #define AC97_SE_TI3D 19 + #define AC97_SE_VLSI3D 20 + #define AC97_SE_TRITECH3D 21 + #define AC97_SE_REALTECH3D 22 + #define AC97_SE_SAMSUNG3D 23 + #define AC97_SE_WOLFSON3D 24 + #define AC97_SE_DELTA3D 25 + #define AC97_SE_SIGMATEL3D 26 + #define AC97_SE_ROCKWELL3D 28 + +/* Play master volume registers (index 0x02, 0x04, 0x06) */ +#define AC97_CRIDX_MASTER_VOLUME 0x02 /* Stereo master volume register (ML, MR) */ +#define AC97_CRIDX_HEADPHONE_VOLUME 0x04 /* Headphone volume register (ML, MR) */ +#define AC97_CRIDX_MASTER_VOLUME_MONO 0x06 /* Mono master volume register (MM/MR) */ + +/* Play master volume register definitions */ +#define AC97_MR_MASK 0x003f /* Right channel level (1.5dB step) */ +#define AC97_MR_SHIFT 0 +#define AC97_ML_MASK 0x3f00 /* Left channel level */ +#define AC97_ML_SHIFT 8 +#define AC97_MUTE_MASK 0x8000 /* Mute bit (able to keep original level value) */ +#define AC97_MUTE_BIT 15 + + #define AC97_VOLUME_INCSTEP (-1) /* 1.5dB increase step */ + #define AC97_VOLUME_DECSTEP (+1) /* 1.5dB decrease step */ + + #define AC97_VOLUME_0DB_ATTEN 0x00 /* 0 dB attenuation (max) (required) */ + #define AC97_VOLUME_46P5DB_ATTEN 0x1f /* 46.5dB attenuation (required) */ + #define AC97_VOLUME_94P5DB_ATTEN 0x3f /* 94.5dB attenuation (min) (optional) */ + + #define AC97_VOLUME_MAX 0x00 /* 0 dB attenuation (max) (required) */ + #define AC97_VOLUME_MIDDLE 0x1f /* 46.5dB attenuation (required) */ + #define AC97_VOLUME_MIN 0x3f /* 94.5dB attenuation (min) (optional) */ + +/* Master tone control register (index 0x08) */ +#define AC97_CRIDX_MASTER_TONE 0x08 /* Master tone (bass & treble) control register */ + +/* Master tone control register definitions */ +#define AC97_TREBLE_MASK 0x000f /* Tremble level (10kHz center, 1.5dB step) */ +#define AC97_TREBLE_SHIFT 0 +#define AC97_BASS_MASK 0x0f00 /* Base level (100Hz center, 1.5dB step) */ +#define AC97_BASS_SHIFT 8 + + #define AC97_TONE_INCSTEP (-1) /* +1.5dB increase step */ + #define AC97_TONE_DECSTEP (+1) /* -1.5dB decrease step */ + + #define AC97_TONE_MAX 0x00 /* +10.5dB gain */ + #define AC97_TONE_CENTER 0x07 /* 0 dB gain */ + #define AC97_TONE_MIN 0x0e /* -10.5dB gain */ + #define AC97_TONE_BYPASS 0x0f /* Bypass */ + +/* PC beep register (index 0x0a) */ +#define AC97_CRIDX_PCBEEP 0x0a /* PC beep input level control register */ + +/* PC beep register definitions */ +#define AC97_PCBEEP_MASK 0x001e /* Beep level (3dB step) */ +#define AC97_PCBEEP_SHIFT 1 +#define AC97_PCBEEP_MUTE_MASK 0x8000 /* Mute bit (able to keep original level value) */ +#define AC97_PCBEEP_MUTE_BIT 15 + + #define AC97_PCBEEP_INCSTEP (+1) /* 3dB increase step */ + #define AC97_PCBEEP_DECSTEP (-1) /* 3dB decrease step */ + + #define AC97_PCBEEP_0DB 0 /* 0dB */ + #define AC97_PCBEEP_45DB 15 /* 45dB */ + +/* Analog mixer input gain registers (index 0x0c ~ 0x18) */ +#define AC97_CRIDX_PHONE_GAIN 0x0c /* Phone volume input gain control register (GR, M) */ +#define AC97_CRIDX_MIC_GAIN 0x0e /* Microphone volume input gain control register (BOOST, GR, M) */ +#define AC97_CRIDX_LINEIN_GAIN 0x10 /* Line in volume input gain control register (GL, GR, M) */ +#define AC97_CRIDX_CD_GAIN 0x12 /* CD volume input gain control register (GL, GR, M) */ +#define AC97_CRIDX_VIDEO_GAIN 0x14 /* Video volume input gain control register (GL, GR, M) */ +#define AC97_CRIDX_AUX_GAIN 0x16 /* AUX volume input gain control register (GL, GR, M) */ +#define AC97_CRIDX_PCMOUT_GAIN 0x18 /* PCM out from AC97 volume input gain control register (GL, GR, M) */ + +/* + * Phone volume input gain register definitions + * Microphone volume input gain control register definitions + * Line in volume input gain control register definitions + * CD volume input gain control register definitions + * Video volume input gain control register definitions + * AUX volume input gain control register definitions + * PCM out from AC97 volume input gain control register definitions + */ +#define AC97_MIXER_GR_MASK 0x001f /* Mixer input gain right channel (1.5dB step) */ +#define AC97_MIXER_GR_SHIFT 0 +#define AC97_MIXER_GN_MASK AC97_GR_MASK +#define AC97_MIXER_GN_SHIFT AC97_GR_SHIFT +#define AC97_MIXER_GL_MASK 0x1f00 /* Mixer input gain left channel (1.5dB step) */ +#define AC97_MIXER_GL_SHIFT 0 +#define AC97_MIXER_MUTE_MASK 0x8000 /* Mute bit (able to keep original level value) */ +#define AC97_MIXER_MUTE_BIT 15 + + #define AC97_MIXER_INCSTEP (-1) /* 1.5dB increase step */ + #define AC97_MIXER_DECSTEP (+1) /* 1.5dB decrease step */ + + #define AC97_MIXER_MAX 0x00 /* +12.0dB gain */ + #define AC97_MIXER_CENTER 0x08 /* 0 dB gain */ + #define AC97_MIXER_MIN 0x1f /* -34.5dB gain */ + +/* Microphone volume input gain control register specific definitions */ +#define AC97_MIC_VOLUME_BOOST_MASK 0x0040 /* 20dB boost bit */ +#define AC97_MIC_VOLUME_BOOST_BIT 0 + +/* ------------------------------------------------ */ +/* Record select control register (index 0x1a) */ +/* */ +#define AC97_CRIDX_RECORD_SELECT 0x1a /* Record select control register */ + +/* Record select control register definitions */ +#define AC97_RECORD_SR_MASK 0x0007 /* Record select right channel */ +#define AC97_RECORD_SR_SHIFT 0 +#define AC97_RECORD_SL_MASK 0x0700 /* Record select left channel */ +#define AC97_RECORD_SL_SHIFT 8 + + #define AC97_RECORD_SELECT_MIC 0 + #define AC97_RECORD_SELECT_CD 1 + #define AC97_RECORD_SELECT_VIDEO 2 + #define AC97_RECORD_SELECT_AUX 3 + #define AC97_RECORD_SELECT_LINEIN 4 + #define AC97_RECORD_SELECT_STEREOMIX 5 + #define AC97_RECORD_SELECT_MONOMIX 6 + #define AC97_RECORD_SELECT_PHONE 7 + +/* ------------------------------------------------ */ +/* Record gain registers (index 0x1c, 0x1e) */ +/* */ +#define AC97_CRIDX_RECORD_GAIN 0x1c /* Record gain (stereo input) register (GL, GR, M) */ +#define AC97_CRIDX_RECORD_GAIN_MIC 0x1e /* Record gain mic (optional ch3 mic) register (GR, M) */ + +/* Record gain (stereo input) register definitions */ +/* Record gain mic (optional ch3 mic) register definitions */ +#define AC97_RECORD_GR_MASK 0x000f /* Record gain right channel (1.5dB step) */ +#define AC97_RECORD_GR_SHIFT 0 +#define AC97_RECORD_GL_MASK 0x0f00 /* Record gain left channel (1.5dB step) */ +#define AC97_RECORD_GL_SHIFT 8 +#define AC97_RECORD_MUTE_MASK 0x8000 /* Mute bit (able to keep original level value) */ +#define AC97_RECORD_MUTE_BIT 15 + + #define AC97_RECORD_INCSTEP (+1) /* 1.5dB increase step */ + #define AC97_RECORD_DECSTEP (-1) /* 1.5dB decrease step */ + + #define AC97_RECORD_0DB 0x00 /* 0.0dB gain */ + #define AC97_RECORD_22P5DB 0x0f /* +22.5dB gain */ + +/* ------------------------------------------------ */ +/* General purpose register (index 0x20) */ +/* */ +#define AC97_CRIDX_GPR 0x20 /* General purpose register */ + +/* General purpose register definitions */ +#define AC97_GPR_LPBK_MASK 0x0080 /* ADC/DAC loopback mode (system performance measurement) */ +#define AC97_GPR_LPBK_BIT 7 +#define AC97_GPR_MS_MASK 0x0100 /* Mic select (0: mic1, 1: mic2) */ +#define AC97_GPR_MS_BIT 8 +#define AC97_GPR_MIX_MASK 0x0200 /* Mono output select (0: mix, 1: mic) */ +#define AC97_GPR_MIX_BIT 9 +#define AC97_GPR_LD_MASK 0x1000 /* Loudness/bass_boost (0: off, 1: on) */ +#define AC97_GPR_LD_BIT 12 +#define AC97_GPR_3D_MASK 0x2000 /* 3D stereo enhancement (0: off, 1: on) */ +#define AC97_GPR_3D_BIT 13 +#define AC97_GPR_ST_MASK 0x4000 /* Simulated stereo enhancement (0: off, 1: on) */ +#define AC97_GPR_ST_BIT 14 +#define AC97_GPR_POP_MASK 0x8000 /* PCM out path & mute (0: pre 3D, 1: post 3D) */ +#define AC97_GPR_POP_BIT 15 + +/* ------------------------------------------------ */ +/* 3D control register (index 0x22) */ +/* */ +#define AC97_CRIDX_3D_CONTROL 0x22 /* 3D control register */ + +/* 3D control register definitions */ +#define AC97_3D_CONTROL_DP_MASK 0x000f /* Depth */ +#define AC97_3D_CONTROL_DP_SHIFT 0 +#define AC97_3D_CONTROL_CR_MASK 0x0f00 /* Center */ +#define AC97_3D_CONTROL_CR_SHIFT 8 + +/* ------------------------------------------------ */ +/* Powerdown control/status register (index 0x20) */ +/* */ +#define AC97_CRIDX_POWER 0x26 /* Powerdown control/status register */ + +/* Powerdown control/status register definitions */ +#define AC97_POWER_ADC_MASK 0x0001 /* ADC selction ready to transmit data */ +#define AC97_POWER_ADC_BIT 0 +#define AC97_POWER_DAC_MASK 0x0002 /* DAC selection ready to accept data */ +#define AC97_POWER_DAC_BIT 1 +#define AC97_POWER_ANL_MASK 0x0004 /* Analog mixer, etc. ready */ +#define AC97_POWER_ANL_BIT 2 +#define AC97_POWER_REF_MASK 0x0008 /* Vref's up to nominal level */ +#define AC97_POWER_REF_BIT 3 + +#define AC97_POWER_PR0_MASK 0x0100 /* PCM in ADC's & input mux powerdown */ +#define AC97_POWER_PR0_BIT 8 +#define AC97_POWER_PR1_MASK 0x0200 /* PCM out DACs powerdown */ +#define AC97_POWER_PR1_BIT 9 +#define AC97_POWER_PR2_MASK 0x0400 /* Analog mixer power down (Vref still on) */ +#define AC97_POWER_PR2_BIT 10 +#define AC97_POWER_PR3_MASK 0x0800 /* Analog mixer power down (Vref off) */ +#define AC97_POWER_PR3_BIT 11 +#define AC97_POWER_PR4_MASK 0x1000 /* Digital interface (AC-link) powerdown (external clk off) */ +#define AC97_POWER_PR4_BIT 12 +#define AC97_POWER_PR5_MASK 0x2000 /* Internal clk disable */ +#define AC97_POWER_PR5_BIT 13 +#define AC97_POWER_PR6_MASK 0x4000 /* HP amp powerdown */ +#define AC97_POWER_PR6_BIT 14 + +#define AC97_POWER_EAPD_MASK 0x8000 /* External amplifier power down */ +#define AC97_POWER_EAPD_BIT 15 + +/* ------------------------------------------------ */ +/* Vendor ID registers (index 0x20) */ +/* */ +#define AC97_CRIDX_VENDOR_ID1 0x7c /* Vendor ID register 1 */ +#define AC97_CRIDX_VENDOR_ID2 0x7e /* Vendor ID register 2 */ + +/* Vendor ID 1 register definitions */ +#define AC97_VENDOR_CHAR2_MASK 0x00ff /* Second ascii char of vendor id */ +#define AC97_VENDOR_CHAR2_SHIFT 0 +#define AC97_VENDOR_CHAR1_MASK 0xff00 /* First ascii char of vendor id */ +#define AC97_VENDOR_CHAR1_SHIFT 8 + +/* Vendor ID 2 register definitions */ +#define AC97_VENDOR_REV_MASK 0x00ff /* Vendor revision number */ +#define AC97_VENDOR_REV_SHIFT 0 +#define AC97_VENDOR_CHAR3_MASK 0xff00 /* Third ascii char of vendor id */ +#define AC97_VENDOR_CHAR3_SHIFT 8 + +/* + * Todo: + * Appendix A - AC97 2.0 Variable Sample Rate Extension + * Appendix B - AC97 2.0 Modem AFE Extension + * Appendix C - AC97 2.0 Multiple Codec Extension + */ + +/***************************************************************************** + * AC97 Driver-Supplement Helper Macros + ****************************************************************************/ + +/* Make frame slot1 value to write AC97 codec register */ +#define AC97_MAKE_WCMD_ADDR(idx) \ + (((AC97_CMD_WRITE << AC97_CMDADDR_RW_BIT) & AC97_CMDADDR_RW_MASK) | \ + (((uint32_t)(idx) << AC97_CMDADDR_CRIDX_SHIFT) & AC97_CMDADDR_CRIDX_MASK)) + +/* Make frame slot1 value to read AC97 codec register */ +#define AC97_MAKE_RCMD_ADDR(idx) \ + (((AC97_CMD_READ << AC97_CMDADDR_RW_BIT) & AC97_CMDADDR_RW_MASK) | \ + (((uint32_t)(idx) << AC97_CMDADDR_CRIDX_SHIFT) & AC97_CMDADDR_CRIDX_MASK)) + +/* Make frame slot2 value to write AC97 codec register */ +#define AC97_MAKE_CMD_DATA(data) \ + (((uint32_t)(data) << AC97_CMDDATA_SHIFT) & AC97_CMDDATA_MASK) + +/* Make frame slot1 and slot2 value to tx buffer for AC97 codec register write */ +#define AC97_MAKE_WCMD(txb, idx, data) \ + ((uint32_t *)(txb))[0] = AC97_MAKE_WCMD_ADDR(idx); \ + ((uint32_t *)(txb))[1] = AC97_MAKE_CMD_DATA(data); + +/* Make frame slot1 and slot2 value to tx buffer for AC97 codec register read */ +#define AC97_MAKE_RCMD(txb, idx, data) \ + ((uint32_t *)(txb))[0] = AC97_MAKE_RCMD_ADDR(idx); \ + /*((uint32_t *)(txb))[1] = AC97_MAKE_CMD_DATA(data); */ + +/******************************************************************************* + * Following helper functions imply non-20-bit msb-aligned sdata_out format + ******************************************************************************/ + +/* Make codec stereo volume */ +#define AC97_STEREO_VOLUME(l, r) \ + ((((uint32_t)(l) << AC97_ML_SHIFT) & AC97_ML_MASK) | \ + (((uint32_t)(r) << AC97_MR_SHIFT) & AC97_MR_MASK)) + +/* Make codec mono volume */ +#define AC97_MONO_VOLUME(m) \ + ((((uint32_t)(m) << AC97_MR_SHIFT) & AC97_MR_MASK)) + +/* Make tone (bass, treble) gain value */ +#define AC97_TONE_GAIN(b, t) \ + ((((uint32_t)(b) << AC97_BASS_SHIFT) & AC97_BASS_MASK) | \ + (((uint32_t)(t) << AC97_TREBLE_SHIFT) & AC97_TREBLE_MASK)) + +/* Make pc-beep gain value */ +#define AC97_PCBEEP_GAIN(g) \ + ((((uint32_t)(g) << AC97_MIXER_GR_SHIFT) & AC97_MIXER_GR_MASK)) + +/* Make mixer phone gain value */ +#define AC97_PHONE_GAIN(m) \ + ((((uint32_t)(m) << AC97_PCBEEP_SHIFT) & AC97_PCBEEP_MASK)) + +/* Make mixer mic gain value */ +#define AC97_MIC_GAIN(b, m) \ + ((((uint32_t)(m) << AC97_MIXER_GR_SHIFT) & AC97_MIXER_GR_MASK) | \ + (((uint32_t)(b) << AC97_MIC_VOLUME_BOOST_BIT) & AC97_MIC_VOLUME_BOOST_MASK)) + +/* Make mixer gain value */ +#define AC97_MIXER_GAIN(l, r) \ + ((((uint32_t)(l) << AC97_MIXER_GL_SHIFT) & AC97_MIXER_GL_MASK) | \ + (((uint32_t)(r) << AC97_MIXER_GR_SHIFT) & AC97_MIXER_GR_MASK)) + +/* Make record select value */ +#define AC97_RECORD_SELECT(l, r) \ + ((((uint32_t)(l) << AC97_RECORD_SL_SHIFT) & AC97_RECORD_SL_MASK) | \ + (((uint32_t)(r) << AC97_RECORD_SR_SHIFT) & AC97_RECORD_SR_MASK)) + +/* Make record gain value */ +#define AC97_RECORD_GAIN(l, r) \ + ((((uint32_t)(l) << AC97_RECORD_GL_SHIFT) & AC97_RECORD_GL_MASK) | \ + (((uint32_t)(r) << AC97_RECORD_GR_SHIFT) & AC97_RECORD_GR_MASK)) + +/* Make record mic gain value */ +#define AC97_RECORD_MIC_GAIN(m) \ + (((uint32_t)(m) << AC97_RECORD_GR_SHIFT) & AC97_RECORD_GR_MASK) + +void ac97_init(void); +#endif /* __SSPD_AC97_H__ */ diff --git a/bsp/AE210P/driver/ssp/sspd_rts.c b/bsp/AE210P/driver/ssp/sspd_rts.c new file mode 100644 index 0000000000000000000000000000000000000000..50ce245f41e402544dbc6f77ebebbcea8f48bfd4 --- /dev/null +++ b/bsp/AE210P/driver/ssp/sspd_rts.c @@ -0,0 +1,456 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Mar.16.2008 Created. + ****************************************************************************/ + +#include "hal.h" +#include "sspd_rts.h" +#include "bsp_hal.h" + +#define RTS_PRESSED_Z1_MIN 0x10 +#define RTS_PRESSED_Z2_MAX 0xfe0 + +typedef struct _SSPD_RTS_CONTEXT{ + + hal_bh_t hisr; + + hal_semaphore_t *usr_ievent; + struct ts_data *usr_idata; + +} SSPD_RTS_CONTEXT; + +SSPD_RTS_CONTEXT rts_ctxt; + +#define SSPD_HISR_STACK_SIZE 1024 +static uint32_t sspd_rts_hisr_stack[SSPD_HISR_STACK_SIZE]; + +static void _sspd_rts_lisr(int vector){ + + int x = 0, y = 0, z1 = 0, z2 = 0, p = 0; + + DEBUG(0, 1, "Enter\n"); + + if (vector != RTS_LISR_VECTOR) + hal_system_error(HAL_ERR_UNHANDLED_INTERRUPT); + + /* Disable #PENIRQ interrupt */ + uint32_t prv_msk = hal_intc_irq_mask(RTS_LISR_VECTOR); + + /* Clear #PENIRQ interrupt status */ + hal_intc_irq_clean(RTS_LISR_VECTOR); + + /* Enable higher priority interrupt */ + GIE_ENABLE(); +//FIXME +#if 0 +#if(NO_EXTERNAL_INT_CTL==0) + /* Disable #PENIRQ interrupt temporarily */ + CLRB32(INTC_HW1_ER, RTS_LISR_VECTOR); + + /* Clear #PENIRQ interrupt status */ + SETB32(INTC_HW1_CLR, RTS_LISR_VECTOR); +#else + /* FIXME add clear ts interrupt */ +#endif +#endif + _sspd_rts_probe(&x, &y, &z1, &z2, &p); + _sspd_rts_probe(&x, &y, &z1, &z2, &p); + _sspd_rts_probe(&x, &y, &z1, &z2, &p); + + rts_ctxt.usr_idata->x = x; + rts_ctxt.usr_idata->y = y; + rts_ctxt.usr_idata->z1 = z1; + rts_ctxt.usr_idata->z2 = z2; + + DEBUG(0, 1, "%4d, %4d, %4d, %4d\n", x, y, z1, z2); + + if (z1 < 100) { + /* Disable GIE to prevent nested self */ + GIE_DISABLE(); + /* + * Clear #PENIRQ interrupt status again because _sspd_rts_probe would trigger #PENIRQ interrupt + * Please reference ADS7846 Spec. + */ + hal_intc_irq_clean(RTS_LISR_VECTOR); + + /* Re-enable touch interrupt */ + hal_intc_irq_unmask(prv_msk); + return; + + } + + hal_raise_bh(&rts_ctxt.hisr); + // TODO + // It is a walk around since interrupt priority + // we should change the hisr + hal_intc_irq_unmask(prv_msk); + hal_intc_irq_disable(RTS_LISR_VECTOR); +} + +static inline void ts_hisr(void *param){ + + hal_bh_t *bh = param; + + while (1){ + + DEBUG(0, 1, "before\n"); + hal_pend_semaphore(&bh->sem, HAL_SUSPEND); + DEBUG(0, 1, "after\n"); + hal_post_semaphore(rts_ctxt.usr_ievent); + +#ifndef CONFIG_PLAT_QEMU + hal_sleep(300); +#endif + + hal_intc_irq_clean(RTS_LISR_VECTOR); + HAL_INTC_IRQ_ATOMIC_ENABLE(RTS_LISR_VECTOR); + // SETB32(INTC_HW1_ER, RTS_LISR_VECTOR); + // SETB32(INTC_HW1_CLR, RTS_LISR_VECTOR); + } +} + +static void _sspd_rts_set_sclk(int sclk){ + + int sclk_div; /* serial clock rate divisor */ + + if (sclk > RTS_ADS7846_DCLK_MAX){ + + DEBUG(1, 1, "Warning : SCLK exceed allowable range! Truncation is performed.\n"); + sclk = RTS_ADS7846_DCLK_MAX; + } + + /* + * sclk source: + * PLL3 (SSPCLK = PLL3/6) AG101 internal clk + * GPIO25 (SSPCLK = GPIO25) AG101 external clk + * OSCCLK (SSPCLK = OSCCLK * 6 / 6) Leopard + * + * calculate sclk_div from internal PLL3 + * + * sclk_div = (SSPCLK / sclk / 2) - 1 + * = ((PLL3 / 6) / sclk / 2) - 1 + * = ((OSCCLK * 30 / 6) / sclk / 2) - 1 + */ + + /* + * setup PMU SSP clock source + * + * PMU_SSPCLKSEL: MFPSR[6] + * 0: SSPCLK + * 1: GPIO25 + * + * PMU_AC97CLKOUTSEL: MFPSR[13] + * 0: GPIO + * 1: AC97CLK out + */ + + /* [2008-03-20] SSP1 only works with internal clock source on AG101 and Leopard EVBs. */ + +#if 0 /*(MB_SSP_EXT_CLK) */ + sclk_div = (24768000 / (sclk << 1)) - 1; + SSPD_TRACE(("\nSSPCLK: GPIO25\n")); + SETB32(PMU_MFPSR, PMU_SSPCLKSEL_BIT); +#else + sclk_div = (MB_OSCCLK / (2 * sclk)) - 1; + DEBUG(1, 1, "SSPCLK: PLL\n"); + CLRB32(PMU_MFPSR, PMU_SSPCLKSEL_BIT); +#endif + + DEBUG(1, 1, "sclk : %d, sclk_div : 0x%04x\n", sclk, sclk_div); + + /* + * setup SSP SCLKDIV + * PDL : (padding data length) not used + * SDL : (serial data length) 8-1 (8 bits) + * SCLKDIV : sclk_div + */ +#ifndef CONFIG_PLAT_QEMU + OUT32(SSPC_CR1, ((7 << SSPC_C1_SDL_SHIFT) & SSPC_C1_SDL_MASK) | /* bit data length */ + ((sclk_div << SSPC_C1_SCLKDIV_SHIFT) & SSPC_C1_SCLKDIV_MASK)); /* sclkdiv */ +#else + OUT32(SSPC_CR1, ((23 << SSPC_C1_SDL_SHIFT) & SSPC_C1_SDL_MASK) | /* bit data length */ + ((sclk_div << SSPC_C1_SCLKDIV_SHIFT) & SSPC_C1_SCLKDIV_MASK)); /* sclkdiv */ +#endif +} + +int _sspd_rts_init(struct ts_dev *ts){ + + int status = HAL_SUCCESS; + int core_intl; + + core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS); + + /* SSP controler initialization - SPI */ + + /* Disable all SSP interrupts, and set DMA trigger FIFO threshold to 0. */ + OUT32(SSPC_INTCR, 0); + /* check ts interrupt vector*/ + if (ts->penirq){ + status = hal_register_isr(RTS_LISR_VECTOR, _sspd_rts_lisr, (void*)0); + if (status != HAL_SUCCESS){ + + DEBUG(1, 1, "Failed to register SSPD driver LISR!\n"); + return status; + } + + rts_ctxt.usr_ievent = ts->event_obj; + rts_ctxt.usr_idata = ts->event_data; + rts_ctxt.hisr.th.fn = ts_hisr; + rts_ctxt.hisr.th.ptos = &sspd_rts_hisr_stack[SSPD_HISR_STACK_SIZE]; + rts_ctxt.hisr.th.stack_size = sizeof(sspd_rts_hisr_stack); + rts_ctxt.hisr.th.prio = CONFIG_TSD_HISR_PRIORITY; + rts_ctxt.hisr.th.name = "TS BH"; + rts_ctxt.hisr.th.arg = &rts_ctxt.hisr; + status = hal_create_bh(&rts_ctxt.hisr); + + if (status != HAL_SUCCESS){ + + DEBUG(1, 1, "Failed to create SSPD-RTS driver HISR!\n"); + return status; + } + + /* INTC */ + /* - Disable #PENIRQ interrupt */ + hal_intc_irq_disable(RTS_LISR_VECTOR); + /* - Clear #PENIRQ interrupt status */ + hal_intc_irq_clean(RTS_LISR_VECTOR); + /* - Setup #PENIRQ interrupt trigger mode - edge trigger */ + /* - Setup #PENIRQ interrupt trigger level - assert low */ + hal_intc_irq_config(RTS_LISR_VECTOR, IRQ_EDGE_TRIGGER, IRQ_ACTIVE_LOW); + + if (ts->penirq_en){ + /* - Enable #PENIRQ interrupt */ + hal_intc_irq_enable(RTS_LISR_VECTOR); + } + } + + /* Reset SSP controller */ + SETB32(SSPC_CR2, SSPC_C2_SSPRST_BIT); + + /* Disable SSP data out */ + CLRR32(SSPC_CR2, SSPC_C2_SSPEN_MASK | SSPC_C2_TXDOE_MASK); + + /* setup sspc clock */ + _sspd_rts_set_sclk(RTS_ADS7846_DCLK_DEFAULT); + + _nds_kwait(RTS_RESET_WAIT); + + /* Set SSP frame format to SPI */ + OUT32(SSPC_CR0, ((0 << SSPC_C0_SCLKPH_BIT) & SSPC_C0_SCLKPH_MASK) | /* phase (1 not working for 16clk mode) */ + ((0 << SSPC_C0_SCLKPO_BIT) & SSPC_C0_SCLKPO_MASK) | /* polarity */ + ((SSPC_SSP_MASTER << SSPC_C0_OPM_SHIFT) & SSPC_C0_OPM_MASK) | /* operation mode */ + ((0 << SSPC_C0_LBM_BIT) & SSPC_C0_LBM_MASK) | /* loopback */ + ((SSPC_MOTO_SPI << SSPC_C0_FFMT_SHIFT) & SSPC_C0_FFMT_MASK)); /* frame format */ + + /* Clear FIFO garbage */ + SETR32(SSPC_CR2, SSPC_C2_RXFCLR_MASK | SSPC_C2_TXFCLR_MASK); + + + /* Restore CPU interrupt controller to previous level */ + hal_global_int_ctl(core_intl); + + return status; +} + +int _sspd_rts_probe(int *x, int *y, int *z1, int *z2, int *pressed){ + + uint32_t data[12]; + int t, i; + + /* Clear FIFO garbage */ + SETR32(SSPC_CR2, SSPC_C2_RXFCLR_MASK | SSPC_C2_TXFCLR_MASK); + + /* Enable SSP */ + SETB32(SSPC_CR2, SSPC_C2_SSPEN_BIT); + + /* Disable SSP data out temporarily */ + CLRB32(SSPC_CR2, SSPC_C2_TXDOE_BIT); + + /* [hw-limit] Wait until the ssp controller get ready */ + // _nds_kwait(RTS_DIN_WAIT); + + t = 0; + while (((IN32(SSPC_SR) & SSPC_SR_BUSY_MASK) != 0) && (t++ < RTS_DIN_TIMEOUT)) + ; + + DEBUG(0, 1, "[RTS] SR : 0x%08lx\n", IN32(SSPC_SR)); + + /* + * ------------------------------------------------------------------------ + * Timing of 16-clock-cycle per conversion + * + * power-up read y read x power down (full cycle) + * --------- --------- --------- --------------- + * dout (bytes) ctrl 0 ctrl 0 ctrl 0 ctrl 0 0 ____ + * din (bytes) 0 msb lsb msb lsb msb lsb msb lsb ____ + * ^^^^ ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^ + * don't care x1 or y1 x2 or y2 don't care + * + * x = (x1 + x2) / 2 (if averaging was expected) + * y = (y1 + y2) / 2 (if averaging was expected) + * + * Note: Watch out SSP FIFO depth (12 for AG101/Leopard) + * ------------------------------------------------------------------------ + */ + + /* SPI dout ... */ +#ifndef CONFIG_PLAT_QEMU + /* power up */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RY); + OUT32(SSPC_DR, 0); + + /* read y */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RY); + OUT32(SSPC_DR, 0); + + /* read x */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RX); + OUT32(SSPC_DR, 0); + + /* read z1 */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RZ1); + OUT32(SSPC_DR, 0); + + /* read z2 && power down */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RZ2_PD); + OUT32(SSPC_DR, 0); + OUT32(SSPC_DR, 0); +#else + /* power up */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RY << 16); + OUT32(SSPC_DR, 0); + + /* read y */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RY << 16); + OUT32(SSPC_DR, 0); + + /* read x */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RX << 16); + OUT32(SSPC_DR, 0); + + /* read z1 */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RZ1 << 16); + OUT32(SSPC_DR, 0); + + /* read z2 && power down */ + OUT32(SSPC_DR, RTS_ADS7846_CTL_RZ2_PD << 16); + OUT32(SSPC_DR, 0); + OUT32(SSPC_DR, 0); +#endif + /* Enable SSP-TX out */ + SETB32(SSPC_CR2, SSPC_C2_TXDOE_BIT); + + /* SPI din ... */ + for (i = 0; i < 11; ++i){ + + /* Wait until data ready */ + t = 0; + while ((IN32(SSPC_SR) & SSPC_SR_RFVE_MASK) == 0){ + if ( ++t > RTS_DIN_TIMEOUT){ + + DEBUG(1, 1, "rts spi timeout at data[%d]\n", i); + goto _timeout; + } + } + /* Read data byte */ + data[i] = IN32(SSPC_DR); + DEBUG(0, 1, "[RTS] data[%d] %d, 0x%x\n", i, data[i], data[i]); + } + + /* Disable SSP data out */ + CLRR32(SSPC_CR2, SSPC_C2_SSPEN_MASK | SSPC_C2_TXDOE_MASK); + + /* Compose final data (12-bits or 8-bits) */ +#if ((RTS_ADS7846_RY & RTS_ADS7846_MODE_MASK) == (RTS_ADS7846_8_BITS << RTS_ADS7846_MODE_SHIFT)) + *y = RTS_ADS7846_8BITS_DATA(data[3], data[4]); + *x = RTS_ADS7846_8BITS_DATA(data[5], data[6]); + *z1 = RTS_ADS7846_8BITS_DATA(data[7], data[8]); + *z2 = RTS_ADS7846_8BITS_DATA(data[9], data[10]); +#else + *y = RTS_ADS7846_12BITS_DATA(data[3], data[4]); + *x = RTS_ADS7846_12BITS_DATA(data[5], data[6]); + *z1 = RTS_ADS7846_12BITS_DATA(data[7], data[8]); + *z2 = RTS_ADS7846_12BITS_DATA(data[9], data[10]); +#endif +#ifndef CONFIG_PLAT_QEMU + DEBUG(0, 1, "[RTS] y - %04d, msb(0x%02lx) lsb(0x%02lx)\n", *y, (data[3] & 0xff), (data[4] & 0xff)); + DEBUG(0, 1, "[RTS] x - %04d, msb(0x%02lx) lsb(0x%02lx)\n", *x, (data[5] & 0xff), (data[6] & 0xff)); + DEBUG(0, 1, "[RTS] z1 - %04d, msb(0x%02lx) lsb(0x%02lx)\n", *z1, (data[7] & 0xff), (data[8] & 0xff)); + DEBUG(0, 1, "[RTS] z2 - %04d, msb(0x%02lx) lsb(0x%02lx)\n", *z2, (data[9] & 0xff), (data[10] & 0xff)); +#else + DEBUG(0, 1, "[RTS] y - %d, msb(0x%x)%d, lsb(0x%x)%d\n", *y, data[3],data[3], data[4], data[4]); + DEBUG(0, 1, "[RTS] x - %d, msb(0x%x)%d, lsb(0x%x)%d\n", *x, data[5],data[5], data[6], data[6]); + DEBUG(0, 1, "[RTS] z1 - %d, msb(0x%x)%d, lsb(0x%x)%d\n", *z1, data[7],data[7], data[8], data[8]); + DEBUG(0, 1, "[RTS] z2 - %d, msb(0x%x)%d, lsb(0x%x)%d\n", *z2, data[9],data[9], data[10], data[10]); +#endif + if ((*z1 < RTS_PRESSED_Z1_MIN) && (*z2 >= RTS_PRESSED_Z2_MAX)) + *pressed = 0; + else + *pressed = 1; + + return HAL_SUCCESS; + +_timeout: + + return HAL_FAILURE; +} + +void ts_adjust(struct ts_dev *ts, int ts_x, int ts_y, int *x, int *y) +{ + *x = (ts->lcd_width * (ts_x - ts->left)) / (ts->right - ts->left); + *y = (ts->lcd_height * (ts_y - ts->top)) / (ts->bottom - ts->top); + DEBUG(0, 0, "adj (x, y) = (%4d, %4d)\n", *x, *y); +} + +void ts_raw_value(struct ts_dev *ts, int *x, int *y) +{ + hal_pend_semaphore(&ts->sem, HAL_SUSPEND); + + *x = ts->data.x; + *y = ts->data.y; + DEBUG(0, 0, "raw (x, y) = (%4d, %4d)\n", *x, *y); +} + +void ts_value(struct ts_dev *ts, int *x, int *y) +{ + int raw_x, raw_y; + ts_raw_value(ts, &raw_x, &raw_y); + ts_adjust(ts, raw_x, raw_y, x, y); +} + +void ts_calibrate(struct ts_dev *ts, + void (*draw_cross)(void *param, int x, int y), + int count) +{ + int i = 0; + int left = 0, right = 0, top = 0, bottom = 0; + + for (i = 0; i < count; i++) { + + int raw_x = 0, raw_y = 0; + + DEBUG(0, 0, "(left, top) = "); + draw_cross(NULL, ts->lcd_width * 1 / 5, ts->lcd_height * 1 / 5); + ts_raw_value(ts, &raw_x, &raw_y); + left = ((left * i) + raw_x) / (i + 1); + top = ((top * i) + raw_y) / (i + 1); + DEBUG(0, 0, "(%4d, %4d) || (x, y) = (%4d, %4d)\n", left, top, raw_x, raw_y); + + DEBUG(0, 0, "(right, bottom) = "); + draw_cross(NULL, ts->lcd_width * 4 / 5, ts->lcd_height * 4 / 5); + ts_raw_value(ts, &raw_x, &raw_y); + right = ((right * i) + raw_x) / (i + 1); + bottom = ((bottom * i) + raw_y) / (i + 1); + DEBUG(0, 0, "(%4d, %4d) || (x, y) = (%4d, %4d)\n", right, bottom, raw_x, raw_y); + } + + ts->left = left - (right - left) / 3; + ts->right = right + (right - left) / 3; + ts->top = top - (bottom - top) / 3; + ts->bottom = bottom + (bottom - top) / 3; +} diff --git a/bsp/AE210P/driver/ssp/sspd_rts.h b/bsp/AE210P/driver/ssp/sspd_rts.h new file mode 100644 index 0000000000000000000000000000000000000000..cdb2ba3516b62fc7e4ffaee133e36b2a7313473c --- /dev/null +++ b/bsp/AE210P/driver/ssp/sspd_rts.h @@ -0,0 +1,199 @@ +/***************************************************************************** + * + * Copyright Andes Technology Corporation 2007-2008 + * All Rights Reserved. + * + * Revision History: + * + * Mar.16.2008 Created. + ****************************************************************************/ + +/***************************************************************************** + * + * FILE NAME VERSION + * + * sspd_rts.h + * + * DESCRIPTION + * + * SPI digital serial interface protocol header for resistive + * touch screen controller. + * + * DATA STRUCTURES + * + * None + * + * DEPENDENCIES + * + * None + * + ****************************************************************************/ +#ifndef __SSPD_RTS_H__ +#define __SSPD_RTS_H__ + +/***************************************************************************** + * Configuration Options + ****************************************************************************/ + +/* Non-zero to enable 16-clock per conversion mode, otherwise 24-clock cycle is applied. */ +#define RTS_16CLK_CONV_CYCLE 1 + +#define RTS_LISR_VECTOR INTC_HW0_BIT /* AG101 connects #PENIRQ to hw0 vector */ + +/* polling loop counter for waiting hw-reset */ +#define RTS_RESET_WAIT (0x300000) + +/* CPU polling counter to avoid bouncing signals of previous RTS operation */ +#define RTS_DEBOUNCE_WAIT (0x30000) + +/* polling counter for serial data in */ +#define RTS_DIN_TIMEOUT (0x30000) + +/* HISR definitions */ +#define RTS_HISR_PRIORITY 0 /* 0: highest, 2: lowest */ +#define RTS_HISR_STACK_SIZE 2048 /* Please align to 32-bit */ + +#define RTS_HISR_AS_TOUCHED 0x00000001 /* Activate HISR for touched interrupt */ + + +/***************************************************************************** + * Resistive Touch Screen Digital Interface Definitions + ****************************************************************************/ + +/* Definitions for ADS7846 */ + +/* Control Byte Bits */ +#define RTS_ADS7846_PD_MASK 0x03 /* Start Bit (MSB) */ +#define RTS_ADS7846_PD_SHIFT 0 + #define RTS_ADS7846_PD 0x00 /* power down between conversion, #penirq enabled */ + #define RTS_ADS7846_ADC 0x01 /* ref off, adc on, #penirq disabled */ + #define RTS_ADS7846_REF 0x02 /* ref on, adc off, #penirq enabled */ + #define RTS_ADS7846_PW 0x03 /* power on, ref on, adc on, #penirq disabled */ + +#define RTS_ADS7846_SER_MASK 0x04 /* Single-Ended/#Differential-Reference Register */ +#define RTS_ADS7846_SER_SHIFT 2 + #define RTS_ADS7846_DF 0x00 /* differential */ + #define RTS_ADS7846_SE 0x01 /* single-ended */ + +#define RTS_ADS7846_MODE_MASK 0x08 /* Conversion Selection Bit */ +#define RTS_ADS7846_MODE_SHIFT 3 + #define RTS_ADS7846_12_BITS 0x00 /* 12 bits conversion */ + #define RTS_ADS7846_8_BITS 0x01 /* 8 bits conversion */ + +#define RTS_ADS7846_MUX_MASK 0x70 /* (A2 ~ A0) Control the setting of multiplexer input */ +#define RTS_ADS7846_MUX_SHIFT 4 + + #define RTS_ADS7846_DF_X 0x05 /* [A2:A0] 101b, Driver: X+ X-, Measure Y+ */ + #define RTS_ADS7846_DF_Y 0x01 /* [A2:A0] 001b, Driver: Y+ Y-, Measure X+ */ + #define RTS_ADS7846_DF_Z1 0x03 /* [A2:A0] 011b, Driver: Y+ X-, Measure X+ */ + #define RTS_ADS7846_DF_Z2 0x04 /* [A2:A0] 100b, Driver: Y+ X-, Measure Y- */ + + #define RTS_ADS7846_SE_X 0x05 /* [A2:A0] 101b */ + #define RTS_ADS7846_SE_Y 0x01 /* [A2:A0] 001b */ + #define RTS_ADS7846_SE_Z1 0x03 /* [A2:A0] 011b */ + #define RTS_ADS7846_SE_Z2 0x04 /* [A2:A0] 100b */ + #define RTS_ADS7846_SE_BAT 0x02 /* [A2:A0] 010b */ + #define RTS_ADS7846_SE_AUX 0x06 /* [A2:A0] 110b */ + #define RTS_ADS7846_SE_TEMP0 0x00 /* [A2:A0] 000b */ + #define RTS_ADS7846_SE_TEMP1 0x07 /* [A2:A0] 111b */ + +#define RTS_ADS7846_START_MASK 0x80 /* Start Bit (MSB) */ +#define RTS_ADS7846_START_BIT 7 + #define RTS_ADS7846_START 1 + +/* Supplimental Macros */ +#define RTS_ADS7846_PADDING_BYTE 0 /* Padding byte feed after the command byte to continue serial clocking */ + +#define RTS_ADS7846_CTRL_BYTE(mux, mode, ser, pd) \ + ((((uint32_t)(mux) << RTS_ADS7846_MUX_SHIFT) & RTS_ADS7846_MUX_MASK) | \ + (((uint32_t)(mode) << RTS_ADS7846_MODE_SHIFT) & RTS_ADS7846_MODE_MASK) | \ + (((uint32_t)(ser) << RTS_ADS7846_SER_SHIFT) & RTS_ADS7846_SER_MASK) | \ + (((uint32_t)(pd) << RTS_ADS7846_PD_SHIFT) & RTS_ADS7846_PD_MASK) | \ + (uint32_t)RTS_ADS7846_START_MASK) + +/* this is correct */ +#define RTS_ADS7846_8BITS_DATA(msb, lsb) ((((uint32_t)(msb) & 0x07) << 5) | (((uint32_t)(lsb) & 0xff) >> 3)) +#ifndef CONFIG_PLAT_QEMU +#define RTS_ADS7846_12BITS_DATA(msb, lsb) ((((uint32_t)(msb) & 0x7f) << 5) | (((uint32_t)(lsb) & 0xff) >> 3)) +#else +#define RTS_ADS7846_12BITS_DATA(msb, lsb) msb +//#define RTS_ADS7846_12BITS_DATA(msb, lsb) ((msb >> 19) & 0xfff) +#endif + +/* Pre-defined Control-Byte Constants */ +#define RTS_ADS7846_CTL_RY RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Y, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PW) +#define RTS_ADS7846_CTL_RX RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_X, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PW) +#define RTS_ADS7846_CTL_RZ1 RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Z1, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PW) +#define RTS_ADS7846_CTL_RZ2 RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Z2, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PW) + +#define RTS_ADS7846_CTL_RY_PD RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Y, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PD) +#define RTS_ADS7846_CTL_RX_PD RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_X, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PD) +#define RTS_ADS7846_CTL_RZ1_PD RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Z1, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PD) +#define RTS_ADS7846_CTL_RZ2_PD RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Z2, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PD) +#define RTS_ADS7846_CTL_PD RTS_ADS7846_CTRL_BYTE(RTS_ADS7846_DF_Y, RTS_ADS7846_12_BITS, \ + RTS_ADS7846_DF, RTS_ADS7846_PD) +/* + * DCLK + * --------------- + * From pp3: + * 125 kHz max throughput rate, so ... + * DCLK_max = 125k * 16(16-clock-per-conversion mode) = 2.0MHz + * + * From table VI (p.p.14): + * (tch + tcl) = 400ns minimum, so ... + * DCLK_max = 1/400ns = 2.5MHz ? + */ +#define RTS_ADS7846_DCLK_MAX 2000000 /* adopt 2.0MHz for safe */ +#define RTS_ADS7846_DCLK_DEFAULT 125000 /* 7812 data per second (3906 x-y/sec, or 1953 x-y-z1-z2/sec) */ + + +/***************************************************************************** + * SSP Controller Resistive Touch Screen Driver-Supplement Interfaces + ****************************************************************************/ +struct ts_data { + + int x; + int y; + int z1; + int z2; + int pressed; + +}; + +struct ts_dev { + + int left; + int right; + int top; + int bottom; + + int lcd_width; + int lcd_height; + + int penirq; /* initialize touch screen driver in #penirq mode or polling mode */ + int penirq_en; /* enable #penirq after initialization if penirq is non-zero */ + + void *event_obj; /* (in) Event object to notify app about the interrupt. */ + struct ts_data *event_data; /* Client specified struct pointer to receive {x,y,touched} states */ + + hal_semaphore_t sem; + struct ts_data data; +}; + +extern int _sspd_rts_init(struct ts_dev *ts); +extern int _sspd_rts_probe(int *x, int *y, int *z1, int *z2, int *pressed); + +extern void ts_adjust(struct ts_dev *ts, int ts_x, int ts_y, int *x, int *y); +extern void ts_raw_value(struct ts_dev *ts, int *x, int *y); +extern void ts_value(struct ts_dev *ts, int *x, int *y); +extern void ts_init(struct ts_dev *ts); +extern void ts_calibrate(struct ts_dev *ts, void (*draw_cross)(void *param, int x, int y), int count); +#endif /* __SSPD_RTS_H__ */ diff --git a/bsp/AE210P/driver/uart/Kbuild b/bsp/AE210P/driver/uart/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..ae696493e107a0f995fd5237bd86b0f6fe99d20f --- /dev/null +++ b/bsp/AE210P/driver/uart/Kbuild @@ -0,0 +1,2 @@ +lib-y := +lib-y += uart.o diff --git a/bsp/AE210P/driver/uart/uart.c b/bsp/AE210P/driver/uart/uart.c new file mode 100644 index 0000000000000000000000000000000000000000..7196353307f310fa978d2a8211fdddac9069c944 --- /dev/null +++ b/bsp/AE210P/driver/uart/uart.c @@ -0,0 +1,143 @@ +#include + +#define DEFAULT_BAUDRATE 115200 /* 8n1 */ + +#define IN8(reg) (uint8_t)((*(volatile unsigned long *)(reg)) & 0x000000FF) +#define READ_CLR(reg) (*(volatile unsigned long *)(reg)) + +int drv_uart_set_baudrate(int baudrate) +{ + unsigned long baud_div; /* baud rate divisor */ + unsigned long temp_word; + + baud_div = (MB_UCLK / (16 * baudrate)); + + /* Save LCR temporary */ + temp_word = IN8(STUARTC_BASE + UARTC_LCR_OFFSET); + + /* Setup dlab bit for baud rate setting */ + OUT8(STUARTC_BASE + UARTC_LCR_OFFSET, (temp_word | UARTC_LCR_DLAB)); + + /* Apply baud rate */ + OUT8(STUARTC_BASE + UARTC_DLM_OFFSET, (unsigned char)(baud_div >> 8)); + OUT8(STUARTC_BASE + UARTC_DLL_OFFSET, (unsigned char)baud_div); + OUT8(STUARTC_BASE + UARTC_PSR_OFFSET, (unsigned char)1); + + /* Restore LCR */ + OUT8(STUARTC_BASE + UARTC_LCR_OFFSET, temp_word); + + return 0; +} + +int drv_uart_is_kbd_hit(void) +{ + return IN8(STUARTC_BASE + UARTC_LSR_OFFSET) & UARTC_LSR_RDR; +} + +int drv_uart_get_char(void) +{ + while (!(IN8(STUARTC_BASE + UARTC_LSR_OFFSET) & UARTC_LSR_RDR)) + ; + + return IN8(STUARTC_BASE + UARTC_RBR_OFFSET); +} + +void drv_uart_put_char(int ch) +{ + while (!(IN8(STUARTC_BASE + UARTC_LSR_OFFSET) & UARTC_LSR_THRE)) + ; + + OUT8(STUARTC_BASE + UARTC_THR_OFFSET, ch); +} + +int drv_uart_init(void) +{ + /* Clear everything */ + OUT8(STUARTC_BASE + UARTC_IER_OFFSET, 0x0); + OUT8(STUARTC_BASE + UARTC_LCR_OFFSET, 0x0); + + /* Setup baud rate */ + drv_uart_set_baudrate(DEFAULT_BAUDRATE); + + /* Setup parity, data bits, and stop bits */ + OUT8(STUARTC_BASE + UARTC_LCR_OFFSET, \ + (UARTC_LCR_PARITY_NONE | UARTC_LCR_BITS8 | UARTC_LCR_STOP1)); + + return 0; +} + +/********************************************** + * + * Archer Chang + * + * driver API with reg base + * +***********************************************/ +int __drv_uart_set_baudrate(unsigned int regbase, int baudrate) +{ + unsigned long baud_div; /* baud rate divisor */ + unsigned long temp_word; + + baud_div = (MB_UCLK / (16 * baudrate)); + + /* Save LCR temporary */ + temp_word = IN8(regbase + UARTC_LCR_OFFSET); + + /* Setup dlab bit for baud rate setting */ + OUT8(regbase + UARTC_LCR_OFFSET, (temp_word | UARTC_LCR_DLAB)); + + /* Apply baud rate */ + OUT8(regbase + UARTC_DLM_OFFSET, (unsigned char)(baud_div >> 8)); + OUT8(regbase + UARTC_DLL_OFFSET, (unsigned char)baud_div); + OUT8(regbase + UARTC_PSR_OFFSET, (unsigned char)1); + + /* Restore LCR */ + OUT8(regbase + UARTC_LCR_OFFSET, temp_word); + + return 0; +} + +int __drv_uart_is_kbd_hit(unsigned int regbase) +{ + return IN8(regbase + UARTC_LSR_OFFSET) & UARTC_LSR_RDR; +} + +int __drv_uart_get_char(unsigned int regbase) +{ + while (!(IN8(regbase + UARTC_LSR_OFFSET) & UARTC_LSR_RDR)) + ; + + return IN8(regbase + UARTC_RBR_OFFSET); +} + +void __drv_uart_put_char(unsigned int regbase, int ch) +{ + while (!(IN8(regbase + UARTC_LSR_OFFSET) & UARTC_LSR_THRE)) + ; + + OUT8(regbase + UARTC_THR_OFFSET, ch); +} + +int __drv_uart_put_char_nowait(unsigned int regbase, int ch) +{ + OUT8(regbase + UARTC_THR_OFFSET, ch); + + return 1; +} + +int __drv_uart_init(unsigned int regbase, int baudrate) +{ + /* Clear everything */ + OUT8(regbase + UARTC_IER_OFFSET, 0x0); + OUT8(regbase + UARTC_LCR_OFFSET, 0x0); + + /* Setup baud rate */ + __drv_uart_set_baudrate(regbase, baudrate); + + /* Setup parity, data bits, and stop bits */ + OUT8(regbase + UARTC_LCR_OFFSET, \ + (UARTC_LCR_PARITY_NONE | UARTC_LCR_BITS8 | UARTC_LCR_STOP1)); + + return 0; +} + diff --git a/bsp/AE210P/driver/uart/uart.h b/bsp/AE210P/driver/uart/uart.h new file mode 100644 index 0000000000000000000000000000000000000000..adff80e64cc79c1e39f8a3f13dc8d7af405ae141 --- /dev/null +++ b/bsp/AE210P/driver/uart/uart.h @@ -0,0 +1,17 @@ +#ifndef __DRV_UART_H__ +#define __DRV_UART_H__ + +extern int drv_uart_init(void); +extern int drv_uart_set_baudrate(int baudrate); +extern int drv_uart_is_kbd_hit(void); +extern int drv_uart_get_char(void); +extern void drv_uart_put_char(int ch); + +extern int __drv_uart_init (unsigned int regbase, int baudrate); +extern int __drv_uart_set_baudrate (unsigned int regbase, int baudrate); +extern int __drv_uart_is_kbd_hit (unsigned int regbase); +extern int __drv_uart_get_char (unsigned int regbase); +extern void __drv_uart_put_char (unsigned int regbase, int ch); +extern void __drv_uart_put_char_nowait(unsigned int regbase, int ch); + +#endif /* __DRV_UART_H__ */ diff --git a/bsp/AE210P/nds32.h b/bsp/AE210P/nds32.h new file mode 100644 index 0000000000000000000000000000000000000000..8015eb51c33747eb3896e815109bcd2b47562c2b --- /dev/null +++ b/bsp/AE210P/nds32.h @@ -0,0 +1,80 @@ +#ifndef __NDS32_H__ +#define __NDS32_H__ + +#include "nds32_defs.h" + +/* Support FPU */ +#if defined(__NDS32_EXT_FPU_DP__) || defined(__NDS32_EXT_FPU_SP__) +#define __TARGET_FPU_EXT +#if defined(__NDS32_EXT_FPU_CONFIG_0__) +#define FPU_REGS 8 +#elif defined(__NDS32_EXT_FPU_CONFIG_1__) +#define FPU_REGS 16 +#elif defined(__NDS32_EXT_FPU_CONFIG_2__) +#define FPU_REGS 32 +#elif defined(__NDS32_EXT_FPU_CONFIG_3__) +#define FPU_REGS 64 +#else +#error FPU register numbers no defined +#endif +#endif + +/* Support IFC */ +#ifdef __NDS32_EXT_IFC__ +#ifndef CONFIG_NO_NDS32_EXT_IFC +#define __TARGET_IFC_EXT +#endif +#endif + +/* Support ZOL */ +#ifdef CONFIG_HWZOL +#define __TARGET_ZOL_EXT +#endif + +#ifndef __ASSEMBLER__ + +#include "nds32_intrinsic.h" + +#define GIE_ENABLE() __nds32__gie_en() +#define GIE_DISABLE() __nds32__gie_dis() + +#ifdef CONFIG_CPU_DCACHE_ENABLE + +#define NDS_DCache_Flush nds32_dcache_flush +#define NDS_DCache_Invalidate_Flush nds32_dcache_invalidate +#define NDS_DCache_Writeback nds32_dcache_flush_range + +#else + +#define NDS_DCache_Flush() ((void)0) +#define NDS_DCache_Invalidate_Flush() ((void)0) +#define NDS_DCache_Writeback() ((void)0) + +#endif + +static inline void GIE_SAVE(unsigned long *var) +{ + *var = __nds32__mfsr(NDS32_SR_PSW); + GIE_DISABLE(); +} + +static inline void GIE_RESTORE(unsigned long var) +{ + if (var & PSW_mskGIE) + GIE_ENABLE(); +} + +extern void *OS_CPU_Vector_Table[32]; +typedef void (*isr_t)(int vector); + +static inline void register_isr(int vector, isr_t isr, isr_t *old) +{ + if (old) + *old = OS_CPU_Vector_Table[vector]; + + OS_CPU_Vector_Table[vector] = isr; +} + +#endif /* __ASSEMBLER__ */ + +#endif /* __NDS32_H__ */ diff --git a/bsp/AE210P/nds32_defs.h b/bsp/AE210P/nds32_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..cf552806a09c1b100be7cec893dd4c444f1eeb4c --- /dev/null +++ b/bsp/AE210P/nds32_defs.h @@ -0,0 +1,1362 @@ +/* + * Copyright (C) 2008 Andes Technology, Inc. + */ + +#ifndef __NDS32_DEFS_H__ +#define __NDS32_DEFS_H__ +/****************************************************************************** + * cr0: CPU_VER (CPU Version Register) + *****************************************************************************/ + +#define CPU_VER_offCFGID 0 /* Minor configuration */ +#define CPU_VER_offREV 16 /* Revision of the CPU version */ +#define CPU_VER_offCPUID 24 /* Major CPU versions */ + +#define CPU_VER_mskCFGID ( 0xFFFF << CPU_VER_offCFGID ) +#define CPU_VER_mskREV ( 0xFF << CPU_VER_offREV ) +#define CPU_VER_mskCPUID ( 0xFF << CPU_VER_offCPUID ) + +/****************************************************************************** + * cr1: ICM_CFG (Instruction Cache/Memory Configuration Register) + *****************************************************************************/ +#define ICM_CFG_offISET 0 /* I-cache sets (# of cache lines) per way */ +#define ICM_CFG_offIWAY 3 /* I-cache ways */ +#define ICM_CFG_offISZ 6 /* I-cache line size */ +#define ICM_CFG_offILCK 9 /* I-cache locking support */ +#define ICM_CFG_offILMB 10 /* On-chip ILM banks */ +#define ICM_CFG_offBSAV 13 /* ILM base register alignment version */ +#define ICM_CFG_offEXT 15 /* External ILM or not */ +#define ICM_CFG_offULM_2BANK 16 /* In ULM configuration, ILM has two banks */ +/* bit 17:31 reserved */ + +#define ICM_CFG_mskISET ( 0x7 << ICM_CFG_offISET ) +#define ICM_CFG_mskIWAY ( 0x7 << ICM_CFG_offIWAY ) +#define ICM_CFG_mskISZ ( 0x7 << ICM_CFG_offISZ ) +#define ICM_CFG_mskILCK ( 0x1 << ICM_CFG_offILCK ) +#define ICM_CFG_mskILMB ( 0x7 << ICM_CFG_offILMB ) +#define ICM_CFG_mskBSAV ( 0x3 << ICM_CFG_offBSAV ) +#define ICM_CFG_mskEXT ( 0x1 << ICM_CFG_offEXT ) +#define ICM_CFG_mskULM_2BANK ( 0x1 << ICM_CFG_offULM_2BANK ) + +/****************************************************************************** + * cr2: DCM_CFG (Data Cache/Memory Configuration Register) + *****************************************************************************/ +#define DCM_CFG_offDSET 0 /* D-cache sets (# of cache lines) per way */ +#define DCM_CFG_offDWAY 3 /* D-cache ways */ +#define DCM_CFG_offDSZ 6 /* D-cache line size */ +#define DCM_CFG_offDLCK 9 /* D-cache locking support */ +#define DCM_CFG_offDLMB 10 /* On-chip DLM banks */ +#define DCM_CFG_offBSAV 13 /* DLM base register alignment version */ +#define DCM_CFG_offEXT 15 /* External DLM or not */ +#define DCM_CFG_offULM_2BANK 16 /* In ULM configuration, DLM has two banks */ +/* bit 17:31 reserved */ + +#define DCM_CFG_mskDSET ( 0x7 << DCM_CFG_offDSET ) +#define DCM_CFG_mskDWAY ( 0x7 << DCM_CFG_offDWAY ) +#define DCM_CFG_mskDSZ ( 0x7 << DCM_CFG_offDSZ ) +#define DCM_CFG_mskDLCK ( 0x1 << DCM_CFG_offDLCK ) +#define DCM_CFG_mskDLMB ( 0x7 << DCM_CFG_offDLMB ) +#define DCM_CFG_mskBSAV ( 0x3 << DCM_CFG_offBSAV ) +#define DCM_CFG_mskEXT ( 0x1 << DCM_CFG_offEXT ) +#define DCM_CFG_mskULM_2BANK ( 0x1 << DCM_CFG_offULM_2BANK ) + +/****************************************************************************** + * cr3: MMU_CFG (MMU Configuration Register) + *****************************************************************************/ +#define MMU_CFG_offMMPS 0 /* Memory management protection scheme */ +#define MMU_CFG_offMMPV 2 /* Memory management protection version number */ +#define MMU_CFG_offFATB 7 /* Fully-associative or non-fully-associative TLB */ + +#ifdef CONFIG_FULL_ASSOC +#define MMU_CFG_offFATBSZ 8 /* TLB entries while using full-associative TLB */ +#else +#define MMU_CFG_offTBW 8 /* TLB ways(non-associative) TBS */ +#define MMU_CFG_offTBS 11 /* TLB sets per way(non-associative) TBS */ +/* bit 14:14 reserved */ +#endif + +#define MMU_CFG_offEP8MIN4 15 /* 8KB page supported while minimum page is 4KB */ +#define MMU_CFG_offfEPSZ 16 /* Extra page size supported */ +#define MMU_CFG_offTLBLCK 24 /* TLB locking support */ +#define MMU_CFG_offHPTWK 25 /* Hardware Page Table Walker implemented */ +#define MMU_CFG_offDE 26 /* Default endian */ +#define MMU_CFG_offNTPT 27 /* Partitions for non-translated attributes */ +#define MMU_CFG_offIVTB 28 /* Invisible TLB */ +#define MMU_CFG_offVLPT 29 /* VLPT for fast TLB fill handling implemented */ +#define MMU_CFG_offNTME 30 /* Non-translated VA to PA mapping */ +#define MMU_CFG_offDRDE 31 /* Device register default endian */ + +#define MMU_CFG_mskMMPS ( 0x3 << MMU_CFG_offMMPS ) +#define MMU_CFG_mskMMPV ( 0x1F << MMU_CFG_offMMPV ) +#define MMU_CFG_mskFATB ( 0x1 << MMU_CFG_offFATB ) +#ifdef CONFIG_FULL_ASSOC +#define MMU_CFG_mskFATBSZ ( 0x7f << MMU_CFG_offFATBSZ ) +#else +#define MMU_CFG_mskTBW ( 0x7 << MMU_CFG_offTBW ) +#define MMU_CFG_mskTBS ( 0x7 << MMU_CFG_offTBS ) +#endif +#define MMU_CFG_mskEP8MIN4 ( 0x1 << MMU_CFG_offEP8MIN4 ) +#define MMU_CFG_mskfEPSZ ( 0xFF << MMU_CFG_offfEPSZ ) +#define MMU_CFG_mskTLBLCK ( 0x1 << MMU_CFG_offTLBLCK ) +#define MMU_CFG_mskHPTWK ( 0x1 << MMU_CFG_offHPTWK ) +#define MMU_CFG_mskDE ( 0x1 << MMU_CFG_offDE ) +#define MMU_CFG_mskNTPT ( 0x1 << MMU_CFG_offNTPT ) +#define MMU_CFG_mskIVTB ( 0x1 << MMU_CFG_offIVTB ) +#define MMU_CFG_mskVLPT ( 0x1 << MMU_CFG_offVLPT ) +#define MMU_CFG_mskNTME ( 0x1 << MMU_CFG_offNTME ) +#define MMU_CFG_mskDRDE ( 0x1 << MMU_CFG_offDRDE ) + +/****************************************************************************** + * cr4: MSC_CFG (Misc Configuration Register) + *****************************************************************************/ +#define MSC_CFG_offEDM 0 /* EDM */ +#define MSC_CFG_offLMDMA 1 /* Local memory DMA engine */ +#define MSC_CFG_offPFM 2 /* Performance monitoring feature */ +#define MSC_CFG_offHSMP 3 /* HSMP_SADDR (V1 and V2 of HSMP) register */ +#define MSC_CFG_offTRACE 4 /* Debug Tracer Unit */ +#define MSC_CFG_offDIV 5 /* Divide instructions support */ +#define MSC_CFG_offMAC 6 /* Multiply instructions support */ +#define MSC_CFG_offAUDIO 7 /* AUDIO ISA extension support */ +#define MSC_CFG_offL2C 9 /* L2 unified cache */ +#define MSC_CFG_offRDREG 10 /* Reduced Register configuration */ +#define MSC_CFG_offADR24 11 /* Reduced Address Space to 24-bit configuration */ +#define MSC_CFG_offINTLC 12 /* interruption level configuration */ +#define MSC_CFG_offBASEV 13 /* Baseline instructions version */ +#define MSC_CFG_offNOD 16 /* Dx registers */ +#define MSC_CFG_offIMV 17 /* Implementation-dependent register detection scheme version */ +#define MSC_CFG_offIMR 18 /* First implementation-dependent register of SR encoding {2, 15, 0} */ +#define MSC_CFG_offIFC 19 /* IFC support */ +#define MSC_CFG_offMCU 20 /* MCU family */ +#define MSC_CFG_offSHADOW 21 /* shadow registers support */ +#define MSC_CFG_offEIT 24 /* EX9 support */ +#define MSC_CFG_offULM 25 /* ULM configuration */ +#define MSC_CFG_offPFT 26 /* Performance Throttling feature support */ +#define MSC_CFG_offHSP 27 /* HW Stack protection/recording feature support */ +/* bit 28:29 reserved */ +#define MSC_CFG_offMSC_EXT 30 /* Miscellaneous Configuration Extension */ + +#define MSC_CFG_mskEDM ( 0x1 << MSC_CFG_offEDM ) +#define MSC_CFG_mskLMDMA ( 0x1 << MSC_CFG_offLMDMA ) +#define MSC_CFG_mskPFM ( 0x1 << MSC_CFG_offPFM ) +#define MSC_CFG_mskHSMP ( 0x1 << MSC_CFG_offHSMP ) +#define MSC_CFG_mskTRACE ( 0x1 << MSC_CFG_offTRACE ) +#define MSC_CFG_mskDIV ( 0x1 << MSC_CFG_offDIV ) +#define MSC_CFG_mskMAC ( 0x1 << MSC_CFG_offMAC ) +#define MSC_CFG_mskAUDIO ( 0x3 << MSC_CFG_offAUDIO ) +#define MSC_CFG_mskL2C ( 0x1 << MSC_CFG_offL2C ) +#define MSC_CFG_mskRDREG ( 0x1 << MSC_CFG_offRDREG ) +#define MSC_CFG_mskADR24 ( 0x1 << MSC_CFG_offADR24 ) +#define MSC_CFG_mskINTLC ( 0x1 << MSC_CFG_offINTLC ) +#define MSC_CFG_mskBASEV ( 0x7 << MSC_CFG_offBASEV ) +#define MSC_CFG_mskNOD ( 0x1 << MSC_CFG_offNOD ) +#define MSC_CFG_mskIMV ( 0x1 << MSC_CFG_offIMV ) +#define MSC_CFG_mskIMR ( 0x1 << MSC_CFG_offIMR ) +#define MSC_CFG_mskIFC ( 0x1 << MSC_CFG_offIFC ) +#define MSC_CFG_mskMCU ( 0x1 << MSC_CFG_offMCU ) +#define MSC_CFG_mskSHADOW ( 0x7 << MSC_CFG_offSHADOW ) +#define MSC_CFG_mskEIT ( 0x1 << MSC_CFG_offEIT ) +#define MSC_CFG_mskULM ( 0x1 << MSC_CFG_offULM ) +#define MSC_CFG_mskPFT ( 0x1 << MSC_CFG_offPFT ) +#define MSC_CFG_mskHSP ( 0x1 << MSC_CFG_offHSP ) +#define MSC_CFG_mskMSC_EXT ( 0x3 << MSC_CFG_offMSC_EXT ) + +/****************************************************************************** + * cr5: CORE_CFG (Core Identification Register) + *****************************************************************************/ +#define CORE_ID_offCOREID 0 +/* bit 4:31 reserved */ + +#define CORE_ID_mskCOREID ( 0xF << CORE_ID_offCOREID ) + +/****************************************************************************** + * cr6: FUCOP_EXIST (FPU and Coprocessor Existence Configuration Register) + *****************************************************************************/ +#define FUCOP_EXIST_offCP0EX 0 /* Coprocessor #0 existence */ +#define FUCOP_EXIST_offCP1EX 1 /* Coprocessor #1 existence */ +#define FUCOP_EXIST_offCP2EX 2 /* Coprocessor #2 existence */ +#define FUCOP_EXIST_offCP3EX 3 /* Coprocessor #3 existence */ +/* bit 4:15 reserved */ +#define FUCOP_EXIST_offCPV 16 /* Coprocessor ISA extension version */ +/* bit 18:30 reserved */ +#define FUCOP_EXIST_offCP0ISFPU 31 /* Coprocessor #0 is FPU when CP0EX is 1 */ + +#define FUCOP_EXIST_mskCP0EX ( 0x1 << FUCOP_EXIST_offCP0EX ) +#define FUCOP_EXIST_mskCP1EX ( 0x1 << FUCOP_EXIST_offCP1EX ) +#define FUCOP_EXIST_mskCP2EX ( 0x1 << FUCOP_EXIST_offCP2EX ) +#define FUCOP_EXIST_mskCP3EX ( 0x1 << FUCOP_EXIST_offCP3EX ) +#define FUCOP_EXIST_mskCPV ( 0x3 << FUCOP_EXIST_offCPV ) +#define FUCOP_EXIST_mskCP0ISFPU ( 0x1 << FUCOP_EXIST_offCP0ISFPU ) + +/****************************************************************************** + * ir0: PSW (Processor Status Word Register) + * ir1: IPSW (Interruption PSW Register) + * ir2: P_IPSW (Previous IPSW Register) + *****************************************************************************/ +#define PSW_offGIE 0 /* Global Interrupt Enable */ +#define PSW_offINTL 1 /* Interruption Stack Level */ +#define PSW_offPOM 3 /* Processor Operation Mode, User/Superuser */ +#define PSW_offBE 5 /* Endianness for data memory access, 1:MSB, 0:LSB */ +#define PSW_offIT 6 /* Enable instruction address translation */ +#define PSW_offDT 7 /* Enable data address translation */ +#define PSW_offIME 8 /* Instruction Machine Error flag */ +#define PSW_offDME 9 /* Data Machine Error flag */ +#define PSW_offDEX 10 /* Debug Exception */ +#define PSW_offHSS 11 /* Hardware Single Stepping */ +#define PSW_offDRBE 12 /* Device Register Endian mode for device register */ +#define PSW_offAEN 13 /* Audio ISA special features enable control */ +#define PSW_offWBNA 14 /* write-back, write-allocation to write-back, no-write-allocation */ +#define PSW_offIFCON 15 /* Hardware Single Stepping */ +#define PSW_offCPL 16 /* Current Priority Level */ +/* bit 19 reserved */ +#define PSW_offOV 20 /* Overflow flag for saturation arithmetic instructions */ +#define PSW_offPFT_EN 21 /* Enable performance throttling */ +/* bit 22:31 reserved */ + +#define PSW_mskGIE ( 0x1 << PSW_offGIE ) +#define PSW_mskINTL ( 0x3 << PSW_offINTL ) +#define PSW_mskPOM ( 0x3 << PSW_offPOM ) +#define PSW_mskBE ( 0x1 << PSW_offBE ) +#define PSW_mskIT ( 0x1 << PSW_offIT ) +#define PSW_mskDT ( 0x1 << PSW_offDT ) +#define PSW_mskIME ( 0x1 << PSW_offIME ) +#define PSW_mskDME ( 0x1 << PSW_offDME ) +#define PSW_mskDEX ( 0x1 << PSW_offDEX ) +#define PSW_mskHSS ( 0x1 << PSW_offHSS ) +#define PSW_mskDRBE ( 0x1 << PSW_offDRBE ) +#define PSW_mskAEN ( 0x1 << PSW_offAEN ) +#define PSW_mskWBNA ( 0x1 << PSW_offWBNA ) +#define PSW_mskIFCON ( 0x1 << PSW_offIFCON ) +#define PSW_mskCPL ( 0x7 << PSW_offCPL ) +#define PSW_mskOV ( 0x1 << PSW_offOV ) +#define PSW_mskPFT_EN ( 0x1 << PSW_offPFT_EN ) + +/****************************************************************************** + * ir3: IVB (Interruption Vector Base Register) + *****************************************************************************/ +#define IVB_offPROG_PRI_LVL 0 /* Programmable Priority Level *///// +#define IVB_offNIVIC 1 /* Number of input for Internal Vector Interrupt Controller*/ +/* bit 4:10 reserved */ +#define IVB_offIVIC_VER 11 /* Internal Vectored Interrupt Controller (IVIC) Version */ +#define IVB_offEVIC 13 /* External Vector Interrupt Controller mode */ +#define IVB_offESZ 14 /* Size of each vector entry */ +#define IVB_offIVBASE 16 /* BasePA of interrupt vector table */ + +#define IVB_mskPROG_PRI_LVL ( 0x1 << IVB_offPROG_PRI_LVL) +#define IVB_mskNIVIC ( 0x7 << IVB_offNIVIC) +#define IVB_mskIVIC_VER ( 0x3 << IVB_offIVIC_VER ) +#define IVB_mskEVIC ( 0x1 << IVB_offEVIC ) +#define IVB_mskESZ ( 0x3 << IVB_offESZ ) +#define IVB_mskIVBASE ( 0xFFFF << IVB_offIVBASE ) + +/****************************************************************************** + * ir4: EVA (Exception Virtual Address Register) + * ir5: P_EVA (Previous EVA Register) + *****************************************************************************/ + + /* This register contains the VA that causes the exception */ + +/****************************************************************************** + * ir6: ITYPE (Interruption Type Register) + * ir7: P_ITYPE (Previous ITYPE Register) + *****************************************************************************/ +#define ITYPE_offETYPE 0 /* Exception Type */ +#define ITYPE_offINST 4 /* Exception caused by insn fetch or data access */ +/* bit 5:15 reserved */ +#define ITYPE_offSWID 16 /* SWID of debugging exception */ +/* bit 31:31 reserved */ + +#define ITYPE_mskETYPE ( 0xF << ITYPE_offETYPE ) +#define ITYPE_mskINST ( 0x1 << ITYPE_offINST ) +#define ITYPE_mskSWID ( 0x7FFF << ITYPE_offSWID ) + +/****************************************************************************** + * ir8: MERR (Machine Error Log Register) + *****************************************************************************/ +/* bit 0:30 reserved */ +#define MERR_offBUSERR 31 /* Bus error caused by a load insn */ + +#define MERR_mskBUSERR ( 0x1 << MERR_offBUSERR ) + +/****************************************************************************** + * ir9: IPC (Interruption Program Counter Register) + * ir10: P_IPC (Previous IPC Register) + * ir11: OIPC (Overflow Interruption Program Counter Register) + *****************************************************************************/ + + /* This is the shadow stack register of the Program Counter */ + +/****************************************************************************** + * ir12: P_P0 (Previous P0 Register) + * ir13: P_P1 (Previous P1 Register) + *****************************************************************************/ + + /* These are shadow registers of $p0 and $p1 */ + +/****************************************************************************** + * ir14: INT_MASK (Interruption Masking Register) + *****************************************************************************/ +#define INT_MASK_offH0IM 0 /* Hardware Interrupt 0 Mask bit */ +#define INT_MASK_offH1IM 1 /* Hardware Interrupt 1 Mask bit */ +#define INT_MASK_offH2IM 2 /* Hardware Interrupt 2 Mask bit */ +#define INT_MASK_offH3IM 3 /* Hardware Interrupt 3 Mask bit */ +#define INT_MASK_offH4IM 4 /* Hardware Interrupt 4 Mask bit */ +#define INT_MASK_offH5IM 5 /* Hardware Interrupt 5 Mask bit */ +#define INT_MASK_offH6IM 6 /* Hardware Interrupt 6 Mask bit */ +#define INT_MASK_offH7IM 7 /* Hardware Interrupt 7 Mask bit */ +#define INT_MASK_offH8IM 8 /* Hardware Interrupt 8 Mask bit */ +#define INT_MASK_offH9IM 9 /* Hardware Interrupt 9 Mask bit */ +#define INT_MASK_offH10IM 10 /* Hardware Interrupt 10 Mask bit */ +#define INT_MASK_offH11IM 11 /* Hardware Interrupt 11 Mask bit */ +#define INT_MASK_offH12IM 12 /* Hardware Interrupt 12 Mask bit */ +#define INT_MASK_offH13IM 13 /* Hardware Interrupt 13 Mask bit */ +#define INT_MASK_offH14IM 14 /* Hardware Interrupt 14 Mask bit */ +#define INT_MASK_offH15IM 15 /* Hardware Interrupt 15 Mask bit */ +#define INT_MASK_offSIM 16 /* Software Interrupt Mask bit */ +/* bit 17:28 reserved */ +#define INT_MASK_offALZ 29 /* All zero opcode reserved instruction exception mask */ +#define INT_MASK_offIDIVZE 30 /* Enable detection for Divide-By-Zero */ +#define INT_MASK_offDSSIM 31 /* Default Single Stepping Interruption Mask */ + +#define INT_MASK_mskH0IM ( 0x1 << INT_MASK_offH0IM ) +#define INT_MASK_mskH1IM ( 0x1 << INT_MASK_offH1IM ) +#define INT_MASK_mskH2IM ( 0x1 << INT_MASK_offH2IM ) +#define INT_MASK_mskH3IM ( 0x1 << INT_MASK_offH3IM ) +#define INT_MASK_mskH4IM ( 0x1 << INT_MASK_offH4IM ) +#define INT_MASK_mskH5IM ( 0x1 << INT_MASK_offH5IM ) +#define INT_MASK_mskH6IM ( 0x1 << INT_MASK_offH6IM ) +#define INT_MASK_mskH7IM ( 0x1 << INT_MASK_offH7IM ) +#define INT_MASK_mskH8IM ( 0x1 << INT_MASK_offH8IM ) +#define INT_MASK_mskH9IM ( 0x1 << INT_MASK_offH9IM ) +#define INT_MASK_mskH10IM ( 0x1 << INT_MASK_offH10IM ) +#define INT_MASK_mskH11IM ( 0x1 << INT_MASK_offH11IM ) +#define INT_MASK_mskH12IM ( 0x1 << INT_MASK_offH12IM ) +#define INT_MASK_mskH13IM ( 0x1 << INT_MASK_offH13IM ) +#define INT_MASK_mskH14IM ( 0x1 << INT_MASK_offH14IM ) +#define INT_MASK_mskH15IM ( 0x1 << INT_MASK_offH15IM ) +#define INT_MASK_mskSIM ( 0x1 << INT_MASK_offSIM ) +#define INT_MASK_mskALZ ( 0x1 << INT_MASK_offALZ ) +#define INT_MASK_mskIDIVZE ( 0x1 << INT_MASK_offIDIVZE ) +#define INT_MASK_mskDSSIM ( 0x1 << INT_MASK_offDSSIM ) + +/****************************************************************************** + * ir15: INT_PEND (Interruption Pending Register) + *****************************************************************************/ +#define INT_PEND_offH0I 0 /* Hardware Interrupt 0 pending bit */ +#define INT_PEND_offH1I 1 /* Hardware Interrupt 1 pending bit */ +#define INT_PEND_offH2I 2 /* Hardware Interrupt 2 pending bit */ +#define INT_PEND_offH3I 3 /* Hardware Interrupt 3 pending bit */ +#define INT_PEND_offH4I 4 /* Hardware Interrupt 4 pending bit */ +#define INT_PEND_offH5I 5 /* Hardware Interrupt 5 pending bit */ +#define INT_PEND_offH6I 6 /* Hardware Interrupt 6 pending bit */ +#define INT_PEND_offH7I 7 /* Hardware Interrupt 7 pending bit */ +#define INT_PEND_offH8I 8 /* Hardware Interrupt 8 pending bit */ +#define INT_PEND_offH9I 9 /* Hardware Interrupt 9 pending bit */ +#define INT_PEND_offH10I 10 /* Hardware Interrupt 10 pending bit */ +#define INT_PEND_offH11I 11 /* Hardware Interrupt 11 pending bit */ +#define INT_PEND_offH12I 12 /* Hardware Interrupt 12 pending bit */ +#define INT_PEND_offH13I 13 /* Hardware Interrupt 13 pending bit */ +#define INT_PEND_offH14I 14 /* Hardware Interrupt 14 pending bit */ +#define INT_PEND_offH15I 15 /* Hardware Interrupt 15 pending bit */ + +#define INT_PEND_offCIPL 0 /* Current Interrupt Priority Level */ + +#define INT_PEND_offSWI 16 /* Software Interrupt pending bit */ +/* bit 17:31 reserved */ + +#define INT_PEND_mskH0I ( 0x1 << INT_PEND_offH0I ) +#define INT_PEND_mskH1I ( 0x1 << INT_PEND_offH1I ) +#define INT_PEND_mskH2I ( 0x1 << INT_PEND_offH2I ) +#define INT_PEND_mskH3I ( 0x1 << INT_PEND_offH3I ) +#define INT_PEND_mskH4I ( 0x1 << INT_PEND_offH4I ) +#define INT_PEND_mskH5I ( 0x1 << INT_PEND_offH5I ) +#define INT_PEND_mskH6I ( 0x1 << INT_PEND_offH6I ) +#define INT_PEND_mskH7I ( 0x1 << INT_PEND_offH7I ) +#define INT_PEND_mskH8I ( 0x1 << INT_PEND_offH8I ) +#define INT_PEND_mskH9I ( 0x1 << INT_PEND_offH9I ) +#define INT_PEND_mskH10I ( 0x1 << INT_PEND_offH10I ) +#define INT_PEND_mskH11I ( 0x1 << INT_PEND_offH11I ) +#define INT_PEND_mskH12I ( 0x1 << INT_PEND_offH12I ) +#define INT_PEND_mskH13I ( 0x1 << INT_PEND_offH13I ) +#define INT_PEND_mskH14I ( 0x1 << INT_PEND_offH14I ) +#define INT_PEND_mskH15I ( 0x1 << INT_PEND_offH15I ) +#define INT_PEND_mskCIPL ( 0x1 << INT_PEND_offCIPL ) +#define INT_PEND_mskSWI ( 0x1 << INT_PEND_offSWI ) + +/****************************************************************************** + * ir16: SP_USR (Shadowed User Stack Pointer Register) + * ir17: SP_PRIV (Shadowed Privileged Stack Pointer Register) + *****************************************************************************/ + + /* These are shadow registers of $sp */ + +/****************************************************************************** + * ir18: INT_PRI (Interrupt Priority Register) + *****************************************************************************/ +#define INT_PRI_offH0PRI 0 /* Hardware Interrupt 0 Priority Level */ +#define INT_PRI_offH1PRI 2 /* Hardware Interrupt 1 Priority Level */ +#define INT_PRI_offH2PRI 4 /* Hardware Interrupt 2 Priority Level */ +#define INT_PRI_offH3PRI 6 /* Hardware Interrupt 3 Priority Level */ +#define INT_PRI_offH4PRI 8 /* Hardware Interrupt 4 Priority Level */ +#define INT_PRI_offH5PRI 10 /* Hardware Interrupt 5 Priority Level */ +#define INT_PRI_offH6PRI 12 /* Hardware Interrupt 6 Priority Level */ +#define INT_PRI_offH7PRI 14 /* Hardware Interrupt 7 Priority Level */ +#define INT_PRI_offH8PRI 16 /* Hardware Interrupt 8 Priority Level */ +#define INT_PRI_offH9PRI 18 /* Hardware Interrupt 9 Priority Level */ +#define INT_PRI_offH10PRI 20 /* Hardware Interrupt 10 Priority Level */ +#define INT_PRI_offH11PRI 22 /* Hardware Interrupt 11 Priority Level */ +#define INT_PRI_offH12PRI 24 /* Hardware Interrupt 12 Priority Level */ +#define INT_PRI_offH13PRI 26 /* Hardware Interrupt 13 Priority Level */ +#define INT_PRI_offH14PRI 28 /* Hardware Interrupt 14 Priority Level */ +#define INT_PRI_offH15PRI 30 /* Hardware Interrupt 15 Priority Level */ + +#define INT_PRI_mskH0PRI ( 0x3 << INT_PRI_offH0PRI ) +#define INT_PRI_mskH1PRI ( 0x3 << INT_PRI_offH1PRI ) +#define INT_PRI_mskH2PRI ( 0x3 << INT_PRI_offH2PRI ) +#define INT_PRI_mskH3PRI ( 0x3 << INT_PRI_offH3PRI ) +#define INT_PRI_mskH4PRI ( 0x3 << INT_PRI_offH4PRI ) +#define INT_PRI_mskH5PRI ( 0x3 << INT_PRI_offH5PRI ) +#define INT_PRI_mskH6PRI ( 0x3 << INT_PRI_offH6PRI ) +#define INT_PRI_mskH7PRI ( 0x3 << INT_PRI_offH7PRI ) +#define INT_PRI_mskH8PRI ( 0x3 << INT_PRI_offH8PRI ) +#define INT_PRI_mskH9PRI ( 0x3 << INT_PRI_offH9PRI ) +#define INT_PRI_mskH10PRI ( 0x3 << INT_PRI_offH10PRI ) +#define INT_PRI_mskH11PRI ( 0x3 << INT_PRI_offH11PRI ) +#define INT_PRI_mskH12PRI ( 0x3 << INT_PRI_offH12PRI ) +#define INT_PRI_mskH13PRI ( 0x3 << INT_PRI_offH13PRI ) +#define INT_PRI_mskH14PRI ( 0x3 << INT_PRI_offH14PRI ) +#define INT_PRI_mskH15PRI ( 0x3 << INT_PRI_offH15PRI ) + +/****************************************************************************** + * ir19: INT_CTRL (Interrupt Control Register) + *****************************************************************************/ +#define INT_CTRL_offPPL2FIX_EN 0 +/* bit 1:31 reserved */ + +#define INT_CTRL_mskPPL2FIX_EN ( 0x1 << INT_CTRL_offPPL2FIX_EN ) + +/****************************************************************************** + * ir26: INT_MASK2 (Interruption Masking Register 2) + *****************************************************************************/ +#define INT_MASK2_offH0IM 0 /* Hardware Interrupt 0 Mask bit */ +#define INT_MASK2_offH1IM 1 /* Hardware Interrupt 1 Mask bit */ +#define INT_MASK2_offH2IM 2 /* Hardware Interrupt 2 Mask bit */ +#define INT_MASK2_offH3IM 3 /* Hardware Interrupt 3 Mask bit */ +#define INT_MASK2_offH4IM 4 /* Hardware Interrupt 4 Mask bit */ +#define INT_MASK2_offH5IM 5 /* Hardware Interrupt 5 Mask bit */ +#define INT_MASK2_offH6IM 6 /* Hardware Interrupt 6 Mask bit */ +#define INT_MASK2_offH7IM 7 /* Hardware Interrupt 7 Mask bit */ +#define INT_MASK2_offH8IM 8 /* Hardware Interrupt 8 Mask bit */ +#define INT_MASK2_offH9IM 9 /* Hardware Interrupt 9 Mask bit */ +#define INT_MASK2_offH10IM 10 /* Hardware Interrupt 10 Mask bit */ +#define INT_MASK2_offH11IM 11 /* Hardware Interrupt 11 Mask bit */ +#define INT_MASK2_offH12IM 12 /* Hardware Interrupt 12 Mask bit */ +#define INT_MASK2_offH13IM 13 /* Hardware Interrupt 13 Mask bit */ +#define INT_MASK2_offH14IM 14 /* Hardware Interrupt 14 Mask bit */ +#define INT_MASK2_offH15IM 15 /* Hardware Interrupt 15 Mask bit */ +#define INT_MASK2_offH16IM 16 /* Hardware Interrupt 16 Mask bit */ +#define INT_MASK2_offH17IM 17 /* Hardware Interrupt 17 Mask bit */ +#define INT_MASK2_offH18IM 18 /* Hardware Interrupt 18 Mask bit */ +#define INT_MASK2_offH19IM 19 /* Hardware Interrupt 19 Mask bit */ +#define INT_MASK2_offH20IM 20 /* Hardware Interrupt 20 Mask bit */ +#define INT_MASK2_offH21IM 21 /* Hardware Interrupt 21 Mask bit */ +#define INT_MASK2_offH22IM 22 /* Hardware Interrupt 22 Mask bit */ +#define INT_MASK2_offH23IM 23 /* Hardware Interrupt 23 Mask bit */ +#define INT_MASK2_offH24IM 24 /* Hardware Interrupt 24 Mask bit */ +#define INT_MASK2_offH25IM 25 /* Hardware Interrupt 25 Mask bit */ +#define INT_MASK2_offH26IM 26 /* Hardware Interrupt 26 Mask bit */ +#define INT_MASK2_offH27IM 27 /* Hardware Interrupt 27 Mask bit */ +#define INT_MASK2_offH28IM 28 /* Hardware Interrupt 28 Mask bit */ +#define INT_MASK2_offH29IM 29 /* Hardware Interrupt 29 Mask bit */ +#define INT_MASK2_offH30IM 30 /* Hardware Interrupt 30 Mask bit */ +#define INT_MASK2_offH31IM 31 /* Hardware Interrupt 31 Mask bit */ + +#define INT_MASK2_mskH0IM ( 0x1 << INT_MASK2_offH0IM ) +#define INT_MASK2_mskH1IM ( 0x1 << INT_MASK2_offH1IM ) +#define INT_MASK2_mskH2IM ( 0x1 << INT_MASK2_offH2IM ) +#define INT_MASK2_mskH3IM ( 0x1 << INT_MASK2_offH3IM ) +#define INT_MASK2_mskH4IM ( 0x1 << INT_MASK2_offH4IM ) +#define INT_MASK2_mskH5IM ( 0x1 << INT_MASK2_offH5IM ) +#define INT_MASK2_mskH6IM ( 0x1 << INT_MASK2_offH6IM ) +#define INT_MASK2_mskH7IM ( 0x1 << INT_MASK2_offH7IM ) +#define INT_MASK2_mskH8IM ( 0x1 << INT_MASK2_offH8IM ) +#define INT_MASK2_mskH9IM ( 0x1 << INT_MASK2_offH9IM ) +#define INT_MASK2_mskH10IM ( 0x1 << INT_MASK2_offH10IM ) +#define INT_MASK2_mskH11IM ( 0x1 << INT_MASK2_offH11IM ) +#define INT_MASK2_mskH12IM ( 0x1 << INT_MASK2_offH12IM ) +#define INT_MASK2_mskH13IM ( 0x1 << INT_MASK2_offH13IM ) +#define INT_MASK2_mskH14IM ( 0x1 << INT_MASK2_offH14IM ) +#define INT_MASK2_mskH15IM ( 0x1 << INT_MASK2_offH15IM ) +#define INT_MASK2_mskH16IM ( 0x1 << INT_MASK2_offH16IM ) +#define INT_MASK2_mskH17IM ( 0x1 << INT_MASK2_offH17IM ) +#define INT_MASK2_mskH18IM ( 0x1 << INT_MASK2_offH18IM ) +#define INT_MASK2_mskH19IM ( 0x1 << INT_MASK2_offH19IM ) +#define INT_MASK2_mskH20IM ( 0x1 << INT_MASK2_offH20IM ) +#define INT_MASK2_mskH21IM ( 0x1 << INT_MASK2_offH21IM ) +#define INT_MASK2_mskH22IM ( 0x1 << INT_MASK2_offH22IM ) +#define INT_MASK2_mskH23IM ( 0x1 << INT_MASK2_offH23IM ) +#define INT_MASK2_mskH24IM ( 0x1 << INT_MASK2_offH24IM ) +#define INT_MASK2_mskH25IM ( 0x1 << INT_MASK2_offH25IM ) +#define INT_MASK2_mskH26IM ( 0x1 << INT_MASK2_offH26IM ) +#define INT_MASK2_mskH27IM ( 0x1 << INT_MASK2_offH27IM ) +#define INT_MASK2_mskH28IM ( 0x1 << INT_MASK2_offH28IM ) +#define INT_MASK2_mskH29IM ( 0x1 << INT_MASK2_offH29IM ) +#define INT_MASK2_mskH30IM ( 0x1 << INT_MASK2_offH30IM ) +#define INT_MASK2_mskH31IM ( 0x1 << INT_MASK2_offH31IM ) + +/****************************************************************************** + * ir27: INT_PEND2 (Interruption Pending Register 2) + *****************************************************************************/ +#define INT_PEND2_offH0I 0 /* Hardware Interrupt 0 Pending bit */ +#define INT_PEND2_offH1I 1 /* Hardware Interrupt 1 Pending bit */ +#define INT_PEND2_offH2I 2 /* Hardware Interrupt 2 Pending bit */ +#define INT_PEND2_offH3I 3 /* Hardware Interrupt 3 Pending bit */ +#define INT_PEND2_offH4I 4 /* Hardware Interrupt 4 Pending bit */ +#define INT_PEND2_offH5I 5 /* Hardware Interrupt 5 Pending bit */ +#define INT_PEND2_offH6I 6 /* Hardware Interrupt 6 Pending bit */ +#define INT_PEND2_offH7I 7 /* Hardware Interrupt 7 Pending bit */ +#define INT_PEND2_offH8I 8 /* Hardware Interrupt 8 Pending bit */ +#define INT_PEND2_offH9I 9 /* Hardware Interrupt 9 Pending bit */ +#define INT_PEND2_offH10I 10 /* Hardware Interrupt 10 Pending bit */ +#define INT_PEND2_offH11I 11 /* Hardware Interrupt 11 Pending bit */ +#define INT_PEND2_offH12I 12 /* Hardware Interrupt 12 Pending bit */ +#define INT_PEND2_offH13I 13 /* Hardware Interrupt 13 Pending bit */ +#define INT_PEND2_offH14I 14 /* Hardware Interrupt 14 Pending bit */ +#define INT_PEND2_offH15I 15 /* Hardware Interrupt 15 Pending bit */ +#define INT_PEND2_offH16I 16 /* Hardware Interrupt 16 Pending bit */ +#define INT_PEND2_offH17I 17 /* Hardware Interrupt 17 Pending bit */ +#define INT_PEND2_offH18I 18 /* Hardware Interrupt 18 Pending bit */ +#define INT_PEND2_offH19I 19 /* Hardware Interrupt 19 Pending bit */ +#define INT_PEND2_offH20I 20 /* Hardware Interrupt 20 Pending bit */ +#define INT_PEND2_offH21I 21 /* Hardware Interrupt 21 Pending bit */ +#define INT_PEND2_offH22I 22 /* Hardware Interrupt 22 Pending bit */ +#define INT_PEND2_offH23I 23 /* Hardware Interrupt 23 Pending bit */ +#define INT_PEND2_offH24I 24 /* Hardware Interrupt 24 Pending bit */ +#define INT_PEND2_offH25I 25 /* Hardware Interrupt 25 Pending bit */ +#define INT_PEND2_offH26I 26 /* Hardware Interrupt 26 Pending bit */ +#define INT_PEND2_offH27I 27 /* Hardware Interrupt 27 Pending bit */ +#define INT_PEND2_offH28I 28 /* Hardware Interrupt 28 Pending bit */ +#define INT_PEND2_offH29I 29 /* Hardware Interrupt 29 Pending bit */ +#define INT_PEND2_offH30I 30 /* Hardware Interrupt 30 Pending bit */ +#define INT_PEND2_offH31I 31 /* Hardware Interrupt 31 Pending bit */ + +#define INT_PEND2_mskH0I ( 0x1 << INT_PEND2_offH0I ) +#define INT_PEND2_mskH1I ( 0x1 << INT_PEND2_offH1I ) +#define INT_PEND2_mskH2I ( 0x1 << INT_PEND2_offH2I ) +#define INT_PEND2_mskH3I ( 0x1 << INT_PEND2_offH3I ) +#define INT_PEND2_mskH4I ( 0x1 << INT_PEND2_offH4I ) +#define INT_PEND2_mskH5I ( 0x1 << INT_PEND2_offH5I ) +#define INT_PEND2_mskH6I ( 0x1 << INT_PEND2_offH6I ) +#define INT_PEND2_mskH7I ( 0x1 << INT_PEND2_offH7I ) +#define INT_PEND2_mskH8I ( 0x1 << INT_PEND2_offH8I ) +#define INT_PEND2_mskH9I ( 0x1 << INT_PEND2_offH9I ) +#define INT_PEND2_mskH10I ( 0x1 << INT_PEND2_offH10I ) +#define INT_PEND2_mskH11I ( 0x1 << INT_PEND2_offH11I ) +#define INT_PEND2_mskH12I ( 0x1 << INT_PEND2_offH12I ) +#define INT_PEND2_mskH13I ( 0x1 << INT_PEND2_offH13I ) +#define INT_PEND2_mskH14I ( 0x1 << INT_PEND2_offH14I ) +#define INT_PEND2_mskH15I ( 0x1 << INT_PEND2_offH15I ) +#define INT_PEND2_mskH16I ( 0x1 << INT_PEND2_offH16I ) +#define INT_PEND2_mskH17I ( 0x1 << INT_PEND2_offH17I ) +#define INT_PEND2_mskH18I ( 0x1 << INT_PEND2_offH18I ) +#define INT_PEND2_mskH19I ( 0x1 << INT_PEND2_offH19I ) +#define INT_PEND2_mskH20I ( 0x1 << INT_PEND2_offH20I ) +#define INT_PEND2_mskH21I ( 0x1 << INT_PEND2_offH21I ) +#define INT_PEND2_mskH22I ( 0x1 << INT_PEND2_offH22I ) +#define INT_PEND2_mskH23I ( 0x1 << INT_PEND2_offH23I ) +#define INT_PEND2_mskH24I ( 0x1 << INT_PEND2_offH24I ) +#define INT_PEND2_mskH25I ( 0x1 << INT_PEND2_offH25I ) +#define INT_PEND2_mskH26I ( 0x1 << INT_PEND2_offH26I ) +#define INT_PEND2_mskH27I ( 0x1 << INT_PEND2_offH27I ) +#define INT_PEND2_mskH28I ( 0x1 << INT_PEND2_offH28I ) +#define INT_PEND2_mskH29I ( 0x1 << INT_PEND2_offH29I ) +#define INT_PEND2_mskH30I ( 0x1 << INT_PEND2_offH30I ) +#define INT_PEND2_mskH31I ( 0x1 << INT_PEND2_offH31I ) + +/****************************************************************************** + * ir28: INT_PRI2 (Interrupt Priority Register) + *****************************************************************************/ +#define INT_PRI_offH16PRI 0 /* Hardware Interrupt 16 Priority Level */ +#define INT_PRI_offH17PRI 2 /* Hardware Interrupt 17 Priority Level */ +#define INT_PRI_offH18PRI 4 /* Hardware Interrupt 18 Priority Level */ +#define INT_PRI_offH19PRI 6 /* Hardware Interrupt 19 Priority Level */ +#define INT_PRI_offH20PRI 8 /* Hardware Interrupt 20 Priority Level */ +#define INT_PRI_offH21PRI 10 /* Hardware Interrupt 21 Priority Level */ +#define INT_PRI_offH22PRI 12 /* Hardware Interrupt 22 Priority Level */ +#define INT_PRI_offH23PRI 14 /* Hardware Interrupt 23 Priority Level */ +#define INT_PRI_offH24PRI 16 /* Hardware Interrupt 24 Priority Level */ +#define INT_PRI_offH25PRI 18 /* Hardware Interrupt 25 Priority Level */ +#define INT_PRI_offH26PRI 20 /* Hardware Interrupt 26 Priority Level */ +#define INT_PRI_offH27PRI 22 /* Hardware Interrupt 27 Priority Level */ +#define INT_PRI_offH28PRI 24 /* Hardware Interrupt 28 Priority Level */ +#define INT_PRI_offH29PRI 26 /* Hardware Interrupt 29 Priority Level */ +#define INT_PRI_offH30PRI 28 /* Hardware Interrupt 30 Priority Level */ +#define INT_PRI_offH31PRI 30 /* Hardware Interrupt 31 Priority Level */ + +#define INT_PRI_mskH16PRI ( 0x3 << INT_PRI_offH16PRI ) +#define INT_PRI_mskH17PRI ( 0x3 << INT_PRI_offH17PRI ) +#define INT_PRI_mskH18PRI ( 0x3 << INT_PRI_offH18PRI ) +#define INT_PRI_mskH19PRI ( 0x3 << INT_PRI_offH19PRI ) +#define INT_PRI_mskH20PRI ( 0x3 << INT_PRI_offH20PRI ) +#define INT_PRI_mskH21PRI ( 0x3 << INT_PRI_offH21PRI ) +#define INT_PRI_mskH22PRI ( 0x3 << INT_PRI_offH22PRI ) +#define INT_PRI_mskH23PRI ( 0x3 << INT_PRI_offH23PRI ) +#define INT_PRI_mskH24PRI ( 0x3 << INT_PRI_offH24PRI ) +#define INT_PRI_mskH25PRI ( 0x3 << INT_PRI_offH25PRI ) +#define INT_PRI_mskH26PRI ( 0x3 << INT_PRI_offH26PRI ) +#define INT_PRI_mskH27PRI ( 0x3 << INT_PRI_offH27PRI ) +#define INT_PRI_mskH28PRI ( 0x3 << INT_PRI_offH28PRI ) +#define INT_PRI_mskH29PRI ( 0x3 << INT_PRI_offH29PRI ) +#define INT_PRI_mskH30PRI ( 0x3 << INT_PRI_offH30PRI ) +#define INT_PRI_mskH31PRI ( 0x3 << INT_PRI_offH31PRI ) + +/****************************************************************************** + * ir29: INT_TRIGGER (Interrupt Trigger Type Register) + *****************************************************************************/ +#define INT_TRIGGER_offH0TRIG 0 /* Hardware Interrupt 0 Trigger Type bit */ +#define INT_TRIGGER_offH1TRIG 1 /* Hardware Interrupt 1 Trigger Type bit */ +#define INT_TRIGGER_offH2TRIG 2 /* Hardware Interrupt 2 Trigger Type bit */ +#define INT_TRIGGER_offH3TRIG 3 /* Hardware Interrupt 3 Trigger Type bit */ +#define INT_TRIGGER_offH4TRIG 4 /* Hardware Interrupt 4 Trigger Type bit */ +#define INT_TRIGGER_offH5TRIG 5 /* Hardware Interrupt 5 Trigger Type bit */ +#define INT_TRIGGER_offH6TRIG 6 /* Hardware Interrupt 6 Trigger Type bit */ +#define INT_TRIGGER_offH7TRIG 7 /* Hardware Interrupt 7 Trigger Type bit */ +#define INT_TRIGGER_offH8TRIG 8 /* Hardware Interrupt 8 Trigger Type bit */ +#define INT_TRIGGER_offH9TRIG 9 /* Hardware Interrupt 9 Trigger Type bit */ +#define INT_TRIGGER_offH10TRIG 10 /* Hardware Interrupt 10 Trigger Type bit */ +#define INT_TRIGGER_offH11TRIG 11 /* Hardware Interrupt 11 Trigger Type bit */ +#define INT_TRIGGER_offH12TRIG 12 /* Hardware Interrupt 12 Trigger Type bit */ +#define INT_TRIGGER_offH13TRIG 13 /* Hardware Interrupt 13 Trigger Type bit */ +#define INT_TRIGGER_offH14TRIG 14 /* Hardware Interrupt 14 Trigger Type bit */ +#define INT_TRIGGER_offH15TRIG 15 /* Hardware Interrupt 15 Trigger Type bit */ +#define INT_TRIGGER_offH16TRIG 16 /* Hardware Interrupt 16 Trigger Type bit */ +#define INT_TRIGGER_offH17TRIG 17 /* Hardware Interrupt 17 Trigger Type bit */ +#define INT_TRIGGER_offH18TRIG 18 /* Hardware Interrupt 18 Trigger Type bit */ +#define INT_TRIGGER_offH19TRIG 19 /* Hardware Interrupt 19 Trigger Type bit */ +#define INT_TRIGGER_offH20TRIG 20 /* Hardware Interrupt 20 Trigger Type bit */ +#define INT_TRIGGER_offH21TRIG 21 /* Hardware Interrupt 21 Trigger Type bit */ +#define INT_TRIGGER_offH22TRIG 22 /* Hardware Interrupt 22 Trigger Type bit */ +#define INT_TRIGGER_offH23TRIG 23 /* Hardware Interrupt 23 Trigger Type bit */ +#define INT_TRIGGER_offH24TRIG 24 /* Hardware Interrupt 24 Trigger Type bit */ +#define INT_TRIGGER_offH25TRIG 25 /* Hardware Interrupt 25 Trigger Type bit */ +#define INT_TRIGGER_offH26TRIG 26 /* Hardware Interrupt 26 Trigger Type bit */ +#define INT_TRIGGER_offH27TRIG 27 /* Hardware Interrupt 27 Trigger Type bit */ +#define INT_TRIGGER_offH28TRIG 28 /* Hardware Interrupt 28 Trigger Type bit */ +#define INT_TRIGGER_offH29TRIG 29 /* Hardware Interrupt 29 Trigger Type bit */ +#define INT_TRIGGER_offH30TRIG 30 /* Hardware Interrupt 30 Trigger Type bit */ +#define INT_TRIGGER_offH31TRIG 31 /* Hardware Interrupt 31 Trigger Type bit */ + +#define INT_TRIGGER_mskH0TRIG ( 0x1 << INT_TRIGGER_offH0TRIG ) +#define INT_TRIGGER_mskH1TRIG ( 0x1 << INT_TRIGGER_offH1TRIG ) +#define INT_TRIGGER_mskH2TRIG ( 0x1 << INT_TRIGGER_offH2TRIG ) +#define INT_TRIGGER_mskH3TRIG ( 0x1 << INT_TRIGGER_offH3TRIG ) +#define INT_TRIGGER_mskH4TRIG ( 0x1 << INT_TRIGGER_offH4TRIG ) +#define INT_TRIGGER_mskH5TRIG ( 0x1 << INT_TRIGGER_offH5TRIG ) +#define INT_TRIGGER_mskH6TRIG ( 0x1 << INT_TRIGGER_offH6TRIG ) +#define INT_TRIGGER_mskH7TRIG ( 0x1 << INT_TRIGGER_offH7TRIG ) +#define INT_TRIGGER_mskH8TRIG ( 0x1 << INT_TRIGGER_offH8TRIG ) +#define INT_TRIGGER_mskH9TRIG ( 0x1 << INT_TRIGGER_offH9TRIG ) +#define INT_TRIGGER_mskH10TRIG ( 0x1 << INT_TRIGGER_offH10TRIG ) +#define INT_TRIGGER_mskH11TRIG ( 0x1 << INT_TRIGGER_offH11TRIG ) +#define INT_TRIGGER_mskH12TRIG ( 0x1 << INT_TRIGGER_offH12TRIG ) +#define INT_TRIGGER_mskH13TRIG ( 0x1 << INT_TRIGGER_offH13TRIG ) +#define INT_TRIGGER_mskH14TRIG ( 0x1 << INT_TRIGGER_offH14TRIG ) +#define INT_TRIGGER_mskH15TRIG ( 0x1 << INT_TRIGGER_offH15TRIG ) +#define INT_TRIGGER_mskH16TRIG ( 0x1 << INT_TRIGGER_offH16TRIG ) +#define INT_TRIGGER_mskH17TRIG ( 0x1 << INT_TRIGGER_offH17TRIG ) +#define INT_TRIGGER_mskH18TRIG ( 0x1 << INT_TRIGGER_offH18TRIG ) +#define INT_TRIGGER_mskH19TRIG ( 0x1 << INT_TRIGGER_offH19TRIG ) +#define INT_TRIGGER_mskH20TRIG ( 0x1 << INT_TRIGGER_offH20TRIG ) +#define INT_TRIGGER_mskH21TRIG ( 0x1 << INT_TRIGGER_offH21TRIG ) +#define INT_TRIGGER_mskH22TRIG ( 0x1 << INT_TRIGGER_offH22TRIG ) +#define INT_TRIGGER_mskH23TRIG ( 0x1 << INT_TRIGGER_offH23TRIG ) +#define INT_TRIGGER_mskH24TRIG ( 0x1 << INT_TRIGGER_offH24TRIG ) +#define INT_TRIGGER_mskH25TRIG ( 0x1 << INT_TRIGGER_offH25TRIG ) +#define INT_TRIGGER_mskH26TRIG ( 0x1 << INT_TRIGGER_offH26TRIG ) +#define INT_TRIGGER_mskH27TRIG ( 0x1 << INT_TRIGGER_offH27TRIG ) +#define INT_TRIGGER_mskH28TRIG ( 0x1 << INT_TRIGGER_offH28TRIG ) +#define INT_TRIGGER_mskH29TRIG ( 0x1 << INT_TRIGGER_offH29TRIG ) +#define INT_TRIGGER_mskH30TRIG ( 0x1 << INT_TRIGGER_offH30TRIG ) +#define INT_TRIGGER_mskH31TRIG ( 0x1 << INT_TRIGGER_offH31TRIG ) + +/****************************************************************************** + * mr0: MMU_CTL (MMU Control Register) + *****************************************************************************/ +#define MMU_CTL_offD 0 /* Default minimum page size */ +#define MMU_CTL_offNTC0 1 /* Non-Translated Cachebility of partition 0 */ +#define MMU_CTL_offNTC1 3 /* Non-Translated Cachebility of partition 1 */ +#define MMU_CTL_offNTC2 5 /* Non-Translated Cachebility of partition 2 */ +#define MMU_CTL_offNTC3 7 /* Non-Translated Cachebility of partition 3 */ +#define MMU_CTL_offTBALCK 9 /* TLB all-lock resolution scheme */ +#define MMU_CTL_offMPZIU 10 /* Multiple Page Size In Use bit */ +#define MMU_CTL_offNTM0 11 /* Non-Translated VA to PA of partition 0 */ +#define MMU_CTL_offNTM1 13 /* Non-Translated VA to PA of partition 1 */ +#define MMU_CTL_offNTM2 15 /* Non-Translated VA to PA of partition 2 */ +#define MMU_CTL_offNTM3 17 /* Non-Translated VA to PA of partition 3 */ +#define MMU_CTL_offDREE 19 /* Device register endian control enable */ +/* bit 20:31 reserved */ + +#define MMU_CTL_mskD ( 0x1 << MMU_CTL_offD ) +#define MMU_CTL_mskNTC0 ( 0x3 << MMU_CTL_offNTC0 ) +#define MMU_CTL_mskNTC1 ( 0x3 << MMU_CTL_offNTC1 ) +#define MMU_CTL_mskNTC2 ( 0x3 << MMU_CTL_offNTC2 ) +#define MMU_CTL_mskNTC3 ( 0x3 << MMU_CTL_offNTC3 ) +#define MMU_CTL_mskTBALCK ( 0x1 << MMU_CTL_offTBALCK ) +#define MMU_CTL_mskMPZIU ( 0x1 << MMU_CTL_offMPZIU ) +#define MMU_CTL_mskNTM0 ( 0x3 << MMU_CTL_offNTM0 ) +#define MMU_CTL_mskNTM1 ( 0x3 << MMU_CTL_offNTM1 ) +#define MMU_CTL_mskNTM2 ( 0x3 << MMU_CTL_offNTM2 ) +#define MMU_CTL_mskNTM3 ( 0x3 << MMU_CTL_offNTM3 ) +#define MMU_CTL_mskDREE ( 0x1 << MMU_CTL_offDREE ) + +/****************************************************************************** + * mr1: L1_PPTB (L1 Physical Page Table Base Register) + *****************************************************************************/ +#define L1_PPTB_offNV 0 /* Enable Hardware Page Table Walker (HPTWK) */ +/* bit 1:11 reserved */ +#define L1_PPTB_offBASE 12 /* First level physical page table base address */ + +#define L1_PPTB_mskNV ( 0x1 << L1_PPTB_offNV ) +#define L1_PPTB_mskBASE ( 0xFFFFF << L1_PPTB_offBASE ) + +/****************************************************************************** + * mr2: TLB_VPN (TLB Access VPN Register) + *****************************************************************************/ +/* bit 0:11 reserved */ +#define TLB_VPN_offVPN 12 /* Virtual Page Number */ + +#define TLB_VPN_mskVPN ( 0xFFFFF << TLB_VPN_offVPN ) + +/****************************************************************************** + * mr3: TLB_DATA (TLB Access Data Register) + *****************************************************************************/ +#define TLB_DATA_offV 0 /* PTE is valid and present */ +#define TLB_DATA_offM 1 /* Page read/write access privilege */ +#define TLB_DATA_offD 4 /* Dirty bit */ +#define TLB_DATA_offX 5 /* Executable bit */ +#define TLB_DATA_offA 6 /* Access bit */ +#define TLB_DATA_offG 7 /* Global page (shared across contexts) */ +#define TLB_DATA_offC 8 /* Cacheability atribute */ +/* bit 11:11 reserved */ +#define TLB_DATA_offPPN 12 /* Phisical Page Number */ + +#define TLB_DATA_mskV ( 0x1 << TLB_DATA_offV ) +#define TLB_DATA_mskM ( 0x7 << TLB_DATA_offM ) +#define TLB_DATA_mskD ( 0x1 << TLB_DATA_offD ) +#define TLB_DATA_mskX ( 0x1 << TLB_DATA_offX ) +#define TLB_DATA_mskA ( 0x1 << TLB_DATA_offA ) +#define TLB_DATA_mskG ( 0x1 << TLB_DATA_offG ) +#define TLB_DATA_mskC ( 0x7 << TLB_DATA_offC ) +#define TLB_DATA_mskPPN ( 0xFFFFF << TLB_DATA_offPPN ) + +/****************************************************************************** + * mr4: TLB_MISC (TLB Access Misc Register) + *****************************************************************************/ +#define TLB_MISC_offACC_PSZ 0 /* Page size of a PTE entry */ +#define TLB_MISC_offCID 4 /* Context id */ +/* bit 13:31 reserved */ + +#define TLB_MISC_mskACC_PSZ ( 0xF << TLB_MISC_offACC_PSZ ) +#define TLB_MISC_mskCID ( 0x1FF << TLB_MISC_offCID ) + +/****************************************************************************** + * mr5: VLPT_IDX (Virtual Linear Page Table Index Register) + *****************************************************************************/ +#define VLPT_IDX_offZERO 0 /* Always 0 */ +#define VLPT_IDX_offEVPN 2 /* Exception Virtual Page Number */ +#define VLPT_IDX_offVLPTB 22 /* Base VA of VLPT */ + +#define VLPT_IDX_mskZERO ( 0x3 << VLPT_IDX_offZERO ) +#define VLPT_IDX_mskEVPN ( 0xFFFFF << VLPT_IDX_offEVPN ) +#define VLPT_IDX_mskVLPTB ( 0x3FF << VLPT_IDX_offVLPTB ) + +/****************************************************************************** + * mr6: ILMB (Instruction Local Memory Base Register) + *****************************************************************************/ +#define ILMB_offIEN 0 /* Enable ILM */ +#define ILMB_offILMSZ 1 /* Size of ILM */ +/* bit 5:19 reserved */ +#define ILMB_offIBPA 10 /* Base PA of ILM */ + +#define ILMB_mskIEN ( 0x1 << ILMB_offIEN ) +#define ILMB_mskILMSZ ( 0xF << ILMB_offILMSZ ) +#define ILMB_mskIBPA ( 0xFFF << ILMB_offIBPA ) + +/****************************************************************************** + * mr7: DLMB (Data Local Memory Base Register) + *****************************************************************************/ +#define DLMB_offDEN 0 /* Enable DLM */ +#define DLMB_offDLMSZ 1 /* Size of DLM */ +#define DLMB_offDBM 5 /* Enable Double-Buffer Mode for DLM */ +#define DLMB_offDBB 6 /* Double-buffer bank which can be accessed by the processor */ +/* bit 7:19 reserved */ +#define DLMB_offDBPA 10 /* Base PA of DLM */ + +#define DLMB_mskDEN ( 0x1 << DLMB_offDEN ) +#define DLMB_mskDLMSZ ( 0xF << DLMB_offDLMSZ ) +#define DLMB_mskDBM ( 0x1 << DLMB_offDBM ) +#define DLMB_mskDBB ( 0x1 << DLMB_offDBB ) +#define DLMB_mskDBPA ( 0xFFF << DLMB_offDBPA ) + +/****************************************************************************** + * mr8: CACHE_CTL (Cache Control Register) + *****************************************************************************/ +#define CACHE_CTL_offIC_EN 0 /* Enable I-cache */ +#define CACHE_CTL_offDC_EN 1 /* Enable D-cache */ +#define CACHE_CTL_offICALCK 2 /* I-cache all-lock resolution scheme */ +#define CACHE_CTL_offDCALCK 3 /* D-cache all-lock resolution scheme */ +#define CACHE_CTL_offDCCWF 4 /* Enable D-cache Critical Word Forwarding */ +#define CACHE_CTL_offDCPMW 5 /* Enable D-cache concurrent miss and write-back processing */ +/* bit 6:31 reserved */ + +#define CACHE_CTL_mskIC_EN ( 0x1 << CACHE_CTL_offIC_EN ) +#define CACHE_CTL_mskDC_EN ( 0x1 << CACHE_CTL_offDC_EN ) +#define CACHE_CTL_mskICALCK ( 0x1 << CACHE_CTL_offICALCK ) +#define CACHE_CTL_mskDCALCK ( 0x1 << CACHE_CTL_offDCALCK ) +#define CACHE_CTL_mskDCCWF ( 0x1 << CACHE_CTL_offDCCWF ) +#define CACHE_CTL_mskDCPMW ( 0x1 << CACHE_CTL_offDCPMW ) + +/****************************************************************************** + * mr9: HSMP_SADDR (High Speed Memory Port Starting Address) + *****************************************************************************/ +#define HSMP_SADDR_offEN 0 /* Enable control bit for the High Speed Memory port */ +#define HSMP_SADDR_offRANGE 1 /* Denote the address range (only defined in HSMP v2 ) */ +/* bit 13:19 reserved */ + +#define HSMP_SADDR_offSADJ1DR 20 /* Starting base PA of the High Speed Memory Port region */ + +#define HSMP_SADDR_mskEN ( 0x1 << HSMP_SADDR_offEN ) +#define HSMP_SADDR_mskRANGE ( 0xFFF << HSMP_SADDR_offRANGE ) +#define HSMP_SADDR_mskSADDR ( 0xFFF << HSMP_SADDR_offSADDR ) + +/****************************************************************************** + * mr10: HSMP_EADDR (High Speed Memory Port Ending Address) + *****************************************************************************/ +/* bit 0:19 reserved */ +#define HSMP_EADDR_offEADDR 20 + +#define HSMP_EADDR_mskEADDR ( 0xFFF << HSMP_EADDR_offEADDR ) + +/****************************************************************************** + * dr0+(n*5): BPCn (n=0-7) (Breakpoint Control Register) + *****************************************************************************/ +#define BPC_offWP 0 /* Configuration of BPAn */ +#define BPC_offEL 1 /* Enable BPAn */ +#define BPC_offS 2 /* Data address comparison for a store instruction */ +#define BPC_offP 3 /* Compared data address is PA */ +#define BPC_offC 4 /* CID value is compared with the BPCIDn register */ +#define BPC_offBE0 5 /* Enable byte mask for the comparison with register */ +#define BPC_offBE1 6 /* Enable byte mask for the comparison with register */ +#define BPC_offBE2 7 /* Enable byte mask for the comparison with register */ +#define BPC_offBE3 8 /* Enable byte mask for the comparison with register */ +#define BPC_offT 9 /* Enable breakpoint Embedded Tracer triggering operation */ + +#define BPC_mskWP ( 0x1 << BPC_offWP ) +#define BPC_mskEL ( 0x1 << BPC_offEL ) +#define BPC_mskS ( 0x1 << BPC_offS ) +#define BPC_mskP ( 0x1 << BPC_offP ) +#define BPC_mskC ( 0x1 << BPC_offC ) +#define BPC_mskBE0 ( 0x1 << BPC_offBE0 ) +#define BPC_mskBE1 ( 0x1 << BPC_offBE1 ) +#define BPC_mskBE2 ( 0x1 << BPC_offBE2 ) +#define BPC_mskBE3 ( 0x1 << BPC_offBE3 ) +#define BPC_mskT ( 0x1 << BPC_offT ) + +/****************************************************************************** + * dr1+(n*5): BPAn (n=0-7) (Breakpoint Address Register) + *****************************************************************************/ + + /* These registers contain break point address */ + +/****************************************************************************** + * dr2+(n*5): BPAMn (n=0-7) (Breakpoint Address Mask Register) + *****************************************************************************/ + + /* These registerd contain the address comparison mask for the BPAn register */ + +/****************************************************************************** + * dr3+(n*5): BPVn (n=0-7) Breakpoint Data Value Register + *****************************************************************************/ + + /* The BPVn register contains the data value that will be compared with the + * incoming load/store data value */ + +/****************************************************************************** + * dr4+(n*5): BPCIDn (n=0-7) (Breakpoint Context ID Register) + *****************************************************************************/ +#define BPCID_offCID 0 /* CID that will be compared with a process's CID */ +/* bit 9:31 reserved */ + +#define BPCID_mskCID ( 0x1FF << BPCID_offCID ) + +/****************************************************************************** + * dr40: EDM_CFG (EDM Configuration Register) + *****************************************************************************/ +#define EDM_CFG_offBC 0 /* Number of hardware breakpoint sets implemented */ +#define EDM_CFG_offDIMU 3 /* Debug Instruction Memory Unit exists */ +/* bit 4:15 reserved */ +#define EDM_CFG_offVER 16 /* EDM version */ + +#define EDM_CFG_mskBC ( 0x7 << EDM_CFG_offBC ) +#define EDM_CFG_mskDIMU ( 0x1 << EDM_CFG_offDIMU ) +#define EDM_CFG_mskVER ( 0xFFFF << EDM_CFG_offVER ) + +/****************************************************************************** + * dr41: EDMSW (EDM Status Word) + *****************************************************************************/ +#define EDMSW_offWV 0 /* Write Valid */ +#define EDMSW_offRV 1 /* Read Valid */ +#define EDMSW_offDE 2 /* Debug exception has occurred for this core */ +/* bit 3:31 reserved */ + +#define EDMSW_mskWV ( 0x1 << EDMSW_offWV ) +#define EDMSW_mskRV ( 0x1 << EDMSW_offRV ) +#define EDMSW_mskDE ( 0x1 << EDMSW_offDE ) + +/****************************************************************************** + * dr42: EDM_CTL (EDM Control Register) + *****************************************************************************/ +/* bit 0:30 reserved */ +#define EDM_CTL_offDEH_SEL 31 /* Controls where debug exception is directed to */ + +#define EDM_CTL_mskDEH_SEL ( 0x1 << EDM_CTL_offDEH_SEL ) + +/****************************************************************************** + * dr43: EDM_DTR (EDM Data Transfer Register) + *****************************************************************************/ + + /* This is used to exchange data between the embedded EDM logic + * and the processor core */ + +/****************************************************************************** + * dr44: BPMTC (Breakpoint Match Trigger Counter Register) + *****************************************************************************/ +#define BPMTC_offBPMTC 0 /* Breakpoint match trigger counter value */ +/* bit 16:31 reserved */ + +#define BPMTC_mskBPMTC ( 0xFFFF << BPMTC_offBPMTC ) + +/****************************************************************************** + * dr45: DIMBR (Debug Instruction Memory Base Register) + *****************************************************************************/ +/* bit 0:11 reserved */ +#define DIMBR_offDIMB 12 /* Base address of the Debug Instruction Memory (DIM)*/ +#define DIMBR_mskDIMB ( 0xFFFFF << DIMBR_offDIMB ) + +/****************************************************************************** + * dr46: TECR0(Trigger Event Control register 0) + * dr47: TECR1 (Trigger Event Control register 1) + *****************************************************************************/ +#define TECR_offBP 0 /* Controld which BP is used as a trigger source */ +#define TECR_offNMI 8 /* Use NMI as a trigger source */ +#define TECR_offHWINT 9 /* Corresponding interrupt is used as a trigger source */ +#define TECR_offEVIC 15 /* Enable HWINT as a trigger source in EVIC mode */ +#define TECR_offSYS 16 /* Enable SYSCALL instruction as a trigger source */ +#define TECR_offDBG 17 /* Enable debug exception as a trigger source */ +#define TECR_offMRE 18 /* Enable MMU related exception as a trigger source */ +#define TECR_offE 19 /* An exception is used as a trigger source */ +/* bit 20:30 reserved */ +#define TECR_offL 31 /* Link/Cascade TECR0 trigger event to TECR1 trigger event */ + +#define TECR_mskBP ( 0xFF << TECR_offBP ) +#define TECR_mskNMI ( 0x1 << TECR_offBNMI ) +#define TECR_mskHWINT ( 0x3F << TECR_offBHWINT ) +#define TECR_mskEVIC ( 0x1 << TECR_offBEVIC ) +#define TECR_mskSYS ( 0x1 << TECR_offBSYS ) +#define TECR_mskDBG ( 0x1 << TECR_offBDBG ) +#define TECR_mskMRE ( 0x1 << TECR_offBMRE ) +#define TECR_mskE ( 0x1 << TECR_offE ) +#define TECR_mskL ( 0x1 << TECR_offL ) + +/****************************************************************************** + * hspr0: HSP_CTL (HW Stack Protection Control Register) + *****************************************************************************/ +#define HSP_CTL_offHSP_EN 0 /* Enable bit for the stack protection and recording mechanism */ +#define HSP_CTL_offSCHM 1 /* Operating scheme of the stack protection and recording */ +#define HSP_CTL_offSU 2 /* Enable the SP protection and recording in the super-user mode */ +#define HSP_CTL_offU 3 /* Enable the SP protection and recording in the user mode */ +#define HSP_CTL_offSPL 4 /* (Secure Core Only) the enabled Security Privilege Level */ +/* bit 7:31 reserved */ + +#define HSP_CTL_mskHSP_EN ( 0x1 << HSP_CTL_offHSP_EN ) +#define HSP_CTL_mskSCHM ( 0x1 << HSP_CTL_offSCHM ) +#define HSP_CTL_mskSU ( 0x1 << HSP_CTL_offSU ) +#define HSP_CTL_mskU ( 0x1 << HSP_CTL_offU ) +#define HSP_CTL_mskSPL ( 0x7 << HSP_CTL_offSPL ) + +/****************************************************************************** + * hspr1: SP_BOUND (SP Bound Register) + * hspr2: SP_BOUND_PRIV (Shadowed Privileged SP Bound Register) + *****************************************************************************/ + + /* These registers contains the stack overflow bound */ + +/****************************************************************************** + * pfr0-2: PFMC0-2 (Performance Counter Register 0-2) + *****************************************************************************/ + + /* These registers contains performance event count */ + +/****************************************************************************** + * pfr3: PFM_CTL (Performance Counter Control Register) + *****************************************************************************/ +#define PFM_CTL_offEN0 0 /* Enable PFMC0 */ +#define PFM_CTL_offEN1 1 /* Enable PFMC1 */ +#define PFM_CTL_offEN2 2 /* Enable PFMC2 */ +#define PFM_CTL_offIE0 3 /* Enable interrupt for PFMC0 */ +#define PFM_CTL_offIE1 4 /* Enable interrupt for PFMC1 */ +#define PFM_CTL_offIE2 5 /* Enable interrupt for PFMC2 */ +#define PFM_CTL_offOVF0 6 /* Overflow bit of PFMC0 */ +#define PFM_CTL_offOVF1 7 /* Overflow bit of PFMC1 */ +#define PFM_CTL_offOVF2 8 /* Overflow bit of PFMC2 */ +#define PFM_CTL_offKS0 9 /* Enable superuser mode event counting for PFMC0 */ +#define PFM_CTL_offKS1 10 /* Enable superuser mode event counting for PFMC1 */ +#define PFM_CTL_offKS2 11 /* Enable superuser mode event counting for PFMC2 */ +#define PFM_CTL_offKU0 12 /* Enable user mode event counting for PFMC0 */ +#define PFM_CTL_offKU1 13 /* Enable user mode event counting for PFMC1 */ +#define PFM_CTL_offKU2 14 /* Enable user mode event counting for PFMC2 */ +#define PFM_CTL_offSEL0 15 /* The event selection for PFMC0 */ +#define PFM_CTL_offSEL1 16 /* The event selection for PFMC1 */ +#define PFM_CTL_offSEL2 22 /* The event selection for PFMC2 */ +/* bit 28:30 reserved */ +#define PFM_CTL_offMIN_CFG 31 /* Minimum Configuration */ + +#define PFM_CTL_mskEN0 ( 0x01 << PFM_CTL_offEN0 ) +#define PFM_CTL_mskEN1 ( 0x01 << PFM_CTL_offEN1 ) +#define PFM_CTL_mskEN2 ( 0x01 << PFM_CTL_offEN2 ) +#define PFM_CTL_mskIE0 ( 0x01 << PFM_CTL_offIE0 ) +#define PFM_CTL_mskIE1 ( 0x01 << PFM_CTL_offIE1 ) +#define PFM_CTL_mskIE2 ( 0x01 << PFM_CTL_offIE2 ) +#define PFM_CTL_mskOVF0 ( 0x01 << PFM_CTL_offOVF0 ) +#define PFM_CTL_mskOVF1 ( 0x01 << PFM_CTL_offOVF1 ) +#define PFM_CTL_mskOVF2 ( 0x01 << PFM_CTL_offOVF2 ) +#define PFM_CTL_mskKS0 ( 0x01 << PFM_CTL_offKS0 ) +#define PFM_CTL_mskKS1 ( 0x01 << PFM_CTL_offKS1 ) +#define PFM_CTL_mskKS2 ( 0x01 << PFM_CTL_offKS2 ) +#define PFM_CTL_mskKU0 ( 0x01 << PFM_CTL_offKU0 ) +#define PFM_CTL_mskKU1 ( 0x01 << PFM_CTL_offKU1 ) +#define PFM_CTL_mskKU2 ( 0x01 << PFM_CTL_offKU2 ) +#define PFM_CTL_mskSEL0 ( 0x01 << PFM_CTL_offSEL0 ) +#define PFM_CTL_mskSEL1 ( 0x3F << PFM_CTL_offSEL1 ) +#define PFM_CTL_mskSEL2 ( 0x3F << PFM_CTL_offSEL2 ) +#define PFM_CTL_mskMIN_CFG ( 0x01 << PFM_CTL_offMIN_CFG ) + +/****************************************************************************** + * pfr4: PFT_CTL (Performance Throttling Control Register) + *****************************************************************************/ +/* bit 0:3 reserved */ +#define PFT_CTL_offT_LEVEL 4 /* Throttling Level */ +#define PFT_CTL_offFAST_INT 8 /* Fast interrupt response */ +/* bit 9:31 reserved */ + +#define PFT_CTL_mskT_LEVEL ( 0x0F << PFT_CTL_offT_LEVEL ) +#define PFT_CTL_mskFAST_INT ( 0x01 << PFT_CTL_offFAST_INT ) + +/****************************************************************************** + * idr0: SDZ_CTL (Structure Downsizing Control Register) + *****************************************************************************/ +#define SDZ_CTL_offICDZ 0 /* I-cache downsizing control */ +#define SDZ_CTL_offDCDZ 3 /* D-cache downsizing control */ +#define SDZ_CTL_offMTBDZ 6 /* MTLB downsizing control */ +#define SDZ_CTL_offBTBDZ 9 /* Branch Target Table downsizing control */ +/* bit 12:31 reserved */ +#define SDZ_CTL_mskICDZ ( 0x07 << SDZ_CTL_offICDZ ) +#define SDZ_CTL_mskDCDZ ( 0x07 << SDZ_CTL_offDCDZ ) +#define SDZ_CTL_mskMTBDZ ( 0x07 << SDZ_CTL_offMTBDZ ) +#define SDZ_CTL_mskBTBDZ ( 0x07 << SDZ_CTL_offBTBDZ ) + +/****************************************************************************** + * idr1: MISC_CTL (Miscellaneous Control Register) + *****************************************************************************/ +#define MISC_CTL_offBTB 0 /* Disable Branch Target Buffer */ +#define MISC_CTL_offRTP 1 /* Disable Return Target Predictor */ +#define MISC_CTL_offPTEEPF 2 /* Disable HPTWK L2 PTE pefetch */ +#define MISC_CTL_offTCM 3 /* Disable Two Cycle Multiplication */ +#define MISC_CTL_offSP_SHADOW_EN 4 /* Enable control for shadow stack pointers */ +#define MISC_CTL_offLP_CACHE 5 /* Disable the Loop Cache */ +/* bit 6:6 reserved */ +#define MISC_CTL_offILMC_EN 7 /* Enable Instruction Local Memory Cache */ +#define MISC_CTL_offACE 8 /* Disable Andes Custom Extension */ +/* bit 9:31 reserved */ + +#define MISC_CTL_makBTB ( 0x1 << MISC_CTL_makBTB ) +#define MISC_CTL_makRTP ( 0x1 << MISC_CTL_makRTP ) +#define MISC_CTL_makPTEEPF ( 0x1 << MISC_CTL_makPTEEPF ) +#define MISC_CTL_mskTCM ( 0x1 << MISC_CTL_offTCM ) +#define MISC_CTL_mskSP_SHADOW_EN ( 0x1 << MISC_CTL_offSP_SHADOW_EN ) +#define MISC_CTL_mskLP_CACHE ( 0x1 << MISC_CTL_offLP_CACHE ) +#define MISC_CTL_mskILMC_EN ( 0x1 << MISC_CTL_offILMC_EN ) +#define MISC_CTL_mskACE ( 0x1 << MISC_CTL_offACE ) + +/****************************************************************************** + * racr0: PRUSR_ACC_CTL (Privileged Resource User Access Control Registers) + *****************************************************************************/ +#define PRUSR_ACC_CTL_offDMA_EN 0 /* Allow user mode access of DMA registers */ +#define PRUSR_ACC_CTL_offPFM_EN 1 /* Allow user mode access of PFM registers */ + +#define PRUSR_ACC_CTL_mskDMA_EN ( 0x1 << PRUSR_ACC_CTL_offDMA_EN ) +#define PRUSR_ACC_CTL_mskPFM_EN ( 0x1 << PRUSR_ACC_CTL_offPFM_EN ) + +/****************************************************************************** + * dmar0: DMA_CFG (DMA Configuration Register) + *****************************************************************************/ +#define DMA_CFG_offNCHN 0 /* The number of DMA channels implemented */ +#define DMA_CFG_offUNEA 2 /* Un-aligned External Address transfer feature */ +#define DMA_CFG_off2DET 3 /* 2-D Element Transfer feature */ +/* bit 4:15 reserved */ +#define DMA_CFG_offVER 16 /* DMA architecture and implementation version */ + +#define DMA_CFG_mskNCHN ( 0x3 << DMA_CFG_offNCHN ) +#define DMA_CFG_mskUNEA ( 0x1 << DMA_CFG_offUNEA ) +#define DMA_CFG_msk2DET ( 0x1 << DMA_CFG_off2DET ) +#define DMA_CFG_mskVER ( 0xFFFF << DMA_CFG_offVER ) + +/****************************************************************************** + * dmar1: DMA_GCSW (DMA Global Control and Status Word Register) + *****************************************************************************/ +#define DMA_GCSW_offC0STAT 0 /* DMA channel 0 state */ +#define DMA_GCSW_offC1STAT 3 /* DMA channel 1 state */ +/* bit 6:11 reserved */ +#define DMA_GCSW_offC0INT 12 /* DMA channel 0 generate interrupt */ +#define DMA_GCSW_offC1INT 13 /* DMA channel 1 generate interrupt */ +#define DMA_GCSW_offHCHAN 16 /* Head channel number */ +#define DMA_GCSW_offFSM 18 /* Fast-start mode field */ +#define DMA_GCSW_offSCMD 20 /* DMA Sub-Action Command used in the fast-start mode */ +/* bit 22:27 reserved */ +#define DMA_GCSW_offSDBE 28 /* Shadow DBM and DBB bits Enable control */ +#define DMA_GCSW_offDBM 29 /* Double-Buffer Mode enable control for the data local memory */ +#define DMA_GCSW_offDBB 30 /* Double-Buffer Bank */ +#define DMA_GCSW_offEN 31 /* Enable DMA engine */ + +#define DMA_GCSW_mskC0STAT ( 0x7 << DMA_GCSW_offC0STAT ) +#define DMA_GCSW_mskC1STAT ( 0x7 << DMA_GCSW_offC1STAT ) +#define DMA_GCSW_mskC0INT ( 0x1 << DMA_GCSW_offC0INT ) +#define DMA_GCSW_mskC1INT ( 0x1 << DMA_GCSW_offC1INT ) +#define DMA_GCSW_mskHCHAN ( 0x3 << DMA_GCSW_offHCHAN ) +#define DMA_GCSW_mskFSM ( 0x3 << DMA_GCSW_offFSM ) +#define DMA_GCSW_mskSCMD ( 0x3 << DMA_GCSW_offSCMD ) +#define DMA_GCSW_mskSDBE ( 0x1 << DMA_GCSW_offSDBE ) +#define DMA_GCSW_mskDBM ( 0x1 << DMA_GCSW_offDBM ) +#define DMA_GCSW_mskDBB ( 0x1 << DMA_GCSW_offDBB ) +#define DMA_GCSW_mskEN ( 0x1 << DMA_GCSW_offEN ) + +/****************************************************************************** + * dmar2: DMA_CHNSEL (DMA Channel Selection Register) + *****************************************************************************/ +#define DMA_CHNSEL_offCHAN 0 /* Selected channel number */ +/* bit 2:31 reserved */ + +#define DMA_CHNSEL_mskCHAN ( 0x3 << DMA_CHNSEL_offCHAN ) + +/****************************************************************************** + * dmar3: DMA_ACT (DMA Action Register) + *****************************************************************************/ +#define DMA_ACT_offACMD 0 /* DMA Action Command */ +#define DMA_ACT_offSCMD 2 /* DMA Sub-action Command */ +/* bit 4:31 reserved */ +#define DMA_ACT_mskACMD ( 0x3 << DMA_ACT_offACMD ) +#define DMA_ACT_mskSCMD ( 0x3 << DMA_ACT_offSCMD ) + +/****************************************************************************** + * dmar4: DMA_SETUP (DMA Setup Register) + *****************************************************************************/ +#define DMA_SETUP_offLM 0 /* Local Memory Selection */ +#define DMA_SETUP_offTDIR 1 /* Transfer Direction */ +#define DMA_SETUP_offTES 2 /* Transfer Element Size */ +#define DMA_SETUP_offESTR 4 /* External memory transfer Stride */ +#define DMA_SETUP_offCIE 16 /* Interrupt Enable on Completion */ +#define DMA_SETUP_offSIE 17 /* Interrupt Enable on explicit Stop */ +#define DMA_SETUP_offEIE 18 /* Interrupt Enable on Error */ +#define DMA_SETUP_offUE 19 /* Enable the Un-aligned External Address */ +#define DMA_SETUP_off2DE 20 /* Enable the 2-D External Transfer */ +#define DMA_SETUP_offCOA 21 /* Transfer Coalescable */ +/* bit 24:31 reserved */ + +#define DMA_SETUP_mskLM ( 0x1 << DMA_SETUP_offLM ) +#define DMA_SETUP_mskTDIR ( 0x1 << DMA_SETUP_offTDIR ) +#define DMA_SETUP_mskTES ( 0x3 << DMA_SETUP_offTES ) +#define DMA_SETUP_mskESTR ( 0xFFF << DMA_SETUP_offESTR ) +#define DMA_SETUP_mskCIE ( 0x1 << DMA_SETUP_offCIE ) +#define DMA_SETUP_mskSIE ( 0x1 << DMA_SETUP_offSIE ) +#define DMA_SETUP_mskEIE ( 0x1 << DMA_SETUP_offEIE ) +#define DMA_SETUP_mskUE ( 0x1 << DMA_SETUP_offUE ) +#define DMA_SETUP_msk2DE ( 0x1 << DMA_SETUP_off2DE ) +#define DMA_SETUP_mskCOA ( 0x7 << DMA_SETUP_offCOA ) + +/****************************************************************************** + * dmar5: DMA_ISADDR (DMA Internal Start Address Register) + *****************************************************************************/ +#define DMA_ISADDR_offISADDR 0 /* Internal Start Address */ +/* bit 20:31 reserved */ +#define DMA_ISADDR_mskISADDR ( 0xFFFFF << DMA_ISADDR_offISADDR ) + +/****************************************************************************** + * dmar6: DMA_ESADDR (DMA External Start Address Register) + *****************************************************************************/ + /* This register holds External Start Address */ + +/****************************************************************************** + * dmar7: DMA_TCNT (DMA Transfer Element Count Register) + *****************************************************************************/ +#define DMA_TCNT_offTCNT 0 /* DMA transfer element count */ +/* bit 18:31 reserved */ +#define DMA_TCNT_mskTCNT ( 0x7FFFFF << DMA_TCNT_offTCNT ) + +/****************************************************************************** + * dmar8: DMA_STATUS (DMA Status Register) + *****************************************************************************/ +#define DMA_STATUS_offSTAT 0 /* DMA channel state */ +#define DMA_STATUS_offSTUNA 3 /* Un-aligned error on External Stride value */ +#define DMA_STATUS_offDERR 4 /* DMA Transfer Disruption Error */ +#define DMA_STATUS_offEUNA 5 /* Un-aligned error on the External address */ +#define DMA_STATUS_offIUNA 6 /* Un-aligned error on the Internal address */ +#define DMA_STATUS_offIOOR 7 /* Out-Of-Range error on the Internal address */ +#define DMA_STATUS_offEBUS 8 /* Bus Error on an External DMA transfer */ +#define DMA_STATUS_offESUP 9 /* DMA setup error */ +/* bit 10:30 reserved */ +#define DMA_STATUS_offWE 31 /* Wait event */ + +#define DMA_STATUS_mskSTAT ( 0x7 << DMA_STATUS_offSTAT ) +#define DMA_STATUS_mskSTUNA ( 0x1 << DMDMA_STATUS_offSTUNA ) +#define DMA_STATUS_mskDERR ( 0x1 << DMDMA_STATUS_offDERR ) +#define DMA_STATUS_mskEUNA ( 0x1 << DMDMA_STATUS_offEUNA ) +#define DMA_STATUS_mskIUNA ( 0x1 << DMDMA_STATUS_offIUNA ) +#define DMA_STATUS_mskIOOR ( 0x1 << DMDMA_STATUS_offIOOR ) +#define DMA_STATUS_mskEBUS ( 0x1 << DMDMA_STATUS_offEBUS ) +#define DMA_STATUS_mskESUP ( 0x1 << DMDMA_STATUS_offESUP ) +#define DMA_STATUS_mskWE ( 0x1 << DMA_STATUS_offWE ) + +/****************************************************************************** + * dmar9: DMA_2DSET (DMA 2D Setup Register) + *****************************************************************************/ +#define DMA_2DSET_offWECNT 0 /* The Width Element Count for a 2-D region */ +#define DMA_2DSET_offHTSTR 16 /* The Height Stride for a 2-D region */ + +#define DMA_2DSET_mskHTSTR ( 0xFFFF << DMA_2DSET_offHTSTR ) +#define DMA_2DSET_mskWECNT ( 0xFFFF << DMA_2DSET_offWECNT ) + +/****************************************************************************** + * dmar10: DMA_2DSCTL (DMA 2D Startup Control Register) + *****************************************************************************/ +#define DMA_2DSCTL_offSTWECNT 0 /* Startup Width Element Count for a 2-D region */ +/* bit 16:31 reserved */ + +#define DMA_2DSCTL_mskSTWECNT ( 0xFFFF << DMA_2DSCTL_offSTWECNT ) + +/****************************************************************************** + * fpcsr: FPCSR (Floating-Point Control Status Register) + *****************************************************************************/ +#define FPCSR_offRM 0 +#define FPCSR_offIVO 2 +#define FPCSR_offDBZ 3 +#define FPCSR_offOVF 4 +#define FPCSR_offUDF 5 +#define FPCSR_offIEX 6 +#define FPCSR_offIVOE 7 +#define FPCSR_offDBZE 8 +#define FPCSR_offOVFE 9 +#define FPCSR_offUDFE 10 +#define FPCSR_offIEXE 11 +#define FPCSR_offDNZ 12 +#define FPCSR_offIVOT 13 +#define FPCSR_offDBZT 14 +#define FPCSR_offOVFT 15 +#define FPCSR_offUDFT 16 +#define FPCSR_offIEXT 17 +#define FPCSR_offDNIT 18 +#define FPCSR_offRIT 19 + +#define FPCSR_mskRM ( 0x3 << FPCSR_offRM ) +#define FPCSR_mskIVO ( 0x1 << FPCSR_offIVO ) +#define FPCSR_mskDBZ ( 0x1 << FPCSR_offDBZ ) +#define FPCSR_mskOVF ( 0x1 << FPCSR_offOVF ) +#define FPCSR_mskUDF ( 0x1 << FPCSR_offUDF ) +#define FPCSR_mskIEX ( 0x1 << FPCSR_offIEX ) +#define FPCSR_mskIVOE ( 0x1 << FPCSR_offIVOE ) +#define FPCSR_mskDBZE ( 0x1 << FPCSR_offDBZE ) +#define FPCSR_mskOVFE ( 0x1 << FPCSR_offOVFE ) +#define FPCSR_mskUDFE ( 0x1 << FPCSR_offUDFE ) +#define FPCSR_mskIEXE ( 0x1 << FPCSR_offIEXE ) +#define FPCSR_mskDNZ ( 0x1 << FPCSR_offDNZ ) +#define FPCSR_mskIVOT ( 0x1 << FPCSR_offIVOT ) +#define FPCSR_mskDBZT ( 0x1 << FPCSR_offDBZT ) +#define FPCSR_mskOVFT ( 0x1 << FPCSR_offOVFT ) +#define FPCSR_mskUDFT ( 0x1 << FPCSR_offUDFT ) +#define FPCSR_mskIEXT ( 0x1 << FPCSR_offIEXT ) +#define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT ) +#define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT ) + +/****************************************************************************** + * fpcfg: FPCFG (Floating-Point Configuration Register) + *****************************************************************************/ +#define FPCFG_offSP 0 +#define FPCFG_offDP 1 +#define FPCFG_offFREG 2 +#define FPCFG_offFMA 4 +/* bit 5:21 reserved */ +#define FPCFG_offIMVER 22 +#define FPCFG_offAVER 27 + +#define FPCFG_mskSP ( 0x1 << FPCFG_offSP ) +#define FPCFG_mskDP ( 0x1 << FPCFG_offDP ) +#define FPCFG_mskFREG ( 0x3 << FPCFG_offFREG ) +#define FPCFG_mskFMA ( 0x1 << FPCFG_offFMA ) +#define FPCFG_mskIMVER ( 0x1F << FPCFG_offIMVER ) +#define FPCFG_mskAVER ( 0x1F << FPCFG_offAVER ) + +/****************************************************************************** + * fucpr: FUCOP_CTL (FPU and Coprocessor Enable Control Register) + *****************************************************************************/ +#define FUCOP_CTL_offFPUEN 0 +#define FUCOP_CTL_offCP1EN 1 +#define FUCOP_CTL_offCP2EN 2 +#define FUCOP_CTL_offCP3EN 3 +/* bit 4:30 reserved */ +#define FUCOP_CTL_offAUEN 31 + +#define FUCOP_CTL_mskFPUEN ( 0x1 << FUCOP_CTL_offFPUEN ) +#define FUCOP_CTL_mskCP1EN ( 0x1 << FUCOP_CTL_offCP1EN ) +#define FUCOP_CTL_mskCP2EN ( 0x1 << FUCOP_CTL_offCP2EN ) +#define FUCOP_CTL_mskCP3EN ( 0x1 << FUCOP_CTL_offCP3EN ) +#define FUCOP_CTL_mskAUEN ( 0x1 << FUCOP_CTL_offAUEN ) + +#ifdef CONFIG_CACHE_L2 +/****************************************************************************** + * L2_CA_CONF (Cache architecture configuration) + *****************************************************************************/ +#define L2_CA_CONF_offL2CLSZ 8 +#define L2_CA_CONF_mskL2CLSZ (0x7 << L2_CA_CONF_offL2CLSZ) +//TODO finish this table + +/****************************************************************************** + * L2CC_SETUP (L2CC Setup register) + *****************************************************************************/ +#define L2CC_SETUP_offPART 0 +#define L2CC_SETUP_mskPART (0x3 << L2_CA_CONF_offPART) +#define L2CC_SETUP_offDDLATC 4 +#define L2CC_SETUP_mskDDLATC (0x3 << L2_CA_CONF_offDDLATC) +#define L2CC_SETUP_offTDLATC 8 +#define L2CC_SETUP_mskTDLATC (0x3 << L2_CA_CONF_offTDLATC) + +/****************************************************************************** + * L2CC_PROT (L2CC Protect register) + *****************************************************************************/ +#define L2CC_PROT_offMRWEN 31 +#define L2CC_PROT_mskMRWEN (0x1 << L2CC_PROT_offMRWEN) +//TODO finish this table +// +/****************************************************************************** + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n) + *****************************************************************************/ +#define L2CC_CTRL_offEN 31 +#define L2CC_CTRL_mskEN (0x1 << L2CC_CTRL_offEN) + +/****************************************************************************** + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n) + *****************************************************************************/ +#define L2_CCTL_STATUS_offCMD_COMP 31 +#define L2_CCTL_STATUS_mskCMD_COMP (0x1 << L2_CCTL_STATUS_offCMD_COMP) +//TODO finish this table + +#endif + +#endif /* __NDS32_DEFS_H__ */ diff --git a/bsp/AE210P/os_cpu_common.h b/bsp/AE210P/os_cpu_common.h new file mode 100644 index 0000000000000000000000000000000000000000..b010e0d64dea46694040e5fb0251f898df06e264 --- /dev/null +++ b/bsp/AE210P/os_cpu_common.h @@ -0,0 +1,426 @@ +#include "nds32.h" + + .set regno, 0 +#ifdef __TARGET_IFC_EXT + .set regno, regno+1 +#endif +#ifdef __TARGET_ZOL_EXT + .set regno, regno+3 +#endif + + /* Descend PSW.INTL and enable PSW.AEN */ + .macro IntlDescend + mfsr $r1, $PSW +#ifdef __TARGET_ZOL_EXT + /* Also enable ZOL (PSW.AEN) */ + xori $r1, $r1, #((1 << 13) | (1 << 1)) +#else + addi $r1, $r1, #-2 +#endif + mtsr $r1, $PSW + .endm + + /* FPU registers */ + .macro SAVE_FPU_REGS_00 + fsdi.bi $fd3, [$sp], -8 + fsdi.bi $fd2, [$sp], -8 + fsdi.bi $fd1, [$sp], -8 + fsdi $fd0, [$sp+0] + .endm + + .macro SAVE_FPU_REGS_01 + fsdi.bi $fd7, [$sp], -8 + fsdi.bi $fd6, [$sp], -8 + fsdi.bi $fd5, [$sp], -8 + fsdi.bi $fd4, [$sp], -8 + SAVE_FPU_REGS_00 + .endm + + .macro SAVE_FPU_REGS_02 + fsdi.bi $fd15, [$sp], -8 + fsdi.bi $fd14, [$sp], -8 + fsdi.bi $fd13, [$sp], -8 + fsdi.bi $fd12, [$sp], -8 + fsdi.bi $fd11, [$sp], -8 + fsdi.bi $fd10, [$sp], -8 + fsdi.bi $fd9, [$sp], -8 + fsdi.bi $fd8, [$sp], -8 + SAVE_FPU_REGS_01 + .endm + + .macro SAVE_FPU_REGS_03 + fsdi.bi $fd31, [$sp], -8 + fsdi.bi $fd30, [$sp], -8 + fsdi.bi $fd29, [$sp], -8 + fsdi.bi $fd28, [$sp], -8 + fsdi.bi $fd27, [$sp], -8 + fsdi.bi $fd26, [$sp], -8 + fsdi.bi $fd25, [$sp], -8 + fsdi.bi $fd24, [$sp], -8 + fsdi.bi $fd23, [$sp], -8 + fsdi.bi $fd22, [$sp], -8 + fsdi.bi $fd21, [$sp], -8 + fsdi.bi $fd20, [$sp], -8 + fsdi.bi $fd19, [$sp], -8 + fsdi.bi $fd18, [$sp], -8 + fsdi.bi $fd17, [$sp], -8 + fsdi.bi $fd16, [$sp], -8 + SAVE_FPU_REGS_02 + .endm + + .macro push_fpu +#if defined(__NDS32_EXT_FPU_CONFIG_0__) + addi $sp, $sp, -8 + SAVE_FPU_REGS_00 +#elif defined(__NDS32_EXT_FPU_CONFIG_1__) + addi $sp, $sp, -8 + SAVE_FPU_REGS_01 +#elif defined(__NDS32_EXT_FPU_CONFIG_2__) + addi $sp, $sp, -8 + SAVE_FPU_REGS_02 +#elif defined(__NDS32_EXT_FPU_CONFIG_3__) + addi $sp, $sp, -8 + SAVE_FPU_REGS_03 +#else +#endif + .endm + + .macro RESTORE_FPU_REGS_00 + fldi.bi $fd0, [$sp], 8 + fldi.bi $fd1, [$sp], 8 + fldi.bi $fd2, [$sp], 8 + fldi.bi $fd3, [$sp], 8 + .endm + + .macro RESTORE_FPU_REGS_01 + RESTORE_FPU_REGS_00 + fldi.bi $fd4, [$sp], 8 + fldi.bi $fd5, [$sp], 8 + fldi.bi $fd6, [$sp], 8 + fldi.bi $fd7, [$sp], 8 + .endm + + .macro RESTORE_FPU_REGS_02 + RESTORE_FPU_REGS_01 + fldi.bi $fd8, [$sp], 8 + fldi.bi $fd9, [$sp], 8 + fldi.bi $fd10, [$sp], 8 + fldi.bi $fd11, [$sp], 8 + fldi.bi $fd12, [$sp], 8 + fldi.bi $fd13, [$sp], 8 + fldi.bi $fd14, [$sp], 8 + fldi.bi $fd15, [$sp], 8 + .endm + + .macro RESTORE_FPU_REGS_03 + RESTORE_FPU_REGS_02 + fldi.bi $fd16, [$sp], 8 + fldi.bi $fd17, [$sp], 8 + fldi.bi $fd18, [$sp], 8 + fldi.bi $fd19, [$sp], 8 + fldi.bi $fd20, [$sp], 8 + fldi.bi $fd21, [$sp], 8 + fldi.bi $fd22, [$sp], 8 + fldi.bi $fd23, [$sp], 8 + fldi.bi $fd24, [$sp], 8 + fldi.bi $fd25, [$sp], 8 + fldi.bi $fd26, [$sp], 8 + fldi.bi $fd27, [$sp], 8 + fldi.bi $fd28, [$sp], 8 + fldi.bi $fd29, [$sp], 8 + fldi.bi $fd30, [$sp], 8 + fldi.bi $fd31, [$sp], 8 + .endm + + .macro pop_fpu +#if defined(__NDS32_EXT_FPU_CONFIG_0__) + RESTORE_FPU_REGS_00 +#elif defined(__NDS32_EXT_FPU_CONFIG_1__) + RESTORE_FPU_REGS_01 +#elif defined(__NDS32_EXT_FPU_CONFIG_2__) + RESTORE_FPU_REGS_02 +#elif defined(__NDS32_EXT_FPU_CONFIG_3__) + RESTORE_FPU_REGS_03 +#else +#endif + .endm + + /* FPU Caller registers */ + .macro SAVE_FPU_CALLER_REGS_00 + addi $sp, $sp, -8 + fsdi.bi $fd2, [$sp], -8 + fsdi.bi $fd1, [$sp], -8 + fsdi $fd0, [$sp+0] + .endm + + .macro SAVE_FPU_CALLER_REGS_01 + SAVE_FPU_CALLER_REGS_00 + .endm + + .macro SAVE_FPU_CALLER_REGS_02 + addi $sp, $sp, -8 + fsdi.bi $fd15, [$sp], -8 + fsdi.bi $fd14, [$sp], -8 + fsdi.bi $fd13, [$sp], -8 + fsdi.bi $fd12, [$sp], -8 + fsdi.bi $fd11, [$sp], -8 + fsdi.bi $fd2, [$sp], -8 + fsdi.bi $fd1, [$sp], -8 + fsdi $fd0, [$sp+0] + .endm + + .macro SAVE_FPU_CALLER_REGS_03 + addi $sp, $sp, -8 + fsdi.bi $fd23, [$sp], -8 + fsdi.bi $fd22, [$sp], -8 + fsdi.bi $fd21, [$sp], -8 + fsdi.bi $fd20, [$sp], -8 + fsdi.bi $fd19, [$sp], -8 + fsdi.bi $fd18, [$sp], -8 + fsdi.bi $fd17, [$sp], -8 + fsdi.bi $fd16, [$sp], -8 + fsdi.bi $fd15, [$sp], -8 + fsdi.bi $fd14, [$sp], -8 + fsdi.bi $fd13, [$sp], -8 + fsdi.bi $fd12, [$sp], -8 + fsdi.bi $fd11, [$sp], -8 + fsdi.bi $fd2, [$sp], -8 + fsdi.bi $fd1, [$sp], -8 + fsdi $fd0, [$sp+0] + .endm + + .macro push_fpu_caller +#if defined(__NDS32_EXT_FPU_CONFIG_0__) + SAVE_FPU_CALLER_REGS_00 +#elif defined(__NDS32_EXT_FPU_CONFIG_1__) + SAVE_FPU_CALLER_REGS_01 +#elif defined(__NDS32_EXT_FPU_CONFIG_2__) + SAVE_FPU_CALLER_REGS_02 +#elif defined(__NDS32_EXT_FPU_CONFIG_3__) + SAVE_FPU_CALLER_REGS_03 +#else +#endif + .endm + + .macro RESTORE_FPU_CALLER_REGS_00 + fldi.bi $fd0, [$sp], 8 + fldi.bi $fd1, [$sp], 8 + fldi.bi $fd2, [$sp], 8 + .endm + + .macro RESTORE_FPU_CALLER_REGS_01 + RESTORE_FPU_CALLER_REGS_00 + .endm + + .macro RESTORE_FPU_CALLER_REGS_02 + fldi.bi $fd0, [$sp], 8 + fldi.bi $fd1, [$sp], 8 + fldi.bi $fd2, [$sp], 8 + fldi.bi $fd11, [$sp], 8 + fldi.bi $fd12, [$sp], 8 + fldi.bi $fd13, [$sp], 8 + fldi.bi $fd14, [$sp], 8 + fldi.bi $fd15, [$sp], 8 + .endm + + .macro RESTORE_FPU_CALLER_REGS_03 + fldi.bi $fd0, [$sp], 8 + fldi.bi $fd1, [$sp], 8 + fldi.bi $fd2, [$sp], 8 + fldi.bi $fd11, [$sp], 8 + fldi.bi $fd12, [$sp], 8 + fldi.bi $fd13, [$sp], 8 + fldi.bi $fd14, [$sp], 8 + fldi.bi $fd15, [$sp], 8 + fldi.bi $fd16, [$sp], 8 + fldi.bi $fd17, [$sp], 8 + fldi.bi $fd18, [$sp], 8 + fldi.bi $fd19, [$sp], 8 + fldi.bi $fd20, [$sp], 8 + fldi.bi $fd21, [$sp], 8 + fldi.bi $fd22, [$sp], 8 + fldi.bi $fd23, [$sp], 8 + .endm + + .macro pop_fpu_caller +#if defined(__NDS32_EXT_FPU_CONFIG_0__) + RESTORE_FPU_CALLER_REGS_00 +#elif defined(__NDS32_EXT_FPU_CONFIG_1__) + RESTORE_FPU_CALLER_REGS_01 +#elif defined(__NDS32_EXT_FPU_CONFIG_2__) + RESTORE_FPU_CALLER_REGS_02 +#elif defined(__NDS32_EXT_FPU_CONFIG_3__) + RESTORE_FPU_CALLER_REGS_03 +#else +#endif + .endm + + /* IFC system register */ + .macro MFUSR_IFC R0="$r1" + mfusr \R0, $IFC_LP + .endm + + .macro MTUSR_IFC R0="$r1" + mtusr \R0, $IFC_LP + .endm + + /* ZOL system registers */ + .macro MFUSR_ZOL R0="$r1", R1="$r2", R2="$r3" + mfusr \R0, $LB + mfusr \R1, $LE + mfusr \R2, $LC + .endm + + .macro MTUSR_ZOL R0="$r1", R1="$r2", R2="$r3" + mtusr \R0, $LB + mtusr \R1, $LE + mtusr \R2, $LC + .endm + + /* Context-switch save and restore routines */ + .macro SAVE_ALL + pushm $r6, $r30 + + mfsr $r1, $IPC + mfsr $r2, $IPSW + + .if (regno == 4) + MFUSR_ZOL "$r3","$r4","$r5" + MFUSR_IFC "$r6" + pushm $r0, $r6 /* $0 is dummy */ + .else + .if (regno == 3) + MFUSR_ZOL "$r3","$r4","$r5" + pushm $r1, $r5 + .else + .if (regno == 1) + MFUSR_IFC "$r3" + pushm $r1, $r3 + .else + pushm $r1, $r2 + .endif + .endif + .endif + + push_fpu + .endm + + .macro RESTORE_ALL + pop_fpu + setgie.d + dsb + + .if (regno == 4) + popm $r0, $r6 /* $0 is dummy */ + MTUSR_ZOL "$r3","$r4","$r5" + MTUSR_IFC "$r6" + .else + .if (regno == 3) + popm $r1, $r5 + MTUSR_ZOL "$r3","$r4","$r5" + .else + .if (regno == 1) + popm $r1, $r3 + MTUSR_IFC "$r3" + .else + popm $r1, $r2 + .endif + .endif + .endif + + mtsr $r1, $IPC + mtsr $r2, $IPSW + + popm $r6, $r30 + popm $r0, $r5 + .endm + + /* Nested IRQ save and restore routines*/ + .macro SAVE_CALLER + pushm $r15,$r30 /* full: 16 gpr, reduce: 4 gpr */ + + .if (regno == 4) + MFUSR_ZOL "$r1","$r2","$r3" + MFUSR_IFC "$r4" + pushm $r1, $r4 + + mfsr $r1, $IPC + mfsr $r2, $IPSW + pushm $r1, $r2 + .else + mfsr $r1, $IPC + mfsr $r2, $IPSW + .if (regno == 3) + MFUSR_ZOL "$r3","$r4","$r5" + pushm $r0, $r5 /* $0 is dummy */ + .else + .if (regno == 1) + MFUSR_IFC "$r3" + pushm $r0, $r3 /* $r0 is dummy */ + .else + pushm $r1, $r2 + .endif + .endif + .endif + + push_fpu_caller + .endm + + .macro RESTORE_CALLER + pop_fpu_caller + setgie.d + dsb + + .if (regno == 4) + popm $r1, $r2 + mtsr $r1, $IPC + mtsr $r2, $IPSW + + popm $r1, $r4 + MTUSR_ZOL "$r1","$r2","$r3" + MTUSR_IFC "$r4" + .else + .if (regno == 3) + popm $r0, $r5 /* $0 is dummy */ + MTUSR_ZOL "$r3","$r4","$r5" + .else + .if (regno == 1) + popm $r0, $r3 /* $0 is dummy */ + MTUSR_IFC "$r3" + .else + popm $r1, $r2 + .endif + .endif + mtsr $r1, $IPC + mtsr $r2, $IPSW + .endif + + popm $r15,$r30 /* full: 16 gpr, reduce: 4 gpr*/ + popm $r0, $r5 + .endm + + /* Non-Nested IRQ save and restore routines */ + .macro SAVE_CALLER_UNNESTED + pushm $r15,$r30 /* full: 16 gpr, reduce: 4 gpr */ + + .if (regno == 1) + MFUSR_IFC "$r1" + pushm $r0, $r1 /* $r0 is dummy */ + .endif + + push_fpu_caller + .endm + + .macro RESTORE_CALLER_UNNESTED + pop_fpu_caller + + .if (regno == 1) + setgie.d + dsb + popm $r0, $r1 /* $0 is dummy */ + MTUSR_IFC "$r1" + .endif + + popm $r15,$r30 /* full: 16 gpr, reduce: 4 gpr*/ + popm $r0, $r5 + .endm diff --git a/bsp/AE210P/os_except.c b/bsp/AE210P/os_except.c new file mode 100644 index 0000000000000000000000000000000000000000..8d0b829e68384dcbfac29d11a96f23d9411a3792 --- /dev/null +++ b/bsp/AE210P/os_except.c @@ -0,0 +1,54 @@ +#include "hal.h" +#include "uart/uart.h" +#include "osc/osc.h" +#include "os_except.h" + +/* + ********************************************************************************************************* + * Register Exception Handlers + * + * Description : This function is called to register general exception handler. + * The total number of general exception is 16. + * + * Arguments : ipc + * + * Notes : + ********************************************************************************************************* + */ +inline void register_exception_handler(int genneral_except_num, void (*handler)(unsigned int ipc)) +{ + if (genneral_except_num >= 16) + { + puts("Non-exist general exception number.\n"); + while (1); + } + + General_Exception_Handler_Table[genneral_except_num] = handler; +} + +/* + ********************************************************************************************************* + * Exception Dispatcher + * + * Description : This function is called from exception handler to dispatch different + * exception handler according to register itype. + * + * Arguments : ipc + * + * Notes : + ********************************************************************************************************* + */ +void OS_CPU_EXCEPTION_Dispatcher(unsigned int ipc) +{ + /* Interrupt is still disabled at this point */ + /* get all needed system registers' values before re-enable interrupt */ + unsigned int itype = __nds32__mfsr (NDS32_SR_ITYPE); + unsigned int exception_num; + void (*pHandler)(unsigned int ipc); + + exception_num = itype & 0xf; + + pHandler = General_Exception_Handler_Table[exception_num]; + + pHandler(ipc); +} diff --git a/bsp/AE210P/os_except.h b/bsp/AE210P/os_except.h new file mode 100644 index 0000000000000000000000000000000000000000..254a6dce51f69c801673810aba455f14bff9fc58 --- /dev/null +++ b/bsp/AE210P/os_except.h @@ -0,0 +1,23 @@ +#ifndef __OS_EXCEPT_H__ +#define __OS_EXCEPT_H__ + +/*********************************** + TYPES OF GENERAL EXCEPTION + ***********************************/ +#define GE_ALIGN_CHECK 0 +#define GE_RESERVED_INST 1 +#define GE_TRAP 2 +#define GE_ARITHMETIC 3 +#define GE_PRECISE_BUS_ERR 4 +#define GE_INPRECISE_BUS_ERR 5 +#define GE_COPROCESSOR 6 +#define GE_PRIVILEGE_INST 7 +#define GE_RESERVED_VALUE 8 +#define GE_NON_EXIST_LOCAL_MEM 9 +#define GE_MPZIU_CTRL 10 + +void *General_Exception_Handler_Table[16]; + +inline void register_exception_handler(int genneral_except_num, void (*handler)(unsigned int ipc)); + +#endif diff --git a/bsp/AE210P/readme/readme.txt b/bsp/AE210P/readme/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..b442d974cb0f93bda9e6d5783a0694d859cd275c --- /dev/null +++ b/bsp/AE210P/readme/readme.txt @@ -0,0 +1,49 @@ +E-Mail : Archer Zhang + +****************************** +文件(夹)添加和修改 +****************************** +[1] 在bsp目录下,添加AE210P目录,这是Andes AE210P EVB(N1068A)的主目录; +[2] 在libcpu目录下,添加nds32目录,这是Andes N10系列Core的体系目录; +[3] 由于编译器的原因,修改了finsh.h文件的Line:74~75,如下 + #if !(defined(__GNUC__) && defined(__x86_64__)) + //typedef unsigned int size_t; // 注释这个typedef + #include // 添加两个头文件包含 + #include + #else +[4] 由于串口未使用中断接收,而是使用了查询接收,所以修改了shell.c文件,如下 + a. Line:316~317 + //rt_device_set_rx_indicate(shell->device, finsh_rx_ind); + //rt_device_open(shell->device, (RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_RX)); + rt_device_open(shell->device, (RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM)); + + b. Line:326,注释该行 + // if (rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER) != RT_EOK) continue; + + c. Line:553,添加CPU占用的释放 + + rt_thread_delay(1); // 或者rt-schedule(); + +****************************** +工程管理 +****************************** +[1] 该工程使用Makefile管理,Makefile即文件AE210P/Makefile; + 编译如下: + make APP=rtthread AE210P=1 USING_CLI=1 DEBUG=1 all + make APP=rtthread AE210P=1 USING_CLI=1 DEBUG=1 clean + +****************************** +Tool Chain/IDE +****************************** +[1] IDE:AndeSight_V300_STD + +这是一个基于Eclipse和GNU、GDB的环境,参阅对应工具/环境的标准文档即可。 + +关于创建工程和调试,请参阅《Andes工程创建和调试.docx》。 + +****************************** +测试目标板(PCBA) +****************************** +[1] AE210P EVB + + diff --git a/bsp/AE210P/reset.c b/bsp/AE210P/reset.c new file mode 100644 index 0000000000000000000000000000000000000000..b0c8b4dbc852bc8b9933a8478a851fa6d300a9bd --- /dev/null +++ b/bsp/AE210P/reset.c @@ -0,0 +1,138 @@ +#include "nds32_intrinsic.h" +#include "nds32.h" + +#ifndef VECTOR_BASE +#define VECTOR_BASE 0x00000000 +#endif + +#define PSW_MSK \ + (PSW_mskGIE | PSW_mskINTL | PSW_mskPOM | PSW_mskIFCON | PSW_mskCPL) +#define PSW_INIT \ + (0x0UL << PSW_offGIE \ + | 0x0UL << PSW_offINTL \ + | 0x1UL << PSW_offPOM \ + | 0x0UL << PSW_offIFCON \ + | 0x7UL << PSW_offCPL) + +#define IVB_MSK \ + (IVB_mskEVIC | IVB_mskESZ | IVB_mskIVBASE) +#define IVB_INIT \ + ((VECTOR_BASE >> IVB_offIVBASE) << IVB_offIVBASE\ + | 0x1UL << IVB_offESZ \ + | 0x0UL << IVB_offEVIC) + + +#pragma weak c_startup = c_startup_common + +void c_startup(void); + +/* + * Default c_startup() function which used for those relocation from LMA to VMA. + */ +static void c_startup_common(void) +{ +#ifdef XIP_MODE + /* Data section initialization */ +#define MEMCPY(des, src, n) __builtin_memcpy ((des), (src), (n)) + extern char __rw_lma_start, __rw_lma_end, __rw_vma_start; + unsigned int size = &__rw_lma_end - &__rw_lma_start; + + /* Copy data section from LMA to VMA */ + MEMCPY(&__rw_vma_start, &__rw_lma_start, size); +#else + /* We do nothing for those LMA equal to VMA */ +#endif +} + +static void cpu_init(void) +{ + unsigned int reg; + + /* Set PSW GIE/INTL to 0, superuser & CPL to 7 */ + reg = (__nds32__mfsr(NDS32_SR_PSW) & ~PSW_MSK) | PSW_INIT; + __nds32__mtsr(reg, NDS32_SR_PSW); + __nds32__isb(); + + /* Set vector size: 16 byte, base: VECTOR_BASE, mode: IVIC */ + reg = (__nds32__mfsr(NDS32_SR_IVB) & ~IVB_MSK) | IVB_INIT; + __nds32__mtsr(reg, NDS32_SR_IVB); + + /* + * Check interrupt priority programmable (IVB.PROG_PRI_LVL) + * 0: Fixed priority, 1: Programmable priority + */ + if (reg & IVB_mskPROG_PRI_LVL) + { + /* Set PPL2FIX_EN to 0 to enable Programmable Priority Level */ + __nds32__mtsr(0x0, NDS32_SR_INT_CTRL); + } + + /* Mask and clear hardware interrupts */ + if (reg & IVB_mskIVIC_VER) + { + /* IVB.IVIC_VER >= 1*/ + __nds32__mtsr(0x0, NDS32_SR_INT_MASK2); + __nds32__mtsr(-1, NDS32_SR_INT_PEND2); + } + else + { + __nds32__mtsr(__nds32__mfsr(NDS32_SR_INT_MASK) & ~0xFFFF, NDS32_SR_INT_MASK); + } +} + +/* + * Vectors initialization. This means to copy exception handler code to + * vector entry base address. + */ +static void vector_init(void) +{ + extern unsigned int OS_Int_Vectors, OS_Int_Vectors_End; + + if ((unsigned int)&OS_Int_Vectors != VECTOR_BASE) + { + volatile unsigned int *vector_srcptr = &OS_Int_Vectors; + volatile unsigned int *vector_dstptr = (unsigned int *)VECTOR_BASE; + + /* copy vector table to VECTOR_BASE */ + while (vector_srcptr != &OS_Int_Vectors_End) + *vector_dstptr++ = *vector_srcptr++; + } +} + +/* + * NDS32 reset handler to reset all devices sequentially and call application + * entry function. + */ +void reset(void) +{ + extern void hardware_init(void); + extern void bsp_init(void); + extern void rtthread_startup(void); + + /* + * Initialize CPU to a post-reset state, ensuring the ground doesn't + * shift under us while we try to set things up. + */ + cpu_init(); + + /* + * Initialize LMA/VMA sections. + * Relocation for any sections that need to be copied from LMA to VMA. + */ + c_startup(); + + /* Copy vector table to vector base address */ + vector_init(); + + /* Call platform specific hardware initialization */ + hardware_init(); + + /* Setup the OS system required initialization */ + bsp_init(); + + /* Application enrty function */ + rtthread_startup(); + + /* Never go back here! */ + while(1); +} diff --git a/bsp/AE210P/rtconfig.h b/bsp/AE210P/rtconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..01a94682a6f796c532f7925fae8c0497ebe837e6 --- /dev/null +++ b/bsp/AE210P/rtconfig.h @@ -0,0 +1,199 @@ +/* RT-Thread config file */ +#ifndef __RTTHREAD_CFG_H__ +#define __RTTHREAD_CFG_H__ + +/* RT_NAME_MAX*/ +#define RT_NAME_MAX 8 + +/* RT_ALIGN_SIZE*/ +#define RT_ALIGN_SIZE 4 + +/* PRIORITY_MAX */ +#define RT_THREAD_PRIORITY_MAX 32 + +/* Tick per Second */ +#define RT_TICK_PER_SECOND (100) + +/* SECTION: RT_DEBUG */ +/* Thread Debug */ +#define RT_DEBUG +#define RT_THREAD_DEBUG + +#define RT_USING_OVERFLOW_CHECK + +/* Using Hook */ +#define RT_USING_HOOK + +/* Using Software Timer */ +/* #define RT_USING_TIMER_SOFT */ +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 +#define RT_TIMER_TICK_PER_SECOND 10 + +//#define RT_PRINTF_LONGLONG + +/* SECTION: IPC */ +/* Using Semaphore*/ +#define RT_USING_SEMAPHORE + +/* Using Mutex */ +#define RT_USING_MUTEX + +/* Using Event */ +#define RT_USING_EVENT + +/* Using MailBox */ +#define RT_USING_MAILBOX + +/* Using Message Queue */ +#define RT_USING_MESSAGEQUEUE + +/* SECTION: Memory Management */ +/* Using Memory Pool Management*/ +//#define RT_USING_MEMPOOL + +/* Using Dynamic Heap Management */ +#define RT_USING_HEAP + +/* Using Small MM */ +#define RT_USING_SMALL_MEM + +// +#define RT_USING_COMPONENTS_INIT + +/* SECTION: Device System */ +/* Using Device System */ +#define RT_USING_DEVICE +// +#define RT_USING_DEVICE_IPC +// +#define RT_USING_SERIAL + +/* SECTION: Console options */ +#define RT_USING_CONSOLE +//#define RT_KPRINTF +/* the buffer size of console*/ +#define RT_CONSOLEBUF_SIZE 260 +// +#define RT_CONSOLE_DEVICE_NAME "uart02" + +/* SECTION: finsh, a C-Express shell */ +#define RT_USING_FINSH +/* Using symbol table */ +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION + +/* SECTION: MSH, a bash shell */ +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT + +/* SECTION: MXCLI, modified base-on MSH */ +//#define FINSH_USING_MXCLI + +/* SECTION: device filesystem */ +//#define RT_USING_DFS +//#define DFS_USING_WORKDIR +//#define RT_USING_DFS_DEVFS + +//#define RT_USING_DFS_JFFS2 +/* Reentrancy (thread safe) of the FatFs module. */ +#define RT_DFS_ELM_REENTRANT +/* Number of volumes (logical drives) to be used. */ +#define RT_DFS_ELM_DRIVES 2 +/* #define RT_DFS_ELM_USE_LFN 1 */ +/* #define RT_DFS_ELM_CODE_PAGE 936 */ +#define RT_DFS_ELM_MAX_LFN 255 +/* Maximum sector size to be handled. */ +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 + +/* the max number of mounted filesystem */ +#define DFS_FILESYSTEMS_MAX 2 +/* the max number of opened files */ +#define DFS_FD_MAX 4 + +/* SECTION: lwip, a lighwight TCP/IP protocol stack */ +/* #define RT_USING_LWIP */ +/* LwIP uses RT-Thread Memory Management */ +#define RT_LWIP_USING_RT_MEM +/* Enable ICMP protocol*/ +#define RT_LWIP_ICMP +/* Enable UDP protocol*/ +#define RT_LWIP_UDP +/* Enable TCP protocol*/ +#define RT_LWIP_TCP +/* Enable DNS */ +#define RT_LWIP_DNS + +/* the number of simulatenously active TCP connections*/ +#define RT_LWIP_TCP_PCB_NUM 5 + +/* Using DHCP */ +/* #define RT_LWIP_DHCP */ + +/* ip address of target*/ +#define RT_LWIP_IPADDR0 192 +#define RT_LWIP_IPADDR1 168 +#define RT_LWIP_IPADDR2 1 +#define RT_LWIP_IPADDR3 30 + +/* gateway address of target*/ +#define RT_LWIP_GWADDR0 192 +#define RT_LWIP_GWADDR1 168 +#define RT_LWIP_GWADDR2 1 +#define RT_LWIP_GWADDR3 1 + +/* mask address of target*/ +#define RT_LWIP_MSKADDR0 255 +#define RT_LWIP_MSKADDR1 255 +#define RT_LWIP_MSKADDR2 255 +#define RT_LWIP_MSKADDR3 0 + +/* tcp thread options */ +#define RT_LWIP_TCPTHREAD_PRIORITY 12 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 10 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 + +/* ethernet if thread options */ +#define RT_LWIP_ETHTHREAD_PRIORITY 15 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 10 +#define RT_LWIP_ETHTHREAD_STACKSIZE 512 + +/* TCP sender buffer space */ +#define RT_LWIP_TCP_SND_BUF 8192 +/* TCP receive window. */ +#define RT_LWIP_TCP_WND 8192 + +/* SECTION: RT-Thread/GUI */ +/* #define RT_USING_RTGUI */ + +/* name length of RTGUI object */ +#define RTGUI_NAME_MAX 12 +/* support 16 weight font */ +#define RTGUI_USING_FONT16 +/* support Chinese font */ +#define RTGUI_USING_FONTHZ +/* use DFS as file interface */ +#define RTGUI_USING_DFS_FILERW +/* use font file as Chinese font */ +#define RTGUI_USING_HZ_FILE +/* use Chinese bitmap font */ +#define RTGUI_USING_HZ_BMP +/* use small size in RTGUI */ +#define RTGUI_USING_SMALL_SIZE +/* use mouse cursor */ +/* #define RTGUI_USING_MOUSE_CURSOR */ +/* default font size in RTGUI */ +#define RTGUI_DEFAULT_FONT_SIZE 16 + +/* image support */ +/* #define RTGUI_IMAGE_XPM */ +/* #define RTGUI_IMAGE_BMP */ + +// +// #define RT_USING_CMSIS_OS +// +#define RT_USING_RTT_CMSIS +// +// #define RT_USING_BSP_CMSIS + +#endif diff --git a/bsp/AE210P/start.S b/bsp/AE210P/start.S new file mode 100644 index 0000000000000000000000000000000000000000..73caedf2982ceb180b62935daf969d3e704f2f8b --- /dev/null +++ b/bsp/AE210P/start.S @@ -0,0 +1,197 @@ +!******************************************************************************************************** +! +! (c) Copyright 2005-2014, Andes Techonology +! All Rights Reserved +! +! NDS32 Generic Port +! GNU C Compiler +! +!******************************************************************************************************** +!******************************************************************************************************** +! INCLUDE ASSEMBLY CONSTANTS +!******************************************************************************************************** + +#include +#include "nds32_defs.h" +#include "os_cpu_common.h" + +#ifndef VECTOR_NUMINTRS +#define VECTOR_NUMINTRS 32 +#endif + + .global OS_Init_Nds32 + .global OS_Int_Vectors + .global OS_Int_Vectors_End + + .macro WEAK_DEFAULT weak_sym, default_handler + .weak \weak_sym + .set \weak_sym ,\default_handler + .endm + + ! Define standard NDS32 vector table entry point of + ! exception/interruption vectors + .macro VECTOR handler + WEAK_DEFAULT \handler, OS_Default_Exception + .align 4 +__\handler: +#ifdef MPU_SUPPORT + la $p0, \handler + jr5 $p0 +#else + pushm $r0, $r5 + la $r0, \handler + jr5 $r0 +#endif + .endm + + .macro INTERRUPT_VECTOR num + WEAK_DEFAULT OS_Trap_Interrupt_HW\num, OS_Default_Interrupt + .align 4 +__OS_Trap_Interrupt_HW\num: +#ifdef MPU_SUPPORT + la $p1, OS_Trap_Interrupt_HW\num + li $p0, \num + jr5 $p1 +#else + pushm $r0, $r5 + la $r1, OS_Trap_Interrupt_HW\num + li $r0, \num + jr5 $r1 +#endif + .endm + +!******************************************************************************************************** +! Vector Entry Table +!******************************************************************************************************** + .section .nds32_init, "ax" + +OS_Int_Vectors: + b OS_Init_Nds32 ! (0) Trap Reset/NMI + VECTOR OS_Trap_TLB_Fill ! (1) Trap TLB fill + VECTOR OS_Trap_PTE_Not_Present ! (2) Trap PTE not present + VECTOR OS_Trap_TLB_Misc ! (3) Trap TLB misc + VECTOR OS_Trap_TLB_VLPT_Miss ! (4) Trap TLB VLPT miss + VECTOR OS_Trap_Machine_Error ! (5) Trap Machine error + VECTOR OS_Trap_Debug_Related ! (6) Trap Debug related + VECTOR OS_Trap_General_Exception ! (7) Trap General exception + VECTOR OS_Trap_Syscall ! (8) Syscall + + ! Interrupt vectors + .altmacro + .set irqno, 0 + .rept VECTOR_NUMINTRS + INTERRUPT_VECTOR %irqno + .set irqno, irqno+1 + .endr + + .align 4 +OS_Int_Vectors_End: + +!****************************************************************************************************** +! Start Entry +!****************************************************************************************************** + .section .text + .global _start +OS_Init_Nds32: +_start: + !************************** Begin of do-not-modify ************************** + ! Please don't modify this code + ! Initialize the registers used by the compiler + + nds32_init ! NDS32 startup initial macro in + + !*************************** End of do-not-modify *************************** + +#ifdef CONFIG_HWZOL + ! enable AEN + mfsr $r0, $PSW + ori $r0, $r0, (1 << PSW_offAEN) + mtsr $r0, $PSW +#endif + +#if (defined(CONFIG_CPU_ICACHE_ENABLE) || defined(CONFIG_CPU_DCACHE_ENABLE)) + ! disable cache + mfsr $r0, $CACHE_CTL + li $r1, ~(CACHE_CTL_mskIC_EN | CACHE_CTL_mskDC_EN) + and $r0, $r0, $r1 + mtsr $r0, $CACHE_CTL +#endif + + ! Do system low level setup. It must be a leaf function. + bal _nds32_init_mem + +#if 1 /* Speed prefer */ + ! We do this on a word basis. + ! Currently, the default linker script guarantee + ! the __bss_start/_end boundary word-aligned. + + ! Clear bss + la $r0, __bss_start + la $r1, _end + sub $r2, $r1, $r0 ! $r2: Size of .bss + beqz $r2, clear_end + + andi $r7, $r2, 0x1f ! $r7 = $r2 mod 32 + movi $r3, 0 + movi $r4, 0 + movi $r5, 0 + movi $r6, 0 + movi $r8, 0 + movi $r9, 0 + movi $r10, 0 + beqz $r7, clear_loop ! if $r7 == 0, bss_size%32 == 0 + sub $r2, $r2, $r7 + +first_clear: + swi.bi $r3, [$r0], #4 ! clear each word + addi $r7, $r7, -4 + bnez $r7, first_clear + li $r1, 0xffffffe0 + and $r2, $r2, $r1 ! check bss_size/32 == 0 or not + beqz $r2, clear_end ! if bss_size/32 == 0 , needless to clear + +clear_loop: + smw.bim $r3, [$r0], $r10 !clear each 8 words + addi $r2, $r2, -32 + bgez $r2, clear_loop + +clear_end: +#else /* Size prefer */ + ! Clear bss + la $r0, _edata + la $r1, _end + beq $r0, $r1, 2f + li $r2, #0 +1: + swi.bi $r2, [$r0], #4 + bne $r0, $r1, 1b +2: +#endif + ! Set-up the stack pointer + la $sp, _stack + + ! System reset handler + bal reset + + ! Default exceptions / interrupts handler +OS_Default_Exception: +OS_Default_Interrupt: +die: + b die + +!******************************************************************************************************** +! Interrupt vector Table +!******************************************************************************************************** + + .data + .align 2 + + ! These tables contain the isr pointers used to deliver interrupts + .global OS_CPU_Vector_Table +OS_CPU_Vector_Table: + .rept 32 + .long OS_Default_Interrupt + .endr + + .end + diff --git a/bsp/AE210P/startup.c b/bsp/AE210P/startup.c new file mode 100644 index 0000000000000000000000000000000000000000..c46085397c96830d9b361beaeed9e0d1c1eef11d --- /dev/null +++ b/bsp/AE210P/startup.c @@ -0,0 +1,113 @@ +/* + * File : startup.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://openlab.rt-thread.com/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2006-08-31 Bernard first implementation + */ + +#include +#include + +#ifdef RT_USING_COMPONENTS_INIT +#include +#endif /* RT_USING_COMPONENTS_INIT */ + +#include "board.h" + +extern int rt_application_init(void); // define in application/application.c + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#elif __ICCARM__ +#pragma section="HEAP" +#else +extern int __bss_end; +extern int _stack; +#endif + +/******************************************************************************* +* Function Name : assert_failed +* Description : Reports the name of the source file and the source line number +* where the assert error has occurred. +* Input : - file: pointer to the source file name +* - line: assert error line source number +* Output : None +* Return : None +*******************************************************************************/ +void assert_failed(char* file, int line) +{ + rt_kprintf("\n\r Wrong parameter value detected on\r\n"); + rt_kprintf(" file %s\r\n", file); + rt_kprintf(" line %d\r\n", line); + + while (1) ; +} + +/** + * This function will startup RT-Thread RTOS. + */ +void rtthread_startup(void) +{ + /* show version */ + rt_show_version(); + +#ifdef RT_USING_HEAP +#if STM32_EXT_SRAM + rt_system_heap_init((void*)STM32_EXT_SRAM_BEGIN, (void*)STM32_EXT_SRAM_END); +#else +#ifdef __CC_ARM + rt_system_heap_init((void*)&Image$$RW_IRAM1$$ZI$$Limit, (void*)MXT_IRAM_END); +#elif __ICCARM__ + rt_system_heap_init(__segment_end("HEAP"), (void*)STM32_SRAM_END); +#else + /* init memory system */ + rt_system_heap_init((void *)0x00250000, (void *)0x00280000); +#endif +#endif /* STM32_EXT_SRAM */ +#endif /* RT_USING_HEAP */ + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + + /* init scheduler system */ + rt_system_scheduler_init(); + + /* initialize timer */ + rt_system_timer_init(); + + /* init timer thread */ + rt_system_timer_thread_init(); + + /* init application */ + rt_application_init(); + + /* init idle thread */ + rt_thread_idle_init(); + + /* start scheduler */ + rt_system_scheduler_start(); + + /* never reach here */ + return ; +} + +//int main(void) +//{ +// /* disable interrupt first */ +// rt_hw_interrupt_disable(); +// +// /* startup RT-Thread RTOS */ +// rtthread_startup(); +// +// return 0; +//} + +/*@}*/ diff --git a/libcpu/nds32/context_gcc.S b/libcpu/nds32/context_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..8d5f3287e9cc026dbfbbedaac48af35eaec83118 --- /dev/null +++ b/libcpu/nds32/context_gcc.S @@ -0,0 +1,188 @@ +#include "nds32.h" +#include "os_cpu_common.h" +#include "config.h" + + .align 4 +! void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); +! R0 --> from +! R1 --> to + .section .text + .global rt_hw_context_switch_interrupt + .global rt_hw_context_switch +rt_hw_context_switch_interrupt: +rt_hw_context_switch: + push25 $r6,#8 ! {$r6, $fp, $gp, $lp} + + la $r2, rt_thread_switch_interrupt_flag + lw $r3, [$r2] + movi $r4, #1 + beq $r3, $r4, _reswitch + sw $r4, [$r2] ! set rt_thread_switch_interrupt_flag to 1 + + la $r2, rt_interrupt_from_thread + sw $r0, [$r2] ! set rt_interrupt_from_thread +_reswitch: + la $r2, rt_interrupt_to_thread + sw $r1, [$r2] ! set rt_interrupt_to_thread + bal hal_intc_swi_trigger ! trigger the swi exception (causes context switch) + + pop25 $r6,#8 ! {$r6, $fp, $gp, $lp} + +! R0 --> switch from thread stack +! R1 --> switch to thread stack +! psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack + + .align 4 + .global OS_Trap_Interrupt_SWI +OS_Trap_Interrupt_SWI: +! pushm $r0, $r5 + setgie.d ! disable interrupt to protect context switch + dsb + + IntlDescend ! Descend interrupt level + + movi $r0, 0x0 + mtsr $r0, $INT_PEND ! clean SWI pending + + la $r0, rt_thread_switch_interrupt_flag ! get rt_thread_switch_interrupt_flag + lw $r1, [$r0] + beqz $r1, pendsv_exit ! swi has already been handled + + movi $r1, #0 + sw $r1, [$r0] ! clear rt_thread_switch_interrupt_flag to 0 + + la $r0, rt_interrupt_from_thread + lw $r1, [$r0] + beqz $r1, switch_to_thread ! skip register save at the first time(os startup phase) + + SAVE_ALL + + move $r1, $sp + la $r0, rt_interrupt_from_thread + lw $r0, [$r0] + sw $r1, [$r0] + +switch_to_thread: + la $r1, rt_interrupt_to_thread + lw $r1, [$r1] + lw $r1, [$r1] ! load thread stack pointer + move $sp, $r1 ! update stack pointer + RESTORE_ALL ! pop registers + +pendsv_exit: + setgie.e + iret + + .align 4 +! void rt_hw_context_switch_to(rt_uint32 to); +! R0 --> to + .global rt_hw_context_switch_to +rt_hw_context_switch_to: + la $r1, rt_interrupt_to_thread + sw $r0, [$r1] + + ! set from thread to 0 + la $r1, rt_interrupt_from_thread + movi $r0, #0 + sw $r0, [$r1] + + ! set interrupt flag to 1 + la $r1, rt_thread_switch_interrupt_flag + movi $r0, #1 + sw $r0, [$r1] + + ! set the SWI exception priority(must be the lowest level) + ! todo + + ! trigger the SWI exception (causes context switch) + jal hal_intc_swi_trigger + + setgie.e ! enable interrupts at processor level + +1: + b 1b ! never reach here + +#ifndef VECTOR_NUMINTRS +#define VECTOR_NUMINTRS 32 +#endif + + .global OS_Trap_Int_Common + + ! Set up Interrupt vector ISR + ! HW#IRQ_SWI_VECTOR : OS_Trap_Interrupt_SWI (SWI) + ! HW#n : OS_Trap_Int_Common + + .macro SET_HWISR num + .global OS_Trap_Interrupt_HW\num + .if \num == IRQ_SWI_VECTOR + .set OS_Trap_Interrupt_HW\num, OS_Trap_Interrupt_SWI + .else + .set OS_Trap_Interrupt_HW\num, OS_Trap_Int_Common + .endif + .endm + + .altmacro + .set irqno, 0 + .rept VECTOR_NUMINTRS + SET_HWISR %irqno + .set irqno, irqno+1 + .endr + .noaltmacro + +! .global OS_Trap_Int_Common +OS_Trap_Int_Common: +#ifdef MPU_SUPPORT + mfsr $p1, $PSW + ori $p1, $p1, (PSW_mskIT | PSW_mskDT) + mtsr $p1, $PSW ! enable IT/DT + dsb + pushm $r0, $r5 + move $r0, $p0 ! IRQ number +#endif + ! $r0 : HW Interrupt vector number + SAVE_CALLER + + IntlDescend ! Descend interrupt level + + mfsr $r1, $IPSW ! Use IPSW.CPL to check come from thread or ISR + srli45 $r1, #PSW_offCPL + fexti33 $r1, #0x2 ! IPSW.CPL + bnec $r1, #0x7, 2f ! IPSW.CPL != 7, come form ISR, reentrant + + move $fp, $sp ! save old stack pointer + la $sp, __OS_Int_Stack ! switch to interrupt stack +2: + setgie.e ! allow nested now + + ! The entire CPU state is now stashed on the stack, + ! and the stack is also 8-byte alignment. + ! We can call C program based interrupt handler now. + la $r1, OS_CPU_Vector_Table + lw $r1, [$r1+($r0<<2)] ! ISR function pointer + jral $r1 ! Call ISR + + la $r1, __OS_Int_Stack ! Check for nested interruption return + bne $r1, $sp, 3f ! $sp != __OS_Int_Stack? + + move $sp, $fp ! Move back to the thread stack +3: + RESTORE_CALLER + + iret + +! .set OS_Trap_Interrupt_HW9, OS_Trap_Interrupt_SWI +! .set OS_Trap_Interrupt_HW19, OS_Trap_Int_Common + +!********************************************* +! POINTERS TO VARIABLES +!********************************************* +#ifdef MPU_SUPPORT + .section privileged_data +#else + .section .bss +#endif + .skip IRQ_STACK_SIZE + .align 3 +__OS_Int_Stack: + + .end diff --git a/libcpu/nds32/cpuport.c b/libcpu/nds32/cpuport.c new file mode 100644 index 0000000000000000000000000000000000000000..17523f24303bf857e724d903dee01b34e93a546b --- /dev/null +++ b/libcpu/nds32/cpuport.c @@ -0,0 +1,221 @@ +/* + * File : cpuport.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-01-05 Bernard first version + * 2011-02-14 onelife Modify for EFM32 + * 2011-06-17 onelife Merge all of the C source code into cpuport.c + * 2012-12-23 aozima stack addr align to 8byte. + * 2012-12-29 Bernard Add exception hook. + * 2013-07-09 aozima enhancement hard fault exception handler. + */ + +#include + +#include "nds32.h" + +/* + * Initialise the stack of a task to look exactly as if a call to + * SAVE_CONTEXT had been called. + * + * See header file for description. + * + * + * Stack Layout: + * High |-----------------| + * | $R5 | + * |-----------------| + * | . | + * | . | + * |-----------------| + * | $R0 | + * |-----------------| + * | $R30 (LP) | + * |-----------------| + * | $R29 (GP) | + * |-----------------| + * | $R28 (FP) | + * |-----------------| + * | $R15 $R27 | + * |-----------------| + * | $R10 $R26 | + * |-----------------| + * | . | + * | . | + * |-----------------| + * | $R6 | + * |-----------------| + * | $IFC_LP | (Option) + * |-----------------| + * | $LC/$LE/$LB | (Option) + * | (ZOL) | + * |-----------------| + * | $IPSW | + * |-----------------| + * | $IPC | + * |-----------------| + * | Dummy word | (Option, only exist when IFC & ZOL both configured) + * |-----------------| + * | $FPU | (Option) + * |-----------------| + * Low + * + */ + +struct stack_frame +{ + rt_uint32_t topOfStack[34]; +}; + +/* flag in interrupt handling */ +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; +/* exception hook */ +static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL; + +rt_base_t rt_hw_interrupt_disable(void) +{ + rt_base_t level = __nds32__mfsr(NDS32_SR_PSW); + + GIE_DISABLE(); + + return level; +} + +void rt_hw_interrupt_enable(rt_base_t level) +{ + if (level & PSW_mskGIE) + GIE_ENABLE(); +} + +/* For relax support, must initial $gp at task init*/ +extern uint32_t _SDA_BASE_ __attribute__ ((weak)); + +/************************************************************** + * 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_int32_t i; + rt_uint32_t *pxTopOfStack; + + pxTopOfStack = (rt_uint32_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 4); + + /* Simulate the stack frame as it would be created by a context switch */ + /* R0 ~ R5 registers */ + for (i = 5; i >= 1; i--) /* R5, R4, R3, R2 and R1. */ + *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i; + *--pxTopOfStack = (rt_uint32_t)parameter; /* R0 : Argument */ + + /* R6 ~ R30 registers */ + *--pxTopOfStack = (rt_uint32_t)texit; /* R30: $LP */ + *--pxTopOfStack = (rt_uint32_t)&_SDA_BASE_; /* R29: $GP */ + *--pxTopOfStack = (rt_uint32_t)0x2828282828; /* R28: $FP */ +#ifdef __NDS32_REDUCE_REGS__ + *--pxTopOfStack = (rt_uint32_t)0x1515151515; /* R15 */ + for (i = 10; i >= 6; i--) /* R10 ~ R6 */ + *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i; +#else + for (i = 27; i >= 6; i--) /* R27 ~ R6 */ + *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i; +#endif + + /* IFC system register */ +#ifdef __TARGET_IFC_EXT + *--pxTopOfStack = (rt_uint32_t)0x0; /* $IFC_LP */ +#endif + + /* ZOL system registers */ +#ifdef __TARGET_ZOL_EXT + *--pxTopOfStack = (rt_uint32_t)0x0; /* $LC */ + *--pxTopOfStack = (rt_uint32_t)0x0; /* $LE */ + *--pxTopOfStack = (rt_uint32_t)0x0; /* $LB */ +#endif + + /* IPSW and IPC system registers */ + /* Default IPSW: enable GIE, set CPL to 7, clear IFCON */ + i = (__nds32__mfsr(NDS32_SR_PSW) | PSW_mskGIE | PSW_mskCPL) & ~PSW_mskIFCON; + *--pxTopOfStack = (rt_uint32_t)i; /* $IPSW */ + *--pxTopOfStack = (rt_uint32_t)tentry; /* $IPC */ + + /* Dummy word for 8-byte stack alignment */ +#if defined(__TARGET_IFC_EXT) && defined(__TARGET_ZOL_EXT) + *--pxTopOfStack = (rt_uint32_t)0xFFFFFFFF; /* Dummy */ +#endif + + /* FPU registers */ +#ifdef __TARGET_FPU_EXT + for (i = 0; i < FPU_REGS; i++) + *--pxTopOfStack = (rt_uint32_t)0x0; /* FPU */ +#endif + + return (rt_uint8_t *)pxTopOfStack; +} + +/** + * This function set the hook, which is invoked on fault exception handling. + * + * @param exception_handle the exception handling hook function. + */ +void rt_hw_exception_install(rt_err_t (*exception_handle)(void* context)) +{ + rt_exception_hook = exception_handle; +} + +#ifdef RT_USING_CPU_FFS +/** + * 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. + */ +#if defined(__CC_ARM) +__asm int __rt_ffs(int value) +{ + CMP r0, #0x00 + BEQ exit + RBIT r0, r0 + CLZ r0, r0 + ADDS r0, r0, #0x01 + + exit + BX lr +} +#elif defined(__IAR_SYSTEMS_ICC__) +int __rt_ffs(int value) +{ + if (value == 0) return value; + + __ASM("RBIT r0, r0"); + __ASM("CLZ r0, r0"); + __ASM("ADDS r0, r0, #0x01"); +} +#elif defined(__GNUC__) +int __rt_ffs(int value) +{ + return __builtin_ffs(value); +} +#endif + +#endif