Hi, On Tue, 2023-03-21 at 10:50 +0100, Sascha Hauer wrote: > We have different driver specific variants of functions polling for the > device ready in the tree. Add a common sdhci_wait_for_done() and use > it where appropriate. This fixes a few deficiencies with the driver > specific variants. > > rk_sdhci_wait_for_done() didn't check the SDHCI_INT_TIMEOUT bit and > returned -EPERM instead when it ought to return -ETIMEDOUT. The core > tries to detect a SD card first and expects a -ETIMEDOUT for the setup > command when really a eMMC is connected. Only with a -ETIMEDOUT the core > tries to detect a eMMC next. > > at91_sdhci_wait_for_done() returned the status instead of the expected > 0 value for success. I had to revert this commit to run barebox_update on the CM3 RK3566. Otherwise writes to the boot partition would hang indefinitely. Best regards, Rouven Czerwinski > > Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> > --- > drivers/mci/arasan-sdhci.c | 29 +--------------------------- > drivers/mci/atmel-sdhci-common.c | 28 +-------------------------- > drivers/mci/rockchip-dwcmshc-sdhci.c | 25 +----------------------- > drivers/mci/sdhci.c | 27 ++++++++++++++++++++++++++ > drivers/mci/sdhci.h | 1 + > 5 files changed, 31 insertions(+), 79 deletions(-) > > diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c > index 00a8ceed68..650de22b69 100644 > --- a/drivers/mci/arasan-sdhci.c > +++ b/drivers/mci/arasan-sdhci.c > @@ -133,33 +133,6 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) > sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); > } > > -static int arasan_sdhci_wait_for_done(struct arasan_sdhci_host *host, u32 mask) > -{ > - u64 start = get_time_ns(); > - u32 stat; > - > - do { > - stat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS); > - > - if (stat & SDHCI_INT_TIMEOUT) > - return -ETIMEDOUT; > - > - if (stat & SDHCI_INT_ERROR) { > - dev_err(host->mci.hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", > - stat); > - return -EPERM; > - } > - > - if (is_timeout(start, 1000 * MSECOND)) { > - dev_err(host->mci.hw_dev, > - "SDHCI timeout while waiting for done\n"); > - return -ETIMEDOUT; > - } > - } while ((stat & mask) != mask); > - > - return 0; > -} > - > static void print_error(struct arasan_sdhci_host *host, int cmdidx, int ret) > { > if (ret == -ETIMEDOUT) > @@ -213,7 +186,7 @@ static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, > sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); > sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); > > - ret = arasan_sdhci_wait_for_done(host, mask); > + ret = sdhci_wait_for_done(&host->sdhci, mask); > if (ret) > goto error; > > diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c > index 05a019beb6..58ba0b9b3d 100644 > --- a/drivers/mci/atmel-sdhci-common.c > +++ b/drivers/mci/atmel-sdhci-common.c > @@ -89,32 +89,6 @@ exit: > return is_inserted; > } > > -static int at91_sdhci_wait_for_done(struct at91_sdhci *host, u32 mask) > -{ > - struct sdhci *sdhci = &host->sdhci; > - u32 status; > - int ret; > - > - ret = sdhci_read32_poll_timeout(sdhci, SDHCI_INT_STATUS, status, > - (status & mask) == mask || (status & SDHCI_INT_ERROR), > - USEC_PER_SEC); > - > - if (ret < 0) { > - dev_err(host->dev, "SDHCI timeout while waiting for done\n"); > - return ret; > - } > - > - if (status & SDHCI_INT_TIMEOUT) > - return -ETIMEDOUT; > - > - if (status & SDHCI_INT_ERROR) { > - dev_err(host->dev, "SDHCI_INT_STATUS: 0x%08x\n", status); > - return -EPERM; > - } > - > - return status & 0xFFFF; > -} > - > int at91_sdhci_send_command(struct at91_sdhci *host, struct mci_cmd *cmd, > struct mci_data *data) > { > @@ -158,7 +132,7 @@ int at91_sdhci_send_command(struct at91_sdhci *host, struct mci_cmd *cmd, > sdhci_write32(sdhci, SDHCI_ARGUMENT, cmd->cmdarg); > sdhci_write16(sdhci, SDHCI_COMMAND, command); > > - status = at91_sdhci_wait_for_done(host, mask); > + status = sdhci_wait_for_done(&host->sdhci, mask); > if (status < 0) > goto error; > > diff --git a/drivers/mci/rockchip-dwcmshc-sdhci.c b/drivers/mci/rockchip-dwcmshc-sdhci.c > index 4b4e8b7bd6..e055a8ea71 100644 > --- a/drivers/mci/rockchip-dwcmshc-sdhci.c > +++ b/drivers/mci/rockchip-dwcmshc-sdhci.c > @@ -216,29 +216,6 @@ static void rk_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) > sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); > } > > -static int rk_sdhci_wait_for_done(struct rk_sdhci_host *host, u32 mask) > -{ > - u64 start = get_time_ns(); > - u16 stat; > - > - do { > - stat = sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS); > - if (stat & SDHCI_INT_ERROR) { > - dev_dbg(host->mci.hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", > - sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); > - return -EPERM; > - } > - > - if (is_timeout(start, 1000 * MSECOND)) { > - dev_err(host->mci.hw_dev, > - "SDHCI timeout while waiting for done\n"); > - return -ETIMEDOUT; > - } > - } while ((stat & mask) != mask); > - > - return 0; > -} > - > static void print_error(struct rk_sdhci_host *host, int cmdidx) > { > dev_dbg(host->mci.hw_dev, > @@ -285,7 +262,7 @@ static int rk_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, > sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); > sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); > > - ret = rk_sdhci_wait_for_done(host, SDHCI_INT_CMD_COMPLETE); > + ret = sdhci_wait_for_done(&host->sdhci, SDHCI_INT_CMD_COMPLETE); > if (ret == -EPERM) > goto error; > else if (ret) > diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c > index 2cdd3c3c8f..635884e2a2 100644 > --- a/drivers/mci/sdhci.c > +++ b/drivers/mci/sdhci.c > @@ -124,6 +124,33 @@ void sdhci_set_bus_width(struct sdhci *host, int width) > > #endif > > +int sdhci_wait_for_done(struct sdhci *sdhci, u32 mask) > +{ > + u64 start = get_time_ns(); > + u32 stat; > + > + do { > + stat = sdhci_read32(sdhci, SDHCI_INT_STATUS); > + > + if (stat & SDHCI_INT_TIMEOUT) > + return -ETIMEDOUT; > + > + if (stat & SDHCI_INT_ERROR) { > + dev_err(sdhci->mci->hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", > + stat); > + return -EPERM; > + } > + > + if (is_timeout(start, 1000 * MSECOND)) { > + dev_err(sdhci->mci->hw_dev, > + "SDHCI timeout while waiting for done\n"); > + return -ETIMEDOUT; > + } > + } while ((stat & mask) != mask); > + > + return 0; > +} > + > void sdhci_setup_data_pio(struct sdhci *sdhci, struct mci_data *data) > { > if (!data) > diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h > index c538385939..fe8c25cb9c 100644 > --- a/drivers/mci/sdhci.h > +++ b/drivers/mci/sdhci.h > @@ -257,6 +257,7 @@ static inline void sdhci_write8(struct sdhci *host, int reg, u32 val) > } > > #define SDHCI_NO_DMA DMA_ERROR_CODE > +int sdhci_wait_for_done(struct sdhci *host, u32 mask); > void sdhci_read_response(struct sdhci *host, struct mci_cmd *cmd); > void sdhci_set_cmd_xfer_mode(struct sdhci *host, struct mci_cmd *cmd, > struct mci_data *data, bool dma, u32 *command,