drv_wdt.c 3.4 KB
Newer Older
B
bigmagic 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author         Notes
 * 2019-07-29     zdzn           first version
 */
#include "drv_wdt.h"

#ifdef BSP_USING_WDT

#define PM_RSTC				0x1c
#define PM_RSTS				0x20
#define PM_WDOG				0x24

#define PM_PASSWORD			0x5a000000

#define PM_WDOG_TIME_SET		0x000fffff
#define PM_RSTC_WRCFG_CLR		0xffffffcf
#define PM_RSTS_HADWRH_SET		0x00000040
#define PM_RSTC_WRCFG_SET		0x00000030
#define PM_RSTC_WRCFG_FULL_RESET	0x00000020
#define PM_RSTC_RESET			0x00000102
#define PM_RSTS_PARTITION_CLR          0xfffffaaa

#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)

static struct raspi_wdt_driver bcm_wdt =
{
    .base = PER_BASE,
};

void raspi_watchdog_init(rt_uint32_t time_init)
{
    bcm_wdt.timeout = time_init;
}

void raspi_watchdog_start()
{
    volatile rt_uint32_t cur;
    bcm283x_peri_write(bcm_wdt.base + PM_WDOG, PM_PASSWORD
            | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET));
    bcm283x_peri_write(bcm_wdt.base + PM_WDOG, PM_PASSWORD
            | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET));

    cur = bcm283x_peri_read(bcm_wdt.base + PM_RSTC);

    bcm283x_peri_write(bcm_wdt.base + PM_RSTC, PM_PASSWORD
            | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET);

}

void raspi_watchdog_stop()
{
    bcm283x_peri_write(bcm_wdt.base + PM_RSTC, PM_PASSWORD | PM_RSTC_RESET);
}

void raspi_watchdog_clr()
{
    bcm_wdt.timeout = 0;
}

void raspi_watchdog_set_timeout( rt_uint32_t timeout_us)
{
    bcm_wdt.timeout = timeout_us;
}

rt_uint64_t raspi_watchdog_get_timeout()
{
    return bcm_wdt.timeout;
}

rt_uint64_t raspi_watchdog_get_timeleft()
{
    rt_uint32_t ret = bcm283x_peri_read(bcm_wdt.base + PM_WDOG);
    return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
}

static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt)
{
    /*init for 10S*/
    raspi_watchdog_init(1000000);
    raspi_watchdog_start();
    raspi_watchdog_stop();
    return RT_EOK;
}

static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg)
{
    rt_uint64_t  timeout_us = 0;
    switch (cmd)
    {
    case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
        timeout_us = *((rt_uint32_t *)arg) * 1000000;
        if (timeout_us >= 0xFFFFFFFF)
            timeout_us = 0xFFFFFFFF;
        raspi_watchdog_set_timeout((rt_uint32_t)timeout_us);
        break;
    case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
        timeout_us = raspi_watchdog_get_timeout();
        *((rt_uint32_t *)arg) = timeout_us / 1000000;
        break;
    case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
        timeout_us = raspi_watchdog_get_timeleft();
        *((rt_uint32_t *)arg) = timeout_us / 1000000;
        break;
    case RT_DEVICE_CTRL_WDT_KEEPALIVE:
        raspi_watchdog_clr();
        break;
    case RT_DEVICE_CTRL_WDT_START:
        raspi_watchdog_start();
        break;
    case RT_DEVICE_CTRL_WDT_STOP:
        raspi_watchdog_stop();
        break;
    default:
        return RT_EIO;
    }
    return RT_EOK;
}

static const struct rt_watchdog_ops raspi_wdg_pos =
{
    raspi_wdg_init,
    raspi_wdg_control,
};

static rt_watchdog_t raspi_wdg;

int rt_hw_wdt_init(void)
{
    raspi_wdg.ops = &raspi_wdg_pos;
    rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL);
    return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_wdt_init);
#endif /*BSP_USING_WDT */