提交 6605b65e 编写于 作者: L liang yongxiang

[bsp] remove AE210P bsp

上级 46b9be60
#************************************************************
# 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
Andes Maintainer: **It's a very early and draft porting yet.**
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,如下
```c
#if !(defined(__GNUC__) && defined(__x86_64__))
//typedef unsigned int size_t; // 注释这个typedef
#include <stddef.h> // 添加两个头文件包含
#include <string.h>
#else
```
4. 由于串口未使用中断接收,而是使用了查询接收,所以修改了shell.c文件,如下
```c
a. Line316317
//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. Line326,注释该行
// if (rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER) != RT_EOK) continue;
c. Line553,添加CPU占用的释放
rt_thread_delay(1); // 或者rt-schedule();
```
## 工程管理
1. 该工程使用Makefile管理,Makefile即文件AE210P/Makefile。编译如下:
```bash
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
/*
* 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;
}
/*@}*/
/*
* 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);
}
/*@}*/
/*
* 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__ */
#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);
}
/*****************************************************************************
*
* 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__ */
/* 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");
USER_SECTIONS FSymTab
USER_SECTIONS VSymTab
USER_SECTIONS .rti_fn.0
USER_SECTIONS .rti_fn.0.end
USER_SECTIONS .rti_fn.1
USER_SECTIONS .rti_fn.1.end
USER_SECTIONS .rti_fn.2
USER_SECTIONS .rti_fn.2.end
USER_SECTIONS .rti_fn.3
USER_SECTIONS .rti_fn.3.end
USER_SECTIONS .rti_fn.4
USER_SECTIONS .rti_fn.4.end
USER_SECTIONS .rti_fn.5
USER_SECTIONS .rti_fn.5.end
USER_SECTIONS .rti_fn.6
USER_SECTIONS .rti_fn.6.end
USER_SECTIONS .rti_fn.7
USER_SECTIONS .rti_fn.7.end
FLASH1 0x0
{
ROM 0x0 0x80000 ; EILM_SIZE <= 512KB
{
* (+RO)
. = ALIGN(4);
ADDR __fsymtab_start
* KEEP( FSymTab )
. = ALIGN(4);
ADDR __fsymtab_end
. = ALIGN(4);
ADDR __vsymtab_start
* KEEP( VSymTab )
. = ALIGN(4);
ADDR __vsymtab_end
. = ALIGN(4);
ADDR __rt_init_start
* KEEP( .rti_fn.0 )
* KEEP( .rti_fn.0.end )
* KEEP( .rti_fn.1 )
* KEEP( .rti_fn.1.end )
* KEEP( .rti_fn.2 )
* KEEP( .rti_fn.2.end )
* KEEP( .rti_fn.3 )
* KEEP( .rti_fn.3.end )
* KEEP( .rti_fn.4 )
* KEEP( .rti_fn.4.end )
* KEEP( .rti_fn.5 )
* KEEP( .rti_fn.5.end )
* KEEP( .rti_fn.6 )
* KEEP( .rti_fn.6.end )
* KEEP( .rti_fn.7 )
* KEEP( .rti_fn.7.end )
. = ALIGN(4);
ADDR __rt_init_end
}
; RAM 0x200000 0x80000 ; EDLM_SIZE <= 512KB
RAM 0x200000 0x50000 ; EDLM_SIZE <= 320KB
{
LOADADDR NEXT __rw_lma_start
ADDR NEXT __rw_vma_start
*(+RW)
LOADADDR NEXT __rw_lma_end
*(+ZI)
; STACK = 0x27fff8 ; 512KB
STACK = 0x24fff8 ; 320KB
}
}
\ No newline at end of file
/*****************************************************************************
*
* 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__ */
/*****************************************************************************
*
* 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__ */
/*
* 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 */
}
/*
* 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__"
#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
#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
}
#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__ */
#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"
#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__ */
/*****************************************************************************
*
* 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;
}
/*****************************************************************************
*
* 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__ */
#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;
}
#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__
lib-${CONFIG_FB_FTLCDC100} += font.o lcd.o
#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++;
}
}
#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__ */
#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;
}
#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__ */
#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;
}
#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
lib-y +=
lib-y += sdd.o
lib-y += sdd_sd.o
/*****************************************************************************
*
* 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__ */
/*****************************************************************************
*
* 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;
}
/*****************************************************************************
*
* 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__ */
/*****************************************************************************
*
* 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;
}
/*****************************************************************************
*
* 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__ */
lib-${CONFIG_FTSSP010} := sspd_ac97.o sspd_rts.o
#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;
}
}
/*****************************************************************************
*
* 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__ */
/*****************************************************************************
*
* 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;
}
/*****************************************************************************
*
* 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__ */
#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;
}
#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__ */
#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__ */
/*
* 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__ */
#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
#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);
}
#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
#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);
}
/* 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
!********************************************************************************************************
!
! (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
/*
* 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;
//}
/*@}*/
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册