};
#endif
+static const struct pll_rate_table tl1_fixed_pll_rate_table[] = {
+ PLL_FRAC_RATE(2000000000ULL, 166, 1, 1, 0, 0x3F15555),
+};
+
static struct meson_clk_pll tl1_fixed_pll = {
.m = {
.reg_off = HHI_FIX_PLL_CNTL0,
.width = 19,
},
.lock = &clk_lock,
+ .rate_table = tl1_fixed_pll_rate_table,
+ .rate_count = ARRAY_SIZE(tl1_fixed_pll_rate_table),
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
- .ops = &meson_tl1_pll_ro_ops,
+ .ops = &meson_tl1_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
+ .flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED,
},
};
},
};
+static struct clk_mux tl1_switch_clk81 = {
+ .reg = (void *)HHI_MPEG_CLK_CNTL,
+ .mask = 0x1,
+ .shift = 8,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "switch_clk81",
+ .ops = &clk_mux_ops,
+ .parent_names = (const char *[]){ "xtal", "clk81" },
+ .num_parents = 2,
+ },
+};
+
/* Everything Else (EE) domain gates */
/* HHI_GCLK_MPEG0 26 bits valid */
static MESON_GATE_TL1(tl1_ddr, HHI_GCLK_MPEG0, 0);
[CLKID_DSU_PRE_PARENT0] = &tl1_dsu_pre0_clk.hw,
[CLKID_DSU_PRE_CLK] = &tl1_dsu_pre_clk.hw,
[CLKID_DSU_CLK] = &tl1_dsu_clk.hw,
+ [CLKID_SWITCH_CLK81] = &tl1_switch_clk81.hw,
};
/* Convenience tables to populate base addresses in .probe */
tl1_dsu_clk.reg = clk_base
+ (unsigned long)tl1_dsu_clk.reg;
+ tl1_switch_clk81.reg = clk_base
+ + (unsigned long)tl1_switch_clk81.reg;
+
/* Populate base address for gates */
for (i = 0; i < ARRAY_SIZE(tl1_clk_gates); i++)
tl1_clk_gates[i]->reg = clk_base +
WARN_ON(IS_ERR(clks[clkid]));
}
}
+ clks[CLKID_SWITCH_CLK81] = clk_register(NULL, &tl1_switch_clk81.hw);
+ WARN_ON(IS_ERR(clks[CLKID_SWITCH_CLK81]));
meson_tl1_sdemmc_init();
meson_tl1_media_init();
#define TL1_SYS_PLL_CNTL4 0x88770290
#define TL1_SYS_PLL_CNTL5 0x39272000
+#define TL1_FIXED_PLL_CNTL0 0xD00104A6
+#define TL1_FIXED_PLL_CNTL1 0x3F15555
+#define TL1_FIXED_PLL_CNTL2 0x00000000
+#define TL1_FIXED_PLL_CNTL3 0x6A285C60
+#define TL1_FIXED_PLL_CNTL4 0x65771290
+#define TL1_FIXED_PLL_CNTL5 0x39272000
+#define TL1_FIXED_PLL_CNTL6 0x56540000
+#define TL1_FIXED_PLL_TST 0xA000004F
#define TL1_GP0_PLL_CNTL1 0x00000000
#define TL1_GP0_PLL_CNTL2 0x00000000
for (i = 0; i < pll->rate_count; i++) {
if (rate <= rate_table[i].rate) {
ret_rate = rate_table[i].rate;
- if (!strcmp(clk_hw_get_name(hw), "sys_pll"))
+ if (!strcmp(clk_hw_get_name(hw), "sys_pll")
+ || !strcmp(clk_hw_get_name(hw), "fixed_pll"))
do_div(ret_rate, 1000);
+
return ret_rate;
}
}
/* else return the smallest value */
ret_rate = rate_table[0].rate;
- if (!strcmp(clk_hw_get_name(hw), "sys_pll"))
+ if (!strcmp(clk_hw_get_name(hw), "sys_pll")
+ || !strcmp(clk_hw_get_name(hw), "fixed_pll"))
do_div(ret_rate, 1000);
+
return ret_rate;
}
if (parent_rate == 0 || rate == 0)
return -EINVAL;
- if (!strcmp(clk_hw_get_name(hw), "sys_pll"))
+ if (!strcmp(clk_hw_get_name(hw), "sys_pll")
+ || !strcmp(clk_hw_get_name(hw), "fixed_pll"))
rate *= 1000;
old_rate = rate;
cntlbase + (unsigned long)(0*4));
writel(TM2_PCIE_PLL_CNTL2_,
cntlbase + (unsigned long)(7*4));
+ } else if (!strcmp(clk_hw_get_name(hw), "fixed_pll")) {
+ writel((readl(cntlbase) | MESON_PLL_RESET)
+ & (~MESON_PLL_ENABLE), cntlbase);
+
+ udelay(100);
+ writel(TL1_FIXED_PLL_CNTL1,
+ cntlbase + (unsigned long)(1*4));
+ writel(TL1_FIXED_PLL_CNTL2,
+ cntlbase + (unsigned long)(2*4));
+ writel(TL1_FIXED_PLL_CNTL3,
+ cntlbase + (unsigned long)(3*4));
+ writel(TL1_FIXED_PLL_CNTL4,
+ cntlbase + (unsigned long)(4*4));
+ writel(TL1_FIXED_PLL_CNTL5,
+ cntlbase + (unsigned long)(5*4));
+ writel(TL1_FIXED_PLL_CNTL6,
+ cntlbase + (unsigned long)(6*4));
+ udelay(10);
} else {
pr_err("%s: %s pll not found!!!\n",
__func__, clk_hw_get_name(hw));
return -EINVAL;
}
- /* when set rate for pcie pll, do not set M/N/OD/frac registers bit */
- if (strcmp(clk_hw_get_name(hw), "pcie_pll")) {
reg = readl(pll->base + p->reg_off);
tmp = rate_set->n;
reg = PARM_SET(p->width, p->shift, reg, tmp);
writel(reg, pll->base + p->reg_off);
}
- }
p = &pll->n;
/* PLL reset */
if (!strcmp(clk_hw_get_name(hw), "gp0_pll")
|| !strcmp(clk_hw_get_name(hw), "gp1_pll")
|| !strcmp(clk_hw_get_name(hw), "hifi_pll")
- || !strcmp(clk_hw_get_name(hw), "sys_pll")) {
+ || !strcmp(clk_hw_get_name(hw), "sys_pll")
+ || !strcmp(clk_hw_get_name(hw), "fixed_pll")) {
void *cntlbase = pll->base + p->reg_off;
if (readl(cntlbase + (unsigned long)(6*4))
first_set = 0;
}
-
parent = clk_hw_get_parent(hw);
/*First init, just set minimal rate.*/