From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mike Turquette Subject: Re: [PATCH] twl4030 reboot workaround Date: Wed, 28 Jul 2010 10:47:36 -0500 Message-ID: <4C505118.40807@ti.com> References: <1265226207-22971-3-git-send-email-mturquette@ti.com> <1280310092-27260-1-git-send-email-ext-mikko.rapeli@nokia.com> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1; format=flowed Content-Transfer-Encoding: 7bit Return-path: Received: from bear.ext.ti.com ([192.94.94.41]:33336 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755508Ab0G1Prm (ORCPT ); Wed, 28 Jul 2010 11:47:42 -0400 In-Reply-To: <1280310092-27260-1-git-send-email-ext-mikko.rapeli@nokia.com> Sender: linux-omap-owner@vger.kernel.org List-Id: linux-omap@vger.kernel.org To: Mikko Rapeli Cc: "linux-omap@vger.kernel.org" , "sameo@linux.intel.com" Mikko Rapeli wrote: > From: Mikko Rapeli > > Original patch: http://marc.info/?l=linux-omap&m=126522625032441&w=2 I forgot about this one... > "Removes TWL4030 sleep script prior to rebooting, only on OMAP3. This is > necessary since DPLL3 reset causes SYS_OFFMODE pin to go low, resulting > in the sleep script being executed on TWL4030. This usually results in > VDD1 & VDD2 voltage collapse while ROM code is executing, followed by an > MPU Watch Dog reset or worse, an irrecoverable hang." > > Original patch resulted in a crash due to sleeping i2c calls late in the > reboot sequence. Here's how to trigger the crash: > > # cat /dev/urandom > /foo & > sync(); > reboot(LINUX_REBOOT_CMD_RESTART2); > > Kernel trace from 2.6.32: > > Unable to handle kernel NULL pointer dereference at virtual address 00000000 > pgd = c0004000 > [00000000] *pgd=00000000 > Internal error: Oops: 805 [#2] PREEMPT > ... > [] (exit_mmap+0x1d4/0x1f8) from [] (mmput+0x34/0x110) > [] (mmput+0x34/0x110) from [] (exit_mm+0x140/0x180) > [] (exit_mm+0x140/0x180) from [] (do_exit+0x5d8/0x6ac) > [] (do_exit+0x5d8/0x6ac) from [] (die+0x2d4/0x2e0) > [] (die+0x2d4/0x2e0) from [] (baddataabort+0x0/0x50) > [] (baddataabort+0x0/0x50) from [] (i2c_transfer+0xec/0x104) > [] (i2c_transfer+0xec/0x104) from [<00000001>] (0x1) > > Fix is to move reboot preparations into a reboot notifier. > > Signed-off-by: Mikko Rapeli > --- > drivers/mfd/twl4030-power.c | 29 +++++++++++++++++++++++++++++ > 1 files changed, 29 insertions(+), 0 deletions(-) > > diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c > index 7efa878..5d46768 100644 > --- a/drivers/mfd/twl4030-power.c > +++ b/drivers/mfd/twl4030-power.c > @@ -28,6 +28,7 @@ > #include > #include > #include > +#include > > #include > > @@ -127,6 +128,29 @@ static u8 res_config_addrs[] = { > [RES_Main_Ref] = 0x94, > }; > > +/* > + * PRCM on OMAP3 will drive SYS_OFFMODE low during DPLL3 warm reset. > + * This causes Gaia sleep script to execute, usually killing VDD1 and > + * VDD2 while code is running. WA is to disable the sleep script > + * before warm reset. > + */ > +static int twl4030_prepare_for_reboot(struct notifier_block *this, > + unsigned long cmd, void *p) > +{ > + int err; > + err = twl4030_remove_script(TWL4030_SLEEP_SCRIPT); > + if (err) > + pr_err("TWL4030: error trying to disable sleep script!\n"); > + > + return NOTIFY_DONE; > +} > + > +static struct notifier_block twl4030_reboot_notifier = { > + .notifier_call = twl4030_prepare_for_reboot, > + .next = NULL, > + .priority = 0 > +}; > + > static int __init twl4030_write_script_byte(u8 address, u8 byte) > { > int err; > @@ -549,6 +573,11 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) > err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); > if (err) > pr_err("TWL4030 Unable to relock registers\n"); > + > + err = register_reboot_notifier(&twl4030_reboot_notifier); This method is much better than the method I proposed before. Taking into account the comments from others, ACK. Mike > + if (err) > + pr_err("TWL4030 Failed to register reboot notifier\n"); > + > return; > > unlock: