From 3be534aa11af26d4f679894a3268b21afdfbe178 Mon Sep 17 00:00:00 2001 From: linzhenxing Date: Wed, 24 Aug 2022 10:53:12 +0800 Subject: [PATCH] =?UTF-8?q?mmc=20=E6=A8=A1=E5=BC=8F=E4=B8=8B=E5=A4=A9?= =?UTF-8?q?=E6=9C=BA=20high-speed-ddr=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../drivers/include/drivers/mmcsd_card.h | 5 +- .../drivers/include/drivers/mmcsd_cmd.h | 3 +- .../drivers/include/drivers/mmcsd_core.h | 1 + .../drivers/include/drivers/mmcsd_host.h | 18 +- components/drivers/sdio/mmc.c | 186 +++++++++++------- components/drivers/sdio/mmcsd_core.c | 6 + 6 files changed, 140 insertions(+), 79 deletions(-) diff --git a/components/drivers/include/drivers/mmcsd_card.h b/components/drivers/include/drivers/mmcsd_card.h index ea2de15ca5..75c42b46c4 100644 --- a/components/drivers/include/drivers/mmcsd_card.h +++ b/components/drivers/include/drivers/mmcsd_card.h @@ -150,10 +150,11 @@ struct rt_mmcsd_card { #define CARD_TYPE_SDIO_COMBO 3 /* SD combo (IO+mem) card */ rt_uint16_t flags; -#define CARD_FLAG_HIGHSPEED (1 << 0) /* SDIO bus speed 50MHz */ +#define CARD_FLAG_HIGHSPEED (1 << 0) /* SDIO bus speed 50MHz sdr*/ #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*/ 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 */ diff --git a/components/drivers/include/drivers/mmcsd_cmd.h b/components/drivers/include/drivers/mmcsd_cmd.h index 7c2f26e892..21e23cec6a 100644 --- a/components/drivers/include/drivers/mmcsd_cmd.h +++ b/components/drivers/include/drivers/mmcsd_cmd.h @@ -37,7 +37,8 @@ extern "C" { #define SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ #define READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ #define READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ - +#define SEND_TUNING_BLOCK 19 /* adtc R1 */ +#define SEND_TUNING_BLOCK_HS200 21 /* adtc R1*/ /* class 3 */ #define WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ diff --git a/components/drivers/include/drivers/mmcsd_core.h b/components/drivers/include/drivers/mmcsd_core.h index e78469007a..70337c36b1 100644 --- a/components/drivers/include/drivers/mmcsd_core.h +++ b/components/drivers/include/drivers/mmcsd_core.h @@ -228,6 +228,7 @@ void mmcsd_set_chip_select(struct rt_mmcsd_host *host, rt_int32_t mode); void mmcsd_set_clock(struct rt_mmcsd_host *host, rt_uint32_t clk); void mmcsd_set_bus_mode(struct rt_mmcsd_host *host, rt_uint32_t mode); void mmcsd_set_bus_width(struct rt_mmcsd_host *host, rt_uint32_t width); +void mmcsd_set_timing(struct rt_mmcsd_host *host, rt_uint32_t timing); void mmcsd_set_data_timeout(struct rt_mmcsd_data *data, const struct rt_mmcsd_card *card); rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr); void mmcsd_change(struct rt_mmcsd_host *host); diff --git a/components/drivers/include/drivers/mmcsd_host.h b/components/drivers/include/drivers/mmcsd_host.h index 1550c4b3c7..ddb37802ca 100644 --- a/components/drivers/include/drivers/mmcsd_host.h +++ b/components/drivers/include/drivers/mmcsd_host.h @@ -46,6 +46,19 @@ struct rt_mmcsd_io_cfg { #define MMCSD_BUS_WIDTH_4 2 #define MMCSD_BUS_WIDTH_8 3 + unsigned char timing; /* timing specification used */ + +#define MMCSD_TIMING_LEGACY 0 +#define MMCSD_TIMING_MMC_HS 1 +#define MMCSD_TIMING_SD_HS 2 +#define MMCSD_TIMING_UHS_SDR12 3 +#define MMCSD_TIMING_UHS_SDR25 4 +#define MMCSD_TIMING_UHS_SDR50 5 +#define MMCSD_TIMING_UHS_SDR104 6 +#define MMCSD_TIMING_UHS_DDR50 7 +#define MMCSD_TIMING_MMC_DDR52 8 +#define MMCSD_TIMING_MMC_HS200 9 +#define MMCSD_TIMING_MMC_HS400 10 }; struct rt_mmcsd_host; @@ -56,6 +69,7 @@ struct rt_mmcsd_host_ops { void (*set_iocfg)(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg); rt_int32_t (*get_card_status)(struct rt_mmcsd_host *host); void (*enable_sdio_irq)(struct rt_mmcsd_host *host, rt_int32_t en); + void (*execute_tuning)(struct rt_mmcsd_host *host, rt_int32_t opcode); }; struct rt_mmcsd_host { @@ -90,7 +104,9 @@ 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 */ +#define MMCSD_SUP_HIGHSPEED (1 << 5) /* support high speed SDR*/ +#define MMCSD_SUP_HIGHSPEED_DDR (1 << 6)/* HIGH SPEED DDR*/ +#define MMCSD_SUP_HS200 (1 << 7) 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 */ diff --git a/components/drivers/sdio/mmc.c b/components/drivers/sdio/mmc.c index ff946d93d0..d7c2f4e929 100644 --- a/components/drivers/sdio/mmc.c +++ b/components/drivers/sdio/mmc.c @@ -181,16 +181,25 @@ static int mmc_get_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t **new_ext_csd) */ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) { - rt_uint64_t card_capacity = 0; - - if(card == RT_NULL || ext_csd == RT_NULL) - { - LOG_E("emmc parse ext csd fail, invaild args"); - return -1; - } + rt_uint64_t card_capacity = 0; + struct rt_mmcsd_host *host; + if(card == RT_NULL || ext_csd == RT_NULL) + { + LOG_E("emmc parse ext csd fail, invaild args"); + return -1; + } - card->flags |= CARD_FLAG_HIGHSPEED; - card->hs_max_data_rate = 52000000; + host = card->host; + if (host->flags & MMCSD_SUP_HIGHSPEED_DDR) + { + card->flags |= CARD_FLAG_HIGHSPEED_DDR; + card->hs_max_data_rate = 52000000; + } + else + { + card->flags |= CARD_FLAG_HIGHSPEED; + card->hs_max_data_rate = 52000000; + } card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); card->card_sec_cnt = card_capacity; @@ -289,82 +298,101 @@ out: */ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) { - rt_uint32_t ext_csd_bits[] = { - EXT_CSD_BUS_WIDTH_8, - EXT_CSD_BUS_WIDTH_4, - EXT_CSD_BUS_WIDTH_1 - }; - rt_uint32_t bus_widths[] = { - MMCSD_BUS_WIDTH_8, - MMCSD_BUS_WIDTH_4, - MMCSD_BUS_WIDTH_1 - }; - struct rt_mmcsd_host *host = card->host; - unsigned idx, bus_width = 0; - int err = 0; + 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[] = + { + MMCSD_BUS_WIDTH_8, + MMCSD_BUS_WIDTH_4, + MMCSD_BUS_WIDTH_1 + }; + struct rt_mmcsd_host *host = card->host; + unsigned idx, bus_width = 0; + int err = 0, ddr = 0; if (GET_BITS(card->resp_csd, 122, 4) < 4) return 0; - /* - * Unlike SD, MMC cards dont have a configuration register to notify - * supported bus width. So bus test command should be run to identify - * the supported bus width or compare the ext csd values of current - * bus width and ext csd values of 1 bit mode read earlier. - */ - for (idx = 0; idx < sizeof(bus_widths)/sizeof(rt_uint32_t); idx++) { + if (card->flags & CARD_FLAG_HIGHSPEED_DDR) + { + ddr = 2; + } /* - * Host is capable of 8bit transfer, then switch - * the device to work in 8bit transfer mode. If the - * mmc switch command returns error then switch to - * 4bit transfer mode. On success set the corresponding - * bus width on the host. Meanwhile, mmc core would - * bail out early if corresponding bus capable wasn't - * set by drivers. + * Unlike SD, MMC cards dont have a configuration register to notify + * supported bus width. So bus test command should be run to identify + * the supported bus width or compare the ext csd values of current + * bus width and ext csd values of 1 bit mode read earlier. */ + for (idx = 0; idx < sizeof(bus_widths)/sizeof(rt_uint32_t); idx++) + { + /* + * Host is capable of 8bit transfer, then switch + * the device to work in 8bit transfer mode. If the + * mmc switch command returns error then switch to + * 4bit transfer mode. On success set the corresponding + * bus width on the host. Meanwhile, mmc core would + * bail out early if corresponding bus capable wasn't + * set by drivers. + */ + bus_width = bus_widths[idx]; + if (bus_width == MMCSD_BUS_WIDTH_1) + { + ddr = 0; + } + + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, + ext_csd_bits[idx][0]); + + if (err) + continue; + + mmcsd_set_bus_width(host, bus_width); + err = mmc_compare_ext_csds(card, ext_csd, bus_width); + if (!err) + { + break; + } + else + { + switch(ext_csd_bits[idx][0]) + { + case 0: + LOG_E("switch to bus width 1 bit failed!"); + break; + case 1: + LOG_E("switch to bus width 4 bit failed!"); + break; + case 2: + LOG_E("switch to bus width 8 bit failed!"); + break; + default: + break; + } + } + } - if (!(((host->flags & MMCSD_BUSWIDTH_8) && - ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8) || - ((host->flags & MMCSD_BUSWIDTH_4) && - ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_4) || - !(ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8))) + if (!err && ddr) { - continue; + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, + ext_csd_bits[idx][1]); } - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - ext_csd_bits[idx]); - if (err) - continue; - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, - 1); + if (!err) + { + if (card->flags & (CARD_FLAG_HIGHSPEED | CARD_FLAG_HIGHSPEED_DDR)) + { - if (err) - continue; - bus_width = bus_widths[idx]; - mmcsd_set_bus_width(host, bus_width); - err = mmc_compare_ext_csds(card, ext_csd, bus_width); - if (!err) { - err = bus_width; - break; - } else { - switch(ext_csd_bits[idx]){ - case 0: - LOG_E("switch to bus width 1 bit failed!"); - break; - case 1: - LOG_E("switch to bus width 4 bit failed!"); - break; - case 2: - LOG_E("switch to bus width 8 bit failed!"); - break; - default: - break; - } + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, + 1); + } } - } return err; } @@ -520,14 +548,22 @@ static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host, card->flags |= CARD_FLAG_SDHC; /* set bus speed */ - if (card->flags & CARD_FLAG_HIGHSPEED) + if (card->flags & (CARD_FLAG_HIGHSPEED | CARD_FLAG_HIGHSPEED_DDR)) max_data_rate = card->hs_max_data_rate; else max_data_rate = card->max_data_rate; /*switch bus width and bus mode*/ mmc_select_bus_width(card, ext_csd); - + if (card->flags & CARD_FLAG_HIGHSPEED_DDR) + { + mmcsd_set_timing(host, MMCSD_TIMING_MMC_DDR52); + } + else + { + mmcsd_set_timing(host, MMCSD_TIMING_UHS_SDR50); + } + mmcsd_set_clock(host, max_data_rate); host->card = card; diff --git a/components/drivers/sdio/mmcsd_core.c b/components/drivers/sdio/mmcsd_core.c index a78c78f93d..6e3949ba70 100644 --- a/components/drivers/sdio/mmcsd_core.c +++ b/components/drivers/sdio/mmcsd_core.c @@ -438,6 +438,12 @@ void mmcsd_set_bus_width(struct rt_mmcsd_host *host, rt_uint32_t width) mmcsd_set_iocfg(host); } +void mmcsd_set_timing(struct rt_mmcsd_host *host, rt_uint32_t timing) +{ + host->io_cfg.timing = timing; + mmcsd_set_iocfg(host); +} + void mmcsd_set_data_timeout(struct rt_mmcsd_data *data, const struct rt_mmcsd_card *card) { -- Gitee