[bsp] add k230

This commit is contained in:
heyuanjie87 2024-09-26 10:34:04 +08:00 committed by GitHub
parent 633d203fa6
commit caac564854
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 4495 additions and 0 deletions

1360
bsp/k230/.config Normal file

File diff suppressed because it is too large Load Diff

9
bsp/k230/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
#Build & install directories
build/
packages/
install/
rtthread.*
__pycache__
.config.old

46
bsp/k230/Kconfig Normal file
View File

@ -0,0 +1,46 @@
mainmenu "RT-Thread Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config RTT_DIR
string
option env="RTT_ROOT"
default "../../rt-thread"
config PKGS_DIR
string
option env="PKGS_ROOT"
default "packages"
source "$RTT_DIR/Kconfig"
source "$PKGS_DIR/Kconfig"
rsource "board/Kconfig"
config BOARD_fpgac908
bool
select ARCH_RISCV64
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select RT_USING_CACHE
select ARCH_MM_MMU
select ARCH_RISCV_FPU_D
select ARCH_REMAP_KERNEL if RT_USING_SMART
default y
config __STACKSIZE__
int "stack size for interrupt"
default 4096
config C908_PLIC_PHY_ADDR
int "PLIC base address"
default 0xF00000000
config BSP_ROOTFS_TYPE_CROMFS
bool "Use CROMFS as ROOTFS"
select RT_USING_DFS_CROMFS
select PKG_USING_ZLIB
select PKG_USING_ZLIB_LATEST_VERSION
default y

38
bsp/k230/README.md Normal file
View File

@ -0,0 +1,38 @@
# rt-smart canaan porting
## 下载依赖的软件包
在软件包无需变更的情况下只须执行一次
```
source ~/.env/env.sh
pkgs --update
```
## 将根文件系统编译进内核
为了方便测试这里将根文件系统制作成CROMFS格式转换成C代码编译进内核。
1. 在 https://github.com/RT-Thread/userapps 页面下载riscv64预编译镜像
2. 解压后将其中的ext4.img挂载到一个目录中
```
sudo mount ext4.img dir
```
3. 删除其中一些不必要的文件以减小内核体积
```
du -ha # 查看文件大小
sudo rm -rf dir/www dir/usr/share/fonts dir/tc
```
4. 生成cromfs文件
工具位于 https://github.com/RT-Thread/userapps/tree/main/tools/cromfs
```
sudo ./cromfs-tool-x64 dir crom.img ./ # 将生成的cromfs_data.c放入applications目录
```
## 编译
```
export RTT_EXEC_PATH=/mnt/e/tools/riscv64gc/bin # 你自己的编译器路径
scons -j8
```

14
bsp/k230/SConscript Normal file
View File

@ -0,0 +1,14 @@
# for module compiling
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

37
bsp/k230/SConstruct Normal file
View File

@ -0,0 +1,37 @@
import os
import sys
import rtconfig
from rtconfig import RTT_ROOT
import sys
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
stack_size = 4096
stack_lds = open('link_stacksize.lds', 'w')
if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__')
stack_lds.write('__STACKSIZE__ = %d;' % stack_size)
stack_lds.close()
# make a building
DoBuilding(TARGET, objs)

View File

@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <rtthread.h>
#include <rthw.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
printf("Hello RISC-V\n");
return 0;
}

View File

@ -0,0 +1,58 @@
#include <rtthread.h>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
rt_weak uint8_t *cromfs_get_partition_data(uint32_t *len)
{
return RT_NULL;
}
static int mnt_cromfs(void)
{
uint32_t length = 0;
uint8_t *data = cromfs_get_partition_data(&length);
int ret = -1;
if (data && length)
{
ret = dfs_mount(NULL, "/", "crom", 0, data);
}
return ret;
}
int mnt_init(void)
{
rt_err_t ret;
ret = mnt_cromfs();
if (ret != RT_EOK)
{
rt_kprintf("CromFS mount failed!\n");
return ret;
}
mkdir("/dev/shm", 0x777);
if (dfs_mount(RT_NULL, "/dev/shm", "tmp", 0, 0) != 0)
{
rt_kprintf("Dir /dev/shm mount failed!\n");
}
#ifdef BSP_SD_SDIO_DEV
while (mmcsd_wait_cd_changed(100) != MMCSD_HOST_PLUGED)
;
if (dfs_mount(BSP_SD_MNT_DEVNAME, "/mnt", "elm", 0, 0) != 0)
{
rt_kprintf("Dir /mnt mount failed!\n");
}
#endif
rt_kprintf("file system initialization done!\n");
return 0;
}
INIT_ENV_EXPORT(mnt_init);
#endif

38
bsp/k230/board/Kconfig Normal file
View File

@ -0,0 +1,38 @@
menu "Drivers Configuration"
menuconfig BSP_USING_SDIO
bool "Enable SDIO"
select RT_USING_SDIO
default n
if BSP_USING_SDIO
config BSP_USING_SDIO0
bool "Enable SDIO0"
default n
if BSP_USING_SDIO0
config BSP_SDIO0_EMMC
bool "Enable eMMC"
default y
config BSP_SDIO0_1V8
bool "Enable 1.8V"
default y
endif
config BSP_USING_SDIO1
bool "Enable SDIO1"
default y
config BSP_SD_SDIO_DEV
int "SDIO device SdCard on"
range 0 1
default 1
config BSP_SD_MNT_DEVNAME
string "The name of the SD-BlkDev to be mounted"
default "sd13"
endif
endmenu

19
bsp/k230/board/SConscript Normal file
View File

@ -0,0 +1,19 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
objs = [group]
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

118
bsp/k230/board/board.c Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "tick.h"
#include "drv_uart.h"
#include <sbi.h>
#ifdef RT_USING_SMART
#include <mmu.h>
#include "page.h"
/* respect to boot loader, must be 0xFFFFFFC000200000 */
RT_STATIC_ASSERT(kmem_region, KERNEL_VADDR_START == 0xFFFFFFC000220000);
rt_region_t init_page_region = {(rt_size_t)RT_HW_PAGE_START, (rt_size_t)RT_HW_PAGE_END};
extern size_t MMUTable[];
struct mem_desc platform_mem_desc[] = {
{KERNEL_VADDR_START, (rt_size_t)RT_HW_PAGE_END - 1, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM},
};
#define NUM_MEM_DESC (sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]))
#endif /* RT_USING_SMART */
#ifndef ARCH_REMAP_KERNEL
#define IOREMAP_VEND USER_VADDR_START
#else
#define IOREMAP_VEND 0ul
#endif
//初始化BSS节区
void init_bss(void)
{
unsigned int *dst;
dst = &__bss_start;
while (dst < &__bss_end)
{
*dst++ = 0;
}
}
static void __rt_assert_handler(const char *ex_string, const char *func, rt_size_t line)
{
rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line);
asm volatile("ebreak":::"memory");
}
//BSP的C入口
void primary_cpu_entry(void)
{
//关中断
rt_hw_interrupt_disable();
rt_assert_set_hook(__rt_assert_handler);
//启动RT-Thread Smart内核
entry();
}
#define IOREMAP_SIZE (1ul << 30)
//这个初始化程序由内核主动调用,此时调度器还未启动,因此在此不能使用依赖线程上下文的函数
void rt_hw_board_init(void)
{
#ifdef RT_USING_SMART
/* init data structure */
rt_hw_mmu_map_init(&rt_kernel_space, (void *)(IOREMAP_VEND - IOREMAP_SIZE), IOREMAP_SIZE, (rt_size_t *)MMUTable, PV_OFFSET);
/* init page allocator */
rt_page_init(init_page_region);
/* setup region, and enable MMU */
rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, NUM_MEM_DESC);
#endif
#ifdef RT_USING_HEAP
/* initialize memory system */
rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
#endif
/* initalize interrupt */
rt_hw_interrupt_init();
/* initialize hardware interrupt */
rt_hw_uart_init();
rt_hw_tick_init();
#ifdef RT_USING_CONSOLE
/* set console device */
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif /* RT_USING_CONSOLE */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
}
void rt_hw_cpu_reset(void)
{
sbi_shutdown();
while(1);
}
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine);

33
bsp/k230/board/board.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
*/
#ifndef BOARD_H__
#define BOARD_H__
#include <rtconfig.h>
extern unsigned int __sram_size;
extern unsigned int __sram_base;
extern unsigned int __sram_end;
#define RAM_END (rt_size_t)((void *)&__sram_end)
extern unsigned int __bss_start;
extern unsigned int __bss_end;
#define RT_HW_HEAP_BEGIN ((void *)&__bss_end)
#define RT_HW_HEAP_END ((void *)(((rt_size_t)RT_HW_HEAP_BEGIN) + 8 * 1024 * 1024))
#define RT_HW_PAGE_START ((void *)((rt_size_t)RT_HW_HEAP_END + sizeof(rt_size_t)))
#define RT_HW_PAGE_END ((void *)(RAM_END))
void rt_hw_board_init(void);
void rt_init_user_mem(struct rt_thread *thread, const char *name, unsigned long *entry);
#endif

View File

@ -0,0 +1,21 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = []
CPPPATH = [cwd]
src += Glob('*.c')
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
objs = [group]
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

View File

@ -0,0 +1,19 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Interdrv', src, depend = [''], CPPPATH = CPPPATH)
objs = [group]
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

View File

@ -0,0 +1,19 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Sdio', src, depend = ['BSP_USING_SDIO'], CPPPATH = CPPPATH)
objs = [group]
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

View File

@ -0,0 +1,930 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-10-10 Tanek first version
* 2021-07-07 linzhenxing add sd card drivers in mmu
* 2021-07-14 linzhenxing add emmc
*/
#include <rtthread.h>
#include <rthw.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_sdhci.h"
#include "riscv_io.h"
#include <string.h>
#include <ioremap.h>
#include <cache.h>
#ifdef RT_USING_SDIO
#define DBG_TAG "drv_sdhci"
#ifdef RT_SDIO_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_WARNING
#endif /* RT_SDIO_DEBUG */
#include <rtdbg.h>
#if defined(BSP_USING_SDIO0) || defined(BSP_USING_SDIO1)
#define SDHCI_SDMA_ENABLE
#define CACHE_LINESIZE (64)
#define BIT(x) (1 << x)
#define DWC_MSHC_PTR_VENDOR1 0x500
#define MSHC_CTRL_R (DWC_MSHC_PTR_VENDOR1 + 0x08)
#define EMMC_CTRL_R (DWC_MSHC_PTR_VENDOR1 + 0x2c)
#define SDHCI_VENDER_AT_CTRL_REG (DWC_MSHC_PTR_VENDOR1 + 0x40)
#define SDHCI_VENDER_AT_STAT_REG (DWC_MSHC_PTR_VENDOR1 + 0x44)
#define SDHCI_TUNE_CLK_STOP_EN_MASK BIT(16)
#define SDHCI_TUNE_SWIN_TH_VAL_LSB (24)
#define SDHCI_TUNE_SWIN_TH_VAL_MASK (0xFF)
#define CARD_IS_EMMC 0
#define EMMC_RST_N 2
#define EMMC_RST_N_OE 3
#define DWC_MSHC_PTR_PHY_REGS 0x300
#define DWC_MSHC_PHY_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x0)
#define PAD_SN_LSB 20
#define PAD_SN_MASK 0xF
#define PAD_SN_DEFAULT ((0x8 & PAD_SN_MASK) << PAD_SN_LSB)
#define PAD_SP_LSB 16
#define PAD_SP_MASK 0xF
#define PAD_SP_DEFAULT ((0x9 & PAD_SP_MASK) << PAD_SP_LSB)
#define PHY_PWRGOOD BIT(1)
#define PHY_RSTN BIT(0)
#define DWC_MSHC_CMDPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x4)
#define DWC_MSHC_DATPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x6)
#define DWC_MSHC_CLKPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x8)
#define DWC_MSHC_STBPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0xA)
#define DWC_MSHC_RSTNPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0xC)
#define TXSLEW_N_LSB 9
#define TXSLEW_N_MASK 0xF
#define TXSLEW_P_LSB 5
#define TXSLEW_P_MASK 0xF
#define WEAKPULL_EN_LSB 3
#define WEAKPULL_EN_MASK 0x3
#define RXSEL_LSB 0
#define RXSEL_MASK 0x3
#define DWC_MSHC_COMMDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x1C)
#define DWC_MSHC_SDCLKDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x1D)
#define DWC_MSHC_SDCLKDL_DC (DWC_MSHC_PTR_PHY_REGS + 0x1E)
#define DWC_MSHC_SMPLDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x20)
#define DWC_MSHC_ATDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x21)
#define DWC_MSHC_PHY_PAD_SD_CLK \
((1 << TXSLEW_N_LSB) | (3 << TXSLEW_P_LSB) | (0 << WEAKPULL_EN_LSB) | (2 << RXSEL_LSB))
#define DWC_MSHC_PHY_PAD_SD_DAT \
((1 << TXSLEW_N_LSB) | (3 << TXSLEW_P_LSB) | (1 << WEAKPULL_EN_LSB) | (2 << RXSEL_LSB))
#define DWC_MSHC_PHY_PAD_SD_STB \
((1 << TXSLEW_N_LSB) | (3 << TXSLEW_P_LSB) | (2 << WEAKPULL_EN_LSB) | (2 << RXSEL_LSB))
#define DWC_MSHC_PHY_PAD_EMMC_CLK \
((2 << TXSLEW_N_LSB) | (2 << TXSLEW_P_LSB) | (0 << WEAKPULL_EN_LSB) | (1 << RXSEL_LSB))
#define DWC_MSHC_PHY_PAD_EMMC_DAT \
((2 << TXSLEW_N_LSB) | (2 << TXSLEW_P_LSB) | (1 << WEAKPULL_EN_LSB) | (1 << RXSEL_LSB))
#define DWC_MSHC_PHY_PAD_EMMC_STB \
((2 << TXSLEW_N_LSB) | (2 << TXSLEW_P_LSB) | (2 << WEAKPULL_EN_LSB) | (1 << RXSEL_LSB))
static struct sdhci_host* sdhci_host0;
static struct sdhci_host* sdhci_host1;
static inline void sdhci_writel(struct sdhci_host* host, uint32_t val, int reg)
{
writel(val, (void*)host->mapbase + reg);
}
static inline void sdhci_writew(struct sdhci_host* host, uint16_t val, int reg)
{
writew((uint16_t)val, (void*)host->mapbase + reg);
}
static inline void sdhci_writeb(struct sdhci_host* host, uint8_t val, int reg)
{
writeb((uint8_t)val, (void*)host->mapbase + reg);
}
static inline uint32_t sdhci_readl(struct sdhci_host* host, int reg)
{
return (uint32_t)readl((void*)host->mapbase + reg);
}
static inline uint16_t sdhci_readw(struct sdhci_host* host, int reg)
{
return (uint16_t)readw((void*)host->mapbase + reg);
}
static inline uint8_t sdhci_readb(struct sdhci_host* host, int reg)
{
return (uint8_t)readb((void*)host->mapbase + reg);
}
static void emmc_reg_display(struct sdhci_host* host)
{
rt_kprintf("SD_MASA_R:%x\n", sdhci_readl(host, SDHCI_DMA_ADDRESS));
rt_kprintf("BLCOKSIZE_R:%x\n", sdhci_readw(host, SDHCI_BLOCK_SIZE));
rt_kprintf("BLOCKCOUNT_R:%x\n", sdhci_readw(host, SDHCI_BLOCK_COUNT));
rt_kprintf("ARGUMENT_R:%x\n", sdhci_readl(host, SDHCI_ARGUMENT));
rt_kprintf("XFER_MODE_R:%x\n", sdhci_readw(host, SDHCI_TRANSFER_MODE));
rt_kprintf("CMD_R:%x\n", sdhci_readw(host, SDHCI_COMMAND));
rt_kprintf("RESP0_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE));
rt_kprintf("RESP1_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE + 4));
rt_kprintf("RESP2_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE + 8));
rt_kprintf("RESP3_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE + 12));
rt_kprintf("BUF_DATA_R:%x\n", sdhci_readl(host, SDHCI_BUFFER));
rt_kprintf("PSTATE_REG_R:%x\n", sdhci_readl(host, SDHCI_PRESENT_STATE));
rt_kprintf("HOST_CTL_R:%x\n", sdhci_readb(host, SDHCI_HOST_CONTROL));
rt_kprintf("PWR_CTRL_R:%x\n", sdhci_readb(host, SDHCI_POWER_CONTROL));
rt_kprintf("BGAP_CTRL_R:%x\n", sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
rt_kprintf("WUP_CTRL_R:%x\n", sdhci_readb(host, SDHCI_WAKE_UP_CONTROL));
rt_kprintf("CLK_CTRL_R:%x\n", sdhci_readw(host, SDHCI_CLOCK_CONTROL));
rt_kprintf("TOUT_CTRL_R:%x\n", sdhci_readb(host, SDHCI_TIMEOUT_CONTROL));
rt_kprintf("SW_RSR_R:%x\n", sdhci_readb(host, SDHCI_SOFTWARE_RESET));
rt_kprintf("NORMAL_INT_STAT_R:%x\n", sdhci_readw(host, SDHCI_INT_STATUS));
rt_kprintf("ERROR_INT_STAT_R:%x\n", sdhci_readw(host, SDHCI_INT_STATUS + 2));
rt_kprintf("NORMAL_INT_STAT_EN_R:%x\n", sdhci_readw(host, SDHCI_INT_ENABLE));
rt_kprintf("ERROR_INT_STAT_EN_R:%x\n", sdhci_readw(host, SDHCI_INT_ENABLE + 2));
rt_kprintf("NORNAL_INT_SIGNAL_EN_R:%x\n", sdhci_readw(host, SDHCI_SIGNAL_ENABLE));
rt_kprintf("ERROR_INT_SIGNAL_EN_R:%x\n", sdhci_readw(host, SDHCI_SIGNAL_ENABLE + 2));
rt_kprintf("AUTO_CMD_STAT_R:%x\n", sdhci_readw(host, SDHCI_AUTO_CMD_STATUS));
rt_kprintf("HOST_CTRL2_R:%x\n", sdhci_readw(host, SDHCI_HOST_CONTROL2));
rt_kprintf("CAPABILITIES1_R:%x\n", sdhci_readl(host, SDHCI_CAPABILITIES));
rt_kprintf("CAPABILITIES2_R:%x\n", sdhci_readl(host, SDHCI_CAPABILITIES_1));
rt_kprintf("FORCE_AUTO_CMD_STAT_R:%x\n", sdhci_readw(host, SDHCI_MAX_CURRENT));
rt_kprintf("FORCE_ERROR_INT_STAT_R:%x\n", sdhci_readw(host, SDHCI_SET_ACMD12_ERROR));
rt_kprintf("AMDA_ERR_STAT_STAT_R:%x\n", sdhci_readl(host, SDHCI_ADMA_ERROR));
rt_kprintf("AMDA_SA_LOW_STAT_R:%x\n", sdhci_readl(host, SDHCI_ADMA_ADDRESS));
rt_kprintf("AMDA_SA_HIGH_STAT_R:%x\n", sdhci_readl(host, SDHCI_ADMA_ADDRESS_HI));
}
static inline void delay_1k(unsigned int uicnt)
{
int i, j;
for (i = 0; i < uicnt; i++)
for (j = 0; j < 1000; j++)
asm("nop");
}
static void dwcmshc_phy_1_8v_init(struct sdhci_host* host)
{
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_DAT, DWC_MSHC_CMDPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_DAT, DWC_MSHC_DATPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_CLK, DWC_MSHC_CLKPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_STB, DWC_MSHC_STBPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_DAT, DWC_MSHC_RSTNPAD_CNFG);
}
static void dwcmshc_phy_3_3v_init(struct sdhci_host* host)
{
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_DAT, DWC_MSHC_CMDPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_DAT, DWC_MSHC_DATPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_CLK, DWC_MSHC_CLKPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_STB, DWC_MSHC_STBPAD_CNFG);
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_DAT, DWC_MSHC_RSTNPAD_CNFG);
}
static void dwcmshc_phy_delay_config(struct sdhci_host* host)
{
sdhci_writeb(host, 1, DWC_MSHC_COMMDL_CNFG);
if (host->tx_delay_line > 256) {
LOG_E("host%d: tx_delay_line err\n", host->index);
} else if (host->tx_delay_line > 128) {
sdhci_writeb(host, 0x1, DWC_MSHC_SDCLKDL_CNFG);
sdhci_writeb(host, host->tx_delay_line - 128, DWC_MSHC_SDCLKDL_DC);
} else {
sdhci_writeb(host, 0x0, DWC_MSHC_SDCLKDL_CNFG);
sdhci_writeb(host, host->tx_delay_line, DWC_MSHC_SDCLKDL_DC);
}
sdhci_writeb(host, host->rx_delay_line, DWC_MSHC_SMPLDL_CNFG);
sdhci_writeb(host, 0xc, DWC_MSHC_ATDL_CNFG);
sdhci_writel(host, (sdhci_readl(host, SDHCI_VENDER_AT_CTRL_REG) | BIT(16) | BIT(17) | BIT(19) | BIT(20)), SDHCI_VENDER_AT_CTRL_REG);
sdhci_writel(host, 0x0, SDHCI_VENDER_AT_STAT_REG);
}
static int dwcmshc_phy_init(struct sdhci_host* host)
{
uint32_t reg;
uint32_t timeout = 15000;
/* reset phy */
sdhci_writew(host, 0, DWC_MSHC_PHY_CNFG);
/* Disable the clock */
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
if (host->io_fixed_1v8) {
uint32_t data = sdhci_readw(host, SDHCI_HOST_CONTROL2);
data |= SDHCI_CTRL_VDD_180;
sdhci_writew(host, data, SDHCI_HOST_CONTROL2);
dwcmshc_phy_1_8v_init(host);
} else {
dwcmshc_phy_3_3v_init(host);
}
dwcmshc_phy_delay_config(host);
/* Wait max 150 ms */
while (1) {
reg = sdhci_readl(host, DWC_MSHC_PHY_CNFG);
if (reg & PHY_PWRGOOD)
break;
if (!timeout) {
return -1;
}
timeout--;
delay_1k(1);
}
reg = PAD_SN_DEFAULT | PAD_SP_DEFAULT;
sdhci_writel(host, reg, DWC_MSHC_PHY_CNFG);
/* de-assert the phy */
reg |= PHY_RSTN;
sdhci_writel(host, reg, DWC_MSHC_PHY_CNFG);
return 0;
}
static void sdhci_reset(struct sdhci_host* host, uint8_t mask)
{
unsigned long timeout;
/* Wait max 100 ms */
timeout = 100;
sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
if (timeout == 0) {
LOG_E("%s: Reset 0x%x never completed.\n",
__func__, (int)mask);
return;
}
timeout--;
delay_1k(1);
}
if (mask == SDHCI_RESET_ALL) {
if (host->index == 0) {
uint16_t emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
if (host->is_emmc_card)
emmc_ctl |= (1 << CARD_IS_EMMC);
else
emmc_ctl &= ~(1 << CARD_IS_EMMC);
sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
}
if (host->have_phy)
dwcmshc_phy_init(host);
else
sdhci_writeb(host, host->mshc_ctrl_r, MSHC_CTRL_R);
}
}
static uint32_t sdhci_get_present_status_flag(struct sdhci_host* sdhci_host)
{
return sdhci_readl(sdhci_host, SDHCI_PRESENT_STATE);
}
static uint32_t sdhci_get_int_status_flag(struct sdhci_host* sdhci_host)
{
return sdhci_readl(sdhci_host, SDHCI_INT_STATUS);
}
static void sdhci_clear_int_status_flag(struct sdhci_host* sdhci_host, uint32_t mask)
{
sdhci_writel(sdhci_host, mask, SDHCI_INT_STATUS);
}
static void sdhic_error_recovery(struct sdhci_host* sdhci_host)
{
uint32_t status;
/* get host present status */
status = sdhci_get_present_status_flag(sdhci_host);
/* check command inhibit status flag */
if ((status & SDHCI_CMD_INHIBIT) != 0U) {
/* reset command line */
sdhci_reset(sdhci_host, SDHCI_RESET_CMD);
}
/* check data inhibit status flag */
if ((status & SDHCI_DATA_INHIBIT) != 0U) {
/* reset data line */
sdhci_reset(sdhci_host, SDHCI_RESET_DATA);
}
}
static rt_err_t sdhci_receive_command_response(struct sdhci_host* sdhci_host, struct sdhci_command* command)
{
if (command->responseType == card_response_type_r2) {
/* CRC is stripped so we need to do some shifting. */
for (int i = 0; i < 4; i++) {
command->response[3 - i] = sdhci_readl(sdhci_host, SDHCI_RESPONSE + (3 - i) * 4) << 8;
if (i != 3)
command->response[3 - i] |= sdhci_readb(sdhci_host, SDHCI_RESPONSE + (3 - i) * 4 - 1);
}
} else {
command->response[0] = sdhci_readl(sdhci_host, SDHCI_RESPONSE);
}
/* check response error flag */
if ((command->responseErrorFlags != 0U) && ((command->responseType == card_response_type_r1) || (command->responseType == card_response_type_r1b) || (command->responseType == card_response_type_r6) || (command->responseType == card_response_type_r5))) {
if (((command->responseErrorFlags) & (command->response[0U])) != 0U)
return -1; // kStatus_USDHC_SendCommandFailed;
}
return 0;
}
static void sdhci_send_command(struct sdhci_host* sdhci_host, struct sdhci_command* command, rt_bool_t enDMA)
{
RT_ASSERT(RT_NULL != command);
uint32_t cmd_r, xfer_mode;
struct sdhci_data* sdhci_data = sdhci_host->sdhci_data;
cmd_r = SDHCI_MAKE_CMD(command->index, command->flags);
if (sdhci_data != RT_NULL) {
#ifdef SDHCI_SDMA_ENABLE
rt_ubase_t start_addr, dma_addr;
if (sdhci_data->rxData)
start_addr = (rt_ubase_t)((uint8_t*)sdhci_data->rxData);
else
start_addr = (rt_ubase_t)((uint8_t*)sdhci_data->txData);
rt_hw_cpu_dcache_clean((void*)start_addr, sdhci_data->blockSize * sdhci_data->blockCount);
command->flags2 |= sdhci_enable_dma_flag;
dma_addr = rt_kmem_v2p((void*)start_addr);
sdhci_writel(sdhci_host, dma_addr, SDHCI_DMA_ADDRESS);
#endif
sdhci_writew(sdhci_host, SDHCI_MAKE_BLKSZ(7, sdhci_data->blockSize), SDHCI_BLOCK_SIZE);
sdhci_writew(sdhci_host, sdhci_data->blockCount, SDHCI_BLOCK_COUNT);
}
xfer_mode = command->flags2 & 0x1ff;
sdhci_writew(sdhci_host, xfer_mode, SDHCI_TRANSFER_MODE);
sdhci_writel(sdhci_host, command->argument, SDHCI_ARGUMENT);
sdhci_writew(sdhci_host, cmd_r, SDHCI_COMMAND);
}
static rt_err_t sdhci_wait_command_done(struct sdhci_host* sdhci_host, struct sdhci_command* command, rt_bool_t executeTuning)
{
RT_ASSERT(RT_NULL != command);
rt_uint32_t event;
/* tuning cmd do not need to wait command done */
if (executeTuning)
return 0;
/* Wait command complete or USDHC encounters error. */
rt_event_recv(&sdhci_host->event, SDHCI_INT_ERROR | SDHCI_INT_RESPONSE,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
if (event & SDHCI_INT_ERROR) {
LOG_D("%s: Error detected in status(0x%X)!\n", __func__, sdhci_host->error_code);
return -1;
}
return sdhci_receive_command_response(sdhci_host, command);
}
static rt_err_t sdhci_transfer_data_blocking(struct sdhci_host* sdhci_host, struct sdhci_data* data, rt_bool_t enDMA)
{
#ifdef SDHCI_SDMA_ENABLE
rt_err_t err;
rt_uint32_t event;
while (1) {
err = rt_event_recv(&sdhci_host->event, SDHCI_INT_ERROR | SDHCI_INT_DATA_END | SDHCI_INT_DMA_END,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 1000, &event);
if (err == -RT_ETIMEOUT) {
rt_kprintf("%s: Transfer data timeout\n", __func__);
return -1;
}
if (event & SDHCI_INT_ERROR) {
LOG_D("%s: Error detected in status(0x%X)!\n", __func__, sdhci_host->error_code);
emmc_reg_display(sdhci_host);
return -1;
}
if (event & SDHCI_INT_DMA_END) {
sdhci_writel(sdhci_host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
sdhci_writel(sdhci_host, sdhci_readl(sdhci_host, SDHCI_DMA_ADDRESS), SDHCI_DMA_ADDRESS);
}
if (event & SDHCI_INT_DATA_END) {
if (data && data->rxData)
rt_hw_cpu_dcache_invalidate((void*)data->rxData, data->blockSize * data->blockCount);
return 0;
}
}
#else
uint32_t stat, rdy, mask, timeout, block;
block = 0;
timeout = 1000000;
rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
while (1) {
stat = sdhci_get_int_status_flag(sdhci_host);
if (stat & SDHCI_INT_ERROR) {
LOG_D("%s: Error detected in status(0x%X)!\n", __func__, stat);
emmc_reg_display(sdhci_host);
return -1;
}
if (stat & rdy) {
if (!(sdhci_readl(sdhci_host, SDHCI_PRESENT_STATE) & mask)) {
continue;
}
sdhci_clear_int_status_flag(sdhci_host, rdy);
if (data->rxData) {
for (int i = 0; i < data->blockSize / 4; i++)
data->rxData[i + block * data->blockSize] = sdhci_readl(sdhci_host, SDHCI_BUFFER);
} else {
for (int i = 0; i < data->blockSize / 4; i++)
sdhci_writel(sdhci_host, data->txData[i + block * data->blockSize], SDHCI_BUFFER);
}
block++;
if (block >= data->blockCount)
return 0;
}
if (timeout == 0) {
rt_kprintf("%s: Transfer data timeout\n", __func__);
return -1;
}
timeout--;
delay_1k(1);
}
#endif
}
static rt_err_t sdhci_set_transfer_config(struct sdhci_host* sdhci_host, struct sdhci_command* sdhci_command, struct sdhci_data* sdhci_data)
{
RT_ASSERT(sdhci_command);
/* Define the flag corresponding to each response type. */
switch (sdhci_command->responseType) {
case card_response_type_none:
break;
case card_response_type_r1: /* Response 1 */
case card_response_type_r5: /* Response 5 */
case card_response_type_r6: /* Response 6 */
case card_response_type_r7: /* Response 7 */
sdhci_command->flags |= (sdhci_cmd_resp_short | sdhci_enable_cmd_crc_flag | sdhci_enable_cmd_index_chk_flag);
break;
case card_response_type_r1b: /* Response 1 with busy */
case card_response_type_r5b: /* Response 5 with busy */
sdhci_command->flags |= (sdhci_cmd_resp_short_busy | sdhci_enable_cmd_crc_flag | sdhci_enable_cmd_index_chk_flag);
break;
case card_response_type_r2: /* Response 2 */
sdhci_command->flags |= (sdhci_cmd_resp_long | sdhci_enable_cmd_crc_flag);
break;
case card_response_type_r3: /* Response 3 */
case card_response_type_r4: /* Response 4 */
sdhci_command->flags |= (sdhci_cmd_resp_short);
break;
default:
break;
}
if (sdhci_command->type == card_command_type_abort) {
sdhci_command->flags |= sdhci_enable_command_type_abort;
} else if (sdhci_command->type == card_command_type_resume) {
sdhci_command->flags |= sdhci_enable_command_type_resume;
} else if (sdhci_command->type == card_command_type_suspend) {
sdhci_command->flags |= sdhci_enable_command_type_suspend;
} else if (sdhci_command->type == card_command_type_normal) {
sdhci_command->flags |= sdhci_enable_command_type_normal;
}
if (sdhci_data) {
sdhci_command->flags |= sdhci_enable_cmd_data_present_flag;
sdhci_command->flags2 |= sdhci_enable_block_count_flag;
if (sdhci_data->rxData) {
sdhci_command->flags2 |= sdhci_data_read_flag;
}
if (sdhci_data->blockCount > 1U) {
sdhci_command->flags2 |= (sdhci_multiple_block_flag);
/* auto command 12 */
if (sdhci_data->enableAutoCommand12) {
/* Enable Auto command 12. */
sdhci_command->flags2 |= sdhci_enable_auto_command12_flag;
}
/* auto command 23 */
if (sdhci_data->enableAutoCommand23) {
sdhci_command->flags2 |= sdhci_enable_auto_command23_flag;
}
}
}
return 0;
}
static rt_err_t sdhci_transfer_blocking(struct sdhci_host* sdhci_host)
{
RT_ASSERT(sdhci_host);
struct sdhci_command* sdhci_command = sdhci_host->sdhci_command;
struct sdhci_data* sdhci_data = sdhci_host->sdhci_data;
rt_bool_t enDMA = false;
int ret = RT_EOK;
/* Wait until command/data bus out of busy status. */
while (sdhci_get_present_status_flag(sdhci_host) & sdhci_command_inhibit_flag) {
}
while (sdhci_data && (sdhci_get_present_status_flag(sdhci_host) & sdhci_data_inhibit_flag)) {
}
sdhci_writel(sdhci_host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
ret = sdhci_set_transfer_config(sdhci_host, sdhci_command, sdhci_data);
if (ret != 0) {
return ret;
}
sdhci_writel(sdhci_host, sdhci_readl(sdhci_host, SDHCI_SIGNAL_ENABLE) |
SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_SIGNAL_ENABLE);
rt_event_control(&sdhci_host->event, RT_IPC_CMD_RESET, 0);
sdhci_send_command(sdhci_host, sdhci_command, enDMA);
/* wait command done */
ret = sdhci_wait_command_done(sdhci_host, sdhci_command, ((sdhci_data == RT_NULL) ? false : sdhci_data->executeTuning));
/* transfer data */
if ((sdhci_data != RT_NULL) && (ret == 0)) {
ret = sdhci_transfer_data_blocking(sdhci_host, sdhci_data, enDMA);
}
sdhci_writel(sdhci_host, sdhci_readl(sdhci_host, SDHCI_SIGNAL_ENABLE) &
~(SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK), SDHCI_SIGNAL_ENABLE);
sdhci_writel(sdhci_host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
sdhci_reset(sdhci_host, SDHCI_RESET_CMD);
sdhci_reset(sdhci_host, SDHCI_RESET_DATA);
return ret;
}
static void sdhci_init(struct sdhci_host* host)
{
sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_writeb(host, SDHCI_CTRL_HISPD, SDHCI_HOST_CONTROL);
sdhci_writeb(host, 0x7, SDHCI_TIMEOUT_CONTROL);
sdhci_writeb(host, SDHCI_POWER_ON | SDHCI_POWER_330, SDHCI_POWER_CONTROL);
sdhci_writew(host, SDHCI_CLOCK_INT_EN, SDHCI_CLOCK_CONTROL);
while ((sdhci_readw(host, SDHCI_CLOCK_CONTROL) & SDHCI_CLOCK_INT_STABLE) == 0)
;
sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_INT_ENABLE);
sdhci_writel(host, SDHCI_INT_CARD_INT, SDHCI_SIGNAL_ENABLE);
}
static void sdhci_irq(int vector, void* param)
{
struct sdhci_host* host = param;
uint32_t status = sdhci_get_int_status_flag(host);
if (status & (SDHCI_INT_ERROR | SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_RESPONSE)) {
host->error_code = (status >> 16) & 0xffff;
rt_event_send(&host->event, status & (SDHCI_INT_ERROR | SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_RESPONSE));
}
if (status & SDHCI_INT_CARD_INT)
sdio_irq_wakeup(host->host);
sdhci_clear_int_status_flag(host, status);
}
static void kd_mmc_request(struct rt_mmcsd_host* host, struct rt_mmcsd_req* req)
{
struct sdhci_host* mmcsd;
struct rt_mmcsd_cmd* cmd;
struct rt_mmcsd_data* data;
rt_err_t error;
struct sdhci_data sdhci_data = { 0 };
struct sdhci_command sdhci_command = { 0 };
RT_ASSERT(host != RT_NULL);
RT_ASSERT(req != RT_NULL);
mmcsd = (struct sdhci_host*)host->private_data;
RT_ASSERT(mmcsd != RT_NULL);
cmd = req->cmd;
RT_ASSERT(cmd != RT_NULL);
LOG_D("\tcmd->cmd_code: %02d, cmd->arg: %08x, cmd->flags: %08x --> ", cmd->cmd_code, cmd->arg, cmd->flags);
data = cmd->data;
sdhci_command.index = cmd->cmd_code;
sdhci_command.argument = cmd->arg;
if (cmd->cmd_code == STOP_TRANSMISSION)
sdhci_command.type = card_command_type_abort;
else
sdhci_command.type = card_command_type_normal;
switch (cmd->flags & RESP_MASK) {
case RESP_NONE:
sdhci_command.responseType = card_response_type_none;
break;
case RESP_R1:
sdhci_command.responseType = card_response_type_r1;
break;
case RESP_R1B:
sdhci_command.responseType = card_response_type_r1b;
break;
case RESP_R2:
sdhci_command.responseType = card_response_type_r2;
break;
case RESP_R3:
sdhci_command.responseType = card_response_type_r3;
break;
case RESP_R4:
sdhci_command.responseType = card_response_type_r4;
break;
case RESP_R6:
sdhci_command.responseType = card_response_type_r6;
break;
case RESP_R7:
sdhci_command.responseType = card_response_type_r7;
break;
case RESP_R5:
sdhci_command.responseType = card_response_type_r5;
break;
default:
RT_ASSERT(RT_NULL);
}
sdhci_command.flags = 0;
sdhci_command.flags2 = 0;
sdhci_command.responseErrorFlags = 0;
mmcsd->sdhci_command = &sdhci_command;
if (data) {
if (req->stop != RT_NULL)
sdhci_data.enableAutoCommand12 = true;
else
sdhci_data.enableAutoCommand12 = false;
sdhci_data.enableAutoCommand23 = false;
sdhci_data.blockSize = data->blksize;
sdhci_data.blockCount = data->blks;
if (data->flags == DATA_DIR_WRITE) {
sdhci_data.txData = data->buf;
sdhci_data.rxData = RT_NULL;
} else {
sdhci_data.rxData = data->buf;
sdhci_data.txData = RT_NULL;
}
#ifdef SDHCI_SDMA_ENABLE
uint32_t sz = sdhci_data.blockSize * sdhci_data.blockCount;
uint32_t pad = 0;
if (sz & (CACHE_LINESIZE - 1))
pad = (sz + (CACHE_LINESIZE - 1)) & ~(CACHE_LINESIZE - 1);
if (sdhci_data.rxData && (((uint64_t)(sdhci_data.rxData) & (CACHE_LINESIZE - 1)) || pad)) {
sdhci_data.rxData = rt_malloc_align(pad ? pad : sz, CACHE_LINESIZE);
} else if (((uint64_t)(sdhci_data.txData) & (CACHE_LINESIZE - 1)) || pad) {
sdhci_data.txData = rt_malloc_align(pad ? pad : sz, CACHE_LINESIZE);
rt_memcpy(sdhci_data.txData, data->buf, sz);
}
#endif
mmcsd->sdhci_data = &sdhci_data;
} else {
mmcsd->sdhci_data = RT_NULL;
}
error = sdhci_transfer_blocking(mmcsd);
#ifdef SDHCI_SDMA_ENABLE
if (data && sdhci_data.rxData && sdhci_data.rxData != data->buf) {
rt_memcpy(data->buf, sdhci_data.rxData, sdhci_data.blockSize * sdhci_data.blockCount);
rt_free_align(sdhci_data.rxData);
} else if (data && sdhci_data.txData && sdhci_data.txData != data->buf) {
rt_free_align(sdhci_data.txData);
}
#endif
if (error == -1) {
LOG_D(" ***USDHC_TransferBlocking error: %d*** --> \n", error);
cmd->err = -RT_ERROR;
}
if ((cmd->flags & RESP_MASK) == RESP_R2) {
cmd->resp[3] = sdhci_command.response[0];
cmd->resp[2] = sdhci_command.response[1];
cmd->resp[1] = sdhci_command.response[2];
cmd->resp[0] = sdhci_command.response[3];
LOG_D(" resp 0x%08X 0x%08X 0x%08X 0x%08X\n",
cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
} else {
cmd->resp[0] = sdhci_command.response[0];
LOG_D(" resp 0x%08X\n", cmd->resp[0]);
}
mmcsd_req_complete(host);
}
static void kd_mmc_clock_freq_change(struct sdhci_host* host, uint32_t clock)
{
uint32_t div, val;
val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
val &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_PROG_CLOCK_MODE);
sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
if (clock == 0)
return;
if (host->max_clk <= clock) {
div = 1;
} else {
for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
if ((host->max_clk / div) <= clock)
break;
}
}
div >>= 1;
val &= ~((SDHCI_DIV_MASK << SDHCI_DIVIDER_SHIFT) | SDHCI_DIV_HI_MASK);
val |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
val |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
val |= SDHCI_CLOCK_CARD_EN | SDHCI_PROG_CLOCK_MODE;
sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
while ((sdhci_readw(host, SDHCI_CLOCK_CONTROL) & SDHCI_CLOCK_INT_STABLE) == 0)
;
}
static void kd_set_iocfg(struct rt_mmcsd_host* host, struct rt_mmcsd_io_cfg* io_cfg)
{
struct sdhci_host* mmcsd;
unsigned int sdhci_clk;
unsigned int bus_width;
uint8_t ctrl;
RT_ASSERT(host != RT_NULL);
RT_ASSERT(host->private_data != RT_NULL);
RT_ASSERT(io_cfg != RT_NULL);
mmcsd = (struct sdhci_host*)host->private_data;
sdhci_clk = io_cfg->clock;
bus_width = io_cfg->bus_width;
LOG_D("%s: sdhci_clk=%d, bus_width:%d\n", __func__, sdhci_clk, bus_width);
kd_mmc_clock_freq_change(mmcsd, sdhci_clk);
ctrl = sdhci_readb(mmcsd, SDHCI_HOST_CONTROL);
ctrl &= ~(SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS);
if (bus_width == 3)
ctrl |= SDHCI_CTRL_8BITBUS;
else if (bus_width == 2)
ctrl |= SDHCI_CTRL_4BITBUS;
sdhci_writeb(mmcsd, ctrl, SDHCI_HOST_CONTROL);
}
static void kd_enable_sdio_irq(struct rt_mmcsd_host* mmcsd_host, rt_int32_t en)
{
struct sdhci_host* host = (struct sdhci_host*)mmcsd_host->private_data;
uint32_t val;
val = sdhci_readw(host, SDHCI_INT_ENABLE);
if (en)
val |= SDHCI_INT_CARD_INT;
else
val &= ~SDHCI_INT_CARD_INT;
sdhci_writew(host, val, SDHCI_INT_ENABLE);
}
static const struct rt_mmcsd_host_ops ops = {
kd_mmc_request,
kd_set_iocfg,
RT_NULL,
kd_enable_sdio_irq,
RT_NULL,
};
void kd_sdhci0_reset(int value)
{
struct sdhci_host* host = sdhci_host0;
uint16_t emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
emmc_ctl |= (1 << EMMC_RST_N_OE);
if (value)
emmc_ctl |= (1 << EMMC_RST_N);
else
emmc_ctl &= ~(1 << EMMC_RST_N);
sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
}
void kd_sdhci_change(int id)
{
if (id == 0)
mmcsd_change(sdhci_host0->host);
else if (id == 1)
mmcsd_change(sdhci_host1->host);
}
rt_int32_t kd_sdhci_init(void)
{
uint32_t val;
void* hi_sys_virt_addr = rt_ioremap((void*)0x91585000, 0x10);
#ifdef BSP_USING_SDIO0
val = readl(hi_sys_virt_addr + 0);
val |= 1 << 6 | 1 << 4;
writel(val, hi_sys_virt_addr + 0);
sdhci_host0 = rt_malloc(sizeof(struct sdhci_host));
if (!sdhci_host0)
return -1;
rt_memset(sdhci_host0, 0, sizeof(struct sdhci_host));
sdhci_host0->mapbase = (void*)rt_ioremap((void*)SDEMMC0_BASE, 0x1000);
sdhci_host0->index = 0;
sdhci_host0->have_phy = 1;
sdhci_host0->mshc_ctrl_r = 0;
sdhci_host0->rx_delay_line = 0x0d;
sdhci_host0->tx_delay_line = 0xc0;
#ifdef BSP_SDIO0_EMMC
sdhci_host0->is_emmc_card = 1;
#else
sdhci_host0->is_emmc_card = 0;
#endif
#ifdef BSP_SDIO0_1V8
sdhci_host0->io_fixed_1v8 = 1;
#else
sdhci_host0->io_fixed_1v8 = 0;
#endif
sdhci_host0->sdhci_data = RT_NULL;
sdhci_host0->sdhci_command = RT_NULL;
sdhci_host0->max_clk = 200000000;
sdhci_init(sdhci_host0);
rt_event_init(&sdhci_host0->event, "sd0_event", RT_IPC_FLAG_PRIO);
rt_hw_interrupt_install(IRQN_SD0, sdhci_irq, sdhci_host0, "sd0");
rt_hw_interrupt_umask(IRQN_SD0);
struct rt_mmcsd_host* mmcsd_host0 = mmcsd_alloc_host();
if (!mmcsd_host0) {
rt_free(sdhci_host0);
return -1;
}
mmcsd_host0->ops = &ops;
mmcsd_host0->freq_min = 400000;
mmcsd_host0->freq_max = 50000000;
#ifdef BSP_SDIO0_EMMC
strncpy(mmcsd_host0->name, "emmc", sizeof(mmcsd_host0->name) - 1);
mmcsd_host0->flags = MMCSD_BUSWIDTH_8 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
#else
strncpy(mmcsd_host0->name, "sd0", sizeof(mmcsd_host0->name) - 1);
mmcsd_host0->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
#endif
mmcsd_host0->valid_ocr = sdhci_host0->io_fixed_1v8 ? VDD_165_195 : VDD_32_33 | VDD_33_34;
#ifdef BSP_USING_CYW43XX
mmcsd_host0->valid_ocr = VDD_32_33 | VDD_33_34;
#endif
mmcsd_host0->max_seg_size = 512 * 512;
mmcsd_host0->max_dma_segs = 1;
mmcsd_host0->max_blk_size = 512;
mmcsd_host0->max_blk_count = 4096;
mmcsd_host0->private_data = sdhci_host0;
sdhci_host0->host = mmcsd_host0;
#endif
#ifdef BSP_USING_SDIO1
val = readl(hi_sys_virt_addr + 8);
val |= 1 << 2 | 1 << 0;
writel(val, hi_sys_virt_addr + 8);
sdhci_host1 = rt_malloc(sizeof(struct sdhci_host));
if (!sdhci_host1)
return -2;
rt_memset(sdhci_host1, 0, sizeof(struct sdhci_host));
sdhci_host1->mapbase = (void*)rt_ioremap((void*)SDEMMC1_BASE, 0x1000);
sdhci_host1->index = 1;
sdhci_host1->have_phy = 0;
sdhci_host1->mshc_ctrl_r = 0;
sdhci_host1->rx_delay_line = 0;
sdhci_host1->tx_delay_line = 0;
sdhci_host1->sdhci_data = RT_NULL;
sdhci_host1->sdhci_command = RT_NULL;
sdhci_host1->max_clk = 100000000;
sdhci_init(sdhci_host1);
rt_event_init(&sdhci_host1->event, "sd1_event", RT_IPC_FLAG_PRIO);
rt_hw_interrupt_install(IRQN_SD1, sdhci_irq, sdhci_host1, "sd1");
rt_hw_interrupt_umask(IRQN_SD1);
struct rt_mmcsd_host* mmcsd_host1 = mmcsd_alloc_host();
if (!mmcsd_host1) {
rt_free(sdhci_host1);
return -2;
}
strncpy(mmcsd_host1->name, "sd1", sizeof(mmcsd_host1->name) - 1);
mmcsd_host1->ops = &ops;
mmcsd_host1->freq_min = 400000;
mmcsd_host1->freq_max = 50000000;
mmcsd_host1->valid_ocr = VDD_32_33 | VDD_33_34;
mmcsd_host1->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
mmcsd_host1->max_seg_size = 512 * 512;
mmcsd_host1->max_dma_segs = 1;
mmcsd_host1->max_blk_size = 512;
mmcsd_host1->max_blk_count = 4096;
mmcsd_host1->private_data = sdhci_host1;
sdhci_host1->host = mmcsd_host1;
#endif
#ifdef BSP_SD_SDIO_DEV
kd_sdhci_change(BSP_SD_SDIO_DEV);
#endif
rt_iounmap(hi_sys_virt_addr);
return 0;
}
INIT_DEVICE_EXPORT(kd_sdhci_init);
#endif /*defined(BSP_USING_SDIO0) || defined(BSP_USING_SDIO1)*/
#endif /*defined(RT_USING_SDIO)*/

View File

@ -0,0 +1,496 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_SDHCI__
#define __DRV_SDHCI__
#define false 0
#define true 1
#define SDEMMC0_BASE 0x91580000
#define SDEMMC1_BASE 0x91581000
#define IRQN_SD0 142
#define IRQN_SD1 144
/*
* Controller registers
*/
#define SDHCI_DMA_ADDRESS 0x00
#define SDHCI_ARGUMENT2 SDHCI_DMA_ADDRESS
#define SDHCI_32BIT_BLK_CNT SDHCI_DMA_ADDRESS
#define SDHCI_BLOCK_SIZE 0x04
#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
#define SDHCI_BLOCK_COUNT 0x06
#define SDHCI_ARGUMENT 0x08
#define SDHCI_TRANSFER_MODE 0x0C
#define SDHCI_TRNS_DMA 0x01
#define SDHCI_TRNS_BLK_CNT_EN 0x02
#define SDHCI_TRNS_AUTO_CMD12 0x04
#define SDHCI_TRNS_AUTO_CMD23 0x08
#define SDHCI_TRNS_AUTO_SEL 0x0C
#define SDHCI_TRNS_READ 0x10
#define SDHCI_TRNS_MULTI 0x20
#define SDHCI_COMMAND 0x0E
#define SDHCI_CMD_RESP_MASK 0x03
#define SDHCI_CMD_CRC 0x08
#define SDHCI_CMD_INDEX 0x10
#define SDHCI_CMD_DATA 0x20
#define SDHCI_CMD_ABORTCMD 0xC0
#define SDHCI_CMD_RESP_NONE 0x00
#define SDHCI_CMD_RESP_LONG 0x01
#define SDHCI_CMD_RESP_SHORT 0x02
#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
#define SDHCI_GET_CMD(c) ((c >> 8) & 0x3f)
#define SDHCI_RESPONSE 0x10
#define SDHCI_BUFFER 0x20
#define SDHCI_PRESENT_STATE 0x24
#define SDHCI_CMD_INHIBIT 0x00000001
#define SDHCI_DATA_INHIBIT 0x00000002
#define SDHCI_DOING_WRITE 0x00000100
#define SDHCI_DOING_READ 0x00000200
#define SDHCI_SPACE_AVAILABLE 0x00000400
#define SDHCI_DATA_AVAILABLE 0x00000800
#define SDHCI_CARD_PRESENT 0x00010000
#define SDHCI_CARD_PRES_SHIFT 16
#define SDHCI_CD_STABLE 0x00020000
#define SDHCI_CD_LVL 0x00040000
#define SDHCI_CD_LVL_SHIFT 18
#define SDHCI_WRITE_PROTECT 0x00080000
#define SDHCI_DATA_LVL_MASK 0x00F00000
#define SDHCI_DATA_LVL_SHIFT 20
#define SDHCI_DATA_0_LVL_MASK 0x00100000
#define SDHCI_CMD_LVL 0x01000000
#define SDHCI_HOST_CONTROL 0x28
#define SDHCI_CTRL_LED 0x01
#define SDHCI_CTRL_4BITBUS 0x02
#define SDHCI_CTRL_HISPD 0x04
#define SDHCI_CTRL_DMA_MASK 0x18
#define SDHCI_CTRL_SDMA 0x00
#define SDHCI_CTRL_ADMA1 0x08
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
#define SDHCI_CTRL_ADMA3 0x18
#define SDHCI_CTRL_8BITBUS 0x20
#define SDHCI_CTRL_CDTEST_INS 0x40
#define SDHCI_CTRL_CDTEST_EN 0x80
#define SDHCI_POWER_CONTROL 0x29
#define SDHCI_POWER_ON 0x01
#define SDHCI_POWER_180 0x0A
#define SDHCI_POWER_300 0x0C
#define SDHCI_POWER_330 0x0E
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
#define SDHCI_WAKE_UP_CONTROL 0x2B
#define SDHCI_WAKE_ON_INT 0x01
#define SDHCI_WAKE_ON_INSERT 0x02
#define SDHCI_WAKE_ON_REMOVE 0x04
#define SDHCI_CLOCK_CONTROL 0x2C
#define SDHCI_DIVIDER_SHIFT 8
#define SDHCI_DIVIDER_HI_SHIFT 6
#define SDHCI_DIV_MASK 0xFF
#define SDHCI_DIV_MASK_LEN 8
#define SDHCI_DIV_HI_MASK 0x300
#define SDHCI_PROG_CLOCK_MODE 0x0020
#define SDHCI_CLOCK_CARD_EN 0x0004
#define SDHCI_CLOCK_PLL_EN 0x0008
#define SDHCI_CLOCK_INT_STABLE 0x0002
#define SDHCI_CLOCK_INT_EN 0x0001
#define SDHCI_TIMEOUT_CONTROL 0x2E
#define SDHCI_SOFTWARE_RESET 0x2F
#define SDHCI_RESET_ALL 0x01
#define SDHCI_RESET_CMD 0x02
#define SDHCI_RESET_DATA 0x04
#define SDHCI_INT_STATUS 0x30
#define SDHCI_INT_ENABLE 0x34
#define SDHCI_SIGNAL_ENABLE 0x38
#define SDHCI_INT_RESPONSE 0x00000001
#define SDHCI_INT_DATA_END 0x00000002
#define SDHCI_INT_BLK_GAP 0x00000004
#define SDHCI_INT_DMA_END 0x00000008
#define SDHCI_INT_SPACE_AVAIL 0x00000010
#define SDHCI_INT_DATA_AVAIL 0x00000020
#define SDHCI_INT_CARD_INSERT 0x00000040
#define SDHCI_INT_CARD_REMOVE 0x00000080
#define SDHCI_INT_CARD_INT 0x00000100
#define SDHCI_INT_RETUNE 0x00001000
#define SDHCI_INT_CQE 0x00004000
#define SDHCI_INT_ERROR 0x00008000
#define SDHCI_INT_TIMEOUT 0x00010000
#define SDHCI_INT_CRC 0x00020000
#define SDHCI_INT_END_BIT 0x00040000
#define SDHCI_INT_INDEX 0x00080000
#define SDHCI_INT_DATA_TIMEOUT 0x00100000
#define SDHCI_INT_DATA_CRC 0x00200000
#define SDHCI_INT_DATA_END_BIT 0x00400000
#define SDHCI_INT_BUS_POWER 0x00800000
#define SDHCI_INT_AUTO_CMD_ERR 0x01000000
#define SDHCI_INT_ADMA_ERROR 0x02000000
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_AUTO_CMD_ERR)
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | SDHCI_INT_BLK_GAP)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_CQE_INT_ERR_MASK ( \
SDHCI_INT_ADMA_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)
#define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE)
#define SDHCI_AUTO_CMD_STATUS 0x3C
#define SDHCI_AUTO_CMD_TIMEOUT 0x00000002
#define SDHCI_AUTO_CMD_CRC 0x00000004
#define SDHCI_AUTO_CMD_END_BIT 0x00000008
#define SDHCI_AUTO_CMD_INDEX 0x00000010
#define SDHCI_HOST_CONTROL2 0x3E
#define SDHCI_CTRL_UHS_MASK 0x0007
#define SDHCI_CTRL_UHS_SDR12 0x0000
#define SDHCI_CTRL_UHS_SDR25 0x0001
#define SDHCI_CTRL_UHS_SDR50 0x0002
#define SDHCI_CTRL_UHS_SDR104 0x0003
#define SDHCI_CTRL_UHS_DDR50 0x0004
#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
#define SDHCI_CTRL_VDD_180 0x0008
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
#define SDHCI_CTRL_DRV_TYPE_A 0x0010
#define SDHCI_CTRL_DRV_TYPE_C 0x0020
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
#define SDHCI_CTRL_EXEC_TUNING 0x0040
#define SDHCI_CTRL_TUNED_CLK 0x0080
#define SDHCI_CMD23_ENABLE 0x0800
#define SDHCI_CTRL_V4_MODE 0x1000
#define SDHCI_CTRL_64BIT_ADDR 0x2000
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
#define SDHCI_CAPABILITIES 0x40
#define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0)
#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
#define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8)
#define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8)
#define SDHCI_MAX_BLOCK_MASK 0x00030000
#define SDHCI_MAX_BLOCK_SHIFT 16
#define SDHCI_CAN_DO_8BIT 0x00040000
#define SDHCI_CAN_DO_ADMA2 0x00080000
#define SDHCI_CAN_DO_ADMA1 0x00100000
#define SDHCI_CAN_DO_HISPD 0x00200000
#define SDHCI_CAN_DO_SDMA 0x00400000
#define SDHCI_CAN_DO_SUSPEND 0x00800000
#define SDHCI_CAN_VDD_330 0x01000000
#define SDHCI_CAN_VDD_300 0x02000000
#define SDHCI_CAN_VDD_180 0x04000000
#define SDHCI_CAN_64BIT_V4 0x08000000
#define SDHCI_CAN_64BIT 0x10000000
#define SDHCI_CAPABILITIES_1 0x44
#define SDHCI_SUPPORT_SDR50 0x00000001
#define SDHCI_SUPPORT_SDR104 0x00000002
#define SDHCI_SUPPORT_DDR50 0x00000004
#define SDHCI_DRIVER_TYPE_A 0x00000010
#define SDHCI_DRIVER_TYPE_C 0x00000020
#define SDHCI_DRIVER_TYPE_D 0x00000040
#define SDHCI_RETUNING_TIMER_COUNT_MASK GENMASK(11, 8)
#define SDHCI_USE_SDR50_TUNING 0x00002000
#define SDHCI_RETUNING_MODE_MASK GENMASK(15, 14)
#define SDHCI_CLOCK_MUL_MASK GENMASK(23, 16)
#define SDHCI_CAN_DO_ADMA3 0x08000000
#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
#define SDHCI_MAX_CURRENT 0x48
#define SDHCI_MAX_CURRENT_LIMIT GENMASK(7, 0)
#define SDHCI_MAX_CURRENT_330_MASK GENMASK(7, 0)
#define SDHCI_MAX_CURRENT_300_MASK GENMASK(15, 8)
#define SDHCI_MAX_CURRENT_180_MASK GENMASK(23, 16)
#define SDHCI_MAX_CURRENT_MULTIPLIER 4
/* 4C-4F reserved for more max current */
#define SDHCI_SET_ACMD12_ERROR 0x50
#define SDHCI_SET_INT_ERROR 0x52
#define SDHCI_ADMA_ERROR 0x54
/* 55-57 reserved */
#define SDHCI_ADMA_ADDRESS 0x58
#define SDHCI_ADMA_ADDRESS_HI 0x5C
/* 60-FB reserved */
#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64
#define SDHCI_PRESET_FOR_SDR12 0x66
#define SDHCI_PRESET_FOR_SDR25 0x68
#define SDHCI_PRESET_FOR_SDR50 0x6A
#define SDHCI_PRESET_FOR_SDR104 0x6C
#define SDHCI_PRESET_FOR_DDR50 0x6E
#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */
#define SDHCI_PRESET_DRV_MASK GENMASK(15, 14)
#define SDHCI_PRESET_CLKGEN_SEL BIT(10)
#define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0)
#define SDHCI_SLOT_INT_STATUS 0xFC
#define SDHCI_HOST_VERSION 0xFE
#define SDHCI_VENDOR_VER_MASK 0xFF00
#define SDHCI_VENDOR_VER_SHIFT 8
#define SDHCI_SPEC_VER_MASK 0x00FF
#define SDHCI_SPEC_VER_SHIFT 0
#define SDHCI_SPEC_100 0
#define SDHCI_SPEC_200 1
#define SDHCI_SPEC_300 2
#define SDHCI_SPEC_400 3
#define SDHCI_SPEC_410 4
#define SDHCI_SPEC_420 5
/*
* End of controller registers.
*/
#define SDHCI_MAX_DIV_SPEC_300 2046
/*! @brief Transfer flag mask */
enum sdhci_transfer_mode
{
sdhci_enable_dma_flag = SDHCI_TRNS_DMA, /*!< Enable DMA */
sdhci_enable_block_count_flag = SDHCI_TRNS_BLK_CNT_EN, /*!< Enable block count */
sdhci_enable_auto_command12_flag = SDHCI_TRNS_AUTO_CMD12, /*!< Enable auto CMD12 */
sdhci_data_read_flag = SDHCI_TRNS_READ, /*!< Enable data read */
sdhci_multiple_block_flag = SDHCI_TRNS_MULTI, /*!< Multiple block data read/write */
sdhci_enable_auto_command23_flag = SDHCI_TRNS_AUTO_CMD23, /*!< Enable auto CMD23 */
sdhci_enable_auto_commamd_sel_flag = SDHCI_TRNS_AUTO_SEL, /* Enable auto command sel*/
};
enum sdhci_command_flag
{
sdhci_cmd_resp_nono = SDHCI_CMD_RESP_NONE,
sdhci_cmd_resp_long = SDHCI_CMD_RESP_LONG,
sdhci_cmd_resp_short = SDHCI_CMD_RESP_SHORT,
sdhci_cmd_resp_short_busy = SDHCI_CMD_RESP_SHORT_BUSY,
sdhci_enable_cmd_crc_flag = SDHCI_CMD_CRC,
sdhci_enable_cmd_index_chk_flag = SDHCI_CMD_INDEX,
sdhci_enable_cmd_data_present_flag = SDHCI_CMD_DATA,
sdhci_enable_command_type_normal = 0x00,
sdhci_enable_command_type_suspend = 0x40,
sdhci_enable_command_type_resume = 0x80,
sdhci_enable_command_type_abort = 0xc0,
};
/*! @brief Present status flag mask */
enum sdhci_present_status_flag
{
sdhci_command_inhibit_flag = 0x1, /*!< Command inhibit */
sdhci_data_inhibit_flag = 0x2, /*!< Data inhibit */
sdhci_data_line_active_flag = 0x4, /*!< Data line active */
sdhci_write_transfer_active_flag = 0x100, /*!< Write transfer active */
sdhci_read_transfer_active_flag = 0x200, /*!< Read transfer active */
sdhci_buffer_write_enable_flag = 0x400, /*!< Buffer write enable */
sdhci_buffer_read_enable_flag = 0x800, /*!< Buffer read enable */
sdhci_card_insert_flag = 0x10000, /*!< Card inserted */
sdhci_sd_clock_stable_flag = 0x20000, /*!< SD bus clock stable */
sdhci_card_detect_pin_level_flag = 0x40000, /*!< card detect pin level */
sdhci_write_protect_switch_pin_level_flag = 0x80000, /*<write protect switch pin level>*/
sdhci_data0_line_level_flag = (1U << 20), /*!< Data0 line signal level */
sdhci_data1_line_level_flag = (1U << (20 + 1U)), /*!< Data1 line signal level */
sdhci_data2_line_level_flag = (1U << (20 + 2U)), /*!< Data2 line signal level */
sdhci_data3_line_level_flag = (1U << (20 + 3U)), /*!< Data3 line signal level */
sdhci_data4_line_level_flag = (1U << (4 + 0U)), /*!< Data4 line signal level */
sdhci_data5_line_level_flag = (1U << (4 + 1U)), /*!< Data5 line signal level */
sdhci_data6_line_level_flag = (1U << (4 + 2U)), /*!< Data6 line signal level */
sdhci_data7_line_level_flag = (1U << (4 + 3U)), /*!< Data7 line signal level */
sdhci_command_line_signal_level_flag =0x1000000,
sdhci_host_reg_voltage_stable_flag = 0x2000000,
sdhci_command_not_issued_by_error_flag = 0x8000000,
sdhci_sub_command_status_flag = 0x10000000,
sdhci_in_dormant_status_flag = 0x20000000,
sdhci_lane_synchronization_flag = 0x40000000,
sdhci_uhs_ii_interface_detection_flag = 0x80000000,
};
/*! @brief Interrupt status flag mask */
enum sdhci_interrupt_status_flag
{
sdhci_command_complete_flag = 0x1, /*!< Command complete */
sdhci_data_complete_flag = 0x2, /*!< Data complete */
sdhci_block_gap_event_flag = 0x4, /*!< Block gap event */
sdhci_dma_complete_flag = 0x8, /*!< DMA interrupt */
sdhci_buffer_write_ready_flag = 0x10, /*!< Buffer write ready */
sdhci_buffer_read_ready_flag = 0x20, /*!< Buffer read ready */
sdhci_card_insertion_flag = 0x40, /*!< Card inserted */
sdhci_card_removal_flag = 0x80, /*!< Card removed */
sdhci_card_interrupt_flag = 0x100, /*!< Card interrupt */
sdhci_command_timeout_flag = 0x10000, /*!< Command timeout error */
sdhci_command_crc_error_flag = 0x20000, /*!< Command CRC error */
sdhci_command_end_bit_error_flag = 0x40000, /*!< Command end bit error */
sdhci_command_index_error_flag = 0x80000, /*!< Command index error */
sdhci_data_timeout_flag = 0x100000, /*!< Data timeout error */
sdhci_data_crc_error_flag = 0x200000, /*!< Data CRC error */
sdhci_data_end_bit_error_flag = 0x400000, /*!< Data end bit error */
sdhci_auto_command_error_flag = 0x1000000, /*!< Auto CMD error */
sdhci_dma_error_flag = 0x2000000, /*!< ADMA error */
sdhci_tuning_error_flag = 0x4000000, /* tuning err*/
sdhci_response_err_flag = 0x8000000, /*resp error*/
sdhci_command_error_flag = (sdhci_command_timeout_flag | sdhci_command_crc_error_flag | sdhci_command_end_bit_error_flag |
sdhci_command_index_error_flag), /*!< Command error */
sdhci_data_error_flag = (sdhci_data_timeout_flag | sdhci_data_crc_error_flag | sdhci_data_end_bit_error_flag |
sdhci_auto_command_error_flag), /*!< Data error */
sdhci_error_flag = (sdhci_command_error_flag | sdhci_data_error_flag | sdhci_dma_error_flag), /*!< All error */
sdhci_data_flag = (sdhci_data_complete_flag | sdhci_dma_complete_flag | sdhci_buffer_write_ready_flag |
sdhci_buffer_read_ready_flag | sdhci_data_error_flag | sdhci_dma_error_flag), /*!< Data interrupts */
sdhci_command_flag = (sdhci_command_error_flag | sdhci_command_complete_flag), /*!< Command interrupts */
sdhci_card_detect_flag = (sdhci_card_insertion_flag | sdhci_card_removal_flag), /*!< Card detection interrupts */
sdhci_sdr104_tuning_flag = (sdhci_tuning_error_flag),
sdhci_all_interrupt_flags = (sdhci_block_gap_event_flag | sdhci_card_detect_flag | sdhci_command_flag |
sdhci_data_flag | sdhci_error_flag | sdhci_sdr104_tuning_flag), /*!< All flags mask */
};
/*! @brief USDHC status */
enum sdhci_status
{
sdhci_status_busy_transferring = 65, /*!< Transfer is on-going */
sdhci_status_prepare_adma_descriptor_failed = 66, /*!< Set DMA descriptor failed */
sdhci_status_send_command_failed = 67, /*!< Send command failed */
sdhci_status_transfer_data_failed = 68, /*!< Transfer data failed */
sdhci_status_dma_data_addr_no_align = 69, /*!< data address not align */
sdhci_status_retuning_request = 70, /*!< re-tuning request */
sdhci_status_tuning_error = 71, /*!< tuning error */
};
/* ADMA2 data alignment */
#define SDHCI_ADMA2_ALIGN 4
#define SDHCI_ADMA2_MASK (SDHCI_ADMA2_ALIGN - 1)
/*! @brief The bit shift for LENGTH field in ADMA2's descriptor */
#define SDHCI_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U)
/*! @brief The bit mask for LENGTH field in ADMA2's descriptor */
#define SDHCI_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
/*! @brief The maximum value of LENGTH field in ADMA2's descriptor */
#define SDHCI_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHCI_ADMA2_DESCRIPTOR_LENGTH_MASK - 3U)
#define SDHCI_DESC_VALID (0x1U << 0)
#define SDHCI_DESC_END (0x1U << 1)
#define SDHCI_DESC_INT (0x1U << 2)
#define SDHCI_DESC_TRAN (0x2U << 4)
struct sdhci_64bit_adma2_descriptor
{
uint32_t attribute;
uint32_t address;
};
/*! @brief The command type */
enum sdhci_card_command_type
{
card_command_type_normal = 0U, /*!< Normal command */
card_command_type_suspend = 1U, /*!< Suspend command */
card_command_type_resume = 2U, /*!< Resume command */
card_command_type_abort = 3U, /*!< Abort command */
};
/*!
* @brief The command response type.
*
* Define the command response type from card to host controller.
*/
enum sdhci_card_response_type
{
card_response_type_none = 0U, /*!< Response type: none */
card_response_type_r1 = 1U, /*!< Response type: R1 */
card_response_type_r1b = 2U, /*!< Response type: R1b */
card_response_type_r2 = 3U, /*!< Response type: R2 */
card_response_type_r3 = 4U, /*!< Response type: R3 */
card_response_type_r4 = 5U, /*!< Response type: R4 */
card_response_type_r5 = 6U, /*!< Response type: R5 */
card_response_type_r5b = 7U, /*!< Response type: R5b */
card_response_type_r6 = 8U, /*!< Response type: R6 */
card_response_type_r7 = 9U, /*!< Response type: R7 */
};
/*!
* @brief Card data descriptor
*
* Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card
* driver
* want to ignore the error event to read/write all the data not to stop read/write immediately when error event
* happen for example bus testing procedure for MMC card.
*/
struct sdhci_data
{
rt_bool_t enableAutoCommand12; /*!< Enable auto CMD12 */
rt_bool_t enableAutoCommand23; /*!< Enable auto CMD23 */
rt_bool_t enableIgnoreError; /*!< Enable to ignore error event to read/write all the data */
rt_bool_t executeTuning; /*!< execute tuning flag */
size_t blockSize; /*!< Block size */
uint32_t blockCount; /*!< Block count */
uint32_t *rxData; /*!< Buffer to save data read */
const uint32_t *txData; /*!< Data buffer to write */
};
/*!
* @brief Card command descriptor
*
* Define card command-related attribute.
*/
struct sdhci_command
{
uint32_t index; /*!< Command index */
uint32_t argument; /*!< Command argument */
enum sdhci_card_command_type type; /*!< Command type */
enum sdhci_card_response_type responseType; /*!< Command response type */
uint32_t response[4U]; /*!< Response for this command */
uint32_t responseErrorFlags; /*!< response error flag, the flag which need to check
the command reponse*/
uint16_t flags; /*!< Cmd flags */
uint16_t flags2; /*xfer mode*/
};
struct sdhci_host
{
struct rt_mmcsd_host *host;
void *mapbase;
struct sdhci_data *sdhci_data;
struct sdhci_command *sdhci_command;
void *usdhc_adma2_table;
struct rt_event event;
uint16_t error_code;
uint32_t max_clk;
uint8_t index;
uint8_t is_emmc_card;
uint8_t io_fixed_1v8;
uint8_t have_phy;
uint8_t mshc_ctrl_r;
uint32_t rx_delay_line;
uint32_t tx_delay_line;
};
#endif /*__DRV_SDHCI__*/

View File

@ -0,0 +1,19 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Uart', src, depend = [''], CPPPATH = CPPPATH)
objs = [group]
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

View File

@ -0,0 +1,370 @@
/*
* Copyright (c) 2019-2020
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#include <rthw.h>
#include <rtdevice.h>
#include <lwp_user_mm.h>
#include <ioremap.h>
#include "board.h"
#include "drv_uart.h"
#include "riscv_io.h"
#include "board.h"
#define UART_DEFAULT_BAUDRATE 115200
#define UART_CLK 50000000
#define UART_ADDR 0x91403000UL
#define UART_IRQ 0x13
#define UART_RBR (0x00) /* receive buffer register */
#define UART_THR (0x00) /* transmit holding register */
#define UART_DLL (0x00) /* divisor latch low register */
#define UART_DLH (0x04) /* diviso latch high register */
#define UART_IER (0x04) /* interrupt enable register */
#define UART_IIR (0x08) /* interrupt identity register */
#define UART_FCR (0x08) /* FIFO control register */
#define UART_LCR (0x0c) /* line control register */
#define UART_MCR (0x10) /* modem control register */
#define UART_LSR (0x14) /* line status register */
#define UART_MSR (0x18) /* modem status register */
#define UART_SCH (0x1c) /* scratch register */
#define UART_USR (0x7c) /* status register */
#define UART_TFL (0x80) /* transmit FIFO level */
#define UART_RFL (0x84) /* RFL */
#define UART_HALT (0xa4) /* halt tx register */
#define UART_DLF (0xc0) /* Divisor Latch Fraction Register */
#define BIT(x) (1 << x)
/* Line Status Rigster */
#define UART_LSR_RXFIFOE (BIT(7))
#define UART_LSR_TEMT (BIT(6))
#define UART_LSR_THRE (BIT(5))
#define UART_LSR_BI (BIT(4))
#define UART_LSR_FE (BIT(3))
#define UART_LSR_PE (BIT(2))
#define UART_LSR_OE (BIT(1))
#define UART_LSR_DR (BIT(0))
#define UART_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */
/* Line Control Register */
#define UART_LCR_DLAB (BIT(7))
#define UART_LCR_SBC (BIT(6))
#define UART_LCR_PARITY_MASK (BIT(5)|BIT(4))
#define UART_LCR_EPAR (1 << 4)
#define UART_LCR_OPAR (0 << 4)
#define UART_LCR_PARITY (BIT(3))
#define UART_LCR_STOP (BIT(2))
#define UART_LCR_DLEN_MASK (BIT(1)|BIT(0))
#define UART_LCR_WLEN5 (0)
#define UART_LCR_WLEN6 (1)
#define UART_LCR_WLEN7 (2)
#define UART_LCR_WLEN8 (3)
/* Halt Register */
#define UART_HALT_LCRUP (BIT(2))
#define UART_HALT_FORCECFG (BIT(1))
#define UART_HALT_HTX (BIT(0))
/* Interrupt Enable Register */
#define UART_IER_MASK (0xff)
#define UART_IER_PTIME (BIT(7))
#define UART_IER_RS485 (BIT(4))
#define UART_IER_MSI (BIT(3))
#define UART_IER_RLSI (BIT(2))
#define UART_IER_THRI (BIT(1))
#define UART_IER_RDI (BIT(0))
/* Interrupt ID Register */
#define UART_IIR_FEFLAG_MASK (BIT(6)|BIT(7))
#define UART_IIR_IID_MASK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
#define UART_IIR_IID_MSTA (0)
#define UART_IIR_IID_NOIRQ (1)
#define UART_IIR_IID_THREMP (2)
#define UART_IIR_IID_RXDVAL (4)
#define UART_IIR_IID_LINESTA (6)
#define UART_IIR_IID_BUSBSY (7)
#define UART_IIR_IID_CHARTO (12)
struct device_uart
{
rt_ubase_t hw_base;
rt_uint32_t irqno;
};
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg);
static int drv_uart_putc(struct rt_serial_device *serial, char c);
static int drv_uart_getc(struct rt_serial_device *serial);
const struct rt_uart_ops _uart_ops =
{
rt_uart_configure,
uart_control,
drv_uart_putc,
drv_uart_getc,
//TODO: add DMA support
RT_NULL
};
struct rt_serial_device serial1;
struct device_uart uart1;
#define write32(addr, val) writel(val, (void*)(addr))
#define read32(addr) readl((void*)(addr))
static void _uart_init(void *uart_base)
{
uint32_t bdiv;
uint32_t dlf;
uint32_t dlh;
uint32_t dll;
bdiv = UART_CLK / UART_DEFAULT_BAUDRATE;
dlh = bdiv >> 12;
dll = (bdiv - (dlh << 12)) / 16;
dlf = bdiv - (dlh << 12) - dll * 16;
if(dlh == 0 && dll == 0)
{
dll = 1;
dlf = 0;
}
write32(uart_base + UART_LCR, 0x00);
/* Disable all interrupts */
write32(uart_base + UART_IER, 0x00);
/* Enable DLAB */
write32(uart_base + UART_LCR, 0x80);
if (bdiv) {
/* Set divisor low byte */
write32(uart_base + UART_DLL, dll);
/* Set divisor high byte */
write32(uart_base + UART_DLH, dlh);
/* Set divisor fraction byte*/
write32(uart_base + UART_DLF, dlf);
}
/* 8 bits, no parity, one stop bit */
write32(uart_base + UART_LCR, 0x03);
/* Enable FIFO */
write32(uart_base + UART_FCR, 0x01);
/* No modem control DTR RTS */
write32(uart_base + UART_MCR, 0x00);
/* Clear line status */
read32(uart_base + UART_LSR);
/* Read receive buffer */
read32(uart_base + UART_RBR);
read32(uart_base + UART_USR);
read32(uart_base + UART_FCR);
/* Set scratchpad */
write32(uart_base + UART_SCH, 0x00);
//enable uart rx irq
// write32(uart_base + UART_IER, 0x01);
}
static void uart_set_isr(void *uart_base, uint8_t enable, uint32_t irq_type)
{
uint32_t value;
value = read32(uart_base + UART_IER);
if (enable)
{
value |= irq_type;
}
else
{
value &= ~irq_type;
}
write32(uart_base + UART_IER, value);
}
/*
* UART interface
*/
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
return (RT_EOK);
}
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
#ifdef RT_USING_SERIAL_V2
rt_ubase_t ctrl_flag = 0;
rt_ubase_t ctrl_arg;
#endif
#ifdef RT_USING_SERIAL_V2
ctrl_arg = (rt_ubase_t)arg;
if (ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING))
{
ctrl_flag |= RT_DEVICE_FLAG_INT_RX;
}
#endif
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
#ifdef RT_USING_SERIAL_V2
if (ctrl_flag & RT_DEVICE_FLAG_INT_RX)
#else
if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
#endif
{
uart_set_isr((void*)(uart->hw_base), 0, UART_IER_RDI);
}
break;
case RT_DEVICE_CTRL_SET_INT:
#ifdef RT_USING_SERIAL_V2
if (ctrl_flag & RT_DEVICE_FLAG_INT_RX)
#else
if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
#endif
{
uart_set_isr((void*)(uart->hw_base), 1, UART_IER_RDI);
}
break;
#ifdef RT_USING_SERIAL_V2
case RT_DEVICE_CTRL_CONFIG:
if (ctrl_flag & RT_DEVICE_FLAG_INT_RX)
{
uart_set_isr((void*)(uart->hw_base), 1, UART_IER_RDI);
}
break;
#endif
case RT_FIOMMAP2:
{
struct dfs_mmap2_args *mmap2 = (struct dfs_mmap2_args *)arg;
if (mmap2)
{
if (mmap2->length > 0x400)
{
return -RT_ENOMEM;
}
mmap2->ret = lwp_map_user_phy(lwp_self(), RT_NULL, (void*)(uart->hw_base), mmap2->length, 0);
}
break;
}
}
return (RT_EOK);
}
static int drv_uart_putc(struct rt_serial_device *serial, char c)
{
volatile uint32_t *sed_buf;
volatile uint32_t *sta;
struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
sed_buf = (uint32_t *)(uart->hw_base + UART_THR);
sta = (uint32_t *)(uart->hw_base + UART_USR);
/* FIFO status, contain valid data */
// while (!(*sta & 0x02));
while (!(read32(uart->hw_base + UART_LSR) & 0x20));
*sed_buf = c;
return (1);
}
static int drv_uart_getc(struct rt_serial_device *serial)
{
struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
volatile uint32_t *lsr = (uint32_t *)(uart->hw_base + UART_LSR);
volatile uint32_t *rbr = (uint32_t *)(uart->hw_base + UART_RBR);
if (!(*lsr & UART_LSR_DR))
{
return -1;
}
return (int)*rbr;
}
static void rt_hw_uart_isr(int irq, void *param)
{
struct rt_serial_device *serial = (struct rt_serial_device*)param;
struct device_uart *uart;
size_t uart_base;
uint32_t iir, lsr;
uart = (struct device_uart*)serial->parent.user_data;
uart_base = uart->hw_base;
iir = readb((void*)(uart_base + UART_IIR)) & UART_IIR_IID_MASK;
lsr = readb((void*)(uart_base + UART_LSR));
// rt_kprintf("uart isr iir:%x lsr:%x\r\n", iir, lsr);
if (iir == UART_IIR_IID_BUSBSY)
{
(void)readb((void*)(uart_base + UART_USR));
}
else if (lsr & (UART_LSR_DR | UART_LSR_BI))
{
#ifdef RT_USING_SERIAL_V2
struct rt_serial_rx_fifo *rx_fifo;
uint8_t data;
rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
RT_ASSERT(rx_fifo != RT_NULL);
do {
data = readb((void*)(uart_base + UART_RBR));
rt_ringbuffer_putchar(&(rx_fifo->rb), data);
lsr = readb((void*)(uart_base + UART_LSR));
} while(lsr & UART_LSR_DR);
#endif
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
else if (iir & UART_IIR_IID_CHARTO)
/* has charto irq but no dr lsr? just read and ignore */
{
readb((void*)(uart_base + UART_RBR));
}
}
/*
* UART Initiation
*/
int rt_hw_uart_init(void)
{
struct rt_serial_device *serial;
struct device_uart *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
{
serial = &serial1;
uart = &uart1;
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
uart->hw_base = (rt_base_t)rt_ioremap((void *)UART_ADDR, 0x1000);
uart->irqno = UART_IRQ;
_uart_init((void*)(uart->hw_base));
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart1");
rt_hw_interrupt_umask(uart->irqno);
rt_hw_serial_register(serial,
RT_CONSOLE_DEVICE_NAME,
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
}
return 0;
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2019-2020, Xim
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#ifndef __DRV_UART_H__
#define __DRV_UART_H__
void rt_hw_uart_start_rx_thread();
int rt_hw_uart_init(void);
void drv_uart_puts(char *str); // for syscall
#endif /* __DRV_UART_H__ */

184
bsp/k230/link.lds Normal file
View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/12/12 bernard The first version
*/
INCLUDE "link_stacksize.lds"
OUTPUT_ARCH( "riscv" )
/*
* Memory layout:
* 2M ==> +128K: Bootloader(sbi)
* 2M+128K ==> +sizeof(rtthread.bin): Kernel
* ~ ==> 32M: Heap
* 32M - 66M: Page
*/
MEMORY
{
SRAM(wx) : ORIGIN = 0xFFFFFFC000220000, LENGTH = 64M - 128K
}
ENTRY(_start)
SECTIONS
{
. = ORIGIN(SRAM) ;
/* __STACKSIZE__ = 4096; */
__sram_base = ORIGIN(SRAM);
__sram_size = LENGTH(SRAM);
__sram_end = __sram_base + __sram_size;
__text_start = .;
.start :
{
*(.start);
} > SRAM
. = ALIGN(8);
.text :
{
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
*(.gnu.linkonce.t*)
/* section information for finsh shell */
. = ALIGN(8);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(8);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
. = ALIGN(8);
/* section information for initial. */
. = ALIGN(8);
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
. = ALIGN(8);
__rt_utest_tc_tab_start = .;
KEEP(*(UtestTcTab))
__rt_utest_tc_tab_end = .;
. = ALIGN(8);
_etext = .;
} > SRAM
.eh_frame_hdr :
{
*(.eh_frame_hdr)
*(.eh_frame_entry)
} > SRAM
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > SRAM
. = ALIGN(8);
__text_end = .;
__text_size = __text_end - __text_start;
.data :
{
*(.data)
*(.data.*)
*(.data1)
*(.data1.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata)
*(.sdata.*)
} > SRAM
/* stack for dual core */
.stack :
{
. = ALIGN(64);
__stack_start__ = .;
. += __STACKSIZE__;
__stack_cpu0 = .;
. += __STACKSIZE__;
__stack_cpu1 = .;
} > SRAM
. = ALIGN(8);
.osdebug :
{
_osdebug_start = .;
. += 87K;
_osdebug_end = .;
} > SRAM
. = ALIGN(8);
.sbss :
{
__bss_start = .;
*(.sbss)
*(.sbss.*)
*(.dynsbss)
*(.scommon)
} > SRAM
.bss :
{
*(.bss)
*(.bss.*)
*(.dynbss)
*(COMMON)
__bss_end = .;
} > SRAM
_end = .;
/* Stabs debugging sections. */
.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) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.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) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

View File

@ -0,0 +1 @@
__STACKSIZE__ = 8192;

77
bsp/k230/mkfm.sh Normal file
View File

@ -0,0 +1,77 @@
#/bin/sh
#add_firmHead xxx.bin "-n"
#output fn_$1 fa_$1 fs_$1
add_firmHead()
{
local filename="$1"
local firmware_gen="tools/firmware_gen.py"
if [ $# -ge 2 ]; then
firmArgs="$2" #add k230 firmware head
cp ${filename} ${filename}.t; python3 ${firmware_gen} -i ${filename}.t -o f${firmArgs##-}${filename} ${firmArgs};
else
#add k230 firmware head
firmArgs="-n"; cp ${filename} ${filename}.t; python3 ${firmware_gen} -i ${filename}.t -o f${firmArgs##-}_${filename} ${firmArgs};
fi
rm -rf ${filename}.t
}
k230_gzip()
{
local filename="$1"
local k230_gzip_tool="tools/k230_priv_gzip "
${k230_gzip_tool} -n8 -f -k ${filename} || ${k230_gzip_tool} -n9 -f -k ${filename} || \
${k230_gzip_tool} -n7 -f -k ${filename} || ${k230_gzip_tool} -n6 -f -k ${filename} || \
${k230_gzip_tool} -n5 -f -k ${filename} || ${k230_gzip_tool} -n4 -f -k ${filename}
sed -i -e "1s/\x08/\x09/" ${filename}.gz
}
bin_gzip_ubootHead_firmHead()
{
local mkimage="tools/mkimage"
local file_full_path="$1"
local filename=$(basename ${file_full_path})
local mkimgArgs="$2"
local firmArgs="$3"
[ "$(dirname ${file_full_path})" == "$(pwd)" ] || cp ${file_full_path} .
k230_gzip ${filename}
#add uboot head
${mkimage} -A riscv -C gzip ${mkimgArgs} -d ${filename}.gz ug_${filename}
add_firmHead ug_${filename}
rm -rf ${filename} ${filename}.gz ug_${filename}
}
gen_rtt_bin()
{
local filename="fw_payload.bin"
local CONFIG_MEM_RTT_SYS_BASE="0x200000"
bin_gzip_ubootHead_firmHead "opensbi/build/platform/kendryte/fpgac908/firmware/${filename}" \
"-O opensbi -T multi -a ${CONFIG_MEM_RTT_SYS_BASE} -e ${CONFIG_MEM_RTT_SYS_BASE} -n rtt"
mv fn_ug_${filename} rtt_system.bin
}
build_sbi()
{
cc=~/.tools/gnu_gcc/riscv64-linux-musleabi_for_x86_64-pc-linux-gnu/bin/riscv64-unknown-linux-musl-
if [ -n "$1" ]; then
cc=$1
fi
cd opensbi && make FW_PAYLOAD_PATH=../rtthread.bin FW_FDT_PATH=hw.dtb PLATFORM=kendryte/fpgac908 CROSS_COMPILE=$cc
cd ..
}
build_sbi $1
gen_rtt_bin

491
bsp/k230/rtconfig.h Normal file
View File

@ -0,0 +1,491 @@
#ifndef RT_CONFIG_H__
#define RT_CONFIG_H__
/* RT-Thread Kernel */
#define RT_NAME_MAX 8
#define RT_USING_SMART
#define RT_CPUS_NR 1
#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
#define RT_TICK_PER_SECOND 1000
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR
#define RT_USING_HOOKLIST
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 8192
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 8192
#define RT_USING_CPU_USAGE_TRACER
/* kservice optimization */
/* end of kservice optimization */
/* klibc optimization */
#define RT_KLIBC_USING_PRINTF_LONGLONG
/* end of klibc optimization */
#define RT_USING_DEBUG
#define RT_DEBUGING_ASSERT
#define RT_DEBUGING_COLOR
#define RT_DEBUGING_CONTEXT
#define RT_USING_OVERFLOW_CHECK
/* Inter-Thread communication */
#define RT_USING_SEMAPHORE
#define RT_USING_MUTEX
#define RT_USING_EVENT
#define RT_USING_MAILBOX
#define RT_USING_MESSAGEQUEUE
/* end of Inter-Thread communication */
/* Memory Management */
#define RT_PAGE_MAX_ORDER 11
#define RT_USING_MEMPOOL
#define RT_USING_SLAB
#define RT_USING_SLAB_AS_HEAP
#define RT_USING_HEAP
/* end of Memory Management */
#define RT_USING_DEVICE
#define RT_USING_DEVICE_OPS
#define RT_USING_SCHED_THREAD_CTX
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 256
#define RT_CONSOLE_DEVICE_NAME "uart"
#define RT_VER_NUM 0x50200
#define RT_USING_STDC_ATOMIC
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
#define ARCH_CPU_64BIT
#define RT_USING_CACHE
#define ARCH_MM_MMU
#define KERNEL_VADDR_START 0xFFFFFFC000220000
#define ARCH_RISCV
#define ARCH_RISCV_FPU
#define ARCH_RISCV_FPU_D
#define ARCH_RISCV64
#define ARCH_USING_NEW_CTX_SWITCH
#define ARCH_REMAP_KERNEL
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
#define RT_MAIN_THREAD_STACK_SIZE 8192
#define RT_MAIN_THREAD_PRIORITY 10
#define RT_USING_MSH
#define RT_USING_FINSH
#define FINSH_USING_MSH
#define FINSH_THREAD_NAME "tshell"
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 8192
#define FINSH_USING_HISTORY
#define FINSH_HISTORY_LINES 5
#define FINSH_USING_SYMTAB
#define FINSH_CMD_SIZE 80
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
#define FINSH_USING_OPTION_COMPLETION
/* DFS: device virtual file system */
#define RT_USING_DFS
#define DFS_USING_POSIX
#define DFS_USING_WORKDIR
#define DFS_FD_MAX 16
#define RT_USING_DFS_V2
#define RT_USING_DFS_ELMFAT
/* elm-chan's FatFs, Generic FAT Filesystem Module */
#define RT_DFS_ELM_CODE_PAGE 437
#define RT_DFS_ELM_WORD_ACCESS
#define RT_DFS_ELM_USE_LFN_3
#define RT_DFS_ELM_USE_LFN 3
#define RT_DFS_ELM_LFN_UNICODE_0
#define RT_DFS_ELM_LFN_UNICODE 0
#define RT_DFS_ELM_MAX_LFN 255
#define RT_DFS_ELM_DRIVES 2
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
#define RT_DFS_ELM_REENTRANT
#define RT_DFS_ELM_MUTEX_TIMEOUT 3000
/* end of elm-chan's FatFs, Generic FAT Filesystem Module */
#define RT_USING_DFS_DEVFS
#define RT_USING_DFS_PTYFS
#define RT_USING_DFS_CROMFS
#define RT_USING_DFS_TMPFS
#define RT_USING_PAGECACHE
/* page cache config */
#define RT_PAGECACHE_COUNT 4096
#define RT_PAGECACHE_ASPACE_COUNT 1024
#define RT_PAGECACHE_PRELOAD 4
#define RT_PAGECACHE_HASH_NR 1024
#define RT_PAGECACHE_GC_WORK_LEVEL 90
#define RT_PAGECACHE_GC_STOP_LEVEL 70
/* end of page cache config */
/* end of DFS: device virtual file system */
/* Device Drivers */
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
#define RT_USING_SYSTEM_WORKQUEUE
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 8192
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_CPUTIME
#define RT_USING_CPUTIME_RISCV
#define CPUTIME_TIMER_FREQ 25000000
#define RT_USING_NULL
#define RT_USING_ZERO
#define RT_USING_RANDOM
#define RT_USING_RTC
#define RT_USING_SDIO
#define RT_SDIO_STACK_SIZE 8192
#define RT_SDIO_THREAD_PRIORITY 15
#define RT_MMCSD_STACK_SIZE 8192
#define RT_MMCSD_THREAD_PREORITY 22
#define RT_MMCSD_MAX_PARTITION 16
#define RT_USING_PIN
#define RT_USING_KTIME
/* end of Device Drivers */
/* C/C++ and POSIX layer */
/* ISO-ANSI C layer */
/* Timezone and Daylight Saving Time */
#define RT_LIBC_USING_LIGHT_TZ_DST
#define RT_LIBC_TZ_DEFAULT_HOUR 8
#define RT_LIBC_TZ_DEFAULT_MIN 0
#define RT_LIBC_TZ_DEFAULT_SEC 0
/* end of Timezone and Daylight Saving Time */
/* end of ISO-ANSI C layer */
/* POSIX (Portable Operating System Interface) layer */
#define RT_USING_POSIX_FS
#define RT_USING_POSIX_DEVIO
#define RT_USING_POSIX_STDIO
#define RT_USING_POSIX_POLL
#define RT_USING_POSIX_SELECT
#define RT_USING_POSIX_EPOLL
#define RT_USING_POSIX_SIGNALFD
#define RT_SIGNALFD_MAX_NUM 10
#define RT_USING_POSIX_SOCKET
#define RT_USING_POSIX_TERMIOS
#define RT_USING_POSIX_DELAY
#define RT_USING_POSIX_CLOCK
#define RT_USING_POSIX_TIMER
/* Interprocess Communication (IPC) */
/* Socket is in the 'Network' category */
/* end of Interprocess Communication (IPC) */
/* end of POSIX (Portable Operating System Interface) layer */
/* end of C/C++ and POSIX layer */
/* Network */
#define RT_USING_SAL
#define SAL_INTERNET_CHECK
/* Docking with protocol stacks */
#define SAL_USING_LWIP
/* end of Docking with protocol stacks */
#define SAL_USING_POSIX
#define RT_USING_NETDEV
#define NETDEV_USING_IFCONFIG
#define NETDEV_USING_PING
#define NETDEV_USING_NETSTAT
#define NETDEV_USING_AUTO_DEFAULT
#define NETDEV_IPV4 1
#define NETDEV_IPV6 0
#define RT_USING_LWIP
#define RT_USING_LWIP212
#define RT_USING_LWIP_VER_NUM 0x20102
#define RT_LWIP_MEM_ALIGNMENT 8
#define RT_LWIP_IGMP
#define RT_LWIP_ICMP
#define RT_LWIP_DNS
#define RT_LWIP_DHCP
#define IP_SOF_BROADCAST 1
#define IP_SOF_BROADCAST_RECV 1
/* Static IPv4 Address */
#define RT_LWIP_IPADDR "192.168.1.30"
#define RT_LWIP_GWADDR "192.168.1.1"
#define RT_LWIP_MSKADDR "255.255.255.0"
/* end of Static IPv4 Address */
#define RT_LWIP_UDP
#define RT_LWIP_TCP
#define RT_LWIP_RAW
#define RT_MEMP_NUM_NETCONN 8
#define RT_LWIP_PBUF_NUM 16
#define RT_LWIP_RAW_PCB_NUM 4
#define RT_LWIP_UDP_PCB_NUM 4
#define RT_LWIP_TCP_PCB_NUM 4
#define RT_LWIP_TCP_SEG_NUM 40
#define RT_LWIP_TCP_SND_BUF 8196
#define RT_LWIP_TCP_WND 8196
#define RT_LWIP_TCPTHREAD_PRIORITY 10
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
#define RT_LWIP_TCPTHREAD_STACKSIZE 8192
#define RT_LWIP_ETHTHREAD_PRIORITY 12
#define RT_LWIP_ETHTHREAD_STACKSIZE 8192
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define RT_LWIP_NETIF_NAMESIZE 6
#define SO_REUSE 1
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_SNDTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_SO_LINGER 0
#define LWIP_NETIF_LOOPBACK 0
#define RT_LWIP_USING_PING
/* end of Network */
/* Memory protection */
/* end of Memory protection */
/* Utilities */
#define RT_USING_RESOURCE_ID
#define RT_USING_ADT
#define RT_USING_ADT_AVL
#define RT_USING_ADT_BITMAP
#define RT_USING_ADT_HASHMAP
#define RT_USING_ADT_REF
/* end of Utilities */
#define RT_USING_LWP
#define LWP_DEBUG
#define LWP_DEBUG_INIT
#define RT_LWP_MAX_NR 30
#define LWP_TASK_STACK_SIZE 16384
#define RT_CH_MSG_MAX_NR 1024
#define LWP_TID_MAX_NR 64
#define RT_LWP_SHM_MAX_NR 64
#define RT_USING_LDSO
#define LWP_USING_TERMINAL
#define LWP_PTY_MAX_PARIS_LIMIT 64
/* Memory management */
/* end of Memory management */
/* Using USB legacy version */
/* end of Using USB legacy version */
/* end of RT-Thread Components */
/* RT-Thread Utestcases */
/* end of RT-Thread Utestcases */
/* RT-Thread online packages */
/* IoT - internet of things */
/* Wi-Fi */
/* Marvell WiFi */
/* end of Marvell WiFi */
/* Wiced WiFi */
/* end of Wiced WiFi */
/* CYW43012 WiFi */
/* end of CYW43012 WiFi */
/* BL808 WiFi */
/* end of BL808 WiFi */
/* CYW43439 WiFi */
/* end of CYW43439 WiFi */
/* end of Wi-Fi */
/* IoT Cloud */
/* end of IoT Cloud */
/* end of IoT - internet of things */
/* security packages */
/* end of security packages */
/* language packages */
/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */
/* XML: Extensible Markup Language */
/* end of XML: Extensible Markup Language */
/* end of language packages */
/* multimedia packages */
/* LVGL: powerful and easy-to-use embedded GUI library */
/* end of LVGL: powerful and easy-to-use embedded GUI library */
/* u8g2: a monochrome graphic library */
/* end of u8g2: a monochrome graphic library */
/* end of multimedia packages */
/* tools packages */
/* end of tools packages */
/* system packages */
/* enhanced kernel services */
/* end of enhanced kernel services */
/* acceleration: Assembly language or algorithmic acceleration packages */
/* end of acceleration: Assembly language or algorithmic acceleration packages */
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
/* Micrium: Micrium software products porting for RT-Thread */
/* end of Micrium: Micrium software products porting for RT-Thread */
/* end of system packages */
/* peripheral libraries and drivers */
/* HAL & SDK Drivers */
/* STM32 HAL & SDK Drivers */
/* end of STM32 HAL & SDK Drivers */
/* Infineon HAL Packages */
/* end of Infineon HAL Packages */
/* Kendryte SDK */
/* end of Kendryte SDK */
/* end of HAL & SDK Drivers */
/* sensors drivers */
/* end of sensors drivers */
/* touch drivers */
/* end of touch drivers */
/* end of peripheral libraries and drivers */
/* AI packages */
/* end of AI packages */
/* Signal Processing and Control Algorithm Packages */
/* end of Signal Processing and Control Algorithm Packages */
/* miscellaneous packages */
/* project laboratory */
/* end of project laboratory */
/* samples: kernel and components samples */
/* end of samples: kernel and components samples */
/* entertainment: terminal games and other interesting software packages */
/* end of entertainment: terminal games and other interesting software packages */
#define PKG_USING_ZLIB
#define PKG_USING_ZLIB_LATEST_VERSION
/* end of miscellaneous packages */
/* Arduino libraries */
/* Projects and Demos */
/* end of Projects and Demos */
/* Sensors */
/* end of Sensors */
/* Display */
/* end of Display */
/* Timing */
/* end of Timing */
/* Data Processing */
/* end of Data Processing */
/* Data Storage */
/* Communication */
/* end of Communication */
/* Device Control */
/* end of Device Control */
/* Other */
/* end of Other */
/* Signal IO */
/* end of Signal IO */
/* Uncategorized */
/* end of Arduino libraries */
/* end of RT-Thread online packages */
/* Drivers Configuration */
/* end of Drivers Configuration */
#define BOARD_fpgac908
#define __STACKSIZE__ 8192
#define C908_PLIC_PHY_ADDR 0xF00000000
#define BSP_ROOTFS_TYPE_CROMFS
#endif

54
bsp/k230/rtconfig.py Normal file
View File

@ -0,0 +1,54 @@
import os
# toolchains options
ARCH ='risc-v'
VENDOR ='t-head'
CPU ='c908'
CROSS_TOOL ='gcc'
RTT_ROOT = os.getenv('RTT_ROOT', r'../..')
if os.getenv('RTT_CC'):
CROSS_TOOL = os.getenv('RTT_CC')
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = r'/opt/Xuantie-900-gcc-elf-newlib-x86_64-V2.8.1/bin'
else:
print('Please make sure your toolchains is GNU GCC!')
exit(0)
EXEC_PATH = os.getenv('RTT_EXEC_PATH', EXEC_PATH)
BUILD = 'debug'
if PLATFORM == 'gcc':
# toolchains
#PREFIX = 'riscv64-unknown-elf-'
PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-unknown-linux-musl-'
CC = PREFIX + 'gcc'
CXX = PREFIX + 'g++'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'elf'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64'
CFLAGS = DEVICE + ' -Wno-cpp -fvar-tracking -ffreestanding -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -D_POSIX_SOURCE '
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__'
LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds' + ' -lsupc++ -lgcc -static'
CPATH = ''
LPATH = ''
if BUILD == 'debug':
CFLAGS += ' -O2 -g -gdwarf-2'
AFLAGS += ' -g -gdwarf-2'
else:
CFLAGS += ' -O2 -g -gdwarf-2'
CXXFLAGS = CFLAGS
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'