The patch defines virtual nodes for VDD1 and VDD2 Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/board-3430sdp.c | 38 +++++ arch/arm/mach-omap2/clock34xx.c | 206 +++++++++++++++++++++++++----- arch/arm/mach-omap2/clock34xx.h | 29 ++++ include/asm-arm/arch-omap/board-3430sdp.h | 35 +++++ include/asm-arm/arch-omap/clock.h | 8 + 5 files changed, 287 insertions(+), 29 deletions(-) Index: linux-omap-2.6/arch/arm/mach-omap2/clock34xx.h =================================================================== --- linux-omap-2.6.orig/arch/arm/mach-omap2/clock34xx.h 2008-08-06 14:55:12.000000000 +0530 +++ linux-omap-2.6/arch/arm/mach-omap2/clock34xx.h 2008-08-07 15:07:19.000000000 +0530 @@ -36,6 +36,14 @@ static int omap3_noncore_dpll_enable(str static void omap3_noncore_dpll_disable(struct clk *clk); static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); +static void omap3_table_recalc(struct clk *clk); +static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate); +static int omap3_select_table_rate(struct clk *clk, unsigned long rate); + +extern struct vdd_prcm_config vdd1_rate_table[]; +extern struct vdd_prcm_config vdd2_rate_table[]; +extern struct vdd_prcm_config iva2_rate_table[]; + /* Maximum DPLL multiplier, divider values for OMAP3 */ #define OMAP3_MAX_DPLL_MULT 2048 @@ -3064,6 +3072,24 @@ static struct clk wdt1_fck = { .recalc = &followparent_recalc, }; +static struct clk virt_vdd1_prcm_set = { + .name = "virt_vdd1_prcm_set", + .flags = CLOCK_IN_OMAP343X | VIRTUAL_CLOCK | ALWAYS_ENABLED, + .parent = &mpu_ck, /* Indexed by mpu speed, no parent */ + .recalc = &omap3_table_recalc, /*sets are keyed on mpu rate */ + .set_rate = &omap3_select_table_rate, + .round_rate = &omap3_round_to_table_rate, +}; + +static struct clk virt_vdd2_prcm_set = { + .name = "virt_vdd2_prcm_set", + .flags = CLOCK_IN_OMAP343X | VIRTUAL_CLOCK | ALWAYS_ENABLED, + .parent = &core_ck, + .recalc = &omap3_table_recalc, + .set_rate = &omap3_select_table_rate, + .round_rate = &omap3_round_to_table_rate, +}; + static struct clk *onchip_34xx_clks[] __initdata = { &omap_32k_fck, &virt_12m_ck, @@ -3276,6 +3302,9 @@ static struct clk *onchip_34xx_clks[] __ &secure_32k_fck, &gpt12_fck, &wdt1_fck, + /* virtual group clock */ + &virt_vdd1_prcm_set, + &virt_vdd2_prcm_set, }; #endif Index: linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c =================================================================== --- linux-omap-2.6.orig/arch/arm/mach-omap2/clock34xx.c 2008-08-07 14:34:23.000000000 +0530 +++ linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c 2008-08-07 15:07:19.000000000 +0530 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,32 @@ #define MAX_DPLL_WAIT_TRIES 1000000 +struct vdd_prcm_config *curr_vdd1_prcm_set; +struct vdd_prcm_config *curr_vdd2_prcm_set; +static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk; + +#ifndef CONFIG_CPU_FREQ +static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult) +{ + unsigned long new_jiffy_l, new_jiffy_h; + + /* + * Recalculate loops_per_jiffy. We do it this way to + * avoid math overflow on 32-bit machines. Maybe we + * should make this architecture dependent? If you have + * a better way of doing this, please replace! + * + * new = old * mult / div + */ + new_jiffy_h = ref / div; + new_jiffy_l = (ref % div) / 100; + new_jiffy_h *= mult; + new_jiffy_l = new_jiffy_l * mult / div; + + return new_jiffy_h + new_jiffy_l * 100; +} +#endif + /** * omap3_dpll_recalc - recalculate DPLL rate * @clk: DPLL struct clk @@ -644,15 +671,6 @@ void omap2_clk_prepare_for_reboot(void) */ static int __init omap2_clk_arch_init(void) { - if (!mpurate) - return -EINVAL; - - /* REVISIT: not yet ready for 343x */ -#if 0 - if (omap2_select_table_rate(&virt_prcm_set, mpurate)) - printk(KERN_ERR "Could not find matching MPU rate\n"); -#endif - recalculate_root_clocks(); printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): " @@ -670,6 +688,9 @@ int __init omap2_clk_init(void) struct clk **clkp; /* u32 clkrate; */ u32 cpu_clkflg; + unsigned long mpu_speed, core_speed; + struct vdd_prcm_config *prcm_vdd; + /* REVISIT: Ultimately this will be used for multiboot */ #if 0 @@ -712,22 +733,31 @@ int __init omap2_clk_init(void) } } - /* REVISIT: Not yet ready for OMAP3 */ -#if 0 - /* Check the MPU rate set by bootloader */ - clkrate = omap2_get_dpll_rate_24xx(&dpll_ck); - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - if (prcm->xtal_speed != sys_ck.rate) - continue; - if (prcm->dpll_speed <= clkrate) - break; + recalculate_root_clocks(); + + dpll1_clk = clk_get(NULL, "dpll1_ck"); + dpll2_clk = clk_get(NULL, "dpll2_ck"); + dpll3_clk = clk_get(NULL, "dpll3_ck"); + +#ifdef CONFIG_MACH_OMAP_3430SDP + mpu_speed = dpll1_clk->rate; + prcm_vdd = vdd1_rate_table + MAX_VDD1_OPP; + for (; prcm_vdd->speed; prcm_vdd--) { + if (prcm_vdd->speed <= mpu_speed) { + curr_vdd1_prcm_set = prcm_vdd; + break; + } } - curr_prcm_set = prcm; -#endif - recalculate_root_clocks(); + core_speed = dpll3_clk->rate; + prcm_vdd = vdd2_rate_table + MAX_VDD2_OPP; + for (; prcm_vdd->speed; prcm_vdd--) { + if (prcm_vdd->speed <= core_speed) { + curr_vdd2_prcm_set = prcm_vdd; + break; + } + } +#endif printk(KERN_INFO "Clocking rate (Crystal/DPLL/ARM core): " "%ld.%01ld/%ld/%ld MHz\n", @@ -740,13 +770,131 @@ int __init omap2_clk_init(void) */ clk_enable_init_clocks(); - /* Avoid sleeping during omap2_clk_prepare_for_reboot() */ - /* REVISIT: not yet ready for 343x */ -#if 0 - vclk = clk_get(NULL, "virt_prcm_set"); - sclk = clk_get(NULL, "sys_ck"); -#endif return 0; } +inline unsigned int get_freq(struct vdd_prcm_config *opp_freq_table, + unsigned long opp) +{ + struct vdd_prcm_config *prcm_config; + prcm_config = opp_freq_table; + + for (; prcm_config->opp; prcm_config--) + if (prcm_config->opp == opp) + return prcm_config->speed; + return 0; +} + +inline unsigned int get_opp(struct vdd_prcm_config *opp_freq_table, + unsigned long freq) +{ + struct vdd_prcm_config *prcm_config; + prcm_config = opp_freq_table; + + if (prcm_config->speed <= freq) + return prcm_config->opp; /* Return the Highest OPP */ + for (; prcm_config->speed; prcm_config--) { + if (prcm_config->speed < freq) + return (prcm_config+1)->opp; + else if (prcm_config->speed == freq) + return prcm_config->opp; + } + /* Return the least OPP */ + return (prcm_config+1)->opp; +} + +#ifdef CONFIG_MACH_OMAP_3430SDP +static void omap3_table_recalc(struct clk *clk) +{ + if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set)) + return; + + if ((curr_vdd1_prcm_set) && (clk == &virt_vdd1_prcm_set)) + clk->rate = curr_vdd1_prcm_set->speed; + else if ((curr_vdd2_prcm_set) && (clk == &virt_vdd2_prcm_set)) + clk->rate = curr_vdd2_prcm_set->speed; + pr_debug("CLK RATE:%lu\n", clk->rate); +} + +static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate) +{ + struct vdd_prcm_config *ptr; + long highest_rate; + + if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set)) + return -EINVAL; + + highest_rate = -EINVAL; + + if (clk == &virt_vdd1_prcm_set) + ptr = vdd1_rate_table + MAX_VDD1_OPP; + else + ptr = vdd2_rate_table + MAX_VDD2_OPP; + + for (; ptr->speed; ptr--) { + highest_rate = ptr->speed; + pr_debug("Highest speed : %lu, rate: %lu\n", highest_rate, + rate); + if (ptr->speed <= rate) + break; + } + return highest_rate; +} + +static int omap3_select_table_rate(struct clk *clk, unsigned long rate) +{ + struct vdd_prcm_config *prcm_vdd; + unsigned long found_speed = 0, curr_mpu_speed; + int index; + + if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set)) + return -EINVAL; + + if (clk == &virt_vdd1_prcm_set) { + prcm_vdd = vdd1_rate_table + MAX_VDD1_OPP; + index = MAX_VDD1_OPP; + } else if (clk == &virt_vdd2_prcm_set) { + prcm_vdd = vdd2_rate_table + MAX_VDD2_OPP; + index = MAX_VDD2_OPP; + } + + for (; prcm_vdd->speed; prcm_vdd--, index--) { + if (prcm_vdd->speed <= rate) { + found_speed = prcm_vdd->speed; + pr_debug("Found speed = %lu\n", found_speed); + break; + } + } + + if (!found_speed) { + printk(KERN_INFO "Could not set table rate to %luMHz\n", + rate / 1000000); + return -EINVAL; + } + + + if (clk == &virt_vdd1_prcm_set) { + curr_mpu_speed = curr_vdd1_prcm_set->speed; + clk_set_rate(dpll1_clk, prcm_vdd->speed); + clk_set_rate(dpll2_clk, iva2_rate_table[index].speed); + curr_vdd1_prcm_set = prcm_vdd; +#ifndef CONFIG_CPU_FREQ + /*Update loops_per_jiffy if processor speed is being changed*/ + loops_per_jiffy = compute_lpj(loops_per_jiffy, + curr_mpu_speed/1000, found_speed/1000); #endif + } else { + clk_set_rate(dpll3_clk, prcm_vdd->speed); + curr_vdd2_prcm_set = prcm_vdd; + } + return 0; +} +#else /* CONFIG_MACH_OMAP_3430SDP */ +static void omap3_table_recalc(struct clk *clk) {} +static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate) +{ return 0; } +static int omap3_select_table_rate(struct clk *clk, unsigned long rate) +{ return 0; } +#endif /* CONFIG_MACH_OMAP_3430SDP */ + +#endif /* CONFIG_ARCH_OMAP3 */ Index: linux-omap-2.6/include/asm-arm/arch-omap/clock.h =================================================================== --- linux-omap-2.6.orig/include/asm-arm/arch-omap/clock.h 2008-08-07 14:34:23.000000000 +0530 +++ linux-omap-2.6/include/asm-arm/arch-omap/clock.h 2008-08-07 15:07:19.000000000 +0530 @@ -126,6 +126,14 @@ struct clk_functions { #endif }; +#ifdef CONFIG_ARCH_OMAP3 +struct vdd_prcm_config { + unsigned long speed; + unsigned long opp; + unsigned long flags; +}; +#endif + extern unsigned int mpurate; extern int clk_init(struct clk_functions *custom_clocks); Index: linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c =================================================================== --- linux-omap-2.6.orig/arch/arm/mach-omap2/board-3430sdp.c 2008-08-06 14:55:12.000000000 +0530 +++ linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c 2008-08-07 15:07:50.000000000 +0530 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,43 @@ #define ENABLE_VAUX3_DEDICATED 0x03 #define ENABLE_VAUX3_DEV_GRP 0x20 +struct vdd_prcm_config vdd1_rate_table[] = { + {0, 0, 0}, + /*OPP1*/ + {S125M, VDD1_OPP1, 0}, + /*OPP2*/ + {S250M, VDD1_OPP2, 0}, + /*OPP3*/ + {S500M, VDD1_OPP3, 0}, + /*OPP4*/ + {S550M, VDD1_OPP4, 0}, + /*OPP5*/ + {S600M, VDD1_OPP5, 0}, +}; + +struct vdd_prcm_config vdd2_rate_table[] = { + {0, 0, 0}, + /*OPP1*/ + {0, VDD2_OPP1, 0}, + /*OPP2*/ + {S83M, VDD2_OPP2, 0}, + /*OPP3*/ + {S166M, VDD2_OPP3, 0}, +}; + +struct vdd_prcm_config iva2_rate_table[] = { + {0, 0, 0}, + /*OPP1*/ + {S90M, VDD1_OPP1, 0}, + /*OPP2*/ + {S180M, VDD1_OPP2, 0}, + /*OPP3*/ + {S360M, VDD1_OPP3, 0}, + /*OPP4*/ + {S400M, VDD1_OPP4, 0}, + /*OPP5*/ + {S430M, VDD1_OPP5, 0}, +}; #define TWL4030_MSECURE_GPIO 22 Index: linux-omap-2.6/include/asm-arm/arch-omap/board-3430sdp.h =================================================================== --- linux-omap-2.6.orig/include/asm-arm/arch-omap/board-3430sdp.h 2008-08-06 14:55:22.000000000 +0530 +++ linux-omap-2.6/include/asm-arm/arch-omap/board-3430sdp.h 2008-08-07 15:07:19.000000000 +0530 @@ -68,5 +68,40 @@ extern void twl4030_bci_battery_init(voi #define FLASH_SIZE_SDPV1 SZ_64M #define FLASH_SIZE_SDPV2 SZ_128M +/* MPU speeds */ +#define S600M 600000000 +#define S550M 550000000 +#define S500M 500000000 +#define S250M 250000000 +#define S125M 125000000 + +/* IVA speeds */ +#define S430M 430000000 +#define S400M 400000000 +#define S360M 360000000 +#define S180M 180000000 +#define S90M 90000000 + +/* L3 speeds */ +#define S83M 83000000 +#define S166M 166000000 + +/* VDD1 OPPS */ +#define VDD1_OPP1 0x1 +#define VDD1_OPP2 0x2 +#define VDD1_OPP3 0x3 +#define VDD1_OPP4 0x4 +#define VDD1_OPP5 0x5 + +/* VDD2 OPPS */ +#define VDD2_OPP1 0x1 +#define VDD2_OPP2 0x2 +#define VDD2_OPP3 0x3 + +#define MIN_VDD1_OPP VDD1_OPP1 +#define MAX_VDD1_OPP VDD1_OPP5 +#define MIN_VDD2_OPP VDD2_OPP1 +#define MAX_VDD2_OPP VDD2_OPP3 + #endif /* __ASM_ARCH_OMAP_3430SDP_H */ -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html