watchdog: rti_wdt: Add support for loading firmware
To avoid the need of extra boot scripting on AM65x for loading a watchdog firmware, add the required rproc init and loading logic for the first R5F core to the watchdog start handler. In case the R5F cluster is in lock-step mode, also initialize the second core. The firmware itself is embedded into U-Boot binary to ease access to it and ensure it is properly hashed in case of secure boot. One possible firmware source is https://github.com/siemens/k3-rti-wdt. The board is responsible for providing the firmware as additional loadable via the U-Boot fit image. The driver will pick up its location from /fit-images/k3-rti-wdt-firmware then. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
This commit is contained in:
parent
a2db09e269
commit
f3efb1d106
@ -218,6 +218,26 @@ config WDT_K3_RTI
|
||||
Say Y here if you want to include support for the K3 watchdog
|
||||
timer (RTI module) available in the K3 generation of processors.
|
||||
|
||||
if WDT_K3_RTI
|
||||
|
||||
config WDT_K3_RTI_LOAD_FW
|
||||
bool "Load watchdog firmware"
|
||||
depends on REMOTEPROC
|
||||
help
|
||||
Automatically load the specified firmware image into the MCU R5F
|
||||
core 0. On the AM65x, this firmware is supposed to handle the expiry
|
||||
of the watchdog timer, typically by resetting the system.
|
||||
|
||||
config WDT_K3_RTI_FW_FILE
|
||||
string "Watchdog firmware image file"
|
||||
default "k3-rti-wdt.fw"
|
||||
depends on WDT_K3_RTI_LOAD_FW
|
||||
help
|
||||
Firmware image to be embedded into U-Boot and loaded on watchdog
|
||||
start.
|
||||
|
||||
endif
|
||||
|
||||
config WDT_SANDBOX
|
||||
bool "Enable Watchdog Timer support for Sandbox"
|
||||
depends on SANDBOX && WDT
|
||||
|
@ -11,9 +11,11 @@
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <power-domain.h>
|
||||
#include <wdt.h>
|
||||
#include <asm/io.h>
|
||||
#include <remoteproc.h>
|
||||
|
||||
/* Timer register set definition */
|
||||
#define RTIDWDCTRL 0x90
|
||||
@ -42,6 +44,88 @@ struct rti_wdt_priv {
|
||||
unsigned int clk_khz;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WDT_K3_RTI_LOAD_FW
|
||||
#define RTI_WDT_FIT_PATH "/fit-images/k3-rti-wdt-firmware"
|
||||
|
||||
static int rti_wdt_load_fw(struct udevice *dev)
|
||||
{
|
||||
struct udevice *rproc_dev;
|
||||
int primary_core, ret;
|
||||
u32 cluster_mode;
|
||||
ofnode node;
|
||||
u64 rti_wdt_fw;
|
||||
u32 rti_wdt_fw_size;
|
||||
|
||||
node = ofnode_path(RTI_WDT_FIT_PATH);
|
||||
if (!ofnode_valid(node))
|
||||
goto fit_error;
|
||||
|
||||
ret = ofnode_read_u64(node, "load", &rti_wdt_fw);
|
||||
if (ret)
|
||||
goto fit_error;
|
||||
ret = ofnode_read_u32(node, "size", &rti_wdt_fw_size);
|
||||
if (ret)
|
||||
goto fit_error;
|
||||
|
||||
node = ofnode_by_compatible(ofnode_null(), "ti,am654-r5fss");
|
||||
if (!ofnode_valid(node))
|
||||
goto dt_error;
|
||||
|
||||
ret = ofnode_read_u32(node, "ti,cluster-mode", &cluster_mode);
|
||||
if (ret)
|
||||
cluster_mode = 1;
|
||||
|
||||
node = ofnode_by_compatible(node, "ti,am654-r5f");
|
||||
if (!ofnode_valid(node))
|
||||
goto dt_error;
|
||||
|
||||
ret = uclass_get_device_by_ofnode(UCLASS_REMOTEPROC, node, &rproc_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
primary_core = dev_seq(rproc_dev);
|
||||
|
||||
ret = rproc_dev_init(primary_core);
|
||||
if (ret)
|
||||
goto fw_error;
|
||||
|
||||
if (cluster_mode == 1) {
|
||||
ret = rproc_dev_init(primary_core + 1);
|
||||
if (ret)
|
||||
goto fw_error;
|
||||
}
|
||||
|
||||
ret = rproc_load(primary_core, (ulong)rti_wdt_fw,
|
||||
rti_wdt_fw_size);
|
||||
if (ret)
|
||||
goto fw_error;
|
||||
|
||||
ret = rproc_start(primary_core);
|
||||
if (ret)
|
||||
goto fw_error;
|
||||
|
||||
return 0;
|
||||
|
||||
fit_error:
|
||||
dev_err(dev, "No loadable firmware found under %s\n", RTI_WDT_FIT_PATH);
|
||||
return -ENOENT;
|
||||
|
||||
dt_error:
|
||||
dev_err(dev, "No compatible firmware target processor found\n");
|
||||
return -ENODEV;
|
||||
|
||||
fw_error:
|
||||
dev_err(dev, "Failed to load watchdog firmware into remote processor %d\n",
|
||||
primary_core);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline int rti_wdt_load_fw(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rti_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
{
|
||||
struct rti_wdt_priv *priv = dev_get_priv(dev);
|
||||
@ -51,6 +135,10 @@ static int rti_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
if (readl(priv->regs + RTIDWDCTRL) == WDENABLE_KEY)
|
||||
return -EBUSY;
|
||||
|
||||
ret = rti_wdt_load_fw(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
timer_margin = timeout_ms * priv->clk_khz / 1000;
|
||||
timer_margin >>= WDT_PRELOAD_SHIFT;
|
||||
if (timer_margin > WDT_PRELOAD_MAX)
|
||||
|
Loading…
Reference in New Issue
Block a user