[components][drivers][mmc] add HS400 support to mmc driver
- added HS400 supprt (both eMMC5.0 and eMMC5.1 flavor are supported) Signed-off-by: Fan YANG <fan.yang@hpmicro.com>
This commit is contained in:
parent
5dd3b7427a
commit
1a1514640a
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-06-15 hichard first version
|
||||
* 2015-06-15 hichard first version
|
||||
* 2024-05-25 HPMicro add strobe support
|
||||
*/
|
||||
|
||||
#ifndef __MMC_H__
|
||||
|
@ -45,6 +46,7 @@ extern "C" {
|
|||
#define EXT_CSD_PART_CONFIG 179 /* R/W */
|
||||
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
|
||||
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
|
||||
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
|
||||
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||
#define EXT_CSD_POWER_CLASS 187 /* R/W */
|
||||
#define EXT_CSD_REV 192 /* RO */
|
||||
|
@ -130,8 +132,9 @@ extern "C" {
|
|||
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_8_EH_DS 0x86/* Card is in 8 bit DDR mode with Enhanced Data Strobe */
|
||||
|
||||
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
|
||||
#define EXT_CSD_TIMING_BC 0 /* Backwards compatibility */
|
||||
#define EXT_CSD_TIMING_HS 1 /* High speed */
|
||||
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
|
||||
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-07-25 weety first version
|
||||
* 2011-07-25 weety first version
|
||||
* 2024-05-24 HPMicro add HS400 support
|
||||
*/
|
||||
|
||||
#ifndef __MMCSD_CARD_H__
|
||||
|
@ -130,6 +131,7 @@ struct rt_sdio_function {
|
|||
struct rt_mmc_ext_csd
|
||||
{
|
||||
rt_uint32_t cache_size;
|
||||
rt_uint32_t enhanced_data_strobe;
|
||||
};
|
||||
|
||||
struct rt_mmcsd_card {
|
||||
|
@ -156,13 +158,14 @@ struct rt_mmcsd_card {
|
|||
#define CARD_FLAG_HIGHSPEED (1 << 0) /* SDIO bus speed 50MHz */
|
||||
#define CARD_FLAG_SDHC (1 << 1) /* SDHC card */
|
||||
#define CARD_FLAG_SDXC (1 << 2) /* SDXC card */
|
||||
#define CARD_FLAG_HIGHSPEED_DDR (1 << 3) /*HIGH SPEED DDR*/
|
||||
#define CARD_FLAG_HS200 (1 << 4) /* BUS SPEED 200mHz*/
|
||||
#define CARD_FLAG_HIGHSPEED_DDR (1 << 3) /* HIGH SPEED DDR */
|
||||
#define CARD_FLAG_HS200 (1 << 4) /* BUS SPEED 200MHz */
|
||||
#define CARD_FLAG_HS400 (1 << 5) /* BUS SPEED 400MHz */
|
||||
struct rt_sd_scr scr;
|
||||
struct rt_mmcsd_csd csd;
|
||||
rt_uint32_t hs_max_data_rate; /* max data transfer rate in high speed mode */
|
||||
|
||||
rt_uint8_t sdio_function_num; /* totol number of SDIO functions */
|
||||
rt_uint8_t sdio_function_num; /* total number of SDIO functions */
|
||||
struct rt_sdio_cccr cccr; /* common card info */
|
||||
struct rt_sdio_cis cis; /* common tuple info */
|
||||
struct rt_sdio_function *sdio_function[SDIO_MAX_FUNCTIONS + 1]; /* SDIO functions (devices) */
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-07-25 weety first version
|
||||
* 2011-07-25 weety first version
|
||||
* 2024-05-25 HPMicro add HS400 support
|
||||
*/
|
||||
|
||||
#ifndef __HOST_H__
|
||||
|
@ -60,6 +61,7 @@ struct rt_mmcsd_io_cfg
|
|||
#define MMCSD_TIMING_MMC_DDR52 8
|
||||
#define MMCSD_TIMING_MMC_HS200 9
|
||||
#define MMCSD_TIMING_MMC_HS400 10
|
||||
#define MMCSD_TIMING_MMC_HS400_ENH_DS 11
|
||||
|
||||
unsigned char drv_type; /* driver type (A, B, C, D) */
|
||||
|
||||
|
@ -120,15 +122,19 @@ struct rt_mmcsd_host
|
|||
#define MMCSD_HOST_IS_SPI (1 << 3)
|
||||
#define controller_is_spi(host) (host->flags & MMCSD_HOST_IS_SPI)
|
||||
#define MMCSD_SUP_SDIO_IRQ (1 << 4) /* support signal pending SDIO IRQs */
|
||||
#define MMCSD_SUP_HIGHSPEED (1 << 5) /* support high speed SDR*/
|
||||
#define MMCSD_SUP_HIGHSPEED (1 << 5) /* support high speed SDR */
|
||||
#define MMCSD_SUP_DDR_3V3 (1 << 6)
|
||||
#define MMCSD_SUP_DDR_1V8 (1 << 7)
|
||||
#define MMCSD_SUP_DDR_1V2 (1 << 8)
|
||||
#define MMCSD_SUP_HIGHSPEED_DDR (MMCSD_SUP_DDR_3V3 | MMCSD_SUP_DDR_1V8 | MMCSD_SUP_DDR_1V2)/* HIGH SPEED DDR*/
|
||||
#define MMCSD_SUP_HIGHSPEED_DDR (MMCSD_SUP_DDR_3V3 | MMCSD_SUP_DDR_1V8 | MMCSD_SUP_DDR_1V2)/* HIGH SPEED DDR */
|
||||
#define MMCSD_SUP_HS200_1V8 (1 << 9)
|
||||
#define MMCSD_SUP_HS200_1V2 (1 << 10)
|
||||
#define MMCSD_SUP_HS200 (MMCSD_SUP_HS200_1V2 | MMCSD_SUP_HS200_1V8) /* hs200 sdr */
|
||||
#define MMCSD_SUP_NONREMOVABLE (1 << 11)
|
||||
#define MMCSD_SUP_HS400_1V8 (1 << 12)
|
||||
#define MMCSD_SUP_HS400_1V2 (1 << 13)
|
||||
#define MMCSD_SUP_HS400 (MMCSD_SUP_HS400_1V2 | MMCSD_SUP_HS400_1V8) /* hs400 ddr */
|
||||
#define MMCSD_SUP_ENH_DS (1 << 14)
|
||||
|
||||
rt_uint32_t max_seg_size; /* maximum size of one dma segment */
|
||||
rt_uint32_t max_dma_segs; /* maximum number of dma segments in one request */
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-06-15 hichard first version
|
||||
* 2024-05-25 HPMicro add HS400 support
|
||||
*/
|
||||
|
||||
#include <drivers/mmcsd_core.h>
|
||||
|
@ -193,12 +194,19 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|||
}
|
||||
|
||||
host = card->host;
|
||||
if (host->flags & MMCSD_SUP_HS200)
|
||||
|
||||
uint8_t device_type = ext_csd[EXT_CSD_CARD_TYPE];
|
||||
if ((host->flags & MMCSD_SUP_HS400) && (device_type & EXT_CSD_CARD_TYPE_HS400))
|
||||
{
|
||||
card->flags |= CARD_FLAG_HS400;
|
||||
card->max_data_rate = 200000000;
|
||||
}
|
||||
else if ((host->flags & MMCSD_SUP_HS200) && (device_type & EXT_CSD_CARD_TYPE_HS200))
|
||||
{
|
||||
card->flags |= CARD_FLAG_HS200;
|
||||
card->hs_max_data_rate = 200000000;
|
||||
card->max_data_rate = 200000000;
|
||||
}
|
||||
else if (host->flags & MMCSD_SUP_HIGHSPEED_DDR)
|
||||
else if ((host->flags & MMCSD_SUP_HIGHSPEED_DDR) && (device_type & EXT_CSD_CARD_TYPE_DDR_52))
|
||||
{
|
||||
card->flags |= CARD_FLAG_HIGHSPEED_DDR;
|
||||
card->hs_max_data_rate = 52000000;
|
||||
|
@ -209,6 +217,11 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|||
card->hs_max_data_rate = 52000000;
|
||||
}
|
||||
|
||||
if (ext_csd[EXT_CSD_STROBE_SUPPORT] != 0)
|
||||
{
|
||||
card->ext_csd.enhanced_data_strobe = 1;
|
||||
}
|
||||
|
||||
card->ext_csd.cache_size =
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 0] << 0 |
|
||||
ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
|
||||
|
@ -410,6 +423,7 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
rt_err_t mmc_send_op_cond(struct rt_mmcsd_host *host,
|
||||
rt_uint32_t ocr, rt_uint32_t *rocr)
|
||||
{
|
||||
|
@ -484,28 +498,111 @@ static int mmc_select_hs200(struct rt_mmcsd_card *card)
|
|||
return ret;
|
||||
|
||||
mmcsd_set_timing(card->host, MMCSD_TIMING_MMC_HS200);
|
||||
mmcsd_set_clock(card->host, 200000000);
|
||||
mmcsd_set_clock(card->host, card->max_data_rate);
|
||||
|
||||
ret = mmcsd_excute_tuning(card);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mmc_switch_to_hs400(struct rt_mmcsd_card *card)
|
||||
{
|
||||
struct rt_mmcsd_host *host = card->host;
|
||||
int err;
|
||||
rt_uint8_t ext_csd_bus_width;
|
||||
rt_uint32_t hs_timing;
|
||||
|
||||
/* Switch to HS_TIMING to 0x01 (High Speed) */
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS);
|
||||
if (err != RT_EOK)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
mmcsd_set_timing(card->host, MMCSD_TIMING_MMC_HS);
|
||||
/* Host changes frequency to <= 52MHz */
|
||||
mmcsd_set_clock(card->host, 52000000);
|
||||
|
||||
rt_bool_t support_enhanced_ds = ((card->ext_csd.enhanced_data_strobe != 0) &&
|
||||
((host->flags & MMCSD_SUP_ENH_DS) != 0));
|
||||
|
||||
/* Set the bus width to:
|
||||
* 0x86 if enhanced data strobe is supported, or
|
||||
* 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;
|
||||
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BUS_WIDTH,
|
||||
ext_csd_bus_width);
|
||||
if (err != RT_EOK)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Set HS_TIMING to 0x03 (HS400) */
|
||||
err = mmc_switch(card,
|
||||
EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_HS_TIMING,
|
||||
EXT_CSD_TIMING_HS400);
|
||||
if (err != RT_EOK)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Change the Host timing accordingly */
|
||||
hs_timing = support_enhanced_ds ?
|
||||
MMCSD_TIMING_MMC_HS400_ENH_DS :
|
||||
MMCSD_TIMING_MMC_HS400;
|
||||
mmcsd_set_timing(host, hs_timing);
|
||||
|
||||
/* Host may changes frequency to <= 200MHz */
|
||||
mmcsd_set_clock(card->host, card->max_data_rate);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static int mmc_select_hs400(struct rt_mmcsd_card *card)
|
||||
{
|
||||
int ret;
|
||||
struct rt_mmcsd_host *host = card->host;
|
||||
/* if the card or host doesn't support enhanced data strobe, switch to HS200 and perform tuning process first */
|
||||
if ((card->ext_csd.enhanced_data_strobe == 0) || ((host->flags & MMCSD_SUP_ENH_DS) == 0))
|
||||
{
|
||||
ret = mmc_select_hs200(card);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return mmc_switch_to_hs400(card);
|
||||
}
|
||||
|
||||
static int mmc_select_timing(struct rt_mmcsd_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (card->flags & CARD_FLAG_HS200)
|
||||
if (card->flags & CARD_FLAG_HS400)
|
||||
{
|
||||
LOG_I("emmc: switch to HS400 mode\n");
|
||||
ret = mmc_select_hs400(card);
|
||||
}
|
||||
else if (card->flags & CARD_FLAG_HS200)
|
||||
{
|
||||
LOG_I("emmc: switch to HS200 mode\n");
|
||||
ret = mmc_select_hs200(card);
|
||||
}
|
||||
else if (card->flags & CARD_FLAG_HIGHSPEED_DDR)
|
||||
{
|
||||
LOG_I("emmc: switch to HIGH Speed DDR mode\n");
|
||||
mmcsd_set_timing(card->host, MMCSD_TIMING_MMC_DDR52);
|
||||
mmcsd_set_clock(card->host, card->hs_max_data_rate);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_I("emmc: switch to HIGH Speed mode\n");
|
||||
mmcsd_set_timing(card->host, MMCSD_TIMING_MMC_HS);
|
||||
mmcsd_set_clock(card->host, card->hs_max_data_rate);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue