rt-thread-official/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c

186 lines
4.2 KiB
C
Raw Normal View History

2022-01-07 13:49:06 +08:00
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-10-26 bigmagic first version
*/
#include <rthw.h>
#include "drv_wdt.h"
#include "drv_gpio.h"
#include "mbox.h"
2022-01-07 13:49:06 +08:00
#include "raspi4.h"
#ifdef BSP_USING_WDT
#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
static struct raspi_wdt_driver bcm_wdt;
void raspi_watchdog_init(rt_uint32_t time_init)
{
bcm_wdt.timeout = time_init;
}
void raspi_watchdog_start()
{
volatile rt_uint32_t cur;
PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET);
cur = (PM_RSTC);
PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
}
void raspi_watchdog_stop()
{
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 = (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);
void poweroff(void)
{
unsigned long r;
rt_kprintf("poweroff...\n");
/* power off devices one by one */
for (r = 0; r < 16; ++r)
{
bcm271x_mbox_poweroff_devices(r);
}
/* power off gpio pins (but not VCC pins) */
GPIO_REG_GPFSEL0(GPIO_BASE) = 0;
GPIO_REG_GPFSEL1(GPIO_BASE) = 0;
GPIO_REG_GPFSEL2(GPIO_BASE) = 0;
GPIO_REG_GPFSEL3(GPIO_BASE) = 0;
GPIO_REG_GPFSEL4(GPIO_BASE) = 0;
GPIO_REG_GPFSEL5(GPIO_BASE) = 0;
GPIO_REG_GPPUD(GPIO_BASE) = 0;
rt_thread_mdelay(150);
GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0xffffffff;
GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0xffffffff;
rt_thread_mdelay(150);
/* flush GPIO setup */
GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0;
GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0;
/* power off the SoC (GPU + CPU), partition 63 used to indicate halt */
r = PM_RSTS;
r &= ~0xfffffaaa;
r |= 0x555;
PM_RSTS |= PM_PASSWORD | r;
PM_WDOG |= PM_PASSWORD | 0x0A;
PM_RSTC |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
while (1) {};
}
MSH_CMD_EXPORT(poweroff, poweroff...);
2022-01-07 13:49:06 +08:00
void reboot(void)
{
unsigned int r;
rt_kprintf("reboot system...\n");
rt_thread_mdelay(100);
r = PM_RSTS;
/* trigger a restart by instructing the GPU to boot from partition 0 */
r &= ~0xfffffaaa;
PM_RSTS |= (PM_PASSWORD | r); /* boot from partition 0 */
PM_WDOG |= (PM_PASSWORD | 0x0A);
PM_RSTC |= (PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET);
while (1) {};
}
MSH_CMD_EXPORT(reboot, reboot system...);
#endif /*BSP_USING_WDT */