@@ -123,15 +123,16 @@ struct mmc_omap_host {
struct mmc_data * data;
struct mmc_host * mmc;
struct device * dev;
- unsigned char id; /* 16xx chips have 2 MMC blocks */
struct clk * iclk;
struct clk * fclk;
struct resource *mem_res;
void __iomem *virt_base;
unsigned int phys_base;
int irq;
+ unsigned char id; /* 16xx chips have 2 MMC blocks */
unsigned char bus_mode;
unsigned char hw_bus_mode;
+ unsigned char power_mode;
struct work_struct cmd_abort_work;
unsigned abort:1;
@@ -1233,7 +1234,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct mmc_omap_slot *slot = mmc_priv(mmc);
struct mmc_omap_host *host = slot->host;
int i, dsor;
- int clk_enabled;
+ int clk_enabled, init_stream;
mmc_omap_select_slot(slot, 0);
@@ -1243,20 +1244,27 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
slot->vdd = ios->vdd;
clk_enabled = 0;
+ init_stream = 0;
switch (ios->power_mode) {
case MMC_POWER_OFF:
+ printk("MMC_POWER_OFF\n");
mmc_omap_set_power(slot, 0, ios->vdd);
break;
case MMC_POWER_UP:
+ printk("MMC_POWER_UP\n");
/* Cannot touch dsor yet, just power up MMC */
mmc_omap_set_power(slot, 1, ios->vdd);
+ host->power_mode = ios->power_mode;
goto exit;
case MMC_POWER_ON:
+ printk("MMC_POWER_ON\n");
mmc_omap_fclk_enable(host, 1);
clk_enabled = 1;
- dsor |= 1 << 11;
+ if (host->power_mode != MMC_POWER_ON)
+ init_stream = 1;
break;
}
+ host->power_mode = ios->power_mode;
if (slot->bus_mode != ios->bus_mode) {
if (slot->pdata->set_bus_mode != NULL)
@@ -1269,12 +1277,15 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
* goes somehow out of sync, and the POW bit is not being set,
* which results in the while loop below getting stuck.
* Writing to the CON register twice seems to do the trick. */
+ if (ios->power_mode == MMC_POWER_ON)
+ dsor |= 1 << 11;
+ printk("MMC dsor: %x\n", dsor);
for (i = 0; i < 2; i++)
OMAP_MMC_WRITE(host, CON, dsor);
slot->saved_con = dsor;
- if (ios->power_mode == MMC_POWER_ON) {
+ if (init_stream) {
/* worst case at 400kHz, 80 cycles makes 200 microsecs */
- int usecs = 250;
+ int usecs = 512;
/* Send clock cycles, poll completion */
OMAP_MMC_WRITE(host, IE, 0);
@@ -1285,8 +1296,8 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
usecs--;
}
OMAP_MMC_WRITE(host, STAT, 1);
+ printk("time elapsed: %dus\n", 512 - usecs);
}
-
exit:
mmc_omap_release_slot(slot, clk_enabled);
}
@@ -1445,6 +1456,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
host->id = pdev->id;
+ host->power_mode = -1;
host->mem_res = res;
host->irq = irq;
@@ -1459,8 +1471,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
goto err_ioremap;
host->iclk = clk_get(&pdev->dev, "ick");
- if (IS_ERR(host->iclk))
+ if (IS_ERR(host->iclk)) {
+ ret = PTR_ERR(host->iclk);
goto err_free_mmc_host;
+ }
clk_enable(host->iclk);
host->fclk = clk_get(&pdev->dev, "fck");
@@ -1500,10 +1514,8 @@ err_free_irq:
err_free_fclk:
clk_put(host->fclk);
err_free_iclk:
- if (host->iclk != NULL) {
- clk_disable(host->iclk);
- clk_put(host->iclk);
- }
+ clk_disable(host->iclk);
+ clk_put(host->iclk);
err_free_mmc_host:
iounmap(host->virt_base);
err_ioremap:
@@ -1529,6 +1541,7 @@ static int mmc_omap_remove(struct platform_device *pdev)
host->pdata->cleanup(&pdev->dev);
mmc_omap_fclk_enable(host, 0);
+ free_irq(host->irq, host);
clk_put(host->fclk);
clk_disable(host->iclk);
clk_put(host->iclk);