diff --git a/arch/powerpc/cpu/mpc8xx/Kconfig b/arch/powerpc/cpu/mpc8xx/Kconfig index a7050145129..bfd903bc107 100644 --- a/arch/powerpc/cpu/mpc8xx/Kconfig +++ b/arch/powerpc/cpu/mpc8xx/Kconfig @@ -48,7 +48,8 @@ config SYS_SIUMCR SIU Module Configuration (11-6) config SYS_SYPCR - hex "SYPCR register" + hex "SYPCR register" if !WDT_MPC8xxx + default 0 help System Protection Control (11-9) diff --git a/arch/powerpc/cpu/mpc8xx/cpu_init.c b/arch/powerpc/cpu/mpc8xx/cpu_init.c index 86b08a61749..feef792ee77 100644 --- a/arch/powerpc/cpu/mpc8xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc8xx/cpu_init.c @@ -26,10 +26,9 @@ void cpu_init_f(immap_t __iomem *immr) /* SYPCR - contains watchdog control (11-9) */ -#ifndef CONFIG_HW_WATCHDOG /* deactivate watchdog if not enabled in config */ - out_be32(&immr->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE); -#endif + if (!IS_ENABLED(CONFIG_WDT_MPC8xxx)) + out_be32(&immr->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE); schedule(); diff --git a/arch/powerpc/dts/cmpc885.dts b/arch/powerpc/dts/cmpc885.dts index adda0f3e9dd..7b9566a0fa4 100644 --- a/arch/powerpc/dts/cmpc885.dts +++ b/arch/powerpc/dts/cmpc885.dts @@ -18,11 +18,6 @@ stdout-path = &SERIAL; }; - WDT: watchdog@0 { - device_type = "watchdog"; - compatible = "fsl,pq1-wdt"; - }; - SERIAL: serial { compatible = "fsl,pq1-smc"; }; @@ -43,6 +38,13 @@ ranges = <0 0xff000000 0x4000>; reg = <0xff000000 0x00000200>; + WDT: watchdog@0 { + compatible = "fsl,pq1-wdt"; + reg = <0x0 0x10>; + timeout-sec = <2>; + hw_margin_ms = <1000>; + }; + CPM1_PIO_B: gpio-controller@ab8 { #gpio-cells = <2>; compatible = "fsl,cpm1-pario-bank-b"; diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts index 5f32d8a2e55..c4d7737bc67 100644 --- a/arch/powerpc/dts/mcr3000.dts +++ b/arch/powerpc/dts/mcr3000.dts @@ -9,9 +9,25 @@ /dts-v1/; / { - WDT: watchdog@0 { - compatible = "fsl,pq1-wdt"; + #address-cells = <1>; + #size-cells = <1>; + + soc: immr@ff000000 { + #address-cells = <1>; + #size-cells = <1>; + device-type = "soc"; + compatible = "simple-bus"; + ranges = <0 0xff000000 0x4000>; + reg = <0xff000000 0x00000200>; + + WDT: watchdog@0 { + compatible = "fsl,pq1-wdt"; + reg = <0x0 0x10>; + timeout-sec = <2>; + hw_margin_ms = <1000>; + }; }; + SERIAL: smc@0 { compatible = "fsl,pq1-smc"; }; diff --git a/board/cssi/mcr3000/mcr3000.c b/board/cssi/mcr3000/mcr3000.c index 7b3ab12bd5c..3514f674901 100644 --- a/board/cssi/mcr3000/mcr3000.c +++ b/board/cssi/mcr3000/mcr3000.c @@ -138,17 +138,3 @@ int board_early_init_f(void) return 0; } - -int board_early_init_r(void) -{ - struct udevice *watchdog_dev = NULL; - - if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { - puts("Cannot find watchdog!\n"); - } else { - puts("Enabling watchdog.\n"); - wdt_start(watchdog_dev, 0xffff, 0); - } - - return 0; -} diff --git a/configs/CMPC885_defconfig b/configs/CMPC885_defconfig index 484a81b8d3f..1fe67d02f2f 100644 --- a/configs/CMPC885_defconfig +++ b/configs/CMPC885_defconfig @@ -11,7 +11,6 @@ CONFIG_TARGET_CMPC885=y CONFIG_MPC885=y CONFIG_CMD_IMMAP=y CONFIG_SYS_SIUMCR=0x00620000 -CONFIG_SYS_SYPCR=0xFFFFFF8F CONFIG_SYS_TBSCR=0x00C3 CONFIG_SYS_PISCR=0x0000 CONFIG_SYS_PLPRCR_BOOL=y @@ -106,5 +105,6 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_MPC8XX_SPI=y CONFIG_WDT=y +CONFIG_WDT_MPC8xxx_BME=y # CONFIG_REGEX is not set CONFIG_LZMA=y diff --git a/configs/MCR3000_defconfig b/configs/MCR3000_defconfig index 4b5ce407eae..fc2bf5b2f94 100644 --- a/configs/MCR3000_defconfig +++ b/configs/MCR3000_defconfig @@ -11,7 +11,6 @@ CONFIG_MPC8xx=y CONFIG_TARGET_MCR3000=y CONFIG_CMD_IMMAP=y CONFIG_SYS_SIUMCR=0x00600400 -CONFIG_SYS_SYPCR=0xFFFFFF8F CONFIG_SYS_TBSCR=0x00C3 CONFIG_SYS_PISCR=0x0000 CONFIG_SYS_PLPRCR_BOOL=y @@ -29,7 +28,6 @@ CONFIG_AUTOBOOT_PROMPT="\nEnter password - autoboot in %d sec...\n" CONFIG_AUTOBOOT_DELAY_STR="root" CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="run flashboot" -CONFIG_BOARD_EARLY_INIT_R=y # CONFIG_HWCONFIG is not set CONFIG_MISC_INIT_R=y CONFIG_HUSH_PARSER=y @@ -102,4 +100,5 @@ CONFIG_MPC8XX_FEC=y # CONFIG_PCI is not set CONFIG_DM_SERIAL=y CONFIG_WDT=y +CONFIG_WDT_MPC8xxx_BME=y CONFIG_LZMA=y diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index f6554d5c93e..f7fbb28d80a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -187,10 +187,26 @@ config WDT_MESON_GXBB config WDT_MPC8xxx bool "MPC8xxx watchdog timer support" depends on WDT && MPC8xx - select HW_WATCHDOG help Select this to enable mpc8xxx watchdog timer +config WDT_MPC8xxx_BME + bool "Enable MPC8xx Bus Monitoring" + depends on WDT_MPC8xxx && MPC8xx + help + Select this to enable mpc8xx Bus Monitor. + +config WDT_MPC8xxx_BMT + int "MPC8xx Bus Monitor Timing" if WDT_MPC8xxx_BME + range 0 255 + default 255 + depends on WDT_MPC8xxx + help + Bus monitor timing. Defines the timeout period, in 8 system clock + resolution, for the bus monitor. + + Maximum timeout is 2,040 clocks (255 x 8). + config WDT_MT7620 bool "MediaTek MT7620 watchdog timer support" depends on WDT && SOC_MT7620 diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index ffca3ec877c..9a29938face 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -7,32 +7,61 @@ #include #include #include -#include -#include +#include #include -void hw_watchdog_reset(void) -{ - immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; +struct mpc8xxx_wdt { + __be32 res0; + __be32 swcrr; /* System watchdog control register */ +#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ +#define SWCRR_BME 0x00000080 /* Bus monitor enable (mpc8xx) */ +#define SWCRR_SWF 0x00000008 /* Software Watchdog Freeze (mpc8xx). */ +#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ +#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ +#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ + __be32 swcnr; /* System watchdog count register */ + u8 res1[2]; + __be16 swsrr; /* System watchdog service register */ + u8 res2[0xf0]; +}; - out_be16(&immap->im_siu_conf.sc_swsr, 0x556c); /* write magic1 */ - out_be16(&immap->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */ +struct mpc8xxx_wdt_priv { + struct mpc8xxx_wdt __iomem *base; +}; + +static int mpc8xxx_wdt_reset(struct udevice *dev) +{ + struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev); + + out_be16(&priv->base->swsrr, 0x556c); /* write magic1 */ + out_be16(&priv->base->swsrr, 0xaa39); /* write magic2 */ + + return 0; } static int mpc8xxx_wdt_start(struct udevice *dev, u64 timeout, ulong flags) { - immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; - u32 val = CONFIG_SYS_SYPCR; + struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev); const char *mode = env_get("watchdog_mode"); + ulong prescaler = dev_get_driver_data(dev); + u16 swtc = min_t(u16, timeout * get_board_sys_clk() / 1000 / prescaler, U16_MAX); + u32 val; + + mpc8xxx_wdt_reset(dev); if (strcmp(mode, "off") == 0) - val = val & ~(SYPCR_SWE | SYPCR_SWRI); + val = (swtc << 16) | SWCRR_SWPR; else if (strcmp(mode, "nmi") == 0) - val = (val & ~SYPCR_SWRI) | SYPCR_SWE; + val = (swtc << 16) | SWCRR_SWPR | SWCRR_SWEN; + else + val = (swtc << 16) | SWCRR_SWPR | SWCRR_SWEN | SWCRR_SWRI; - out_be32(&immap->im_siu_conf.sc_sypcr, val); + if (IS_ENABLED(CONFIG_WDT_MPC8xxx_BME)) + val |= (CONFIG_WDT_MPC8xxx_BMT << 8) | SWCRR_BME; - if (!(in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE)) + out_be32(&priv->base->swcrr, val); + + if (!(in_be32(&priv->base->swcrr) & SWCRR_SWEN)) return -EBUSY; return 0; @@ -40,18 +69,23 @@ static int mpc8xxx_wdt_start(struct udevice *dev, u64 timeout, ulong flags) static int mpc8xxx_wdt_stop(struct udevice *dev) { - immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; + struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev); - out_be32(&immap->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE); + clrbits_be32(&priv->base->swcrr, SWCRR_SWEN); - if (in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE) + if (in_be32(&priv->base->swcrr) & SWCRR_SWEN) return -EBUSY; return 0; } -static int mpc8xxx_wdt_reset(struct udevice *dev) +static int mpc8xxx_wdt_of_to_plat(struct udevice *dev) { - hw_watchdog_reset(); + struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev); + + priv->base = (void __iomem *)devfdt_remap_addr(dev); + + if (!priv->base) + return -EINVAL; return 0; } @@ -63,7 +97,7 @@ static const struct wdt_ops mpc8xxx_wdt_ops = { }; static const struct udevice_id mpc8xxx_wdt_ids[] = { - { .compatible = "fsl,pq1-wdt" }, + { .compatible = "fsl,pq1-wdt", .data = 0x800 }, {} }; @@ -72,4 +106,6 @@ U_BOOT_DRIVER(wdt_mpc8xxx) = { .id = UCLASS_WDT, .of_match = mpc8xxx_wdt_ids, .ops = &mpc8xxx_wdt_ops, + .of_to_plat = mpc8xxx_wdt_of_to_plat, + .priv_auto = sizeof(struct mpc8xxx_wdt_priv), };