aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-12-17 21:38:55 -0500
committerOlof Johansson <olof@lixom.net>2012-12-17 21:38:55 -0500
commit10be289d07a5327e2e7764bb3ccbffa215075103 (patch)
treee1591c2cee3da7e98e0166a60ff6517d63ba28c1
parent68136b105cbb798b13e9545b9952e568d04e347c (diff)
parent9db316b6bf0234d9391f87dd0d28b23f5a44facb (diff)
Merge tag 'omap-fixes-a-for-v3.8-window' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into fixes
From Paul Walmsley per Tony Lindgrens request: Fix some OMAP4 clock problems, and deal with some sparse warnings from the OMAP CPUIdle code. * tag 'omap-fixes-a-for-v3.8-window' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending: ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings ARM: OMAP4: clock data: DPLLs are missing bypass clocks in their parent lists ARM: OMAP4: clock data: div_iva_hs_clk is a power-of-two divider ARM: OMAP4: Fix EMU clock domain always on ARM: OMAP4460: Workaround ABE DPLL failing to turn-on ARM: OMAP4: Enhance support for DPLLs with 4X multiplier ARM: OMAP4: Add function table for non-M4X dplls ARM: OMAP4: Update timer clock aliases
-rw-r--r--arch/arm/mach-omap2/cclock44xx_data.c78
-rw-r--r--arch/arm/mach-omap2/clock.h10
-rw-r--r--arch/arm/mach-omap2/clockdomain.c3
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c14
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c28
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c46
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c64
7 files changed, 189 insertions, 54 deletions
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
index aa56c3e5bb34..5789a5e25563 100644
--- a/arch/arm/mach-omap2/cclock44xx_data.c
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -40,6 +40,14 @@
40#define OMAP4430_MODULEMODE_HWCTRL_SHIFT 0 40#define OMAP4430_MODULEMODE_HWCTRL_SHIFT 0
41#define OMAP4430_MODULEMODE_SWCTRL_SHIFT 1 41#define OMAP4430_MODULEMODE_SWCTRL_SHIFT 1
42 42
43/*
44 * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
45 * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
46 * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
47 * half of this value.
48 */
49#define OMAP4_DPLL_ABE_DEFFREQ 98304000
50
43/* Root clocks */ 51/* Root clocks */
44 52
45DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0); 53DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
@@ -124,6 +132,8 @@ static struct dpll_data dpll_abe_dd = {
124 .enable_mask = OMAP4430_DPLL_EN_MASK, 132 .enable_mask = OMAP4430_DPLL_EN_MASK,
125 .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, 133 .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
126 .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, 134 .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
135 .m4xen_mask = OMAP4430_DPLL_REGM4XEN_MASK,
136 .lpmode_mask = OMAP4430_DPLL_LPMODE_EN_MASK,
127 .max_multiplier = 2047, 137 .max_multiplier = 2047,
128 .max_divider = 128, 138 .max_divider = 128,
129 .min_divider = 1, 139 .min_divider = 1,
@@ -233,7 +243,7 @@ static struct dpll_data dpll_core_dd = {
233 243
234 244
235static const char *dpll_core_ck_parents[] = { 245static const char *dpll_core_ck_parents[] = {
236 "sys_clkin_ck", 246 "sys_clkin_ck", "core_hsd_byp_clk_mux_ck"
237}; 247};
238 248
239static struct clk dpll_core_ck; 249static struct clk dpll_core_ck;
@@ -286,9 +296,9 @@ DEFINE_CLK_DIVIDER(div_core_ck, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0,
286 OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT, 296 OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT,
287 OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL); 297 OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL);
288 298
289DEFINE_CLK_OMAP_HSDIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck", 299DEFINE_CLK_DIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
290 &dpll_core_m5x2_ck, 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA, 300 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA, OMAP4430_CLKSEL_0_1_SHIFT,
291 OMAP4430_CLKSEL_0_1_MASK); 301 OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
292 302
293DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 303DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
294 0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT, 304 0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT,
@@ -363,8 +373,21 @@ static struct dpll_data dpll_iva_dd = {
363 .min_divider = 1, 373 .min_divider = 1,
364}; 374};
365 375
376static const char *dpll_iva_ck_parents[] = {
377 "sys_clkin_ck", "iva_hsd_byp_clk_mux_ck"
378};
379
366static struct clk dpll_iva_ck; 380static struct clk dpll_iva_ck;
367 381
382static const struct clk_ops dpll_ck_ops = {
383 .enable = &omap3_noncore_dpll_enable,
384 .disable = &omap3_noncore_dpll_disable,
385 .recalc_rate = &omap3_dpll_recalc,
386 .round_rate = &omap2_dpll_round_rate,
387 .set_rate = &omap3_noncore_dpll_set_rate,
388 .get_parent = &omap2_init_dpll_parent,
389};
390
368static struct clk_hw_omap dpll_iva_ck_hw = { 391static struct clk_hw_omap dpll_iva_ck_hw = {
369 .hw = { 392 .hw = {
370 .clk = &dpll_iva_ck, 393 .clk = &dpll_iva_ck,
@@ -373,7 +396,7 @@ static struct clk_hw_omap dpll_iva_ck_hw = {
373 .ops = &clkhwops_omap3_dpll, 396 .ops = &clkhwops_omap3_dpll,
374}; 397};
375 398
376DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_core_ck_parents, dpll_abe_ck_ops); 399DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_iva_ck_parents, dpll_ck_ops);
377 400
378static const char *dpll_iva_x2_ck_parents[] = { 401static const char *dpll_iva_x2_ck_parents[] = {
379 "dpll_iva_ck", 402 "dpll_iva_ck",
@@ -416,6 +439,10 @@ static struct dpll_data dpll_mpu_dd = {
416 .min_divider = 1, 439 .min_divider = 1,
417}; 440};
418 441
442static const char *dpll_mpu_ck_parents[] = {
443 "sys_clkin_ck", "div_mpu_hs_clk"
444};
445
419static struct clk dpll_mpu_ck; 446static struct clk dpll_mpu_ck;
420 447
421static struct clk_hw_omap dpll_mpu_ck_hw = { 448static struct clk_hw_omap dpll_mpu_ck_hw = {
@@ -426,7 +453,7 @@ static struct clk_hw_omap dpll_mpu_ck_hw = {
426 .ops = &clkhwops_omap3_dpll, 453 .ops = &clkhwops_omap3_dpll,
427}; 454};
428 455
429DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_abe_ck_ops); 456DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_mpu_ck_parents, dpll_ck_ops);
430 457
431DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2); 458DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2);
432 459
@@ -464,6 +491,9 @@ static struct dpll_data dpll_per_dd = {
464 .min_divider = 1, 491 .min_divider = 1,
465}; 492};
466 493
494static const char *dpll_per_ck_parents[] = {
495 "sys_clkin_ck", "per_hsd_byp_clk_mux_ck"
496};
467 497
468static struct clk dpll_per_ck; 498static struct clk dpll_per_ck;
469 499
@@ -475,7 +505,7 @@ static struct clk_hw_omap dpll_per_ck_hw = {
475 .ops = &clkhwops_omap3_dpll, 505 .ops = &clkhwops_omap3_dpll,
476}; 506};
477 507
478DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_abe_ck_ops); 508DEFINE_STRUCT_CLK(dpll_per_ck, dpll_per_ck_parents, dpll_ck_ops);
479 509
480DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0, 510DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
481 OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT, 511 OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
@@ -559,6 +589,10 @@ static struct dpll_data dpll_usb_dd = {
559 .min_divider = 1, 589 .min_divider = 1,
560}; 590};
561 591
592static const char *dpll_usb_ck_parents[] = {
593 "sys_clkin_ck", "usb_hs_clk_div_ck"
594};
595
562static struct clk dpll_usb_ck; 596static struct clk dpll_usb_ck;
563 597
564static struct clk_hw_omap dpll_usb_ck_hw = { 598static struct clk_hw_omap dpll_usb_ck_hw = {
@@ -569,7 +603,7 @@ static struct clk_hw_omap dpll_usb_ck_hw = {
569 .ops = &clkhwops_omap3_dpll, 603 .ops = &clkhwops_omap3_dpll,
570}; 604};
571 605
572DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_core_ck_parents, dpll_abe_ck_ops); 606DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_usb_ck_parents, dpll_ck_ops);
573 607
574static const char *dpll_usb_clkdcoldo_ck_parents[] = { 608static const char *dpll_usb_clkdcoldo_ck_parents[] = {
575 "dpll_usb_ck", 609 "dpll_usb_ck",
@@ -696,9 +730,13 @@ DEFINE_CLK_DIVIDER(syc_clk_div_ck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
696 OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT, 730 OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
697 OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL); 731 OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
698 732
733static const char *dbgclk_mux_ck_parents[] = {
734 "sys_clkin_ck"
735};
736
699static struct clk dbgclk_mux_ck; 737static struct clk dbgclk_mux_ck;
700DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL); 738DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL);
701DEFINE_STRUCT_CLK(dbgclk_mux_ck, dpll_core_ck_parents, 739DEFINE_STRUCT_CLK(dbgclk_mux_ck, dbgclk_mux_ck_parents,
702 dpll_usb_clkdcoldo_ck_ops); 740 dpll_usb_clkdcoldo_ck_ops);
703 741
704/* Leaf clocks controlled by modules */ 742/* Leaf clocks controlled by modules */
@@ -1935,10 +1973,10 @@ static struct omap_clk omap44xx_clks[] = {
1935 CLK("4803e000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X), 1973 CLK("4803e000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
1936 CLK("48086000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X), 1974 CLK("48086000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
1937 CLK("48088000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X), 1975 CLK("48088000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
1938 CLK("49038000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), 1976 CLK("40138000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
1939 CLK("4903a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), 1977 CLK("4013a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
1940 CLK("4903c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), 1978 CLK("4013c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
1941 CLK("4903e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X), 1979 CLK("4013e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
1942 CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X), 1980 CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X),
1943}; 1981};
1944 1982
@@ -1955,6 +1993,7 @@ int __init omap4xxx_clk_init(void)
1955{ 1993{
1956 u32 cpu_clkflg; 1994 u32 cpu_clkflg;
1957 struct omap_clk *c; 1995 struct omap_clk *c;
1996 int rc;
1958 1997
1959 if (cpu_is_omap443x()) { 1998 if (cpu_is_omap443x()) {
1960 cpu_mask = RATE_IN_4430; 1999 cpu_mask = RATE_IN_4430;
@@ -1983,5 +2022,18 @@ int __init omap4xxx_clk_init(void)
1983 omap2_clk_enable_init_clocks(enable_init_clks, 2022 omap2_clk_enable_init_clocks(enable_init_clks,
1984 ARRAY_SIZE(enable_init_clks)); 2023 ARRAY_SIZE(enable_init_clks));
1985 2024
2025 /*
2026 * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
2027 * state when turning the ABE clock domain. Workaround this by
2028 * locking the ABE DPLL on boot.
2029 */
2030 if (cpu_is_omap446x()) {
2031 rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
2032 if (!rc)
2033 rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
2034 if (rc)
2035 pr_err("%s: failed to configure ABE DPLL!\n", __func__);
2036 }
2037
1986 return 0; 2038 return 0;
1987} 2039}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 9917f793c3b6..b40204837bd7 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -195,6 +195,10 @@ struct clksel {
195 * @enable_mask: mask of the DPLL mode bitfield in @control_reg 195 * @enable_mask: mask of the DPLL mode bitfield in @control_reg
196 * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate() 196 * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
197 * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate() 197 * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
198 * @last_rounded_m4xen: cache of the last M4X result of
199 * omap4_dpll_regm4xen_round_rate()
200 * @last_rounded_lpmode: cache of the last lpmode result of
201 * omap4_dpll_lpmode_recalc()
198 * @max_multiplier: maximum valid non-bypass multiplier value (actual) 202 * @max_multiplier: maximum valid non-bypass multiplier value (actual)
199 * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() 203 * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
200 * @min_divider: minimum valid non-bypass divider value (actual) 204 * @min_divider: minimum valid non-bypass divider value (actual)
@@ -205,6 +209,8 @@ struct clksel {
205 * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg 209 * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
206 * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg 210 * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
207 * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg 211 * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
212 * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
213 * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
208 * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg 214 * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
209 * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs 215 * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
210 * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs 216 * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
@@ -233,6 +239,8 @@ struct dpll_data {
233 u32 enable_mask; 239 u32 enable_mask;
234 unsigned long last_rounded_rate; 240 unsigned long last_rounded_rate;
235 u16 last_rounded_m; 241 u16 last_rounded_m;
242 u8 last_rounded_m4xen;
243 u8 last_rounded_lpmode;
236 u16 max_multiplier; 244 u16 max_multiplier;
237 u8 last_rounded_n; 245 u8 last_rounded_n;
238 u8 min_divider; 246 u8 min_divider;
@@ -245,6 +253,8 @@ struct dpll_data {
245 u32 idlest_mask; 253 u32 idlest_mask;
246 u32 dco_mask; 254 u32 dco_mask;
247 u32 sddiv_mask; 255 u32 sddiv_mask;
256 u32 lpmode_mask;
257 u32 m4xen_mask;
248 u8 auto_recal_bit; 258 u8 auto_recal_bit;
249 u8 recal_en_bit; 259 u8 recal_en_bit;
250 u8 recal_st_bit; 260 u8 recal_st_bit;
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 384873580b23..7faf82d4e85c 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -998,7 +998,8 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
998 spin_lock_irqsave(&clkdm->lock, flags); 998 spin_lock_irqsave(&clkdm->lock, flags);
999 999
1000 /* corner case: disabling unused clocks */ 1000 /* corner case: disabling unused clocks */
1001 if (__clk_get_enable_count(clk) == 0) 1001 if ((__clk_get_enable_count(clk) == 0) &&
1002 (atomic_read(&clkdm->usecount) == 0))
1002 goto ccd_exit; 1003 goto ccd_exit;
1003 1004
1004 if (atomic_read(&clkdm->usecount) == 0) { 1005 if (atomic_read(&clkdm->usecount) == 0) {
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index bca7a8885703..22590dbe8f14 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -40,6 +40,8 @@ struct omap3_idle_statedata {
40 u32 core_state; 40 u32 core_state;
41}; 41};
42 42
43static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
44
43static struct omap3_idle_statedata omap3_idle_data[] = { 45static struct omap3_idle_statedata omap3_idle_data[] = {
44 { 46 {
45 .mpu_state = PWRDM_POWER_ON, 47 .mpu_state = PWRDM_POWER_ON,
@@ -71,7 +73,7 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
71 }, 73 },
72}; 74};
73 75
74static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; 76/* Private functions */
75 77
76static int __omap3_enter_idle(struct cpuidle_device *dev, 78static int __omap3_enter_idle(struct cpuidle_device *dev,
77 struct cpuidle_driver *drv, 79 struct cpuidle_driver *drv,
@@ -260,11 +262,11 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
260 return ret; 262 return ret;
261} 263}
262 264
263DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); 265static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
264 266
265struct cpuidle_driver omap3_idle_driver = { 267static struct cpuidle_driver omap3_idle_driver = {
266 .name = "omap3_idle", 268 .name = "omap3_idle",
267 .owner = THIS_MODULE, 269 .owner = THIS_MODULE,
268 .states = { 270 .states = {
269 { 271 {
270 .enter = omap3_enter_idle_bm, 272 .enter = omap3_enter_idle_bm,
@@ -327,6 +329,8 @@ struct cpuidle_driver omap3_idle_driver = {
327 .safe_state_index = 0, 329 .safe_state_index = 0,
328}; 330};
329 331
332/* Public functions */
333
330/** 334/**
331 * omap3_idle_init - Init routine for OMAP3 idle 335 * omap3_idle_init - Init routine for OMAP3 idle
332 * 336 *
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 288bee6cbb76..d639aef0deda 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -54,6 +54,8 @@ static struct clockdomain *cpu_clkdm[NR_CPUS];
54static atomic_t abort_barrier; 54static atomic_t abort_barrier;
55static bool cpu_done[NR_CPUS]; 55static bool cpu_done[NR_CPUS];
56 56
57/* Private functions */
58
57/** 59/**
58 * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions 60 * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions
59 * @dev: cpuidle device 61 * @dev: cpuidle device
@@ -161,9 +163,19 @@ fail:
161 return index; 163 return index;
162} 164}
163 165
164DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); 166/*
167 * For each cpu, setup the broadcast timer because local timers
168 * stops for the states above C1.
169 */
170static void omap_setup_broadcast_timer(void *arg)
171{
172 int cpu = smp_processor_id();
173 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
174}
175
176static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
165 177
166struct cpuidle_driver omap4_idle_driver = { 178static struct cpuidle_driver omap4_idle_driver = {
167 .name = "omap4_idle", 179 .name = "omap4_idle",
168 .owner = THIS_MODULE, 180 .owner = THIS_MODULE,
169 .en_core_tk_irqen = 1, 181 .en_core_tk_irqen = 1,
@@ -178,7 +190,7 @@ struct cpuidle_driver omap4_idle_driver = {
178 .desc = "MPUSS ON" 190 .desc = "MPUSS ON"
179 }, 191 },
180 { 192 {
181 /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */ 193 /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
182 .exit_latency = 328 + 440, 194 .exit_latency = 328 + 440,
183 .target_residency = 960, 195 .target_residency = 960,
184 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED, 196 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
@@ -200,15 +212,7 @@ struct cpuidle_driver omap4_idle_driver = {
200 .safe_state_index = 0, 212 .safe_state_index = 0,
201}; 213};
202 214
203/* 215/* Public functions */
204 * For each cpu, setup the broadcast timer because local timers
205 * stops for the states above C1.
206 */
207static void omap_setup_broadcast_timer(void *arg)
208{
209 int cpu = smp_processor_id();
210 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
211}
212 216
213/** 217/**
214 * omap4_idle_init - Init routine for OMAP4 idle 218 * omap4_idle_init - Init routine for OMAP4 idle
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index fafb28c0dcbc..2bb18838cba9 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -291,16 +291,13 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
291 291
292/* 292/*
293 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly 293 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
294 * @clk: struct clk * of DPLL to set 294 * @clk: struct clk * of DPLL to set
295 * @m: DPLL multiplier to set 295 * @freqsel: FREQSEL value to set
296 * @n: DPLL divider to set
297 * @freqsel: FREQSEL value to set
298 * 296 *
299 * Program the DPLL with the supplied M, N values, and wait for the DPLL to 297 * Program the DPLL with the last M, N values calculated, and wait for
300 * lock.. Returns -EINVAL upon error, or 0 upon success. 298 * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success.
301 */ 299 */
302static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n, 300static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
303 u16 freqsel)
304{ 301{
305 struct dpll_data *dd = clk->dpll_data; 302 struct dpll_data *dd = clk->dpll_data;
306 u8 dco, sd_div; 303 u8 dco, sd_div;
@@ -323,23 +320,45 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n,
323 /* Set DPLL multiplier, divider */ 320 /* Set DPLL multiplier, divider */
324 v = __raw_readl(dd->mult_div1_reg); 321 v = __raw_readl(dd->mult_div1_reg);
325 v &= ~(dd->mult_mask | dd->div1_mask); 322 v &= ~(dd->mult_mask | dd->div1_mask);
326 v |= m << __ffs(dd->mult_mask); 323 v |= dd->last_rounded_m << __ffs(dd->mult_mask);
327 v |= (n - 1) << __ffs(dd->div1_mask); 324 v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
328 325
329 /* Configure dco and sd_div for dplls that have these fields */ 326 /* Configure dco and sd_div for dplls that have these fields */
330 if (dd->dco_mask) { 327 if (dd->dco_mask) {
331 _lookup_dco(clk, &dco, m, n); 328 _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n);
332 v &= ~(dd->dco_mask); 329 v &= ~(dd->dco_mask);
333 v |= dco << __ffs(dd->dco_mask); 330 v |= dco << __ffs(dd->dco_mask);
334 } 331 }
335 if (dd->sddiv_mask) { 332 if (dd->sddiv_mask) {
336 _lookup_sddiv(clk, &sd_div, m, n); 333 _lookup_sddiv(clk, &sd_div, dd->last_rounded_m,
334 dd->last_rounded_n);
337 v &= ~(dd->sddiv_mask); 335 v &= ~(dd->sddiv_mask);
338 v |= sd_div << __ffs(dd->sddiv_mask); 336 v |= sd_div << __ffs(dd->sddiv_mask);
339 } 337 }
340 338
341 __raw_writel(v, dd->mult_div1_reg); 339 __raw_writel(v, dd->mult_div1_reg);
342 340
341 /* Set 4X multiplier and low-power mode */
342 if (dd->m4xen_mask || dd->lpmode_mask) {
343 v = __raw_readl(dd->control_reg);
344
345 if (dd->m4xen_mask) {
346 if (dd->last_rounded_m4xen)
347 v |= dd->m4xen_mask;
348 else
349 v &= ~dd->m4xen_mask;
350 }
351
352 if (dd->lpmode_mask) {
353 if (dd->last_rounded_lpmode)
354 v |= dd->lpmode_mask;
355 else
356 v &= ~dd->lpmode_mask;
357 }
358
359 __raw_writel(v, dd->control_reg);
360 }
361
343 /* We let the clock framework set the other output dividers later */ 362 /* We let the clock framework set the other output dividers later */
344 363
345 /* REVISIT: Set ramp-up delay? */ 364 /* REVISIT: Set ramp-up delay? */
@@ -492,8 +511,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
492 pr_debug("%s: %s: set rate: locking rate to %lu.\n", 511 pr_debug("%s: %s: set rate: locking rate to %lu.\n",
493 __func__, __clk_get_name(hw->clk), rate); 512 __func__, __clk_get_name(hw->clk), rate);
494 513
495 ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m, 514 ret = omap3_noncore_dpll_program(clk, freqsel);
496 dd->last_rounded_n, freqsel);
497 if (!ret) 515 if (!ret)
498 new_parent = dd->clk_ref; 516 new_parent = dd->clk_ref;
499 } 517 }
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index d3326c474fdc..d28b0f726715 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -20,6 +20,15 @@
20#include "clock44xx.h" 20#include "clock44xx.h"
21#include "cm-regbits-44xx.h" 21#include "cm-regbits-44xx.h"
22 22
23/*
24 * Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
25 * can supported when using the DPLL low-power mode. Frequencies are
26 * defined in OMAP4430/60 Public TRM section 3.6.3.3.2 "Enable Control,
27 * Status, and Low-Power Operation Mode".
28 */
29#define OMAP4_DPLL_LP_FINT_MAX 1000000
30#define OMAP4_DPLL_LP_FOUT_MAX 100000000
31
23/* Supported only on OMAP4 */ 32/* Supported only on OMAP4 */
24int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk) 33int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
25{ 34{
@@ -82,6 +91,31 @@ const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
82}; 91};
83 92
84/** 93/**
94 * omap4_dpll_lpmode_recalc - compute DPLL low-power setting
95 * @dd: pointer to the dpll data structure
96 *
97 * Calculates if low-power mode can be enabled based upon the last
98 * multiplier and divider values calculated. If low-power mode can be
99 * enabled, then the bit to enable low-power mode is stored in the
100 * last_rounded_lpmode variable. This implementation is based upon the
101 * criteria for enabling low-power mode as described in the OMAP4430/60
102 * Public TRM section 3.6.3.3.2 "Enable Control, Status, and Low-Power
103 * Operation Mode".
104 */
105static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
106{
107 long fint, fout;
108
109 fint = __clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1);
110 fout = fint * dd->last_rounded_m;
111
112 if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX))
113 dd->last_rounded_lpmode = 1;
114 else
115 dd->last_rounded_lpmode = 0;
116}
117
118/**
85 * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit 119 * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
86 * @clk: struct clk * of the DPLL to compute the rate for 120 * @clk: struct clk * of the DPLL to compute the rate for
87 * 121 *
@@ -130,7 +164,6 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
130 unsigned long *parent_rate) 164 unsigned long *parent_rate)
131{ 165{
132 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 166 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
133 u32 v;
134 struct dpll_data *dd; 167 struct dpll_data *dd;
135 long r; 168 long r;
136 169
@@ -139,18 +172,31 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
139 172
140 dd = clk->dpll_data; 173 dd = clk->dpll_data;
141 174
142 /* regm4xen adds a multiplier of 4 to DPLL calculations */ 175 dd->last_rounded_m4xen = 0;
143 v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
144
145 if (v)
146 target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
147 176
177 /*
178 * First try to compute the DPLL configuration for
179 * target rate without using the 4X multiplier.
180 */
148 r = omap2_dpll_round_rate(hw, target_rate, NULL); 181 r = omap2_dpll_round_rate(hw, target_rate, NULL);
182 if (r != ~0)
183 goto out;
184
185 /*
186 * If we did not find a valid DPLL configuration, try again, but
187 * this time see if using the 4X multiplier can help. Enabling the
188 * 4X multiplier is equivalent to dividing the target rate by 4.
189 */
190 r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT,
191 NULL);
149 if (r == ~0) 192 if (r == ~0)
150 return r; 193 return r;
151 194
152 if (v) 195 dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
153 clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; 196 dd->last_rounded_m4xen = 1;
197
198out:
199 omap4_dpll_lpmode_recalc(dd);
154 200
155 return clk->dpll_data->last_rounded_rate; 201 return dd->last_rounded_rate;
156} 202}