|
@@ -418,6 +418,8 @@ static int dw_mci_idmac_init(struct dw_mci *host)
|
|
|
p->des3 = host->sg_dma;
|
|
|
p->des0 = IDMAC_DES0_ER;
|
|
|
|
|
|
+ mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET);
|
|
|
+
|
|
|
/* Mask out interrupts - get Tx & Rx complete only */
|
|
|
mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
|
|
|
SDMMC_IDMAC_INT_TI);
|
|
@@ -615,14 +617,15 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
|
|
|
u32 div;
|
|
|
|
|
|
if (slot->clock != host->current_speed) {
|
|
|
- if (host->bus_hz % slot->clock)
|
|
|
+ div = host->bus_hz / slot->clock;
|
|
|
+ if (host->bus_hz % slot->clock && host->bus_hz > slot->clock)
|
|
|
/*
|
|
|
* move the + 1 after the divide to prevent
|
|
|
* over-clocking the card.
|
|
|
*/
|
|
|
- div = ((host->bus_hz / slot->clock) >> 1) + 1;
|
|
|
- else
|
|
|
- div = (host->bus_hz / slot->clock) >> 1;
|
|
|
+ div += 1;
|
|
|
+
|
|
|
+ div = (host->bus_hz != slot->clock) ? DIV_ROUND_UP(div, 2) : 0;
|
|
|
|
|
|
dev_info(&slot->mmc->class_dev,
|
|
|
"Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ"
|
|
@@ -939,8 +942,8 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd
|
|
|
mdelay(20);
|
|
|
|
|
|
if (cmd->data) {
|
|
|
- host->data = NULL;
|
|
|
dw_mci_stop_dma(host);
|
|
|
+ host->data = NULL;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1623,7 +1626,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
|
|
|
if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
|
|
|
mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
|
|
|
mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
|
|
|
- set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
|
|
|
host->dma_ops->complete(host);
|
|
|
}
|
|
|
#endif
|
|
@@ -1725,7 +1727,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
|
|
|
|
|
|
#ifdef CONFIG_MMC_DW_IDMAC
|
|
|
ctrl = mci_readl(host, BMOD);
|
|
|
- ctrl |= 0x01; /* Software reset of DMA */
|
|
|
+ /* Software reset of DMA */
|
|
|
+ ctrl |= SDMMC_IDMAC_SWRESET;
|
|
|
mci_writel(host, BMOD, ctrl);
|
|
|
#endif
|
|
|
|
|
@@ -1950,10 +1953,6 @@ int dw_mci_probe(struct dw_mci *host)
|
|
|
spin_lock_init(&host->lock);
|
|
|
INIT_LIST_HEAD(&host->queue);
|
|
|
|
|
|
-
|
|
|
- host->dma_ops = host->pdata->dma_ops;
|
|
|
- dw_mci_init_dma(host);
|
|
|
-
|
|
|
/*
|
|
|
* Get the host data width - this assumes that HCON has been set with
|
|
|
* the correct values.
|
|
@@ -1981,10 +1980,11 @@ int dw_mci_probe(struct dw_mci *host)
|
|
|
}
|
|
|
|
|
|
/* Reset all blocks */
|
|
|
- if (!mci_wait_reset(&host->dev, host)) {
|
|
|
- ret = -ENODEV;
|
|
|
- goto err_dmaunmap;
|
|
|
- }
|
|
|
+ if (!mci_wait_reset(&host->dev, host))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ host->dma_ops = host->pdata->dma_ops;
|
|
|
+ dw_mci_init_dma(host);
|
|
|
|
|
|
/* Clear the interrupts for the host controller */
|
|
|
mci_writel(host, RINTSTS, 0xFFFFFFFF);
|
|
@@ -2170,14 +2170,14 @@ int dw_mci_resume(struct dw_mci *host)
|
|
|
if (host->vmmc)
|
|
|
regulator_enable(host->vmmc);
|
|
|
|
|
|
- if (host->dma_ops->init)
|
|
|
- host->dma_ops->init(host);
|
|
|
-
|
|
|
if (!mci_wait_reset(&host->dev, host)) {
|
|
|
ret = -ENODEV;
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ if (host->dma_ops->init)
|
|
|
+ host->dma_ops->init(host);
|
|
|
+
|
|
|
/* Restore the old value at FIFOTH register */
|
|
|
mci_writel(host, FIFOTH, host->fifoth_val);
|
|
|
|