static int cpu_op_nr;
static struct cpu_op *cpu_op_tbl;
static struct clk *pll2_400;
+static struct clk *pll2_200;
static struct clk *cpu_clk;
static unsigned int org_ldo;
static struct clk *pll3;
+static struct clk *pll2;
+static struct clk *periph_clk;
+static struct clk *osc;
static struct delayed_work low_bus_freq_handler;
+extern void update_usecount(struct clk *clk, bool flag);
+static inline void update_periph_clk_parent(struct clk *new_parent)
+{
+ update_usecount(periph_clk->parent, false);
+
+ periph_clk->parent = new_parent;
+
+ update_usecount(periph_clk->parent, true);
+}
static void reduce_bus_freq_handler(struct work_struct *work)
{
unsigned long reg;
/* Need to ensure that PLL2_PFD_400M is kept ON. */
clk_enable(pll2_400);
update_ddr_freq(50000000);
+ /* Make sure periph clk's parent also got updated */
+ update_periph_clk_parent(pll2_200);
+
audio_bus_freq_mode = 1;
low_bus_freq_mode = 0;
} else {
update_ddr_freq(24000000);
+ /* Make sure periph clk's parent also got updated */
+ update_periph_clk_parent(osc);
if (audio_bus_freq_mode)
clk_disable(pll2_400);
low_bus_freq_mode = 1;
}
clk_enable(pll3);
+
/* Enable the PU LDO */
if (cpu_is_mx6q() && low_bus_freq_mode) {
__raw_writel(org_ldo, ANADIG_REG_CORE);
if (high_bus_freq) {
update_ddr_freq(ddr_normal_rate);
+ /* Make sure periph clk's parent also got updated */
+ update_periph_clk_parent(pll2);
if (med_bus_freq_mode)
clk_disable(pll2_400);
high_bus_freq_mode = 1;
} else {
clk_enable(pll2_400);
update_ddr_freq(ddr_med_rate);
+ /* Make sure periph clk's parent also got updated */
+ update_periph_clk_parent(pll2_400);
high_bus_freq_mode = 0;
med_bus_freq_mode = 1;
}
return PTR_ERR(pll2_400);
}
+ pll2_200 = clk_get(NULL, "pll2_200M");
+ if (IS_ERR(pll2_400)) {
+ printk(KERN_DEBUG "%s: failed to get pll2_200M\n",
+ __func__);
+ return PTR_ERR(pll2_200);
+ }
+
+ pll2 = clk_get(NULL, "pll2");
+ if (IS_ERR(pll2_400)) {
+ printk(KERN_DEBUG "%s: failed to get pll2\n",
+ __func__);
+ return PTR_ERR(pll2);
+ }
+
cpu_clk = clk_get(NULL, "cpu_clk");
if (IS_ERR(cpu_clk)) {
printk(KERN_DEBUG "%s: failed to get cpu_clk\n",
if (IS_ERR(pll3)) {
printk(KERN_DEBUG "%s: failed to get pll3\n",
__func__);
- return PTR_ERR(cpu_clk);
+ return PTR_ERR(pll3);
+ }
+
+ periph_clk = clk_get(NULL, "periph_clk");
+ if (IS_ERR(periph_clk)) {
+ printk(KERN_DEBUG "%s: failed to get periph\n",
+ __func__);
+ return PTR_ERR(periph_clk);
+ }
+
+ osc = clk_get(NULL, "osc");
+ if (IS_ERR(osc)) {
+ printk(KERN_DEBUG "%s: failed to get osc\n",
+ __func__);
+ return PTR_ERR(osc);
}
err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
unsigned int reg;
void __iomem *pllbase;
+ if ((arm_needs_pll2_400) && (clk == &pll2_528_bus_main_clk))
+ return;
+
pllbase = _get_pll_base(clk);
reg = __raw_readl(pllbase);
unsigned int div;
unsigned long val;
+ /* If PLL1 is bypassed, its rate will be from OSC directly */
+ if (__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_SYS_BYPASS_MASK)
+ return clk_get_rate(clk->parent);
+
div = __raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
val = (clk_get_rate(clk->parent) * div) / 2;
return val;
/* keep correct count. */
clk_enable(&cpu_clk);
clk_enable(&periph_clk);
-
/* Disable un-necessary PFDs & PLLs */
if (pll2_pfd_400M.usecount == 0 && cpu_is_mx6q())
pll2_pfd_400M.disable(&pll2_pfd_400M);
EXPORT_SYMBOL(clk_get_usecount);
+/*!
+ * @brief Function to update the usage count for the requested clock.
+ *
+ * This function returns none.
+ *
+ * @param clk clk we want to update.
+ * @param flag Increase or decrease usecount.
+ *
+ * @return Returns none.
+ */
+void update_usecount(struct clk *clk, bool flag)
+{
+ if (!flag) {
+ if (clk_get_usecount(clk) > 1) {
+ mutex_lock(&clocks_mutex);
+ clk->usecount--;
+ mutex_unlock(&clocks_mutex);
+ } else
+ clk_disable(clk);
+ } else {
+ if (clk_get_usecount(clk) < 1)
+ clk_enable(clk);
+ else {
+ mutex_lock(&clocks_mutex);
+ clk->usecount++;
+ mutex_unlock(&clocks_mutex);
+ }
+ }
+}
+EXPORT_SYMBOL(update_usecount);
+
/* Retrieve the *current* clock rate. If the clock itself
* does not provide a special calculation routine, ask
* its parent and so on, until one is able to return