u-boot/drivers/watchdog/tangier_wdt.c
Simon Glass 8b85dfc675 dm: Avoid accessing seq directly
At present various drivers etc. access the device's 'seq' member directly.
This makes it harder to change the meaning of that member. Change access
to go through a function instead.

The drivers/i2c/lpc32xx_i2c.c file is left unchanged for now.

Signed-off-by: Simon Glass <sjg@chromium.org>
2020-12-18 20:32:21 -07:00

93 lines
2.2 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2017 Intel Corporation
*/
#include <common.h>
#include <dm.h>
#include <log.h>
#include <wdt.h>
#include <div64.h>
#include <asm/scu.h>
/* Hardware timeout in seconds */
#define WDT_PRETIMEOUT 15
#define WDT_TIMEOUT_MIN (1 + WDT_PRETIMEOUT)
#define WDT_TIMEOUT_MAX 170
/*
* Note, firmware chooses 90 seconds as a default timeout for watchdog on
* Intel Tangier SoC. It means that without handling it in the running code
* the reboot will happen.
*/
enum {
SCU_WATCHDOG_START = 0,
SCU_WATCHDOG_STOP = 1,
SCU_WATCHDOG_KEEPALIVE = 2,
SCU_WATCHDOG_SET_ACTION_ON_TIMEOUT = 3,
};
static int tangier_wdt_reset(struct udevice *dev)
{
scu_ipc_simple_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_KEEPALIVE);
return 0;
}
static int tangier_wdt_stop(struct udevice *dev)
{
return scu_ipc_simple_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_STOP);
}
static int tangier_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
{
u32 timeout_sec;
int in_size;
struct ipc_wd_start {
u32 pretimeout;
u32 timeout;
} ipc_wd_start;
/* Calculate timeout in seconds and restrict to min and max value */
do_div(timeout_ms, 1000);
timeout_sec = clamp_t(u32, timeout_ms, WDT_TIMEOUT_MIN, WDT_TIMEOUT_MAX);
/* Update values in the IPC request */
ipc_wd_start.pretimeout = timeout_sec - WDT_PRETIMEOUT;
ipc_wd_start.timeout = timeout_sec;
/*
* SCU expects the input size for watchdog IPC
* to be based on 4 bytes
*/
in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4);
scu_ipc_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_START,
(u32 *)&ipc_wd_start, in_size, NULL, 0);
return 0;
}
static const struct wdt_ops tangier_wdt_ops = {
.reset = tangier_wdt_reset,
.start = tangier_wdt_start,
.stop = tangier_wdt_stop,
};
static const struct udevice_id tangier_wdt_ids[] = {
{ .compatible = "intel,tangier-wdt" },
{ /* sentinel */ }
};
static int tangier_wdt_probe(struct udevice *dev)
{
debug("%s: Probing wdt%u\n", __func__, dev_seq(dev));
return 0;
}
U_BOOT_DRIVER(wdt_tangier) = {
.name = "wdt_tangier",
.id = UCLASS_WDT,
.of_match = tangier_wdt_ids,
.ops = &tangier_wdt_ops,
.probe = tangier_wdt_probe,
};