[PATCH] watchdog: add minimal jz4740 driver
Sascha Hauer
s.hauer at pengutronix.de
Wed Jul 30 23:13:36 PDT 2014
On Thu, Jul 31, 2014 at 02:12:41AM +0400, Antony Pavlov wrote:
> Also move reset_cpu() for jz4755 SoC from platform code
> into the new driver code.
>
> At the moment mach-xburst lacks clk support so jz4740 watchdog
> driver looks like a template. We can improve jz4740 watchdog
> driver in the future after adding clk support
>
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
> arch/mips/dts/jz4755.dtsi | 5 ++
> arch/mips/mach-xburst/Kconfig | 2 +
> arch/mips/mach-xburst/include/mach/jz4750d_regs.h | 22 -----
> arch/mips/mach-xburst/reset-jz4750.c | 18 -----
> drivers/watchdog/Kconfig | 7 ++
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/jz4740.c | 98 +++++++++++++++++++++++
> 7 files changed, 113 insertions(+), 40 deletions(-)
>
> diff --git a/arch/mips/dts/jz4755.dtsi b/arch/mips/dts/jz4755.dtsi
> index 0e655b6..7184635 100644
> --- a/arch/mips/dts/jz4755.dtsi
> +++ b/arch/mips/dts/jz4755.dtsi
> @@ -8,6 +8,11 @@
> #size-cells = <1>;
> ranges;
>
> + wdt: wdt at b0002000 {
> + compatible = "ingenic,jz4740-wdt";
> + reg = <0xb0002000 0x10>;
> + };
> +
> serial0: serial at b0030000 {
> compatible = "ingenic,jz4740-uart";
> reg = <0xb0030000 0x20>;
> diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig
> index 706d592..f7b8470 100644
> --- a/arch/mips/mach-xburst/Kconfig
> +++ b/arch/mips/mach-xburst/Kconfig
> @@ -6,6 +6,8 @@ config ARCH_TEXT_BASE
>
> config CPU_JZ4755
> bool
> + select WATCHDOG
> + select WATCHDOG_JZ4740
>
> choice
> prompt "Board type"
> diff --git a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h
> index 7a3daad..396c823 100644
> --- a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h
> +++ b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h
> @@ -59,28 +59,6 @@
> #define TCU_OSTCSR_PCK_EN (1 << 0) /* select pclk as the timer clock input */
>
> /*************************************************************************
> - * WDT (WatchDog Timer)
> - *************************************************************************/
> -#define WDT_TDR (WDT_BASE + 0x00)
> -#define WDT_TCER (WDT_BASE + 0x04)
> -#define WDT_TCNT (WDT_BASE + 0x08)
> -#define WDT_TCSR (WDT_BASE + 0x0c)
> -
> -#define WDT_TCSR_PRESCALE_BIT 3
> -#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT)
> - #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT)
> - #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT)
> - #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT)
> - #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT)
> - #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT)
> - #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT)
> -#define WDT_TCSR_EXT_EN (1 << 2)
> -#define WDT_TCSR_RTC_EN (1 << 1)
> -#define WDT_TCSR_PCK_EN (1 << 0)
> -
> -#define WDT_TCER_TCEN (1 << 0)
> -
> -/*************************************************************************
> * RTC
> *************************************************************************/
> #define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */
> diff --git a/arch/mips/mach-xburst/reset-jz4750.c b/arch/mips/mach-xburst/reset-jz4750.c
> index 8f33672..25830f1 100644
> --- a/arch/mips/mach-xburst/reset-jz4750.c
> +++ b/arch/mips/mach-xburst/reset-jz4750.c
> @@ -24,8 +24,6 @@
> #include <io.h>
> #include <mach/jz4750d_regs.h>
>
> -#define JZ_EXTAL 24000000
> -
> static void __noreturn jz4750d_halt(void)
> {
> while (1) {
> @@ -39,22 +37,6 @@ static void __noreturn jz4750d_halt(void)
> unreachable();
> }
>
> -void __noreturn reset_cpu(ulong addr)
> -{
> - __raw_writew(WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN, (u16 *)WDT_TCSR);
> - __raw_writew(0, (u16 *)WDT_TCNT);
> -
> - /* reset after 4ms */
> - __raw_writew(JZ_EXTAL / 1000, (u16 *)WDT_TDR);
> - /* enable wdt clock */
> - __raw_writel(TCU_TSCR_WDTSC, (u32 *)TCU_TSCR);
> - /* start wdt */
> - __raw_writeb(WDT_TCER_TCEN, (u8 *)WDT_TCER);
> -
> - unreachable();
> -}
> -EXPORT_SYMBOL(reset_cpu);
> -
> void __noreturn poweroff()
> {
> u32 ctrl;
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 2e2900c..7f7b02e 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -21,4 +21,11 @@ config WATCHDOG_IMX
> depends on ARCH_IMX
> help
> Add support for watchdog found on Freescale i.MX SoCs.
> +
> +config WATCHDOG_JZ4740
> + bool "Ingenic jz4740 SoC hardware watchdog"
> + depends on MACH_MIPS_XBURST
> + help
> + Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
> +
> endif
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index f522b88..865fc47 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -1,3 +1,4 @@
> obj-$(CONFIG_WATCHDOG) += wd_core.o
> obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o
> +obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o
> obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o
> diff --git a/drivers/watchdog/jz4740.c b/drivers/watchdog/jz4740.c
> new file mode 100644
> index 0000000..ac1ff42
> --- /dev/null
> +++ b/drivers/watchdog/jz4740.c
> @@ -0,0 +1,98 @@
> +/*
> + * JZ4740 Watchdog driver
> + *
> + * Copyright (C) 2014 Antony Pavlov <antonynpavlov at gmail.com>
> + *
> + * Based on jz4740_wdt.c from linux-3.15.
> + *
> + * Copyright (C) 2010, Paul Cercueil <paul at crapouillou.net>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <io.h>
> +
> +#define JZ_REG_WDT_TIMER_DATA 0x0
> +#define JZ_REG_WDT_COUNTER_ENABLE 0x4
> +#define JZ_REG_WDT_TIMER_COUNTER 0x8
> +#define JZ_REG_WDT_TIMER_CONTROL 0xC
> +
> +#define JZ_WDT_CLOCK_PCLK 0x1
> +#define JZ_WDT_CLOCK_RTC 0x2
> +#define JZ_WDT_CLOCK_EXT 0x4
> +
> +#define JZ_WDT_CLOCK_DIV_SHIFT 3
> +
> +#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT)
> +#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT)
> +#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT)
> +#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT)
> +#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT)
> +#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT)
> +
> +#define JZ_EXTAL 24000000
> +
> +struct jz4740_wdt_drvdata {
> + void __iomem *base;
> +};
> +
> +static struct jz4740_wdt_drvdata *reset_wd;
> +
> +void __noreturn reset_cpu(unsigned long addr)
> +{
> + if (reset_wd) {
> + void __iomem *base = reset_wd->base;
> +
> + writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT,
> + base + JZ_REG_WDT_TIMER_CONTROL);
> + writew(0, base + JZ_REG_WDT_TIMER_COUNTER);
> +
> + /* reset after 4ms */
> + writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA);
> +
> + /* start wdt */
> + writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE);
> +
> + mdelay(1000);
> + } else
> + pr_err("%s: can't reset cpu\n", __func__);
> +
> + hang();
> +}
> +EXPORT_SYMBOL(reset_cpu);
> +
> +static int jz4740_wdt_probe(struct device_d *dev)
> +{
> + struct jz4740_wdt_drvdata *priv;
> +
> + priv = xzalloc(sizeof(struct jz4740_wdt_drvdata));
> + priv->base = dev_request_mem_region(dev, 0);
Please check the return value.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the barebox
mailing list