module_param(sd_slow_ratio, int, 0644);
/*
+ * Post-power SD clock rate
+ *
+ * you can override this on kernel commandline using
+ *
+ * glamo_mci.sd_post_power_clock=1000000
+ *
+ * for example
+ *
+ * After changing power to card, clock is held at this rate until first bulk
+ * transfer completes
+ */
+
+static int sd_post_power_clock = 1000000;
+module_param(sd_post_power_clock, int, 0644);
+
+
+/*
* SD Signal drive strength
*
* you can override this on kernel commandline using
writew(readw(glamo_mci_def_pdata.pglamo->base +
GLAMO_REG_CLOCK_GEN5_1) & (~GLAMO_CLOCK_GEN51_EN_DIV_TCLK),
glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
- } else {
- /* set the nearest prescaler factor
- *
- * register shared with SCLK divisor -- no chance of race because
- * we don't use sensor interface
- */
- writew_dly((readw(glamo_mci_def_pdata.pglamo->base +
- GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
- glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
- /* enable clock to divider input */
- writew_dly(readw(glamo_mci_def_pdata.pglamo->base +
- GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
- glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
+
+ goto done;
}
+ if (host->force_slow_during_powerup)
+ div = host->clk_rate / sd_post_power_clock;
+ else
+ if (host->pdata->glamo_mci_use_slow)
+ if ((host->pdata->glamo_mci_use_slow)())
+ div = div * sd_slow_ratio;
+
+ if (div > 255)
+ div = 255;
+
+ /*
+ * set the nearest prescaler factor
+ *
+ * register shared with SCLK divisor -- no chance of race because
+ * we don't use sensor interface
+ */
+ writew_dly((readw(glamo_mci_def_pdata.pglamo->base +
+ GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
+ /* enable clock to divider input */
+ writew_dly(readw(glamo_mci_def_pdata.pglamo->base +
+ GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
+
+done:
spin_unlock_irqrestore(&clock_lock, flags);
}
if (division)
*division = 0xff;
- if (!sd_idleclk)
+ if (!sd_idleclk && !host->force_slow_during_powerup)
/* clock off */
__glamo_mci_fix_card_div(host, -1);
}
goto done;
}
+ /* disable the initial slow start after first bulk transfer */
+ if (host->force_slow_during_powerup)
+ host->force_slow_during_powerup--;
+
if (host->pio_active == XFER_READ)
do_pio_read(host);
host->cmd_is_stop = 0;
}
- if (!sd_idleclk)
+ if (!sd_idleclk && !host->force_slow_during_powerup)
/* clock off */
__glamo_mci_fix_card_div(host, -1);
{
u8 u8a[6];
u16 fire = 0;
- u16 timeout = 0xfff; /* max glamo MMC timeout, in units of 16 clocks */
/* if we can't do it, reject as busy */
if (!readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1) &
fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
break;
}
- /* enforce timeout, clipping at default 65520 clocks if larger */
- if (cmd->data)
- /* so long as there is one... */
- if (cmd->data->timeout_clks &&
- /* ... and it is not longer than we can handle */
- (cmd->data->timeout_clks <= 0xffff))
- timeout = cmd->data->timeout_clks >> 4; /* / 16 clks */
- writew(timeout, host->base + GLAMO_REG_MMC_TIMEOUT);
+ /* always largest timeout */
+ writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
/* Generate interrupt on txfer */
writew_dly((readw_dly(host->base + GLAMO_REG_MMC_BASIC) & 0x3e) |
/* resume requested clock rate
* scale it down by sd_slow_ratio if platform requests it
*/
- if (host->pdata->glamo_mci_use_slow)
- if ((host->pdata->glamo_mci_use_slow)())
- __glamo_mci_fix_card_div(host, host->clk_div *
- sd_slow_ratio);
- else
- __glamo_mci_fix_card_div(host, host->clk_div);
- else
- __glamo_mci_fix_card_div(host, host->clk_div);
+ __glamo_mci_fix_card_div(host, host->clk_div);
if (glamo_mci_send_command(host, cmd))
goto bail;
goto done;
if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
goto done;
+
/*
* Otherwise can can use the interrupt as async completion --
* if there is read data coming, or we wait for write data to complete,
host->mrq = NULL;
mmc_request_done(host->mmc, cmd->mrq);
bail:
- if (!sd_idleclk)
+ if (!sd_idleclk && !host->force_slow_during_powerup)
/* stop the clock to card */
__glamo_mci_fix_card_div(host, -1);
}
switch(ios->power_mode) {
case MMC_POWER_ON:
case MMC_POWER_UP:
+ /*
+ * we should use very slow clock until first bulk
+ * transfer completes OK
+ */
+ host->force_slow_during_powerup = 1;
+
if (host->vdd_current != ios->vdd) {
host->pdata->glamo_set_mci_power(ios->power_mode,
ios->vdd);
default:
if (host->power_mode_current == MMC_POWER_OFF)
break;
+ /* never want clocking with dead card */
+ __glamo_mci_fix_card_div(host, -1);
+
glamo_engine_disable(glamo_mci_def_pdata.pglamo,
GLAMO_ENGINE_MMC);
host->pdata->glamo_set_mci_power(MMC_POWER_OFF, 0);
if (powering)
msleep(1);
- if (!sd_idleclk)
+ if (!sd_idleclk && !host->force_slow_during_powerup)
/* stop the clock to card, because we are idle until transfer */
__glamo_mci_fix_card_div(host, -1);
* make sure the clock was running during suspend and consequently
* resume
*/
- if (host->pdata->glamo_mci_use_slow)
- if ((host->pdata->glamo_mci_use_slow)())
- __glamo_mci_fix_card_div(host, host->clk_div *
- sd_slow_ratio);
- else
- __glamo_mci_fix_card_div(host, host->clk_div);
- else
- __glamo_mci_fix_card_div(host, host->clk_div);
+ __glamo_mci_fix_card_div(host, host->clk_div);
/* we are going to do more commands to override this in
* mmc_suspend_host(), so we need to change sd_idleclk for the