aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/clock.c14
-rw-r--r--arch/arm/mach-omap2/clock24xx.c2
-rw-r--r--arch/arm/mach-omap2/clock34xx.c23
-rw-r--r--arch/arm/mach-omap2/clock34xx.h33
-rw-r--r--arch/arm/mach-omap2/clockdomains.h2
-rw-r--r--arch/arm/mach-omap2/cm-regbits-34xx.h14
-rw-r--r--arch/arm/mach-omap2/irq.c18
-rw-r--r--arch/arm/mach-omap2/pm-debug.c152
-rw-r--r--arch/arm/mach-omap2/pm.c111
-rw-r--r--arch/arm/mach-omap2/pm.h38
-rw-r--r--arch/arm/mach-omap2/pm24xx.c549
-rw-r--r--arch/arm/mach-omap2/pm34xx.c710
-rw-r--r--arch/arm/mach-omap2/prcm-common.h2
-rw-r--r--arch/arm/mach-omap2/prm.h2
-rw-r--r--arch/arm/mach-omap2/sdrc.c24
-rw-r--r--arch/arm/mach-omap2/serial.c440
-rw-r--r--arch/arm/mach-omap2/sleep24xx.S1
-rw-r--r--arch/arm/mach-omap2/sleep34xx.S436
-rw-r--r--arch/arm/mach-omap2/sram34xx.S129
-rw-r--r--arch/arm/mach-omap2/usb-musb.c21
21 files changed, 2502 insertions, 225 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 10e7c29ac1db..c48b12c0fe2d 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -25,8 +25,10 @@ obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o
25 25
26# Power Management 26# Power Management
27ifeq ($(CONFIG_PM),y) 27ifeq ($(CONFIG_PM),y)
28obj-y += pm.o 28obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
29obj-$(CONFIG_ARCH_OMAP24XX) += sleep24xx.o 29obj-$(CONFIG_ARCH_OMAP24XX) += sleep24xx.o
30obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o
31obj-$(CONFIG_PM_DEBUG) += pm-debug.o
30endif 32endif
31 33
32# Clock framework 34# Clock framework
@@ -59,9 +61,7 @@ obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
59 mmc-twl4030.o \ 61 mmc-twl4030.o \
60 board-zoom-debugboard.o 62 board-zoom-debugboard.o
61# Platform specific device init code 63# Platform specific device init code
62ifeq ($(CONFIG_USB_MUSB_SOC),y)
63obj-y += usb-musb.o 64obj-y += usb-musb.o
64endif
65 65
66onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o 66onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o
67obj-y += $(onenand-m) $(onenand-y) 67obj-y += $(onenand-m) $(onenand-y)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index dd37483f3d18..ba528f85749c 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -547,8 +547,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
547 const struct clksel_rate *clkr; 547 const struct clksel_rate *clkr;
548 u32 last_div = 0; 548 u32 last_div = 0;
549 549
550 printk(KERN_INFO "clock: clksel_round_rate_div: %s target_rate %ld\n", 550 pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
551 clk->name, target_rate); 551 clk->name, target_rate);
552 552
553 *new_div = 1; 553 *new_div = 1;
554 554
@@ -562,7 +562,7 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
562 562
563 /* Sanity check */ 563 /* Sanity check */
564 if (clkr->div <= last_div) 564 if (clkr->div <= last_div)
565 printk(KERN_ERR "clock: clksel_rate table not sorted " 565 pr_err("clock: clksel_rate table not sorted "
566 "for clock %s", clk->name); 566 "for clock %s", clk->name);
567 567
568 last_div = clkr->div; 568 last_div = clkr->div;
@@ -574,7 +574,7 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
574 } 574 }
575 575
576 if (!clkr->div) { 576 if (!clkr->div) {
577 printk(KERN_ERR "clock: Could not find divisor for target " 577 pr_err("clock: Could not find divisor for target "
578 "rate %ld for clock %s parent %s\n", target_rate, 578 "rate %ld for clock %s parent %s\n", target_rate,
579 clk->name, clk->parent->name); 579 clk->name, clk->parent->name);
580 return ~0; 580 return ~0;
@@ -582,8 +582,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
582 582
583 *new_div = clkr->div; 583 *new_div = clkr->div;
584 584
585 printk(KERN_INFO "clock: new_div = %d, new_rate = %ld\n", *new_div, 585 pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
586 (clk->parent->rate / clkr->div)); 586 (clk->parent->rate / clkr->div));
587 587
588 return (clk->parent->rate / clkr->div); 588 return (clk->parent->rate / clkr->div);
589} 589}
@@ -1035,7 +1035,7 @@ void omap2_clk_disable_unused(struct clk *clk)
1035 if ((regval32 & (1 << clk->enable_bit)) == v) 1035 if ((regval32 & (1 << clk->enable_bit)) == v)
1036 return; 1036 return;
1037 1037
1038 printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name); 1038 printk(KERN_DEBUG "Disabling unused clock \"%s\"\n", clk->name);
1039 if (cpu_is_omap34xx()) { 1039 if (cpu_is_omap34xx()) {
1040 omap2_clk_enable(clk); 1040 omap2_clk_enable(clk);
1041 omap2_clk_disable(clk); 1041 omap2_clk_disable(clk);
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index c442fe9f998a..44de0271fc2f 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -725,7 +725,7 @@ int __init omap2_clk_init(void)
725 clk_init(&omap2_clk_functions); 725 clk_init(&omap2_clk_functions);
726 726
727 for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) 727 for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
728 clk_init_one(c->lk.clk); 728 clk_preinit(c->lk.clk);
729 729
730 osc_ck.rate = omap2_osc_clk_recalc(&osc_ck); 730 osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
731 propagate_rate(&osc_ck); 731 propagate_rate(&osc_ck);
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index ba05aa42bd8e..9e43fe5209d3 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -129,6 +129,9 @@ static struct omap_clk omap34xx_clks[] = {
129 CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2), 129 CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2),
130 CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2), 130 CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2),
131 CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1), 131 CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1),
132 CLK(NULL, "modem_fck", &modem_fck, CK_343X),
133 CLK(NULL, "sad2d_ick", &sad2d_ick, CK_343X),
134 CLK(NULL, "mad2d_ick", &mad2d_ick, CK_343X),
132 CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X), 135 CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X),
133 CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X), 136 CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X),
134 CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2), 137 CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2),
@@ -281,6 +284,8 @@ static struct omap_clk omap34xx_clks[] = {
281 284
282#define MAX_DPLL_WAIT_TRIES 1000000 285#define MAX_DPLL_WAIT_TRIES 1000000
283 286
287#define MIN_SDRC_DLL_LOCK_FREQ 83000000
288
284/** 289/**
285 * omap3_dpll_recalc - recalculate DPLL rate 290 * omap3_dpll_recalc - recalculate DPLL rate
286 * @clk: DPLL struct clk 291 * @clk: DPLL struct clk
@@ -703,6 +708,7 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
703static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) 708static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
704{ 709{
705 u32 new_div = 0; 710 u32 new_div = 0;
711 u32 unlock_dll = 0;
706 unsigned long validrate, sdrcrate; 712 unsigned long validrate, sdrcrate;
707 struct omap_sdrc_params *sp; 713 struct omap_sdrc_params *sp;
708 714
@@ -729,17 +735,22 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
729 if (!sp) 735 if (!sp)
730 return -EINVAL; 736 return -EINVAL;
731 737
732 pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate, 738 if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) {
733 validrate); 739 pr_debug("clock: will unlock SDRC DLL\n");
734 pr_info("clock: SDRC timing params used: %08x %08x %08x\n", 740 unlock_dll = 1;
735 sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb); 741 }
742
743 pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
744 validrate);
745 pr_debug("clock: SDRC timing params used: %08x %08x %08x\n",
746 sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb);
736 747
737 /* REVISIT: SRAM code doesn't support other M2 divisors yet */ 748 /* REVISIT: SRAM code doesn't support other M2 divisors yet */
738 WARN_ON(new_div != 1 && new_div != 2); 749 WARN_ON(new_div != 1 && new_div != 2);
739 750
740 /* REVISIT: Add SDRC_MR changing to this code also */ 751 /* REVISIT: Add SDRC_MR changing to this code also */
741 omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, 752 omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
742 sp->actim_ctrlb, new_div); 753 sp->actim_ctrlb, new_div, unlock_dll);
743 754
744 return 0; 755 return 0;
745} 756}
@@ -956,7 +967,7 @@ int __init omap2_clk_init(void)
956 clk_init(&omap2_clk_functions); 967 clk_init(&omap2_clk_functions);
957 968
958 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) 969 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
959 clk_init_one(c->lk.clk); 970 clk_preinit(c->lk.clk);
960 971
961 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) 972 for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
962 if (c->cpu & cpu_clkflg) { 973 if (c->cpu & cpu_clkflg) {
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 496f0e9caeb2..e433aec4efdd 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -1230,6 +1230,37 @@ static struct clk d2d_26m_fck = {
1230 .recalc = &followparent_recalc, 1230 .recalc = &followparent_recalc,
1231}; 1231};
1232 1232
1233static struct clk modem_fck = {
1234 .name = "modem_fck",
1235 .ops = &clkops_omap2_dflt_wait,
1236 .parent = &sys_ck,
1237 .init = &omap2_init_clk_clkdm,
1238 .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
1239 .enable_bit = OMAP3430_EN_MODEM_SHIFT,
1240 .clkdm_name = "d2d_clkdm",
1241 .recalc = &followparent_recalc,
1242};
1243
1244static struct clk sad2d_ick = {
1245 .name = "sad2d_ick",
1246 .ops = &clkops_omap2_dflt_wait,
1247 .parent = &l3_ick,
1248 .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
1249 .enable_bit = OMAP3430_EN_SAD2D_SHIFT,
1250 .clkdm_name = "d2d_clkdm",
1251 .recalc = &followparent_recalc,
1252};
1253
1254static struct clk mad2d_ick = {
1255 .name = "mad2d_ick",
1256 .ops = &clkops_omap2_dflt_wait,
1257 .parent = &l3_ick,
1258 .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
1259 .enable_bit = OMAP3430_EN_MAD2D_SHIFT,
1260 .clkdm_name = "d2d_clkdm",
1261 .recalc = &followparent_recalc,
1262};
1263
1233static const struct clksel omap343x_gpt_clksel[] = { 1264static const struct clksel omap343x_gpt_clksel[] = {
1234 { .parent = &omap_32k_fck, .rates = gpt_32k_rates }, 1265 { .parent = &omap_32k_fck, .rates = gpt_32k_rates },
1235 { .parent = &sys_ck, .rates = gpt_sys_rates }, 1266 { .parent = &sys_ck, .rates = gpt_sys_rates },
@@ -1947,8 +1978,6 @@ static struct clk usb_l4_ick = {
1947 .recalc = &omap2_clksel_recalc, 1978 .recalc = &omap2_clksel_recalc,
1948}; 1979};
1949 1980
1950/* XXX MDM_INTC_ICK, SAD2D_ICK ?? */
1951
1952/* SECURITY_L4_ICK2 based clocks */ 1981/* SECURITY_L4_ICK2 based clocks */
1953 1982
1954static struct clk security_l4_ick2 = { 1983static struct clk security_l4_ick2 = {
diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index 281d5da19188..fe319ae4ca0a 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -195,7 +195,7 @@ static struct clockdomain sgx_clkdm = {
195static struct clockdomain d2d_clkdm = { 195static struct clockdomain d2d_clkdm = {
196 .name = "d2d_clkdm", 196 .name = "d2d_clkdm",
197 .pwrdm = { .name = "core_pwrdm" }, 197 .pwrdm = { .name = "core_pwrdm" },
198 .flags = CLKDM_CAN_HWSUP, 198 .flags = CLKDM_CAN_HWSUP_SWSUP,
199 .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK, 199 .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
200 .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), 200 .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
201}; 201};
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 6f3f5a36aae6..6923deb98a28 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -145,6 +145,8 @@
145#define OMAP3430_CLKACTIVITY_MPU_MASK (1 << 0) 145#define OMAP3430_CLKACTIVITY_MPU_MASK (1 << 0)
146 146
147/* CM_FCLKEN1_CORE specific bits */ 147/* CM_FCLKEN1_CORE specific bits */
148#define OMAP3430_EN_MODEM (1 << 31)
149#define OMAP3430_EN_MODEM_SHIFT 31
148 150
149/* CM_ICLKEN1_CORE specific bits */ 151/* CM_ICLKEN1_CORE specific bits */
150#define OMAP3430_EN_ICR (1 << 29) 152#define OMAP3430_EN_ICR (1 << 29)
@@ -161,6 +163,8 @@
161#define OMAP3430_EN_MAILBOXES_SHIFT 7 163#define OMAP3430_EN_MAILBOXES_SHIFT 7
162#define OMAP3430_EN_OMAPCTRL (1 << 6) 164#define OMAP3430_EN_OMAPCTRL (1 << 6)
163#define OMAP3430_EN_OMAPCTRL_SHIFT 6 165#define OMAP3430_EN_OMAPCTRL_SHIFT 6
166#define OMAP3430_EN_SAD2D (1 << 3)
167#define OMAP3430_EN_SAD2D_SHIFT 3
164#define OMAP3430_EN_SDRC (1 << 1) 168#define OMAP3430_EN_SDRC (1 << 1)
165#define OMAP3430_EN_SDRC_SHIFT 1 169#define OMAP3430_EN_SDRC_SHIFT 1
166 170
@@ -176,6 +180,10 @@
176#define OMAP3430_EN_DES1 (1 << 0) 180#define OMAP3430_EN_DES1 (1 << 0)
177#define OMAP3430_EN_DES1_SHIFT 0 181#define OMAP3430_EN_DES1_SHIFT 0
178 182
183/* CM_ICLKEN3_CORE */
184#define OMAP3430_EN_MAD2D_SHIFT 3
185#define OMAP3430_EN_MAD2D (1 << 3)
186
179/* CM_FCLKEN3_CORE specific bits */ 187/* CM_FCLKEN3_CORE specific bits */
180#define OMAP3430ES2_EN_TS_SHIFT 1 188#define OMAP3430ES2_EN_TS_SHIFT 1
181#define OMAP3430ES2_EN_TS_MASK (1 << 1) 189#define OMAP3430ES2_EN_TS_MASK (1 << 1)
@@ -231,6 +239,8 @@
231#define OMAP3430ES2_ST_CPEFUSE_MASK (1 << 0) 239#define OMAP3430ES2_ST_CPEFUSE_MASK (1 << 0)
232 240
233/* CM_AUTOIDLE1_CORE */ 241/* CM_AUTOIDLE1_CORE */
242#define OMAP3430_AUTO_MODEM (1 << 31)
243#define OMAP3430_AUTO_MODEM_SHIFT 31
234#define OMAP3430ES2_AUTO_MMC3 (1 << 30) 244#define OMAP3430ES2_AUTO_MMC3 (1 << 30)
235#define OMAP3430ES2_AUTO_MMC3_SHIFT 30 245#define OMAP3430ES2_AUTO_MMC3_SHIFT 30
236#define OMAP3430ES2_AUTO_ICR (1 << 29) 246#define OMAP3430ES2_AUTO_ICR (1 << 29)
@@ -287,6 +297,8 @@
287#define OMAP3430_AUTO_HSOTGUSB_SHIFT 4 297#define OMAP3430_AUTO_HSOTGUSB_SHIFT 4
288#define OMAP3430ES1_AUTO_D2D (1 << 3) 298#define OMAP3430ES1_AUTO_D2D (1 << 3)
289#define OMAP3430ES1_AUTO_D2D_SHIFT 3 299#define OMAP3430ES1_AUTO_D2D_SHIFT 3
300#define OMAP3430_AUTO_SAD2D (1 << 3)
301#define OMAP3430_AUTO_SAD2D_SHIFT 3
290#define OMAP3430_AUTO_SSI (1 << 0) 302#define OMAP3430_AUTO_SSI (1 << 0)
291#define OMAP3430_AUTO_SSI_SHIFT 0 303#define OMAP3430_AUTO_SSI_SHIFT 0
292 304
@@ -308,6 +320,8 @@
308#define OMAP3430ES2_AUTO_USBTLL (1 << 2) 320#define OMAP3430ES2_AUTO_USBTLL (1 << 2)
309#define OMAP3430ES2_AUTO_USBTLL_SHIFT 2 321#define OMAP3430ES2_AUTO_USBTLL_SHIFT 2
310#define OMAP3430ES2_AUTO_USBTLL_MASK (1 << 2) 322#define OMAP3430ES2_AUTO_USBTLL_MASK (1 << 2)
323#define OMAP3430_AUTO_MAD2D_SHIFT 3
324#define OMAP3430_AUTO_MAD2D (1 << 3)
311 325
312/* CM_CLKSEL_CORE */ 326/* CM_CLKSEL_CORE */
313#define OMAP3430_CLKSEL_SSI_SHIFT 8 327#define OMAP3430_CLKSEL_SSI_SHIFT 8
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 998c5c45587e..b82863887f10 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -28,7 +28,6 @@
28#define INTC_MIR_CLEAR0 0x0088 28#define INTC_MIR_CLEAR0 0x0088
29#define INTC_MIR_SET0 0x008c 29#define INTC_MIR_SET0 0x008c
30#define INTC_PENDING_IRQ0 0x0098 30#define INTC_PENDING_IRQ0 0x0098
31
32/* Number of IRQ state bits in each MIR register */ 31/* Number of IRQ state bits in each MIR register */
33#define IRQ_BITS_PER_REG 32 32#define IRQ_BITS_PER_REG 32
34 33
@@ -134,7 +133,6 @@ static struct irq_chip omap_irq_chip = {
134 .ack = omap_mask_ack_irq, 133 .ack = omap_mask_ack_irq,
135 .mask = omap_mask_irq, 134 .mask = omap_mask_irq,
136 .unmask = omap_unmask_irq, 135 .unmask = omap_unmask_irq,
137 .disable = omap_mask_irq,
138}; 136};
139 137
140static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) 138static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
@@ -157,6 +155,22 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
157 intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG); 155 intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG);
158} 156}
159 157
158int omap_irq_pending(void)
159{
160 int i;
161
162 for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
163 struct omap_irq_bank *bank = irq_banks + i;
164 int irq;
165
166 for (irq = 0; irq < bank->nr_irqs; irq += 32)
167 if (intc_bank_read_reg(bank, INTC_PENDING_IRQ0 +
168 ((irq >> 5) << 5)))
169 return 1;
170 }
171 return 0;
172}
173
160void __init omap_init_irq(void) 174void __init omap_init_irq(void)
161{ 175{
162 unsigned long nr_of_irqs = 0; 176 unsigned long nr_of_irqs = 0;
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
new file mode 100644
index 000000000000..6cc375a275be
--- /dev/null
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -0,0 +1,152 @@
1/*
2 * OMAP Power Management debug routines
3 *
4 * Copyright (C) 2005 Texas Instruments, Inc.
5 * Copyright (C) 2006-2008 Nokia Corporation
6 *
7 * Written by:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Tony Lindgren
10 * Juha Yrjola
11 * Amit Kucheria <amit.kucheria@nokia.com>
12 * Igor Stoppa <igor.stoppa@nokia.com>
13 * Jouni Hogander
14 *
15 * Based on pm.c for omap2
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation.
20 */
21
22#include <linux/kernel.h>
23#include <linux/timer.h>
24#include <linux/clk.h>
25#include <linux/err.h>
26#include <linux/io.h>
27
28#include <mach/clock.h>
29#include <mach/board.h>
30
31#include "prm.h"
32#include "cm.h"
33#include "pm.h"
34
35int omap2_pm_debug;
36
37#define DUMP_PRM_MOD_REG(mod, reg) \
38 regs[reg_count].name = #mod "." #reg; \
39 regs[reg_count++].val = prm_read_mod_reg(mod, reg)
40#define DUMP_CM_MOD_REG(mod, reg) \
41 regs[reg_count].name = #mod "." #reg; \
42 regs[reg_count++].val = cm_read_mod_reg(mod, reg)
43#define DUMP_PRM_REG(reg) \
44 regs[reg_count].name = #reg; \
45 regs[reg_count++].val = __raw_readl(reg)
46#define DUMP_CM_REG(reg) \
47 regs[reg_count].name = #reg; \
48 regs[reg_count++].val = __raw_readl(reg)
49#define DUMP_INTC_REG(reg, off) \
50 regs[reg_count].name = #reg; \
51 regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
52
53void omap2_pm_dump(int mode, int resume, unsigned int us)
54{
55 struct reg {
56 const char *name;
57 u32 val;
58 } regs[32];
59 int reg_count = 0, i;
60 const char *s1 = NULL, *s2 = NULL;
61
62 if (!resume) {
63#if 0
64 /* MPU */
65 DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
66 DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
67 DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
68 DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
69 DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
70#endif
71#if 0
72 /* INTC */
73 DUMP_INTC_REG(INTC_MIR0, 0x0084);
74 DUMP_INTC_REG(INTC_MIR1, 0x00a4);
75 DUMP_INTC_REG(INTC_MIR2, 0x00c4);
76#endif
77#if 0
78 DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
79 if (cpu_is_omap24xx()) {
80 DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
81 DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
82 OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
83 DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
84 OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
85 }
86 DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
87 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
88 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
89 DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
90 DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
91 DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
92 DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
93#endif
94#if 0
95 /* DSP */
96 if (cpu_is_omap24xx()) {
97 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
98 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
99 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
100 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
101 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
102 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
103 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
104 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
105 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
106 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
107 }
108#endif
109 } else {
110 DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
111 if (cpu_is_omap24xx())
112 DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
113 DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
114 DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
115#if 1
116 DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
117 DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
118 DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
119#endif
120 }
121
122 switch (mode) {
123 case 0:
124 s1 = "full";
125 s2 = "retention";
126 break;
127 case 1:
128 s1 = "MPU";
129 s2 = "retention";
130 break;
131 case 2:
132 s1 = "MPU";
133 s2 = "idle";
134 break;
135 }
136
137 if (!resume)
138#ifdef CONFIG_NO_HZ
139 printk(KERN_INFO
140 "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
141 jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
142 jiffies));
143#else
144 printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
145#endif
146 else
147 printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
148 us / 1000, us % 1000);
149
150 for (i = 0; i < reg_count; i++)
151 printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
152}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
deleted file mode 100644
index ea8ceaed09cb..000000000000
--- a/arch/arm/mach-omap2/pm.c
+++ /dev/null
@@ -1,111 +0,0 @@
1/*
2 * linux/arch/arm/mach-omap2/pm.c
3 *
4 * OMAP2 Power Management Routines
5 *
6 * Copyright (C) 2006 Nokia Corporation
7 * Tony Lindgren <tony@atomide.com>
8 *
9 * Copyright (C) 2005 Texas Instruments, Inc.
10 * Richard Woodruff <r-woodruff2@ti.com>
11 *
12 * Based on pm.c for omap1
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/suspend.h>
20#include <linux/sched.h>
21#include <linux/proc_fs.h>
22#include <linux/interrupt.h>
23#include <linux/sysfs.h>
24#include <linux/module.h>
25#include <linux/delay.h>
26#include <linux/clk.h>
27#include <linux/io.h>
28
29#include <asm/irq.h>
30#include <asm/atomic.h>
31#include <asm/mach/time.h>
32#include <asm/mach/irq.h>
33
34#include <mach/irqs.h>
35#include <mach/clock.h>
36#include <mach/sram.h>
37#include <mach/pm.h>
38
39static struct clk *vclk;
40static void (*omap2_sram_idle)(void);
41static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
42static void (*saved_idle)(void);
43
44extern void __init pmdomain_init(void);
45extern void pmdomain_set_autoidle(void);
46
47static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
48
49void omap2_pm_idle(void)
50{
51 local_irq_disable();
52 local_fiq_disable();
53 if (need_resched()) {
54 local_fiq_enable();
55 local_irq_enable();
56 return;
57 }
58
59 omap2_sram_idle();
60 local_fiq_enable();
61 local_irq_enable();
62}
63
64static int omap2_pm_prepare(void)
65{
66 /* We cannot sleep in idle until we have resumed */
67 saved_idle = pm_idle;
68 pm_idle = NULL;
69 return 0;
70}
71
72static int omap2_pm_suspend(void)
73{
74 return 0;
75}
76
77static int omap2_pm_enter(suspend_state_t state)
78{
79 int ret = 0;
80
81 switch (state)
82 {
83 case PM_SUSPEND_STANDBY:
84 case PM_SUSPEND_MEM:
85 ret = omap2_pm_suspend();
86 break;
87 default:
88 ret = -EINVAL;
89 }
90
91 return ret;
92}
93
94static void omap2_pm_finish(void)
95{
96 pm_idle = saved_idle;
97}
98
99static struct platform_suspend_ops omap_pm_ops = {
100 .prepare = omap2_pm_prepare,
101 .enter = omap2_pm_enter,
102 .finish = omap2_pm_finish,
103 .valid = suspend_valid_only_mem,
104};
105
106static int __init omap2_pm_init(void)
107{
108 return 0;
109}
110
111__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
new file mode 100644
index 000000000000..f7b3baf76678
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.h
@@ -0,0 +1,38 @@
1/*
2 * OMAP2/3 Power Management Routines
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Jouni Hogander
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#ifndef __ARCH_ARM_MACH_OMAP2_PM_H
12#define __ARCH_ARM_MACH_OMAP2_PM_H
13
14extern int omap2_pm_init(void);
15extern int omap3_pm_init(void);
16
17#ifdef CONFIG_PM_DEBUG
18extern void omap2_pm_dump(int mode, int resume, unsigned int us);
19extern int omap2_pm_debug;
20#else
21#define omap2_pm_dump(mode, resume, us) do {} while (0);
22#define omap2_pm_debug 0
23#endif /* CONFIG_PM_DEBUG */
24
25extern void omap24xx_idle_loop_suspend(void);
26
27extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
28 void __iomem *sdrc_power);
29extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
30extern void save_secure_ram_context(u32 *addr);
31
32extern unsigned int omap24xx_idle_loop_suspend_sz;
33extern unsigned int omap34xx_suspend_sz;
34extern unsigned int save_secure_ram_context_sz;
35extern unsigned int omap24xx_cpu_suspend_sz;
36extern unsigned int omap34xx_cpu_suspend_sz;
37
38#endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
new file mode 100644
index 000000000000..db1025562fb0
--- /dev/null
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -0,0 +1,549 @@
1/*
2 * OMAP2 Power Management Routines
3 *
4 * Copyright (C) 2005 Texas Instruments, Inc.
5 * Copyright (C) 2006-2008 Nokia Corporation
6 *
7 * Written by:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Tony Lindgren
10 * Juha Yrjola
11 * Amit Kucheria <amit.kucheria@nokia.com>
12 * Igor Stoppa <igor.stoppa@nokia.com>
13 *
14 * Based on pm.c for omap1
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2 as
18 * published by the Free Software Foundation.
19 */
20
21#include <linux/suspend.h>
22#include <linux/sched.h>
23#include <linux/proc_fs.h>
24#include <linux/interrupt.h>
25#include <linux/sysfs.h>
26#include <linux/module.h>
27#include <linux/delay.h>
28#include <linux/clk.h>
29#include <linux/io.h>
30#include <linux/irq.h>
31#include <linux/time.h>
32#include <linux/gpio.h>
33
34#include <asm/mach/time.h>
35#include <asm/mach/irq.h>
36#include <asm/mach-types.h>
37
38#include <mach/irqs.h>
39#include <mach/clock.h>
40#include <mach/sram.h>
41#include <mach/control.h>
42#include <mach/mux.h>
43#include <mach/dma.h>
44#include <mach/board.h>
45
46#include "prm.h"
47#include "prm-regbits-24xx.h"
48#include "cm.h"
49#include "cm-regbits-24xx.h"
50#include "sdrc.h"
51#include "pm.h"
52
53#include <mach/powerdomain.h>
54#include <mach/clockdomain.h>
55
56static void (*omap2_sram_idle)(void);
57static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
58 void __iomem *sdrc_power);
59
60static struct powerdomain *mpu_pwrdm;
61static struct powerdomain *core_pwrdm;
62
63static struct clockdomain *dsp_clkdm;
64static struct clockdomain *gfx_clkdm;
65
66static struct clk *osc_ck, *emul_ck;
67
68static int omap2_fclks_active(void)
69{
70 u32 f1, f2;
71
72 f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
73 f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
74
75 /* Ignore UART clocks. These are handled by UART core (serial.c) */
76 f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2);
77 f2 &= ~OMAP24XX_EN_UART3;
78
79 if (f1 | f2)
80 return 1;
81 return 0;
82}
83
84static void omap2_enter_full_retention(void)
85{
86 u32 l;
87 struct timespec ts_preidle, ts_postidle, ts_idle;
88
89 /* There is 1 reference hold for all children of the oscillator
90 * clock, the following will remove it. If no one else uses the
91 * oscillator itself it will be disabled if/when we enter retention
92 * mode.
93 */
94 clk_disable(osc_ck);
95
96 /* Clear old wake-up events */
97 /* REVISIT: These write to reserved bits? */
98 prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
99 prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
100 prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
101
102 /*
103 * Set MPU powerdomain's next power state to RETENTION;
104 * preserve logic state during retention
105 */
106 pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
107 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
108
109 /* Workaround to kill USB */
110 l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
111 omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
112
113 omap2_gpio_prepare_for_retention();
114
115 if (omap2_pm_debug) {
116 omap2_pm_dump(0, 0, 0);
117 getnstimeofday(&ts_preidle);
118 }
119
120 /* One last check for pending IRQs to avoid extra latency due
121 * to sleeping unnecessarily. */
122 if (omap_irq_pending())
123 goto no_sleep;
124
125 omap_uart_prepare_idle(0);
126 omap_uart_prepare_idle(1);
127 omap_uart_prepare_idle(2);
128
129 /* Jump to SRAM suspend code */
130 omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
131 OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
132 OMAP_SDRC_REGADDR(SDRC_POWER));
133
134 omap_uart_resume_idle(2);
135 omap_uart_resume_idle(1);
136 omap_uart_resume_idle(0);
137
138no_sleep:
139 if (omap2_pm_debug) {
140 unsigned long long tmp;
141
142 getnstimeofday(&ts_postidle);
143 ts_idle = timespec_sub(ts_postidle, ts_preidle);
144 tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
145 omap2_pm_dump(0, 1, tmp);
146 }
147 omap2_gpio_resume_after_retention();
148
149 clk_enable(osc_ck);
150
151 /* clear CORE wake-up events */
152 prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
153 prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
154
155 /* wakeup domain events - bit 1: GPT1, bit5 GPIO */
156 prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
157
158 /* MPU domain wake events */
159 l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
160 if (l & 0x01)
161 prm_write_mod_reg(0x01, OCP_MOD,
162 OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
163 if (l & 0x20)
164 prm_write_mod_reg(0x20, OCP_MOD,
165 OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
166
167 /* Mask future PRCM-to-MPU interrupts */
168 prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
169}
170
171static int omap2_i2c_active(void)
172{
173 u32 l;
174
175 l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
176 return l & (OMAP2420_EN_I2C2 | OMAP2420_EN_I2C1);
177}
178
179static int sti_console_enabled;
180
181static int omap2_allow_mpu_retention(void)
182{
183 u32 l;
184
185 /* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
186 l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
187 if (l & (OMAP2420_EN_MMC | OMAP24XX_EN_UART2 |
188 OMAP24XX_EN_UART1 | OMAP24XX_EN_MCSPI2 |
189 OMAP24XX_EN_MCSPI1 | OMAP24XX_EN_DSS1))
190 return 0;
191 /* Check for UART3. */
192 l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
193 if (l & OMAP24XX_EN_UART3)
194 return 0;
195 if (sti_console_enabled)
196 return 0;
197
198 return 1;
199}
200
201static void omap2_enter_mpu_retention(void)
202{
203 int only_idle = 0;
204 struct timespec ts_preidle, ts_postidle, ts_idle;
205
206 /* Putting MPU into the WFI state while a transfer is active
207 * seems to cause the I2C block to timeout. Why? Good question. */
208 if (omap2_i2c_active())
209 return;
210
211 /* The peripherals seem not to be able to wake up the MPU when
212 * it is in retention mode. */
213 if (omap2_allow_mpu_retention()) {
214 /* REVISIT: These write to reserved bits? */
215 prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
216 prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
217 prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
218
219 /* Try to enter MPU retention */
220 prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
221 OMAP_LOGICRETSTATE,
222 MPU_MOD, PM_PWSTCTRL);
223 } else {
224 /* Block MPU retention */
225
226 prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
227 only_idle = 1;
228 }
229
230 if (omap2_pm_debug) {
231 omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
232 getnstimeofday(&ts_preidle);
233 }
234
235 omap2_sram_idle();
236
237 if (omap2_pm_debug) {
238 unsigned long long tmp;
239
240 getnstimeofday(&ts_postidle);
241 ts_idle = timespec_sub(ts_postidle, ts_preidle);
242 tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
243 omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
244 }
245}
246
247static int omap2_can_sleep(void)
248{
249 if (omap2_fclks_active())
250 return 0;
251 if (osc_ck->usecount > 1)
252 return 0;
253 if (omap_dma_running())
254 return 0;
255
256 return 1;
257}
258
259static void omap2_pm_idle(void)
260{
261 local_irq_disable();
262 local_fiq_disable();
263
264 if (!omap2_can_sleep()) {
265 if (omap_irq_pending())
266 goto out;
267 omap2_enter_mpu_retention();
268 goto out;
269 }
270
271 if (omap_irq_pending())
272 goto out;
273
274 omap2_enter_full_retention();
275
276out:
277 local_fiq_enable();
278 local_irq_enable();
279}
280
281static int omap2_pm_prepare(void)
282{
283 /* We cannot sleep in idle until we have resumed */
284 disable_hlt();
285 return 0;
286}
287
288static int omap2_pm_suspend(void)
289{
290 u32 wken_wkup, mir1;
291
292 wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
293 prm_write_mod_reg(wken_wkup & ~OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN);
294
295 /* Mask GPT1 */
296 mir1 = omap_readl(0x480fe0a4);
297 omap_writel(1 << 5, 0x480fe0ac);
298
299 omap_uart_prepare_suspend();
300 omap2_enter_full_retention();
301
302 omap_writel(mir1, 0x480fe0a4);
303 prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
304
305 return 0;
306}
307
308static int omap2_pm_enter(suspend_state_t state)
309{
310 int ret = 0;
311
312 switch (state) {
313 case PM_SUSPEND_STANDBY:
314 case PM_SUSPEND_MEM:
315 ret = omap2_pm_suspend();
316 break;
317 default:
318 ret = -EINVAL;
319 }
320
321 return ret;
322}
323
324static void omap2_pm_finish(void)
325{
326 enable_hlt();
327}
328
329static struct platform_suspend_ops omap_pm_ops = {
330 .prepare = omap2_pm_prepare,
331 .enter = omap2_pm_enter,
332 .finish = omap2_pm_finish,
333 .valid = suspend_valid_only_mem,
334};
335
336static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm)
337{
338 omap2_clkdm_allow_idle(clkdm);
339 return 0;
340}
341
342static void __init prcm_setup_regs(void)
343{
344 int i, num_mem_banks;
345 struct powerdomain *pwrdm;
346
347 /* Enable autoidle */
348 prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
349 OMAP2_PRCM_SYSCONFIG_OFFSET);
350
351 /* Set all domain wakeup dependencies */
352 prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
353 prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP);
354 prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
355 prm_write_mod_reg(0, CORE_MOD, PM_WKDEP);
356 if (cpu_is_omap2430())
357 prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
358
359 /*
360 * Set CORE powerdomain memory banks to retain their contents
361 * during RETENTION
362 */
363 num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
364 for (i = 0; i < num_mem_banks; i++)
365 pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
366
367 /* Set CORE powerdomain's next power state to RETENTION */
368 pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
369
370 /*
371 * Set MPU powerdomain's next power state to RETENTION;
372 * preserve logic state during retention
373 */
374 pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
375 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
376
377 /* Force-power down DSP, GFX powerdomains */
378
379 pwrdm = clkdm_get_pwrdm(dsp_clkdm);
380 pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
381 omap2_clkdm_sleep(dsp_clkdm);
382
383 pwrdm = clkdm_get_pwrdm(gfx_clkdm);
384 pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
385 omap2_clkdm_sleep(gfx_clkdm);
386
387 /* Enable clockdomain hardware-supervised control for all clkdms */
388 clkdm_for_each(_pm_clkdm_enable_hwsup);
389
390 /* Enable clock autoidle for all domains */
391 cm_write_mod_reg(OMAP24XX_AUTO_CAM |
392 OMAP24XX_AUTO_MAILBOXES |
393 OMAP24XX_AUTO_WDT4 |
394 OMAP2420_AUTO_WDT3 |
395 OMAP24XX_AUTO_MSPRO |
396 OMAP2420_AUTO_MMC |
397 OMAP24XX_AUTO_FAC |
398 OMAP2420_AUTO_EAC |
399 OMAP24XX_AUTO_HDQ |
400 OMAP24XX_AUTO_UART2 |
401 OMAP24XX_AUTO_UART1 |
402 OMAP24XX_AUTO_I2C2 |
403 OMAP24XX_AUTO_I2C1 |
404 OMAP24XX_AUTO_MCSPI2 |
405 OMAP24XX_AUTO_MCSPI1 |
406 OMAP24XX_AUTO_MCBSP2 |
407 OMAP24XX_AUTO_MCBSP1 |
408 OMAP24XX_AUTO_GPT12 |
409 OMAP24XX_AUTO_GPT11 |
410 OMAP24XX_AUTO_GPT10 |
411 OMAP24XX_AUTO_GPT9 |
412 OMAP24XX_AUTO_GPT8 |
413 OMAP24XX_AUTO_GPT7 |
414 OMAP24XX_AUTO_GPT6 |
415 OMAP24XX_AUTO_GPT5 |
416 OMAP24XX_AUTO_GPT4 |
417 OMAP24XX_AUTO_GPT3 |
418 OMAP24XX_AUTO_GPT2 |
419 OMAP2420_AUTO_VLYNQ |
420 OMAP24XX_AUTO_DSS,
421 CORE_MOD, CM_AUTOIDLE1);
422 cm_write_mod_reg(OMAP24XX_AUTO_UART3 |
423 OMAP24XX_AUTO_SSI |
424 OMAP24XX_AUTO_USB,
425 CORE_MOD, CM_AUTOIDLE2);
426 cm_write_mod_reg(OMAP24XX_AUTO_SDRC |
427 OMAP24XX_AUTO_GPMC |
428 OMAP24XX_AUTO_SDMA,
429 CORE_MOD, CM_AUTOIDLE3);
430 cm_write_mod_reg(OMAP24XX_AUTO_PKA |
431 OMAP24XX_AUTO_AES |
432 OMAP24XX_AUTO_RNG |
433 OMAP24XX_AUTO_SHA |
434 OMAP24XX_AUTO_DES,
435 CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
436
437 cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
438
439 /* Put DPLL and both APLLs into autoidle mode */
440 cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
441 (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
442 (0x03 << OMAP24XX_AUTO_54M_SHIFT),
443 PLL_MOD, CM_AUTOIDLE);
444
445 cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL |
446 OMAP24XX_AUTO_WDT1 |
447 OMAP24XX_AUTO_MPU_WDT |
448 OMAP24XX_AUTO_GPIOS |
449 OMAP24XX_AUTO_32KSYNC |
450 OMAP24XX_AUTO_GPT1,
451 WKUP_MOD, CM_AUTOIDLE);
452
453 /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
454 * stabilisation */
455 prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
456 OMAP2_PRCM_CLKSSETUP_OFFSET);
457
458 /* Configure automatic voltage transition */
459 prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
460 OMAP2_PRCM_VOLTSETUP_OFFSET);
461 prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT |
462 (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
463 OMAP24XX_MEMRETCTRL |
464 (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
465 (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
466 OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
467
468 /* Enable wake-up events */
469 prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1,
470 WKUP_MOD, PM_WKEN);
471}
472
473int __init omap2_pm_init(void)
474{
475 u32 l;
476
477 if (!cpu_is_omap24xx())
478 return -ENODEV;
479
480 printk(KERN_INFO "Power Management for OMAP2 initializing\n");
481 l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
482 printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
483
484 /* Look up important powerdomains, clockdomains */
485
486 mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
487 if (!mpu_pwrdm)
488 pr_err("PM: mpu_pwrdm not found\n");
489
490 core_pwrdm = pwrdm_lookup("core_pwrdm");
491 if (!core_pwrdm)
492 pr_err("PM: core_pwrdm not found\n");
493
494 dsp_clkdm = clkdm_lookup("dsp_clkdm");
495 if (!dsp_clkdm)
496 pr_err("PM: mpu_clkdm not found\n");
497
498 gfx_clkdm = clkdm_lookup("gfx_clkdm");
499 if (!gfx_clkdm)
500 pr_err("PM: gfx_clkdm not found\n");
501
502
503 osc_ck = clk_get(NULL, "osc_ck");
504 if (IS_ERR(osc_ck)) {
505 printk(KERN_ERR "could not get osc_ck\n");
506 return -ENODEV;
507 }
508
509 if (cpu_is_omap242x()) {
510 emul_ck = clk_get(NULL, "emul_ck");
511 if (IS_ERR(emul_ck)) {
512 printk(KERN_ERR "could not get emul_ck\n");
513 clk_put(osc_ck);
514 return -ENODEV;
515 }
516 }
517
518 prcm_setup_regs();
519
520 /* Hack to prevent MPU retention when STI console is enabled. */
521 {
522 const struct omap_sti_console_config *sti;
523
524 sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
525 struct omap_sti_console_config);
526 if (sti != NULL && sti->enable)
527 sti_console_enabled = 1;
528 }
529
530 /*
531 * We copy the assembler sleep/wakeup routines to SRAM.
532 * These routines need to be in SRAM as that's the only
533 * memory the MPU can see when it wakes up.
534 */
535 if (cpu_is_omap24xx()) {
536 omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
537 omap24xx_idle_loop_suspend_sz);
538
539 omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
540 omap24xx_cpu_suspend_sz);
541 }
542
543 suspend_set_ops(&omap_pm_ops);
544 pm_idle = omap2_pm_idle;
545
546 return 0;
547}
548
549late_initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
new file mode 100644
index 000000000000..841d4c5ed8be
--- /dev/null
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -0,0 +1,710 @@
1/*
2 * OMAP3 Power Management Routines
3 *
4 * Copyright (C) 2006-2008 Nokia Corporation
5 * Tony Lindgren <tony@atomide.com>
6 * Jouni Hogander
7 *
8 * Copyright (C) 2005 Texas Instruments, Inc.
9 * Richard Woodruff <r-woodruff2@ti.com>
10 *
11 * Based on pm.c for omap1
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/pm.h>
19#include <linux/suspend.h>
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <linux/list.h>
23#include <linux/err.h>
24#include <linux/gpio.h>
25
26#include <mach/sram.h>
27#include <mach/clockdomain.h>
28#include <mach/powerdomain.h>
29#include <mach/control.h>
30#include <mach/serial.h>
31
32#include "cm.h"
33#include "cm-regbits-34xx.h"
34#include "prm-regbits-34xx.h"
35
36#include "prm.h"
37#include "pm.h"
38
39struct power_state {
40 struct powerdomain *pwrdm;
41 u32 next_state;
42 u32 saved_state;
43 struct list_head node;
44};
45
46static LIST_HEAD(pwrst_list);
47
48static void (*_omap_sram_idle)(u32 *addr, int save_state);
49
50static struct powerdomain *mpu_pwrdm;
51
52/* PRCM Interrupt Handler for wakeups */
53static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
54{
55 u32 wkst, irqstatus_mpu;
56 u32 fclk, iclk;
57
58 /* WKUP */
59 wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
60 if (wkst) {
61 iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
62 fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
63 cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN);
64 cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN);
65 prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST);
66 while (prm_read_mod_reg(WKUP_MOD, PM_WKST))
67 cpu_relax();
68 cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN);
69 cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN);
70 }
71
72 /* CORE */
73 wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1);
74 if (wkst) {
75 iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
76 fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
77 cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1);
78 cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1);
79 prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1);
80 while (prm_read_mod_reg(CORE_MOD, PM_WKST1))
81 cpu_relax();
82 cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1);
83 cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1);
84 }
85 wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3);
86 if (wkst) {
87 iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
88 fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
89 cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3);
90 cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
91 prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3);
92 while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3))
93 cpu_relax();
94 cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3);
95 cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
96 }
97
98 /* PER */
99 wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST);
100 if (wkst) {
101 iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
102 fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
103 cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN);
104 cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN);
105 prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST);
106 while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST))
107 cpu_relax();
108 cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN);
109 cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN);
110 }
111
112 if (omap_rev() > OMAP3430_REV_ES1_0) {
113 /* USBHOST */
114 wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST);
115 if (wkst) {
116 iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
117 CM_ICLKEN);
118 fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
119 CM_FCLKEN);
120 cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
121 CM_ICLKEN);
122 cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
123 CM_FCLKEN);
124 prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD,
125 PM_WKST);
126 while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
127 PM_WKST))
128 cpu_relax();
129 cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD,
130 CM_ICLKEN);
131 cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD,
132 CM_FCLKEN);
133 }
134 }
135
136 irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
137 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
138 prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
139 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
140
141 while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET))
142 cpu_relax();
143
144 return IRQ_HANDLED;
145}
146
147static void omap_sram_idle(void)
148{
149 /* Variable to tell what needs to be saved and restored
150 * in omap_sram_idle*/
151 /* save_state = 0 => Nothing to save and restored */
152 /* save_state = 1 => Only L1 and logic lost */
153 /* save_state = 2 => Only L2 lost */
154 /* save_state = 3 => L1, L2 and logic lost */
155 int save_state = 0, mpu_next_state;
156
157 if (!_omap_sram_idle)
158 return;
159
160 mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
161 switch (mpu_next_state) {
162 case PWRDM_POWER_RET:
163 /* No need to save context */
164 save_state = 0;
165 break;
166 default:
167 /* Invalid state */
168 printk(KERN_ERR "Invalid mpu state in sram_idle\n");
169 return;
170 }
171 omap2_gpio_prepare_for_retention();
172 omap_uart_prepare_idle(0);
173 omap_uart_prepare_idle(1);
174 omap_uart_prepare_idle(2);
175
176 _omap_sram_idle(NULL, save_state);
177 cpu_init();
178
179 omap_uart_resume_idle(2);
180 omap_uart_resume_idle(1);
181 omap_uart_resume_idle(0);
182 omap2_gpio_resume_after_retention();
183}
184
185/*
186 * Check if functional clocks are enabled before entering
187 * sleep. This function could be behind CONFIG_PM_DEBUG
188 * when all drivers are configuring their sysconfig registers
189 * properly and using their clocks properly.
190 */
191static int omap3_fclks_active(void)
192{
193 u32 fck_core1 = 0, fck_core3 = 0, fck_sgx = 0, fck_dss = 0,
194 fck_cam = 0, fck_per = 0, fck_usbhost = 0;
195
196 fck_core1 = cm_read_mod_reg(CORE_MOD,
197 CM_FCLKEN1);
198 if (omap_rev() > OMAP3430_REV_ES1_0) {
199 fck_core3 = cm_read_mod_reg(CORE_MOD,
200 OMAP3430ES2_CM_FCLKEN3);
201 fck_sgx = cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
202 CM_FCLKEN);
203 fck_usbhost = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
204 CM_FCLKEN);
205 } else
206 fck_sgx = cm_read_mod_reg(GFX_MOD,
207 OMAP3430ES2_CM_FCLKEN3);
208 fck_dss = cm_read_mod_reg(OMAP3430_DSS_MOD,
209 CM_FCLKEN);
210 fck_cam = cm_read_mod_reg(OMAP3430_CAM_MOD,
211 CM_FCLKEN);
212 fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
213 CM_FCLKEN);
214
215 /* Ignore UART clocks. These are handled by UART core (serial.c) */
216 fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2);
217 fck_per &= ~OMAP3430_EN_UART3;
218
219 if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
220 fck_cam | fck_per | fck_usbhost)
221 return 1;
222 return 0;
223}
224
225static int omap3_can_sleep(void)
226{
227 if (!omap_uart_can_sleep())
228 return 0;
229 if (omap3_fclks_active())
230 return 0;
231 return 1;
232}
233
234/* This sets pwrdm state (other than mpu & core. Currently only ON &
235 * RET are supported. Function is assuming that clkdm doesn't have
236 * hw_sup mode enabled. */
237static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
238{
239 u32 cur_state;
240 int sleep_switch = 0;
241 int ret = 0;
242
243 if (pwrdm == NULL || IS_ERR(pwrdm))
244 return -EINVAL;
245
246 while (!(pwrdm->pwrsts & (1 << state))) {
247 if (state == PWRDM_POWER_OFF)
248 return ret;
249 state--;
250 }
251
252 cur_state = pwrdm_read_next_pwrst(pwrdm);
253 if (cur_state == state)
254 return ret;
255
256 if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
257 omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
258 sleep_switch = 1;
259 pwrdm_wait_transition(pwrdm);
260 }
261
262 ret = pwrdm_set_next_pwrst(pwrdm, state);
263 if (ret) {
264 printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
265 pwrdm->name);
266 goto err;
267 }
268
269 if (sleep_switch) {
270 omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
271 pwrdm_wait_transition(pwrdm);
272 }
273
274err:
275 return ret;
276}
277
278static void omap3_pm_idle(void)
279{
280 local_irq_disable();
281 local_fiq_disable();
282
283 if (!omap3_can_sleep())
284 goto out;
285
286 if (omap_irq_pending())
287 goto out;
288
289 omap_sram_idle();
290
291out:
292 local_fiq_enable();
293 local_irq_enable();
294}
295
296static int omap3_pm_prepare(void)
297{
298 disable_hlt();
299 return 0;
300}
301
302static int omap3_pm_suspend(void)
303{
304 struct power_state *pwrst;
305 int state, ret = 0;
306
307 /* Read current next_pwrsts */
308 list_for_each_entry(pwrst, &pwrst_list, node)
309 pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
310 /* Set ones wanted by suspend */
311 list_for_each_entry(pwrst, &pwrst_list, node) {
312 if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
313 goto restore;
314 if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
315 goto restore;
316 }
317
318 omap_uart_prepare_suspend();
319 omap_sram_idle();
320
321restore:
322 /* Restore next_pwrsts */
323 list_for_each_entry(pwrst, &pwrst_list, node) {
324 set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
325 state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
326 if (state > pwrst->next_state) {
327 printk(KERN_INFO "Powerdomain (%s) didn't enter "
328 "target state %d\n",
329 pwrst->pwrdm->name, pwrst->next_state);
330 ret = -1;
331 }
332 }
333 if (ret)
334 printk(KERN_ERR "Could not enter target state in pm_suspend\n");
335 else
336 printk(KERN_INFO "Successfully put all powerdomains "
337 "to target state\n");
338
339 return ret;
340}
341
342static int omap3_pm_enter(suspend_state_t state)
343{
344 int ret = 0;
345
346 switch (state) {
347 case PM_SUSPEND_STANDBY:
348 case PM_SUSPEND_MEM:
349 ret = omap3_pm_suspend();
350 break;
351 default:
352 ret = -EINVAL;
353 }
354
355 return ret;
356}
357
358static void omap3_pm_finish(void)
359{
360 enable_hlt();
361}
362
363static struct platform_suspend_ops omap_pm_ops = {
364 .prepare = omap3_pm_prepare,
365 .enter = omap3_pm_enter,
366 .finish = omap3_pm_finish,
367 .valid = suspend_valid_only_mem,
368};
369
370
371/**
372 * omap3_iva_idle(): ensure IVA is in idle so it can be put into
373 * retention
374 *
375 * In cases where IVA2 is activated by bootcode, it may prevent
376 * full-chip retention or off-mode because it is not idle. This
377 * function forces the IVA2 into idle state so it can go
378 * into retention/off and thus allow full-chip retention/off.
379 *
380 **/
381static void __init omap3_iva_idle(void)
382{
383 /* ensure IVA2 clock is disabled */
384 cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
385
386 /* if no clock activity, nothing else to do */
387 if (!(cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
388 OMAP3430_CLKACTIVITY_IVA2_MASK))
389 return;
390
391 /* Reset IVA2 */
392 prm_write_mod_reg(OMAP3430_RST1_IVA2 |
393 OMAP3430_RST2_IVA2 |
394 OMAP3430_RST3_IVA2,
395 OMAP3430_IVA2_MOD, RM_RSTCTRL);
396
397 /* Enable IVA2 clock */
398 cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2,
399 OMAP3430_IVA2_MOD, CM_FCLKEN);
400
401 /* Set IVA2 boot mode to 'idle' */
402 omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
403 OMAP343X_CONTROL_IVA2_BOOTMOD);
404
405 /* Un-reset IVA2 */
406 prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL);
407
408 /* Disable IVA2 clock */
409 cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
410
411 /* Reset IVA2 */
412 prm_write_mod_reg(OMAP3430_RST1_IVA2 |
413 OMAP3430_RST2_IVA2 |
414 OMAP3430_RST3_IVA2,
415 OMAP3430_IVA2_MOD, RM_RSTCTRL);
416}
417
418static void __init omap3_d2d_idle(void)
419{
420 u16 mask, padconf;
421
422 /* In a stand alone OMAP3430 where there is not a stacked
423 * modem for the D2D Idle Ack and D2D MStandby must be pulled
424 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
425 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */
426 mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
427 padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
428 padconf |= mask;
429 omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
430
431 padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
432 padconf |= mask;
433 omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
434
435 /* reset modem */
436 prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
437 OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
438 CORE_MOD, RM_RSTCTRL);
439 prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
440}
441
442static void __init prcm_setup_regs(void)
443{
444 /* XXX Reset all wkdeps. This should be done when initializing
445 * powerdomains */
446 prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
447 prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
448 prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
449 prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
450 prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
451 prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
452 if (omap_rev() > OMAP3430_REV_ES1_0) {
453 prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
454 prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
455 } else
456 prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
457
458 /*
459 * Enable interface clock autoidle for all modules.
460 * Note that in the long run this should be done by clockfw
461 */
462 cm_write_mod_reg(
463 OMAP3430_AUTO_MODEM |
464 OMAP3430ES2_AUTO_MMC3 |
465 OMAP3430ES2_AUTO_ICR |
466 OMAP3430_AUTO_AES2 |
467 OMAP3430_AUTO_SHA12 |
468 OMAP3430_AUTO_DES2 |
469 OMAP3430_AUTO_MMC2 |
470 OMAP3430_AUTO_MMC1 |
471 OMAP3430_AUTO_MSPRO |
472 OMAP3430_AUTO_HDQ |
473 OMAP3430_AUTO_MCSPI4 |
474 OMAP3430_AUTO_MCSPI3 |
475 OMAP3430_AUTO_MCSPI2 |
476 OMAP3430_AUTO_MCSPI1 |
477 OMAP3430_AUTO_I2C3 |
478 OMAP3430_AUTO_I2C2 |
479 OMAP3430_AUTO_I2C1 |
480 OMAP3430_AUTO_UART2 |
481 OMAP3430_AUTO_UART1 |
482 OMAP3430_AUTO_GPT11 |
483 OMAP3430_AUTO_GPT10 |
484 OMAP3430_AUTO_MCBSP5 |
485 OMAP3430_AUTO_MCBSP1 |
486 OMAP3430ES1_AUTO_FAC | /* This is es1 only */
487 OMAP3430_AUTO_MAILBOXES |
488 OMAP3430_AUTO_OMAPCTRL |
489 OMAP3430ES1_AUTO_FSHOSTUSB |
490 OMAP3430_AUTO_HSOTGUSB |
491 OMAP3430_AUTO_SAD2D |
492 OMAP3430_AUTO_SSI,
493 CORE_MOD, CM_AUTOIDLE1);
494
495 cm_write_mod_reg(
496 OMAP3430_AUTO_PKA |
497 OMAP3430_AUTO_AES1 |
498 OMAP3430_AUTO_RNG |
499 OMAP3430_AUTO_SHA11 |
500 OMAP3430_AUTO_DES1,
501 CORE_MOD, CM_AUTOIDLE2);
502
503 if (omap_rev() > OMAP3430_REV_ES1_0) {
504 cm_write_mod_reg(
505 OMAP3430_AUTO_MAD2D |
506 OMAP3430ES2_AUTO_USBTLL,
507 CORE_MOD, CM_AUTOIDLE3);
508 }
509
510 cm_write_mod_reg(
511 OMAP3430_AUTO_WDT2 |
512 OMAP3430_AUTO_WDT1 |
513 OMAP3430_AUTO_GPIO1 |
514 OMAP3430_AUTO_32KSYNC |
515 OMAP3430_AUTO_GPT12 |
516 OMAP3430_AUTO_GPT1 ,
517 WKUP_MOD, CM_AUTOIDLE);
518
519 cm_write_mod_reg(
520 OMAP3430_AUTO_DSS,
521 OMAP3430_DSS_MOD,
522 CM_AUTOIDLE);
523
524 cm_write_mod_reg(
525 OMAP3430_AUTO_CAM,
526 OMAP3430_CAM_MOD,
527 CM_AUTOIDLE);
528
529 cm_write_mod_reg(
530 OMAP3430_AUTO_GPIO6 |
531 OMAP3430_AUTO_GPIO5 |
532 OMAP3430_AUTO_GPIO4 |
533 OMAP3430_AUTO_GPIO3 |
534 OMAP3430_AUTO_GPIO2 |
535 OMAP3430_AUTO_WDT3 |
536 OMAP3430_AUTO_UART3 |
537 OMAP3430_AUTO_GPT9 |
538 OMAP3430_AUTO_GPT8 |
539 OMAP3430_AUTO_GPT7 |
540 OMAP3430_AUTO_GPT6 |
541 OMAP3430_AUTO_GPT5 |
542 OMAP3430_AUTO_GPT4 |
543 OMAP3430_AUTO_GPT3 |
544 OMAP3430_AUTO_GPT2 |
545 OMAP3430_AUTO_MCBSP4 |
546 OMAP3430_AUTO_MCBSP3 |
547 OMAP3430_AUTO_MCBSP2,
548 OMAP3430_PER_MOD,
549 CM_AUTOIDLE);
550
551 if (omap_rev() > OMAP3430_REV_ES1_0) {
552 cm_write_mod_reg(
553 OMAP3430ES2_AUTO_USBHOST,
554 OMAP3430ES2_USBHOST_MOD,
555 CM_AUTOIDLE);
556 }
557
558 /*
559 * Set all plls to autoidle. This is needed until autoidle is
560 * enabled by clockfw
561 */
562 cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
563 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
564 cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
565 MPU_MOD,
566 CM_AUTOIDLE2);
567 cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
568 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
569 PLL_MOD,
570 CM_AUTOIDLE);
571 cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
572 PLL_MOD,
573 CM_AUTOIDLE2);
574
575 /*
576 * Enable control of expternal oscillator through
577 * sys_clkreq. In the long run clock framework should
578 * take care of this.
579 */
580 prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
581 1 << OMAP_AUTOEXTCLKMODE_SHIFT,
582 OMAP3430_GR_MOD,
583 OMAP3_PRM_CLKSRC_CTRL_OFFSET);
584
585 /* setup wakup source */
586 prm_write_mod_reg(OMAP3430_EN_IO | OMAP3430_EN_GPIO1 |
587 OMAP3430_EN_GPT1 | OMAP3430_EN_GPT12,
588 WKUP_MOD, PM_WKEN);
589 /* No need to write EN_IO, that is always enabled */
590 prm_write_mod_reg(OMAP3430_EN_GPIO1 | OMAP3430_EN_GPT1 |
591 OMAP3430_EN_GPT12,
592 WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
593 /* For some reason IO doesn't generate wakeup event even if
594 * it is selected to mpu wakeup goup */
595 prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
596 OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
597
598 /* Don't attach IVA interrupts */
599 prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
600 prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
601 prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
602 prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
603
604 /* Clear any pending 'reset' flags */
605 prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
606 prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
607 prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
608 prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
609 prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
610 prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
611 prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
612
613 /* Clear any pending PRCM interrupts */
614 prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
615
616 omap3_iva_idle();
617 omap3_d2d_idle();
618}
619
620static int __init pwrdms_setup(struct powerdomain *pwrdm)
621{
622 struct power_state *pwrst;
623
624 if (!pwrdm->pwrsts)
625 return 0;
626
627 pwrst = kmalloc(sizeof(struct power_state), GFP_KERNEL);
628 if (!pwrst)
629 return -ENOMEM;
630 pwrst->pwrdm = pwrdm;
631 pwrst->next_state = PWRDM_POWER_RET;
632 list_add(&pwrst->node, &pwrst_list);
633
634 if (pwrdm_has_hdwr_sar(pwrdm))
635 pwrdm_enable_hdwr_sar(pwrdm);
636
637 return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
638}
639
640/*
641 * Enable hw supervised mode for all clockdomains if it's
642 * supported. Initiate sleep transition for other clockdomains, if
643 * they are not used
644 */
645static int __init clkdms_setup(struct clockdomain *clkdm)
646{
647 if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
648 omap2_clkdm_allow_idle(clkdm);
649 else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
650 atomic_read(&clkdm->usecount) == 0)
651 omap2_clkdm_sleep(clkdm);
652 return 0;
653}
654
655int __init omap3_pm_init(void)
656{
657 struct power_state *pwrst, *tmp;
658 int ret;
659
660 if (!cpu_is_omap34xx())
661 return -ENODEV;
662
663 printk(KERN_ERR "Power Management for TI OMAP3.\n");
664
665 /* XXX prcm_setup_regs needs to be before enabling hw
666 * supervised mode for powerdomains */
667 prcm_setup_regs();
668
669 ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
670 (irq_handler_t)prcm_interrupt_handler,
671 IRQF_DISABLED, "prcm", NULL);
672 if (ret) {
673 printk(KERN_ERR "request_irq failed to register for 0x%x\n",
674 INT_34XX_PRCM_MPU_IRQ);
675 goto err1;
676 }
677
678 ret = pwrdm_for_each(pwrdms_setup);
679 if (ret) {
680 printk(KERN_ERR "Failed to setup powerdomains\n");
681 goto err2;
682 }
683
684 (void) clkdm_for_each(clkdms_setup);
685
686 mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
687 if (mpu_pwrdm == NULL) {
688 printk(KERN_ERR "Failed to get mpu_pwrdm\n");
689 goto err2;
690 }
691
692 _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
693 omap34xx_cpu_suspend_sz);
694
695 suspend_set_ops(&omap_pm_ops);
696
697 pm_idle = omap3_pm_idle;
698
699err1:
700 return ret;
701err2:
702 free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
703 list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
704 list_del(&pwrst->node);
705 kfree(pwrst);
706 }
707 return ret;
708}
709
710late_initcall(omap3_pm_init);
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 812d50ee495d..cb1ae84e0925 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -276,6 +276,8 @@
276/* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */ 276/* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
277#define OMAP3430_EN_GPIO1 (1 << 3) 277#define OMAP3430_EN_GPIO1 (1 << 3)
278#define OMAP3430_EN_GPIO1_SHIFT 3 278#define OMAP3430_EN_GPIO1_SHIFT 3
279#define OMAP3430_EN_GPT12 (1 << 1)
280#define OMAP3430_EN_GPT12_SHIFT 1
279#define OMAP3430_EN_GPT1 (1 << 0) 281#define OMAP3430_EN_GPT1 (1 << 0)
280#define OMAP3430_EN_GPT1_SHIFT 0 282#define OMAP3430_EN_GPT1_SHIFT 0
281 283
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 7c8e0c42b05d..9937e2814696 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -203,9 +203,11 @@
203 203
204#define OMAP3430_PM_MPUGRPSEL 0x00a4 204#define OMAP3430_PM_MPUGRPSEL 0x00a4
205#define OMAP3430_PM_MPUGRPSEL1 OMAP3430_PM_MPUGRPSEL 205#define OMAP3430_PM_MPUGRPSEL1 OMAP3430_PM_MPUGRPSEL
206#define OMAP3430ES2_PM_MPUGRPSEL3 0x00f8
206 207
207#define OMAP3430_PM_IVAGRPSEL 0x00a8 208#define OMAP3430_PM_IVAGRPSEL 0x00a8
208#define OMAP3430_PM_IVAGRPSEL1 OMAP3430_PM_IVAGRPSEL 209#define OMAP3430_PM_IVAGRPSEL1 OMAP3430_PM_IVAGRPSEL
210#define OMAP3430ES2_PM_IVAGRPSEL3 0x00f4
209 211
210#define OMAP3430_PM_PREPWSTST 0x00e8 212#define OMAP3430_PM_PREPWSTST 0x00e8
211 213
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index 2a30060cb4b7..2045441e8385 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -37,6 +37,10 @@ static struct omap_sdrc_params *sdrc_init_params;
37void __iomem *omap2_sdrc_base; 37void __iomem *omap2_sdrc_base;
38void __iomem *omap2_sms_base; 38void __iomem *omap2_sms_base;
39 39
40/* SDRC_POWER register bits */
41#define SDRC_POWER_EXTCLKDIS_SHIFT 3
42#define SDRC_POWER_PWDENA_SHIFT 2
43#define SDRC_POWER_PAGEPOLICY_SHIFT 0
40 44
41/** 45/**
42 * omap2_sdrc_get_params - return SDRC register values for a given clock rate 46 * omap2_sdrc_get_params - return SDRC register values for a given clock rate
@@ -56,9 +60,12 @@ struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
56{ 60{
57 struct omap_sdrc_params *sp; 61 struct omap_sdrc_params *sp;
58 62
63 if (!sdrc_init_params)
64 return NULL;
65
59 sp = sdrc_init_params; 66 sp = sdrc_init_params;
60 67
61 while (sp->rate != r) 68 while (sp->rate && sp->rate != r)
62 sp++; 69 sp++;
63 70
64 if (!sp->rate) 71 if (!sp->rate)
@@ -74,7 +81,14 @@ void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
74 omap2_sms_base = omap2_globals->sms; 81 omap2_sms_base = omap2_globals->sms;
75} 82}
76 83
77/* turn on smart idle modes for SDRAM scheduler and controller */ 84/**
85 * omap2_sdrc_init - initialize SMS, SDRC devices on boot
86 * @sp: pointer to a null-terminated list of struct omap_sdrc_params
87 *
88 * Turn on smart idle modes for SDRAM scheduler and controller.
89 * Program a known-good configuration for the SDRC to deal with buggy
90 * bootloaders.
91 */
78void __init omap2_sdrc_init(struct omap_sdrc_params *sp) 92void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
79{ 93{
80 u32 l; 94 u32 l;
@@ -90,4 +104,10 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
90 sdrc_write_reg(l, SDRC_SYSCONFIG); 104 sdrc_write_reg(l, SDRC_SYSCONFIG);
91 105
92 sdrc_init_params = sp; 106 sdrc_init_params = sp;
107
108 /* XXX Enable SRFRONIDLEREQ here also? */
109 l = (1 << SDRC_POWER_EXTCLKDIS_SHIFT) |
110 (1 << SDRC_POWER_PWDENA_SHIFT) |
111 (1 << SDRC_POWER_PAGEPOLICY_SHIFT);
112 sdrc_write_reg(l, SDRC_POWER);
93} 113}
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 3c2d325d3dca..fddbc4e1b231 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -6,6 +6,8 @@
6 * Copyright (C) 2005-2008 Nokia Corporation 6 * Copyright (C) 2005-2008 Nokia Corporation
7 * Author: Paul Mundt <paul.mundt@nokia.com> 7 * Author: Paul Mundt <paul.mundt@nokia.com>
8 * 8 *
9 * Major rework for PM support by Kevin Hilman
10 *
9 * Based off of arch/arm/mach-omap/omap1/serial.c 11 * Based off of arch/arm/mach-omap/omap1/serial.c
10 * 12 *
11 * This file is subject to the terms and conditions of the GNU General Public 13 * This file is subject to the terms and conditions of the GNU General Public
@@ -21,9 +23,50 @@
21 23
22#include <mach/common.h> 24#include <mach/common.h>
23#include <mach/board.h> 25#include <mach/board.h>
26#include <mach/clock.h>
27#include <mach/control.h>
28
29#include "prm.h"
30#include "pm.h"
31#include "prm-regbits-34xx.h"
32
33#define UART_OMAP_WER 0x17 /* Wake-up enable register */
34
35#define DEFAULT_TIMEOUT (5 * HZ)
36
37struct omap_uart_state {
38 int num;
39 int can_sleep;
40 struct timer_list timer;
41 u32 timeout;
24 42
25static struct clk *uart_ick[OMAP_MAX_NR_PORTS]; 43 void __iomem *wk_st;
26static struct clk *uart_fck[OMAP_MAX_NR_PORTS]; 44 void __iomem *wk_en;
45 u32 wk_mask;
46 u32 padconf;
47
48 struct clk *ick;
49 struct clk *fck;
50 int clocked;
51
52 struct plat_serial8250_port *p;
53 struct list_head node;
54
55#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
56 int context_valid;
57
58 /* Registers to be saved/restored for OFF-mode */
59 u16 dll;
60 u16 dlh;
61 u16 ier;
62 u16 sysc;
63 u16 scr;
64 u16 wer;
65#endif
66};
67
68static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];
69static LIST_HEAD(uart_list);
27 70
28static struct plat_serial8250_port serial_platform_data[] = { 71static struct plat_serial8250_port serial_platform_data[] = {
29 { 72 {
@@ -74,30 +117,358 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
74 * properly. Note that the TX watermark initialization may not be needed 117 * properly. Note that the TX watermark initialization may not be needed
75 * once the 8250.c watermark handling code is merged. 118 * once the 8250.c watermark handling code is merged.
76 */ 119 */
77static inline void __init omap_serial_reset(struct plat_serial8250_port *p) 120static inline void __init omap_uart_reset(struct omap_uart_state *uart)
78{ 121{
122 struct plat_serial8250_port *p = uart->p;
123
79 serial_write_reg(p, UART_OMAP_MDR1, 0x07); 124 serial_write_reg(p, UART_OMAP_MDR1, 0x07);
80 serial_write_reg(p, UART_OMAP_SCR, 0x08); 125 serial_write_reg(p, UART_OMAP_SCR, 0x08);
81 serial_write_reg(p, UART_OMAP_MDR1, 0x00); 126 serial_write_reg(p, UART_OMAP_MDR1, 0x00);
82 serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0)); 127 serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
83} 128}
84 129
85void omap_serial_enable_clocks(int enable) 130#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
131
132static int enable_off_mode; /* to be removed by full off-mode patches */
133
134static void omap_uart_save_context(struct omap_uart_state *uart)
86{ 135{
87 int i; 136 u16 lcr = 0;
88 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { 137 struct plat_serial8250_port *p = uart->p;
89 if (uart_ick[i] && uart_fck[i]) { 138
90 if (enable) { 139 if (!enable_off_mode)
91 clk_enable(uart_ick[i]); 140 return;
92 clk_enable(uart_fck[i]); 141
93 } else { 142 lcr = serial_read_reg(p, UART_LCR);
94 clk_disable(uart_ick[i]); 143 serial_write_reg(p, UART_LCR, 0xBF);
95 clk_disable(uart_fck[i]); 144 uart->dll = serial_read_reg(p, UART_DLL);
145 uart->dlh = serial_read_reg(p, UART_DLM);
146 serial_write_reg(p, UART_LCR, lcr);
147 uart->ier = serial_read_reg(p, UART_IER);
148 uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
149 uart->scr = serial_read_reg(p, UART_OMAP_SCR);
150 uart->wer = serial_read_reg(p, UART_OMAP_WER);
151
152 uart->context_valid = 1;
153}
154
155static void omap_uart_restore_context(struct omap_uart_state *uart)
156{
157 u16 efr = 0;
158 struct plat_serial8250_port *p = uart->p;
159
160 if (!enable_off_mode)
161 return;
162
163 if (!uart->context_valid)
164 return;
165
166 uart->context_valid = 0;
167
168 serial_write_reg(p, UART_OMAP_MDR1, 0x7);
169 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
170 efr = serial_read_reg(p, UART_EFR);
171 serial_write_reg(p, UART_EFR, UART_EFR_ECB);
172 serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
173 serial_write_reg(p, UART_IER, 0x0);
174 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
175 serial_write_reg(p, UART_DLL, uart->dll);
176 serial_write_reg(p, UART_DLM, uart->dlh);
177 serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
178 serial_write_reg(p, UART_IER, uart->ier);
179 serial_write_reg(p, UART_FCR, 0xA1);
180 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
181 serial_write_reg(p, UART_EFR, efr);
182 serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
183 serial_write_reg(p, UART_OMAP_SCR, uart->scr);
184 serial_write_reg(p, UART_OMAP_WER, uart->wer);
185 serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
186 serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
187}
188#else
189static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
190static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
191#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
192
193static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
194{
195 if (uart->clocked)
196 return;
197
198 clk_enable(uart->ick);
199 clk_enable(uart->fck);
200 uart->clocked = 1;
201 omap_uart_restore_context(uart);
202}
203
204#ifdef CONFIG_PM
205
206static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
207{
208 if (!uart->clocked)
209 return;
210
211 omap_uart_save_context(uart);
212 uart->clocked = 0;
213 clk_disable(uart->ick);
214 clk_disable(uart->fck);
215}
216
217static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
218 int enable)
219{
220 struct plat_serial8250_port *p = uart->p;
221 u16 sysc;
222
223 sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
224 if (enable)
225 sysc |= 0x2 << 3;
226 else
227 sysc |= 0x1 << 3;
228
229 serial_write_reg(p, UART_OMAP_SYSC, sysc);
230}
231
232static void omap_uart_block_sleep(struct omap_uart_state *uart)
233{
234 omap_uart_enable_clocks(uart);
235
236 omap_uart_smart_idle_enable(uart, 0);
237 uart->can_sleep = 0;
238 if (uart->timeout)
239 mod_timer(&uart->timer, jiffies + uart->timeout);
240 else
241 del_timer(&uart->timer);
242}
243
244static void omap_uart_allow_sleep(struct omap_uart_state *uart)
245{
246 if (!uart->clocked)
247 return;
248
249 omap_uart_smart_idle_enable(uart, 1);
250 uart->can_sleep = 1;
251 del_timer(&uart->timer);
252}
253
254static void omap_uart_idle_timer(unsigned long data)
255{
256 struct omap_uart_state *uart = (struct omap_uart_state *)data;
257
258 omap_uart_allow_sleep(uart);
259}
260
261void omap_uart_prepare_idle(int num)
262{
263 struct omap_uart_state *uart;
264
265 list_for_each_entry(uart, &uart_list, node) {
266 if (num == uart->num && uart->can_sleep) {
267 omap_uart_disable_clocks(uart);
268 return;
269 }
270 }
271}
272
273void omap_uart_resume_idle(int num)
274{
275 struct omap_uart_state *uart;
276
277 list_for_each_entry(uart, &uart_list, node) {
278 if (num == uart->num) {
279 omap_uart_enable_clocks(uart);
280
281 /* Check for IO pad wakeup */
282 if (cpu_is_omap34xx() && uart->padconf) {
283 u16 p = omap_ctrl_readw(uart->padconf);
284
285 if (p & OMAP3_PADCONF_WAKEUPEVENT0)
286 omap_uart_block_sleep(uart);
96 } 287 }
288
289 /* Check for normal UART wakeup */
290 if (__raw_readl(uart->wk_st) & uart->wk_mask)
291 omap_uart_block_sleep(uart);
292
293 return;
97 } 294 }
98 } 295 }
99} 296}
100 297
298void omap_uart_prepare_suspend(void)
299{
300 struct omap_uart_state *uart;
301
302 list_for_each_entry(uart, &uart_list, node) {
303 omap_uart_allow_sleep(uart);
304 }
305}
306
307int omap_uart_can_sleep(void)
308{
309 struct omap_uart_state *uart;
310 int can_sleep = 1;
311
312 list_for_each_entry(uart, &uart_list, node) {
313 if (!uart->clocked)
314 continue;
315
316 if (!uart->can_sleep) {
317 can_sleep = 0;
318 continue;
319 }
320
321 /* This UART can now safely sleep. */
322 omap_uart_allow_sleep(uart);
323 }
324
325 return can_sleep;
326}
327
328/**
329 * omap_uart_interrupt()
330 *
331 * This handler is used only to detect that *any* UART interrupt has
332 * occurred. It does _nothing_ to handle the interrupt. Rather,
333 * any UART interrupt will trigger the inactivity timer so the
334 * UART will not idle or sleep for its timeout period.
335 *
336 **/
337static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
338{
339 struct omap_uart_state *uart = dev_id;
340
341 omap_uart_block_sleep(uart);
342
343 return IRQ_NONE;
344}
345
346static u32 sleep_timeout = DEFAULT_TIMEOUT;
347
348static void omap_uart_idle_init(struct omap_uart_state *uart)
349{
350 u32 v;
351 struct plat_serial8250_port *p = uart->p;
352 int ret;
353
354 uart->can_sleep = 0;
355 uart->timeout = sleep_timeout;
356 setup_timer(&uart->timer, omap_uart_idle_timer,
357 (unsigned long) uart);
358 mod_timer(&uart->timer, jiffies + uart->timeout);
359 omap_uart_smart_idle_enable(uart, 0);
360
361 if (cpu_is_omap34xx()) {
362 u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
363 u32 wk_mask = 0;
364 u32 padconf = 0;
365
366 uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
367 uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
368 switch (uart->num) {
369 case 0:
370 wk_mask = OMAP3430_ST_UART1_MASK;
371 padconf = 0x182;
372 break;
373 case 1:
374 wk_mask = OMAP3430_ST_UART2_MASK;
375 padconf = 0x17a;
376 break;
377 case 2:
378 wk_mask = OMAP3430_ST_UART3_MASK;
379 padconf = 0x19e;
380 break;
381 }
382 uart->wk_mask = wk_mask;
383 uart->padconf = padconf;
384 } else if (cpu_is_omap24xx()) {
385 u32 wk_mask = 0;
386
387 if (cpu_is_omap2430()) {
388 uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
389 uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
390 } else if (cpu_is_omap2420()) {
391 uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
392 uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
393 }
394 switch (uart->num) {
395 case 0:
396 wk_mask = OMAP24XX_ST_UART1_MASK;
397 break;
398 case 1:
399 wk_mask = OMAP24XX_ST_UART2_MASK;
400 break;
401 case 2:
402 wk_mask = OMAP24XX_ST_UART3_MASK;
403 break;
404 }
405 uart->wk_mask = wk_mask;
406 } else {
407 uart->wk_en = 0;
408 uart->wk_st = 0;
409 uart->wk_mask = 0;
410 uart->padconf = 0;
411 }
412
413 /* Set wake-enable bit */
414 if (uart->wk_en && uart->wk_mask) {
415 v = __raw_readl(uart->wk_en);
416 v |= uart->wk_mask;
417 __raw_writel(v, uart->wk_en);
418 }
419
420 /* Ensure IOPAD wake-enables are set */
421 if (cpu_is_omap34xx() && uart->padconf) {
422 u16 v;
423
424 v = omap_ctrl_readw(uart->padconf);
425 v |= OMAP3_PADCONF_WAKEUPENABLE0;
426 omap_ctrl_writew(v, uart->padconf);
427 }
428
429 p->flags |= UPF_SHARE_IRQ;
430 ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
431 "serial idle", (void *)uart);
432 WARN_ON(ret);
433}
434
435static ssize_t sleep_timeout_show(struct kobject *kobj,
436 struct kobj_attribute *attr,
437 char *buf)
438{
439 return sprintf(buf, "%u\n", sleep_timeout / HZ);
440}
441
442static ssize_t sleep_timeout_store(struct kobject *kobj,
443 struct kobj_attribute *attr,
444 const char *buf, size_t n)
445{
446 struct omap_uart_state *uart;
447 unsigned int value;
448
449 if (sscanf(buf, "%u", &value) != 1) {
450 printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
451 return -EINVAL;
452 }
453 sleep_timeout = value * HZ;
454 list_for_each_entry(uart, &uart_list, node) {
455 uart->timeout = sleep_timeout;
456 if (uart->timeout)
457 mod_timer(&uart->timer, jiffies + uart->timeout);
458 else
459 /* A zero value means disable timeout feature */
460 omap_uart_block_sleep(uart);
461 }
462 return n;
463}
464
465static struct kobj_attribute sleep_timeout_attr =
466 __ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
467
468#else
469static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
470#endif /* CONFIG_PM */
471
101static struct platform_device serial_device = { 472static struct platform_device serial_device = {
102 .name = "serial8250", 473 .name = "serial8250",
103 .id = PLAT8250_DEV_PLATFORM, 474 .id = PLAT8250_DEV_PLATFORM,
@@ -108,7 +479,7 @@ static struct platform_device serial_device = {
108 479
109void __init omap_serial_init(void) 480void __init omap_serial_init(void)
110{ 481{
111 int i; 482 int i, err;
112 const struct omap_uart_config *info; 483 const struct omap_uart_config *info;
113 char name[16]; 484 char name[16];
114 485
@@ -125,6 +496,7 @@ void __init omap_serial_init(void)
125 496
126 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { 497 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
127 struct plat_serial8250_port *p = serial_platform_data + i; 498 struct plat_serial8250_port *p = serial_platform_data + i;
499 struct omap_uart_state *uart = &omap_uart[i];
128 500
129 if (!(info->enabled_uarts & (1 << i))) { 501 if (!(info->enabled_uarts & (1 << i))) {
130 p->membase = NULL; 502 p->membase = NULL;
@@ -133,23 +505,39 @@ void __init omap_serial_init(void)
133 } 505 }
134 506
135 sprintf(name, "uart%d_ick", i+1); 507 sprintf(name, "uart%d_ick", i+1);
136 uart_ick[i] = clk_get(NULL, name); 508 uart->ick = clk_get(NULL, name);
137 if (IS_ERR(uart_ick[i])) { 509 if (IS_ERR(uart->ick)) {
138 printk(KERN_ERR "Could not get uart%d_ick\n", i+1); 510 printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
139 uart_ick[i] = NULL; 511 uart->ick = NULL;
140 } else 512 }
141 clk_enable(uart_ick[i]);
142 513
143 sprintf(name, "uart%d_fck", i+1); 514 sprintf(name, "uart%d_fck", i+1);
144 uart_fck[i] = clk_get(NULL, name); 515 uart->fck = clk_get(NULL, name);
145 if (IS_ERR(uart_fck[i])) { 516 if (IS_ERR(uart->fck)) {
146 printk(KERN_ERR "Could not get uart%d_fck\n", i+1); 517 printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
147 uart_fck[i] = NULL; 518 uart->fck = NULL;
148 } else 519 }
149 clk_enable(uart_fck[i]); 520
521 if (!uart->ick || !uart->fck)
522 continue;
150 523
151 omap_serial_reset(p); 524 uart->num = i;
525 p->private_data = uart;
526 uart->p = p;
527 list_add(&uart->node, &uart_list);
528
529 omap_uart_enable_clocks(uart);
530 omap_uart_reset(uart);
531 omap_uart_idle_init(uart);
152 } 532 }
153 533
154 platform_device_register(&serial_device); 534 err = platform_device_register(&serial_device);
535
536#ifdef CONFIG_PM
537 if (!err)
538 err = sysfs_create_file(&serial_device.dev.kobj,
539 &sleep_timeout_attr.attr);
540#endif
541
155} 542}
543
diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S
index bf9e96105e11..130aadbfa083 100644
--- a/arch/arm/mach-omap2/sleep24xx.S
+++ b/arch/arm/mach-omap2/sleep24xx.S
@@ -28,7 +28,6 @@
28#include <linux/linkage.h> 28#include <linux/linkage.h>
29#include <asm/assembler.h> 29#include <asm/assembler.h>
30#include <mach/io.h> 30#include <mach/io.h>
31#include <mach/pm.h>
32 31
33#include <mach/omap24xx.h> 32#include <mach/omap24xx.h>
34 33
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
new file mode 100644
index 000000000000..e5e2553e79a6
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -0,0 +1,436 @@
1/*
2 * linux/arch/arm/mach-omap2/sleep.S
3 *
4 * (C) Copyright 2007
5 * Texas Instruments
6 * Karthik Dasu <karthik-dp@ti.com>
7 *
8 * (C) Copyright 2004
9 * Texas Instruments, <www.ti.com>
10 * Richard Woodruff <r-woodruff2@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27#include <linux/linkage.h>
28#include <asm/assembler.h>
29#include <mach/io.h>
30#include <mach/control.h>
31
32#include "prm.h"
33#include "sdrc.h"
34
35#define PM_PREPWSTST_CORE_V OMAP34XX_PRM_REGADDR(CORE_MOD, \
36 OMAP3430_PM_PREPWSTST)
37#define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \
38 OMAP3430_PM_PREPWSTST)
39#define PM_PWSTCTRL_MPU_P OMAP34XX_PRM_REGADDR(MPU_MOD, PM_PWSTCTRL)
40#define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is
41 * available */
42#define SCRATCHPAD_BASE_P OMAP343X_CTRL_REGADDR(\
43 OMAP343X_CONTROL_MEM_WKUP +\
44 SCRATCHPAD_MEM_OFFS)
45#define SDRC_POWER_V OMAP34XX_SDRC_REGADDR(SDRC_POWER)
46
47 .text
48/* Function call to get the restore pointer for resume from OFF */
49ENTRY(get_restore_pointer)
50 stmfd sp!, {lr} @ save registers on stack
51 adr r0, restore
52 ldmfd sp!, {pc} @ restore regs and return
53ENTRY(get_restore_pointer_sz)
54 .word . - get_restore_pointer_sz
55/*
56 * Forces OMAP into idle state
57 *
58 * omap34xx_suspend() - This bit of code just executes the WFI
59 * for normal idles.
60 *
61 * Note: This code get's copied to internal SRAM at boot. When the OMAP
62 * wakes up it continues execution at the point it went to sleep.
63 */
64ENTRY(omap34xx_cpu_suspend)
65 stmfd sp!, {r0-r12, lr} @ save registers on stack
66loop:
67 /*b loop*/ @Enable to debug by stepping through code
68 /* r0 contains restore pointer in sdram */
69 /* r1 contains information about saving context */
70 ldr r4, sdrc_power @ read the SDRC_POWER register
71 ldr r5, [r4] @ read the contents of SDRC_POWER
72 orr r5, r5, #0x40 @ enable self refresh on idle req
73 str r5, [r4] @ write back to SDRC_POWER register
74
75 cmp r1, #0x0
76 /* If context save is required, do that and execute wfi */
77 bne save_context_wfi
78 /* Data memory barrier and Data sync barrier */
79 mov r1, #0
80 mcr p15, 0, r1, c7, c10, 4
81 mcr p15, 0, r1, c7, c10, 5
82
83 wfi @ wait for interrupt
84
85 nop
86 nop
87 nop
88 nop
89 nop
90 nop
91 nop
92 nop
93 nop
94 nop
95 bl i_dll_wait
96
97 ldmfd sp!, {r0-r12, pc} @ restore regs and return
98restore:
99 /* b restore*/ @ Enable to debug restore code
100 /* Check what was the reason for mpu reset and store the reason in r9*/
101 /* 1 - Only L1 and logic lost */
102 /* 2 - Only L2 lost - In this case, we wont be here */
103 /* 3 - Both L1 and L2 lost */
104 ldr r1, pm_pwstctrl_mpu
105 ldr r2, [r1]
106 and r2, r2, #0x3
107 cmp r2, #0x0 @ Check if target power state was OFF or RET
108 moveq r9, #0x3 @ MPU OFF => L1 and L2 lost
109 movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation
110 bne logic_l1_restore
111 /* Execute smi to invalidate L2 cache */
112 mov r12, #0x1 @ set up to invalide L2
113smi: .word 0xE1600070 @ Call SMI monitor (smieq)
114logic_l1_restore:
115 mov r1, #0
116 /* Invalidate all instruction caches to PoU
117 * and flush branch target cache */
118 mcr p15, 0, r1, c7, c5, 0
119
120 ldr r4, scratchpad_base
121 ldr r3, [r4,#0xBC]
122 ldmia r3!, {r4-r6}
123 mov sp, r4
124 msr spsr_cxsf, r5
125 mov lr, r6
126
127 ldmia r3!, {r4-r9}
128 /* Coprocessor access Control Register */
129 mcr p15, 0, r4, c1, c0, 2
130
131 /* TTBR0 */
132 MCR p15, 0, r5, c2, c0, 0
133 /* TTBR1 */
134 MCR p15, 0, r6, c2, c0, 1
135 /* Translation table base control register */
136 MCR p15, 0, r7, c2, c0, 2
137 /*domain access Control Register */
138 MCR p15, 0, r8, c3, c0, 0
139 /* data fault status Register */
140 MCR p15, 0, r9, c5, c0, 0
141
142 ldmia r3!,{r4-r8}
143 /* instruction fault status Register */
144 MCR p15, 0, r4, c5, c0, 1
145 /*Data Auxiliary Fault Status Register */
146 MCR p15, 0, r5, c5, c1, 0
147 /*Instruction Auxiliary Fault Status Register*/
148 MCR p15, 0, r6, c5, c1, 1
149 /*Data Fault Address Register */
150 MCR p15, 0, r7, c6, c0, 0
151 /*Instruction Fault Address Register*/
152 MCR p15, 0, r8, c6, c0, 2
153 ldmia r3!,{r4-r7}
154
155 /* user r/w thread and process ID */
156 MCR p15, 0, r4, c13, c0, 2
157 /* user ro thread and process ID */
158 MCR p15, 0, r5, c13, c0, 3
159 /*Privileged only thread and process ID */
160 MCR p15, 0, r6, c13, c0, 4
161 /* cache size selection */
162 MCR p15, 2, r7, c0, c0, 0
163 ldmia r3!,{r4-r8}
164 /* Data TLB lockdown registers */
165 MCR p15, 0, r4, c10, c0, 0
166 /* Instruction TLB lockdown registers */
167 MCR p15, 0, r5, c10, c0, 1
168 /* Secure or Nonsecure Vector Base Address */
169 MCR p15, 0, r6, c12, c0, 0
170 /* FCSE PID */
171 MCR p15, 0, r7, c13, c0, 0
172 /* Context PID */
173 MCR p15, 0, r8, c13, c0, 1
174
175 ldmia r3!,{r4-r5}
176 /* primary memory remap register */
177 MCR p15, 0, r4, c10, c2, 0
178 /*normal memory remap register */
179 MCR p15, 0, r5, c10, c2, 1
180
181 /* Restore cpsr */
182 ldmia r3!,{r4} /*load CPSR from SDRAM*/
183 msr cpsr, r4 /*store cpsr */
184
185 /* Enabling MMU here */
186 mrc p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
187 /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
188 and r7, #0x7
189 cmp r7, #0x0
190 beq usettbr0
191ttbr_error:
192 /* More work needs to be done to support N[0:2] value other than 0
193 * So looping here so that the error can be detected
194 */
195 b ttbr_error
196usettbr0:
197 mrc p15, 0, r2, c2, c0, 0
198 ldr r5, ttbrbit_mask
199 and r2, r5
200 mov r4, pc
201 ldr r5, table_index_mask
202 and r4, r5 /* r4 = 31 to 20 bits of pc */
203 /* Extract the value to be written to table entry */
204 ldr r1, table_entry
205 add r1, r1, r4 /* r1 has value to be written to table entry*/
206 /* Getting the address of table entry to modify */
207 lsr r4, #18
208 add r2, r4 /* r2 has the location which needs to be modified */
209 /* Storing previous entry of location being modified */
210 ldr r5, scratchpad_base
211 ldr r4, [r2]
212 str r4, [r5, #0xC0]
213 /* Modify the table entry */
214 str r1, [r2]
215 /* Storing address of entry being modified
216 * - will be restored after enabling MMU */
217 ldr r5, scratchpad_base
218 str r2, [r5, #0xC4]
219
220 mov r0, #0
221 mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
222 mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array
223 mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB
224 mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB
225 /* Restore control register but dont enable caches here*/
226 /* Caches will be enabled after restoring MMU table entry */
227 ldmia r3!, {r4}
228 /* Store previous value of control register in scratchpad */
229 str r4, [r5, #0xC8]
230 ldr r2, cache_pred_disable_mask
231 and r4, r2
232 mcr p15, 0, r4, c1, c0, 0
233
234 ldmfd sp!, {r0-r12, pc} @ restore regs and return
235save_context_wfi:
236 /*b save_context_wfi*/ @ enable to debug save code
237 mov r8, r0 /* Store SDRAM address in r8 */
238 /* Check what that target sleep state is:stored in r1*/
239 /* 1 - Only L1 and logic lost */
240 /* 2 - Only L2 lost */
241 /* 3 - Both L1 and L2 lost */
242 cmp r1, #0x2 /* Only L2 lost */
243 beq clean_l2
244 cmp r1, #0x1 /* L2 retained */
245 /* r9 stores whether to clean L2 or not*/
246 moveq r9, #0x0 /* Dont Clean L2 */
247 movne r9, #0x1 /* Clean L2 */
248l1_logic_lost:
249 /* Store sp and spsr to SDRAM */
250 mov r4, sp
251 mrs r5, spsr
252 mov r6, lr
253 stmia r8!, {r4-r6}
254 /* Save all ARM registers */
255 /* Coprocessor access control register */
256 mrc p15, 0, r6, c1, c0, 2
257 stmia r8!, {r6}
258 /* TTBR0, TTBR1 and Translation table base control */
259 mrc p15, 0, r4, c2, c0, 0
260 mrc p15, 0, r5, c2, c0, 1
261 mrc p15, 0, r6, c2, c0, 2
262 stmia r8!, {r4-r6}
263 /* Domain access control register, data fault status register,
264 and instruction fault status register */
265 mrc p15, 0, r4, c3, c0, 0
266 mrc p15, 0, r5, c5, c0, 0
267 mrc p15, 0, r6, c5, c0, 1
268 stmia r8!, {r4-r6}
269 /* Data aux fault status register, instruction aux fault status,
270 datat fault address register and instruction fault address register*/
271 mrc p15, 0, r4, c5, c1, 0
272 mrc p15, 0, r5, c5, c1, 1
273 mrc p15, 0, r6, c6, c0, 0
274 mrc p15, 0, r7, c6, c0, 2
275 stmia r8!, {r4-r7}
276 /* user r/w thread and process ID, user r/o thread and process ID,
277 priv only thread and process ID, cache size selection */
278 mrc p15, 0, r4, c13, c0, 2
279 mrc p15, 0, r5, c13, c0, 3
280 mrc p15, 0, r6, c13, c0, 4
281 mrc p15, 2, r7, c0, c0, 0
282 stmia r8!, {r4-r7}
283 /* Data TLB lockdown, instruction TLB lockdown registers */
284 mrc p15, 0, r5, c10, c0, 0
285 mrc p15, 0, r6, c10, c0, 1
286 stmia r8!, {r5-r6}
287 /* Secure or non secure vector base address, FCSE PID, Context PID*/
288 mrc p15, 0, r4, c12, c0, 0
289 mrc p15, 0, r5, c13, c0, 0
290 mrc p15, 0, r6, c13, c0, 1
291 stmia r8!, {r4-r6}
292 /* Primary remap, normal remap registers */
293 mrc p15, 0, r4, c10, c2, 0
294 mrc p15, 0, r5, c10, c2, 1
295 stmia r8!,{r4-r5}
296
297 /* Store current cpsr*/
298 mrs r2, cpsr
299 stmia r8!, {r2}
300
301 mrc p15, 0, r4, c1, c0, 0
302 /* save control register */
303 stmia r8!, {r4}
304clean_caches:
305 /* Clean Data or unified cache to POU*/
306 /* How to invalidate only L1 cache???? - #FIX_ME# */
307 /* mcr p15, 0, r11, c7, c11, 1 */
308 cmp r9, #1 /* Check whether L2 inval is required or not*/
309 bne skip_l2_inval
310clean_l2:
311 /* read clidr */
312 mrc p15, 1, r0, c0, c0, 1
313 /* extract loc from clidr */
314 ands r3, r0, #0x7000000
315 /* left align loc bit field */
316 mov r3, r3, lsr #23
317 /* if loc is 0, then no need to clean */
318 beq finished
319 /* start clean at cache level 0 */
320 mov r10, #0
321loop1:
322 /* work out 3x current cache level */
323 add r2, r10, r10, lsr #1
324 /* extract cache type bits from clidr*/
325 mov r1, r0, lsr r2
326 /* mask of the bits for current cache only */
327 and r1, r1, #7
328 /* see what cache we have at this level */
329 cmp r1, #2
330 /* skip if no cache, or just i-cache */
331 blt skip
332 /* select current cache level in cssr */
333 mcr p15, 2, r10, c0, c0, 0
334 /* isb to sych the new cssr&csidr */
335 isb
336 /* read the new csidr */
337 mrc p15, 1, r1, c0, c0, 0
338 /* extract the length of the cache lines */
339 and r2, r1, #7
340 /* add 4 (line length offset) */
341 add r2, r2, #4
342 ldr r4, assoc_mask
343 /* find maximum number on the way size */
344 ands r4, r4, r1, lsr #3
345 /* find bit position of way size increment */
346 clz r5, r4
347 ldr r7, numset_mask
348 /* extract max number of the index size*/
349 ands r7, r7, r1, lsr #13
350loop2:
351 mov r9, r4
352 /* create working copy of max way size*/
353loop3:
354 /* factor way and cache number into r11 */
355 orr r11, r10, r9, lsl r5
356 /* factor index number into r11 */
357 orr r11, r11, r7, lsl r2
358 /*clean & invalidate by set/way */
359 mcr p15, 0, r11, c7, c10, 2
360 /* decrement the way*/
361 subs r9, r9, #1
362 bge loop3
363 /*decrement the index */
364 subs r7, r7, #1
365 bge loop2
366skip:
367 add r10, r10, #2
368 /* increment cache number */
369 cmp r3, r10
370 bgt loop1
371finished:
372 /*swith back to cache level 0 */
373 mov r10, #0
374 /* select current cache level in cssr */
375 mcr p15, 2, r10, c0, c0, 0
376 isb
377skip_l2_inval:
378 /* Data memory barrier and Data sync barrier */
379 mov r1, #0
380 mcr p15, 0, r1, c7, c10, 4
381 mcr p15, 0, r1, c7, c10, 5
382
383 wfi @ wait for interrupt
384 nop
385 nop
386 nop
387 nop
388 nop
389 nop
390 nop
391 nop
392 nop
393 nop
394 bl i_dll_wait
395 /* restore regs and return */
396 ldmfd sp!, {r0-r12, pc}
397
398i_dll_wait:
399 ldr r4, clk_stabilize_delay
400
401i_dll_delay:
402 subs r4, r4, #0x1
403 bne i_dll_delay
404 ldr r4, sdrc_power
405 ldr r5, [r4]
406 bic r5, r5, #0x40
407 str r5, [r4]
408 bx lr
409pm_prepwstst_core:
410 .word PM_PREPWSTST_CORE_V
411pm_prepwstst_mpu:
412 .word PM_PREPWSTST_MPU_V
413pm_pwstctrl_mpu:
414 .word PM_PWSTCTRL_MPU_P
415scratchpad_base:
416 .word SCRATCHPAD_BASE_P
417sdrc_power:
418 .word SDRC_POWER_V
419context_mem:
420 .word 0x803E3E14
421clk_stabilize_delay:
422 .word 0x000001FF
423assoc_mask:
424 .word 0x3ff
425numset_mask:
426 .word 0x7fff
427ttbrbit_mask:
428 .word 0xFFFFC000
429table_index_mask:
430 .word 0xFFF00000
431table_entry:
432 .word 0x00000C02
433cache_pred_disable_mask:
434 .word 0xFFFFE7FB
435ENTRY(omap34xx_cpu_suspend_sz)
436 .word . - omap34xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index 2c7146136342..c080c82521e1 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -40,69 +40,74 @@
40/* 40/*
41 * Change frequency of core dpll 41 * Change frequency of core dpll
42 * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2 42 * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2
43 * r4 = Unlock SDRC DLL? (1 = yes, 0 = no) -- only unlock DLL for
44 * SDRC rates < 83MHz
43 */ 45 */
44ENTRY(omap3_sram_configure_core_dpll) 46ENTRY(omap3_sram_configure_core_dpll)
45 stmfd sp!, {r1-r12, lr} @ store regs to stack 47 stmfd sp!, {r1-r12, lr} @ store regs to stack
48 ldr r4, [sp, #52] @ pull extra args off the stack
49 dsb @ flush buffered writes to interconnect
46 cmp r3, #0x2 50 cmp r3, #0x2
47 blne configure_sdrc 51 blne configure_sdrc
48 cmp r3, #0x2 52 cmp r4, #0x1
53 bleq unlock_dll
49 blne lock_dll 54 blne lock_dll
50 cmp r3, #0x1
51 blne unlock_dll
52 bl sdram_in_selfrefresh @ put the SDRAM in self refresh 55 bl sdram_in_selfrefresh @ put the SDRAM in self refresh
53 bl configure_core_dpll 56 bl configure_core_dpll
54 bl enable_sdrc 57 bl enable_sdrc
55 cmp r3, #0x1 58 cmp r4, #0x1
56 blne wait_dll_unlock 59 bleq wait_dll_unlock
57 cmp r3, #0x2
58 blne wait_dll_lock 60 blne wait_dll_lock
59 cmp r3, #0x1 61 cmp r3, #0x1
60 blne configure_sdrc 62 blne configure_sdrc
63 isb @ prevent speculative exec past here
61 mov r0, #0 @ return value 64 mov r0, #0 @ return value
62 ldmfd sp!, {r1-r12, pc} @ restore regs and return 65 ldmfd sp!, {r1-r12, pc} @ restore regs and return
63unlock_dll: 66unlock_dll:
64 ldr r4, omap3_sdrc_dlla_ctrl 67 ldr r11, omap3_sdrc_dlla_ctrl
65 ldr r5, [r4] 68 ldr r12, [r11]
66 orr r5, r5, #0x4 69 orr r12, r12, #0x4
67 str r5, [r4] 70 str r12, [r11] @ (no OCP barrier needed)
68 bx lr 71 bx lr
69lock_dll: 72lock_dll:
70 ldr r4, omap3_sdrc_dlla_ctrl 73 ldr r11, omap3_sdrc_dlla_ctrl
71 ldr r5, [r4] 74 ldr r12, [r11]
72 bic r5, r5, #0x4 75 bic r12, r12, #0x4
73 str r5, [r4] 76 str r12, [r11] @ (no OCP barrier needed)
74 bx lr 77 bx lr
75sdram_in_selfrefresh: 78sdram_in_selfrefresh:
76 mov r5, #0x0 @ Move 0 to R5 79 ldr r11, omap3_sdrc_power @ read the SDRC_POWER register
77 mcr p15, 0, r5, c7, c10, 5 @ memory barrier 80 ldr r12, [r11] @ read the contents of SDRC_POWER
78 ldr r4, omap3_sdrc_power @ read the SDRC_POWER register 81 mov r9, r12 @ keep a copy of SDRC_POWER bits
79 ldr r5, [r4] @ read the contents of SDRC_POWER 82 orr r12, r12, #0x40 @ enable self refresh on idle req
80 orr r5, r5, #0x40 @ enable self refresh on idle req 83 bic r12, r12, #0x4 @ clear PWDENA
81 str r5, [r4] @ write back to SDRC_POWER register 84 str r12, [r11] @ write back to SDRC_POWER register
82 ldr r4, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg 85 ldr r12, [r11] @ posted-write barrier for SDRC
83 ldr r5, [r4] 86 ldr r11, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg
84 bic r5, r5, #0x2 @ disable iclk bit for SRDC 87 ldr r12, [r11]
85 str r5, [r4] 88 bic r12, r12, #0x2 @ disable iclk bit for SDRC
89 str r12, [r11]
86wait_sdrc_idle: 90wait_sdrc_idle:
87 ldr r4, omap3_cm_idlest1_core 91 ldr r11, omap3_cm_idlest1_core
88 ldr r5, [r4] 92 ldr r12, [r11]
89 and r5, r5, #0x2 @ check for SDRC idle 93 and r12, r12, #0x2 @ check for SDRC idle
90 cmp r5, #2 94 cmp r12, #2
91 bne wait_sdrc_idle 95 bne wait_sdrc_idle
92 bx lr 96 bx lr
93configure_core_dpll: 97configure_core_dpll:
94 ldr r4, omap3_cm_clksel1_pll 98 ldr r11, omap3_cm_clksel1_pll
95 ldr r5, [r4] 99 ldr r12, [r11]
96 ldr r6, core_m2_mask_val @ modify m2 for core dpll 100 ldr r10, core_m2_mask_val @ modify m2 for core dpll
97 and r5, r5, r6 101 and r12, r12, r10
98 orr r5, r5, r3, lsl #0x1B @ r3 contains the M2 val 102 orr r12, r12, r3, lsl #0x1B @ r3 contains the M2 val
99 str r5, [r4] 103 str r12, [r11]
100 mov r5, #0x800 @ wait for the clock to stabilise 104 ldr r12, [r11] @ posted-write barrier for CM
105 mov r12, #0x800 @ wait for the clock to stabilise
101 cmp r3, #2 106 cmp r3, #2
102 bne wait_clk_stable 107 bne wait_clk_stable
103 bx lr 108 bx lr
104wait_clk_stable: 109wait_clk_stable:
105 subs r5, r5, #1 110 subs r12, r12, #1
106 bne wait_clk_stable 111 bne wait_clk_stable
107 nop 112 nop
108 nop 113 nop
@@ -116,42 +121,42 @@ wait_clk_stable:
116 nop 121 nop
117 bx lr 122 bx lr
118enable_sdrc: 123enable_sdrc:
119 ldr r4, omap3_cm_iclken1_core 124 ldr r11, omap3_cm_iclken1_core
120 ldr r5, [r4] 125 ldr r12, [r11]
121 orr r5, r5, #0x2 @ enable iclk bit for SDRC 126 orr r12, r12, #0x2 @ enable iclk bit for SDRC
122 str r5, [r4] 127 str r12, [r11]
123wait_sdrc_idle1: 128wait_sdrc_idle1:
124 ldr r4, omap3_cm_idlest1_core 129 ldr r11, omap3_cm_idlest1_core
125 ldr r5, [r4] 130 ldr r12, [r11]
126 and r5, r5, #0x2 131 and r12, r12, #0x2
127 cmp r5, #0 132 cmp r12, #0
128 bne wait_sdrc_idle1 133 bne wait_sdrc_idle1
129 ldr r4, omap3_sdrc_power 134restore_sdrc_power_val:
130 ldr r5, [r4] 135 ldr r11, omap3_sdrc_power
131 bic r5, r5, #0x40 136 str r9, [r11] @ restore SDRC_POWER, no barrier needed
132 str r5, [r4]
133 bx lr 137 bx lr
134wait_dll_lock: 138wait_dll_lock:
135 ldr r4, omap3_sdrc_dlla_status 139 ldr r11, omap3_sdrc_dlla_status
136 ldr r5, [r4] 140 ldr r12, [r11]
137 and r5, r5, #0x4 141 and r12, r12, #0x4
138 cmp r5, #0x4 142 cmp r12, #0x4
139 bne wait_dll_lock 143 bne wait_dll_lock
140 bx lr 144 bx lr
141wait_dll_unlock: 145wait_dll_unlock:
142 ldr r4, omap3_sdrc_dlla_status 146 ldr r11, omap3_sdrc_dlla_status
143 ldr r5, [r4] 147 ldr r12, [r11]
144 and r5, r5, #0x4 148 and r12, r12, #0x4
145 cmp r5, #0x0 149 cmp r12, #0x0
146 bne wait_dll_unlock 150 bne wait_dll_unlock
147 bx lr 151 bx lr
148configure_sdrc: 152configure_sdrc:
149 ldr r4, omap3_sdrc_rfr_ctrl 153 ldr r11, omap3_sdrc_rfr_ctrl
150 str r0, [r4] 154 str r0, [r11]
151 ldr r4, omap3_sdrc_actim_ctrla 155 ldr r11, omap3_sdrc_actim_ctrla
152 str r1, [r4] 156 str r1, [r11]
153 ldr r4, omap3_sdrc_actim_ctrlb 157 ldr r11, omap3_sdrc_actim_ctrlb
154 str r2, [r4] 158 str r2, [r11]
159 ldr r2, [r11] @ posted-write barrier for SDRC
155 bx lr 160 bx lr
156 161
157omap3_sdrc_power: 162omap3_sdrc_power:
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 34a56a136efd..d85296dc896c 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -28,10 +28,20 @@
28 28
29#include <mach/hardware.h> 29#include <mach/hardware.h>
30#include <mach/irqs.h> 30#include <mach/irqs.h>
31#include <mach/pm.h>
32#include <mach/mux.h> 31#include <mach/mux.h>
33#include <mach/usb.h> 32#include <mach/usb.h>
34 33
34#define OTG_SYSCONFIG (OMAP34XX_HSUSB_OTG_BASE + 0x404)
35
36static void __init usb_musb_pm_init(void)
37{
38 /* Ensure force-idle mode for OTG controller */
39 if (cpu_is_omap34xx())
40 omap_writel(0, OTG_SYSCONFIG);
41}
42
43#ifdef CONFIG_USB_MUSB_SOC
44
35static struct resource musb_resources[] = { 45static struct resource musb_resources[] = {
36 [0] = { /* start and end set dynamically */ 46 [0] = { /* start and end set dynamically */
37 .flags = IORESOURCE_MEM, 47 .flags = IORESOURCE_MEM,
@@ -184,4 +194,13 @@ void __init usb_musb_init(void)
184 printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n"); 194 printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
185 return; 195 return;
186 } 196 }
197
198 usb_musb_pm_init();
199}
200
201#else
202void __init usb_musb_init(void)
203{
204 usb_musb_pm_init();
187} 205}
206#endif /* CONFIG_USB_MUSB_SOC */