From patchwork Mon Jan 6 14:13:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 239163 List-Id: U-Boot discussion From: marex at denx.de (Marek Vasut) Date: Mon, 6 Jan 2020 15:13:44 +0100 Subject: [PATCH V3 1/3] watchdog: designware: Migrate CONFIG_DESIGNWARE_WATCHDOG to Kconfig Message-ID: <20200106141346.47008-1-marex@denx.de> Migrate CONFIG_DESIGNWARE_WATCHDOG to Kconfig and update the headers accordingly, no functional change. The S10 enables the WDT only in SPL, but does not enable it in U-Boot itself, hence disable it in the config again. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dalon Westergreen Cc: Dinh Nguyen Cc: Jagan Teki Cc: Ley Foon Tan Cc: Philipp Tomisch Cc: Simon Goldschmidt Cc: Tien Fong Chee Reviewed-by: Jagan Teki Tested-by: Jagan Teki # roc-rk3399-pc --- V2: Use non-DM watchdog in SPL on S10 V3: No changes --- configs/socfpga_stratix10_defconfig | 1 + configs/socfpga_vining_fpga_defconfig | 1 + drivers/watchdog/Kconfig | 7 +++++++ include/configs/socfpga_common.h | 4 +--- include/configs/socfpga_stratix10_socdk.h | 7 +++++-- scripts/config_whitelist.txt | 1 - 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig index 0665b460de..82ffedf41a 100644 --- a/configs/socfpga_stratix10_defconfig +++ b/configs/socfpga_stratix10_defconfig @@ -59,3 +59,4 @@ CONFIG_DM_USB=y CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y # CONFIG_SPL_USE_TINY_PRINTF is not set +CONFIG_DESIGNWARE_WATCHDOG=y diff --git a/configs/socfpga_vining_fpga_defconfig b/configs/socfpga_vining_fpga_defconfig index 19bed6be27..0e31e4f165 100644 --- a/configs/socfpga_vining_fpga_defconfig +++ b/configs/socfpga_vining_fpga_defconfig @@ -97,3 +97,4 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 CONFIG_USB_GADGET_DWC2_OTG=y CONFIG_USB_GADGET_DOWNLOAD=y # CONFIG_SPL_WDT is not set +CONFIG_DESIGNWARE_WATCHDOG=y diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 8c16d69d33..5f8a070ef5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -45,6 +45,13 @@ config ULP_WATCHDOG help Say Y here to enable i.MX7ULP watchdog driver. +config DESIGNWARE_WATCHDOG + bool "Designware watchdog timer support" + select HW_WATCHDOG + help + Enable this to support Designware Watchdog Timer IP, present e.g. + on Altera SoCFPGA SoCs. + config WDT bool "Enable driver model for watchdog timer drivers" depends on DM diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h index 05bfef75c0..d1a14d23aa 100644 --- a/include/configs/socfpga_common.h +++ b/include/configs/socfpga_common.h @@ -104,11 +104,9 @@ /* * L4 Watchdog */ -#ifdef CONFIG_HW_WATCHDOG -#define CONFIG_DESIGNWARE_WATCHDOG #define CONFIG_DW_WDT_BASE SOCFPGA_L4WD0_ADDRESS #define CONFIG_DW_WDT_CLOCK_KHZ 25000 -#endif +#define CONFIG_WATCHDOG_TIMEOUT_MSECS 30000 /* * MMC Driver diff --git a/include/configs/socfpga_stratix10_socdk.h b/include/configs/socfpga_stratix10_socdk.h index a10cbec17f..f7a4a30f3a 100644 --- a/include/configs/socfpga_stratix10_socdk.h +++ b/include/configs/socfpga_stratix10_socdk.h @@ -152,13 +152,16 @@ unsigned int cm_get_qspi_controller_clk_hz(void); */ #ifdef CONFIG_SPL_BUILD #define CONFIG_HW_WATCHDOG -#define CONFIG_DESIGNWARE_WATCHDOG +#else +#undef CONFIG_HW_WATCHDOG +#undef CONFIG_DESIGNWARE_WATCHDOG +#endif #define CONFIG_DW_WDT_BASE SOCFPGA_L4WD0_ADDRESS #ifndef __ASSEMBLY__ unsigned int cm_get_l4_sys_free_clk_hz(void); #define CONFIG_DW_WDT_CLOCK_KHZ (cm_get_l4_sys_free_clk_hz() / 1000) #endif -#endif +#define CONFIG_WATCHDOG_TIMEOUT_MSECS 3000 /* * SPL memory layout diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index cf1808e051..5984e579da 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -312,7 +312,6 @@ CONFIG_DEFAULT_IMMR CONFIG_DEF_HWCONFIG CONFIG_DELAY_ENVIRONMENT CONFIG_DESIGNWARE_ETH -CONFIG_DESIGNWARE_WATCHDOG CONFIG_DEVELOP CONFIG_DEVICE_TREE_LIST CONFIG_DFU_ALT From patchwork Mon Jan 6 14:13:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 239165 List-Id: U-Boot discussion From: marex at denx.de (Marek Vasut) Date: Mon, 6 Jan 2020 15:13:45 +0100 Subject: [PATCH V3 2/3] watchdog: designware: Convert to DM and DT probing In-Reply-To: <20200106141346.47008-1-marex@denx.de> References: <20200106141346.47008-1-marex@denx.de> Message-ID: <20200106141346.47008-2-marex@denx.de> Convert the designware watchdog timer driver to DM and add DT probing support. Perform minor coding style clean up, like drop superfluous braces. These ought to be no functional change. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dalon Westergreen Cc: Dinh Nguyen Cc: Jagan Teki Cc: Ley Foon Tan Cc: Philipp Tomisch Cc: Simon Goldschmidt Cc: Tien Fong Chee Reviewed-by: Jagan Teki Tested-by: Jagan Teki # roc-rk3399-pc --- V2: - Support both DM and non-DM probing - Fix watchdog stop handling by setting CR bit V3: - Add missing u-boot,dm-pre-reloc into the DTs --- .../socfpga_cyclone5_vining_fpga-u-boot.dtsi | 4 + .../dts/socfpga_stratix10_socdk-u-boot.dtsi | 4 + configs/socfpga_stratix10_defconfig | 2 + configs/socfpga_vining_fpga_defconfig | 1 + drivers/watchdog/Kconfig | 2 +- drivers/watchdog/designware_wdt.c | 122 ++++++++++++++---- include/configs/socfpga_stratix10_socdk.h | 1 + 7 files changed, 112 insertions(+), 24 deletions(-) diff --git a/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi b/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi index 44bedd8b67..2e4468e8d8 100644 --- a/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi +++ b/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi @@ -56,3 +56,7 @@ &portc { bank-name = "portc"; }; + +&watchdog0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi index e1cfb522bf..a41db08dd4 100755 --- a/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi +++ b/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi @@ -23,3 +23,7 @@ spi-rx-bus-width = <4>; u-boot,dm-pre-reloc; }; + +&watchdog0 { + u-boot,dm-pre-reloc; +}; diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig index 82ffedf41a..29466d0c09 100644 --- a/configs/socfpga_stratix10_defconfig +++ b/configs/socfpga_stratix10_defconfig @@ -60,3 +60,5 @@ CONFIG_USB_DWC2=y CONFIG_USB_STORAGE=y # CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_DESIGNWARE_WATCHDOG=y +CONFIG_WDT=y +# CONFIG_SPL_WDT is not set diff --git a/configs/socfpga_vining_fpga_defconfig b/configs/socfpga_vining_fpga_defconfig index 0e31e4f165..39be88b9b7 100644 --- a/configs/socfpga_vining_fpga_defconfig +++ b/configs/socfpga_vining_fpga_defconfig @@ -97,4 +97,5 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 CONFIG_USB_GADGET_DWC2_OTG=y CONFIG_USB_GADGET_DOWNLOAD=y # CONFIG_SPL_WDT is not set +CONFIG_WDT=y CONFIG_DESIGNWARE_WATCHDOG=y diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 5f8a070ef5..bf5612a811 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -47,7 +47,7 @@ config ULP_WATCHDOG config DESIGNWARE_WATCHDOG bool "Designware watchdog timer support" - select HW_WATCHDOG + select HW_WATCHDOG if !WDT help Enable this to support Designware Watchdog Timer IP, present e.g. on Altera SoCFPGA SoCs. diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c index c668567c66..a7b735979a 100644 --- a/drivers/watchdog/designware_wdt.c +++ b/drivers/watchdog/designware_wdt.c @@ -4,7 +4,8 @@ */ #include -#include +#include +#include #include #include @@ -17,46 +18,51 @@ #define DW_WDT_CR_RMOD_VAL 0x00 #define DW_WDT_CRR_RESTART_VAL 0x76 +struct designware_wdt_priv { + void __iomem *base; +}; + /* * Set the watchdog time interval. * Counter is 32 bit. */ -static int designware_wdt_settimeout(unsigned int timeout) +static int designware_wdt_settimeout(void __iomem *base, unsigned int clk_khz, + unsigned int timeout) { signed int i; /* calculate the timeout range value */ - i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ)) - 16; - if (i > 15) - i = 15; - if (i < 0) - i = 0; + i = log_2_n_round_up(timeout * clk_khz) - 16; + i = clamp(i, 0, 15); + + writel(i | (i << 4), base + DW_WDT_TORR); - writel((i | (i << 4)), (CONFIG_DW_WDT_BASE + DW_WDT_TORR)); return 0; } -static void designware_wdt_enable(void) +static void designware_wdt_enable(void __iomem *base) { - writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) | - (0x1 << DW_WDT_CR_EN_OFFSET)), - (CONFIG_DW_WDT_BASE + DW_WDT_CR)); + writel((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) | + BIT(DW_WDT_CR_EN_OFFSET), + base + DW_WDT_CR); } -static unsigned int designware_wdt_is_enabled(void) +static unsigned int designware_wdt_is_enabled(void __iomem *base) { - unsigned long val; - val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR)); - return val & 0x1; + return readl(base + DW_WDT_CR) & BIT(0); } -#if defined(CONFIG_HW_WATCHDOG) -void hw_watchdog_reset(void) +static void designware_wdt_reset_common(void __iomem *base) { - if (designware_wdt_is_enabled()) + if (designware_wdt_is_enabled(base)) /* restart the watchdog counter */ - writel(DW_WDT_CRR_RESTART_VAL, - (CONFIG_DW_WDT_BASE + DW_WDT_CRR)); + writel(DW_WDT_CRR_RESTART_VAL, base + DW_WDT_CRR); +} + +#if !CONFIG_IS_ENABLED(WDT) +void hw_watchdog_reset(void) +{ + designware_wdt_reset_common((void __iomem *)CONFIG_DW_WDT_BASE); } void hw_watchdog_init(void) @@ -64,10 +70,80 @@ void hw_watchdog_init(void) /* reset to disable the watchdog */ hw_watchdog_reset(); /* set timer in miliseconds */ - designware_wdt_settimeout(CONFIG_WATCHDOG_TIMEOUT_MSECS); + designware_wdt_settimeout((void __iomem *)CONFIG_DW_WDT_BASE, + CONFIG_DW_WDT_CLOCK_KHZ, + CONFIG_WATCHDOG_TIMEOUT_MSECS); /* enable the watchdog */ - designware_wdt_enable(); + designware_wdt_enable((void __iomem *)CONFIG_DW_WDT_BASE); /* reset the watchdog */ hw_watchdog_reset(); } +#else +static int designware_wdt_reset(struct udevice *dev) +{ + struct designware_wdt_priv *priv = dev_get_priv(dev); + + designware_wdt_reset_common(priv->base); + + return 0; +} + +static int designware_wdt_stop(struct udevice *dev) +{ + struct designware_wdt_priv *priv = dev_get_priv(dev); + + designware_wdt_reset(dev); + writel(DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET, + priv->base + DW_WDT_CR); + + return 0; +} + +static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct designware_wdt_priv *priv = dev_get_priv(dev); + + designware_wdt_stop(dev); + + /* set timer in miliseconds */ + designware_wdt_settimeout(priv->base, CONFIG_DW_WDT_CLOCK_KHZ, timeout); + + designware_wdt_enable(priv->base); + + /* reset the watchdog */ + return designware_wdt_reset(dev); +} + +static int designware_wdt_probe(struct udevice *dev) +{ + struct designware_wdt_priv *priv = dev_get_priv(dev); + + priv->base = dev_remap_addr(dev); + if (!priv->base) + return -EINVAL; + + /* reset to disable the watchdog */ + return designware_wdt_stop(dev); +} + +static const struct wdt_ops designware_wdt_ops = { + .start = designware_wdt_start, + .reset = designware_wdt_reset, + .stop = designware_wdt_stop, +}; + +static const struct udevice_id designware_wdt_ids[] = { + { .compatible = "snps,dw-wdt"}, + {} +}; + +U_BOOT_DRIVER(designware_wdt) = { + .name = "designware_wdt", + .id = UCLASS_WDT, + .of_match = designware_wdt_ids, + .priv_auto_alloc_size = sizeof(struct designware_wdt_priv), + .probe = designware_wdt_probe, + .ops = &designware_wdt_ops, + .flags = DM_FLAG_PRE_RELOC, +}; #endif diff --git a/include/configs/socfpga_stratix10_socdk.h b/include/configs/socfpga_stratix10_socdk.h index f7a4a30f3a..9e9209013a 100644 --- a/include/configs/socfpga_stratix10_socdk.h +++ b/include/configs/socfpga_stratix10_socdk.h @@ -151,6 +151,7 @@ unsigned int cm_get_qspi_controller_clk_hz(void); * L4 Watchdog */ #ifdef CONFIG_SPL_BUILD +#undef CONFIG_WATCHDOG #define CONFIG_HW_WATCHDOG #else #undef CONFIG_HW_WATCHDOG From patchwork Mon Jan 6 14:13:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 239164 List-Id: U-Boot discussion From: marex at denx.de (Marek Vasut) Date: Mon, 6 Jan 2020 15:13:46 +0100 Subject: [PATCH V3 3/3] watchdog: designware: Optionally fetch clock and reset from DT In-Reply-To: <20200106141346.47008-1-marex@denx.de> References: <20200106141346.47008-1-marex@denx.de> Message-ID: <20200106141346.47008-3-marex@denx.de> Add optional support for fetching watchdog clock rate from DT and ungating reset via reset framework. This is optional as not all platforms using DW WDT support the clock and reset frameworks yet. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dalon Westergreen Cc: Dinh Nguyen Cc: Jagan Teki Cc: Ley Foon Tan Cc: Philipp Tomisch Cc: Simon Goldschmidt Cc: Tien Fong Chee Reviewed-by: Jagan Teki Tested-by: Jagan Teki # roc-rk3399-pc --- V2: - New patch V3: - Add reset handling --- drivers/watchdog/designware_wdt.c | 40 +++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c index a7b735979a..1024a04596 100644 --- a/drivers/watchdog/designware_wdt.c +++ b/drivers/watchdog/designware_wdt.c @@ -3,8 +3,10 @@ * Copyright (C) 2013 Altera Corporation */ +#include #include #include +#include #include #include #include @@ -15,11 +17,11 @@ #define DW_WDT_CR_EN_OFFSET 0x00 #define DW_WDT_CR_RMOD_OFFSET 0x01 -#define DW_WDT_CR_RMOD_VAL 0x00 #define DW_WDT_CRR_RESTART_VAL 0x76 struct designware_wdt_priv { void __iomem *base; + unsigned int clk_khz; }; /* @@ -42,9 +44,7 @@ static int designware_wdt_settimeout(void __iomem *base, unsigned int clk_khz, static void designware_wdt_enable(void __iomem *base) { - writel((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) | - BIT(DW_WDT_CR_EN_OFFSET), - base + DW_WDT_CR); + writel(BIT(DW_WDT_CR_EN_OFFSET), base + DW_WDT_CR); } static unsigned int designware_wdt_is_enabled(void __iomem *base) @@ -93,8 +93,7 @@ static int designware_wdt_stop(struct udevice *dev) struct designware_wdt_priv *priv = dev_get_priv(dev); designware_wdt_reset(dev); - writel(DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET, - priv->base + DW_WDT_CR); + writel(0, priv->base + DW_WDT_CR); return 0; } @@ -106,7 +105,7 @@ static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags) designware_wdt_stop(dev); /* set timer in miliseconds */ - designware_wdt_settimeout(priv->base, CONFIG_DW_WDT_CLOCK_KHZ, timeout); + designware_wdt_settimeout(priv->base, priv->clk_khz, timeout); designware_wdt_enable(priv->base); @@ -117,11 +116,38 @@ static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags) static int designware_wdt_probe(struct udevice *dev) { struct designware_wdt_priv *priv = dev_get_priv(dev); + __maybe_unused int ret; priv->base = dev_remap_addr(dev); if (!priv->base) return -EINVAL; +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + + priv->clk_khz = clk_get_rate(&clk); + if (!priv->clk_khz) + return -EINVAL; +#else + priv->clk_khz = CONFIG_DW_WDT_CLOCK_KHZ; +#endif + +#if CONFIG_IS_ENABLED(DM_RESET) + struct reset_ctl_bulk resets; + + ret = reset_get_bulk(dev, &resets); + if (ret) + return ret; + + ret = reset_deassert_bulk(&resets); + if (ret) + return ret; +#endif + /* reset to disable the watchdog */ return designware_wdt_stop(dev); }