|
@@ -41,6 +41,36 @@ static struct clk usboh3_clk;
|
|
|
|
|
|
#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
|
|
|
|
|
|
+/* calculate best pre and post dividers to get the required divider */
|
|
|
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
|
|
|
+ u32 max_pre, u32 max_post)
|
|
|
+{
|
|
|
+ if (div >= max_pre * max_post) {
|
|
|
+ *pre = max_pre;
|
|
|
+ *post = max_post;
|
|
|
+ } else if (div >= max_pre) {
|
|
|
+ u32 min_pre, temp_pre, old_err, err;
|
|
|
+ min_pre = DIV_ROUND_UP(div, max_post);
|
|
|
+ old_err = max_pre;
|
|
|
+ for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
|
|
|
+ err = div % temp_pre;
|
|
|
+ if (err == 0) {
|
|
|
+ *pre = temp_pre;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ err = temp_pre - err;
|
|
|
+ if (err < old_err) {
|
|
|
+ old_err = err;
|
|
|
+ *pre = temp_pre;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *post = DIV_ROUND_UP(div, *pre);
|
|
|
+ } else {
|
|
|
+ *pre = div;
|
|
|
+ *post = 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
|
|
|
{
|
|
|
u32 reg = __raw_readl(clk->enable_reg);
|
|
@@ -787,6 +817,20 @@ static struct clk emi_slow_clk = {
|
|
|
.secondary = s, \
|
|
|
}
|
|
|
|
|
|
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
|
|
|
+ static struct clk name = { \
|
|
|
+ .id = i, \
|
|
|
+ .enable_reg = er, \
|
|
|
+ .enable_shift = es, \
|
|
|
+ .get_rate = pfx##_get_rate, \
|
|
|
+ .set_rate = pfx##_set_rate, \
|
|
|
+ .set_parent = pfx##_set_parent, \
|
|
|
+ .enable = _clk_max_enable, \
|
|
|
+ .disable = _clk_max_disable, \
|
|
|
+ .parent = p, \
|
|
|
+ .secondary = s, \
|
|
|
+ }
|
|
|
+
|
|
|
#define CLK_GET_RATE(name, nr, bitsname) \
|
|
|
static unsigned long clk_##name##_get_rate(struct clk *clk) \
|
|
|
{ \
|
|
@@ -817,6 +861,37 @@ static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
|
|
|
return 0; \
|
|
|
}
|
|
|
|
|
|
+#define CLK_SET_RATE(name, nr, bitsname) \
|
|
|
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
|
|
|
+{ \
|
|
|
+ u32 reg, div, parent_rate; \
|
|
|
+ u32 pre = 0, post = 0; \
|
|
|
+ \
|
|
|
+ parent_rate = clk_get_rate(clk->parent); \
|
|
|
+ div = parent_rate / rate; \
|
|
|
+ \
|
|
|
+ if ((parent_rate / div) != rate) \
|
|
|
+ return -EINVAL; \
|
|
|
+ \
|
|
|
+ __calc_pre_post_dividers(div, &pre, &post, \
|
|
|
+ (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
|
|
|
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
|
|
|
+ (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
|
|
|
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
|
|
|
+ \
|
|
|
+ /* Set sdhc1 clock divider */ \
|
|
|
+ reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
|
|
|
+ ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
|
|
|
+ | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
|
|
|
+ reg |= (post - 1) << \
|
|
|
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
|
|
|
+ reg |= (pre - 1) << \
|
|
|
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
|
|
|
+ __raw_writel(reg, MXC_CCM_CSCDR##nr); \
|
|
|
+ \
|
|
|
+ return 0; \
|
|
|
+}
|
|
|
+
|
|
|
/* UART */
|
|
|
CLK_GET_RATE(uart, 1, UART)
|
|
|
CLK_SET_PARENT(uart, 1, UART)
|
|
@@ -847,6 +922,15 @@ static struct clk ecspi_main_clk = {
|
|
|
.set_parent = clk_ecspi_set_parent,
|
|
|
};
|
|
|
|
|
|
+/* eSDHC */
|
|
|
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
|
|
|
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
|
|
|
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
|
|
|
+
|
|
|
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
|
|
|
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
|
|
|
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
|
|
|
+
|
|
|
#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
|
|
|
static struct clk name = { \
|
|
|
.id = i, \
|
|
@@ -935,6 +1019,16 @@ DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
|
|
|
DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
|
|
|
NULL, NULL, &ahb_clk, NULL);
|
|
|
|
|
|
+/* eSDHC */
|
|
|
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
|
|
|
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
|
|
|
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
|
|
|
+ clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
|
|
|
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
|
|
|
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
|
|
|
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
|
|
|
+ clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
|
|
|
+
|
|
|
#define _REGISTER_CLOCK(d, n, c) \
|
|
|
{ \
|
|
|
.dev_id = d, \
|
|
@@ -968,6 +1062,8 @@ static struct clk_lookup lookups[] = {
|
|
|
_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
|
|
|
_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
|
|
|
_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
|
|
|
+ _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
|
|
|
+ _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
|
|
|
};
|
|
|
|
|
|
static void clk_tree_init(void)
|
|
@@ -1011,6 +1107,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
|
|
|
/* set the usboh3_clk parent to pll2_sw_clk */
|
|
|
clk_set_parent(&usboh3_clk, &pll2_sw_clk);
|
|
|
|
|
|
+ /* Set SDHC parents to be PLL2 */
|
|
|
+ clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
|
|
|
+ clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
|
|
|
+
|
|
|
+ /* set SDHC root clock as 166.25MHZ*/
|
|
|
+ clk_set_rate(&esdhc1_clk, 166250000);
|
|
|
+ clk_set_rate(&esdhc2_clk, 166250000);
|
|
|
+
|
|
|
/* System timer */
|
|
|
mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
|
|
|
MX51_MXC_INT_GPT);
|