diff mbox

[U-Boot] arm, arm335x: add watchdog support

Message ID 1370336136-14238-1-git-send-email-hs@denx.de
State Superseded
Delegated to: Tom Rini
Headers show

Commit Message

Heiko Schocher June 4, 2013, 8:55 a.m. UTC
Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.

Signed-off-by: Heiko Schocher <hs@denx.de>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
Cc: Tom Rini <trini@ti.com>
---
 arch/arm/include/asm/arch-am33xx/cpu.h |  20 ++++++
 drivers/watchdog/Makefile              |   1 +
 drivers/watchdog/omap_wdt.c            | 115 +++++++++++++++++++++++++++++++++
 3 Dateien geändert, 136 Zeilen hinzugefügt(+)
 create mode 100644 drivers/watchdog/omap_wdt.c

Comments

Tom Rini June 4, 2013, 9:24 p.m. UTC | #1
On Tue, Jun 04, 2013 at 10:55:36AM +0200, Heiko Schocher wrote:

> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
> 
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Cc: Albert Aribaud <albert.u.boot@aribaud.net>
> Cc: Tom Rini <trini@ti.com>

Reviewed-by: Tom Rini <trini@ti.com>

But this is also unused code right now.  Enabling on the am335x_evm
config is a good place-holder and easy for you to test I assume platform
until you can also post the custom board you're working on.
Heiko Schocher June 5, 2013, 5:22 a.m. UTC | #2
Hello Tom,

Am 04.06.2013 23:24, schrieb Tom Rini:
> On Tue, Jun 04, 2013 at 10:55:36AM +0200, Heiko Schocher wrote:
> 
>> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
>>
>> Signed-off-by: Heiko Schocher <hs@denx.de>
>> Cc: Albert Aribaud <albert.u.boot@aribaud.net>
>> Cc: Tom Rini <trini@ti.com>
> 
> Reviewed-by: Tom Rini <trini@ti.com>
> 
> But this is also unused code right now.  Enabling on the am335x_evm
> config is a good place-holder and easy for you to test I assume platform
> until you can also post the custom board you're working on.

I repost this patch with the board support, ok?

bye,
Heiko
Tom Rini June 5, 2013, 12:19 p.m. UTC | #3
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 06/05/2013 01:22 AM, Heiko Schocher wrote:
> Hello Tom,
> 
> Am 04.06.2013 23:24, schrieb Tom Rini:
>> On Tue, Jun 04, 2013 at 10:55:36AM +0200, Heiko Schocher wrote:
>> 
>>> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog 
>>> support.
>>> 
>>> Signed-off-by: Heiko Schocher <hs@denx.de> Cc: Albert Aribaud 
>>> <albert.u.boot@aribaud.net> Cc: Tom Rini <trini@ti.com>
>> 
>> Reviewed-by: Tom Rini <trini@ti.com>
>> 
>> But this is also unused code right now.  Enabling on the 
>> am335x_evm config is a good place-holder and easy for you to
>> test I assume platform until you can also post the custom board
>> you're working on.
> 
> I repost this patch with the board support, ok?

OK, thanks.

- -- 
Tom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJRryzkAAoJENk4IS6UOR1WX0UP/jxsDh51DNxGlUEtqg03LxhR
FV4bN1yMrcFogeBacW3YIDhq0kgZ+afvxSo3yigExZt0FnWpnAUN1AD4W3fwtB4D
UyNWfmI0KIGyY0/N83hNX1ABtmdILr6eDZEf9xoNfNGh4IQZDGXgaAcgincwZ10d
HioI1cYOHRvMG/VZ4LFj7b5QrhSax2fm5dm51bq0ioII1qdfE4vV+bNgX271mPdB
hfV2XCVsB1wm7MuC1v8NdRDXUly5g2ARIcHq9smdVOiwHl94nS8KOiaM6QAcwB0R
wN/x/h6hYcDVXIrxLvVn+ZRYk96RzurywylNws4xQco7WHKISKTrsWXXmj+ecodX
DWVC1Dk+Ch/V/sJyf+1+p7ctg/PfA/P9VYqdjwrhoTrVTj+4Ds34qOwqW+cx0I+J
Eb5SbeTtjBzMoMWl9f11eJiQ7HqhR6qSijJ2HQlJgVOqMeBbpv1PKAdzRoGWVz2a
QsXUcALr1IkHzn4lKJ2qFDf+erZhTCyWOpeL4BTsqp3hSOJs1BxkRtanpZJU8tzj
9shXkwyCyzXMIxT98WmNB3+p5HaCMoQFOvebVSxTTx9jziuz8+Y9b9+xe7AAcZoU
yAA1a+DmZufkc2sygrC2XENWkEukLro1ir1ivi2sInpA6+i2iWv+YmBgdUpXZIjC
Q6zC5K0jO13kA2wmrY8P
=e8Ph
-----END PGP SIGNATURE-----
Michael Nazzareno Trimarchi June 5, 2013, 1:31 p.m. UTC | #4
Hi

On Jun 4, 2013 10:55 AM, "Heiko Schocher" <hs@denx.de> wrote:
>
> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
>
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Cc: Albert Aribaud <albert.u.boot@aribaud.net>
> Cc: Tom Rini <trini@ti.com>
> ---
>  arch/arm/include/asm/arch-am33xx/cpu.h |  20 ++++++
>  drivers/watchdog/Makefile              |   1 +
>  drivers/watchdog/omap_wdt.c            | 115
+++++++++++++++++++++++++++++++++
>  3 Dateien geändert, 136 Zeilen hinzugefügt(+)
>  create mode 100644 drivers/watchdog/omap_wdt.c
>
> diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h
b/arch/arm/include/asm/arch-am33xx/cpu.h
> index 3d3a7c8..fb44654 100644
> --- a/arch/arm/include/asm/arch-am33xx/cpu.h
> +++ b/arch/arm/include/asm/arch-am33xx/cpu.h
> @@ -61,6 +61,26 @@
>  #define PRM_RSTCTRL_RESET              0x01
>  #define PRM_RSTST_WARM_RESET_MASK      0x232
>
> +/*
> + * Watchdog:
> + * Using the prescaler, the OMAP watchdog could go for many
> + * months before firing.  These limits work without scaling,
> + * with the 60 second default assumed by most tools and docs.
> + */
> +#define TIMER_MARGIN_MAX       (24 * 60 * 60)  /* 1 day */
> +#define TIMER_MARGIN_DEFAULT   60      /* 60 secs */
> +#define TIMER_MARGIN_MIN       1
> +
> +#define PTV                    0       /* prescale */
> +#define GET_WLDR_VAL(secs)     (0xffffffff - ((secs) * (32768/(1<<PTV)))
+ 1)
> +#define WDT_WWPS_PEND_WCLR     BIT(0)
> +#define WDT_WWPS_PEND_WLDR     BIT(2)
> +#define WDT_WWPS_PEND_WTGR     BIT(3)
> +#define WDT_WWPS_PEND_WSPR     BIT(4)
> +
> +#define WDT_WCLR_PRE           BIT(5)
> +#define WDT_WCLR_PTV_OFF       2
> +
>  #ifndef __KERNEL_STRICT_NAMES
>  #ifndef __ASSEMBLY__
>  struct gpmc_cs {
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index d57578d..46adc42 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -34,6 +34,7 @@ COBJS-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o
>  COBJS-$(CONFIG_S5P)               += s5p_wdt.o
>  COBJS-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
>  COBJS-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
> +COBJS-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
>
>  COBJS  := $(COBJS-y)
>  SRCS   := $(COBJS:.o=.c)
> diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
> new file mode 100644
> index 0000000..dc4df98
> --- /dev/null
> +++ b/drivers/watchdog/omap_wdt.c
> @@ -0,0 +1,115 @@
> +/*
> + * omap_wdt.c
> + *
> + * (C) Copyright 2013
> + * Heiko Schocher, DENX Software Engineering, hs@denx.de.
> + *
> + * Based on:
> + *
> + * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure)
watchdog
> + *
> + * Author: MontaVista Software, Inc.
> + *      <gdavis@mvista.com> or <source@mvista.com>
> + *
> + * 2003 (c) MontaVista Software, Inc. This file is licensed under the
> + * terms of the GNU General Public License version 2. This program is
> + * licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + *
> + * History:
> + *
> + * 20030527: George G. Davis <gdavis@mvista.com>
> + *     Initially based on
linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
> + *     (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
> + *     Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk>
> + *
> + * Copyright (c) 2004 Texas Instruments.
> + *     1. Modified to support OMAP1610 32-KHz watchdog timer
> + *     2. Ported to 2.6 kernel
> + *
> + * Copyright (c) 2005 David Brownell
> + *     Use the driver model and standard identifiers; handle bigger
timeouts.
> + */
> +
> +#include <common.h>
> +#include <watchdog.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/io.h>
> +#include <asm/processor.h>
> +#include <asm/arch/cpu.h>
> +
> +/* Hardware timeout in seconds */
> +#define WDT_HW_TIMEOUT 60
> +
> +static unsigned int wdt_trgr_pattern = 0x1234;
> +
> +void hw_watchdog_reset(void)
> +{
> +       struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
> +
> +       /* wait for posted write to complete */
> +       while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WTGR)
> +               ;
> +
> +       wdt_trgr_pattern = ~wdt_trgr_pattern;
> +       writel(wdt_trgr_pattern, &wdt->wdtwtgr);
> +
> +       /* wait for posted write to complete */
> +       while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
> +               ;
> +}
> +

I think that this patch has some problem because watchdog reset is in getc
code. Did you try to paste very long string when it is enabled? You need to
avoid reset when it is not needed

Michael

> +static int omap_wdt_set_timeout(unsigned int timeout)
> +{
> +       struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
> +       u32 pre_margin = GET_WLDR_VAL(timeout);
> +
> +       /* just count up at 32 KHz */
> +       while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
> +               ;
> +
> +       writel(pre_margin, &wdt->wdtwldr);
> +       while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
> +               ;
> +
> +       return 0;
> +}
> +
> +void hw_watchdog_init(void)
> +{
> +       struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
> +
> +       /* initialize prescaler */
> +       while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
> +               ;
> +
> +       writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &wdt->wdtwclr);
> +       while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
> +               ;
> +
> +       omap_wdt_set_timeout(WDT_HW_TIMEOUT);
> +
> +       /* Sequence to enable the watchdog */
> +       writel(0xBBBB, &wdt->wdtwspr);
> +       while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
> +               ;
> +
> +       writel(0x4444, &wdt->wdtwspr);
> +       while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
> +               ;
> +}
> +
> +void hw_watchdog_disable(void)
> +{
> +       struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
> +
> +       /*
> +        * Disable watchdog
> +        */
> +       writel(0xAAAA, &wdt->wdtwspr);
> +       while (readl(&wdt->wdtwwps) != 0x0)
> +               ;
> +       writel(0x5555, &wdt->wdtwspr);
> +       while (readl(&wdt->wdtwwps) != 0x0)
> +               ;
> +}
> --
> 1.7.11.7
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
Heiko Schocher June 5, 2013, 2:17 p.m. UTC | #5
Hello Michael,

Am 05.06.2013 15:31, schrieb Michael Trimarchi:
> Hi
> 
> On Jun 4, 2013 10:55 AM, "Heiko Schocher" <hs@denx.de <mailto:hs@denx.de>> wrote:
>>
>> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
>>
>> Signed-off-by: Heiko Schocher <hs@denx.de <mailto:hs@denx.de>>
>> Cc: Albert Aribaud <albert.u.boot@aribaud.net <mailto:albert.u.boot@aribaud.net>>
>> Cc: Tom Rini <trini@ti.com <mailto:trini@ti.com>>
>> ---
>>  arch/arm/include/asm/arch-am33xx/cpu.h |  20 ++++++
>>  drivers/watchdog/Makefile              |   1 +
>>  drivers/watchdog/omap_wdt.c            | 115 +++++++++++++++++++++++++++++++++
>>  3 Dateien geändert, 136 Zeilen hinzugefügt(+)
>>  create mode 100644 drivers/watchdog/omap_wdt.c
[...]
>> diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
>> new file mode 100644
>> index 0000000..dc4df98
>> --- /dev/null
>> +++ b/drivers/watchdog/omap_wdt.c
>> @@ -0,0 +1,115 @@
[...]
>> +       /* wait for posted write to complete */
>> +       while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
>> +               ;
>> +}
>> +
> 
> I think that this patch has some problem because watchdog reset is in getc code. Did you try to paste very long string when it is enabled? You need to
> avoid reset when it is not needed

I think, I do not understand you ... this is for all watchdogs
the case ...

I currently pasted a 500 bytes long string, seeing no problems
with the watchdog...

bye,
Heiko
Michael Nazzareno Trimarchi June 5, 2013, 2:21 p.m. UTC | #6
Hi

On Jun 5, 2013 4:17 PM, "Heiko Schocher" <hs@denx.de> wrote:
>
> Hello Michael,
>
> Am 05.06.2013 15:31, schrieb Michael Trimarchi:
> > Hi
> >
> > On Jun 4, 2013 10:55 AM, "Heiko Schocher" <hs@denx.de <mailto:hs@denx.de>>
wrote:
> >>
> >> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
> >>
> >> Signed-off-by: Heiko Schocher <hs@denx.de <mailto:hs@denx.de>>
> >> Cc: Albert Aribaud <albert.u.boot@aribaud.net <mailto:
albert.u.boot@aribaud.net>>
> >> Cc: Tom Rini <trini@ti.com <mailto:trini@ti.com>>
> >> ---
> >>  arch/arm/include/asm/arch-am33xx/cpu.h |  20 ++++++
> >>  drivers/watchdog/Makefile              |   1 +
> >>  drivers/watchdog/omap_wdt.c            | 115
+++++++++++++++++++++++++++++++++
> >>  3 Dateien geändert, 136 Zeilen hinzugefügt(+)
> >>  create mode 100644 drivers/watchdog/omap_wdt.c
> [...]
> >> diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
> >> new file mode 100644
> >> index 0000000..dc4df98
> >> --- /dev/null
> >> +++ b/drivers/watchdog/omap_wdt.c
> >> @@ -0,0 +1,115 @@
> [...]
> >> +       /* wait for posted write to complete */
> >> +       while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
> >> +               ;
> >> +}
> >> +
> >
> > I think that this patch has some problem because watchdog reset is in
getc code. Did you try to paste very long string when it is enabled? You
need to
> > avoid reset when it is not needed
>
> I think, I do not understand you ... this is for all watchdogs
> the case ...
>
> I currently pasted a 500 bytes long string, seeing no problems
> with the watchdog...
>

OK, maybe was a problem of my version. I have done the same driver 2 month
ago and tested on omap3. I optimize the watchdog reset using time delaying.
BTW if it works I have no other comments. Sorry for the noise

Michael

> bye,
> Heiko
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Heiko Schocher June 5, 2013, 2:26 p.m. UTC | #7
Hello Michael,

Am 05.06.2013 16:21, schrieb Michael Trimarchi:
> Hi
> 
> On Jun 5, 2013 4:17 PM, "Heiko Schocher" <hs@denx.de <mailto:hs@denx.de>> wrote:
>>
>> Hello Michael,
>>
>> Am 05.06.2013 15:31, schrieb Michael Trimarchi:
>> > Hi
>> >
>> > On Jun 4, 2013 10:55 AM, "Heiko Schocher" <hs@denx.de <mailto:hs@denx.de> <mailto:hs@denx.de <mailto:hs@denx.de>>> wrote:
>> >>
>> >> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
>> >>
>> >> Signed-off-by: Heiko Schocher <hs@denx.de <mailto:hs@denx.de> <mailto:hs@denx.de <mailto:hs@denx.de>>>
>> >> Cc: Albert Aribaud <albert.u.boot@aribaud.net <mailto:albert.u.boot@aribaud.net> <mailto:albert.u.boot@aribaud.net
> <mailto:albert.u.boot@aribaud.net>>>
>> >> Cc: Tom Rini <trini@ti.com <mailto:trini@ti.com> <mailto:trini@ti.com <mailto:trini@ti.com>>>
>> >> ---
>> >>  arch/arm/include/asm/arch-am33xx/cpu.h |  20 ++++++
>> >>  drivers/watchdog/Makefile              |   1 +
>> >>  drivers/watchdog/omap_wdt.c            | 115 +++++++++++++++++++++++++++++++++
>> >>  3 Dateien geändert, 136 Zeilen hinzugefügt(+)
>> >>  create mode 100644 drivers/watchdog/omap_wdt.c
>> [...]
>> >> diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
>> >> new file mode 100644
>> >> index 0000000..dc4df98
>> >> --- /dev/null
>> >> +++ b/drivers/watchdog/omap_wdt.c
>> >> @@ -0,0 +1,115 @@
>> [...]
>> >> +       /* wait for posted write to complete */
>> >> +       while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
>> >> +               ;
>> >> +}
>> >> +
>> >
>> > I think that this patch has some problem because watchdog reset is in getc code. Did you try to paste very long string when it is enabled? You need to
>> > avoid reset when it is not needed
>>
>> I think, I do not understand you ... this is for all watchdogs
>> the case ...
>>
>> I currently pasted a 500 bytes long string, seeing no problems
>> with the watchdog...
>>
> 
> OK, maybe was a problem of my version. I have done the same driver 2 month ago and tested on omap3. I optimize the watchdog reset using time delaying.
> BTW if it works I have no other comments. Sorry for the noise

Maybe you have a chance to try this patch on your hw?

bye,
Heiko
Michael Nazzareno Trimarchi June 5, 2013, 8:58 p.m. UTC | #8
Hi

On Jun 5, 2013 4:27 PM, "Heiko Schocher" <hs@denx.de> wrote:
>
> Hello Michael,
>
> Am 05.06.2013 16:21, schrieb Michael Trimarchi:
> > Hi
> >
> > On Jun 5, 2013 4:17 PM, "Heiko Schocher" <hs@denx.de <mailto:hs@denx.de>>
wrote:
> >>
> >> Hello Michael,
> >>
> >> Am 05.06.2013 15:31, schrieb Michael Trimarchi:
> >> > Hi
> >> >
> >> > On Jun 4, 2013 10:55 AM, "Heiko Schocher" <hs@denx.de <mailto:
hs@denx.de> <mailto:hs@denx.de <mailto:hs@denx.de>>> wrote:
> >> >>
> >> >> Add TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog support.
> >> >>
> >> >> Signed-off-by: Heiko Schocher <hs@denx.de <mailto:hs@denx.de>
<mailto:hs@denx.de <mailto:hs@denx.de>>>
> >> >> Cc: Albert Aribaud <albert.u.boot@aribaud.net <mailto:
albert.u.boot@aribaud.net> <mailto:albert.u.boot@aribaud.net
> > <mailto:albert.u.boot@aribaud.net>>>
> >> >> Cc: Tom Rini <trini@ti.com <mailto:trini@ti.com> <mailto:
trini@ti.com <mailto:trini@ti.com>>>
> >> >> ---
> >> >>  arch/arm/include/asm/arch-am33xx/cpu.h |  20 ++++++
> >> >>  drivers/watchdog/Makefile              |   1 +
> >> >>  drivers/watchdog/omap_wdt.c            | 115
+++++++++++++++++++++++++++++++++
> >> >>  3 Dateien geändert, 136 Zeilen hinzugefügt(+)
> >> >>  create mode 100644 drivers/watchdog/omap_wdt.c
> >> [...]
> >> >> diff --git a/drivers/watchdog/omap_wdt.c
b/drivers/watchdog/omap_wdt.c
> >> >> new file mode 100644
> >> >> index 0000000..dc4df98
> >> >> --- /dev/null
> >> >> +++ b/drivers/watchdog/omap_wdt.c
> >> >> @@ -0,0 +1,115 @@
> >> [...]
> >> >> +       /* wait for posted write to complete */
> >> >> +       while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
> >> >> +               ;
> >> >> +}
> >> >> +
> >> >
> >> > I think that this patch has some problem because watchdog reset is
in getc code. Did you try to paste very long string when it is enabled? You
need to
> >> > avoid reset when it is not needed
> >>
> >> I think, I do not understand you ... this is for all watchdogs
> >> the case ...
> >>
> >> I currently pasted a 500 bytes long string, seeing no problems
> >> with the watchdog...
> >>
> >
> > OK, maybe was a problem of my version. I have done the same driver 2
month ago and tested on omap3. I optimize the watchdog reset using time
delaying.
> > BTW if it works I have no other comments. Sorry for the noise
>
> Maybe you have a chance to try this patch on your hw?
>

Yes I can or I can ask.

Michael

> bye,
> Heiko
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index 3d3a7c8..fb44654 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -61,6 +61,26 @@ 
 #define PRM_RSTCTRL_RESET		0x01
 #define PRM_RSTST_WARM_RESET_MASK	0x232
 
+/*
+ * Watchdog:
+ * Using the prescaler, the OMAP watchdog could go for many
+ * months before firing.  These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX	(24 * 60 * 60)	/* 1 day */
+#define TIMER_MARGIN_DEFAULT	60	/* 60 secs */
+#define TIMER_MARGIN_MIN	1
+
+#define PTV			0	/* prescale */
+#define GET_WLDR_VAL(secs)	(0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+#define WDT_WWPS_PEND_WCLR	BIT(0)
+#define WDT_WWPS_PEND_WLDR	BIT(2)
+#define WDT_WWPS_PEND_WTGR	BIT(3)
+#define WDT_WWPS_PEND_WSPR	BIT(4)
+
+#define WDT_WCLR_PRE		BIT(5)
+#define WDT_WCLR_PTV_OFF	2
+
 #ifndef __KERNEL_STRICT_NAMES
 #ifndef __ASSEMBLY__
 struct gpmc_cs {
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index d57578d..46adc42 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -34,6 +34,7 @@  COBJS-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o
 COBJS-$(CONFIG_S5P)               += s5p_wdt.o
 COBJS-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
 COBJS-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
+COBJS-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
new file mode 100644
index 0000000..dc4df98
--- /dev/null
+++ b/drivers/watchdog/omap_wdt.c
@@ -0,0 +1,115 @@ 
+/*
+ * omap_wdt.c
+ *
+ * (C) Copyright 2013
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * Based on:
+ *
+ * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog
+ *
+ * Author: MontaVista Software, Inc.
+ *	 <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * History:
+ *
+ * 20030527: George G. Davis <gdavis@mvista.com>
+ *	Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
+ *	(c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *	Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ * Copyright (c) 2004 Texas Instruments.
+ *	1. Modified to support OMAP1610 32-KHz watchdog timer
+ *	2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *	Use the driver model and standard identifiers; handle bigger timeouts.
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch/cpu.h>
+
+/* Hardware timeout in seconds */
+#define WDT_HW_TIMEOUT 60
+
+static unsigned int wdt_trgr_pattern = 0x1234;
+
+void hw_watchdog_reset(void)
+{
+	struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
+
+	/* wait for posted write to complete */
+	while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WTGR)
+		;
+
+	wdt_trgr_pattern = ~wdt_trgr_pattern;
+	writel(wdt_trgr_pattern, &wdt->wdtwtgr);
+
+	/* wait for posted write to complete */
+	while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
+		;
+}
+
+static int omap_wdt_set_timeout(unsigned int timeout)
+{
+	struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
+	u32 pre_margin = GET_WLDR_VAL(timeout);
+
+	/* just count up at 32 KHz */
+	while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
+		;
+
+	writel(pre_margin, &wdt->wdtwldr);
+	while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
+		;
+
+	return 0;
+}
+
+void hw_watchdog_init(void)
+{
+	struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
+
+	/* initialize prescaler */
+	while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
+		;
+
+	writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &wdt->wdtwclr);
+	while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
+		;
+
+	omap_wdt_set_timeout(WDT_HW_TIMEOUT);
+
+	/* Sequence to enable the watchdog */
+	writel(0xBBBB, &wdt->wdtwspr);
+	while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
+		;
+
+	writel(0x4444, &wdt->wdtwspr);
+	while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
+		;
+}
+
+void hw_watchdog_disable(void)
+{
+	struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
+
+	/*
+	 * Disable watchdog
+	 */
+	writel(0xAAAA, &wdt->wdtwspr);
+	while (readl(&wdt->wdtwwps) != 0x0)
+		;
+	writel(0x5555, &wdt->wdtwspr);
+	while (readl(&wdt->wdtwwps) != 0x0)
+		;
+}