/* * OMAP3 clock data * * Copyright (C) 2007-2012 Texas Instruments, Inc. * Copyright (C) 2007-2011 Nokia Corporation * * Written by Paul Walmsley * Updated to COMMON clk data format by Rajendra Nayak * With many device clock fixes by Kevin Hilman and Jouni Högander * DPLL bypass clock support added by Roman Tereshonkov * */ /* * Virtual clocks are introduced as convenient tools. * They are sources for other clocks and not supposed * to be requested from drivers directly. */ #include #include #include #include #include #include "soc.h" #include "iomap.h" #include "clock.h" #include "clock3xxx.h" #include "clock34xx.h" #include "clock36xx.h" #include "clock3517.h" #include "cm3xxx.h" #include "cm-regbits-34xx.h" #include "prm3xxx.h" #include "prm-regbits-34xx.h" #include "control.h" /* * clocks */ #define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR /* Maximum DPLL multiplier, divider values for OMAP3 */ #define OMAP3_MAX_DPLL_MULT 2047 #define OMAP3630_MAX_JTYPE_DPLL_MULT 4095 #define OMAP3_MAX_DPLL_DIV 128 DEFINE_CLK_FIXED_RATE(dummy_apb_pclk, CLK_IS_ROOT, 0x0, 0x0); DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0); DEFINE_CLK_FIXED_RATE(omap_32k_fck, CLK_IS_ROOT, 32768, 0x0); DEFINE_CLK_FIXED_RATE(pclk_ck, CLK_IS_ROOT, 27000000, 0x0); DEFINE_CLK_FIXED_RATE(rmii_ck, CLK_IS_ROOT, 50000000, 0x0); DEFINE_CLK_FIXED_RATE(secure_32k_fck, CLK_IS_ROOT, 32768, 0x0); DEFINE_CLK_FIXED_RATE(sys_altclk, CLK_IS_ROOT, 0x0, 0x0); DEFINE_CLK_FIXED_RATE(virt_12m_ck, CLK_IS_ROOT, 12000000, 0x0); DEFINE_CLK_FIXED_RATE(virt_13m_ck, CLK_IS_ROOT, 13000000, 0x0); DEFINE_CLK_FIXED_RATE(virt_16_8m_ck, CLK_IS_ROOT, 16800000, 0x0); DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0); DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0); DEFINE_CLK_FIXED_RATE(virt_38_4m_ck, CLK_IS_ROOT, 38400000, 0x0); static const char *osc_sys_ck_parent_names[] = { "virt_12m_ck", "virt_13m_ck", "virt_19200000_ck", "virt_26000000_ck", "virt_38_4m_ck", "virt_16_8m_ck", }; DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); static struct dpll_data dpll3_dd = { .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK, .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK, .clk_bypass = &sys_ck, .clk_ref = &sys_ck, .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_mask = OMAP3430_EN_CORE_DPLL_MASK, .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT, .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT, .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT, .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK, .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, }; static struct clk dpll3_ck; static const char *dpll3_ck_parent_names[] = { "sys_ck", }; static const struct clk_ops dpll3_ck_ops = { .init = &omap2_init_clk_clkdm, .get_parent = &omap2_init_dpll_parent, .recalc_rate = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, }; static struct clk_hw_omap dpll3_ck_hw = { .hw = { .clk = &dpll3_ck, }, .ops = &clkhwops_omap3_dpll, .dpll_data = &dpll3_dd, .clkdm_name = "dpll3_clkdm", }; DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); static struct clk core_ck; static const char *core_ck_parent_names[] = { "dpll3_m2_ck", }; static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); static struct clk security_l4_ick2; static const char *security_l4_ick2_parent_names[] = { "l4_ick", }; DEFINE_STRUCT_CLK_HW_OMAP(security_l4_ick2, NULL); DEFINE_STRUCT_CLK(security_l4_ick2, security_l4_ick2_parent_names, core_ck_ops); static struct clk aes1_ick; static const char *aes1_ick_parent_names[] = { "security_l4_ick2", }; static const struct clk_ops aes1_ick_ops = { .enable = &omap2_dflt_clk_enable, .disable = &omap2_dflt_clk_disable, .is_enabled = &omap2_dflt_clk_is_enabled, }; static struct clk_hw_omap aes1_ick_hw = { .hw = { .clk = &aes1_ick, }, .ops = &clkhwops_iclk_wait, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_AES1_SHIFT, }; DEFINE_STRUCT_CLK(aes1_ick, aes1_ick_parent_names, aes1_ick_ops); static struct clk core_l4_ick; static const struct clk_ops core_l4_ick_ops = { .init = &omap2_init_clk_clkdm, }; DEFINE_STRUCT_CLK_HW_OMAP(core_l4_ick, "core_l4_clkdm"); DEFINE_STRUCT_CLK(core_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops); static struct clk aes2_ick; static const char *aes2_ick_parent_names[] = { "core_l4_ick", }; static const struct clk_ops aes2_ick_ops = { .init = &omap2_init_clk_clkdm, .enable = &omap2_dflt_clk_enable, .disable = &omap2_dflt_clk_disable, .is_enabled = &omap2_dflt_clk_is_enabled, }; static struct clk_hw_omap aes2_ick_hw = { .hw = { .clk = &aes2_ick, }, .ops = &clkhwops_iclk_wait, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_AES2_SHIFT, .clkdm_name = "core_l4_clkdm", }; DEFINE_STRUCT_CLK(aes2_ick, aes2_ick_parent_names, aes2_ick_ops); static struct clk dpll1_fck; static struct dpll_data dpll1_dd = { .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK, .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK, .clk_bypass = &dpll1_fck, .clk_ref = &sys_ck, .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL), .enable_mask = OMAP3430_EN_MPU_DPLL_MASK, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT, .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT, .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT, .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL), .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK, .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, }; static struct clk dpll1_ck; static const struct clk_ops dpll1_ck_ops = { .init = &omap2_init_clk_clkdm, .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, .get_parent = &omap2_init_dpll_parent, .recalc_rate = &omap3_dpll_recalc, .set_rate = &omap3_noncore_dpll_set_rate, .round_rate = &omap2_dpll_round_rate, }; static struct clk_hw_omap dpll1_ck_hw = { .hw = { .clk = &dpll1_ck, }, .ops = &clkhwops_omap3_dpll, .dpll_data = &dpll1_dd, .clkdm_name = "dpll1_clkdm", }; DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1); DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);