diff mbox series

[U-Boot,V2,2/3] watchdog: designware: Convert to DM and DT probing

Message ID 20191003125942.14826-2-marex@denx.de
State Superseded
Delegated to: Marek Vasut
Headers show
Series [U-Boot,V2,1/3] watchdog: designware: Migrate CONFIG_DESIGNWARE_WATCHDOG to Kconfig | expand

Commit Message

Marek Vasut Oct. 3, 2019, 12:59 p.m. UTC
Convert the designware watchdog timer driver to DM and add DT probing
support. Perform minor coding style clean up, like drop superfluous
braces. There ought to be no functional change.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chin Liang See <chin.liang.see@intel.com>
Cc: Dalon Westergreen <dwesterg@gmail.com>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Jagan Teki <jagan@amarulasolutions.com>
Cc: Ley Foon Tan <ley.foon.tan@intel.com>
Cc: Philipp Tomisch <philipp.tomisch@theobroma-systems.com>
Cc: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Cc: Tien Fong Chee <tien.fong.chee@intel.com>
---
V2: - Support both DM and non-DM probing
    - Fix watchdog stop handling by setting CR bit
---
 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 +
 5 files changed, 104 insertions(+), 24 deletions(-)

Comments

Ley Foon Tan Oct. 4, 2019, 9:26 a.m. UTC | #1
On Thu, Oct 3, 2019 at 9:00 PM Marek Vasut <marex@denx.de> wrote:
>
> Convert the designware watchdog timer driver to DM and add DT probing
> support. Perform minor coding style clean up, like drop superfluous
> braces. There ought to be no functional change.

All watchdog DT nodes with compatible "snps,dw-wdt" need to add
"u-boot,dm-pre-reloc;".

>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Chin Liang See <chin.liang.see@intel.com>
> Cc: Dalon Westergreen <dwesterg@gmail.com>
> Cc: Dinh Nguyen <dinguyen@kernel.org>
> Cc: Jagan Teki <jagan@amarulasolutions.com>
> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
> Cc: Philipp Tomisch <philipp.tomisch@theobroma-systems.com>
> Cc: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> Cc: Tien Fong Chee <tien.fong.chee@intel.com>
> ---
> V2: - Support both DM and non-DM probing
>     - Fix watchdog stop handling by setting CR bit
> ---
>  configs/socfpga_stratix10_defconfig       |   2 +
>  configs/socfpga_vining_fpga_defconfig     |   1 +

Same here. All socfpga defconfig files need to add CONFIG_WDT.

>  drivers/watchdog/Kconfig                  |   2 +-
>  drivers/watchdog/designware_wdt.c         | 122 ++++++++++++++++++----
>  include/configs/socfpga_stratix10_socdk.h |   1 +
>  5 files changed, 104 insertions(+), 24 deletions(-)
>
> diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig
> index 462082b67b..752fa545bd 100644
> --- a/configs/socfpga_stratix10_defconfig
> +++ b/configs/socfpga_stratix10_defconfig
> @@ -57,3 +57,5 @@ CONFIG_DM_USB=y
>  CONFIG_USB_DWC2=y
>  CONFIG_USB_STORAGE=y
>  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 03c43fa8b9..def7a3eca7 100644
> --- a/configs/socfpga_vining_fpga_defconfig
> +++ b/configs/socfpga_vining_fpga_defconfig
> @@ -91,4 +91,5 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0525
>  CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
>  CONFIG_USB_GADGET_DWC2_OTG=y
>  CONFIG_USB_GADGET_DOWNLOAD=y
> +CONFIG_WDT=y
>  CONFIG_DESIGNWARE_WATCHDOG=y
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 6fd9b0a177..bfb91af947 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -38,7 +38,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 <common.h>
> -#include <watchdog.h>
> +#include <dm.h>
> +#include <wdt.h>
>  #include <asm/io.h>
>  #include <asm/utils.h>
>
> @@ -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();

In my "arm: socfpga: Convert drivers from struct to defines" patch
series, I have moved spl_early_init() to the beginning of
spl_board_f().
So, DM framework is initialized in early stage, you should able to use
DM for watchdog in SPL too.
But, maybe need to add a wrapper function to probe watchdog device and
start watchdog. Something like this:

uclass_get_device(UCLASS_WDT, 0, &dev);
wdt_start(dev, CONFIG_WATCHDOG_TIMEOUT_MSECS, 0);

>  }
> +#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);

Still no fixing clear BIT(DW_WDT_CR_EN_OFFSET) in CR register to
disable watchdog.

> +
> +       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);
> +

Need de-assert watchdog reset using reset framework function, reset_get_bulk().



> +       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 353e08f982..0c0c27000a 100644
> --- a/include/configs/socfpga_stratix10_socdk.h
> +++ b/include/configs/socfpga_stratix10_socdk.h
> @@ -161,6 +161,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
> --
> 2.23.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> https://lists.denx.de/listinfo/u-boot
Marek Vasut Nov. 7, 2019, 5:45 p.m. UTC | #2
On 10/4/19 11:26 AM, Ley Foon Tan wrote:
> On Thu, Oct 3, 2019 at 9:00 PM Marek Vasut wrote:
>>
>> Convert the designware watchdog timer driver to DM and add DT probing
>> support. Perform minor coding style clean up, like drop superfluous
>> braces. There ought to be no functional change.
> 
> All watchdog DT nodes with compatible "snps,dw-wdt" need to add
> "u-boot,dm-pre-reloc;".

Only those boards which actually use the WDT, right ? That is, these two
boards below.

>> ---
>> V2: - Support both DM and non-DM probing
>>     - Fix watchdog stop handling by setting CR bit
>> ---
>>  configs/socfpga_stratix10_defconfig       |   2 +
>>  configs/socfpga_vining_fpga_defconfig     |   1 +
> 
> Same here. All socfpga defconfig files need to add CONFIG_WDT.

Only those two, since only those two boards enable the WDT, no ?

[...]

>>  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();
> 
> In my "arm: socfpga: Convert drivers from struct to defines" patch
> series, I have moved spl_early_init() to the beginning of
> spl_board_f().
> So, DM framework is initialized in early stage, you should able to use
> DM for watchdog in SPL too.
> But, maybe need to add a wrapper function to probe watchdog device and
> start watchdog. Something like this:
> 
> uclass_get_device(UCLASS_WDT, 0, &dev);
> wdt_start(dev, CONFIG_WATCHDOG_TIMEOUT_MSECS, 0);

Except this driver is not used only on SoCFPGA.
So the question is, with your conversion series, will there be boards
left which use non-DM version of this WDT driver ?

>>  }
>> +#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);
> 
> Still no fixing clear BIT(DW_WDT_CR_EN_OFFSET) in CR register to
> disable watchdog.

I guess we an just write 0 to the CR register and get rid of RMOD_VAL
altogether ?

>> +
>> +       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);
>> +
> 
> Need de-assert watchdog reset using reset framework function, reset_get_bulk().

Ah yes, and make it presumably optional.

[...]
Simon Goldschmidt Nov. 7, 2019, 7:30 p.m. UTC | #3
Am 03.10.2019 um 14:59 schrieb Marek Vasut:
> Convert the designware watchdog timer driver to DM and add DT probing
> support. Perform minor coding style clean up, like drop superfluous
> braces. There ought to be no functional change.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Chin Liang See <chin.liang.see@intel.com>
> Cc: Dalon Westergreen <dwesterg@gmail.com>
> Cc: Dinh Nguyen <dinguyen@kernel.org>
> Cc: Jagan Teki <jagan@amarulasolutions.com>
> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
> Cc: Philipp Tomisch <philipp.tomisch@theobroma-systems.com>
> Cc: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> Cc: Tien Fong Chee <tien.fong.chee@intel.com>
> ---
> V2: - Support both DM and non-DM probing
>      - Fix watchdog stop handling by setting CR bit
> ---
>   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 +
>   5 files changed, 104 insertions(+), 24 deletions(-)
> 
> diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig
> index 462082b67b..752fa545bd 100644
> --- a/configs/socfpga_stratix10_defconfig
> +++ b/configs/socfpga_stratix10_defconfig
> @@ -57,3 +57,5 @@ CONFIG_DM_USB=y
>   CONFIG_USB_DWC2=y
>   CONFIG_USB_STORAGE=y
>   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 03c43fa8b9..def7a3eca7 100644
> --- a/configs/socfpga_vining_fpga_defconfig
> +++ b/configs/socfpga_vining_fpga_defconfig
> @@ -91,4 +91,5 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0525
>   CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
>   CONFIG_USB_GADGET_DWC2_OTG=y
>   CONFIG_USB_GADGET_DOWNLOAD=y
> +CONFIG_WDT=y
>   CONFIG_DESIGNWARE_WATCHDOG=y
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 6fd9b0a177..bfb91af947 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -38,7 +38,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 <common.h>
> -#include <watchdog.h>
> +#include <dm.h>
> +#include <wdt.h>
>   #include <asm/io.h>
>   #include <asm/utils.h>
>   
> @@ -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 353e08f982..0c0c27000a 100644
> --- a/include/configs/socfpga_stratix10_socdk.h
> +++ b/include/configs/socfpga_stratix10_socdk.h
> @@ -161,6 +161,7 @@ unsigned int cm_get_qspi_controller_clk_hz(void);
>    * L4 Watchdog
>    */
>   #ifdef CONFIG_SPL_BUILD
> +#undef CONFIG_WATCHDOG

I somehow missed this series.
Why is this line here?

Other than that:
Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>

Regards,
Simon

>   #define CONFIG_HW_WATCHDOG
>   #else
>   #undef CONFIG_HW_WATCHDOG
>
Marek Vasut Nov. 7, 2019, 7:37 p.m. UTC | #4
On 11/7/19 8:30 PM, Simon Goldschmidt wrote:
[...]

>> diff --git a/include/configs/socfpga_stratix10_socdk.h
>> b/include/configs/socfpga_stratix10_socdk.h
>> index 353e08f982..0c0c27000a 100644
>> --- a/include/configs/socfpga_stratix10_socdk.h
>> +++ b/include/configs/socfpga_stratix10_socdk.h
>> @@ -161,6 +161,7 @@ unsigned int cm_get_qspi_controller_clk_hz(void);
>>    * L4 Watchdog
>>    */
>>   #ifdef CONFIG_SPL_BUILD
>> +#undef CONFIG_WATCHDOG
> 
> I somehow missed this series.
> Why is this line here?

To avoid using DM watchdog in SPL on S10.
Jagan Teki Dec. 27, 2019, 7:53 a.m. UTC | #5
Hi Marek,

On Thu, Oct 3, 2019 at 6:30 PM Marek Vasut <marex@denx.de> wrote:
>
> Convert the designware watchdog timer driver to DM and add DT probing
> support. Perform minor coding style clean up, like drop superfluous
> braces. There ought to be no functional change.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Chin Liang See <chin.liang.see@intel.com>
> Cc: Dalon Westergreen <dwesterg@gmail.com>
> Cc: Dinh Nguyen <dinguyen@kernel.org>
> Cc: Jagan Teki <jagan@amarulasolutions.com>
> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
> Cc: Philipp Tomisch <philipp.tomisch@theobroma-systems.com>
> Cc: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> Cc: Tien Fong Chee <tien.fong.chee@intel.com>
> ---
> V2: - Support both DM and non-DM probing
>     - Fix watchdog stop handling by setting CR bit
> ---

Please resend on top of master, would like to check it on rockchip.

Jagan.
Marek Vasut Jan. 6, 2020, 2:15 p.m. UTC | #6
On 12/27/19 8:53 AM, Jagan Teki wrote:
> Hi Marek,
> 
> On Thu, Oct 3, 2019 at 6:30 PM Marek Vasut <marex@denx.de> wrote:
>>
>> Convert the designware watchdog timer driver to DM and add DT probing
>> support. Perform minor coding style clean up, like drop superfluous
>> braces. There ought to be no functional change.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> Cc: Chin Liang See <chin.liang.see@intel.com>
>> Cc: Dalon Westergreen <dwesterg@gmail.com>
>> Cc: Dinh Nguyen <dinguyen@kernel.org>
>> Cc: Jagan Teki <jagan@amarulasolutions.com>
>> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
>> Cc: Philipp Tomisch <philipp.tomisch@theobroma-systems.com>
>> Cc: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
>> Cc: Tien Fong Chee <tien.fong.chee@intel.com>
>> ---
>> V2: - Support both DM and non-DM probing
>>     - Fix watchdog stop handling by setting CR bit
>> ---
> 
> Please resend on top of master, would like to check it on rockchip.

Done, please give it a try.
diff mbox series

Patch

diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig
index 462082b67b..752fa545bd 100644
--- a/configs/socfpga_stratix10_defconfig
+++ b/configs/socfpga_stratix10_defconfig
@@ -57,3 +57,5 @@  CONFIG_DM_USB=y
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 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 03c43fa8b9..def7a3eca7 100644
--- a/configs/socfpga_vining_fpga_defconfig
+++ b/configs/socfpga_vining_fpga_defconfig
@@ -91,4 +91,5 @@  CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_WDT=y
 CONFIG_DESIGNWARE_WATCHDOG=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 6fd9b0a177..bfb91af947 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -38,7 +38,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 <common.h>
-#include <watchdog.h>
+#include <dm.h>
+#include <wdt.h>
 #include <asm/io.h>
 #include <asm/utils.h>
 
@@ -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 353e08f982..0c0c27000a 100644
--- a/include/configs/socfpga_stratix10_socdk.h
+++ b/include/configs/socfpga_stratix10_socdk.h
@@ -161,6 +161,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