|
@@ -7,45 +7,77 @@
|
|
|
* Date Author Notes
|
|
* Date Author Notes
|
|
|
* 2015-06-15 hichard first version
|
|
* 2015-06-15 hichard first version
|
|
|
* 2024-05-25 HPMicro add HS400 support
|
|
* 2024-05-25 HPMicro add HS400 support
|
|
|
|
|
+ * 2025-12-11 HPMicro correct the sequence of switching to high-speed ddr mode
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
#include <drivers/dev_mmcsd_core.h>
|
|
#include <drivers/dev_mmcsd_core.h>
|
|
|
#include <drivers/dev_mmc.h>
|
|
#include <drivers/dev_mmc.h>
|
|
|
|
|
|
|
|
-#define DBG_TAG "SDIO"
|
|
|
|
|
|
|
+#define DBG_TAG "SDIO"
|
|
|
#ifdef RT_SDIO_DEBUG
|
|
#ifdef RT_SDIO_DEBUG
|
|
|
-#define DBG_LVL DBG_LOG
|
|
|
|
|
|
|
+#define DBG_LVL DBG_LOG
|
|
|
#else
|
|
#else
|
|
|
-#define DBG_LVL DBG_INFO
|
|
|
|
|
|
|
+#define DBG_LVL DBG_INFO
|
|
|
#endif /* RT_SDIO_DEBUG */
|
|
#endif /* RT_SDIO_DEBUG */
|
|
|
#include <rtdbg.h>
|
|
#include <rtdbg.h>
|
|
|
|
|
|
|
|
-static const rt_uint32_t tran_unit[] =
|
|
|
|
|
-{
|
|
|
|
|
|
|
+static const rt_uint32_t tran_unit[] = {
|
|
|
10000, 100000, 1000000, 10000000,
|
|
10000, 100000, 1000000, 10000000,
|
|
|
- 0, 0, 0, 0
|
|
|
|
|
|
|
+ 0, 0, 0, 0
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-static const rt_uint8_t tran_value[] =
|
|
|
|
|
-{
|
|
|
|
|
- 0, 10, 12, 13, 15, 20, 25, 30,
|
|
|
|
|
- 35, 40, 45, 50, 55, 60, 70, 80,
|
|
|
|
|
|
|
+static const rt_uint8_t tran_value[] = {
|
|
|
|
|
+ 0,
|
|
|
|
|
+ 10,
|
|
|
|
|
+ 12,
|
|
|
|
|
+ 13,
|
|
|
|
|
+ 15,
|
|
|
|
|
+ 20,
|
|
|
|
|
+ 25,
|
|
|
|
|
+ 30,
|
|
|
|
|
+ 35,
|
|
|
|
|
+ 40,
|
|
|
|
|
+ 45,
|
|
|
|
|
+ 50,
|
|
|
|
|
+ 55,
|
|
|
|
|
+ 60,
|
|
|
|
|
+ 70,
|
|
|
|
|
+ 80,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-static const rt_uint32_t tacc_uint[] =
|
|
|
|
|
-{
|
|
|
|
|
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
|
|
|
|
|
|
|
+static const rt_uint32_t tacc_uint[] = {
|
|
|
|
|
+ 1,
|
|
|
|
|
+ 10,
|
|
|
|
|
+ 100,
|
|
|
|
|
+ 1000,
|
|
|
|
|
+ 10000,
|
|
|
|
|
+ 100000,
|
|
|
|
|
+ 1000000,
|
|
|
|
|
+ 10000000,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-static const rt_uint8_t tacc_value[] =
|
|
|
|
|
-{
|
|
|
|
|
- 0, 10, 12, 13, 15, 20, 25, 30,
|
|
|
|
|
- 35, 40, 45, 50, 55, 60, 70, 80,
|
|
|
|
|
|
|
+static const rt_uint8_t tacc_value[] = {
|
|
|
|
|
+ 0,
|
|
|
|
|
+ 10,
|
|
|
|
|
+ 12,
|
|
|
|
|
+ 13,
|
|
|
|
|
+ 15,
|
|
|
|
|
+ 20,
|
|
|
|
|
+ 25,
|
|
|
|
|
+ 30,
|
|
|
|
|
+ 35,
|
|
|
|
|
+ 40,
|
|
|
|
|
+ 45,
|
|
|
|
|
+ 50,
|
|
|
|
|
+ 55,
|
|
|
|
|
+ 60,
|
|
|
|
|
+ 70,
|
|
|
|
|
+ 80,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
rt_inline rt_uint32_t GET_BITS(rt_uint32_t *resp,
|
|
rt_inline rt_uint32_t GET_BITS(rt_uint32_t *resp,
|
|
|
- rt_uint32_t start,
|
|
|
|
|
- rt_uint32_t size)
|
|
|
|
|
|
|
+ rt_uint32_t start,
|
|
|
|
|
+ rt_uint32_t size)
|
|
|
{
|
|
{
|
|
|
const rt_int32_t __size = size;
|
|
const rt_int32_t __size = size;
|
|
|
const rt_uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1;
|
|
const rt_uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1;
|
|
@@ -198,22 +230,22 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|
|
uint8_t device_type = ext_csd[EXT_CSD_CARD_TYPE];
|
|
uint8_t device_type = ext_csd[EXT_CSD_CARD_TYPE];
|
|
|
if ((host->flags & MMCSD_SUP_HS400) && (device_type & EXT_CSD_CARD_TYPE_HS400))
|
|
if ((host->flags & MMCSD_SUP_HS400) && (device_type & EXT_CSD_CARD_TYPE_HS400))
|
|
|
{
|
|
{
|
|
|
- card->flags |= CARD_FLAG_HS400;
|
|
|
|
|
|
|
+ card->flags |= CARD_FLAG_HS400;
|
|
|
card->max_data_rate = 200000000;
|
|
card->max_data_rate = 200000000;
|
|
|
}
|
|
}
|
|
|
else if ((host->flags & MMCSD_SUP_HS200) && (device_type & EXT_CSD_CARD_TYPE_HS200))
|
|
else if ((host->flags & MMCSD_SUP_HS200) && (device_type & EXT_CSD_CARD_TYPE_HS200))
|
|
|
{
|
|
{
|
|
|
- card->flags |= CARD_FLAG_HS200;
|
|
|
|
|
|
|
+ card->flags |= CARD_FLAG_HS200;
|
|
|
card->max_data_rate = 200000000;
|
|
card->max_data_rate = 200000000;
|
|
|
}
|
|
}
|
|
|
else if ((host->flags & MMCSD_SUP_HIGHSPEED_DDR) && (device_type & EXT_CSD_CARD_TYPE_DDR_52))
|
|
else if ((host->flags & MMCSD_SUP_HIGHSPEED_DDR) && (device_type & EXT_CSD_CARD_TYPE_DDR_52))
|
|
|
{
|
|
{
|
|
|
- card->flags |= CARD_FLAG_HIGHSPEED_DDR;
|
|
|
|
|
|
|
+ card->flags |= CARD_FLAG_HIGHSPEED_DDR;
|
|
|
card->hs_max_data_rate = 52000000;
|
|
card->hs_max_data_rate = 52000000;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- card->flags |= CARD_FLAG_HIGHSPEED;
|
|
|
|
|
|
|
+ card->flags |= CARD_FLAG_HIGHSPEED;
|
|
|
card->hs_max_data_rate = 52000000;
|
|
card->hs_max_data_rate = 52000000;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -252,7 +284,7 @@ static int mmc_switch(struct rt_mmcsd_card *card, rt_uint8_t set,
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
|
struct rt_mmcsd_host *host = card->host;
|
|
struct rt_mmcsd_host *host = card->host;
|
|
|
- struct rt_mmcsd_cmd cmd = {0};
|
|
|
|
|
|
|
+ struct rt_mmcsd_cmd cmd = { 0 };
|
|
|
|
|
|
|
|
cmd.cmd_code = SWITCH;
|
|
cmd.cmd_code = SWITCH;
|
|
|
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
|
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
|
@@ -326,14 +358,12 @@ out:
|
|
|
*/
|
|
*/
|
|
|
static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|
static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|
|
{
|
|
{
|
|
|
- rt_uint32_t ext_csd_bits[][2] =
|
|
|
|
|
- {
|
|
|
|
|
- {EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8},
|
|
|
|
|
- {EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4},
|
|
|
|
|
- {EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1},
|
|
|
|
|
|
|
+ rt_uint32_t ext_csd_bits[][2] = {
|
|
|
|
|
+ { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
|
|
|
|
|
+ { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
|
|
|
|
|
+ { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
|
|
|
};
|
|
};
|
|
|
- rt_uint32_t bus_widths[] =
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ rt_uint32_t bus_widths[] = {
|
|
|
MMCSD_BUS_WIDTH_8,
|
|
MMCSD_BUS_WIDTH_8,
|
|
|
MMCSD_BUS_WIDTH_4,
|
|
MMCSD_BUS_WIDTH_4,
|
|
|
MMCSD_BUS_WIDTH_1
|
|
MMCSD_BUS_WIDTH_1
|
|
@@ -403,24 +433,23 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!err && ddr)
|
|
|
|
|
- {
|
|
|
|
|
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
|
|
- EXT_CSD_BUS_WIDTH,
|
|
|
|
|
- ext_csd_bits[idx][1]);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
if (!err)
|
|
if (!err)
|
|
|
{
|
|
{
|
|
|
if (card->flags & (CARD_FLAG_HIGHSPEED | CARD_FLAG_HIGHSPEED_DDR))
|
|
if (card->flags & (CARD_FLAG_HIGHSPEED | CARD_FLAG_HIGHSPEED_DDR))
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_HS_TIMING,
|
|
EXT_CSD_HS_TIMING,
|
|
|
1);
|
|
1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (!err && ddr)
|
|
|
|
|
+ {
|
|
|
|
|
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
|
|
+ EXT_CSD_BUS_WIDTH,
|
|
|
|
|
+ ext_csd_bits[idx][1]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -514,7 +543,7 @@ static int mmc_switch_to_hs400(struct rt_mmcsd_card *card)
|
|
|
|
|
|
|
|
/* Switch to HS_TIMING to 0x01 (High Speed) */
|
|
/* Switch to HS_TIMING to 0x01 (High Speed) */
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
- EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS);
|
|
|
|
|
|
|
+ EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS);
|
|
|
if (err != RT_EOK)
|
|
if (err != RT_EOK)
|
|
|
{
|
|
{
|
|
|
return err;
|
|
return err;
|
|
@@ -530,9 +559,7 @@ static int mmc_switch_to_hs400(struct rt_mmcsd_card *card)
|
|
|
* 0x86 if enhanced data strobe is supported, or
|
|
* 0x86 if enhanced data strobe is supported, or
|
|
|
* 0x06 if enhanced data strobe is not supported
|
|
* 0x06 if enhanced data strobe is not supported
|
|
|
*/
|
|
*/
|
|
|
- ext_csd_bus_width = support_enhanced_ds ?
|
|
|
|
|
- EXT_CSD_DDR_BUS_WIDTH_8_EH_DS :
|
|
|
|
|
- EXT_CSD_DDR_BUS_WIDTH_8;
|
|
|
|
|
|
|
+ ext_csd_bus_width = support_enhanced_ds ? EXT_CSD_DDR_BUS_WIDTH_8_EH_DS : EXT_CSD_DDR_BUS_WIDTH_8;
|
|
|
|
|
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_BUS_WIDTH,
|
|
EXT_CSD_BUS_WIDTH,
|
|
@@ -553,9 +580,7 @@ static int mmc_switch_to_hs400(struct rt_mmcsd_card *card)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Change the Host timing accordingly */
|
|
/* Change the Host timing accordingly */
|
|
|
- hs_timing = support_enhanced_ds ?
|
|
|
|
|
- MMCSD_TIMING_MMC_HS400_ENH_DS :
|
|
|
|
|
- MMCSD_TIMING_MMC_HS400;
|
|
|
|
|
|
|
+ hs_timing = support_enhanced_ds ? MMCSD_TIMING_MMC_HS400_ENH_DS : MMCSD_TIMING_MMC_HS400;
|
|
|
mmcsd_set_timing(host, hs_timing);
|
|
mmcsd_set_timing(host, hs_timing);
|
|
|
|
|
|
|
|
/* Host may changes frequency to <= 200MHz */
|
|
/* Host may changes frequency to <= 200MHz */
|
|
@@ -611,7 +636,7 @@ static int mmc_select_timing(struct rt_mmcsd_card *card)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host,
|
|
static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host,
|
|
|
- rt_uint32_t ocr)
|
|
|
|
|
|
|
+ rt_uint32_t ocr)
|
|
|
{
|
|
{
|
|
|
rt_int32_t err;
|
|
rt_int32_t err;
|
|
|
rt_uint32_t resp[4];
|
|
rt_uint32_t resp[4];
|
|
@@ -741,7 +766,7 @@ err:
|
|
|
rt_int32_t init_mmc(struct rt_mmcsd_host *host, rt_uint32_t ocr)
|
|
rt_int32_t init_mmc(struct rt_mmcsd_host *host, rt_uint32_t ocr)
|
|
|
{
|
|
{
|
|
|
rt_int32_t err;
|
|
rt_int32_t err;
|
|
|
- rt_uint32_t current_ocr;
|
|
|
|
|
|
|
+ rt_uint32_t current_ocr;
|
|
|
/*
|
|
/*
|
|
|
* We need to get OCR a different way for SPI.
|
|
* We need to get OCR a different way for SPI.
|
|
|
*/
|
|
*/
|