This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DRA829V: DRA829 RTI WATCHDOG

Part Number: DRA829V

In one thread ms.keerty told 

There are 3 parts to it:

 

RTI Module which has the timer expiry.

SOC ESM - This is the error signaling module that needs to catch the watchdog RTI timer expiry.

ESM PMIC which is PMIC part to trigger a SoC reset upon ESM event.

1 --> is taken care by the RTI watchdog driver: github.com/.../rti_wdt.c

 

2 --> Is done as part of R5 SPL repo: github.com/.../k3_esm.c

 

3 --> Is done as part of R5 SPL in U-Boot repo: https://github.com/u-boot/u-boot/blob/master/drivers/

 

for j7200,I want above for j721e dra829v

  • Hi Charan,

    It is the same for J721e as well. RTI watchdog works out of the box on J721e SDK as well.
    Same IP and same design the above 3 hold good for J721e as well and works on TI J721e EVM.

    - Keerthy

  • Hi Keerthy mam,

    my rti_wdt.c file looks different which is here

    // SPDX-License-Identifier: GPL-2.0+
    /*
     * Copyright (c) Siemens AG, 2020
     *
     * Authors:
     *   Jan Kiszka <jan.kiszka@siemens.com>
     *
     * Derived from linux/drivers/watchdog/rti_wdt.c
     */

    #include <common.h>
    #include <clk.h>
    #include <dm.h>
    #include <dm/device_compat.h>
    #include <power-domain.h>
    #include <wdt.h>
    #include <asm/io.h>
    #include <remoteproc.h>

    /* Timer register set definition */
    #define RTIDWDCTRL        0x90
    #define RTIDWDPRLD        0x94
    #define RTIWDSTATUS        0x98
    #define RTIWDKEY        0x9c
    #define RTIDWDCNTR        0xa0
    #define RTIWWDRXCTRL        0xa4
    #define RTIWWDSIZECTRL        0xa8

    #define RTIWWDRX_NMI        0xa


    #define RTIWWDSIZE_50P        0x50

    #define WDENABLE_KEY        0xa98559da

    #define WDKEY_SEQ0        0xe51a
    #define WDKEY_SEQ1        0xa35c

    #define WDT_PRELOAD_SHIFT    13

    #define WDT_PRELOAD_MAX        0xfff

    struct rti_wdt_priv {
        phys_addr_t regs;
        unsigned int clk_hz;
    };

    #ifdef CONFIG_WDT_K3_RTI_LOAD_FW
    #define RTI_WDT_FIT_PATH    "/fit-images/k3-rti-wdt-firmware"

    static int rti_wdt_load_fw(struct udevice *dev)
    {
        struct udevice *rproc_dev;
        int primary_core, ret;
        u32 cluster_mode;
        ofnode node;
        u64 rti_wdt_fw;
        u32 rti_wdt_fw_size;

        node = ofnode_path(RTI_WDT_FIT_PATH);
        if (!ofnode_valid(node))
            goto fit_error;

        ret = ofnode_read_u64(node, "load", &rti_wdt_fw);
        if (ret)
            goto fit_error;
        ret = ofnode_read_u32(node, "size", &rti_wdt_fw_size);
        if (ret)
            goto fit_error;

        node = ofnode_by_compatible(ofnode_null(), "ti,am654-r5fss");
        if (!ofnode_valid(node))
            goto dt_error;

        ret = ofnode_read_u32(node, "ti,cluster-mode", &cluster_mode);
        if (ret)
            cluster_mode = 1;

        node = ofnode_by_compatible(node, "ti,am654-r5f");
        if (!ofnode_valid(node))
            goto dt_error;

        ret = uclass_get_device_by_ofnode(UCLASS_REMOTEPROC, node, &rproc_dev);
        if (ret)
            return ret;

        primary_core = dev_seq(rproc_dev);

        ret = rproc_dev_init(primary_core);
        if (ret)
            goto fw_error;

        if (cluster_mode == 1) {
            ret = rproc_dev_init(primary_core + 1);
            if (ret)
                goto fw_error;
        }

        ret = rproc_load(primary_core, (ulong)rti_wdt_fw,
                 rti_wdt_fw_size);
        if (ret)
            goto fw_error;

        ret = rproc_start(primary_core);
        if (ret)
            goto fw_error;

        return 0;

    fit_error:
        dev_err(dev, "No loadable firmware found under %s\n", RTI_WDT_FIT_PATH);
        return -ENOENT;

    dt_error:
        dev_err(dev, "No compatible firmware target processor found\n");
        return -ENODEV;

    fw_error:
        dev_err(dev, "Failed to load watchdog firmware into remote processor %d\n",
            primary_core);
        return ret;
    }
    #else
    static inline int rti_wdt_load_fw(struct udevice *dev)
    {
        return 0;
    }
    #endif




    static int rti_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
    {
        
    #if 1
        
        struct rti_wdt_priv *priv = dev_get_priv(dev);
        u32 timer_margin;
        int ret;
        
        //printf("HACK: Returning early without enabling WDT\n");
        //return 0;

        if (readl(priv->regs + RTIDWDCTRL) == WDENABLE_KEY)
            return -EBUSY;

        ret = rti_wdt_load_fw(dev);
        if (ret < 0)
            return ret;


           // timeout_ms = (timeout_ms * 10000);
            
           // printf("WDT_timeout_ms-%llu\n",timeout_ms);

        timer_margin = timeout_ms * priv->clk_hz / 1000;
        timer_margin >>= WDT_PRELOAD_SHIFT;
        if (timer_margin > WDT_PRELOAD_MAX)
            timer_margin = WDT_PRELOAD_MAX;

        writel(timer_margin, priv->regs + RTIDWDPRLD);
        writel(RTIWWDRX_NMI, priv->regs + RTIWWDRXCTRL);
        writel(RTIWWDSIZE_50P, priv->regs + RTIWWDSIZECTRL);

        readl(priv->regs + RTIWWDSIZECTRL);
        
        printf("HACK: Enabling WDT \n");

        writel(WDENABLE_KEY, priv->regs + RTIDWDCTRL); 
        
        //printf("RTIDWDCTRL RTIWWDRX_NMI Set \n");

        
        
    #endif
        return 0;
        
    }



    static int rti_wdt_reset(struct udevice *dev)
    {
        struct rti_wdt_priv *priv = dev_get_priv(dev);
        u32 prld;
        
        //printf("HACK: Returning early without servicing WDT\n");
        printf("HACK:servicing WDT\n");
        //return 0;

        /* Make sure we do not reset too early */
        prld = readl(priv->regs + RTIDWDPRLD) << WDT_PRELOAD_SHIFT;
        if (readl(priv->regs + RTIDWDCNTR) >= prld / 2)
            return -EPERM;

        writel(WDKEY_SEQ0, priv->regs + RTIWDKEY);
        writel(WDKEY_SEQ1, priv->regs + RTIWDKEY);

        return 0;
    }

    static int rti_wdt_probe(struct udevice *dev)
    {
        struct rti_wdt_priv *priv = dev_get_priv(dev);
        struct clk clk;
        int ret;

        priv->regs = devfdt_get_addr(dev);
        if (!priv->regs)
            return -EINVAL;

        ret = clk_get_by_index(dev, 0, &clk);
        if (ret)
            return ret;

        priv->clk_hz = clk_get_rate(&clk);

        /*
         * If watchdog is running at 32k clock, it is not accurate.
         * Adjust frequency down in this case so that it does not expire
         * earlier than expected.
         */
        if (priv->clk_hz < 32768)
            priv->clk_hz = priv->clk_hz * 9 / 10;
            
        printf("Debug: Watchdog probbed!!!\n");


        return 0;
    }

    static const struct wdt_ops rti_wdt_ops = {
        .start = rti_wdt_start,
        .reset = rti_wdt_reset,
        
        //.start = NULL,
        //.reset = NULL,
    };

    static const struct udevice_id rti_wdt_ids[] = {
        { .compatible = "ti,j7-rti-wdt" },
        { }
    };

    U_BOOT_DRIVER(rti_wdt) = {
        .name = "rti_wdt",
        .id = UCLASS_WDT,
        .of_match = rti_wdt_ids,
        .ops = &rti_wdt_ops,
        .probe = rti_wdt_probe,
        .priv_auto    = sizeof(struct rti_wdt_priv),
        .flags = DM_FLAG_LEAVE_PD_ON,
    };

  • Aree you comparing U-Boot drivers? 

    It's the same. 

    - Keerthy 

  • With this driver,and other two files which are same , my board not getting reset or restart ,but status register showing 0x32 which means violation occurred or time out occurred,i enabled TI k3 Watchdog in menuconfig 

  • Charan,

    Have you tried from Linux? The Linux watchdog driver should be able to reset.

    Also is this a custom board or TI EVM?

    Best Regards,

    Keerthy 

  • Hi Keerthy,
    Linking another 2e2 thread - DRA821: Service watchdog in QNX without privilege access 

    Please note they do not have privilege access in linux.

    Best Regards,

    Madhurya  

  • Madhurya,

    Can you confirm if this is on QNX or Linux? Linux out of the box SDK support RTI watchdog reset.

    On the EVM just boot to Linux and run:

    'touch /dev/watchdog'

    The board should reset in 60 odd seconds.

    - Keerthy

  • Hi Keerthy,

    They are trying these two approaches, a mix of uboot and QNX

     

  • I am now trying in linux (u boot only) ,this also not resetting with the above rti_wdt.c,when I read using md ,status register showing 0x32

    • If this goes well I will try mix of u-boot and qnx
  • Hi Charan,
    This works in linux, we have showcased it to your team. But we made modifications in the uboot to ONLY ENABLE WATCHDOG, hence you will not be able to completely reset the watchdog.

    Best Regards,

    madhruya

  • Yeah,that is the problem, after i enabled also ,my board is not getting reset or restart, just in u-boot also

  • after i enabled also ,my board is not getting reset or restart, just in u-boot also

    In the Linux driver enables watchdog and in the Linux user space we trigger a test case to trigger that.

    In U-Boot you will have to do something similar. Otherwise you will not see the reset.

    If eventually you want to use QNX then i recommend focusing on that.

    - Keerthy

  • How can I do that in qnx, explain 

  • Charan,

    QNX watchdog driver is not TIs expertise and you can work with QNX.

    If you want to explore the U-Boot side:

    https://docs.u-boot.org/en/stable/usage/cmd/wdt.html

    There's a config option to test with watchdog from U-Boot command prompt.

    Best Regards,

    Keerthy