/* * Keep phyctrl_pdb and phyctrl_endll low to allow * initialization of CALIO state M/C DFFs
*/
ret = regmap_update_bits(priv->syscfg, EMMC_PHYCTRL1_REG, PDB_MASK,
PDB_SHIFT(0)); if (ret) {
dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret); return ret;
}
/* Already finish power_off above */ if (!on_off) return 0;
/* * According to the user manual, calpad calibration * cycle takes more than 2us without the minimal recommended * value, so we may need a little margin here
*/
udelay(5);
ret = regmap_update_bits(priv->syscfg, EMMC_PHYCTRL1_REG, PDB_MASK,
PDB_SHIFT(1)); if (ret) {
dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret); return ret;
}
/* * According to the user manual, it asks driver to wait 5us for * calpad busy trimming. However it is documented that this value is * PVT(A.K.A process,voltage and temperature) relevant, so some * failure cases are found which indicates we should be more tolerant * to calpad busy trimming.
*/
ret = regmap_read_poll_timeout(priv->syscfg, EMMC_PHYSTAT_REG,
caldone, IS_CALDONE(caldone),
0, 50); if (ret) {
dev_err(&phy->dev, "caldone failed, ret=%d\n", ret); return ret;
}
/* Set the frequency of the DLL operation */
ret = regmap_update_bits(priv->syscfg, EMMC_PHYCTRL2_REG, FRQSEL_MASK,
FRQSEL_SHIFT(freqsel)); if (ret) {
dev_err(&phy->dev, "set the frequency of dll failed:%d\n", ret); return ret;
}
/* Turn on the DLL */
ret = regmap_update_bits(priv->syscfg, EMMC_PHYCTRL1_REG, ENDLL_MASK,
ENDLL_SHIFT(1)); if (ret) {
dev_err(&phy->dev, "turn on the dll failed: %d\n", ret); return ret;
}
/* * After enabling analog DLL circuits docs say that we need 10.2 us if * our source clock is at 50 MHz and that lock time scales linearly * with clock speed. If we are powering on the PHY and the card clock * is super slow (like 100 kHZ) this could take as long as 5.1 ms as * per the math: 10.2 us * (50000000 Hz / 100000 Hz) => 5.1 ms * Hopefully we won't be running at 100 kHz, but we should still make * sure we wait long enough. * * NOTE: There appear to be corner cases where the DLL seems to take * extra long to lock for reasons that aren't understood. In some * extreme cases we've seen it take up to over 10ms (!). We'll be * generous and give it 50ms.
*/
ret = regmap_read_poll_timeout(priv->syscfg,
EMMC_PHYSTAT_REG,
dllrdy, IS_DLLRDY(dllrdy),
0, 50 * USEC_PER_MSEC); if (ret) {
dev_err(&phy->dev, "dllrdy failed. ret=%d\n", ret); return ret;
}
/* * We purposely get the clock here and not in probe to avoid the * circular dependency problem. We expect: * - PHY driver to probe * - SDHCI driver to start probe * - SDHCI driver to register it's clock * - SDHCI driver to get the PHY * - SDHCI driver to init the PHY * * The clock is optional, so upon any error just return it like * any other error to user. *
*/
priv->emmcclk = clk_get_optional(&phy->dev, "emmcclk"); if (IS_ERR(priv->emmcclk)) {
dev_err(&phy->dev, "ERROR: getting emmcclk\n"); return PTR_ERR(priv->emmcclk);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.