diff --git a/bsp/imx6ull-artpi-smart/.config b/bsp/imx6ull-artpi-smart/.config index 1fb9ad579f7c69cb976086f394d5f16b70994c30..fd6a0470f75e5324056d484a16a0a245ebc111e3 100644 --- a/bsp/imx6ull-artpi-smart/.config +++ b/bsp/imx6ull-artpi-smart/.config @@ -475,6 +475,7 @@ CONFIG_LWP_TID_MAX_NR=64 # CONFIG_PKG_USING_TOUCHGFX2RTT is not set # CONFIG_PKG_USING_NUEMWIN is not set # CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set # # tools packages @@ -751,9 +752,10 @@ CONFIG_BSP_LCD_WIDTH=1024 CONFIG_BSP_LCD_HEIGHT=600 # -# Select SD Card Driver +# Select SDHC Driver # -CONFIG_BSP_USING_SDHC=y +CONFIG_RT_USING_SDIO1=y +# CONFIG_RT_USING_SDIO2 is not set # # Select RTC Driver diff --git a/bsp/imx6ull-artpi-smart/applications/mnt.c b/bsp/imx6ull-artpi-smart/applications/mnt.c index 00d6d1dbfbc8725f31733d6aad6b9f1820e24a8d..b85f5b032e689e9d80cc23a03ca02434993eb09d 100644 --- a/bsp/imx6ull-artpi-smart/applications/mnt.c +++ b/bsp/imx6ull-artpi-smart/applications/mnt.c @@ -16,21 +16,22 @@ int mnt_init(void) { + rt_thread_mdelay(500); if (dfs_mount("sd0", "/", "elm", 0, NULL) != 0) { rt_kprintf("Dir / mount failed!\n"); return -1; } - - rt_thread_mdelay(200); - if (dfs_mount(RT_NULL, "/mnt", "rom", 0, &romfs_root) != 0) + else { - rt_kprintf("Dir /mnt mount failed!\n"); - return -1; + mkdir("/romfs", 777); + mkdir("/flash", 777); + mkdir("/download", 777); } - rt_kprintf("file system initialization done!\n"); return 0; } -INIT_ENV_EXPORT(mnt_init); +INIT_APP_EXPORT(mnt_init); + + #endif diff --git a/bsp/imx6ull-artpi-smart/drivers/Kconfig b/bsp/imx6ull-artpi-smart/drivers/Kconfig index cf719bcb7eca047ce58b493c134677e9ea715493..8d0b855e78490fffa40c06e10be7fe4605942046 100644 --- a/bsp/imx6ull-artpi-smart/drivers/Kconfig +++ b/bsp/imx6ull-artpi-smart/drivers/Kconfig @@ -111,12 +111,16 @@ config BSP_USING_LCD endif endmenu -menu "Select SD Card Driver" +menu "Select SDHC Driver" if RT_USING_SDIO - config BSP_USING_SDHC - bool "Enable SDHC" + config RT_USING_SDIO1 + bool "Enable SDHC1" default n + config RT_USING_SDIO2 + bool "Enable SDHC2" + default n endif + endmenu menu "Select RTC Driver" diff --git a/bsp/imx6ull-artpi-smart/drivers/drv_sdhc.c b/bsp/imx6ull-artpi-smart/drivers/drv_sdhc.c deleted file mode 100644 index b35d06ff390ede96422471ef86529a943ce33c0c..0000000000000000000000000000000000000000 --- a/bsp/imx6ull-artpi-smart/drivers/drv_sdhc.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-23 Lyons first version - */ - -#include - -#ifdef BSP_USING_SDHC - -#include "board.h" -#include "drv_pin.h" -#include "drv_sdhc.h" - -#define DBG_TAG "drv.sdhc" -#define DBG_LVL DBG_LOG -#include - -#define SDCARD_SHOW_CARD_INFO 0 - -/* - * There are 512M Bytes reserved for boot image. - * Modify these parameter manually. - */ -#define SDCARD_PART1_START_SECTOR 8192 //no fs! -#define SDCARD_PART2_START_SECTOR 1056768 //use fs. - -_internal_rw struct imx_sddev _s_sdcard_device = { - .name = "sd0", - .periph.paddr = BOARD_SD_HOST_BASEADDR, - .irqno = RT_NULL, //not use irq yet! - .gpio = { - {IOMUXC_SD1_CLK_USDHC1_CLK, 0U, 0x17049}, - {IOMUXC_SD1_CMD_USDHC1_CMD, 0U, 0x17089}, - - {IOMUXC_SD1_DATA0_USDHC1_DATA0, 0U, 0x17089}, - {IOMUXC_SD1_DATA1_USDHC1_DATA1, 0U, 0x17089}, - {IOMUXC_SD1_DATA2_USDHC1_DATA2, 0U, 0x17089}, - {IOMUXC_SD1_DATA3_USDHC1_DATA3, 0U, 0x17089}, - }, - .flag = 0, -}; - -_internal_rw sd_card_t _s_sd; - -#if defined(SDCARD_SHOW_CARD_INFO) && (SDCARD_SHOW_CARD_INFO) -static void _sdcard_show_info( sd_card_t *card ) -{ - LOG_RAW("------------------------------\n"); - LOG_RAW("sd card infomation\n"); - LOG_RAW("------------------------------\n"); - - LOG_RAW("Version:\n"); - LOG_RAW(" version: %d\n", card->version); - - LOG_RAW("Bus frequency:\n"); - LOG_RAW(" freq: %d Hz\n", card->busClock_Hz); - - LOG_RAW("Capacity information:\n"); - - LOG_RAW(" sector size: %d Bytes\n", card->blockSize); - LOG_RAW(" sector count: %d\n", card->blockCount); - LOG_RAW(" block size: %d\n", card->csd.eraseSectorSize); - - LOG_RAW("Working condition:\n"); - - LOG_RAW(" voltage: "); - if (card->operationVoltage == kCARD_OperationVoltage330V) { - LOG_RAW("3.3V"); - } else if (card->operationVoltage == kCARD_OperationVoltage180V) { - LOG_RAW("1.8V"); - } - LOG_RAW("\n"); - - LOG_RAW(" timing mode: "); - if (card->currentTiming == kSD_TimingSDR12DefaultMode) - { - if (card->operationVoltage == kCARD_OperationVoltage330V) { - LOG_RAW("Default"); - } else if (card->operationVoltage == kCARD_OperationVoltage180V) { - LOG_RAW("SDR12"); - } - } else if (card->currentTiming == kSD_TimingSDR25HighSpeedMode) { - if (card->operationVoltage == kCARD_OperationVoltage180V) { - LOG_RAW("SDR25"); - } else { - LOG_RAW("High Speed"); - } - } else if (card->currentTiming == kSD_TimingSDR50Mode) { - LOG_RAW("SDR50"); - } else if (card->currentTiming == kSD_TimingSDR104Mode) { - LOG_RAW("SDR104"); - } else if (card->currentTiming == kSD_TimingDDR50Mode) { - LOG_RAW("DDR50"); - } - LOG_RAW("\n"); -} -#endif //#if defined(SDCARD_SHOW_CARD_INFO) && (SDCARD_SHOW_CARD_INFO) - -static rt_err_t sdcard_init_clock( struct imx_sddev *sddev ) -{ - RT_ASSERT(RT_NULL != sddev); - - if (IMX6ULL_USDHC1_BASE == sddev->periph.paddr) - { - CLOCK_SetDiv(kCLOCK_Usdhc1Div, 0U); - CLOCK_EnableClock(kCLOCK_Usdhc1); - } else if (IMX6ULL_USDHC2_BASE == sddev->periph.paddr) { - CLOCK_SetDiv(kCLOCK_Usdhc2Div, 0U); - CLOCK_EnableClock(kCLOCK_Usdhc2); - } - - return RT_EOK; -} - -static void _sdcard_gpio_init( struct imx_sddev *sddev ) -{ - RT_ASSERT(RT_NULL != sddev); - - for (int i=0; igpio[i]); - } -} - -static rt_err_t _sdcard_device_init( struct imx_sddev *sddev ) -{ - sd_card_t *card = RT_NULL; - - RT_ASSERT(RT_NULL != sddev); - RT_ASSERT(0 != sddev->periph.vaddr); - - sdcard_init_clock(sddev); - - card = &_s_sd; - - card->host.base = (USDHC_Type*)(sddev->periph.vaddr); - if (IMX6ULL_USDHC1_BASE == sddev->periph.paddr) - { - card->host.sourceClock_Hz = BOARD_USDHC1_CLK_FREQ; - } else if (IMX6ULL_USDHC2_BASE == sddev->periph.paddr) { - card->host.sourceClock_Hz = BOARD_USDHC2_CLK_FREQ; - } - - if (kStatus_Success != SD_Init(card)) - { - SD_Deinit(card); - rt_memset(card, 0U, sizeof(_s_sd)); - - LOG_W("sd card init failed."); - return -RT_ERROR; - } - - sddev->flag = 1; - - LOG_D("sd card init finished."); - LOG_D("sd card has %d sector, sector size %d Bytes.", card->blockCount, card->blockSize); - -#if defined(SDCARD_SHOW_CARD_INFO) && (SDCARD_SHOW_CARD_INFO) - _sdcard_show_info(card); -#endif - - return RT_EOK; -} - -static rt_err_t _sdcard_ops_init( rt_device_t dev ) -{ - return RT_EOK; -} - -static rt_err_t _sdcard_ops_open( rt_device_t dev, - rt_uint16_t oflag ) -{ - RT_ASSERT(RT_NULL != dev); - - if (!(dev->flag & RT_DEVICE_FLAG_RDWR)) - { - LOG_W("only support rd/wr option!"); - return -RT_ERROR; - } - - dev->ref_count++; - - return RT_EOK; -} - -static rt_err_t _sdcard_ops_close( rt_device_t dev ) -{ - RT_ASSERT(RT_NULL != dev); - - dev->ref_count = (0 == dev->ref_count) ? 0 : (dev->ref_count - 1); - - return RT_EOK; -} - -static rt_size_t _sdcard_ops_read( rt_device_t dev, - rt_off_t pos, - void *buffer, - rt_size_t size ) -{ - RT_ASSERT(RT_NULL != dev); - - if (0 == dev->ref_count) - { - return 0; - } - - if (kStatus_Success != SD_ReadBlocks(&_s_sd, buffer, SDCARD_PART2_START_SECTOR+pos, size)) - { - return 0; - } - - return size; -} - -static rt_size_t _sdcard_ops_write( rt_device_t dev, - rt_off_t pos, - const void *buffer, - rt_size_t size ) -{ - RT_ASSERT(RT_NULL != dev); - - if (0 == dev->ref_count) - { - return 0; - } - - if (kStatus_Success != SD_WriteBlocks(&_s_sd, buffer, SDCARD_PART2_START_SECTOR+pos, size)) - { - return 0; - } - - return size; -} - -static rt_err_t _sdcard_ops_control( rt_device_t dev, - int cmd, - void *args ) -{ - struct rt_device_blk_geometry *pgeometry = RT_NULL; - rt_err_t result; - - switch (cmd) - { - case RT_DEVICE_CTRL_BLK_GETGEOME: - if (args) - { - pgeometry = (struct rt_device_blk_geometry*)args; - - pgeometry->sector_count = _s_sd.blockCount; - pgeometry->bytes_per_sector = _s_sd.blockSize; - pgeometry->block_size = _s_sd.csd.eraseSectorSize; - - result = RT_EOK; - } - else - { - result = -RT_EINVAL; - } - break; - - case RT_DEVICE_CTRL_BLK_SYNC: - result = RT_EOK; - break; - - default : - result = -RT_EINVAL; - break; - } - - return result; -} - -#ifdef RT_USING_DEVICE_OPS -_internal_ro struct rt_device_ops _k_sdcard_ops = -{ - _sdcard_ops_init, /* init */ - _sdcard_ops_open, /* open */ - _sdcard_ops_close, /* close */ - _sdcard_ops_read, /* read */ - _sdcard_ops_write, /* write */ - _sdcard_ops_control, /* control */ -}; -#endif - -int rt_hw_sdcard_init(void) -{ - struct rt_device *device = RT_NULL; - - device = &_s_sdcard_device.parent; - - device->type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - device->ops = &_k_sdcard_ops; -#else - device->init = _sdcard_ops_init; - device->open = _sdcard_ops_open; - device->close = _sdcard_ops_close; - device->read = _sdcard_ops_read; - device->write = _sdcard_ops_write; - device->control = _sdcard_ops_control; -#endif - device->user_data = RT_NULL; - - rt_device_register(device, _s_sdcard_device.name, RT_DEVICE_FLAG_RDWR); - - _s_sdcard_device.periph.vaddr = platform_get_periph_vaddr(_s_sdcard_device.periph.paddr); - - _s_sdcard_device.flag = 0; //wait for sdhc init! - - _sdcard_gpio_init(&_s_sdcard_device); - _sdcard_device_init(&_s_sdcard_device); - - return RT_EOK; -} -INIT_DEVICE_EXPORT(rt_hw_sdcard_init); - -#endif //#ifdef BSP_USING_SDHC diff --git a/bsp/imx6ull-artpi-smart/drivers/drv_sdhc.h b/bsp/imx6ull-artpi-smart/drivers/drv_sdhc.h deleted file mode 100644 index 431c07acacecbd63b151c4153ea710aa9ebeaead..0000000000000000000000000000000000000000 --- a/bsp/imx6ull-artpi-smart/drivers/drv_sdhc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-04-23 Lyons first version - */ - -#ifndef __DRV_SDHC_H__ -#define __DRV_SDHC_H__ - -#include "board.h" -#include "drv_common.h" - -#ifdef BSP_USING_SDHC - -/* Fixed value, not edit! */ -#define SDCARD_CONTROL_PIN_NUM (6) - -struct imx_periph -{ - rt_uint32_t paddr; - rt_uint32_t vaddr; -}; - -struct imx_sddev -{ - struct rt_device parent; - - const char *name; - struct imx_periph periph; - rt_uint32_t irqno; - - struct imx6ull_iomuxc gpio[SDCARD_CONTROL_PIN_NUM]; - - rt_uint32_t flag; -}; - -#endif //#ifdef BSP_USING_SDHC -#endif //#ifndef __DRV_SDHC_H__ diff --git a/bsp/imx6ull-artpi-smart/drivers/drv_sdio.c b/bsp/imx6ull-artpi-smart/drivers/drv_sdio.c new file mode 100644 index 0000000000000000000000000000000000000000..6143273e547b0a660edc9e8ef226caa380c861c3 --- /dev/null +++ b/bsp/imx6ull-artpi-smart/drivers/drv_sdio.c @@ -0,0 +1,698 @@ +/* + * 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 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define DBG_TAG "drv_sdio" +#ifdef RT_SDIO_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* RT_SDIO_DEBUG */ +#include + +#define CACHE_LINESIZE (32) + +#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */ +#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */ +#define IMXRT_MAX_FREQ (52UL * 1000UL * 1000UL) + +#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */ +#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */ +#define USDHC_READ_BURST_LEN (8U) /*!< number of words USDHC read in a single burst */ +#define USDHC_WRITE_BURST_LEN (8U) /*!< number of words USDHC write in a single burst */ +#define USDHC_DATA_TIMEOUT (0xFU) /*!< data timeout counter value */ + +/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */ +#define USDHC_READ_WATERMARK_LEVEL (0x80U) +#define USDHC_WRITE_WATERMARK_LEVEL (0x80U) + +/* DMA mode */ +#define USDHC_DMA_MODE kUSDHC_DmaModeAdma2 + +/* Endian mode. */ +#define USDHC_ENDIAN_MODE kUSDHC_EndianModeLittle + +uint32_t g_usdhcAdma2Table[USDHC_ADMA_TABLE_WORDS]; +struct rt_mmcsd_host *host1; +struct rt_mmcsd_host *host2; +static rt_mutex_t mmcsd_mutex = RT_NULL; + +void host_change(void); + +struct imxrt_mmcsd +{ + struct rt_mmcsd_host *host; + struct rt_mmcsd_req *req; + struct rt_mmcsd_cmd *cmd; + + struct rt_timer timer; + + rt_uint32_t *buf; + + usdhc_host_t usdhc_host; + clock_div_t usdhc_div; + clock_ip_name_t ip_clock; + + uint32_t *usdhc_adma2_table; +}; + +/*! @name Configuration */ +/*@{*/ + +/*! + * @brief Sets the IOMUXC pin mux mode. + * @note The first five parameters can be filled with the pin function ID macros. + * + * This is an example to set the ENET1_RX_DATA0 Pad as FLEXCAN1_TX: + * @code + * IOMUXC_SetPinMux(IOMUXC_ENET1_RX_DATA0_FLEXCAN1_TX, 0); + * @endcode + * + * This is an example to set the GPIO1_IO02 Pad as I2C1_SCL: + * @code + * IOMUXC_SetPinMux(IOMUXC_GPIO1_IO02_I2C1_SCL, 0); + * @endcode + * + * @param muxRegister The pin mux register. + * @param muxMode The pin mux mode. + * @param inputRegister The select input register. + * @param inputDaisy The input daisy. + * @param configRegister The config register. + * @param inputOnfield Software input on field. + */ +static inline void _IOMUXC_SetPinMux(uint32_t muxRegister, + uint32_t muxMode, + uint32_t inputRegister, + uint32_t inputDaisy, + uint32_t configRegister, + uint32_t inputOnfield) +{ + *((volatile uint32_t *)rt_ioremap((void*)muxRegister, 0x4)) = + IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield); + + if (inputRegister) + { + *((volatile uint32_t *)rt_ioremap((void*)inputRegister, 0x4)) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy); + } +} + +/*! + * @brief Sets the IOMUXC pin configuration. + * @note The previous five parameters can be filled with the pin function ID macros. + * + * This is an example to set pin configuration for IOMUXC_GPIO1_IO02_I2C1_SCL: + * @code + * IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO02_I2C1_SCL, IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(2U)); + * @endcode + * + * @param muxRegister The pin mux register. + * @param muxMode The pin mux mode. + * @param inputRegister The select input register. + * @param inputDaisy The input daisy. + * @param configRegister The config register. + * @param configValue The pin config value. + */ +static inline void _IOMUXC_SetPinConfig(uint32_t muxRegister, + uint32_t muxMode, + uint32_t inputRegister, + uint32_t inputDaisy, + uint32_t configRegister, + uint32_t configValue) +{ + if (configRegister) + { + *((volatile uint32_t *)rt_ioremap((void*)configRegister, 0x4)) = configValue; + } +} + +static void _mmcsd_gpio_init(struct imxrt_mmcsd *mmcsd) +{ + + CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ +#ifdef RT_USING_SDIO1 + /* uSDHC1 pins start*/ + _IOMUXC_SetPinMux(IOMUXC_UART1_RTS_B_USDHC1_CD_B, 0U); + _IOMUXC_SetPinConfig(IOMUXC_UART1_RTS_B_USDHC1_CD_B, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + _IOMUXC_SetPinMux(IOMUXC_SD1_CLK_USDHC1_CLK, 0U); + _IOMUXC_SetPinConfig(IOMUXC_SD1_CLK_USDHC1_CLK, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(1U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + _IOMUXC_SetPinMux(IOMUXC_SD1_CMD_USDHC1_CMD, 0U); + _IOMUXC_SetPinConfig(IOMUXC_SD1_CMD_USDHC1_CMD, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + _IOMUXC_SetPinMux(IOMUXC_SD1_DATA0_USDHC1_DATA0, 0U); + _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA0_USDHC1_DATA0, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + _IOMUXC_SetPinMux(IOMUXC_SD1_DATA1_USDHC1_DATA1, 0U); + _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA1_USDHC1_DATA1, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + _IOMUXC_SetPinMux(IOMUXC_SD1_DATA2_USDHC1_DATA2, 0U); + _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA2_USDHC1_DATA2, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + _IOMUXC_SetPinMux(IOMUXC_SD1_DATA3_USDHC1_DATA3, 0U); + _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA3_USDHC1_DATA3, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + /* uSDHC1 pins end*/ +#endif + +#ifdef RT_USING_SDIO2 + /* uSDHC2 pins start*/ + _IOMUXC_SetPinMux(IOMUXC_NAND_WE_B_USDHC2_CMD, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_WE_B_USDHC2_CMD, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_RE_B_USDHC2_CLK, 0U); + + _IOMUXC_SetPinConfig(IOMUXC_NAND_RE_B_USDHC2_CLK, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_ALE_USDHC2_RESET_B, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_ALE_USDHC2_RESET_B, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(1U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA00_USDHC2_DATA0, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA00_USDHC2_DATA0, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA01_USDHC2_DATA1, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA01_USDHC2_DATA1, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA02_USDHC2_DATA2, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA02_USDHC2_DATA2, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA03_USDHC2_DATA3, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA03_USDHC2_DATA3, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA04_USDHC2_DATA4, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA04_USDHC2_DATA4, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA05_USDHC2_DATA5, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA05_USDHC2_DATA5, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA06_USDHC2_DATA6, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA06_USDHC2_DATA6, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(7U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + _IOMUXC_SetPinMux(IOMUXC_NAND_DATA07_USDHC2_DATA7, 0U); + _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA07_USDHC2_DATA7, + IOMUXC_SW_PAD_CTL_PAD_SRE_MASK | + IOMUXC_SW_PAD_CTL_PAD_DSE(7U) | + IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) | + IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | + IOMUXC_SW_PAD_CTL_PAD_PUS(1U) | + IOMUXC_SW_PAD_CTL_PAD_HYS_MASK); + + /* uSDHC2 pins end*/ +#endif +} +static void SDMMCHOST_ErrorRecovery(USDHC_Type *base) +{ + uint32_t status = 0U; + /* get host present status */ + status = USDHC_GetPresentStatusFlags(base); + /* check command inhibit status flag */ + if ((status & kUSDHC_CommandInhibitFlag) != 0U) + { + /* reset command line */ + USDHC_Reset(base, kUSDHC_ResetCommand, 1000U); + } + /* check data inhibit status flag */ + if ((status & kUSDHC_DataInhibitFlag) != 0U) + { + /* reset data line */ + USDHC_Reset(base, kUSDHC_ResetData, 1000U); + } +} + +static void _mmcsd_host_init(struct imxrt_mmcsd *mmcsd) +{ + usdhc_host_t *usdhc_host = &mmcsd->usdhc_host; + + /* Initializes SDHC. */ + usdhc_host->config.dataTimeout = USDHC_DATA_TIMEOUT; + usdhc_host->config.endianMode = USDHC_ENDIAN_MODE; + usdhc_host->config.readWatermarkLevel = USDHC_READ_WATERMARK_LEVEL; + usdhc_host->config.writeWatermarkLevel = USDHC_WRITE_WATERMARK_LEVEL; + usdhc_host->config.readBurstLen = USDHC_READ_BURST_LEN; + usdhc_host->config.writeBurstLen = USDHC_WRITE_BURST_LEN; + + USDHC_Init(usdhc_host->base, &(usdhc_host->config)); +} + +static void _mmcsd_clk_init(struct imxrt_mmcsd *mmcsd) +{ + CLOCK_EnableClock(mmcsd->ip_clock); + CLOCK_SetDiv(mmcsd->usdhc_div, 5U); +} + +static void _mmc_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + struct imxrt_mmcsd *mmcsd; + struct rt_mmcsd_cmd *cmd; + struct rt_mmcsd_data *data; + status_t error; + usdhc_adma_config_t dmaConfig; + usdhc_transfer_t fsl_content = {0}; + usdhc_command_t fsl_command = {0}; + usdhc_data_t fsl_data = {0}; + rt_uint32_t *buf = NULL; + + rt_mutex_take(mmcsd_mutex, RT_WAITING_FOREVER); + + RT_ASSERT(host != RT_NULL); + RT_ASSERT(req != RT_NULL); + + mmcsd = (struct imxrt_mmcsd *)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; + + memset(&dmaConfig, 0, sizeof(usdhc_adma_config_t)); + /* config adma */ + dmaConfig.dmaMode = USDHC_DMA_MODE; + dmaConfig.burstLen = kUSDHC_EnBurstLenForINCR; + dmaConfig.admaTable = mmcsd->usdhc_adma2_table; + dmaConfig.admaTableWords = USDHC_ADMA_TABLE_WORDS; + + fsl_command.index = cmd->cmd_code; + fsl_command.argument = cmd->arg; + + if (cmd->cmd_code == STOP_TRANSMISSION) + fsl_command.type = kCARD_CommandTypeAbort; + else + fsl_command.type = kCARD_CommandTypeNormal; + + switch (cmd->flags & RESP_MASK) + { + case RESP_NONE: + fsl_command.responseType = kCARD_ResponseTypeNone; + break; + case RESP_R1: + fsl_command.responseType = kCARD_ResponseTypeR1; + break; + case RESP_R1B: + fsl_command.responseType = kCARD_ResponseTypeR1b; + break; + case RESP_R2: + fsl_command.responseType = kCARD_ResponseTypeR2; + break; + case RESP_R3: + fsl_command.responseType = kCARD_ResponseTypeR3; + break; + case RESP_R4: + fsl_command.responseType = kCARD_ResponseTypeR4; + break; + case RESP_R6: + fsl_command.responseType = kCARD_ResponseTypeR6; + break; + case RESP_R7: + fsl_command.responseType = kCARD_ResponseTypeR7; + break; + case RESP_R5: + fsl_command.responseType = kCARD_ResponseTypeR5; + break; + default: + RT_ASSERT(NULL); + } + + fsl_command.flags = 0; + fsl_content.command = &fsl_command; + + if (data) + { + if (req->stop != NULL) + fsl_data.enableAutoCommand12 = true; + else + fsl_data.enableAutoCommand12 = false; + + fsl_data.enableAutoCommand23 = false; + + fsl_data.enableIgnoreError = false; + fsl_data.blockSize = data->blksize; + fsl_data.blockCount = data->blks; + + LOG_D(" blksize:%d, blks:%d ", fsl_data.blockSize, fsl_data.blockCount); + + if (((rt_uint32_t)data->buf & (CACHE_LINESIZE - 1)) || // align cache(32byte) + ((rt_uint32_t)data->buf > 0x00000000 && (rt_uint32_t)data->buf < 0x00080000) /*|| // ITCM + ((rt_uint32_t)data->buf >= 0x20000000 && (rt_uint32_t)data->buf < 0x20080000)*/) // DTCM + { + + buf = rt_malloc_align(fsl_data.blockSize * fsl_data.blockCount, CACHE_LINESIZE); + RT_ASSERT(buf != RT_NULL); + + LOG_D(" malloc buf: %p, data->buf:%p, %d ", buf, data->buf, fsl_data.blockSize * fsl_data.blockCount); + } + + + if ((cmd->cmd_code == WRITE_BLOCK) || (cmd->cmd_code == WRITE_MULTIPLE_BLOCK)) + { + if (buf) + { + LOG_D(" write(data->buf to buf) "); + rt_memcpy(buf, data->buf, fsl_data.blockSize * fsl_data.blockCount); + fsl_data.txData = (uint32_t const *)buf; + } + else + { + fsl_data.txData = (uint32_t const *)data->buf; + } + + fsl_data.rxData = NULL; + } + else + { + if (buf) + { + fsl_data.rxData = (uint32_t *)buf; + } + else + { + fsl_data.rxData = (uint32_t *)data->buf; + } + + fsl_data.txData = NULL; + } + + fsl_content.data = &fsl_data; + } + else + { + fsl_content.data = NULL; + } + + error = USDHC_TransferBlocking(mmcsd->usdhc_host.base, &dmaConfig, &fsl_content); + if (error == kStatus_Fail) + { + SDMMCHOST_ErrorRecovery(mmcsd->usdhc_host.base); + LOG_D(" ***USDHC_TransferBlocking error: %d*** --> \n", error); + cmd->err = -RT_ERROR; + } + + if (buf) + { + if (fsl_data.rxData) + { + LOG_D("read copy buf to data->buf "); + rt_memcpy(data->buf, buf, fsl_data.blockSize * fsl_data.blockCount); + } + + rt_free_align(buf); + } + + if ((cmd->flags & RESP_MASK) == RESP_R2) + { + cmd->resp[3] = fsl_command.response[0]; + cmd->resp[2] = fsl_command.response[1]; + cmd->resp[1] = fsl_command.response[2]; + cmd->resp[0] = fsl_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] = fsl_command.response[0]; + LOG_D(" resp 0x%08X\n", cmd->resp[0]); + } + + mmcsd_req_complete(host); + + rt_mutex_release(mmcsd_mutex); + return; +} + +static void _mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + + struct imxrt_mmcsd *mmcsd; + unsigned int usdhc_clk; + unsigned int bus_width; + uint32_t src_clk; + + RT_ASSERT(host != RT_NULL); + RT_ASSERT(host->private_data != RT_NULL); + RT_ASSERT(io_cfg != RT_NULL); + + + mmcsd = (struct imxrt_mmcsd *)host->private_data; + usdhc_clk = io_cfg->clock; + bus_width = io_cfg->bus_width; + + if (usdhc_clk > IMXRT_MAX_FREQ) + usdhc_clk = IMXRT_MAX_FREQ; + src_clk = (CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) / (CLOCK_GetDiv(mmcsd->usdhc_div) + 1U)); + + LOG_D("\tsrc_clk: %d, usdhc_clk: %d, bus_width: %d\n", src_clk, usdhc_clk, bus_width); + if (usdhc_clk) + { + USDHC_SetSdClock(mmcsd->usdhc_host.base, src_clk, usdhc_clk); + /* Change bus width */ + if (bus_width == MMCSD_BUS_WIDTH_8) + USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth8Bit); + else if (bus_width == MMCSD_BUS_WIDTH_4) + USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth4Bit); + else if (bus_width == MMCSD_BUS_WIDTH_1) + USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth1Bit); + else + RT_ASSERT(RT_NULL); + + } +} + +static const struct rt_mmcsd_host_ops ops = +{ + _mmc_request, + _mmc_set_iocfg, + RT_NULL,//_mmc_get_card_status, + RT_NULL,//_mmc_enable_sdio_irq, +}; + +rt_int32_t imxrt_mci_init(void) +{ +#ifdef RT_USING_SDIO1 + struct imxrt_mmcsd *mmcsd1; + + host1 = mmcsd_alloc_host(); + if (!host1) + { + return -RT_ERROR; + } + + mmcsd1 = rt_malloc(sizeof(struct imxrt_mmcsd)); + if (!mmcsd1) + { + rt_kprintf("alloc mci failed\n"); + goto err; + } + + rt_memset(mmcsd1, 0, sizeof(struct imxrt_mmcsd)); + mmcsd1->usdhc_host.base = (struct USDHC_Type *)rt_ioremap((void*)USDHC1_BASE, 0x1000); + mmcsd1->usdhc_div = kCLOCK_Usdhc1Div; + mmcsd1->usdhc_adma2_table = g_usdhcAdma2Table; + + host1->ops = &ops; + host1->freq_min = 375000; + host1->freq_max = 25000000; + host1->valid_ocr = VDD_32_33 | VDD_33_34; + host1->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | \ + MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ; + host1->max_seg_size = 65535; + host1->max_dma_segs = 2; + host1->max_blk_size = 512; + host1->max_blk_count = 4096; + + mmcsd1->host = host1; + _mmcsd_clk_init(mmcsd1); + _mmcsd_gpio_init(mmcsd1); + _mmcsd_host_init(mmcsd1); + + host1->private_data = mmcsd1; + + mmcsd_change(host1); +#endif + +#ifdef RT_USING_SDIO2 + struct imxrt_mmcsd *mmcsd2; + host2 = mmcsd_alloc_host(); + if (!host2) + { + return -RT_ERROR; + } + + mmcsd2 = rt_malloc(sizeof(struct imxrt_mmcsd)); + if (!mmcsd2) + { + rt_kprintf("alloc mci failed\n"); + goto err; + } + + rt_memset(mmcsd2, 0, sizeof(struct imxrt_mmcsd)); + mmcsd2->usdhc_host.base = (struct USDHC_Type *)rt_ioremap((void*)USDHC2_BASE, 0x1000); + mmcsd2->usdhc_div = kCLOCK_Usdhc1Div; + mmcsd2->usdhc_adma2_table = g_usdhcAdma2Table; + + host2->ops = &ops; + host2->freq_min = 375000; + host2->freq_max = 52000000; + host2->valid_ocr = VDD_32_33 | VDD_33_34; + host2->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | \ + MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ; + host2->max_seg_size = 65535; + host2->max_dma_segs = 2; + host2->max_blk_size = 512; + host2->max_blk_count = 4096; + + mmcsd2->host = host2; + _mmcsd_clk_init(mmcsd2); + _mmcsd_gpio_init(mmcsd2); + _mmcsd_host_init(mmcsd2); + + host2->private_data = mmcsd2; + mmcsd_change(host2); +#endif + mmcsd_mutex = rt_mutex_create("mmutex", RT_IPC_FLAG_FIFO); + if (mmcsd_mutex == RT_NULL) + { + rt_kprintf("create mmcsd mutex failed.\n"); + return -1; + } + + return 0; + +err: +#ifdef RT_USING_SDIO1 + mmcsd_free_host(host1); +#endif +#ifdef RT_USING_SDIO2 + mmcsd_free_host(host2); +#endif + return -RT_ENOMEM; +} + +INIT_DEVICE_EXPORT(imxrt_mci_init); + diff --git a/bsp/imx6ull-artpi-smart/rtconfig.h b/bsp/imx6ull-artpi-smart/rtconfig.h index 92a784c0ddea39785ce86292986f9531aa0c1835..5273b9c376b7d27eadaef7b8074507ade8a10c3d 100644 --- a/bsp/imx6ull-artpi-smart/rtconfig.h +++ b/bsp/imx6ull-artpi-smart/rtconfig.h @@ -310,9 +310,9 @@ #define BSP_LCD_WIDTH 1024 #define BSP_LCD_HEIGHT 600 -/* Select SD Card Driver */ +/* Select SDHC Driver */ -#define BSP_USING_SDHC +#define RT_USING_SDIO1 /* Select RTC Driver */