diff --git a/bsp/bouffalo_lab/README.md b/bsp/bouffalo_lab/README.md index 85425812c3..0f5c8b4a62 100755 --- a/bsp/bouffalo_lab/README.md +++ b/bsp/bouffalo_lab/README.md @@ -161,7 +161,7 @@ Windows下推荐使用[env工具][1],在console下进入bsp/bouffalo_lab/bl61x 其中: -- bl616:芯片名称 +- bl616:芯片名称(bl808:三核同时下载;或者输入:bl808-m0/bl808-lp/bl808-d0分别烧录对应的核,但是m0必须要烧录才能运行) - /dev/ttyUSB1:下载串口号,linux下为/dev/ttyUSBx或/dev/ttyACMx,windows下为COMx diff --git a/bsp/bouffalo_lab/bl61x/board/Kconfig b/bsp/bouffalo_lab/bl61x/board/Kconfig index 03b674a334..3adc422383 100755 --- a/bsp/bouffalo_lab/bl61x/board/Kconfig +++ b/bsp/bouffalo_lab/bl61x/board/Kconfig @@ -13,4 +13,16 @@ config BSP_USING_ROMAPI config BSP_USING_PSRAM bool "Enable PSRAM" - default n \ No newline at end of file + default n + +choice + prompt "Choose Module" + + default BSP_USING_BL61X_MODULE_DEFAULT + + config BSP_USING_BL61X_MODULE_DEFAULT + bool "Default Module" + config BSP_USING_BL61X_MODULE_M0P + bool "M0P Module" + select BSP_USING_PSRAM +endchoice diff --git a/bsp/bouffalo_lab/bl61x/board/board.c b/bsp/bouffalo_lab/bl61x/board/board.c index 1216b77be0..c68319eaad 100644 --- a/bsp/bouffalo_lab/bl61x/board/board.c +++ b/bsp/bouffalo_lab/bl61x/board/board.c @@ -129,7 +129,11 @@ static void systick_isr(void) void rt_hw_board_init(void) { +#if defined (BSP_USING_BL61X_MODULE_DEFAULT) bflb_flash_init(); +#elif defined (BSP_USING_BL61X_MODULE_M0P) + +#endif system_clock_init(); peripheral_clock_init(); diff --git a/bsp/bouffalo_lab/bl61x/board/fw_header.c b/bsp/bouffalo_lab/bl61x/board/fw_header.c index caac91b0f0..b4f0a5b083 100644 --- a/bsp/bouffalo_lab/bl61x/board/fw_header.c +++ b/bsp/bouffalo_lab/bl61x/board/fw_header.c @@ -6,7 +6,11 @@ __attribute__((section(".fw_header"))) struct bootheader_t fw_header = { /*flash config */ .flash_cfg.magiccode = 0x47464346, .flash_cfg.cfg.ioMode = 0x11, /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */ +#if defined (BSP_USING_BL61X_MODULE_DEFAULT) .flash_cfg.cfg.cReadSupport = 0x00, /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */ +#elif defined (BSP_USING_BL61X_MODULE_M0P) + .flash_cfg.cfg.cReadSupport = 0x01, /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */ +#endif .flash_cfg.cfg.clkDelay = 0x01, /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */ .flash_cfg.cfg.clkInvert = 0x01, /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */ .flash_cfg.cfg.resetEnCmd = 0x66, /*!< Flash enable reset command */ diff --git a/bsp/bouffalo_lab/bl61x/flash_prog_cfg.ini b/bsp/bouffalo_lab/bl61x/flash_prog_cfg.ini index 41aaca3979..9dacfa8a0c 100755 --- a/bsp/bouffalo_lab/bl61x/flash_prog_cfg.ini +++ b/bsp/bouffalo_lab/bl61x/flash_prog_cfg.ini @@ -1,6 +1,6 @@ [cfg] # 0: no erase, 1:programmed section erase, 2: chip erase -erase = 2 +erase = 1 # skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated skip_mode = 0x0, 0x0 # 0: not use isp mode, #1: isp mode diff --git a/bsp/bouffalo_lab/bouffalo_flash_cube.sh b/bsp/bouffalo_lab/bouffalo_flash_cube.sh index 5ddc73f039..b1a7f4fcfc 100755 --- a/bsp/bouffalo_lab/bouffalo_flash_cube.sh +++ b/bsp/bouffalo_lab/bouffalo_flash_cube.sh @@ -31,6 +31,15 @@ then elif [ $CHIPNAME = 'bl808' ] then CONFIG_DIR=./bl808 +elif [ $CHIPNAME = 'bl808-m0' ] +then + CONFIG_DIR=./bl808/m0 +elif [ $CHIPNAME = 'bl808-lp' ] +then + CONFIG_DIR=./bl808/lp +elif [ $CHIPNAME = 'bl808-d0' ] +then + CONFIG_DIR=./bl808/d0 else echo "chip name error" fi diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig b/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig index 7564dd622e..481bc1669d 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig +++ b/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig @@ -1,5 +1,9 @@ menu "General Drivers Configuration" + config BSP_DRIVER_DEBUG + bool "Enable Driver Debug Log Output" + default n + menu "General Purpose UARTs" menuconfig BSP_USING_UART0 bool "Enable UART0" @@ -1400,6 +1404,11 @@ menu "General Drivers Configuration" config BSP_USING_ON_CHIP_FLASH bool "Enable On-Chip FLASH" default n + config BSP_USING_SDH + select RT_USING_SDIO + select RT_USING_DFS + bool "Enable Secure Digital Host Controller(SDH)" + default n menuconfig BSP_USING_FS bool "Enable File System" select RT_USING_DFS diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/SConscript b/bsp/bouffalo_lab/libraries/rt_drivers/SConscript index bbfa1a0a76..336bc2370b 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/SConscript +++ b/bsp/bouffalo_lab/libraries/rt_drivers/SConscript @@ -40,6 +40,9 @@ if GetDepend('BSP_USING_SPI'): if GetDepend('BSP_USING_ON_CHIP_FLASH'): src += ['drv_flash.c'] +if GetDepend('RT_USING_DFS'): + src += ['drv_sdh.c'] + group = DefineGroup('rt_drivers', src, depend = [''], CPPPATH = CPPPATH) objs = [group] diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.c new file mode 100644 index 0000000000..46504bc78d --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.c @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-05-28 flyingcys the first version + */ +#include +#include "board.h" + +#ifdef RT_USING_DFS + +#define LOG_TAG "drv.sdh" +#ifdef BSP_DRIVER_DEBUG +#define DBG_LEVEL DBG_LOG +#else +#define DBG_LEVEL DBG_INFO +#endif +#include + +#include +#include +#include "drv_sdh.h" + +#if defined(BL808) +#include "bl808_common.h" +#include "bl808_glb.h" +#include "bl808_sdh.h" +#elif defined(BL606P) +#include "bl606p_common.h" +#include "bl606p_glb.h" +#include "bl606p_sdh.h" +#elif defined(BL616) +#include "bl616_common.h" +#include "bl616_glb.h" +#include "bl616_sdh.h" +#elif defined(BL628) +#include "bl628_common.h" +#include "bl628_glb.h" +#include "bl628_smih.h" +#endif + +#include "bflb_mtimer.h" +#include "bflb_l1c.h" + +#define SDIO_BUFF_SIZE 4096 +static uint8_t sdh_buffer[SDIO_BUFF_SIZE]; + +#define SDIO_CMDTIMEOUT_MS (2000) + +static uint32_t sdhClockInit = 100ul; +static uint32_t sdhClockSrc = 100ul; + +static SDH_Cfg_Type SDH_Cfg_Type_Instance; +static SDH_DMA_Cfg_Type SDH_DMA_Cfg_TypeInstance; +/*causion: ADMA related variables must on OCRAM or shared ram*/ +static __attribute__((aligned(32), section(".noncacheable"))) SDH_ADMA2_Desc_Type adma2Entries[16]; + +typedef enum { + SD_OK = 0, + SD_CMD_ERROR, + SD_DataCfg_ERROR, + SD_WAITING, +} SD_Error; + +#ifdef BSP_USING_BL808 + +static void sdh_clock_init(void) +{ + PERIPHERAL_CLOCK_SDH_ENABLE(); + uint32_t tmp_val; + tmp_val = BL_RD_REG(PDS_BASE, PDS_CTL5); + uint32_t tmp_val2 = BL_GET_REG_BITS_VAL(tmp_val, PDS_CR_PDS_GPIO_KEEP_EN); + tmp_val2 &= ~(1 << 0); + tmp_val = BL_SET_REG_BITS_VAL(tmp_val, PDS_CR_PDS_GPIO_KEEP_EN, tmp_val2); + BL_WR_REG(PDS_BASE, PDS_CTL5, tmp_val); + GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_SDH); +} + +static void sdh_gpio_init(void) +{ + struct bflb_device_s *gpio; + + gpio = bflb_device_get_by_name("gpio"); + bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_1, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_2, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_3, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_5, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); +} + +#elif defined(BSP_USING_BL61X) + +static void sdh_clock_init(void) +{ + PERIPHERAL_CLOCK_SDH_ENABLE(); + GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_EXT_SDH); +} + +static void sdh_gpio_init(void) +{ + struct bflb_device_s *gpio; + + gpio = bflb_device_get_by_name("gpio"); + bflb_gpio_init(gpio, GPIO_PIN_10, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_11, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_13, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); + bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2); +} +#else +#error "The Current Chip Does Not Support SDH!" +#endif + +static void sdh_set_bus_width(SDH_Data_Bus_Width_Type width) +{ + SDH_Cfg_Type_Instance.vlot18Enable = DISABLE; + SDH_Cfg_Type_Instance.highSpeed = ENABLE; + SDH_Cfg_Type_Instance.dataWidth = width; + SDH_Cfg_Type_Instance.volt = SDH_VOLTAGE_3P3V; + SDH_Cfg_Type_Instance.srcClock = sdhClockSrc; + SDH_Cfg_Type_Instance.busClock = sdhClockInit; + SDH_Ctrl_Init(&SDH_Cfg_Type_Instance); +} + +static void sdio_host_init(void) +{ + GLB_Set_SDH_CLK(ENABLE, GLB_SDH_CLK_WIFIPLL_96M, 7); + + /* initialise SDH controller*/ + SDH_Cfg_Type_Instance.vlot18Enable = DISABLE; + SDH_Cfg_Type_Instance.highSpeed = ENABLE; + SDH_Cfg_Type_Instance.dataWidth = SDH_DATA_BUS_WIDTH_1BIT; + SDH_Cfg_Type_Instance.volt = SDH_VOLTAGE_3P3V; + SDH_Cfg_Type_Instance.srcClock = sdhClockSrc; + SDH_Cfg_Type_Instance.busClock = sdhClockInit; + SDH_Ctrl_Init(&SDH_Cfg_Type_Instance); + + /*setup timeout counter*/ + SDH_Set_Timeout(0x0e); +} + +static SDH_Resp_Type sdio_host_get_resp_type(struct rt_mmcsd_cmd *cmd) +{ + SDH_Resp_Type respType; + + switch (resp_type(cmd)) + { + case RESP_NONE: + respType = SDH_RESP_NONE; + break; + + case RESP_R1: + respType = SDH_RESP_R1; + break; + + case RESP_R1B: + respType = SDH_RESP_R1B; + break; + + case RESP_R2: + respType = SDH_RESP_R2; + break; + + case RESP_R3: + respType = SDH_RESP_R3; + break; + + case RESP_R4: + respType = SDH_RESP_R4; + break; + + case RESP_R5: + respType = SDH_RESP_R5; + break; + + case RESP_R6: + respType = SDH_RESP_R6; + break; + + case RESP_R7: + respType = SDH_RESP_R7; + break; + + default: + respType = SDH_RESP_NONE; + break; + } + + return respType; +} + +static rt_err_t sdio_host_send_command(SDH_CMD_Cfg_Type *SDH_CMD_Cfg_TypeInstance) +{ + SD_Error sd_status; + uint32_t time_node; + + SDH_ClearIntStatus(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS); + + SDH_SendCommand(SDH_CMD_Cfg_TypeInstance); + + time_node = (uint32_t)bflb_mtimer_get_time_ms(); + + uint32_t intFlag; + while (1) + { + intFlag = SDH_GetIntStatus(); + if (intFlag & SDH_INT_CMD_ERRORS) + { + sd_status = SD_CMD_ERROR; + break; + } + else if (intFlag & SDH_INT_CMD_COMPLETED) + { + sd_status = SD_OK; + break; + } + else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) + { + LOG_D("SDH send CMD%ld timeout: %ld ms", SDH_CMD_Cfg_TypeInstance->index, (uint32_t)bflb_mtimer_get_time_ms() - time_node); + return -RT_ETIMEOUT; + } + BL_DRV_DUMMY; + BL_DRV_DUMMY; + } + SDH_ClearIntStatus(intFlag & (SDH_INT_CMD_ERRORS | SDH_INT_CMD_COMPLETED)); + + if (sd_status != SD_OK) + { + LOG_E("SDH send CMD%ld error", SDH_CMD_Cfg_TypeInstance->index); + return -RT_ERROR; + } + else + { + LOG_D("SDH send CMD%ld success", SDH_CMD_Cfg_TypeInstance->index); + + SDH_CMD_Cfg_TypeInstance->response[0] = BL_RD_REG(SDH_BASE, SDH_SD_RESP_0); + SDH_CMD_Cfg_TypeInstance->response[1] = BL_RD_REG(SDH_BASE, SDH_SD_RESP_2); + SDH_CMD_Cfg_TypeInstance->response[2] = BL_RD_REG(SDH_BASE, SDH_SD_RESP_4); + SDH_CMD_Cfg_TypeInstance->response[3] = BL_RD_REG(SDH_BASE, SDH_SD_RESP_6); + } + + return RT_EOK; +} + +static rt_err_t SDH_CardTransferNonBlocking(SDH_DMA_Cfg_Type *dmaCfg, SDH_Trans_Cfg_Type *transfer) +{ + rt_err_t ret = RT_EOK; + SDH_Stat_Type stat = SDH_STAT_SUCCESS; + + stat = SDH_TransferNonBlocking(dmaCfg, transfer); + if (stat != SDH_STAT_SUCCESS) { + LOG_E("SDH_TransferNonBlocking error:%d", stat); + return -RT_ERROR; + } + + /* Flush ADMA2-descriptor-table to RAM, Otherwise ADMA2 will fail */ + bflb_l1c_dcache_clean_range((void *)(dmaCfg->admaEntries), dmaCfg->maxEntries * sizeof(SDH_ADMA2_Desc_Type)); + + ret = sdio_host_send_command(transfer->cmdCfg); + if (ret != RT_EOK) + { + LOG_E("sdio_host_send_command error:%d", transfer->cmdCfg->index); + return ret; + } + + rt_uint32_t intFlag; + SD_Error sd_status; + rt_uint32_t time_node; + + time_node = (uint32_t)bflb_mtimer_get_time_ms(); + while (1) + { + intFlag = SDH_GetIntStatus(); + if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR || intFlag & SDH_INT_AUTO_CMD12_ERROR) + { + sd_status = SD_CMD_ERROR; + break; + + } + else if (intFlag & SDH_INT_DATA_COMPLETED) + { + sd_status = SD_OK; + break; + + } + else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) + { + LOG_E("SDH read data timeout: %ld ms", (uint32_t)bflb_mtimer_get_time_ms() - time_node); + return -RT_ETIMEOUT; + } + BL_DRV_DUMMY; + BL_DRV_DUMMY; + } + SDH_ClearIntStatus(intFlag); + + if (sd_status != SD_OK) + { + LOG_E("sd_status :%d", sd_status); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t rt_hw_sdh_data_transfer(struct rt_mmcsd_host *host, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data) +{ + rt_err_t ret = RT_EOK; + SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance; + SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance = {0}; + SDH_Trans_Cfg_Type SDH_Trans_Cfg_TypeInstance = { &SDH_Data_Cfg_TypeInstance, &SDH_CMD_Cfg_TypeInstance }; + +#if defined(BL808) || defined(BL606P) + /* BL808/BL606 supports only 8-byte aligned addresses */ + if ((uintptr_t)data->buf % 8 != 0) + { + return -RT_EINVAL; + } +#endif + + SDH_CMD_Cfg_TypeInstance.index = cmd->cmd_code; + SDH_CMD_Cfg_TypeInstance.argument = cmd->arg; + SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL; + SDH_CMD_Cfg_TypeInstance.respType = sdio_host_get_resp_type(cmd); + SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT; + + /*set data parameter */ + SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE; + SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE; + SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE; + SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL; + SDH_Data_Cfg_TypeInstance.blockSize = data->blksize; + SDH_Data_Cfg_TypeInstance.blockCount = data->blks; + + if (cmd->cmd_code == READ_SINGLE_BLOCK || cmd->cmd_code == READ_MULTIPLE_BLOCK) + { + SDH_Data_Cfg_TypeInstance.rxDataLen = 0; + SDH_Data_Cfg_TypeInstance.rxData = (rt_uint32_t *)sdh_buffer; + // SDH_Data_Cfg_TypeInstance.rxData = (rt_uint32_t *)data->buf; + SDH_Data_Cfg_TypeInstance.txDataLen = 0; + SDH_Data_Cfg_TypeInstance.txData = NULL; + } + else + { + rt_memcpy((void *)sdh_buffer, (void *)data->buf, data->blksize); + SDH_Data_Cfg_TypeInstance.rxDataLen = 0; + SDH_Data_Cfg_TypeInstance.rxData = NULL; + SDH_Data_Cfg_TypeInstance.txDataLen = 0; + // SDH_Data_Cfg_TypeInstance.txData = (rt_uint32_t *)data->buf; + SDH_Data_Cfg_TypeInstance.txData = (rt_uint32_t *)sdh_buffer; + } + + /*set parameters for SDH_DMA_Cfg_TypeInstance*/ + SDH_DMA_Cfg_TypeInstance.dmaMode = SDH_DMA_MODE_ADMA2; + SDH_DMA_Cfg_TypeInstance.burstSize = SDH_BURST_SIZE_128_BYTES; + + if (cmd->cmd_code == READ_SINGLE_BLOCK || cmd->cmd_code == READ_MULTIPLE_BLOCK) + { + SDH_DMA_Cfg_TypeInstance.fifoThreshold = SDH_BURST_SIZE_128_BYTES; + } + else + SDH_DMA_Cfg_TypeInstance.fifoThreshold = SDH_FIFO_THRESHOLD_256_BYTES; + + SDH_DMA_Cfg_TypeInstance.admaEntries = (rt_uint32_t *)adma2Entries; + SDH_DMA_Cfg_TypeInstance.maxEntries = sizeof(adma2Entries) / sizeof(adma2Entries[0]); + + if (data->flags & DATA_DIR_WRITE) + { + bflb_l1c_dcache_clean_range((void *)(data->buf), data->blksize * data->blks); + } + + ret = SDH_CardTransferNonBlocking(&SDH_DMA_Cfg_TypeInstance, &SDH_Trans_Cfg_TypeInstance); + if (ret != RT_EOK) + { + LOG_E("SDH_CardTransferNonBlocking error:%d", ret); + return ret; + } + + if (resp_type(cmd) != RESP_NONE) + { + cmd->resp[0] = SDH_CMD_Cfg_TypeInstance.response[0]; + LOG_D("resp[0]: %08x", cmd->resp[0]); + } + + if (data->flags & DATA_DIR_READ) + { + bflb_l1c_dcache_invalidate_range((void *)(sdh_buffer), data->blksize * data->blks); + rt_memcpy(data->buf, sdh_buffer, data->blks * data->blksize); + } + + return RT_EOK; +} + +static rt_err_t rt_hw_sdh_cmd_transfer(struct rt_mmcsd_host *host, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data) +{ + rt_err_t ret = RT_EOK; + SDH_Stat_Type stat = SDH_STAT_SUCCESS; + SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance; + SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance = {0}; + + if (data != RT_NULL) + { + SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE; + SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE; + SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE; + SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL; + SDH_Data_Cfg_TypeInstance.blockSize = data->blksize; + SDH_Data_Cfg_TypeInstance.blockCount = data->blks; + SDH_Data_Cfg_TypeInstance.rxDataLen = 0; + SDH_Data_Cfg_TypeInstance.rxData = (rt_uint32_t *)data->buf; + SDH_Data_Cfg_TypeInstance.txDataLen = 0; + SDH_Data_Cfg_TypeInstance.txData = NULL; + + /* Config the data transfer parameter */ + stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance); + if (stat != SDH_STAT_SUCCESS) + { + return -RT_ERROR; + } + + SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT; + } + else + SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE; + + SDH_CMD_Cfg_TypeInstance.index = cmd->cmd_code; + SDH_CMD_Cfg_TypeInstance.argument = cmd->arg; + SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL; + SDH_CMD_Cfg_TypeInstance.respType = sdio_host_get_resp_type(cmd); + + ret = sdio_host_send_command(&SDH_CMD_Cfg_TypeInstance); + if (ret != RT_EOK) + { + memset(cmd->resp, 0, sizeof(cmd->resp)); + return ret; + } + + if (resp_type(cmd) != RESP_NONE) + { + if (resp_type(cmd) == RESP_R2) + { + cmd->resp[0] = ((SDH_CMD_Cfg_TypeInstance.response[3] << 8) & ~0xff); + cmd->resp[0] |= ((SDH_CMD_Cfg_TypeInstance.response[2] >> 24) & 0xff); + cmd->resp[1] = ((SDH_CMD_Cfg_TypeInstance.response[2] << 8) & ~0xff); + cmd->resp[1] |= ((SDH_CMD_Cfg_TypeInstance.response[1] >> 24) & 0xff); + cmd->resp[2] = ((SDH_CMD_Cfg_TypeInstance.response[1] << 8) & ~0xff); + cmd->resp[2] |= ((SDH_CMD_Cfg_TypeInstance.response[0] >> 24) & 0xff); + cmd->resp[3] = ((SDH_CMD_Cfg_TypeInstance.response[3] << 8) & ~0xff); + + LOG_D("resp[0]: %08x %08x %08x %08x", cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); + } + else + { + cmd->resp[0] = SDH_CMD_Cfg_TypeInstance.response[0]; + LOG_D("resp[0]: %08x", cmd->resp[0]); + } + } + + if (data != RT_NULL) + { + SD_Error sd_status; + uint32_t time_node; + time_node = (uint32_t)bflb_mtimer_get_time_ms(); + uint32_t intFlag; + while (1) + { + intFlag = SDH_GetIntStatus(); + if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) + { + sd_status = SD_DataCfg_ERROR; + break; + + } + else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) + { + sd_status = SD_OK; + break; + + } + else if ((uint32_t)bflb_mtimer_get_time_ms() - time_node > SDIO_CMDTIMEOUT_MS) + { + LOG_E("SDH get csr data timeout: %ld ms", (uint32_t)bflb_mtimer_get_time_ms() - time_node); + return -RT_ETIMEOUT; + } + BL_DRV_DUMMY; + BL_DRV_DUMMY; + } + SDH_ClearIntStatus(intFlag); + + if (sd_status != SD_OK) + { + return -RT_ERROR; + } + + if (data->flags & DATA_DIR_READ) + { + rt_uint32_t ret = SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance); + if (ret <= 0) + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static void rt_hw_sdh_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + RT_ASSERT(host != RT_NULL); + RT_ASSERT(req != RT_NULL); + + if (req->cmd != RT_NULL) + { + struct rt_mmcsd_cmd *cmd = req->cmd; + struct rt_mmcsd_data *data = req->data; + + LOG_D("[%s%s%s%s%s]REQ: CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c addr:%08x, blks:%d, blksize:%d datalen:%d", + (host->card == RT_NULL) ? "Unknown" : "", + (host->card) && (host->card->card_type == CARD_TYPE_MMC) ? "MMC" : "", + (host->card) && (host->card->card_type == CARD_TYPE_SD) ? "SD" : "", + (host->card) && (host->card->card_type == CARD_TYPE_SDIO) ? "SDIO" : "", + (host->card) && (host->card->card_type == CARD_TYPE_SDIO_COMBO) ? "SDIO_COMBO" : "", + cmd->cmd_code, + cmd->arg, + resp_type(cmd) == RESP_NONE ? "NONE" : "", + resp_type(cmd) == RESP_R1 ? "R1" : "", + resp_type(cmd) == RESP_R1B ? "R1B" : "", + resp_type(cmd) == RESP_R2 ? "R2" : "", + resp_type(cmd) == RESP_R3 ? "R3" : "", + resp_type(cmd) == RESP_R4 ? "R4" : "", + resp_type(cmd) == RESP_R5 ? "R5" : "", + resp_type(cmd) == RESP_R6 ? "R6" : "", + resp_type(cmd) == RESP_R7 ? "R7" : "", + data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-', + data ? data->buf : 0, + data ? data->blks : 0, + data ? data->blksize : 0, + data ? data->blks * data->blksize : 0); + + if (cmd->cmd_code == READ_SINGLE_BLOCK || cmd->cmd_code == READ_MULTIPLE_BLOCK || \ + cmd->cmd_code == WRITE_BLOCK || cmd->cmd_code == WRITE_MULTIPLE_BLOCK) + { + cmd->err = rt_hw_sdh_data_transfer(host, cmd, data); + } + else + { + cmd->err = rt_hw_sdh_cmd_transfer(host, cmd, data); + } + } + + if (req->stop != RT_NULL) + { + struct rt_mmcsd_cmd *stop = req->stop; + + stop->err = rt_hw_sdh_cmd_transfer(host, stop, RT_NULL); + } + + mmcsd_req_complete(host); +} + +static void rt_hw_sdh_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + rt_uint32_t clk; + + RT_ASSERT(host != RT_NULL); + RT_ASSERT(io_cfg != RT_NULL); + + clk = io_cfg->clock; + + LOG_D("clk:%d width:%s%s%s power:%s%s%s", + clk, + io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "", + io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "", + io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "", + io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "", + io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "", + io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : "" + ); + + /* clock */ + if (clk > host->freq_max) + clk = host->freq_max; + + if (clk < host->freq_min) + clk = host->freq_min; + + /* power mode */ + switch (io_cfg->power_mode) + { + case MMCSD_POWER_UP: + break; + + case MMCSD_POWER_ON: + SDH_Powon(); + break; + + case MMCSD_POWER_OFF: + break; + + default: + break; + } + + /* bus width */ + switch (io_cfg->bus_width) + { + case MMCSD_BUS_WIDTH_1: + sdh_set_bus_width(SDH_DATA_BUS_WIDTH_1BIT); + break; + + case MMCSD_BUS_WIDTH_4: + sdh_set_bus_width(SDH_DATA_BUS_WIDTH_4BITS); + break; + + case MMCSD_BUS_WIDTH_8: + sdh_set_bus_width(SDH_DATA_BUS_WIDTH_8BITS); + break; + + default: + LOG_E("nonsupport bus width: %d", io_cfg->bus_width); + break; + } +} + +static const struct rt_mmcsd_host_ops ops = +{ + rt_hw_sdh_request, + rt_hw_sdh_iocfg, + RT_NULL, + RT_NULL, +}; + +int rt_hw_sdh_init(void) +{ + struct rt_mmcsd_host *host; + + host = mmcsd_alloc_host(); + RT_ASSERT(host != RT_NULL); + + sdh_clock_init(); + sdh_gpio_init(); + + /* reset SDH controller*/ + SDH_Reset(); + + sdio_host_init(); + + /* set host default attributes */ + host->ops = &ops; + host->freq_min = 40 * 1000; + host->freq_max = 50 * 1000 * 1000; + host->valid_ocr = VDD_31_32 | VDD_32_33 | VDD_33_34; + host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_BUSWIDTH_4; + host->max_seg_size = SDIO_BUFF_SIZE; + host->max_dma_segs = 1; + host->max_blk_size = 512; + host->max_blk_count = 512; + + /* link up host and sdio */ + host->private_data = host; + + mmcsd_change(host); + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_sdh_init); + +#endif /* RT_USING_DFS */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.h b/bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.h new file mode 100755 index 0000000000..74eda7cb3d --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.h @@ -0,0 +1,16 @@ + /* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-05-28 flyingcys the first version + */ + +#ifndef __DRV_SDH_H__ +#define __DRV_SDH_H__ + +int rt_hw_sdh_init(void); + +#endif /* __DRV_SDH_H__ */