Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hw/drivers/mmc: Fix Multiple Block Read CMD18 #3036

Merged
merged 2 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion hw/drivers/mmc/include/mmc/mmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ extern "C" {

extern struct disk_ops mmc_ops;

struct mmc_spi_cfg {
uint32_t initial_freq_khz;
uint32_t freq_khz;
uint8_t clock_mode;
};

/**
* Initialize the MMC driver
*
Expand All @@ -56,7 +62,7 @@ extern struct disk_ops mmc_ops;
* @return 0 on success, non-zero on failure
*/
int
mmc_init(int spi_num, void *spi_cfg, int ss_pin);
mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int ss_pin);

/**
* Read data from MMC
Expand Down
90 changes: 43 additions & 47 deletions hw/drivers/mmc/src/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,11 @@

static uint8_t g_block_buf[BLOCK_LEN];

static struct hal_spi_settings mmc_settings = {
.data_order = HAL_SPI_MSB_FIRST,
.data_mode = HAL_SPI_MODE0,
/* XXX: MMC initialization accepts clocks in the range 100-400KHz */
/* TODO: switch to high-speed aka 25MHz after initialization. */
/* Currently the lowest clock acceptable is 125KHz */
.baudrate = 125,
.word_size = HAL_SPI_WORD_SIZE_8BIT,
};

/* FIXME: currently limited to single MMC spi device */
static struct mmc_cfg {
int spi_num;
int ss_pin;
void *spi_cfg;
struct hal_spi_settings *settings;
int spi_num;
int ss_pin;
struct mmc_spi_cfg mmc_spi_cfg;
} g_mmc_cfg;

static int
Expand Down Expand Up @@ -173,36 +162,34 @@ send_mmc_cmd(struct mmc_cfg *mmc, uint8_t cmd, uint32_t payload)
* @param spi_num Number of the SPI channel to be used by MMC
* @param spi_cfg Low-level device specific SPI configuration
* @param ss_pin Number of SS pin if SW controlled, -1 otherwise
* @param mmc_spi_cfg
*
* @return 0 on success, non-zero on failure
*/
int
mmc_init(int spi_num, void *spi_cfg, int ss_pin)
mmc_init(int spi_num, struct mmc_spi_cfg *spi_cfg, int ss_pin)
{
int rc;
int i;
uint8_t status;
uint8_t cmd_resp[4];
uint32_t ocr;
os_time_t timeout;
struct mmc_cfg *mmc;

/* TODO: create new struct for every new spi mmc, add to SLIST */
mmc = &g_mmc_cfg;
mmc->spi_num = spi_num;
struct mmc_cfg *mmc = &g_mmc_cfg;
mmc->ss_pin = ss_pin;
mmc->spi_cfg = spi_cfg;
mmc->settings = &mmc_settings;
mmc->mmc_spi_cfg = *spi_cfg;

hal_gpio_init_out(mmc->ss_pin, 1);
mmc->spi_num = spi_num;
struct hal_spi_settings spi_settings = {
.data_order = HAL_SPI_MSB_FIRST,
.data_mode = mmc->mmc_spi_cfg.clock_mode,
.baudrate = mmc->mmc_spi_cfg.initial_freq_khz,
.word_size = HAL_SPI_WORD_SIZE_8BIT,
};

rc = hal_spi_init(mmc->spi_num, mmc->spi_cfg, HAL_SPI_TYPE_MASTER);
if (rc) {
return (rc);
}
hal_gpio_init_out(mmc->ss_pin, 1);

rc = hal_spi_config(mmc->spi_num, mmc->settings);
rc = hal_spi_config(mmc->spi_num, &spi_settings);
if (rc) {
return (rc);
}
Expand Down Expand Up @@ -232,12 +219,19 @@ mmc_init(int spi_num, void *spi_cfg, int ss_pin)
/* put card in idle state */
status = send_mmc_cmd(mmc, CMD0, 0);

hal_gpio_write(mmc->ss_pin, 1);
/* No card inserted or bad card? */
if (status != R_IDLE) {
rc = error_by_response(status);
goto out;
}

hal_spi_disable(mmc->spi_num);
spi_settings.baudrate = mmc->mmc_spi_cfg.freq_khz;
rc = hal_spi_config(mmc->spi_num, &spi_settings);
hal_spi_enable(mmc->spi_num);
hal_gpio_write(mmc->ss_pin, 0);

/**
* FIXME: while doing a hot-swap of the card or powering off the board
* it is required to send a CMD1 here otherwise CMD8's response will
Expand Down Expand Up @@ -400,27 +394,29 @@ mmc_read(uint8_t mmc_id, uint32_t addr, void *buf, uint32_t len)
goto out;
}

/**
* 7.3.3 Control tokens
* Wait up to 200ms for control token.
*/
timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
do {
res = hal_spi_tx_val(mmc->spi_num, 0xff);
if (res != 0xFF) break;
os_time_delay(OS_TICKS_PER_SEC / 20);
} while (os_time_get() < timeout);

/**
* 7.3.3.2 Start Block Tokens and Stop Tran Token
*/
if (res != START_BLOCK) {
rc = MMC_TIMEOUT;
goto out;
}

index = 0;
while (block_count--) {
/**
* 7.3.3 Control tokens
* Wait up to 200ms for control token.
*/
timeout = os_time_get() + OS_TICKS_PER_SEC / 5;
do {
res = hal_spi_tx_val(mmc->spi_num, 0xff);
if (res != 0xFF) {
break;
}
os_time_delay(OS_TICKS_PER_SEC / 20);
} while (os_time_get() < timeout);

/**
* 7.3.3.2 Start Block Tokens and Stop Tran Token
*/
if (res != START_BLOCK) {
rc = MMC_TIMEOUT;
goto out;
}

for (n = 0; n < BLOCK_LEN; n++) {
g_block_buf[n] = hal_spi_tx_val(mmc->spi_num, 0xff);
}
Expand Down