drivers: watchdog: litex: add litex watchdog
this adds a driver for the litex watchdog. Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
parent
c3752bf442
commit
f775ab4975
8 changed files with 297 additions and 0 deletions
|
@ -17,6 +17,10 @@
|
|||
zephyr,sram = &ram0;
|
||||
};
|
||||
|
||||
aliases {
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
|
||||
ram0: memory@40000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x40000000 0x10000000>;
|
||||
|
@ -36,6 +40,10 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
&wdt0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -12,8 +12,12 @@ toolchain:
|
|||
- zephyr
|
||||
ram: 262144
|
||||
supported:
|
||||
- gpio
|
||||
- uart
|
||||
- spi
|
||||
- i2s
|
||||
- i2c
|
||||
- watchdog
|
||||
testing:
|
||||
ignore_tags:
|
||||
- bluetooth
|
||||
|
|
|
@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_ESP32 wdt_esp32.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_WDT_XT_ESP32 xt_wdt_esp32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_GECKO wdt_gecko.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_ITE_IT8XXX2 wdt_ite_it8xxx2.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_LITEX wdt_litex.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_MAX32 wdt_max32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_IMX_WDOG wdt_mcux_imx_wdog.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG wdt_mcux_wdog.c)
|
||||
|
|
|
@ -132,4 +132,6 @@ source "drivers/watchdog/Kconfig.numaker"
|
|||
|
||||
source "drivers/watchdog/Kconfig.ene"
|
||||
|
||||
source "drivers/watchdog/Kconfig.litex"
|
||||
|
||||
endif # WATCHDOG
|
||||
|
|
12
drivers/watchdog/Kconfig.litex
Normal file
12
drivers/watchdog/Kconfig.litex
Normal file
|
@ -0,0 +1,12 @@
|
|||
# LiteX WDT configuration
|
||||
|
||||
# Copyright (C) 2024 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config WDT_LITEX
|
||||
bool "LiteX Watchdog (WDT) Driver"
|
||||
default y
|
||||
depends on DT_HAS_LITEX_WATCHDOG_ENABLED
|
||||
select HAS_WDT_DISABLE_AT_BOOT
|
||||
help
|
||||
Enable WDT driver for LiteX.
|
238
drivers/watchdog/wdt_litex.c
Normal file
238
drivers/watchdog/wdt_litex.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Vogl Electronic GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT litex_watchdog
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/watchdog.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/sys_clock.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(wdt_litex, CONFIG_WDT_LOG_LEVEL);
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
struct wdt_litex_data {
|
||||
wdt_callback_t callback;
|
||||
uint32_t timeout;
|
||||
bool reset_soc_mode;
|
||||
bool pause_halted;
|
||||
};
|
||||
|
||||
struct wdt_litex_config {
|
||||
uint32_t control_addr;
|
||||
uint32_t cycles_addr;
|
||||
uint32_t cycles_size;
|
||||
uint32_t remaining_addr;
|
||||
uint32_t ev_status_addr;
|
||||
uint32_t ev_pending_addr;
|
||||
uint32_t ev_enable_addr;
|
||||
void (*irq_cfg_func)(void);
|
||||
};
|
||||
|
||||
#define CONTROL_FEED_BIT BIT(0)
|
||||
#define CONTROL_ENABLE_BIT BIT(8)
|
||||
#define CONTROL_RESET_BIT BIT(16)
|
||||
#define CONTROL_PAUSE_HALTED_BIT BIT(24)
|
||||
|
||||
static bool wdt_litex_is_enabled(const struct device *dev)
|
||||
{
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
|
||||
return litex_read8(config->control_addr) & BIT(0);
|
||||
}
|
||||
|
||||
static void wdt_litex_irq_enable(const struct device *dev)
|
||||
{
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
struct wdt_litex_data *data = dev->data;
|
||||
|
||||
if (!data->callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
litex_write8(BIT(0), config->ev_pending_addr);
|
||||
|
||||
litex_write8(BIT(0), config->ev_enable_addr);
|
||||
}
|
||||
|
||||
static void wdt_litex_enable(const struct device *dev)
|
||||
{
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
struct wdt_litex_data *data = dev->data;
|
||||
uint32_t control;
|
||||
|
||||
if (config->cycles_size <= 4) {
|
||||
litex_write32(k_ms_to_cyc_floor32(data->timeout), config->cycles_addr);
|
||||
} else {
|
||||
litex_write64(k_ms_to_cyc_floor64(data->timeout), config->cycles_addr);
|
||||
}
|
||||
|
||||
control = CONTROL_FEED_BIT | CONTROL_ENABLE_BIT;
|
||||
|
||||
if (data->reset_soc_mode) {
|
||||
control |= CONTROL_RESET_BIT;
|
||||
}
|
||||
if (data->pause_halted) {
|
||||
control |= CONTROL_PAUSE_HALTED_BIT;
|
||||
}
|
||||
|
||||
litex_write32(control, config->control_addr);
|
||||
|
||||
wdt_litex_irq_enable(dev);
|
||||
}
|
||||
|
||||
static int wdt_litex_disable(const struct device *dev)
|
||||
{
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
|
||||
litex_write8(0, config->ev_enable_addr);
|
||||
|
||||
if (!wdt_litex_is_enabled(dev)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
litex_write16(CONTROL_ENABLE_BIT, config->control_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdt_litex_feed(const struct device *dev, int channel_id)
|
||||
{
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
|
||||
if (channel_id != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
litex_write8(CONTROL_FEED_BIT, config->control_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdt_litex_setup(const struct device *dev, uint8_t options)
|
||||
{
|
||||
struct wdt_litex_data *data = dev->data;
|
||||
|
||||
data->pause_halted = !!(options & WDT_OPT_PAUSE_HALTED_BY_DBG);
|
||||
|
||||
if (options & WDT_OPT_PAUSE_IN_SLEEP) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (wdt_litex_is_enabled(dev)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
wdt_litex_enable(dev);
|
||||
wdt_litex_feed(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdt_litex_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
|
||||
{
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
struct wdt_litex_data *data = dev->data;
|
||||
|
||||
if (cfg->window.min != 0U || cfg->window.max == 0U) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cfg->window.max > (config->cycles_size <= 4 ? k_cyc_to_ms_floor32(UINT32_MAX)
|
||||
: k_cyc_to_ms_floor64(UINT64_MAX))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wdt_litex_is_enabled(dev)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
data->timeout = cfg->window.max;
|
||||
data->callback = cfg->callback;
|
||||
|
||||
/* Set mode of watchdog and callback */
|
||||
switch (cfg->flags) {
|
||||
case WDT_FLAG_RESET_SOC:
|
||||
LOG_DBG("Configuring reset SOC mode");
|
||||
data->reset_soc_mode = true;
|
||||
break;
|
||||
|
||||
case WDT_FLAG_RESET_NONE:
|
||||
LOG_DBG("Configuring non-reset mode");
|
||||
data->reset_soc_mode = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERR("Unsupported watchdog config flag");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wdt_litex_isr(void *arg)
|
||||
{
|
||||
const struct device *dev = (const struct device *)arg;
|
||||
const struct wdt_litex_config *config = dev->config;
|
||||
struct wdt_litex_data *data = dev->data;
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
if (data->callback) {
|
||||
data->callback(dev, 0);
|
||||
}
|
||||
|
||||
litex_write8(BIT(0), config->ev_pending_addr);
|
||||
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
static int wdt_litex_init(const struct device *dev)
|
||||
{
|
||||
const struct wdt_litex_config *const config = dev->config;
|
||||
|
||||
config->irq_cfg_func();
|
||||
|
||||
#ifndef CONFIG_WDT_DISABLE_AT_BOOT
|
||||
wdt_litex_enable(dev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct wdt_driver_api wdt_api = {
|
||||
.setup = wdt_litex_setup,
|
||||
.disable = wdt_litex_disable,
|
||||
.install_timeout = wdt_litex_install_timeout,
|
||||
.feed = wdt_litex_feed,
|
||||
};
|
||||
|
||||
#define LITEX_WDT_INIT(n) \
|
||||
static void wdt_litex_cfg_func_##n(void); \
|
||||
\
|
||||
static struct wdt_litex_data wdt_litex_data##n; \
|
||||
static struct wdt_litex_config wdt_litex_config##n = { \
|
||||
.control_addr = DT_INST_REG_ADDR_BY_NAME(n, control), \
|
||||
.cycles_addr = DT_INST_REG_ADDR_BY_NAME(n, cycles), \
|
||||
.cycles_size = DT_INST_REG_SIZE_BY_NAME(n, cycles), \
|
||||
.remaining_addr = DT_INST_REG_ADDR_BY_NAME(n, remaining), \
|
||||
.ev_status_addr = DT_INST_REG_ADDR_BY_NAME(n, ev_status), \
|
||||
.ev_pending_addr = DT_INST_REG_ADDR_BY_NAME(n, ev_pending), \
|
||||
.ev_enable_addr = DT_INST_REG_ADDR_BY_NAME(n, ev_enable), \
|
||||
.irq_cfg_func = wdt_litex_cfg_func_##n, \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, wdt_litex_init, NULL, &wdt_litex_data##n, &wdt_litex_config##n, \
|
||||
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_api) \
|
||||
\
|
||||
static void wdt_litex_cfg_func_##n(void) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), wdt_litex_isr, \
|
||||
DEVICE_DT_INST_GET(n), 0); \
|
||||
irq_enable(DT_INST_IRQN(n)); \
|
||||
}
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(LITEX_WDT_INIT)
|
15
dts/bindings/watchdog/litex,watchdog.yaml
Normal file
15
dts/bindings/watchdog/litex,watchdog.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright (c) 2024 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: LiteX watchdog.
|
||||
|
||||
compatible: "litex,watchdog"
|
||||
|
||||
include: base.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
|
@ -144,6 +144,23 @@
|
|||
"uptime_cycles";
|
||||
status = "disabled";
|
||||
};
|
||||
wdt0: watchdog@e000d000 {
|
||||
compatible = "litex,watchdog";
|
||||
interrupt-parent = <&intc0>;
|
||||
reg = <0xe000d000 0x4>,
|
||||
<0xe000d004 0x4>,
|
||||
<0xe000d008 0x4>,
|
||||
<0xe000d00c 0x4>,
|
||||
<0xe000d010 0x4>,
|
||||
<0xe000d014 0x4>;
|
||||
reg-names = "control",
|
||||
"cycles",
|
||||
"remaining",
|
||||
"ev_status",
|
||||
"ev_pending",
|
||||
"ev_enable";
|
||||
interrupts = <8 15>;
|
||||
};
|
||||
mdio0: mdio@e0008000 {
|
||||
compatible = "litex,liteeth-mdio";
|
||||
reg = <0xe0008000 0x4>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue