Browse Source

Merge pull request #826 from ArcherChang/master

[BSP] Add Andes N1068 porting and simple bsp.
Bernard Xiong 7 years ago
parent
commit
ea18ef60ed
58 changed files with 17853 additions and 0 deletions
  1. 76 0
      .cproject
  2. 26 0
      .project
  3. 2 0
      bsp/AE210P/.PHONY.size
  4. 301 0
      bsp/AE210P/Makefile
  5. 136 0
      bsp/AE210P/application.c
  6. 95 0
      bsp/AE210P/board.c
  7. 28 0
      bsp/AE210P/board.h
  8. 338 0
      bsp/AE210P/board/ae210p.c
  9. 74 0
      bsp/AE210P/board/ae210p.h
  10. 202 0
      bsp/AE210P/board/ae210p.ld
  11. 68 0
      bsp/AE210P/board/ae210p.sag
  12. 306 0
      bsp/AE210P/board/ae210p_defs.h
  13. 315 0
      bsp/AE210P/board/ae210p_regs.h
  14. 212 0
      bsp/AE210P/board/uart_dev.c
  15. 23 0
      bsp/AE210P/board/uart_dev.h
  16. 77 0
      bsp/AE210P/bsp_hal.h
  17. 273 0
      bsp/AE210P/cache.c
  18. 45 0
      bsp/AE210P/cache.h
  19. 48 0
      bsp/AE210P/config.h
  20. 78 0
      bsp/AE210P/debug.h
  21. 2 0
      bsp/AE210P/driver/dma/Kbuild
  22. 2513 0
      bsp/AE210P/driver/dma/dmad.c
  23. 275 0
      bsp/AE210P/driver/dma/dmad.h
  24. 86 0
      bsp/AE210P/driver/gpio/gpio.c
  25. 52 0
      bsp/AE210P/driver/gpio/gpio.h
  26. 1 0
      bsp/AE210P/driver/lcd/Kbuild
  27. 248 0
      bsp/AE210P/driver/lcd/font.c
  28. 114 0
      bsp/AE210P/driver/lcd/lcd-info.h
  29. 142 0
      bsp/AE210P/driver/lcd/lcd.c
  30. 29 0
      bsp/AE210P/driver/lcd/lcd.h
  31. 74 0
      bsp/AE210P/driver/osc/osc.c
  32. 77 0
      bsp/AE210P/driver/osc/osc.h
  33. 3 0
      bsp/AE210P/driver/sd/Kbuild
  34. 143 0
      bsp/AE210P/driver/sd/sd.h
  35. 2951 0
      bsp/AE210P/driver/sd/sdd.c
  36. 219 0
      bsp/AE210P/driver/sd/sdd.h
  37. 2662 0
      bsp/AE210P/driver/sd/sdd_sd.c
  38. 927 0
      bsp/AE210P/driver/sd/sdd_sd.h
  39. 1 0
      bsp/AE210P/driver/ssp/Kbuild
  40. 300 0
      bsp/AE210P/driver/ssp/sspd_ac97.c
  41. 444 0
      bsp/AE210P/driver/ssp/sspd_ac97.h
  42. 456 0
      bsp/AE210P/driver/ssp/sspd_rts.c
  43. 199 0
      bsp/AE210P/driver/ssp/sspd_rts.h
  44. 2 0
      bsp/AE210P/driver/uart/Kbuild
  45. 143 0
      bsp/AE210P/driver/uart/uart.c
  46. 17 0
      bsp/AE210P/driver/uart/uart.h
  47. 80 0
      bsp/AE210P/nds32.h
  48. 1362 0
      bsp/AE210P/nds32_defs.h
  49. 426 0
      bsp/AE210P/os_cpu_common.h
  50. 54 0
      bsp/AE210P/os_except.c
  51. 23 0
      bsp/AE210P/os_except.h
  52. 49 0
      bsp/AE210P/readme/readme.txt
  53. 138 0
      bsp/AE210P/reset.c
  54. 199 0
      bsp/AE210P/rtconfig.h
  55. 197 0
      bsp/AE210P/start.S
  56. 113 0
      bsp/AE210P/startup.c
  57. 188 0
      libcpu/nds32/context_gcc.S
  58. 221 0
      libcpu/nds32/cpuport.c

+ 76 - 0
.cproject

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="nds.nds32le-elf-mculib-v3.base.58599081">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="nds.nds32le-elf-mculib-v3.base.58599081" moduleId="org.eclipse.cdt.core.settings" name="Default">
+				<externalSettings/>
+				<extensions>
+					<extension id="com.andestech.ide.cdt.managedbuilder.core.CROSS_GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="${ProjName}" buildProperties="" description="" id="nds.nds32le-elf-mculib-v3.base.58599081" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="nds.nds32le-elf-mculib-v3.base.58599081.1110402366" name="/" resourcePath="">
+						<toolChain id="nds.nds32le-elf-mculib-v3.base.1767351733" name="nds32le-elf-mculib-v3" superClass="nds.nds32le-elf-mculib-v3.base">
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_CPU.1896754197" name="CPU" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_CPU"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_LIST_CPU.895643889" name="LIST_CPU" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_LIST_CPU"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_CORE.1142664471" name="CORE" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_CORE"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_ARCH.1121945628" name="ARCH" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_ARCH"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_ISA_REDUCE_REGS.1293207534" name="ISA_REDUCE_REGS" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_ISA_REDUCE_REGS"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_TARGET.1070191715" name="TARGET" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_TARGET"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_ENDIAN.377724547" name="ENDIAN" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_ENDIAN"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_LIB_C_DEFAULT.464304688" name="LIB_C_DEFAULT" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_LIB_C_DEFAULT"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_LIB_CPP_DEFAULT.1439903022" name="LIB_CPP_DEFAULT" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.NDS32_LIB_CPP_DEFAULT"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.RSE_TARGET.1444389132" name="RSE_TARGET" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.RSE_TARGET"/>
+							<option id="nds32le-elf-mculib-v3.managedbuild.option.toolchain.RSE_CONNECT.1587775719" name="RSE_CONNECT" superClass="nds32le-elf-mculib-v3.managedbuild.option.toolchain.RSE_CONNECT"/>
+							<targetPlatform archList="all" binaryParser="com.andestech.ide.cdt.managedbuilder.core.CROSS_GNU_ELF" id="target.nds.platform.base.894202893" name="Debug Platform" osList="all" superClass="target.nds.platform.base"/>
+							<builder buildPath="${workspace_loc:/rtt_master/bsp/AE210P}" cleanBuildTarget="APP=rtthread AE210P=1 USING_CLI=1 DEBUG=1 clean" id="target.nds.builder.base.798580194" incrementalBuildTarget="APP=rtthread AE210P=1 USING_CLI=1 DEBUG=1 all" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Andes Make Builder" superClass="target.nds.builder.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.archiver.base.541270770" name="Andes Archiver" superClass="tool.nds32le-elf-mculib-v3.archiver.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.cpp.compiler.base.798443763" name="Andes C++ Compiler" superClass="tool.nds32le-elf-mculib-v3.cpp.compiler.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.cpp.linker.base.1663125809" name="Andes C++ Linker" superClass="tool.nds32le-elf-mculib-v3.cpp.linker.base">
+								<option defaultValue="true" id="nds32le-elf-mculib-v3.cpp.link.option.noshared.base.889050287" name="No shared libraries (-static)" superClass="nds32le-elf-mculib-v3.cpp.link.option.noshared.base" valueType="boolean"/>
+							</tool>
+							<tool id="tool.nds32le-elf-mculib-v3.c.compiler.base.1446774168" name="Andes C Compiler" superClass="tool.nds32le-elf-mculib-v3.c.compiler.base">
+								<inputType id="tool.nds.c.compiler.input.624026089" superClass="tool.nds.c.compiler.input"/>
+							</tool>
+							<tool id="tool.nds32le-elf-mculib-v3.c.linker.base.84728931" name="Andes C Linker" superClass="tool.nds32le-elf-mculib-v3.c.linker.base">
+								<option defaultValue="true" id="nds32le-elf-mculib-v3.c.link.option.noshared.base.2119240931" name="No shared libraries (-static)" superClass="nds32le-elf-mculib-v3.c.link.option.noshared.base" valueType="boolean"/>
+								<inputType id="tool.nds.c.linker.input.775039577" superClass="tool.nds.c.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="tool.nds32le-elf-mculib-v3.assembler.base.1651903076" name="Andes Assembler" superClass="tool.nds32le-elf-mculib-v3.assembler.base">
+								<inputType id="tool.nds.assembler.input.639385268" superClass="tool.nds.assembler.input"/>
+							</tool>
+							<tool id="tool.nds32le-elf-mculib-v3.nm.base.1513872058" name="NM (symbol listing)" superClass="tool.nds32le-elf-mculib-v3.nm.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.readelf.base.839251283" name="Readelf (ELF info listing)" superClass="tool.nds32le-elf-mculib-v3.readelf.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.objdump.base.380287659" name="Objdump (disassembly)" superClass="tool.nds32le-elf-mculib-v3.objdump.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.objcopy.base.511281711" name="Objcopy (object content copy)" superClass="tool.nds32le-elf-mculib-v3.objcopy.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.size.base.191568706" name="Size (section size listing)" superClass="tool.nds32le-elf-mculib-v3.size.base"/>
+							<tool id="tool.nds32le-elf-mculib-v3.ldsag.base.682055329" name="LdSaG Tool" superClass="tool.nds32le-elf-mculib-v3.ldsag.base"/>
+						</toolChain>
+					</folderInfo>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="rtt_master.null.750251984" name="rtt_master"/>
+	</storageModule>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="refreshScope" versionNumber="2">
+		<configuration configurationName="Default">
+			<resource resourceType="PROJECT" workspacePath="/rtt_master"/>
+		</configuration>
+	</storageModule>
+</cproject>

+ 26 - 0
.project

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>rtt_master</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
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

+ 301 - 0
bsp/AE210P/Makefile

@@ -0,0 +1,301 @@
+#************************************************************
+# RT-Thread RTOS makefile base on Andes N1068A core
+#
+# Mengxin Technology Co., Ltd.
+# Archer Chang <archer.zhang@wh-mx.com>
+# 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 $$?),0)
+	CFLAGS += -fno-delete-null-pointer-checks
+	LD_FLAGS += -fno-delete-null-pointer-checks
+endif
+
+# Maybe necessary
+NO_IFC = y
+NO_EX9 = y
+
+ifeq ($(shell echo | $(CC) -E -dM - | grep __NDS32_EXT_IFC__ > /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

+ 136 - 0
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 <board.h>
+#include <rtthread.h>
+#include <rthw.h>
+
+#ifdef  RT_USING_COMPONENTS_INIT
+#include <components.h>
+#endif  /* RT_USING_COMPONENTS_INIT */
+
+#ifdef RT_USING_DFS
+/* dfs filesystem:ELM filesystem init */
+#include <dfs_elm.h>
+/* dfs Filesystem APIs */
+#include <dfs_fs.h>
+#endif
+
+#ifdef RT_USING_RTGUI
+#include <rtgui/rtgui.h>
+#include <rtgui/rtgui_server.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/driver.h>
+#include <rtgui/calibration.h>
+#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;
+}
+
+/*@}*/

+ 95 - 0
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 <rthw.h>
+#include <rtthread.h>
+
+#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);
+}
+
+/*@}*/

+ 28 - 0
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__ */

+ 338 - 0
bsp/AE210P/board/ae210p.c

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

+ 74 - 0
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 <inttypes.h>
+#include <nds32_intrinsic.h>
+#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__ */

+ 202 - 0
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");

+ 68 - 0
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
+	}	
+}

+ 306 - 0
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__ */

+ 315 - 0
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 <inttypes.h>
+#include <nds32_intrinsic.h>
+#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<<bit);\
+        __nds32__mtsr(mask, reg);	 \
+	__nds32__dsb();				 \
+}
+
+#define SR_SETB32(reg,bit)\
+{\
+	int mask = __nds32__mfsr(reg)|(1<<bit);\
+	__nds32__mtsr(mask, reg);			\
+	__nds32__dsb();						\
+}
+
+#endif /* __AE210P_REGS_H__ */

+ 212 - 0
bsp/AE210P/board/uart_dev.c

@@ -0,0 +1,212 @@
+/*
+ * File      : uart_dev.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      the first version
+ * 2010-03-29     Bernard      remove interrupt Tx and DMA Rx mode
+ * 2013-05-13     aozima       update for kehong-lingtai.
+ */
+
+#include "uart/uart.h"
+#include "uart_dev.h"
+#include "ae210p.h"
+#include "board.h"
+#include "bsp_hal.h"
+
+#include "rtdevice.h"
+
+#include "serial.h"
+
+#define UART_ENABLE_IRQ(n)  hal_intc_irq_enable(n)
+#define UART_DISABLE_IRQ(n) hal_intc_irq_disable(n)
+
+struct uart_device
+{
+	uint32_t uart_base;
+	uint32_t irq;
+};
+
+static rt_err_t __uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+	struct uart_device *uartDev = RT_NULL;
+
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+
+	uartDev = (struct uart_device *)serial->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 */
+}
+

+ 23 - 0
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__"

+ 77 - 0
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

+ 273 - 0
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
+}

+ 45 - 0
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__ */

+ 48 - 0
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"

+ 78 - 0
bsp/AE210P/debug.h

@@ -0,0 +1,78 @@
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdio.h>
+
+#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__ */

+ 2 - 0
bsp/AE210P/driver/dma/Kbuild

@@ -0,0 +1,2 @@
+lib-y		:=
+lib-y		+= dmad.o

+ 2513 - 0
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;
+}

+ 275 - 0
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 <hal.h>
+
+/*****************************************************************************
+ * 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__ */

+ 86 - 0
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;
+}

+ 52 - 0
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__

+ 1 - 0
bsp/AE210P/driver/lcd/Kbuild

@@ -0,0 +1 @@
+lib-${CONFIG_FB_FTLCDC100}	+= font.o lcd.o

+ 248 - 0
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++;
+	}
+}

+ 114 - 0
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__ */

+ 142 - 0
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;
+}

+ 29 - 0
bsp/AE210P/driver/lcd/lcd.h

@@ -0,0 +1,29 @@
+#ifndef __LCD_H__
+#define __LCD_H__
+
+#include <inttypes.h>
+#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__ */

+ 74 - 0
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;
+}
+

+ 77 - 0
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

+ 3 - 0
bsp/AE210P/driver/sd/Kbuild

@@ -0,0 +1,3 @@
+lib-y		+=
+lib-y		+= sdd.o
+lib-y		+= sdd_sd.o

+ 143 - 0
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 <inttypes.h>
+/*
+ * 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__ */

+ 2951 - 0
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;
+}

+ 219 - 0
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 <hal.h>
+#include <dma/dmad.h>
+#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__ */

+ 2662 - 0
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;
+}

+ 927 - 0
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 <hal.h>
+
+/*****************************************************************************
+ * 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__ */

+ 1 - 0
bsp/AE210P/driver/ssp/Kbuild

@@ -0,0 +1 @@
+lib-${CONFIG_FTSSP010}		:= sspd_ac97.o sspd_rts.o

+ 300 - 0
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;
+	}
+}

+ 444 - 0
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__ */

+ 456 - 0
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;
+}

+ 199 - 0
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__ */

+ 2 - 0
bsp/AE210P/driver/uart/Kbuild

@@ -0,0 +1,2 @@
+lib-y		:=
+lib-y		+= uart.o

+ 143 - 0
bsp/AE210P/driver/uart/uart.c

@@ -0,0 +1,143 @@
+#include <nds32_intrinsic.h>
+
+#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;
+}
+

+ 17 - 0
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__ */

+ 80 - 0
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__ */

+ 1362 - 0
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__ */

+ 426 - 0
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

+ 54 - 0
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);
+}

+ 23 - 0
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

+ 49 - 0
bsp/AE210P/readme/readme.txt

@@ -0,0 +1,49 @@
+E-Mail : Archer Zhang <archer.zhang@wh-mx.com>
+
+******************************
+文件(夹)添加和修改
+******************************
+[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 <stddef.h> // 添加两个头文件包含
+	#include <string.h>
+	#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
+
+

+ 138 - 0
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);
+}

+ 199 - 0
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
+
+// <bool name="RT_USING_COMPONENTS_INIT" description="Using RT-Thread components initialization" default="true" />
+#define RT_USING_COMPONENTS_INIT
+
+/* SECTION: Device System */
+/* Using Device System */
+#define RT_USING_DEVICE
+// <bool name="RT_USING_DEVICE_IPC" description="Using device communication" default="true" />
+#define RT_USING_DEVICE_IPC
+// <bool name="RT_USING_SERIAL" description="Using Serial" default="true" />
+#define RT_USING_SERIAL
+
+/* SECTION: Console options */
+#define RT_USING_CONSOLE
+//#define RT_KPRINTF
+/* the buffer size of console*/
+#define RT_CONSOLEBUF_SIZE 260
+// <string name="RT_CONSOLE_DEVICE_NAME" description="The device name for console" default="uart1" />
+#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 */
+
+// <bool name="RT_USING_CMSIS_OS" description="Using CMSIS OS API" default="true" />
+// #define RT_USING_CMSIS_OS
+// <bool name="RT_USING_RTT_CMSIS" description="Using CMSIS in RTT" default="true" />
+#define RT_USING_RTT_CMSIS
+// <bool name="RT_USING_BSP_CMSIS" description="Using CMSIS in BSP" default="true" />
+// #define RT_USING_BSP_CMSIS
+
+#endif

+ 197 - 0
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 <nds32_init.inc>
+#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 <nds32_init.inc>
+
+	!*************************** 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
+

+ 113 - 0
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 <rthw.h>
+#include <rtthread.h>
+
+#ifdef  RT_USING_COMPONENTS_INIT
+#include <components.h>
+#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;
+//}
+
+/*@}*/

+ 188 - 0
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

+ 221 - 0
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 <rtthread.h>
+
+#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