uboot – driver development – dw watchdog

Description

  • The watchdog module used by the company’s SOC is Synopsys’ IP.

Requirements

  • Users sometimes do some development in uboot/kernel and add some new functions (OTA upgrade, etc.), which may cause problems such as uboot/kernel startup crash or even device freeze. It is necessary to enable watchdog during the uboot startup phase to monitor the operation of the device and reset it after abnormality. .

Implementation

  • Prerequisite: The dts watchdog node configuration is ok.
  • Due to historical reasons, uboot natively supports two wdt drivers and the configuration/implementation methods used, depending on whether it supports DM (Driver model).
  1. DM is not supported and is commonly implemented in earlier versions (uboot, wdt driver)
Core configuration item: CONFIG_HW_WATCHDOG
  1. Support DM
Core configuration item: CONFIG_WDT

// file: drivers/watchdog/Kconfig
config WDT
    bool "Enable driver model for watchdog timer drivers"
    depends on DM
    ....

DM is not supported

Configuration items

  1. Core configuration
CONFIG_HW_WATCHDOG
  1. wdt timeout time
CONFIG_WATCHDOG_TIMEOUT_MSECS
  1. Specific model wdt, for example: dw wdt.
CONFIG_DESIGNWARE_WATCHDOG
  • If support for DM (CONFIG_WDT) is not configured, but hardware wdt is configured, CONFIG_HW_WATCHDOG will be automatically selected, for example:
config DESIGNWARE_WATCHDOG
    bool "Designware watchdog timer support"
    select HW_WATCHDOG if !WDT
    ...

Driver code

  1. Define and implement driver-related functional interfaces
//file: drivers/watchdog/designware_wdt.c
static int designware_wdt_settimeout(unsigned int timeout)
{
    ....
}

static void designware_wdt_enable(void)
{
    ....
}

static void designware_wdt_disable(void)
{
    ....
}

static unsigned int designware_wdt_is_enabled(void)
{
    ....
}
  1. Define and implement external interface
//file: drivers/watchdog/designware_wdt.c
#if defined(CONFIG_HW_WATCHDOG)
void hw_watchdog_reset(void)
{
    ...
}

void hw_watchdog_init(void)
{
    //Initialize wdt and enable
    ...
}

void hw_watchdog_disable(void)
{
    ...
}
#endif

Used in uboot

  1. The header file (watchdog.h) will define unified macros (WATCHDOG_RESET, WATCHDOG_DISABLE) that point to the hw external interface implemented in the driver file. The specific use will be explained later.
// file: include/watchdog.h
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
#define INIT_FUNC_WATCHDOG_INIT init_func_watchdog_init,
#define INIT_FUNC_WATCHDOG_RESET init_func_watchdog_reset,
#else
#define INIT_FUNC_WATCHDOG_INIT
#define INIT_FUNC_WATCHDOG_RESET
#endif

#ifdef CONFIG_HW_WATCHDOG
    #if defined(__ASSEMBLY__)
        #define WATCHDOG_RESET bl hw_watchdog_reset
    #else
        extern void hw_watchdog_reset(void);
        extern void hw_watchdog_disable(void);

        #define WATCHDOG_RESET hw_watchdog_reset
        #define WATCHDOG_DISABLE hw_watchdog_disable
    #endif /* __ASSEMBLY__ */
#else
    ....
#endif
  1. Since DM is not supported, wdt-uclass.c (DM interface) is not used.

Verification

  • In this way, the overall execution process is relatively fixed. Uboot will automatically run when wdt is started. It supports fewer configuration items and the verification method can only be code debugging.
  • Since DM is not supported, this mode does not support wdt cmd.

Support DM

Configuration items

  1. Core configuration
CONFIG_WDT
CONFIG_WATCHDOG // enable the dog feeding interface used internally by uboot. It must be enabled in this mode.
  • After configuring CONFIG_WDT, CONFIG_WATCHDOG will be automatically turned on, as follows:
// file: drivers/watchdog/Kconfig
config WDT
    bool "Enable driver model for watchdog timer drivers"
    depends on DM
    imply WATCHDOG
    ...
  1. Automatic startup configuration (optional configuration)
CONFIG_WATCHDOG_AUTOSTART=y // Automatically start
CONFIG_WATCHDOG_TIMEOUT_MSECS //wdt timeout time, default 60s
  1. Specific model wdt, for example: dw wdt.
CONFIG_DESIGNWARE_WATCHDOG

Driver code

  1. According to the DM model, implement probe and other related interfaces
  2. Implement the wdt operation interface defined by DM
//file: include/wdt.h
struct wdt_ops {
    int (*start)(struct udevice *dev, u64 timeout_ms, ulong flags);
    int (*stop)(struct udevice *dev);
    int (*reset)(struct udevice *dev);
    int (*expire_now)(struct udevice *dev, ulong flags);
}

Used in uboot

  1. wdt cmd uses the unified interface in wdt-uclass.c, and the functions in wdt-uclass.c then call the interface of the specific driver.
  2. A unified macro (WATCHDOG_RESET) will be defined in the header file (watchdog.h) to point to the external dog feeding interface implemented in wdt-uclass.c. The specific use will be explained later.
// file: include/watchdog.h
#ifdef CONFIG_HW_WATCHDOG
    ...
#else
    /*
     * Maybe a software watchdog?
     */
    #if defined(CONFIG_WATCHDOG)
            #if defined(__ASSEMBLY__)
                    #define WATCHDOG_RESET bl watchdog_reset
            #else
                    /* Don't require the watchdog to be enabled in SPL */
                    #if defined(CONFIG_SPL_BUILD) & amp; & amp; \
                            !defined(CONFIG_SPL_WATCHDOG)
                            #define WATCHDOG_RESET() {}
                    #else
                            extern void watchdog_reset(void);

                            #define WATCHDOG_RESET watchdog_reset
                    #endif
            #endif
    #else
            /*
             * No hardware or software watchdog.
             */
            #if defined(__ASSEMBLY__)
                    #define WATCHDOG_RESET /*XXX DO_NOT_DEL_THIS_COMMENT*/
            #else
                    #define WATCHDOG_RESET() {}
            #endif /* __ASSEMBLY__ */
    #endif /* CONFIG_WATCHDOG & amp; & amp; !__ASSEMBLY__ */
#endif /* CONFIG_HW_WATCHDOG */

Verification

  1. Verify using cli command
  • enable wdt command (cmdline)
CONFIG_CMD_WDT=y // wdt cmd
  • running result
uboot# wdt
wdt - Watchdog sub-system

Usage:
wdt list - list watchdog devices
wdt dev [<name>] - get/set current watchdog device
wdt start <timeout ms> [flags] - start watchdog timer
wdt stop - stop watchdog timer
wdt reset-reset watchdog timer
wdt expire [flags] - expire watchdog timer immediately

uboot# wdt list
dw-wd@0x27000000 (designware_wdt) // dts configuration
uboot# wdt dev dw-wd@0x27000000
uboot# wdt start 30000

Used in uboot

  • For both configurations (whether DM is supported), uboot uses unified macros (WATCHDOG_RESET, etc.) to operate wdt. The difference is the function pointed to by the macro.
  1. DM is not supported. WATCHDOG_RESET points to the hw_watchdog_reset function in the wdt driver.
  2. Supports DM, WATCHDOG_RESET points to the watchdog_reset function in wdt-uclass.c.
  • When uboot is initialized, it will actively call INIT_FUNC_WATCHDOG_INIT to initialize wdt. DM configuration (CONFIG_HW_WATCHDOG) is not supported. When wdt is initialized, wdt will be enabled directly.
//file: common/board_f.c
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
static int init_func_watchdog_init(void)
{
# if defined(CONFIG_HW_WATCHDOG) & amp; & amp; \
    (defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \
    defined(CONFIG_SH) || \
    defined(CONFIG_DESIGNWARE_WATCHDOG) || \
    defined(CONFIG_IMX_WATCHDOG))
    hw_watchdog_init(); //This function, the default implementation will configure wdt and enable
    puts("Watchdog enabled\\
");
# endif
    WATCHDOG_RESET();

    return 0;
}

int init_func_watchdog_reset(void)
{
        WATCHDOG_RESET();

        return 0;
}
#endif /* CONFIG_WATCHDOG */
  • uboot is a bare metal program, and all operations are executed sequentially. After turning on wdt, if there are time-consuming operations, you need to call WATCHDOG_RESET to feed the dog. When entering the cli, uboot cli will call WATCHDOG_RESET at intervals to feed the dog.