From 68523f4233de5f233478dde0a63047b4efb710b8 Mon Sep 17 00:00:00 2001
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Date: Mon, 12 Mar 2012 20:34:45 +0530
Subject: [PATCH 1/5] ARM: OMAP4: Workaround the OCP synchronisation issue with
 32K synctimer.

On OMAP4, recently a synchronisation bug is discovered by hardware
team, which leads to incorrect timer value read from 32K sync timer
IP when the IP is comming out of idle.

The issue is due to the synchronization methodology used in the SYNCTIMER IP.
The value of the counter register in 32kHz domain is synchronized to the OCP
domain register only at count up event, and if the OCP clock is switched off,
the OCP register gets out of synch until the first count up event after the
clock is switched back -at the next falling edge of the 32kHz clock.

Further investigation revealed that it applies to gptimer1 and watchdog timer2
as well which may run on 32KHz. This patch fixes the issue for all the
applicable modules.

The BUG has not made it yet to the OMAP errata list and it is applicable to
OMAP1/2/3/4/5. OMAP1/2/3 it is taken care indirectly by autodeps.

By enabling static depedency of wakeup clockdomain with MPU, as soon as MPU
is woken up from lowpower state(idle) or whenever MPU is active, PRCM forces
the OCP clock to be running and allow the counter value to be updated properly
in the OCP clock domain.

The bug is going to fixed in future OMAP versions.

Reported-Tested-by: dave.long@linaro.org
[dave.long@linaro.org: Reported the oprofile time stamp issue with synctimer
and helped to test this patch]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/pm44xx.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index c264ef7219c1..974f7ea19b22 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -196,7 +196,7 @@ static void omap_default_idle(void)
 static int __init omap4_pm_init(void)
 {
 	int ret;
-	struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
+	struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm, *l4wkup;
 	struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per_clkdm;
 
 	if (!cpu_is_omap44xx())
@@ -220,14 +220,19 @@ static int __init omap4_pm_init(void)
 	 * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
 	 * expected. The hardware recommendation is to enable static
 	 * dependencies for these to avoid system lock ups or random crashes.
+	 * The L4 wakeup depedency is added to workaround the OCP sync hardware
+	 * BUG with 32K synctimer which lead to incorrect timer value read
+	 * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
+	 * are part of L4 wakeup clockdomain.
 	 */
 	mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
 	emif_clkdm = clkdm_lookup("l3_emif_clkdm");
 	l3_1_clkdm = clkdm_lookup("l3_1_clkdm");
 	l3_2_clkdm = clkdm_lookup("l3_2_clkdm");
 	l4_per_clkdm = clkdm_lookup("l4_per_clkdm");
+	l4wkup = clkdm_lookup("l4_wkup_clkdm");
 	ducati_clkdm = clkdm_lookup("ducati_clkdm");
-	if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
+	if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || (!l4wkup) ||
 		(!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per_clkdm))
 		goto err2;
 
@@ -235,6 +240,7 @@ static int __init omap4_pm_init(void)
 	ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
 	ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm);
 	ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per_clkdm);
+	ret |= clkdm_add_wkdep(mpuss_clkdm, l4wkup);
 	ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm);
 	ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
 	if (ret) {

From ce229c5d79c03f09d4612dd2bcbff532fdc24e80 Mon Sep 17 00:00:00 2001
From: "Mark A. Greer" <mgreer@animalcreek.com>
Date: Sat, 17 Mar 2012 18:22:47 -0700
Subject: [PATCH 2/5] arm: omap3: pm34xx.c: Fix omap3_pm_init() error out paths

It appears that the error paths were overlooked when the
omap3_pm_init() routine had the prcm chain handler code
added.  Fix this by adding a goto target and reordering
the error handling code.  Also fix how the irq argument
for free_irq() is determined.

Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
Acked-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/pm34xx.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index fc6987578920..c598d26f3317 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -817,13 +817,13 @@ static int __init omap3_pm_init(void)
 
 	if (ret) {
 		pr_err("pm: Failed to request pm_io irq\n");
-		goto err1;
+		goto err2;
 	}
 
 	ret = pwrdm_for_each(pwrdms_setup, NULL);
 	if (ret) {
 		printk(KERN_ERR "Failed to setup powerdomains\n");
-		goto err2;
+		goto err3;
 	}
 
 	(void) clkdm_for_each(clkdms_setup, NULL);
@@ -831,7 +831,8 @@ static int __init omap3_pm_init(void)
 	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
 	if (mpu_pwrdm == NULL) {
 		printk(KERN_ERR "Failed to get mpu_pwrdm\n");
-		goto err2;
+		ret = -EINVAL;
+		goto err3;
 	}
 
 	neon_pwrdm = pwrdm_lookup("neon_pwrdm");
@@ -879,14 +880,17 @@ static int __init omap3_pm_init(void)
 	}
 
 	omap3_save_scratchpad_contents();
-err1:
 	return ret;
-err2:
-	free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
+
+err3:
 	list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
 		list_del(&pwrst->node);
 		kfree(pwrst);
 	}
+	free_irq(omap_prcm_event_to_irq("io"), omap3_pm_init);
+err2:
+	free_irq(omap_prcm_event_to_irq("wkup"), NULL);
+err1:
 	return ret;
 }
 

From 981798569b090543453baccbc0657fbcea311668 Mon Sep 17 00:00:00 2001
From: "Mark A. Greer" <mgreer@animalcreek.com>
Date: Sat, 17 Mar 2012 18:22:48 -0700
Subject: [PATCH 3/5] arm: omap3: pm34xx.c: Replace printk() with appropriate
 pr_*()

Currently, pm34xx.c has a mix of printk() and pr_*() statements
so replace the printk() statements with the equivalent pr_*()
statements.

Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/pm34xx.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c598d26f3317..6aeacf660790 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -166,8 +166,7 @@ static void omap3_save_secure_ram_context(void)
 		pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
 		/* Following is for error tracking, it should not happen */
 		if (ret) {
-			printk(KERN_ERR "save_secure_sram() returns %08x\n",
-				ret);
+			pr_err("save_secure_sram() returns %08x\n", ret);
 			while (1)
 				;
 		}
@@ -307,7 +306,7 @@ void omap_sram_idle(void)
 		break;
 	default:
 		/* Invalid state */
-		printk(KERN_ERR "Invalid mpu state in sram_idle\n");
+		pr_err("Invalid mpu state in sram_idle\n");
 		return;
 	}
 
@@ -463,18 +462,17 @@ static int omap3_pm_suspend(void)
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
-			printk(KERN_INFO "Powerdomain (%s) didn't enter "
-			       "target state %d\n",
+			pr_info("Powerdomain (%s) didn't enter "
+				"target state %d\n",
 			       pwrst->pwrdm->name, pwrst->next_state);
 			ret = -1;
 		}
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
 	}
 	if (ret)
-		printk(KERN_ERR "Could not enter target state in pm_suspend\n");
+		pr_err("Could not enter target state in pm_suspend\n");
 	else
-		printk(KERN_INFO "Successfully put all powerdomains "
-		       "to target state\n");
+		pr_info("Successfully put all powerdomains to target state\n");
 
 	return ret;
 }
@@ -822,7 +820,7 @@ static int __init omap3_pm_init(void)
 
 	ret = pwrdm_for_each(pwrdms_setup, NULL);
 	if (ret) {
-		printk(KERN_ERR "Failed to setup powerdomains\n");
+		pr_err("Failed to setup powerdomains\n");
 		goto err3;
 	}
 
@@ -830,7 +828,7 @@ static int __init omap3_pm_init(void)
 
 	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
 	if (mpu_pwrdm == NULL) {
-		printk(KERN_ERR "Failed to get mpu_pwrdm\n");
+		pr_err("Failed to get mpu_pwrdm\n");
 		ret = -EINVAL;
 		goto err3;
 	}
@@ -865,8 +863,8 @@ static int __init omap3_pm_init(void)
 		omap3_secure_ram_storage =
 			kmalloc(0x803F, GFP_KERNEL);
 		if (!omap3_secure_ram_storage)
-			printk(KERN_ERR "Memory allocation failed when"
-					"allocating for secure sram context\n");
+			pr_err("Memory allocation failed when "
+			       "allocating for secure sram context\n");
 
 		local_irq_disable();
 		local_fiq_disable();

From 9fa2df6b90786301b175e264f5fa9846aba81a65 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Fri, 16 Mar 2012 11:19:09 -0500
Subject: [PATCH 4/5] ARM: OMAP2+: OPP: allow OPP enumeration to continue if
 device is not present

On platforms such as OMAP3, certain variants may not have IVA, SGX
or some specific component. We currently have a check to aid fixing
wrong population of OPP entries for issues such as typos. This however
causes a conflict with valid requirement where the SoC variant does
not actually have the module present.

So, reduce the severity of the print to a debug statement and skip
registering that specific OPP, but continue down the list.

Reported-by: Steve Sakoman <steve@sakoman.com>
Reported-by: Maximilian Schwerin <mvs@tigris.de>
Acked-by: Steve Sakoman <steve@sakoman.com>
Tested-by: Maximilian Schwerin <mvs@tigris.de>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/opp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index 9262a6b47702..de6d46451746 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -64,10 +64,10 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
 		}
 		oh = omap_hwmod_lookup(opp_def->hwmod_name);
 		if (!oh || !oh->od) {
-			pr_warn("%s: no hwmod or odev for %s, [%d] "
+			pr_debug("%s: no hwmod or odev for %s, [%d] "
 				"cannot add OPPs.\n", __func__,
 				opp_def->hwmod_name, i);
-			return -EINVAL;
+			continue;
 		}
 		dev = &oh->od->pdev->dev;
 

From 4ba7c3c3c6567210bf46b1ab3d089134170c2762 Mon Sep 17 00:00:00 2001
From: Ming Lei <tom.leiming@gmail.com>
Date: Thu, 22 Mar 2012 09:23:37 +0800
Subject: [PATCH 5/5] ARM: OMAP3+: fix oops triggered in
 omap_prcm_register_chain_handler(v1)

This patch fixes the oops below[1].

Obviously, the count of "struct irq_chip_generic" instances to be
allocated and setup should be irq_setup->nr_regs instead of
irq_setup->nr_regs plus one, so just fix the iterator to avoid
the oops.

[1], oops log.

[    1.790242] Unable to handle kernel NULL pointer dereference at virtual address 00000004
[    1.798632] pgd = c0004000
[    1.801638] [00000004] *pgd=00000000
[    1.805400] Internal error: Oops: 805 [#1] PREEMPT SMP THUMB2
[    1.811381] Modules linked in:
[    1.814601] CPU: 1    Not tainted  (3.3.0-next-20120320+ #733)
[    1.820683] PC is at irq_setup_generic_chip+0x6a/0x84
[    1.825951] LR is at irq_get_irq_data+0x7/0x8
[    1.830508] pc : [<c006465e>]    lr : [<c0063a03>]    psr: 20000133
[    1.830512] sp : ee04ff58  ip : 00000000  fp : 00000000
[    1.842461] r10: 00000000  r9 : 00000000  r8 : 00000800
[    1.847905] r7 : c064e260  r6 : 000001dc  r5 : 00000001  r4 : ee0accc0
[    1.854687] r3 : 00000002  r2 : 00000800  r1 : 000001dc  r0 : 00000000
[    1.861472] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA Thumb  Segment kernel
[    1.869234] Control: 50c5387d  Table: 8000404a  DAC: 00000015
[    1.875215] Process swapper/0 (pid: 1, stack limit = 0xee04e2f8)
[    1.881463] Stack: (0xee04ff58 to 0xee050000)
[    1.886017] ff40: c061b668 00000008
[    1.894497] ff60: c0682090 ee0accc0 00000003 c001c637 00000000 00000000 00000201 00000000
[    1.902976] ff80: 00000004 c0473820 c0473800 c0459e8d c0680ac0 c000866d 00000004 00000004
[    1.911455] ffa0: ee04ffa8 00000004 c047381c 00000004 c0473820 c0473800 c0680ac0 00000082
[    1.919934] ffc0: c0489694 c045265f 00000004 00000004 c0452135 c000d105 00000033 00000000
[    1.928413] ffe0: c04525b5 c000d111 00000033 00000000 00000000 c000d111 aaaaaaaa aaaaaaaa
[    1.936912] [<c006465e>] (irq_setup_generic_chip+0x6a/0x84) from [<c001c637>] (omap_prcm_register_chain_handler+0x147/0x1a0)
[    1.948516] [<c001c637>] (omap_prcm_register_chain_handler+0x147/0x1a0) from [<c000866d>] (do_one_initcall+0x65/0xf4)
[    1.959500] [<c000866d>] (do_one_initcall+0x65/0xf4) from [<c045265f>] (kernel_init+0xab/0x138)
[    1.968529] [<c045265f>] (kernel_init+0xab/0x138) from [<c000d111>] (kernel_thread_exit+0x1/0x6)
[    1.977632] Code: f7ff f9d1 6b23 1af3 (6043) 086d
[    1.982684] ---[ end trace 1b75b31a2719ed1c ]---
[    1.987526] Kernel panic - not syncing: Attempted to kill init!
exitcode=0x0000000b

Acked-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/prm_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 860118ab43e2..de58b8b878e3 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -291,7 +291,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
 		goto err;
 	}
 
-	for (i = 0; i <= irq_setup->nr_regs; i++) {
+	for (i = 0; i < irq_setup->nr_regs; i++) {
 		gc = irq_alloc_generic_chip("PRCM", 1,
 			irq_setup->base_irq + i * 32, prm_base,
 			handle_level_irq);