|
@@ -66,6 +66,70 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
|
|
|
/* Make sure we use phases which we can enumerate with */
|
|
|
if (!IS_ERR(priv->sample_clk))
|
|
|
clk_set_phase(priv->sample_clk, priv->default_sample_phase);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set the drive phase offset based on speed mode to achieve hold times.
|
|
|
+ *
|
|
|
+ * NOTE: this is _not_ a value that is dynamically tuned and is also
|
|
|
+ * _not_ a value that will vary from board to board. It is a value
|
|
|
+ * that could vary between different SoC models if they had massively
|
|
|
+ * different output clock delays inside their dw_mmc IP block (delay_o),
|
|
|
+ * but since it's OK to overshoot a little we don't need to do complex
|
|
|
+ * calculations and can pick values that will just work for everyone.
|
|
|
+ *
|
|
|
+ * When picking values we'll stick with picking 0/90/180/270 since
|
|
|
+ * those can be made very accurately on all known Rockchip SoCs.
|
|
|
+ *
|
|
|
+ * Note that these values match values from the DesignWare Databook
|
|
|
+ * tables for the most part except for SDR12 and "ID mode". For those
|
|
|
+ * two modes the databook calculations assume a clock in of 50MHz. As
|
|
|
+ * seen above, we always use a clock in rate that is exactly the
|
|
|
+ * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided
|
|
|
+ * back out before the controller sees it).
|
|
|
+ *
|
|
|
+ * From measurement of a single device, it appears that delay_o is
|
|
|
+ * about .5 ns. Since we try to leave a bit of margin, it's expected
|
|
|
+ * that numbers here will be fine even with much larger delay_o
|
|
|
+ * (the 1.4 ns assumed by the DesignWare Databook would result in the
|
|
|
+ * same results, for instance).
|
|
|
+ */
|
|
|
+ if (!IS_ERR(priv->drv_clk)) {
|
|
|
+ int phase;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * In almost all cases a 90 degree phase offset will provide
|
|
|
+ * sufficient hold times across all valid input clock rates
|
|
|
+ * assuming delay_o is not absurd for a given SoC. We'll use
|
|
|
+ * that as a default.
|
|
|
+ */
|
|
|
+ phase = 90;
|
|
|
+
|
|
|
+ switch (ios->timing) {
|
|
|
+ case MMC_TIMING_MMC_DDR52:
|
|
|
+ /*
|
|
|
+ * Since clock in rate with MMC_DDR52 is doubled when
|
|
|
+ * bus width is 8 we need to double the phase offset
|
|
|
+ * to get the same timings.
|
|
|
+ */
|
|
|
+ if (ios->bus_width == MMC_BUS_WIDTH_8)
|
|
|
+ phase = 180;
|
|
|
+ break;
|
|
|
+ case MMC_TIMING_UHS_SDR104:
|
|
|
+ case MMC_TIMING_MMC_HS200:
|
|
|
+ /*
|
|
|
+ * In the case of 150 MHz clock (typical max for
|
|
|
+ * Rockchip SoCs), 90 degree offset will add a delay
|
|
|
+ * of 1.67 ns. That will meet min hold time of .8 ns
|
|
|
+ * as long as clock output delay is < .87 ns. On
|
|
|
+ * SoCs measured this seems to be OK, but it doesn't
|
|
|
+ * hurt to give margin here, so we use 180.
|
|
|
+ */
|
|
|
+ phase = 180;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ clk_set_phase(priv->drv_clk, phase);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#define NUM_PHASES 360
|
|
@@ -233,10 +297,10 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
|
|
|
|
|
|
/* Common capabilities of RK3288 SoC */
|
|
|
static unsigned long dw_mci_rk3288_dwmmc_caps[4] = {
|
|
|
- MMC_CAP_ERASE,
|
|
|
- MMC_CAP_ERASE,
|
|
|
- MMC_CAP_ERASE,
|
|
|
- MMC_CAP_ERASE,
|
|
|
+ MMC_CAP_ERASE | MMC_CAP_CMD23,
|
|
|
+ MMC_CAP_ERASE | MMC_CAP_CMD23,
|
|
|
+ MMC_CAP_ERASE | MMC_CAP_CMD23,
|
|
|
+ MMC_CAP_ERASE | MMC_CAP_CMD23,
|
|
|
};
|
|
|
|
|
|
static const struct dw_mci_drv_data rk2928_drv_data = {
|