0
votes

I have an OrangePi PC Plus board which runs Linux (ubuntu 18.04) with kernel 4.19.57 on Allwinner H3 processor.

We have designed a hardware watchdog using STWD100 ASIC. This IC has a gpio which should be toggled at least once a second, otherwise it resets the board. On the other hand, I have googled on this subject and I realized that Linux kernel has a driver called GPIO watchdog (in drivers/watchdog/gpio_wdt.c file).

Because of the project requirement, watchdog GPIO is connected to pin PA19 of processor should begin toggling as soon as the kernel is decompressed and executed, or board is forced reboot by STWD100. For making the issue more complicated, I should add that we can not make any circuit modification. In order to prevent STWD100 from resetting our board before the kernel is loaded, we have a timer which disables STWD100 for about 5~8 seconds and we can not change this time interval (because it is fixed in the circuit). Therefore, we should run our GPIO watchdog driver in Linux kernel as soon as control is passed to the kernel.

What I have done so far:

  1. Added printk("============================\n"); to gpio_wdt_probe() function of gpio-watchdog driver.
  2. Cross-compiled kernel with CONFIG_GPIO_WATCHDOG=y, CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y.
  3. Decompiled board device tree using dtc to get device tree source code from dtb file.
  4. Modified my device tree source code as follows (according to this link):
/dts-v1/;
/ {
    ...
    soc {
        ...
        pinctrl@1c20800 {
            ...
            phandle = <0x0a>;
            /* Node added by me */
            gpio_wdt: gpio_wdt {                        
                pins = "PA19";
                function = "gpio_out";
                phandle = <0x74>;
            };
            /* Node added by me */
            gpio1: gpio1 {
                gpio-controller;
                #gpio-cells = <2>;
            };
            
        };      
            
        ... 
        /* This node is part of original dts file which triggers internal processor watchdog*/
        watchdog@1c20ca0 {          
            compatible = "allwinner,sun6i-a31-wdt";
            reg = <0x1c20ca0 0x20>;
            interrupts = <0x00 0x19 0x04>;
            phandle = <0x57>;
        };
        ...
    };
    ...
    /* Node added by me */
    watchdog-gpio {
        compatible = "linux,wdt-gpio";
        gpios = <&gpio1 19 1>;          /* PA19 should be toggled */
        hw_algo = "toggle";
        hw_margin_ms = <200>;
        always-running;
        phandle = <0x75>;       
    };
    ...
    __symbols__ {
        ...
        /* Symbol added by me */
        gpiowdt = "/watchdog-gpio";
    };
};

In the source ... depicts some other nodes which I did not modify.

  1. compiled modified device tree using dtc command.

When kernel runs, I can see ============================ in multiple occasions in kernel logs on UART port. This demonstrates that my builtin GPIO watchdog driver is being probed, but my PA19 pin is not toggling. In the case above, I do not get any warning from dtc compiler, but if I replace gpio_wdt instead of gpio1 in the watchdog-gpio node, when compiling device tree I get the following warning from dtc compiler:

Warning (gpios_property): /watchdog-gpio: Missing property '#gpio-cells' in node /soc/pinctrl@1c20800/gpio_wdt or bad phandle (referred from gpios[0])

Could anyone help me find the issue?

1
I'm puzzled by seeing the gpio1 node in DTS. If it's production ready device tree it should have GPIO controller defined.0andriy
@0andriy without definition of gpio1, I get this error from dc compiler: ERROR (phandle_references): /watchdog-gpio: Reference to non-existent node or label "gpio1". I don't know what is the problem. I compile device tree on my PC ubuntu (amd64). should I cross compile it? I think device tree does not require cross compilation.Mohamadreza Misagh
My point is that the original device tree for the platform must have defined GPIO controller already!0andriy
@0andriy , Thank you. The issue is solved now.Mohamadreza Misagh

1 Answers

0
votes

Eventually, I found the solution.

Definition of neither gpio1 nor gpio_wdt would not be useful. I deleted these definitions and modified gpios property in watchdog-gpio node as follows:

watchdog-gpio {
        compatible = "linux,wdt-gpio";
        gpios = <0x0a 0 19 1>;          /* PA19 should be toggled */
        hw_algo = "toggle";
        hw_margin_ms = <200>;
        always-running;
        phandle = <0x75>;       
    };

where: 0x0a is phandle of pinctrl@1c20800 node, 0 corresponds to PortA (for PortC insert 2, for PortD insert 3 and so on), 19 is pin number and 1 corresponds to GPIO flag GPIO_ACTIVE_LOW (flags, that determine active high or active low, pull-up/pull-down resistor connection and so on, are described here).