static int
esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
+ int err = 0;
uint xfertyp;
uint irqstat;
struct fsl_esdhc_cfg *cfg = mmc->priv;
/* Set up for a data transfer if we have one */
if (data) {
- int err;
-
err = esdhc_setup_data(mmc, data);
if(err)
return err;
irqstat = esdhc_read32(®s->irqstat);
- /* Reset CMD and DATA portions on error */
- if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) {
- esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) |
- SYSCTL_RSTC);
- while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC)
- ;
-
- if (data) {
- esdhc_write32(®s->sysctl,
- esdhc_read32(®s->sysctl) |
- SYSCTL_RSTD);
- while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD))
- ;
- }
+ if (irqstat & CMD_ERR) {
+ err = COMM_ERR;
+ goto out;
}
- if (irqstat & CMD_ERR)
- return COMM_ERR;
-
- if (irqstat & IRQSTAT_CTOE)
- return TIMEOUT;
+ if (irqstat & IRQSTAT_CTOE) {
+ err = TIMEOUT;
+ goto out;
+ }
/* Workaround for ESDHC errata ENGcm03648 */
if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
if (timeout <= 0) {
printf("Timeout waiting for DAT0 to go high!\n");
- return TIMEOUT;
+ err = TIMEOUT;
+ goto out;
}
}
do {
irqstat = esdhc_read32(®s->irqstat);
- if (irqstat & IRQSTAT_DTOE)
- return TIMEOUT;
+ if (irqstat & IRQSTAT_DTOE) {
+ err = TIMEOUT;
+ goto out;
+ }
- if (irqstat & DATA_ERR)
- return COMM_ERR;
+ if (irqstat & DATA_ERR) {
+ err = COMM_ERR;
+ goto out;
+ }
} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
#endif
if (data->flags & MMC_DATA_READ)
check_and_invalidate_dcache_range(cmd, data);
}
+out:
+ /* Reset CMD and DATA portions on error */
+ if (err) {
+ esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) |
+ SYSCTL_RSTC);
+ while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC)
+ ;
+
+ if (data) {
+ esdhc_write32(®s->sysctl,
+ esdhc_read32(®s->sysctl) |
+ SYSCTL_RSTD);
+ while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD))
+ ;
+ }
+ }
+
esdhc_write32(®s->irqstat, -1);
- return 0;
+ return err;
}
static void set_sysctl(struct mmc *mmc, uint clock)