1 /*******************************************************************************
2  * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  *
25  * PolarFire SoC (MPFS) Microprocessor Subsystem Watchdog bare metal software
26  * driver public API.
27  *
28  *
29  */
30 /*=========================================================================*//**
31   @mainpage PolarFire SoC MSS Watchdog Bare Metal Driver
32 
33   ==============================================================================
34   Introduction
35   ==============================================================================
36   The PolarFire SoC Microprocessor SubSystem (MSS) includes five instances of
37   watchdog timer hardware blocks used to detect system lockups. This software
38   driver provides a set of functions for controlling the MSS watchdog as part of
39   a bare metal system where no operating system is available. The driver can be
40   adapted for use as part of an operating system, but the implementation of the
41   adaptation layer between the driver and the operating system's driver model is
42   outside the scope of the driver.
43 
44   The MSS watchdog driver provides support for the following features:
45     - Initialization of the MSS watchdog
46     - Reading the current value and status of the watchdog timer
47     - Refreshing the watchdog timer value
48     - Enabling, disabling and clearing timeout and MVRP interrupts.
49 
50   ==============================================================================
51   Hardware Flow Dependencies
52   ==============================================================================
53   The configuration of all the features of the PolarFire SoC MSS watchdog is
54   covered by this driver. Besides, this driver does not require any other
55   configuration.
56 
57   On PolarFire SoC an AXI switch forms a bus matrix interconnect among multiple
58   masters and multiple slaves. Five RISC-V CPUs connect to the Master ports
59   M10 to M14 of the AXI switch. By default, all the APB peripherals are
60   accessible on AXI-Slave 5 of the AXI switch via the AXI to AHB and AHB to APB
61   bridges (referred as main APB bus). However, to support logical separation in
62   the Asymmetric Multi-Processing (AMP) mode of operation, the APB peripherals
63   can alternatively be accessed on the AXI-Slave 6 via the AXI to AHB and AHB to
64   APB bridges (referred as the AMP APB bus).
65 
66   Application must make sure that the desired MSS Watchdog instance is
67   appropriately configured on one of the APB slaves described above by
68   configuring the PolarFire SoC system registers (SYSREG) as per the application
69   need and that the appropriate data structures are provided to this driver as
70   parameter to the functions provided by this driver.
71 
72   The base address and register addresses are defined in this driver as
73   constants. The interrupt number assignment for the MSS Watchdog peripherals
74   are defined as constants in the MPFS HAL. You must ensure that the latest MPFS
75   HAL is included in the project settings of the SoftConsole tool chain and that
76   it is generated into your project.
77 
78   ==============================================================================
79   Theory of Operation
80   ==============================================================================
81   The MSS watchdog driver functions are grouped into the following categories:
82     - Initialization and configuration
83     - Reading the current value and status of the watchdog timer
84     - Refreshing the watchdog timer value
85     - Support for enabling, disabling and clearing time-out and MVRP interrupts.
86 
87   --------------------------------
88   Initialization and Configuration
89   --------------------------------
90   The MSS Watchdog driver provides the MSS_WD_configure() function to configure
91   the MSS Watchdog with desired configuration values. It also provides the
92   MSS_WD_get_config() function to read back the current configurations of the
93   MSS Watchdog. You can use this function to retrieve the current configurations
94   and then overwrite them with the application specific values, such as initial
95   watchdog timer value, Maximum Value (up to which) Refresh (is) Permitted,
96   watchdog time-out value, enable/disable forbidden region, enable/disable
97   MVRP interrupt and interrupt type.
98 
99   The occurrence of a time out event before the system reset can be detected
100   using the MSS_WD_timeout_occured() function. This function would typically be
101   used at the start of the application to detect whether the application is
102   starting as a result of a power-on reset or a watchdog reset. The time out
103   event must be cleared through a call to function MSS_WD_clear_timeout_event()
104   in order to allow the detection of subsequent time out events or
105   differentiating between a RISC-V initiated system reset and watchdog reset.
106 
107   --------------------------------------------
108   Reading the Watchdog Timer Value and Status
109   --------------------------------------------
110   MSS Watchdog is a down counter. A refresh forbidden window can be created by
111   configuring the watchdog Maximum Value up to which Refresh is Permitted (MVRP).
112   When the current value of the watchdog timer is greater than the MVRP value,
113   refreshing the watchdog is forbidden. Attempting to refresh the watchdog timer
114   in the forbidden window will assert a timeout interrupt. The
115   MSS_WD_forbidden_status() function can be used to know whether the watchdog
116   timer is in forbidden window or has crossed it. By default, the forbidden
117   window is disabled. It can be enabled by providing an appropriate value as
118   parameter to the MSS_WD_configure() function. When the forbidden window is
119   disabled, any attempt to refresh the watchdog timer is ignored and the counter
120   keeps on down counting.
121 
122   The current value of the watchdog timer can be read using the
123   MSS_WD_current_value() function. This function can be called at any time.
124 
125   --------------------------------------------
126   Refreshing the Watchdog Timer Value
127   --------------------------------------------
128   The watchdog timer value is refreshed using the MSS_WD_reload() function. The
129   value reloaded into the watchdog timer down-counter is specified at the
130   configuration time with an appropriate value as parameter to the
131   MSS_WD_get_config() function.
132 
133   --------------------------------------------
134   Interrupt Control
135   --------------------------------------------
136   The PolarFire SoC MSS Watchdog generates two interrupts, The MVRP interrupt and
137   the timeout interrupt.
138   The MVRP interrupt is generated when the watchdog down-counter crosses the
139   Maximum Value up to which Refresh is Permitted (MVRP). Following functions to
140   control MVRP interrupt:
141     - MSS_WD_enable_mvrp_irq
142     - MSS_WD_disable_mvrp_irq
143     - MSS_WD_clear_mvrp_irq
144 
145   The timeout interrupt is generated when the watchdog down-counter crosses the
146   watchdog timeout value. The timeout value is a non-zero value and it can be
147   set to a maximum of MSS_WDOG_TRIGGER_MAX. The non-maskable interrupt is
148   generated when the watchdog crosses this timeout value, the down counter
149   keeps on down counting and a reset signal is generated when reaches zero.
150   Following functions to control timeout interrupt:
151     - MSS_WD_enable_timeout_irq
152     - MSS_WD_disable_timeout_irq
153     - MSS_WD_clear_timeout_irq
154 
155  *//*=========================================================================*/
156 
157 #ifndef MSS_WATCHDOG_H_
158 #define MSS_WATCHDOG_H_
159 
160 #ifdef __cplusplus
161 extern "C" {
162 #endif
163 
164 #include <stdint.h>
165 
166 /*
167   The following constants can be used to configure the MSS Watchdog where a
168   zero or non-zero value such as enable or disable is to be provided as input
169   parameter as shown below:
170       wd0lo_config.forbidden_en = MSS_WDOG_DISABLE;
171       MSS_WD_configure(MSS_WDOG0_LO, &wd0lo_config);
172 */
173 #define MSS_WDOG_ENABLE                     1u
174 #define MSS_WDOG_DISABLE                    0u
175 
176 
177 /***************************************************************************//**
178  The mss_watchdog_num_t is the Watchdog module number enumeration.
179  The MSS_WDOG0_LO to MSS_WDOG4_LO Correspond to the Watchdog module number
180  0 to 4 when the appear on the AXI switch Slave 5.
181  The MSS_WDOG0_HI to MSS_WDOG4_HI Correspond to the Watchdog module number
182  0 to 4 when the appear on the AXI switch Slave 6.
183 */
184 typedef enum mss_watchdog_num{
185     MSS_WDOG0_LO    = 0,
186     MSS_WDOG1_LO    = 1,
187     MSS_WDOG2_LO    = 2,
188     MSS_WDOG3_LO    = 3,
189     MSS_WDOG4_LO    = 4,
190     MSS_WDOG0_HI    = 5,
191     MSS_WDOG1_HI    = 6,
192     MSS_WDOG2_HI    = 7,
193     MSS_WDOG3_HI    = 8,
194     MSS_WDOG4_HI    = 9,
195 
196 } mss_watchdog_num_t;
197 
198 
199 /***************************************************************************//**
200   The mss_watchdog_config_t type for the watchdog Configuration structure. This
201   type is used as a parameter for the MSS_WD_configure() and the
202   MSS_WD_get_config() functions.
203 
204   Following are the values as part of this structure
205 |  Parameter       |                         Description                       |
206 |------------------|-----------------------------------------------------------|
207 |   time_val       | The value from which the watchdog timer counts down       |
208 |   mvrp_val       | The Watchdog MVRP value                                   |
209 |   timeout_val    | The watchdog timeout value                                |
210 |   forbidden_en   | Enable/disable the forbidden window                       |
211 |                  | When set, if a refresh occurs in the forbidden window,    |
212 |                  | the watchdog timeout interrupt will be generated.         |
213 
214 
215 Time calculation example:
216 
217    time_val = 0xFFFFF0u
218    mvrp_val = 0x989680u
219    timeout_val = 0x3e8u
220 
221    A presaclar = 256 is used on the MSS AXI clock.
222    Considering AXI clock = 25Mhz
223 
224    The MVRP interrupt will happen after
225    (0xFFFFF0 - 0x989680) * ( 1/25MHz/256)
226    mvrp interrupt will happen after 69 sec. after system reset
227 
228    (0xFFFFF0 - 0x3e8) * ( 1/25MHz/256)
229    timeout interrupt will happen after 171 sec. after system reset
230 
231  */
232 
233 typedef struct mss_watchdog_config{
234     uint32_t                time_val;
235     uint32_t                mvrp_val;
236     uint32_t                timeout_val;
237     uint8_t                 forbidden_en;
238     uint8_t                 intr_type;
239 
240 } mss_watchdog_config_t;
241 
242 /***************************************************************************//**
243  Internal constants and types
244 *******************************************************************************/
245 #define MSS_WDOG_INTEN_MVRP                 0u
246 #define MSS_WDOG_INTEN_TRIG                 1u
247 #define MSS_WDOG_INTEN_SLEEP                2u
248 #define MSS_WDOG_ACTIVE_SLEEP               3u
249 #define MSS_WDOG_ENA_FORBIDDEN              4u
250 
251 #define MSS_WDOG_INTEN_MVRP_MASK            ( 1u << MSS_WDOG_INTEN_MVRP)
252 #define MSS_WDOG_INTEN_TRIG_MASK            ( 1u << MSS_WDOG_INTEN_TRIG)
253 #define MSS_WDOG_INTEN_SLEEP_MASK           ( 1u << MSS_WDOG_INTEN_SLEEP)
254 #define MSS_WDOG_ACTIVE_SLEEP_MASK          ( 1u << MSS_WDOG_ACTIVE_SLEEP)
255 #define MSS_WDOG_ENA_FORBIDDEN_MASK         ( 1u << MSS_WDOG_ENA_FORBIDDEN)
256 
257 #define MSS_WDOG_MVRP_TRIPPED               0u
258 #define MSS_WDOG_WDOG_TRIPPED               1u
259 #define MSS_WDOG_FORBIDDEN                  2u
260 #define MSS_WDOG_TRIGGERED                  3u
261 #define MSS_WDOG_LOCKED                     4u
262 #define MSS_WDOG_DEVRST                     5u
263 
264 #define MSS_WDOG_MVRP_TRIPPED_MASK          ( 1u << MSS_WDOG_MVRP_TRIPPED)
265 #define MSS_WDOG_WDOG_TRIPPED_MASK          ( 1u << MSS_WDOG_WDOG_TRIPPED)
266 #define MSS_WDOG_FORBIDDEN_MASK             ( 1u << MSS_WDOG_FORBIDDEN)
267 #define MSS_WDOG_TRIGGERED_MASK             ( 1u << MSS_WDOG_TRIGGERED)
268 #define MSS_WDOG_LOCKED_MASK                ( 1u << MSS_WDOG_LOCKED)
269 #define MSS_WDOG_DEVRST_MASK                ( 1u << MSS_WDOG_DEVRST)
270 
271 #define MSS_WDOG_TRIGGER_MAX                4095u
272 #define MSS_WDOG_TIMER_MAX                  16777200u            /*0xFFFFFFu*/
273 
274 /*
275   The WATCHDOG_TypeDef is the hardware register structure for the PolarFire SoC
276   MSS Watchdog.
277  */
278 typedef struct
279 {
280     volatile   uint32_t  REFRESH;
281     volatile   uint32_t  CONTROL;
282     volatile   uint32_t  STATUS;
283     volatile   uint32_t  TIME;
284     volatile   uint32_t  MSVP;
285     volatile   uint32_t  TRIGGER;
286     volatile   uint32_t  FORCE;
287 } WATCHDOG_TypeDef;
288 
289 extern WATCHDOG_TypeDef* wdog_hw_base[10];
290 
291 /***************************************************************************//**
292   The MSS_WDOG_REFRESH_KEY macro holds the magic value which will cause a reload
293   of the watchdog's down counter when written to the watchdog's WDOGREFRESH
294   register.
295  */
296 #define MSS_WDOG_REFRESH_KEY    (uint32_t)0xDEADC0DEU
297 
298 /***************************************************************************//**
299   The MSS_WDOG_FORCE_RESET_KEY macro holds the magic value which will force a
300   reset if the Watchdog is already timed out (gone past the timeout value).
301   Writing Any other value or writing TRIGGER register at other times will trigger
302   the watchdog NMI sequence (i.e Raise the timeout interrupt).
303  */
304 #define MSS_WDOG_FORCE_RESET_KEY    (uint32_t)0xDEADU
305 
306 /***************************************************************************//**
307   The MSS_WD_get_config() function returns the current configurations of the
308   PolarFire SoC MSS Watchdog. The MSS Watchdog is pre-initialized by the flash
309   bits at the design time. When used for the first time before calling the
310   MSS_WD_configure() function, this function will return the default
311   configurations as configured at the design time. You can reconfigure the
312   MSS Watchdog using MSS_WD_configure() function. A call to MSS_WD_get_config()
313   function will then return the current configuration values set by a previous
314   call to MSS_WD_configure() function. You may not need to use this function if
315   you do not want to know what the current configurations are. In that case, you
316   can directly use the MSS_WD_configure() function to configure the MSS Watchdog
317   to the values of your choice.
318 
319   @param wd_num
320     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
321     on which the operation needs to be performed. The Watchdog module number can
322     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
323     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
324     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI Correspond to the Watchdog
325     module number 0 to 5 when they appear on the AXI switch Slave 6.
326 
327   @param config
328     The config parameter is the return parameter in which the current
329     configurations of the watchdog module will be stored.
330 
331     Please see the description of mss_watchdog_config_t for details.
332 
333   @return
334     This function does not return any value.
335 
336 
337   Example:
338   @code
339   #include "mss_watchdog.h"
340   mss_watchdog_config_t wd0lo_config;
341 
342   void e51( void )
343   {
344       MSS_WD_get_config(MSS_WDOG0_LO, &wd0lo_config);
345 
346       wd0lo_config.forbidden_en = WDOG_ENABLE;
347       wd0lo_config.mvrp_val = 0xFFFF000u;
348 
349       MSS_WD_configure(MSS_WDOG0_LO, &wd0lo_config);
350 
351       for(;;)
352       {
353           main_task();
354       }
355   }
356 */
357 void MSS_WD_get_config
358 (
359     mss_watchdog_num_t wd_num,
360     mss_watchdog_config_t* config
361 );
362 
363 /***************************************************************************//**
364   The MSS_WD_configure() function configures the desired watchdog module. The
365   Watchdog module is pre-initialized by the flash bits at the design time to the
366   default values. You can reconfigure the Watchdog module using
367   MSS_WD_configure() function.
368 
369   Note that the MSS_WD_configure() function can be used only once, as it writes
370   into the TIME register. After a write into the TIME register, the TIME, TRIGGER
371   and MSVP register values are frozen and can't be altered again unless a system
372   reset happens.
373 
374   Note also that the MSS Watchdog is not enabled at reset, calling this function
375   will start the watchdog, it cannot then be disabled and must be refreshed
376   periodically.
377 
378   @param wd_num
379     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
380     on which the operation needs to be performed. The Watchdog module number can
381     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
382     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
383     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
384     module number 0 to 5 when the appear on the AXI switch Slave 6.
385 
386   @param config
387     The config parameter is the input parameter in which the configurations to be
388     applied to the watchdog module are provided by the application.
389     Please see the description of mss_watchdog_config_t for details.
390 
391   @return
392     This function returns a zero value when executed successfully. A non-zero
393     value is returned when the configuration values are out of bound.
394 
395   Example:
396   @code
397   #include "mss_watchdog.h"
398   mss_watchdog_config_t wd0lo_config;
399 
400   void e51( void )
401   {
402       MSS_WD_get_config(MSS_WDOG0_LO, &wd0lo_config);
403 
404       wd0lo_config.forbidden_en = WDOG_ENABLE;
405       wd0lo_config.mvrp_val = 0xFFFF000u;
406 
407       MSS_WD_configure(MSS_WDOG0_LO, &wd0lo_config);
408 
409       for(;;)
410       {
411           main_task();
412       }
413   }
414 */
415 uint8_t MSS_WD_configure
416 (
417     mss_watchdog_num_t wd_num,
418     const mss_watchdog_config_t * config
419 );
420 
421 /***************************************************************************//**
422   The MSS_WD_reload() function causes the watchdog to reload its down-counter
423   timer with the load value configured through the MSS configurator in the
424   hardware flow. This function must be called regularly to avoid a system reset
425   or a watchdog interrupt.
426 
427   Note that the MSS Watchdog is not enabled at reset, calling this function
428   will start the watchdog, it cannot then be disabled and must be refreshed
429   periodically.
430 
431   @param wd_num
432     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
433     on which the operation needs to be performed. The Watchdog module number can
434     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
435     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
436     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
437     module number 0 to 5 when they appear on the AXI switch Slave 6.
438 
439   @return
440     This function does not return a value.
441  */
MSS_WD_reload(mss_watchdog_num_t wd_num)442 static inline void MSS_WD_reload(mss_watchdog_num_t wd_num)
443 {
444     if ((WATCHDOG_TypeDef*)0 != wdog_hw_base[wd_num])
445     {
446         wdog_hw_base[wd_num]->REFRESH = MSS_WDOG_REFRESH_KEY;
447     }
448 }
449 
450 /***************************************************************************//**
451   The MSS_WD_current_value() function returns the current value of the
452   watchdog's down-counter.
453 
454  @param wd_num
455     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
456     on which the operation needs to be performed. The Watchdog module number can
457     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
458     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
459     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
460     module number 0 to 5 when the appear on the AXI switch Slave 6.
461 
462   @return
463     This function returns the current value of the watchdog’s down-counter as
464     a 32-bit unsigned integer.
465  */
MSS_WD_current_value(mss_watchdog_num_t wd_num)466 static inline uint32_t MSS_WD_current_value(mss_watchdog_num_t wd_num)
467 {
468     return wdog_hw_base[wd_num]->REFRESH;
469 }
470 
471 /***************************************************************************//**
472   The MSS_WD_forbidden_status() function returns the refresh status of the
473   MSS Watchdog.
474 
475   @param wd_num
476     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
477     on which the operation needs to be performed. The Watchdog module number can
478     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
479     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
480     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
481     module number 0 to 5 when the appear on the AXI switch Slave 6.
482 
483   @return
484     This function returns the refresh status of the watchdog. A value of 1
485     indicates that watchdog's down-counter is within the forbidden window and
486     that a reload should not be done. A value of 0 indicates that the watchdog's
487     down counter is within the permitted window and that a reload is allowed.
488  */
MSS_WD_forbidden_status(mss_watchdog_num_t wd_num)489 static inline uint32_t MSS_WD_forbidden_status(mss_watchdog_num_t wd_num)
490 {
491     return ((wdog_hw_base[wd_num]->STATUS & MSS_WDOG_FORBIDDEN_MASK) >>
492                                                             MSS_WDOG_FORBIDDEN);
493 }
494 
495 /***************************************************************************//**
496   The MSS_WD_enable_mvrp_irq() function enables the MVRP interrupt.
497   The MSS Watchdog 0 to 4 generate a local MVRP interrupt to HART0 to 4
498   respectively. At the same time these interrupts are also available over the
499   PLIC. This function allows you to choose which interrupt type should be
500   enabled for each interrupt. The corresponding interrupt handler gets called
501   when the interrupt asserts.
502 
503   Note: The Watchdog MVRP interrupt handler default implementations are
504         weakly defined in  the PolarFire SoC HAL. You must provide your own
505         implementation of these functions, which will override the default
506         implementation, to suit your application. Please refer mss_ints.h in the
507         MPFS HAL for the actual names and the prototypes of these functions.
508 
509   Note: This function must be called from appropriate HART context.
510 
511    @param wd_num
512     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
513     on which the operation needs to be performed. The Watchdog module number can
514     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
515     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
516     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
517     module number 0 to 5 when the appear on the AXI switch Slave 6.
518 
519   @param intr_type
520     The intr_type parameter indicates the type of interrupt that must be enabled.
521     The MVRP interrupt for each hart can either be local interrupt to that hart
522     or it can be accessed as a PLIC interrupt.
523 
524   @return
525     This function does not return a value.
526 
527   Example:
528   @code
529   #include "mss_watchdog.h"
530   void e51( void )
531   {
532 
533       MSS_WD_enable_mvrp_irq(wd_num);
534       for (;;)
535       {
536           main_task();
537           cortex_sleep();
538       }
539   }
540 
541   void wdog0_mvrp_E51_local_IRQHandler_10(void)
542   {
543       process_timeout();
544       MSS_WD_clear_mvrp_irq();
545   }
546   @endcode
547  */
548 static inline void
MSS_WD_enable_mvrp_irq(mss_watchdog_num_t wd_num)549 MSS_WD_enable_mvrp_irq
550 (
551     mss_watchdog_num_t wd_num
552 )
553 {
554     if ((WATCHDOG_TypeDef*)0 != wdog_hw_base[wd_num])
555     {
556         wdog_hw_base[wd_num]->CONTROL |= MSS_WDOG_INTEN_MVRP_MASK;
557     }
558 }
559 
560 /***************************************************************************//**
561   The MSS_WD_disable_mvrp_irq() function disables the generation of the
562   MVRP interrupt.
563 
564   Note: This function must be called from appropriate HART context.
565 
566  @param wd_num
567     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
568     on which the operation needs to be performed. The Watchdog module number can
569     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
570     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
571     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
572     module number 0 to 5 when the appear on the AXI switch Slave 6.
573 
574   @return
575     This function does not return a value.
576  */
577 static __inline void
MSS_WD_disable_mvrp_irq(mss_watchdog_num_t wd_num)578 MSS_WD_disable_mvrp_irq
579 (
580     mss_watchdog_num_t wd_num
581 )
582 {
583     if ((WATCHDOG_TypeDef*)0 != wdog_hw_base[wd_num])
584     {
585         wdog_hw_base[wd_num]->CONTROL &= ~(MSS_WDOG_INTEN_MVRP_MASK);
586     }
587 }
588 
589 /***************************************************************************//**
590   The MSS_WD_clear_timeout_irq() function clears the watchdog’s timeout
591   interrupt which is connected to the RISC-V NMI interrupt. Calling
592   MSS_WD_clear_timeout_irq() results in clearing the RISC-V NMI interrupt.
593   Note: You must call the MSS_WD_clear_timeout_irq() function as part of your
594         implementation of the wdog0_tout_u51_local_IRQHandler_9() timeout
595         interrupt service routine (ISR) in order to prevent the same interrupt
596         event re-triggering a call to the timeout ISR.
597 
598   Note: This function must be called from appropriate HART context.
599 
600   Note: The MSS_WD_enable_timeout_irq() and MSS_WD_disable_timeout_irq() are
601         removed as in the PolarFire SoC MSS Watchdog the timeout interrupt is
602         permanently enabled by default and it can not be disabled.
603 
604  @param wd_num
605     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
606     on which the operation needs to be performed. The Watchdog module number can
607     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
608     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
609     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
610     module number 0 to 5 when the appear on the AXI switch Slave 6.
611 
612   @return
613     This function does not return any value.
614 
615  */
MSS_WD_clear_timeout_irq(mss_watchdog_num_t wd_num)616 static inline void MSS_WD_clear_timeout_irq(mss_watchdog_num_t wd_num)
617 {
618     if ((WATCHDOG_TypeDef*)0 != wdog_hw_base[wd_num])
619     {
620         wdog_hw_base[wd_num]->STATUS |=  MSS_WDOG_WDOG_TRIPPED_MASK;
621         /*
622          * Perform a second write to ensure that the first write completed before
623          * returning from this function. This is to account for posted writes across
624          * the AHB matrix. The second write ensures that the first write has
625          * completed and that the interrupt line has been de-asserted by the time
626          * the function returns. Omitting the second write may result in a delay
627          * in the de-assertion of the interrupt line going to the RISC-V and a
628          * retriggering of the interrupt.
629          */
630         wdog_hw_base[wd_num]->STATUS |=  MSS_WDOG_WDOG_TRIPPED_MASK;
631     }
632 }
633 
634 /***************************************************************************//**
635   The MSS_WD_clear_mvrp_irq() function clears the mvrp interrupt. This
636   function also clears the interrupt in the RISC-V interrupt controller
637   through a call to NVIC_ClearPendingIRQ().
638   Note: You must call the MSS_WD_clear_mvrp_irq() function as part of  your
639         implementation of the wdog0_msvp_u51_local_IRQHandler_10() mvrp interrupt service
640         routine (ISR) in order to prevent the same interrupt event re-triggering
641         a call to the mvrp ISR.
642 
643  @param wd_num
644     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
645     on which the operation needs to be performed. The Watchdog module number can
646     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
647     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
648     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
649     module number 0 to 5 when the appear on the AXI switch Slave 6.
650 
651   @return
652     This function does not return a value.
653 
654 */
MSS_WD_clear_mvrp_irq(mss_watchdog_num_t wd_num)655 static inline void MSS_WD_clear_mvrp_irq(mss_watchdog_num_t wd_num)
656 {
657     if ((WATCHDOG_TypeDef*)0 != wdog_hw_base[wd_num])
658     {
659         wdog_hw_base[wd_num]->STATUS |=  MSS_WDOG_MVRP_TRIPPED_MASK;
660         /*
661          * Perform a second write to ensure that the first write completed before
662          * returning from this function. This is to account for posted writes across
663          * the AHB matrix. The second write ensures that the first write has
664          * completed and that the interrupt line has been de-asserted by the time
665          * the function returns. Omitting the second write may result in a delay
666          * in the de-assertion of the interrupt line going to the RISC-V and a
667          * re-triggering of the interrupt.
668          */
669         wdog_hw_base[wd_num]->STATUS |=  MSS_WDOG_MVRP_TRIPPED_MASK;
670     }
671 }
672 
673 /***************************************************************************//**
674   The MSS_WD_timeout_occured() function reports the occurrence of a timeout
675   event.
676 
677  @param wd_num
678     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
679     on which the operation needs to be performed. The Watchdog module number can
680     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
681     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
682     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
683     module number 0 to 5 when the appear on the AXI switch Slave 6.
684 
685   @return
686     A zero value indicates no watchdog timeout event occurred. A value of 1
687     indicates that a timeout event occurred.
688 
689   Example:
690   @code
691   #include "mss_watchdog.h"
692   void e51( void )
693   {
694       uint32_t wdg_reset;
695 
696       wdg_reset = MSS_WD_timeout_occured();
697       if (wdg_reset)
698       {
699           log_watchdog_event();
700           MSS_WD_clear_timeout_event();
701       }
702 
703       for(;;)
704       {
705           main_task();
706       }
707   }
708 */
MSS_WD_timeout_occured(mss_watchdog_num_t wd_num)709 static inline uint32_t MSS_WD_timeout_occured(mss_watchdog_num_t wd_num)
710 {
711     return((wdog_hw_base[wd_num]->STATUS & MSS_WDOG_TRIGGERED_MASK) >>
712                                                             MSS_WDOG_TRIGGERED);
713 }
714 
715 /***************************************************************************//**
716   The MSS_WD_force_reset() function is used to force an immediate reset
717   if the watchdog has already triggered. Writing any value in this condition
718   will cause an NMI sequence. Moreover any attempt to force reset when the
719   watchdog is not in triggered condition will also cause an NMI sequence.
720 
721   @param wd_num
722     The wd_num parameter is the Watchdog module number in the PolarFire SoC MSS
723     on which the operation needs to be performed. The Watchdog module number can
724     be chosen using mss_watchdog_num_t. The MSS_WDOG0_LO to MSS_WDOG4_LO
725     correspond to the Watchdog module number 0 to 5 when the appear on the AXI
726     switch Slave 5. The MSS_WDOG0_HI to MSS_WDOG4_HI correspond to the watchdog
727     module number 0 to 5 when the appear on the AXI switch Slave 6.
728 
729   @return
730     This function does not return a value.
731  */
MSS_WD_force_reset(mss_watchdog_num_t wd_num)732 static inline void MSS_WD_force_reset(mss_watchdog_num_t wd_num)
733 {
734     if (MSS_WDOG_TRIGGERED_MASK ==
735                        (uint32_t)(wdog_hw_base[wd_num]->STATUS |
736                                                        MSS_WDOG_TRIGGERED_MASK))
737     {
738         wdog_hw_base[wd_num]->FORCE = 0xDEADu;
739     }
740     else
741     {
742         wdog_hw_base[wd_num]->FORCE = 0x0u;
743     }
744 }
745 
746 #ifdef __cplusplus
747 }
748 #endif
749 
750 #endif /* MSS_WATCHDOG_H_ */
751