* Ladislav.Michl@xxxxxxxxx <Ladislav.Michl@xxxxxxxxx> [091021 12:15]: > Hmm, it seems noone is going to fix it for me, so let's move on... > > On Mon, Jan 12, 2009 at 12:42:43PM +0200, Tony Lindgren wrote: > > Hi, > > > > * Ladislav Michl <ladis@xxxxxxxxxxxxxx> [090112 11:19]: > > > Last time I used MMC card with linux-2.6.15-omap2 and it worked pretty well on > > > my custom 5910 based board. Current git nor linux-2.6.22-omap1 (currently used > > > for production) doesn't work at all. Inspecting diff between 2.6.15-omap2 and > > > 2.6.22-omap1 showed that > > > --- a/drivers/mmc/host/omap.c 2009-01-12 09:32:23.000000000 +0100 > > > +++ b/drivers/mmc/host/omap.c 2009-01-12 09:46:26.000000000 +0100 > > > @@ -974,7 +974,7 @@ > > > * Writing to the CON register twice seems to do the trick. */ > > > for (i = 0; i < 2; i++) > > > OMAP_MMC_WRITE(host, CON, dsor); > > > - if (ios->power_mode == MMC_POWER_ON) { > > > + if (ios->power_mode == MMC_POWER_UP) { > > > /* Send clock cycles, poll completion */ > > > OMAP_MMC_WRITE(host, IE, 0); > > > OMAP_MMC_WRITE(host, STAT, 0xffff); > > > did the trick. > > > > > > With above patch applied to 2.6.22-omap1 I got > > > # modprobe omap > > > mmci-omap mmci-omap.1: command timeout, CMD 8 > > > mmcblk0: mmc0:0001 127104KiB > > > mmcblk0: p1 > > > while there is no command timeout with 2.6.15-omap2, but at least it works. > > > > OK, well at least that's a good start on figuring out what has broken > > it. It does not seem like the right fix though as the MMC_POWER_UP > > should just power up the slot, and clocks should not get turned on > > until in MMC_POWER_ON. > > > > > Doing the same modification in current git doesn't help. Moreover removing > > > omap.ko and inserting again behaves differently than inserting for first > > > time: > > > # modprobe omap > > > mmci-omap mmci-omap.0: command timeout (CMD8) > > > mmci-omap mmci-omap.0: command timeout (CMD5) > > > mmci-omap mmci-omap.0: command timeout (CMD5) > > > mmci-omap mmci-omap.0: command timeout (CMD5) > > > mmci-omap mmci-omap.0: command timeout (CMD5) > > > mmci-omap mmci-omap.0: command timeout (CMD55) > > > mmci-omap mmci-omap.0: command timeout (CMD55) > > > mmci-omap mmci-omap.0: command timeout (CMD55) > > > mmci-omap mmci-omap.0: command timeout (CMD55) > > > mmc0: error -22 whilst initialising MMC card > > > # rmmod omap > > > # modprobe omap > > > mmci-omap: probe of mmci-omap.0 failed with error -16 > > > > Looks like the current git head does goto exit after MMC_POWER_UP before > > you even get to that code. > > > > > I'll happily send any requested debug informations and test any patches > > > > Can you maybe try to debug by applying your patch and commenting out > > the goto exit? > > Here is somehow working version. It seems sending init stream multiple times > is not good idea. Please note I have no clue how is MMC supposed to work > (except very basic knowledge). > > So with the patch (complete patch, see mmc driver fixes I posted earlier today) > below, output looks like: > > # modprobe omap > MMC_POWER_OFF > MMC dsor: 0 > MMC_POWER_UP > MMC_POWER_ON > MMC dsor: 878 > time elapsed: 254us > MMC_POWER_ON > MMC dsor: 878 > MMC_POWER_ON > MMC dsor: 878 > mmci-omap mmci-omap.0: command timeout (CMD8) > mmci-omap mmci-omap.0: command timeout (CMD5) > mmci-omap mmci-omap.0: command timeout (CMD5) > mmci-omap mmci-omap.0: command timeout (CMD5) > mmci-omap mmci-omap.0: command timeout (CMD5) > mmci-omap mmci-omap.0: command timeout (CMD55) > mmci-omap mmci-omap.0: command timeout (CMD55) > mmci-omap mmci-omap.0: command timeout (CMD55) > mmci-omap mmci-omap.0: command timeout (CMD55) > MMC_POWER_ON > MMC dsor: 878 > MMC_POWER_ON > MMC dsor: 878 > MMC_POWER_ON > MMC dsor: 878 > MMC_POWER_ON > MMC dsor: 878 > MMC_POWER_ON > MMC dsor: 803 > mmc0: new MMC card at address 0001 > mmcblk0: mmc0:0001 D0601 122 MiB > mmcblk0: > p1 > > Note, that "command timeout" is still there, but at least it detect card and > also note that "worst case at 400kHz, 80 cycles makes 200 microsecs" took > actually more than 200us. Good to hear. Can you please resend this too to the mmc list? Regards, Tony > diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c > index 5d773b8..0bcd6b0 100644 > --- a/drivers/mmc/host/omap.c > +++ b/drivers/mmc/host/omap.c > @@ -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); > > Hints and ideas welcome and appreciated :-) > > Thanks, > ladis -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html