mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 15:31:22 +01:00

For driver subsystems that are not tightly integrated into the OpenSBI init sequence, it is not important that the drivers are initialized in any particular order. By putting all of these drivers in one array, they can all be initialized with a single pass through the devicetree. This saves about 10 ms of boot time on HiFive Unmatched. Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Reviewed-by: Anup Patel <anup@brainfault.org>
78 lines
1.7 KiB
C
78 lines
1.7 KiB
C
/*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2021 Samuel Holland <samuel@sholland.org>
|
|
*/
|
|
|
|
#include <libfdt.h>
|
|
#include <sbi/riscv_io.h>
|
|
#include <sbi/sbi_bitops.h>
|
|
#include <sbi/sbi_error.h>
|
|
#include <sbi/sbi_system.h>
|
|
#include <sbi_utils/fdt/fdt_driver.h>
|
|
#include <sbi_utils/fdt/fdt_helper.h>
|
|
|
|
#define WDT_KEY_VAL 0x16aa0000
|
|
|
|
#define WDT_SOFT_RST_REG 0x08
|
|
#define WDT_SOFT_RST_EN BIT(0)
|
|
|
|
#define WDT_MODE_REG 0x18
|
|
|
|
static volatile char *sunxi_wdt_base;
|
|
|
|
static int sunxi_wdt_system_reset_check(u32 type, u32 reason)
|
|
{
|
|
switch (type) {
|
|
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
|
|
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void sunxi_wdt_system_reset(u32 type, u32 reason)
|
|
{
|
|
/* Disable the watchdog. */
|
|
writel_relaxed(WDT_KEY_VAL,
|
|
sunxi_wdt_base + WDT_MODE_REG);
|
|
|
|
/* Trigger soft reset. */
|
|
writel_relaxed(WDT_KEY_VAL | WDT_SOFT_RST_EN,
|
|
sunxi_wdt_base + WDT_SOFT_RST_REG);
|
|
}
|
|
|
|
static struct sbi_system_reset_device sunxi_wdt_reset = {
|
|
.name = "sunxi-wdt-reset",
|
|
.system_reset_check = sunxi_wdt_system_reset_check,
|
|
.system_reset = sunxi_wdt_system_reset,
|
|
};
|
|
|
|
static int sunxi_wdt_reset_init(const void *fdt, int nodeoff,
|
|
const struct fdt_match *match)
|
|
{
|
|
uint64_t reg_addr;
|
|
int rc;
|
|
|
|
rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, NULL);
|
|
if (rc < 0 || !reg_addr)
|
|
return SBI_ENODEV;
|
|
|
|
sunxi_wdt_base = (volatile char *)(unsigned long)reg_addr;
|
|
|
|
sbi_system_reset_add_device(&sunxi_wdt_reset);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct fdt_match sunxi_wdt_reset_match[] = {
|
|
{ .compatible = "allwinner,sun20i-d1-wdt-reset" },
|
|
{ },
|
|
};
|
|
|
|
const struct fdt_driver fdt_reset_sunxi_wdt = {
|
|
.match_table = sunxi_wdt_reset_match,
|
|
.init = sunxi_wdt_reset_init,
|
|
};
|