/* * Keep phyctrl_pdb and phyctrl_endll low to allow * initialization of CALIO state M/C DFFs
*/
ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK,
FIELD_PREP(PWR_DOWN_MASK, 0)); if (ret) {
dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret); return ret;
}
ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK,
FIELD_PREP(DLL_EN_MASK, 0)); if (ret) {
dev_err(&phy->dev, "turn off the dll failed: %d\n", ret); return ret;
}
/* Already finish power off above */ if (!on_off) return 0;
/* Check for EMMC clock rate*/ if (mhz > 175)
dev_warn(&phy->dev, "Unsupported rate: %d MHz\n", mhz);
/* * 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, PHY_CFG_0, PWR_DOWN_MASK,
FIELD_PREP(PWR_DOWN_MASK, 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, PHY_STAT,
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, PHY_CFG_2, SEL_FREQ_MASK,
FIELD_PREP(SEL_FREQ_MASK, 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, PHY_CFG_0, DLL_EN_MASK,
FIELD_PREP(DLL_EN_MASK, 1)); if (ret) {
dev_err(&phy->dev, "turn on the dll failed: %d\n", ret); return ret;
}
/* * We turned on the DLL even though the rate was 0 because we the * clock might be turned on later. ...but we can't wait for the DLL * to lock when the rate is 0 because it will never lock with no * input clock. * * Technically we should be checking the lock later when the clock * is turned on, but for now we won't.
*/ if (mhz == 0) return 0;
/* * 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 100kHz) 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, PHY_STAT,
dllrdy, IS_DLLRDY(dllrdy),
0, 50 * USEC_PER_MSEC); if (ret)
dev_err(&phy->dev, "dllrdy failed, ret=%d\n", 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");
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.