[components][sdio] Support DDR mode

This commit is contained in:
tyx 2022-04-02 19:03:00 +08:00 committed by guo
parent 556b14ed47
commit 782b9dd45a
4 changed files with 118 additions and 81 deletions

View File

@ -45,7 +45,8 @@ struct rt_mmcsd_io_cfg {
#define MMCSD_BUS_WIDTH_1 0 #define MMCSD_BUS_WIDTH_1 0
#define MMCSD_BUS_WIDTH_4 2 #define MMCSD_BUS_WIDTH_4 2
#define MMCSD_BUS_WIDTH_8 3 #define MMCSD_BUS_WIDTH_8 3
#define MMCSD_DDR_BUS_WIDTH_4 4
#define MMCSD_DDR_BUS_WIDTH_8 5
}; };
struct rt_mmcsd_host; struct rt_mmcsd_host;
@ -90,6 +91,9 @@ struct rt_mmcsd_host {
#define controller_is_spi(host) (host->flags & MMCSD_HOST_IS_SPI) #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_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 */
#define MMCSD_SUP_HIGHSPEED_DDR (1 << 6) /* support high speed(DDR) */
#define MMCSD_SUP_HIGHSPEED_HS200 (1 << 7) /* support high speed HS200 */
#define MMCSD_SUP_HIGHSPEED_HS400 (1 << 8) /* support high speed HS400 */
rt_uint32_t max_seg_size; /* maximum size of one dma segment */ 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 */ rt_uint32_t max_dma_segs; /* maximum number of dma segments in one request */

View File

@ -290,10 +290,19 @@ 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[] = { rt_uint32_t ext_csd_bits[] = {
EXT_CSD_DDR_BUS_WIDTH_8,
EXT_CSD_DDR_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8, EXT_CSD_BUS_WIDTH_8,
EXT_CSD_BUS_WIDTH_4, EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_1 EXT_CSD_BUS_WIDTH_1
}; };
rt_uint32_t bus_widths[] = {
MMCSD_DDR_BUS_WIDTH_8,
MMCSD_DDR_BUS_WIDTH_4,
MMCSD_BUS_WIDTH_8,
MMCSD_BUS_WIDTH_4,
MMCSD_BUS_WIDTH_1
};
struct rt_mmcsd_host *host = card->host; struct rt_mmcsd_host *host = card->host;
unsigned idx, trys, bus_width = 0; unsigned idx, trys, bus_width = 0;
int err = 0; int err = 0;
@ -317,19 +326,33 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
* bail out early if corresponding bus capable wasn't * bail out early if corresponding bus capable wasn't
* set by drivers. * set by drivers.
*/ */
if ((!(host->flags & MMCSD_BUSWIDTH_8) && if ((!((host->flags & MMCSD_BUSWIDTH_8) &&
(host->flags & MMCSD_SUP_HIGHSPEED_DDR)) &&
ext_csd_bits[idx] == EXT_CSD_DDR_BUS_WIDTH_8) ||
(!((host->flags & MMCSD_BUSWIDTH_4) &&
(host->flags & MMCSD_SUP_HIGHSPEED_DDR)) &&
ext_csd_bits[idx] == EXT_CSD_DDR_BUS_WIDTH_4) ||
(!(host->flags & MMCSD_BUSWIDTH_8) &&
ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8) || ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8) ||
(!(host->flags & MMCSD_BUSWIDTH_4) && (!(host->flags & MMCSD_BUSWIDTH_4) &&
(ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_4 || ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_4))
ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8)))
continue; continue;
if (host->flags & MMCSD_SUP_HIGHSPEED_DDR)
{
/* HS_TIMING must be set to "0x1" before setting BUS_WIDTH for dual-data-rate(DDR) operation */
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS);
if (err)
LOG_E("switch to speed mode width hight speed failed!");
}
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,
ext_csd_bits[idx]); ext_csd_bits[idx]);
if (err) if (err)
continue; continue;
bus_width = bus_widths[idx];
for(trys = 0; trys < 5; trys++){ for(trys = 0; trys < 5; trys++){
mmcsd_set_bus_width(host, bus_width); mmcsd_set_bus_width(host, bus_width);
mmcsd_delay_ms(10); mmcsd_delay_ms(10);
@ -342,14 +365,20 @@ static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
break; break;
} else { } else {
switch(ext_csd_bits[idx]){ switch(ext_csd_bits[idx]){
case 0: case EXT_CSD_DDR_BUS_WIDTH_8:
LOG_E("switch to bus width 1 bit failed!"); LOG_E("switch to bus width DDR 8 bit failed!");
break; break;
case 1: case EXT_CSD_DDR_BUS_WIDTH_4:
LOG_E("switch to bus width DDR 4 bit failed!");
break;
case EXT_CSD_BUS_WIDTH_8:
LOG_E("switch to bus width 8 bit failed!");
break;
case EXT_CSD_BUS_WIDTH_4:
LOG_E("switch to bus width 4 bit failed!"); LOG_E("switch to bus width 4 bit failed!");
break; break;
case 2: case EXT_CSD_BUS_WIDTH_1:
LOG_E("switch to bus width 8 bit failed!"); LOG_E("switch to bus width 1 bit failed!");
break; break;
default: default:
break; break;

View File

@ -743,7 +743,11 @@ static rt_int32_t sdio_set_highspeed(struct rt_mmcsd_card *card)
rt_int32_t ret; rt_int32_t ret;
rt_uint8_t speed; rt_uint8_t speed;
if (!(card->host->flags & MMCSD_SUP_HIGHSPEED)) if (!(card->host->flags &
(MMCSD_SUP_HIGHSPEED |
MMCSD_SUP_HIGHSPEED_DDR |
MMCSD_SUP_HIGHSPEED_HS200 |
MMCSD_SUP_HIGHSPEED_HS400)))
return 0; return 0;
if (!card->cccr.high_speed) if (!card->cccr.high_speed)