summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/imx8/scu_api.c20
-rw-r--r--drivers/net/fec_mxc.c14
-rw-r--r--drivers/watchdog/Kconfig7
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/siemens_pmic_wdt.c59
5 files changed, 94 insertions, 7 deletions
diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c
index 591d71b096a..a40c8badf9a 100644
--- a/drivers/misc/imx8/scu_api.c
+++ b/drivers/misc/imx8/scu_api.c
@@ -951,6 +951,26 @@ int sc_timer_set_wdog_window(sc_ipc_t ipc, sc_timer_wdog_time_t window)
return ret;
}
+int sc_timer_control_siemens_pmic_wdog(sc_ipc_t ipc, u8 cmd)
+{
+ struct udevice *dev = gd->arch.scu_dev;
+ struct sc_rpc_msg_s msg;
+ int size = sizeof(struct sc_rpc_msg_s);
+ int ret;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (u8)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (u8)TIMER_FUNC_CTRL_SIEMENS_PMIC_WDOG;
+ RPC_U8(&msg, 0U) = (u8)cmd;
+ RPC_SIZE(&msg) = 2U;
+
+ ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size);
+ if (ret)
+ printf("%s: res:%d\n", __func__, RPC_R8(&msg));
+
+ return ret;
+}
+
int sc_seco_authenticate(sc_ipc_t ipc, sc_seco_auth_cmd_t cmd,
sc_faddr_t addr)
{
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index d6d5cb52fdd..eca681b16d1 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -160,7 +160,7 @@ static int fec_get_clk_rate(void *udev, int idx)
}
}
-static void fec_mii_setspeed(struct ethernet_regs *eth)
+static void fec_mii_setspeed(struct udevice *dev, struct ethernet_regs *eth)
{
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
@@ -182,7 +182,7 @@ static void fec_mii_setspeed(struct ethernet_regs *eth)
u32 hold;
int ret;
- ret = fec_get_clk_rate(NULL, 0);
+ ret = fec_get_clk_rate(dev, 0);
if (ret < 0) {
printf("Can't find FEC0 clk rate: %d\n", ret);
return;
@@ -581,7 +581,7 @@ static int fecmxc_init(struct udevice *dev)
fec_reg_setup(fec);
if (fec->xcv_type != SEVENWIRE)
- fec_mii_setspeed(fec->bus->priv);
+ fec_mii_setspeed(dev, fec->bus->priv);
/* Set Opcode/Pause Duration Register */
writel(0x00010020, &fec->eth->op_pause); /* FIXME 0xffff0020; */
@@ -996,7 +996,7 @@ static void fec_free_descs(struct fec_priv *fec)
free(fec->tbd_base);
}
-struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
+struct mii_dev *fec_get_miibus(struct udevice *dev, ulong base_addr, int dev_id)
{
struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
struct mii_dev *bus;
@@ -1018,7 +1018,7 @@ struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
free(bus);
return NULL;
}
- fec_mii_setspeed(eth);
+ fec_mii_setspeed(dev, eth);
return bus;
}
@@ -1354,10 +1354,10 @@ static int fecmxc_probe(struct udevice *dev)
if (!bus) {
dm_mii_bus = false;
#ifdef CONFIG_FEC_MXC_MDIO_BASE
- bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE,
+ bus = fec_get_miibus(dev, (ulong)CONFIG_FEC_MXC_MDIO_BASE,
dev_seq(dev));
#else
- bus = fec_get_miibus((ulong)priv->eth, dev_seq(dev));
+ bus = fec_get_miibus(dev, (ulong)priv->eth, dev_seq(dev));
#endif
}
if (!bus) {
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 0e45f0a0922..b39b2546e5c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -351,6 +351,13 @@ config WDT_SBSA
In the single stage mode, when the timeout is reached, your system
will be reset by WS1. The first signal (WS0) is ignored.
+config WDT_SIEMENS_PMIC
+ bool "Enable PMIC Watchdog Timer support for Siemens platforms"
+ depends on ARCH_IMX8 && WDT
+ help
+ Select this to enable the PMIC watchdog driver controlled via
+ IMX8 SCU API found on Siemens platforms.
+
config WDT_SL28CPLD
bool "sl28cpld watchdog timer support"
depends on WDT && SL28CPLD
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 0b107c008f7..9b6b1a8e8ad 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_WDT_OCTEONTX) += octeontx_wdt.o
obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o
obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o
+obj-$(CONFIG_WDT_SIEMENS_PMIC) += siemens_pmic_wdt.o
obj-$(CONFIG_WDT_SL28CPLD) += sl28cpld-wdt.o
obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
obj-$(CONFIG_WDT_STARFIVE) += starfive_wdt.o
diff --git a/drivers/watchdog/siemens_pmic_wdt.c b/drivers/watchdog/siemens_pmic_wdt.c
new file mode 100644
index 00000000000..87e817bb5b2
--- /dev/null
+++ b/drivers/watchdog/siemens_pmic_wdt.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for a PMIC watchdog timer controlled via Siemens SCU firmware
+ * extensions. Only useful on some Siemens i.MX8-based platforms as
+ * special NXP SCFW is needed which provides the needed SCU API.
+ *
+ * Copyright (C) 2024 Siemens AG
+ */
+
+#include <dm.h>
+#include <wdt.h>
+#include <firmware/imx/sci/sci.h>
+
+/* watchdog commands */
+#define CMD_START_WDT 0x55
+#define CMD_STOP_WDT 0x45
+#define CMD_PING_WDT 0x35
+
+static int scu_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ /* start external watchdog via Timer API */
+ return sc_timer_control_siemens_pmic_wdog(-1, CMD_START_WDT);
+}
+
+static int scu_wdt_stop(struct udevice *dev)
+{
+ /* stop external watchdog via Timer API */
+ return sc_timer_control_siemens_pmic_wdog(-1, CMD_STOP_WDT);
+}
+
+static int scu_wdt_reset(struct udevice *dev)
+{
+ return sc_timer_control_siemens_pmic_wdog(-1, CMD_PING_WDT);
+}
+
+static int scu_wdt_probe(struct udevice *dev)
+{
+ debug("%s(dev=%p)\n", __func__, dev);
+ return 0;
+}
+
+static const struct wdt_ops scu_wdt_ops = {
+ .reset = scu_wdt_reset,
+ .start = scu_wdt_start,
+ .stop = scu_wdt_stop,
+};
+
+static const struct udevice_id scu_wdt_ids[] = {
+ { .compatible = "siemens,scu-wdt" },
+ { }
+};
+
+U_BOOT_DRIVER(scu_wdt) = {
+ .name = "scu_wdt",
+ .id = UCLASS_WDT,
+ .of_match = scu_wdt_ids,
+ .probe = scu_wdt_probe,
+ .ops = &scu_wdt_ops,
+};