#define DWMMC_MMC0_SDR_TIMING_VAL 0x03030001
#define DWMMC_MMC2_SDR_TIMING_VAL 0x03020001
+#define EXYNOS4412_FIXED_CIU_CLK_DIV 4
+
#ifdef CONFIG_DM_MMC
#include <dm.h>
DECLARE_GLOBAL_DATA_PTR;
/* Chip specific data */
struct exynos_dwmmc_variant {
u32 clksel; /* CLKSEL register offset */
+ u8 div; /* (optional) fixed clock divider value: 0..7 */
};
/* Exynos implmentation specific drver private data */
return 0;
}
-unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
+/**
+ * exynos_dwmmc_get_ciu_div - Get internal clock divider value
+ * @host: MMC controller object
+ *
+ * Returns: Divider value, in range of 1..8
+ */
+static u8 exynos_dwmmc_get_ciu_div(struct dwmci_host *host)
{
struct dwmci_exynos_priv_data *priv = exynos_dwmmc_get_priv(host);
- unsigned long sclk;
- int8_t clk_div;
- int err;
+
+ if (priv->chip->div)
+ return priv->chip->div + 1;
/*
* Since SDCLKIN is divided inside controller by the DIVRATIO
* clock value to calculate the CLKDIV value.
* as per user manual:cclk_in = SDCLKIN / (DIVRATIO + 1)
*/
- clk_div = ((dwmci_readl(host, priv->chip->clksel) >> DWMCI_DIVRATIO_BIT)
- & DWMCI_DIVRATIO_MASK) + 1;
+ return ((dwmci_readl(host, priv->chip->clksel) >> DWMCI_DIVRATIO_BIT)
+ & DWMCI_DIVRATIO_MASK) + 1;
+}
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
+{
+ unsigned long sclk;
+ u8 clk_div;
+ int err;
+
+ clk_div = exynos_dwmmc_get_ciu_div(host);
err = exynos_dwmmc_get_sclk(host, &sclk);
if (err) {
printf("DWMMC%d: failed to get clock rate (%d)\n",
return 0;
}
- /*
- * Assume to know divider value.
- * When clock unit is broken, need to set "host->div"
- */
- return sclk / clk_div / (host->div + 1);
+ return sclk / clk_div;
}
static void exynos_dwmci_board_init(struct dwmci_host *host)
return -EINVAL;
}
- /* Extract the timing info from the node */
- div = dev_read_u32_default(dev, "samsung,dw-mshc-ciu-div", 0);
+ if (priv->chip->div)
+ div = priv->chip->div;
+ else
+ div = dev_read_u32_default(dev, "samsung,dw-mshc-ciu-div", 0);
err = dev_read_u32_array(dev, "samsung,dw-mshc-sdr-timing", timing, 2);
if (err) {
printf("DWMMC%d: Can't get sdr-timings\n", host->dev_index);
host->fifo_depth = dev_read_u32_default(dev, "fifo-depth", 0);
host->bus_hz = dev_read_u32_default(dev, "bus_hz", 0);
- host->div = dev_read_u32_default(dev, "div", 0);
return 0;
}
static const struct exynos_dwmmc_variant exynos4_drv_data = {
.clksel = DWMCI_CLKSEL,
+ .div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1,
};
static const struct exynos_dwmmc_variant exynos5_drv_data = {