summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflyingcys <[email protected]>2023-05-29 09:47:25 +0800
committerGitHub <[email protected]>2023-05-29 09:47:25 +0800
commit8e4a8404e3f09faf9433e9a6112c5b8f60800e0f (patch)
treed137a9c2fd1c05e346c500c0acfb637b24cf66a0
parent7a9ee5af20299e0abf46d6bdcd9d19d18d2bb1fe (diff)
[bsp/bouffalo_lab]add sdcard driver (#7577)
-rwxr-xr-xbsp/bouffalo_lab/README.md2
-rwxr-xr-xbsp/bouffalo_lab/bl61x/board/Kconfig14
-rw-r--r--bsp/bouffalo_lab/bl61x/board/board.c4
-rw-r--r--bsp/bouffalo_lab/bl61x/board/fw_header.c4
-rwxr-xr-xbsp/bouffalo_lab/bl61x/flash_prog_cfg.ini2
-rwxr-xr-xbsp/bouffalo_lab/bouffalo_flash_cube.sh9
-rwxr-xr-xbsp/bouffalo_lab/libraries/rt_drivers/Kconfig9
-rwxr-xr-xbsp/bouffalo_lab/libraries/rt_drivers/SConscript3
-rw-r--r--bsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.c671
-rwxr-xr-xbsp/bouffalo_lab/libraries/rt_drivers/drv_sdh.h16
10 files changed, 731 insertions, 3 deletions
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 <rtdevice.h>
+#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 <rtdbg.h>
+
+#include <drivers/mmcsd_core.h>
+#include <drivers/sdio.h>
+#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__ */