diff mbox series

[1/2] dt-bindings: watchdog: aspeed-wdt: Add aspeed,reset-mask property

Message ID 20230922104231.1434-5-zev@bewilderbeest.net
State New
Headers show
Series watchdog: aspeed: Add aspeed,reset-mask property | expand

Commit Message

Zev Weiss Sept. 22, 2023, 10:42 a.m. UTC
This property configures the Aspeed watchdog timer's reset mask, which
controls which peripherals are reset when the watchdog timer expires.
Some platforms require that certain devices be left untouched across a
reboot; aspeed,reset-mask can now be used to express such constraints.

Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
---
 .../bindings/watchdog/aspeed-wdt.txt          | 18 +++-
 include/dt-bindings/watchdog/aspeed-wdt.h     | 92 +++++++++++++++++++
 2 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h

Comments

Rob Herring (Arm) Sept. 22, 2023, 10:51 p.m. UTC | #1
On Fri, 22 Sep 2023 03:42:33 -0700, Zev Weiss wrote:
> This property configures the Aspeed watchdog timer's reset mask, which
> controls which peripherals are reset when the watchdog timer expires.
> Some platforms require that certain devices be left untouched across a
> reboot; aspeed,reset-mask can now be used to express such constraints.
> 
> Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
> ---
>  .../bindings/watchdog/aspeed-wdt.txt          | 18 +++-
>  include/dt-bindings/watchdog/aspeed-wdt.h     | 92 +++++++++++++++++++
>  2 files changed, 109 insertions(+), 1 deletion(-)
>  create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h
> 

Reviewed-by: Rob Herring <robh@kernel.org>
Andrew Jeffery Sept. 25, 2023, 2:42 a.m. UTC | #2
On Fri, 22 Sep 2023, at 20:12, Zev Weiss wrote:
> This property configures the Aspeed watchdog timer's reset mask, which
> controls which peripherals are reset when the watchdog timer expires.
> Some platforms require that certain devices be left untouched across a
> reboot; aspeed,reset-mask can now be used to express such constraints.
>
> Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
> ---
>  .../bindings/watchdog/aspeed-wdt.txt          | 18 +++-
>  include/dt-bindings/watchdog/aspeed-wdt.h     | 92 +++++++++++++++++++
>  2 files changed, 109 insertions(+), 1 deletion(-)
>  create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h
>
> diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt 
> b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> index a8197632d6d2..3208adb3e52e 100644
> --- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> @@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs:
>  			   is configured as push-pull, then set the pulse
>  			   polarity to active-high. The default is active-low.
> 
> -Example:
> +Optional properties for AST2500- and AST2600-compatible watchdogs:
> + - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
> +		      the watchdog timer expires.  On AST2500 this should be a
> +		      single word defined using the AST2500_WDT_RESET_* macros;
> +		      on AST2600 this should be a two-word array with the first
> +		      word defined using the AST2600_WDT_RESET1_* macros and the
> +		      second word defined using the AST2600_WDT_RESET2_* macros.
> +
> +Examples:
> 
>  	wdt1: watchdog@1e785000 {
>  		compatible = "aspeed,ast2400-wdt";
> @@ -55,3 +63,11 @@ Example:
>  		aspeed,reset-type = "system";
>  		aspeed,external-signal;
>  	};
> +
> +	#include <dt-bindings/watchdog/aspeed-wdt.h>
> +	wdt2: watchdog@1e785040 {
> +		compatible = "aspeed,ast2600-wdt";
> +		reg = <0x1e785040 0x40>;
> +		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
> +				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
> +	};

Rob has acked your current approach already, but I do wonder about an alternative that aligns more with the clock/reset/interrupt properties. Essentially, define a new generic watchdog property that is specified on the controllers to be reset by the watchdog (or even on just the watchdog node itself, emulating what you've proposed here):

watchdog-resets = <phandle index>;

The phandle links to the watchdog of interest, and the index specifies the controller associated with the configuration. It might even be useful to do:

watchdog-resets = <phandle index enable>;

"enable" could provide explicit control over whether somethings should be reset or not (as a way to prevent reset if the controller targeted by the provided index would otherwise be reset in accordance with the default reset value in the watchdog controller).

The macros from the dt-bindings header can then use macros to name the indexes rather than define a mask tied to the register layout. The index may still in some way represent the mask position. This has the benefit of hiding the issue of one vs two configuration registers between the AST2500 and AST2600 while also allowing other controllers to exploit the binding (Nuvoton BMCs? Though maybe it's generalising too early?).

It'd probably need a new function exported from the watchdog subsystem for the drivers to call through, though I don't think that's too much of a hurdle?

Andrew

> diff --git a/include/dt-bindings/watchdog/aspeed-wdt.h 
> b/include/dt-bindings/watchdog/aspeed-wdt.h
> new file mode 100644
> index 000000000000..7ae6d84b2bd9
> --- /dev/null
> +++ b/include/dt-bindings/watchdog/aspeed-wdt.h
> @@ -0,0 +1,92 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +
> +#ifndef DT_BINDINGS_ASPEED_WDT_H
> +#define DT_BINDINGS_ASPEED_WDT_H
> +
> +#define AST2500_WDT_RESET_CPU		(1 << 0)
> +#define AST2500_WDT_RESET_COPROC	(1 << 1)
> +#define AST2500_WDT_RESET_SDRAM		(1 << 2)
> +#define AST2500_WDT_RESET_AHB		(1 << 3)
> +#define AST2500_WDT_RESET_I2C		(1 << 4)
> +#define AST2500_WDT_RESET_MAC0		(1 << 5)
> +#define AST2500_WDT_RESET_MAC1		(1 << 6)
> +#define AST2500_WDT_RESET_GRAPHICS	(1 << 7)
> +#define AST2500_WDT_RESET_USB2_HOST_HUB	(1 << 8)
> +#define AST2500_WDT_RESET_USB_HOST	(1 << 9)
> +#define AST2500_WDT_RESET_HID_EHCI	(1 << 10)
> +#define AST2500_WDT_RESET_VIDEO		(1 << 11)
> +#define AST2500_WDT_RESET_HAC		(1 << 12)
> +#define AST2500_WDT_RESET_LPC		(1 << 13)
> +#define AST2500_WDT_RESET_SDIO		(1 << 14)
> +#define AST2500_WDT_RESET_MIC		(1 << 15)
> +#define AST2500_WDT_RESET_CRT		(1 << 16)
> +#define AST2500_WDT_RESET_PWM		(1 << 17)
> +#define AST2500_WDT_RESET_PECI		(1 << 18)
> +#define AST2500_WDT_RESET_JTAG		(1 << 19)
> +#define AST2500_WDT_RESET_ADC		(1 << 20)
> +#define AST2500_WDT_RESET_GPIO		(1 << 21)
> +#define AST2500_WDT_RESET_MCTP		(1 << 22)
> +#define AST2500_WDT_RESET_XDMA		(1 << 23)
> +#define AST2500_WDT_RESET_SPI		(1 << 24)
> +#define AST2500_WDT_RESET_SOC_MISC	(1 << 25)
> +
> +#define AST2500_WDT_RESET_DEFAULT 0x023ffff3
> +
> +#define AST2600_WDT_RESET1_CPU		(1 << 0)
> +#define AST2600_WDT_RESET1_SDRAM	(1 << 1)
> +#define AST2600_WDT_RESET1_AHB		(1 << 2)
> +#define AST2600_WDT_RESET1_SLI		(1 << 3)
> +#define AST2600_WDT_RESET1_SOC_MISC0	(1 << 4)
> +#define AST2600_WDT_RESET1_COPROC	(1 << 5)
> +#define AST2600_WDT_RESET1_USB_A	(1 << 6)
> +#define AST2600_WDT_RESET1_USB_B	(1 << 7)
> +#define AST2600_WDT_RESET1_UHCI		(1 << 8)
> +#define AST2600_WDT_RESET1_GRAPHICS	(1 << 9)
> +#define AST2600_WDT_RESET1_CRT		(1 << 10)
> +#define AST2600_WDT_RESET1_VIDEO	(1 << 11)
> +#define AST2600_WDT_RESET1_HAC		(1 << 12)
> +#define AST2600_WDT_RESET1_DP		(1 << 13)
> +#define AST2600_WDT_RESET1_DP_MCU	(1 << 14)
> +#define AST2600_WDT_RESET1_GP_MCU	(1 << 15)
> +#define AST2600_WDT_RESET1_MAC0		(1 << 16)
> +#define AST2600_WDT_RESET1_MAC1		(1 << 17)
> +#define AST2600_WDT_RESET1_SDIO0	(1 << 18)
> +#define AST2600_WDT_RESET1_JTAG0	(1 << 19)
> +#define AST2600_WDT_RESET1_MCTP0	(1 << 20)
> +#define AST2600_WDT_RESET1_MCTP1	(1 << 21)
> +#define AST2600_WDT_RESET1_XDMA0	(1 << 22)
> +#define AST2600_WDT_RESET1_XDMA1	(1 << 23)
> +#define AST2600_WDT_RESET1_GPIO0	(1 << 24)
> +#define AST2600_WDT_RESET1_RVAS		(1 << 25)
> +
> +#define AST2600_WDT_RESET1_DEFAULT 0x030f1ff1
> +
> +#define AST2600_WDT_RESET2_CPU		(1 << 0)
> +#define AST2600_WDT_RESET2_SPI		(1 << 1)
> +#define AST2600_WDT_RESET2_AHB2		(1 << 2)
> +#define AST2600_WDT_RESET2_SLI2		(1 << 3)
> +#define AST2600_WDT_RESET2_SOC_MISC1	(1 << 4)
> +#define AST2600_WDT_RESET2_MAC2		(1 << 5)
> +#define AST2600_WDT_RESET2_MAC3		(1 << 6)
> +#define AST2600_WDT_RESET2_SDIO1	(1 << 7)
> +#define AST2600_WDT_RESET2_JTAG1	(1 << 8)
> +#define AST2600_WDT_RESET2_GPIO1	(1 << 9)
> +#define AST2600_WDT_RESET2_MDIO		(1 << 10)
> +#define AST2600_WDT_RESET2_LPC		(1 << 11)
> +#define AST2600_WDT_RESET2_PECI		(1 << 12)
> +#define AST2600_WDT_RESET2_PWM		(1 << 13)
> +#define AST2600_WDT_RESET2_ADC		(1 << 14)
> +#define AST2600_WDT_RESET2_FSI		(1 << 15)
> +#define AST2600_WDT_RESET2_I2C		(1 << 16)
> +#define AST2600_WDT_RESET2_I3C_GLOBAL	(1 << 17)
> +#define AST2600_WDT_RESET2_I3C0		(1 << 18)
> +#define AST2600_WDT_RESET2_I3C1		(1 << 19)
> +#define AST2600_WDT_RESET2_I3C2		(1 << 20)
> +#define AST2600_WDT_RESET2_I3C3		(1 << 21)
> +#define AST2600_WDT_RESET2_I3C4		(1 << 22)
> +#define AST2600_WDT_RESET2_I3C5		(1 << 23)
> +#define AST2600_WDT_RESET2_ESPI		(1 << 26)
> +
> +#define AST2600_WDT_RESET2_DEFAULT 0x03fffff1
> +
> +#endif
> -- 
> 2.40.0.5.gf6e3b97ba6d2.dirty
Zev Weiss Sept. 26, 2023, 12:04 a.m. UTC | #3
On Sun, Sep 24, 2023 at 07:42:45PM PDT, Andrew Jeffery wrote:
>
>
>On Fri, 22 Sep 2023, at 20:12, Zev Weiss wrote:
>> This property configures the Aspeed watchdog timer's reset mask, which
>> controls which peripherals are reset when the watchdog timer expires.
>> Some platforms require that certain devices be left untouched across a
>> reboot; aspeed,reset-mask can now be used to express such constraints.
>>
>> Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
>> ---
>>  .../bindings/watchdog/aspeed-wdt.txt          | 18 +++-
>>  include/dt-bindings/watchdog/aspeed-wdt.h     | 92 +++++++++++++++++++
>>  2 files changed, 109 insertions(+), 1 deletion(-)
>>  create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h
>>
>> diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>> b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>> index a8197632d6d2..3208adb3e52e 100644
>> --- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>> +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>> @@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs:
>>  			   is configured as push-pull, then set the pulse
>>  			   polarity to active-high. The default is active-low.
>>
>> -Example:
>> +Optional properties for AST2500- and AST2600-compatible watchdogs:
>> + - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
>> +		      the watchdog timer expires.  On AST2500 this should be a
>> +		      single word defined using the AST2500_WDT_RESET_* macros;
>> +		      on AST2600 this should be a two-word array with the first
>> +		      word defined using the AST2600_WDT_RESET1_* macros and the
>> +		      second word defined using the AST2600_WDT_RESET2_* macros.
>> +
>> +Examples:
>>
>>  	wdt1: watchdog@1e785000 {
>>  		compatible = "aspeed,ast2400-wdt";
>> @@ -55,3 +63,11 @@ Example:
>>  		aspeed,reset-type = "system";
>>  		aspeed,external-signal;
>>  	};
>> +
>> +	#include <dt-bindings/watchdog/aspeed-wdt.h>
>> +	wdt2: watchdog@1e785040 {
>> +		compatible = "aspeed,ast2600-wdt";
>> +		reg = <0x1e785040 0x40>;
>> +		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
>> +				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
>> +	};
>
>Rob has acked your current approach already, but I do wonder about an 
>alternative that aligns more with the clock/reset/interrupt properties. 
>Essentially, define a new generic watchdog property that is specified 
>on the controllers to be reset by the watchdog (or even on just the 
>watchdog node itself, emulating what you've proposed here):
>
>watchdog-resets = <phandle index>;
>
>The phandle links to the watchdog of interest, and the index specifies 
>the controller associated with the configuration. It might even be 
>useful to do:
>
>watchdog-resets = <phandle index enable>;
>
>"enable" could provide explicit control over whether somethings should 
>be reset or not (as a way to prevent reset if the controller targeted 
>by the provided index would otherwise be reset in accordance with the 
>default reset value in the watchdog controller).
>
>The macros from the dt-bindings header can then use macros to name the 
>indexes rather than define a mask tied to the register layout. The 
>index may still in some way represent the mask position. This has the 
>benefit of hiding the issue of one vs two configuration registers 
>between the AST2500 and AST2600 while also allowing other controllers 
>to exploit the binding (Nuvoton BMCs? Though maybe it's generalising 
>too early?).
>

Sorry, I'm having a bit of a hard time picturing exactly what you're 
suggesting here...to start with:

>property that is specified on the controllers to be reset by the
>watchdog

and

>or even on just the watchdog node itself

seem on the face of it like two fairly different approaches to me.  The 
former sounds more like existing clock/reset/etc. stuff, where the 
peripheral has a property describing its relationship to the "central" 
subsystem, and various peripheral drivers are all individually 
responsible for observing that property and calling in to the central 
subsystem to configure things for that peripheral appropriately; if I'm 
understanding you correctly, it might look something like:

   &spi1 {
     watchdog-resets = <&wdt1 WDT_INDEX_SPI1 0>;
   };

Or maybe something more like how pinctrl works, via phandles to subnodes 
of the central device?

   &wdt1 {
     wdt1_spi1_reset: spi1_reset {
       reg = <0x1c>;
       bit = <24>;
     };
   };

   &spi1 {
     watchdog-resets = <&wdt1_spi1_reset 0>;
   };

Either way, it seems like it'd be complicated by any insufficient 
granularity in the watchdog w.r.t. having independent control over the 
individual devices represented by separate DT nodes (such as how the 
AST2500 watchdog has a single SPI controller reset bit instead of one 
per SPI interface, or its "misc SOC controller" bit governing all sorts 
of odds and ends).

In the latter case (property on the wdt node), would it essentially just 
be kind of an indirection layer mapping hardware-independent device 
indices to specific registers/bits?  It's not obvious to me what purpose 
a phandle to the peripheral device node would serve (would the wdt 
driver have a good way of identifying what specific peripheral it's 
pointing to to know what bit to twiddle?), but maybe I'm 
misunderstanding what you're suggesting...


I guess my other uncertainty is the balance between generalization and 
applicability -- how many other watchdog devices have sufficient 
comparable configurability to make use of it?  I haven't pored over all 
of them, but from a random sampling of 20 so of the other existing wdt 
drivers I don't see any obvious candidates -- the closest I saw were 
cpwd.c, which apparently can distinguish between a CPU reset and a 
CPU/backplane/board reset, and realtek_otto_wdt.c, which can do a CPU or 
a SOC reset (though I don't have any of the hardware docs to know what 
capabilities other devices might provide that the drivers don't use).  
Do the Nuvoton BMCs have watchdogs with peripheral-granularity reset 
configuration?


Thanks,
Zev
Guenter Roeck Sept. 26, 2023, 12:35 a.m. UTC | #4
On Mon, Sep 25, 2023 at 05:04:10PM -0700, Zev Weiss wrote:
> On Sun, Sep 24, 2023 at 07:42:45PM PDT, Andrew Jeffery wrote:
> > 
> > 
> > On Fri, 22 Sep 2023, at 20:12, Zev Weiss wrote:
> > > This property configures the Aspeed watchdog timer's reset mask, which
> > > controls which peripherals are reset when the watchdog timer expires.
> > > Some platforms require that certain devices be left untouched across a
> > > reboot; aspeed,reset-mask can now be used to express such constraints.
> > > 
> > > Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
> > > ---
> > >  .../bindings/watchdog/aspeed-wdt.txt          | 18 +++-
> > >  include/dt-bindings/watchdog/aspeed-wdt.h     | 92 +++++++++++++++++++
> > >  2 files changed, 109 insertions(+), 1 deletion(-)
> > >  create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h
> > > 
> > > diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > index a8197632d6d2..3208adb3e52e 100644
> > > --- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > @@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs:
> > >  			   is configured as push-pull, then set the pulse
> > >  			   polarity to active-high. The default is active-low.
> > > 
> > > -Example:
> > > +Optional properties for AST2500- and AST2600-compatible watchdogs:
> > > + - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
> > > +		      the watchdog timer expires.  On AST2500 this should be a
> > > +		      single word defined using the AST2500_WDT_RESET_* macros;
> > > +		      on AST2600 this should be a two-word array with the first
> > > +		      word defined using the AST2600_WDT_RESET1_* macros and the
> > > +		      second word defined using the AST2600_WDT_RESET2_* macros.
> > > +
> > > +Examples:
> > > 
> > >  	wdt1: watchdog@1e785000 {
> > >  		compatible = "aspeed,ast2400-wdt";
> > > @@ -55,3 +63,11 @@ Example:
> > >  		aspeed,reset-type = "system";
> > >  		aspeed,external-signal;
> > >  	};
> > > +
> > > +	#include <dt-bindings/watchdog/aspeed-wdt.h>
> > > +	wdt2: watchdog@1e785040 {
> > > +		compatible = "aspeed,ast2600-wdt";
> > > +		reg = <0x1e785040 0x40>;
> > > +		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
> > > +				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
> > > +	};
> > 
> > Rob has acked your current approach already, but I do wonder about an
> > alternative that aligns more with the clock/reset/interrupt properties.
> > Essentially, define a new generic watchdog property that is specified on
> > the controllers to be reset by the watchdog (or even on just the
> > watchdog node itself, emulating what you've proposed here):
> > 
> > watchdog-resets = <phandle index>;
> > 
> > The phandle links to the watchdog of interest, and the index specifies
> > the controller associated with the configuration. It might even be
> > useful to do:
> > 
> > watchdog-resets = <phandle index enable>;
> > 
> > "enable" could provide explicit control over whether somethings should
> > be reset or not (as a way to prevent reset if the controller targeted by
> > the provided index would otherwise be reset in accordance with the
> > default reset value in the watchdog controller).
> > 
> > The macros from the dt-bindings header can then use macros to name the
> > indexes rather than define a mask tied to the register layout. The index
> > may still in some way represent the mask position. This has the benefit
> > of hiding the issue of one vs two configuration registers between the
> > AST2500 and AST2600 while also allowing other controllers to exploit the
> > binding (Nuvoton BMCs? Though maybe it's generalising too early?).
> > 
> 
> Sorry, I'm having a bit of a hard time picturing exactly what you're
> suggesting here...to start with:
> 
> > property that is specified on the controllers to be reset by the
> > watchdog
> 
> and
> 
> > or even on just the watchdog node itself
> 
> seem on the face of it like two fairly different approaches to me.  The
> former sounds more like existing clock/reset/etc. stuff, where the
> peripheral has a property describing its relationship to the "central"
> subsystem, and various peripheral drivers are all individually responsible
> for observing that property and calling in to the central subsystem to
> configure things for that peripheral appropriately; if I'm understanding you
> correctly, it might look something like:
> 
>   &spi1 {
>     watchdog-resets = <&wdt1 WDT_INDEX_SPI1 0>;
>   };
> 
> Or maybe something more like how pinctrl works, via phandles to subnodes of
> the central device?
> 
>   &wdt1 {
>     wdt1_spi1_reset: spi1_reset {
>       reg = <0x1c>;
>       bit = <24>;
>     };
>   };
> 
>   &spi1 {
>     watchdog-resets = <&wdt1_spi1_reset 0>;
>   };
> 
> Either way, it seems like it'd be complicated by any insufficient
> granularity in the watchdog w.r.t. having independent control over the
> individual devices represented by separate DT nodes (such as how the AST2500
> watchdog has a single SPI controller reset bit instead of one per SPI
> interface, or its "misc SOC controller" bit governing all sorts of odds and
> ends).
> 
> In the latter case (property on the wdt node), would it essentially just be
> kind of an indirection layer mapping hardware-independent device indices to
> specific registers/bits?  It's not obvious to me what purpose a phandle to
> the peripheral device node would serve (would the wdt driver have a good way
> of identifying what specific peripheral it's pointing to to know what bit to
> twiddle?), but maybe I'm misunderstanding what you're suggesting...
> 
> 
> I guess my other uncertainty is the balance between generalization and
> applicability -- how many other watchdog devices have sufficient comparable
> configurability to make use of it?  I haven't pored over all of them, but
> from a random sampling of 20 so of the other existing wdt drivers I don't
> see any obvious candidates -- the closest I saw were cpwd.c, which
> apparently can distinguish between a CPU reset and a CPU/backplane/board
> reset, and realtek_otto_wdt.c, which can do a CPU or a SOC reset (though I
> don't have any of the hardware docs to know what capabilities other devices
> might provide that the drivers don't use).  Do the Nuvoton BMCs have
> watchdogs with peripheral-granularity reset configuration?
> 

Quite frankly, I don't like where this is going. It is getting way
too complicated. And when something is becoming way too complicated,
I tend to put it on my backburner list. The length of that list quickly
approaches maxint.

Guenter
Andrew Jeffery Sept. 26, 2023, 12:57 a.m. UTC | #5
On Mon, 2023-09-25 at 17:35 -0700, Guenter Roeck wrote:
> On Mon, Sep 25, 2023 at 05:04:10PM -0700, Zev Weiss wrote:
> > On Sun, Sep 24, 2023 at 07:42:45PM PDT, Andrew Jeffery wrote:
> > > 
> > > 
> > > On Fri, 22 Sep 2023, at 20:12, Zev Weiss wrote:
> > > > This property configures the Aspeed watchdog timer's reset mask, which
> > > > controls which peripherals are reset when the watchdog timer expires.
> > > > Some platforms require that certain devices be left untouched across a
> > > > reboot; aspeed,reset-mask can now be used to express such constraints.
> > > > 
> > > > Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
> > > > ---
> > > >  .../bindings/watchdog/aspeed-wdt.txt          | 18 +++-
> > > >  include/dt-bindings/watchdog/aspeed-wdt.h     | 92 +++++++++++++++++++
> > > >  2 files changed, 109 insertions(+), 1 deletion(-)
> > > >  create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > > b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > > index a8197632d6d2..3208adb3e52e 100644
> > > > --- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > > +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > > > @@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs:
> > > >  			   is configured as push-pull, then set the pulse
> > > >  			   polarity to active-high. The default is active-low.
> > > > 
> > > > -Example:
> > > > +Optional properties for AST2500- and AST2600-compatible watchdogs:
> > > > + - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
> > > > +		      the watchdog timer expires.  On AST2500 this should be a
> > > > +		      single word defined using the AST2500_WDT_RESET_* macros;
> > > > +		      on AST2600 this should be a two-word array with the first
> > > > +		      word defined using the AST2600_WDT_RESET1_* macros and the
> > > > +		      second word defined using the AST2600_WDT_RESET2_* macros.
> > > > +
> > > > +Examples:
> > > > 
> > > >  	wdt1: watchdog@1e785000 {
> > > >  		compatible = "aspeed,ast2400-wdt";
> > > > @@ -55,3 +63,11 @@ Example:
> > > >  		aspeed,reset-type = "system";
> > > >  		aspeed,external-signal;
> > > >  	};
> > > > +
> > > > +	#include <dt-bindings/watchdog/aspeed-wdt.h>
> > > > +	wdt2: watchdog@1e785040 {
> > > > +		compatible = "aspeed,ast2600-wdt";
> > > > +		reg = <0x1e785040 0x40>;
> > > > +		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
> > > > +				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
> > > > +	};
> > > 
> > > Rob has acked your current approach already, but I do wonder about an
> > > alternative that aligns more with the clock/reset/interrupt properties.
> > > Essentially, define a new generic watchdog property that is specified on
> > > the controllers to be reset by the watchdog (or even on just the
> > > watchdog node itself, emulating what you've proposed here):
> > > 
> > > watchdog-resets = <phandle index>;
> > > 
> > > The phandle links to the watchdog of interest, and the index specifies
> > > the controller associated with the configuration. It might even be
> > > useful to do:
> > > 
> > > watchdog-resets = <phandle index enable>;
> > > 
> > > "enable" could provide explicit control over whether somethings should
> > > be reset or not (as a way to prevent reset if the controller targeted by
> > > the provided index would otherwise be reset in accordance with the
> > > default reset value in the watchdog controller).
> > > 
> > > The macros from the dt-bindings header can then use macros to name the
> > > indexes rather than define a mask tied to the register layout. The index
> > > may still in some way represent the mask position. This has the benefit
> > > of hiding the issue of one vs two configuration registers between the
> > > AST2500 and AST2600 while also allowing other controllers to exploit the
> > > binding (Nuvoton BMCs? Though maybe it's generalising too early?).
> > > 
> > 
> > Sorry, I'm having a bit of a hard time picturing exactly what you're
> > suggesting here...to start with:
> > 
> > > property that is specified on the controllers to be reset by the
> > > watchdog
> > 
> > and
> > 
> > > or even on just the watchdog node itself
> > 
> > seem on the face of it like two fairly different approaches to me.  The
> > former sounds more like existing clock/reset/etc. stuff, where the
> > peripheral has a property describing its relationship to the "central"
> > subsystem, and various peripheral drivers are all individually responsible
> > for observing that property and calling in to the central subsystem to
> > configure things for that peripheral appropriately; if I'm understanding you
> > correctly, it might look something like:
> > 
> >   &spi1 {
> >     watchdog-resets = <&wdt1 WDT_INDEX_SPI1 0>;
> >   };
> > 
> > Or maybe something more like how pinctrl works, via phandles to subnodes of
> > the central device?
> > 
> >   &wdt1 {
> >     wdt1_spi1_reset: spi1_reset {
> >       reg = <0x1c>;
> >       bit = <24>;
> >     };
> >   };
> > 
> >   &spi1 {
> >     watchdog-resets = <&wdt1_spi1_reset 0>;
> >   };
> > 
> > Either way, it seems like it'd be complicated by any insufficient
> > granularity in the watchdog w.r.t. having independent control over the
> > individual devices represented by separate DT nodes (such as how the AST2500
> > watchdog has a single SPI controller reset bit instead of one per SPI
> > interface, or its "misc SOC controller" bit governing all sorts of odds and
> > ends).
> > 
> > In the latter case (property on the wdt node), would it essentially just be
> > kind of an indirection layer mapping hardware-independent device indices to
> > specific registers/bits?  It's not obvious to me what purpose a phandle to
> > the peripheral device node would serve (would the wdt driver have a good way
> > of identifying what specific peripheral it's pointing to to know what bit to
> > twiddle?), but maybe I'm misunderstanding what you're suggesting...
> > 
> > 
> > I guess my other uncertainty is the balance between generalization and
> > applicability -- how many other watchdog devices have sufficient comparable
> > configurability to make use of it?  I haven't pored over all of them, but
> > from a random sampling of 20 so of the other existing wdt drivers I don't
> > see any obvious candidates -- the closest I saw were cpwd.c, which
> > apparently can distinguish between a CPU reset and a CPU/backplane/board
> > reset, and realtek_otto_wdt.c, which can do a CPU or a SOC reset (though I
> > don't have any of the hardware docs to know what capabilities other devices
> > might provide that the drivers don't use).  Do the Nuvoton BMCs have
> > watchdogs with peripheral-granularity reset configuration?
> > 
> 
> Quite frankly, I don't like where this is going. It is getting way
> too complicated. And when something is becoming way too complicated,
> I tend to put it on my backburner list. The length of that list quickly
> approaches maxint.
> 

No worries. I figured I should at least give the idea some air-time,
even if we did end up discounting it. I feel my description and Zev's
queries make it sound more complex than it might be in practice but I
also haven't written the patch, so never mind!

Andrew
diff mbox series

Patch

diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
index a8197632d6d2..3208adb3e52e 100644
--- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
@@ -47,7 +47,15 @@  Optional properties for AST2500-compatible watchdogs:
 			   is configured as push-pull, then set the pulse
 			   polarity to active-high. The default is active-low.
 
-Example:
+Optional properties for AST2500- and AST2600-compatible watchdogs:
+ - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
+		      the watchdog timer expires.  On AST2500 this should be a
+		      single word defined using the AST2500_WDT_RESET_* macros;
+		      on AST2600 this should be a two-word array with the first
+		      word defined using the AST2600_WDT_RESET1_* macros and the
+		      second word defined using the AST2600_WDT_RESET2_* macros.
+
+Examples:
 
 	wdt1: watchdog@1e785000 {
 		compatible = "aspeed,ast2400-wdt";
@@ -55,3 +63,11 @@  Example:
 		aspeed,reset-type = "system";
 		aspeed,external-signal;
 	};
+
+	#include <dt-bindings/watchdog/aspeed-wdt.h>
+	wdt2: watchdog@1e785040 {
+		compatible = "aspeed,ast2600-wdt";
+		reg = <0x1e785040 0x40>;
+		aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
+				     (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
+	};
diff --git a/include/dt-bindings/watchdog/aspeed-wdt.h b/include/dt-bindings/watchdog/aspeed-wdt.h
new file mode 100644
index 000000000000..7ae6d84b2bd9
--- /dev/null
+++ b/include/dt-bindings/watchdog/aspeed-wdt.h
@@ -0,0 +1,92 @@ 
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef DT_BINDINGS_ASPEED_WDT_H
+#define DT_BINDINGS_ASPEED_WDT_H
+
+#define AST2500_WDT_RESET_CPU		(1 << 0)
+#define AST2500_WDT_RESET_COPROC	(1 << 1)
+#define AST2500_WDT_RESET_SDRAM		(1 << 2)
+#define AST2500_WDT_RESET_AHB		(1 << 3)
+#define AST2500_WDT_RESET_I2C		(1 << 4)
+#define AST2500_WDT_RESET_MAC0		(1 << 5)
+#define AST2500_WDT_RESET_MAC1		(1 << 6)
+#define AST2500_WDT_RESET_GRAPHICS	(1 << 7)
+#define AST2500_WDT_RESET_USB2_HOST_HUB	(1 << 8)
+#define AST2500_WDT_RESET_USB_HOST	(1 << 9)
+#define AST2500_WDT_RESET_HID_EHCI	(1 << 10)
+#define AST2500_WDT_RESET_VIDEO		(1 << 11)
+#define AST2500_WDT_RESET_HAC		(1 << 12)
+#define AST2500_WDT_RESET_LPC		(1 << 13)
+#define AST2500_WDT_RESET_SDIO		(1 << 14)
+#define AST2500_WDT_RESET_MIC		(1 << 15)
+#define AST2500_WDT_RESET_CRT		(1 << 16)
+#define AST2500_WDT_RESET_PWM		(1 << 17)
+#define AST2500_WDT_RESET_PECI		(1 << 18)
+#define AST2500_WDT_RESET_JTAG		(1 << 19)
+#define AST2500_WDT_RESET_ADC		(1 << 20)
+#define AST2500_WDT_RESET_GPIO		(1 << 21)
+#define AST2500_WDT_RESET_MCTP		(1 << 22)
+#define AST2500_WDT_RESET_XDMA		(1 << 23)
+#define AST2500_WDT_RESET_SPI		(1 << 24)
+#define AST2500_WDT_RESET_SOC_MISC	(1 << 25)
+
+#define AST2500_WDT_RESET_DEFAULT 0x023ffff3
+
+#define AST2600_WDT_RESET1_CPU		(1 << 0)
+#define AST2600_WDT_RESET1_SDRAM	(1 << 1)
+#define AST2600_WDT_RESET1_AHB		(1 << 2)
+#define AST2600_WDT_RESET1_SLI		(1 << 3)
+#define AST2600_WDT_RESET1_SOC_MISC0	(1 << 4)
+#define AST2600_WDT_RESET1_COPROC	(1 << 5)
+#define AST2600_WDT_RESET1_USB_A	(1 << 6)
+#define AST2600_WDT_RESET1_USB_B	(1 << 7)
+#define AST2600_WDT_RESET1_UHCI		(1 << 8)
+#define AST2600_WDT_RESET1_GRAPHICS	(1 << 9)
+#define AST2600_WDT_RESET1_CRT		(1 << 10)
+#define AST2600_WDT_RESET1_VIDEO	(1 << 11)
+#define AST2600_WDT_RESET1_HAC		(1 << 12)
+#define AST2600_WDT_RESET1_DP		(1 << 13)
+#define AST2600_WDT_RESET1_DP_MCU	(1 << 14)
+#define AST2600_WDT_RESET1_GP_MCU	(1 << 15)
+#define AST2600_WDT_RESET1_MAC0		(1 << 16)
+#define AST2600_WDT_RESET1_MAC1		(1 << 17)
+#define AST2600_WDT_RESET1_SDIO0	(1 << 18)
+#define AST2600_WDT_RESET1_JTAG0	(1 << 19)
+#define AST2600_WDT_RESET1_MCTP0	(1 << 20)
+#define AST2600_WDT_RESET1_MCTP1	(1 << 21)
+#define AST2600_WDT_RESET1_XDMA0	(1 << 22)
+#define AST2600_WDT_RESET1_XDMA1	(1 << 23)
+#define AST2600_WDT_RESET1_GPIO0	(1 << 24)
+#define AST2600_WDT_RESET1_RVAS		(1 << 25)
+
+#define AST2600_WDT_RESET1_DEFAULT 0x030f1ff1
+
+#define AST2600_WDT_RESET2_CPU		(1 << 0)
+#define AST2600_WDT_RESET2_SPI		(1 << 1)
+#define AST2600_WDT_RESET2_AHB2		(1 << 2)
+#define AST2600_WDT_RESET2_SLI2		(1 << 3)
+#define AST2600_WDT_RESET2_SOC_MISC1	(1 << 4)
+#define AST2600_WDT_RESET2_MAC2		(1 << 5)
+#define AST2600_WDT_RESET2_MAC3		(1 << 6)
+#define AST2600_WDT_RESET2_SDIO1	(1 << 7)
+#define AST2600_WDT_RESET2_JTAG1	(1 << 8)
+#define AST2600_WDT_RESET2_GPIO1	(1 << 9)
+#define AST2600_WDT_RESET2_MDIO		(1 << 10)
+#define AST2600_WDT_RESET2_LPC		(1 << 11)
+#define AST2600_WDT_RESET2_PECI		(1 << 12)
+#define AST2600_WDT_RESET2_PWM		(1 << 13)
+#define AST2600_WDT_RESET2_ADC		(1 << 14)
+#define AST2600_WDT_RESET2_FSI		(1 << 15)
+#define AST2600_WDT_RESET2_I2C		(1 << 16)
+#define AST2600_WDT_RESET2_I3C_GLOBAL	(1 << 17)
+#define AST2600_WDT_RESET2_I3C0		(1 << 18)
+#define AST2600_WDT_RESET2_I3C1		(1 << 19)
+#define AST2600_WDT_RESET2_I3C2		(1 << 20)
+#define AST2600_WDT_RESET2_I3C3		(1 << 21)
+#define AST2600_WDT_RESET2_I3C4		(1 << 22)
+#define AST2600_WDT_RESET2_I3C5		(1 << 23)
+#define AST2600_WDT_RESET2_ESPI		(1 << 26)
+
+#define AST2600_WDT_RESET2_DEFAULT 0x03fffff1
+
+#endif