|
@@ -135,3 +135,85 @@ static struct sh_clk_ops pllc01_clk_ops = {
|
|
|
static struct clk pllc0_clk = {
|
|
|
.ops = &pllc01_clk_ops,
|
|
|
.flags = CLK_ENABLE_ON_INIT,
|
|
|
+ .parent = &extal1_div2_clk,
|
|
|
+ .enable_reg = (void __iomem *)FRQCRC,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk pllc1_clk = {
|
|
|
+ .ops = &pllc01_clk_ops,
|
|
|
+ .flags = CLK_ENABLE_ON_INIT,
|
|
|
+ .parent = &extal1_div2_clk,
|
|
|
+ .enable_reg = (void __iomem *)FRQCRA,
|
|
|
+};
|
|
|
+
|
|
|
+/* Divide PLLC1 by two */
|
|
|
+static struct clk pllc1_div2_clk = {
|
|
|
+ .ops = &div2_clk_ops,
|
|
|
+ .parent = &pllc1_clk,
|
|
|
+};
|
|
|
+
|
|
|
+/* PLLC2 */
|
|
|
+
|
|
|
+/* Indices are important - they are the actual src selecting values */
|
|
|
+static struct clk *pllc2_parent[] = {
|
|
|
+ [0] = &extal1_div2_clk,
|
|
|
+ [1] = &extal2_div2_clk,
|
|
|
+ [2] = &sh7372_dv_clki_div2_clk,
|
|
|
+};
|
|
|
+
|
|
|
+/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */
|
|
|
+static struct cpufreq_frequency_table pllc2_freq_table[29];
|
|
|
+
|
|
|
+static void pllc2_table_rebuild(struct clk *clk)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* Initialise PLLC2 frequency table */
|
|
|
+ for (i = 0; i < ARRAY_SIZE(pllc2_freq_table) - 2; i++) {
|
|
|
+ pllc2_freq_table[i].frequency = clk->parent->rate * (i + 20) * 2;
|
|
|
+ pllc2_freq_table[i].index = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* This is a special entry - switching PLL off makes it a repeater */
|
|
|
+ pllc2_freq_table[i].frequency = clk->parent->rate;
|
|
|
+ pllc2_freq_table[i].index = i;
|
|
|
+
|
|
|
+ pllc2_freq_table[++i].frequency = CPUFREQ_TABLE_END;
|
|
|
+ pllc2_freq_table[i].index = i;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned long pllc2_recalc(struct clk *clk)
|
|
|
+{
|
|
|
+ unsigned long mult = 1;
|
|
|
+
|
|
|
+ pllc2_table_rebuild(clk);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the PLL is off, mult == 1, clk->rate will be updated in
|
|
|
+ * pllc2_enable().
|
|
|
+ */
|
|
|
+ if (__raw_readl(PLLC2CR) & (1 << 31))
|
|
|
+ mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
|
|
|
+
|
|
|
+ return clk->parent->rate * mult;
|
|
|
+}
|
|
|
+
|
|
|
+static long pllc2_round_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ return clk_rate_table_round(clk, clk->freq_table, rate);
|
|
|
+}
|
|
|
+
|
|
|
+static int pllc2_enable(struct clk *clk)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ __raw_writel(__raw_readl(PLLC2CR) | 0x80000000, PLLC2CR);
|
|
|
+
|
|
|
+ for (i = 0; i < 100; i++)
|
|
|
+ if (__raw_readl(PLLC2CR) & 0x80000000) {
|
|
|
+ clk->rate = pllc2_recalc(clk);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_err("%s(): timeout!\n", __func__);
|
|
|
+
|