|
@@ -388,3 +388,106 @@ static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply)
|
|
|
if (div > child_div)
|
|
|
div = child_div;
|
|
|
cpusel = (div > 1) ? (fls(div) - 2) : 0;
|
|
|
+ control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control);
|
|
|
+ actual_rate = parent_rate / (1 << (cpusel + 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_debug("clk %s: new rate %lu (actual rate %lu)\n",
|
|
|
+ clk->name, rate, actual_rate);
|
|
|
+
|
|
|
+ if (apply)
|
|
|
+ pm_writel(CKSEL, control);
|
|
|
+
|
|
|
+ return actual_rate;
|
|
|
+}
|
|
|
+
|
|
|
+static void hsb_clk_mode(struct clk *clk, int enabled)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ u32 mask;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&pm_lock, flags);
|
|
|
+ mask = pm_readl(HSB_MASK);
|
|
|
+ if (enabled)
|
|
|
+ mask |= 1 << clk->index;
|
|
|
+ else
|
|
|
+ mask &= ~(1 << clk->index);
|
|
|
+ pm_writel(HSB_MASK, mask);
|
|
|
+ spin_unlock_irqrestore(&pm_lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned long hsb_clk_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ unsigned long cksel, shift = 0;
|
|
|
+
|
|
|
+ cksel = pm_readl(CKSEL);
|
|
|
+ if (cksel & PM_BIT(HSBDIV))
|
|
|
+ shift = PM_BFEXT(HSBSEL, cksel) + 1;
|
|
|
+
|
|
|
+ return bus_clk_get_rate(clk, shift);
|
|
|
+}
|
|
|
+
|
|
|
+void pba_clk_mode(struct clk *clk, int enabled)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ u32 mask;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&pm_lock, flags);
|
|
|
+ mask = pm_readl(PBA_MASK);
|
|
|
+ if (enabled)
|
|
|
+ mask |= 1 << clk->index;
|
|
|
+ else
|
|
|
+ mask &= ~(1 << clk->index);
|
|
|
+ pm_writel(PBA_MASK, mask);
|
|
|
+ spin_unlock_irqrestore(&pm_lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+unsigned long pba_clk_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ unsigned long cksel, shift = 0;
|
|
|
+
|
|
|
+ cksel = pm_readl(CKSEL);
|
|
|
+ if (cksel & PM_BIT(PBADIV))
|
|
|
+ shift = PM_BFEXT(PBASEL, cksel) + 1;
|
|
|
+
|
|
|
+ return bus_clk_get_rate(clk, shift);
|
|
|
+}
|
|
|
+
|
|
|
+static void pbb_clk_mode(struct clk *clk, int enabled)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ u32 mask;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&pm_lock, flags);
|
|
|
+ mask = pm_readl(PBB_MASK);
|
|
|
+ if (enabled)
|
|
|
+ mask |= 1 << clk->index;
|
|
|
+ else
|
|
|
+ mask &= ~(1 << clk->index);
|
|
|
+ pm_writel(PBB_MASK, mask);
|
|
|
+ spin_unlock_irqrestore(&pm_lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned long pbb_clk_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ unsigned long cksel, shift = 0;
|
|
|
+
|
|
|
+ cksel = pm_readl(CKSEL);
|
|
|
+ if (cksel & PM_BIT(PBBDIV))
|
|
|
+ shift = PM_BFEXT(PBBSEL, cksel) + 1;
|
|
|
+
|
|
|
+ return bus_clk_get_rate(clk, shift);
|
|
|
+}
|
|
|
+
|
|
|
+static struct clk cpu_clk = {
|
|
|
+ .name = "cpu",
|
|
|
+ .get_rate = cpu_clk_get_rate,
|
|
|
+ .set_rate = cpu_clk_set_rate,
|
|
|
+ .users = 1,
|
|
|
+};
|
|
|
+static struct clk hsb_clk = {
|
|
|
+ .name = "hsb",
|
|
|
+ .parent = &cpu_clk,
|
|
|
+ .get_rate = hsb_clk_get_rate,
|
|
|
+};
|
|
|
+static struct clk pba_clk = {
|