From d57526478762c1d6be0383a83e021ed00d2f0a8f Mon Sep 17 00:00:00 2001 From: Fan YANG Date: Thu, 8 Aug 2024 11:32:50 +0800 Subject: [PATCH] arch:hpmicro:sdmmc fix several bugs. - fixed the issue that the timeout feature is not working - fixed the multi-block read/write issue - fixed the clock_freq setting issue Signed-off-by: Fan YANG --- .../src/hpmicro/hpm_sdk/drivers/src/hpm_sdxc_drv.c | 2 ++ .../hpmicro/hpm_sdk/soc/HPM6360/hpm_sdxc_soc_drv.h | 9 +++++---- .../hpmicro/hpm_sdk/soc/HPM6750/hpm_sdxc_soc_drv.h | 10 +++++++++- arch/risc-v/src/hpmicro/hpm_sdmmc.c | 12 +++++++++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arch/risc-v/src/hpmicro/hpm_sdk/drivers/src/hpm_sdxc_drv.c b/arch/risc-v/src/hpmicro/hpm_sdk/drivers/src/hpm_sdxc_drv.c index 7be4c9b5a2175..95d7a8df2d580 100644 --- a/arch/risc-v/src/hpmicro/hpm_sdk/drivers/src/hpm_sdxc_drv.c +++ b/arch/risc-v/src/hpmicro/hpm_sdk/drivers/src/hpm_sdxc_drv.c @@ -498,6 +498,8 @@ void sdxc_init(SDXC_Type *base, const sdxc_config_t *config) prot_ctrl |= SDXC_PROT_CTRL_SD_BUS_PWR_VDD1_MASK; + sdxc_enable_tm_clock(base); + sdxc_set_data_timeout(base, config->data_timeout, NULL); base->PROT_CTRL = prot_ctrl; diff --git a/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6360/hpm_sdxc_soc_drv.h b/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6360/hpm_sdxc_soc_drv.h index fb321b14239fc..4a4e473daab10 100644 --- a/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6360/hpm_sdxc_soc_drv.h +++ b/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6360/hpm_sdxc_soc_drv.h @@ -79,21 +79,22 @@ static inline void sdxc_select_cardclk_delay_source(SDXC_Type *base, bool loopba } } +/** + * @brief Set the Card Clock Delay chain + * @note This feature is not supported on this SoC + */ static inline void sdxc_set_cardclk_delay_chain(SDXC_Type *base, uint32_t number_of_delaycells) { - base->MISC_CTRL1 = (base->MISC_CTRL1 & ~SDXC_MISC_CTRL1_CARDCLK_DLYSEL_MASK) | - SDXC_MISC_CTRL1_CARDCLK_DLYSEL_SET(number_of_delaycells); } /** * @brief Set SDXC data strobe delay chain + * @note This feature is not supported on this SoC * @param [in] base SDXC base * @param [in] num_of_delaycells Number of delay cells for Data strobe */ static inline void sdxc_set_data_strobe_delay(SDXC_Type *base, uint8_t num_of_delaycells) { - base->MISC_CTRL1 = (base->MISC_CTRL1 & ~SDXC_MISC_CTRL1_STROBE_DLYSEL_MASK) | - SDXC_MISC_CTRL1_STROBE_DLYSEL_SET(num_of_delaycells); } static inline uint32_t sdxc_get_default_strobe_delay(SDXC_Type *base) diff --git a/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6750/hpm_sdxc_soc_drv.h b/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6750/hpm_sdxc_soc_drv.h index 23a42ab3bf5a7..a63f93b241fb8 100644 --- a/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6750/hpm_sdxc_soc_drv.h +++ b/arch/risc-v/src/hpmicro/hpm_sdk/soc/HPM6750/hpm_sdxc_soc_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -15,6 +15,14 @@ extern "C" { #endif +/** + * @brief Enable TMCLK (for Data timeout detection) +*/ +static inline void sdxc_enable_tm_clock(SDXC_Type *base) +{ + volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5; + (*reg) |= (1UL << 10); +} /** * @brief Wait at least 74 clocks until card is ready to receive the first command diff --git a/arch/risc-v/src/hpmicro/hpm_sdmmc.c b/arch/risc-v/src/hpmicro/hpm_sdmmc.c index a5937c7bec5e9..620996f2e4b02 100644 --- a/arch/risc-v/src/hpmicro/hpm_sdmmc.c +++ b/arch/risc-v/src/hpmicro/hpm_sdmmc.c @@ -396,7 +396,7 @@ static void hpm_sdmmc_reset(FAR struct sdio_dev_s *dev) flags = enter_critical_section(); clock_add_to_group(priv->clock_name, 0); sdxc_config_t sdxc_config; - sdxc_config.data_timeout = 0xf; + sdxc_config.data_timeout = 1000; sdxc_init(priv->base, &sdxc_config); leave_critical_section(flags); } @@ -472,7 +472,7 @@ static void hpm_sdmmc_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) struct hpm_sdmmc_dev_s *priv = (struct hpm_sdmmc_dev_s *)dev; bool need_disable = false; - bool clock_freq = 0; + uint32_t clock_freq = 0; switch (rate) { default: @@ -588,6 +588,7 @@ static int hpm_sdmmc_interrupt(int irq, void *context, void *arg) { priv->remaining = 0; hpm_sdmmc_endxfer(priv, SDIOWAIT_ERROR); + break; } sdxc_clear_interrupt_status(priv->base, mask); @@ -681,6 +682,11 @@ static int hpm_sdmmc_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t break; } + if (cmd & MMCSD_MULTIBLOCK) + { + sdxc_cmd->cmd_flags |= SDXC_CMD_XFER_MULTI_BLK_SEL_MASK | SDXC_CMD_XFER_BLOCK_COUNT_ENABLE_MASK; + } + if ((sdxc_cmd->cmd_flags & SDXC_CMD_XFER_DATA_PRESENT_SEL_MASK) != 0U) { if (priv->dma_mode == HPM_SDMMC_DMA_MODE_ADMA2) @@ -753,7 +759,7 @@ static int hpm_sdmmc_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd) { struct hpm_sdmmc_dev_s *priv = (struct hpm_sdmmc_dev_s *)dev; - int32_t timeout; + int32_t timeout = HPM_SDMMC_CMDTIMEOUT; uint32_t events = SDXC_INT_STAT_CMD_COMPLETE_MASK; switch (cmd & MMCSD_RESPONSE_MASK) {