|
@@ -217,3 +217,114 @@ static int pllc2_enable(struct clk *clk)
|
|
|
|
|
|
pr_err("%s(): timeout!\n", __func__);
|
|
pr_err("%s(): timeout!\n", __func__);
|
|
|
|
|
|
|
|
+ return -ETIMEDOUT;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pllc2_disable(struct clk *clk)
|
|
|
|
+{
|
|
|
|
+ __raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pllc2_set_rate(struct clk *clk, unsigned long rate)
|
|
|
|
+{
|
|
|
|
+ unsigned long value;
|
|
|
|
+ int idx;
|
|
|
|
+
|
|
|
|
+ idx = clk_rate_table_find(clk, clk->freq_table, rate);
|
|
|
|
+ if (idx < 0)
|
|
|
|
+ return idx;
|
|
|
|
+
|
|
|
|
+ if (rate == clk->parent->rate)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ value = __raw_readl(PLLC2CR) & ~(0x3f << 24);
|
|
|
|
+
|
|
|
|
+ __raw_writel(value | ((idx + 19) << 24), PLLC2CR);
|
|
|
|
+
|
|
|
|
+ clk->rate = clk->freq_table[idx].frequency;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pllc2_set_parent(struct clk *clk, struct clk *parent)
|
|
|
|
+{
|
|
|
|
+ u32 value;
|
|
|
|
+ int ret, i;
|
|
|
|
+
|
|
|
|
+ if (!clk->parent_table || !clk->parent_num)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ /* Search the parent */
|
|
|
|
+ for (i = 0; i < clk->parent_num; i++)
|
|
|
|
+ if (clk->parent_table[i] == parent)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ if (i == clk->parent_num)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ ret = clk_reparent(clk, parent);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ value = __raw_readl(PLLC2CR) & ~(3 << 6);
|
|
|
|
+
|
|
|
|
+ __raw_writel(value | (i << 6), PLLC2CR);
|
|
|
|
+
|
|
|
|
+ /* Rebiuld the frequency table */
|
|
|
|
+ pllc2_table_rebuild(clk);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct sh_clk_ops pllc2_clk_ops = {
|
|
|
|
+ .recalc = pllc2_recalc,
|
|
|
|
+ .round_rate = pllc2_round_rate,
|
|
|
|
+ .set_rate = pllc2_set_rate,
|
|
|
|
+ .enable = pllc2_enable,
|
|
|
|
+ .disable = pllc2_disable,
|
|
|
|
+ .set_parent = pllc2_set_parent,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct clk sh7372_pllc2_clk = {
|
|
|
|
+ .ops = &pllc2_clk_ops,
|
|
|
|
+ .parent = &extal1_div2_clk,
|
|
|
|
+ .freq_table = pllc2_freq_table,
|
|
|
|
+ .nr_freqs = ARRAY_SIZE(pllc2_freq_table) - 1,
|
|
|
|
+ .parent_table = pllc2_parent,
|
|
|
|
+ .parent_num = ARRAY_SIZE(pllc2_parent),
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* External input clock (pin name: FSIACK/FSIBCK ) */
|
|
|
|
+static struct clk fsiack_clk = {
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct clk fsibck_clk = {
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct clk *main_clks[] = {
|
|
|
|
+ &sh7372_dv_clki_clk,
|
|
|
|
+ &r_clk,
|
|
|
|
+ &sh7372_extal1_clk,
|
|
|
|
+ &sh7372_extal2_clk,
|
|
|
|
+ &sh7372_dv_clki_div2_clk,
|
|
|
|
+ &extal1_div2_clk,
|
|
|
|
+ &extal2_div2_clk,
|
|
|
|
+ &extal2_div4_clk,
|
|
|
|
+ &pllc0_clk,
|
|
|
|
+ &pllc1_clk,
|
|
|
|
+ &pllc1_div2_clk,
|
|
|
|
+ &sh7372_pllc2_clk,
|
|
|
|
+ &fsiack_clk,
|
|
|
|
+ &fsibck_clk,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void div4_kick(struct clk *clk)
|
|
|
|
+{
|
|
|
|
+ unsigned long value;
|
|
|
|
+
|
|
|
|
+ /* set KICK bit in FRQCRB to update hardware setting */
|
|
|
|
+ value = __raw_readl(FRQCRB);
|
|
|
|
+ value |= (1 << 31);
|
|
|
|
+ __raw_writel(value, FRQCRB);
|
|
|
|
+}
|
|
|
|
+
|