#include <asm/div64.h>
#include <asm/clkdev.h>
-#include "memory.h"
+#include <mach/sdrc.h>
#include "clock.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X | CK_242X),
/* L4 domain clocks */
CLK(NULL, "l4_ck", &l4_ck, CK_243X | CK_242X),
+ CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X | CK_242X),
/* virtual meta-group clock */
CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X),
/* general l4 interface ck, multi-parent functional clk */
* Omap24xx specific clock functions
*-------------------------------------------------------------------------*/
-/* This actually returns the rate of core_ck, not dpll_ck. */
-static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
+/**
+ * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
+ * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
+ *
+ * Returns the CORE_CLK rate. CORE_CLK can have one of three rate
+ * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
+ * (the latter is unusual). This currently should be called with
+ * struct clk *dpll_ck, which is a composite clock of dpll_ck and
+ * core_ck.
+ */
+static unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
{
- long long dpll_clk;
- u8 amult;
+ long long core_clk;
+ u32 v;
- dpll_clk = omap2_get_dpll_rate(tclk);
+ core_clk = omap2_get_dpll_rate(clk);
- amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
- amult &= OMAP24XX_CORE_CLK_SRC_MASK;
- dpll_clk *= amult;
+ v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+ v &= OMAP24XX_CORE_CLK_SRC_MASK;
+
+ if (v == CORE_CLK_SRC_32K)
+ core_clk = 32768;
+ else
+ core_clk *= v;
- return dpll_clk;
+ return core_clk;
}
static int omap2_enable_osc_ck(struct clk *clk)
}
-static void omap2_dpllcore_recalc(struct clk *clk)
+static unsigned long omap2_dpllcore_recalc(struct clk *clk)
{
- clk->rate = omap2_get_dpll_rate_24xx(clk);
+ return omap2xxx_clk_get_core_rate(clk);
}
static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
u32 bypass = 0;
struct prcm_config tmpset;
const struct dpll_data *dd;
- unsigned long flags;
- int ret = -EINVAL;
- local_irq_save(flags);
- cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
+ cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
mult &= OMAP24XX_CORE_CLK_SRC_MASK;
if ((rate == (cur_rate / 2)) && (mult == 2)) {
- omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
+ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
- omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
} else if (rate != cur_rate) {
valid_rate = omap2_dpllcore_round_rate(rate);
if (valid_rate != rate)
- goto dpll_exit;
+ return -EINVAL;
if (mult == 1)
low = curr_prcm_set->dpll_speed;
dd = clk->dpll_data;
if (!dd)
- goto dpll_exit;
+ return -EINVAL;
tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
bypass = 1;
- omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
+ /* For omap2xxx_sdrc_init_params() */
+ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
/* Force dll lock mode */
omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
bypass);
/* Errata: ret dll entry state */
- omap2_init_memory_params(omap2_dll_force_needed());
- omap2_reprogram_sdrc(done_rate, 0);
+ omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
+ omap2xxx_sdrc_reprogram(done_rate, 0);
}
- omap2_dpllcore_recalc(&dpll_ck);
- ret = 0;
-dpll_exit:
- local_irq_restore(flags);
- return(ret);
+ return 0;
}
/**
*
* Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
*/
-static void omap2_table_mpu_recalc(struct clk *clk)
+static unsigned long omap2_table_mpu_recalc(struct clk *clk)
{
- clk->rate = curr_prcm_set->mpu_speed;
+ return curr_prcm_set->mpu_speed;
}
/*
}
curr_prcm_set = prcm;
- cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
+ cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
if (prcm->dpll_speed == cur_rate / 2) {
- omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
+ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
} else if (prcm->dpll_speed == cur_rate * 2) {
- omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
} else if (prcm->dpll_speed != cur_rate) {
local_irq_save(flags);
cm_write_mod_reg(prcm->cm_clksel_mdm,
OMAP2430_MDM_MOD, CM_CLKSEL);
- /* x2 to enter init_mem */
- omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+ /* x2 to enter omap2xxx_sdrc_init_params() */
+ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
bypass);
- omap2_init_memory_params(omap2_dll_force_needed());
- omap2_reprogram_sdrc(done_rate, 0);
+ omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
+ omap2xxx_sdrc_reprogram(done_rate, 0);
local_irq_restore(flags);
}
- omap2_dpllcore_recalc(&dpll_ck);
return 0;
}
+#ifdef CONFIG_CPU_FREQ
+/*
+ * Walk PRCM rate table and fillout cpufreq freq_table
+ */
+static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)];
+
+void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
+{
+ struct prcm_config *prcm;
+ int i = 0;
+
+ for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+ if (!(prcm->flags & cpu_mask))
+ continue;
+ if (prcm->xtal_speed != sys_ck.rate)
+ continue;
+
+ /* don't put bypass rates in table */
+ if (prcm->dpll_speed == prcm->xtal_speed)
+ continue;
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = prcm->mpu_speed / 1000;
+ i++;
+ }
+
+ if (i == 0) {
+ printk(KERN_WARNING "%s: failed to initialize frequency "
+ "table\n", __func__);
+ return;
+ }
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *table = &freq_table[0];
+}
+#endif
+
static struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable,
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
+#ifdef CONFIG_CPU_FREQ
+ .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
+#endif
};
static u32 omap2_get_apll_clkin(void)
return div;
}
-static void omap2_osc_clk_recalc(struct clk *clk)
+static unsigned long omap2_osc_clk_recalc(struct clk *clk)
{
- clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
+ return omap2_get_apll_clkin() * omap2_get_sysclkdiv();
}
-static void omap2_sys_clk_recalc(struct clk *clk)
+static unsigned long omap2_sys_clk_recalc(struct clk *clk)
{
- clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
+ return clk->parent->rate / omap2_get_sysclkdiv();
}
/*
if (!mpurate)
return -EINVAL;
- if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+ if (clk_set_rate(&virt_prcm_set, mpurate))
printk(KERN_ERR "Could not find matching MPU rate\n");
recalculate_root_clocks();
clk_init(&omap2_clk_functions);
- omap2_osc_clk_recalc(&osc_ck);
+ clk_init_one(&osc_ck);
+ clk_init_one(&sys_ck);
+ osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
propagate_rate(&osc_ck);
- omap2_sys_clk_recalc(&sys_ck);
+ sys_ck.rate = omap2_sys_clk_recalc(&sys_ck);
propagate_rate(&sys_ck);
+ for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
+ clk_init_one(c->lk.clk);
+
cpu_mask = 0;
if (cpu_is_omap2420())
cpu_mask |= CK_242X;
}
/* Check the MPU rate set by bootloader */
- clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
+ clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;