-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
wdt_ifx_cat1.c
143 lines (112 loc) · 3.3 KB
/
wdt_ifx_cat1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* Copyright 2023 Cypress Semiconductor Corporation (an Infineon company) or
* an affiliate of Cypress Semiconductor Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT infineon_cat1_watchdog
#include "cyhal_wdt.h"
#include <zephyr/devicetree.h>
#include <zephyr/drivers/watchdog.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(wdt_infineon_cat1, CONFIG_WDT_LOG_LEVEL);
#define IFX_CAT1_WDT_IS_IRQ_EN DT_NODE_HAS_PROP(DT_DRV_INST(0), interrupts)
struct ifx_cat1_wdt_data {
cyhal_wdt_t obj;
#ifdef IFX_CAT1_WDT_IS_IRQ_EN
wdt_callback_t callback;
#endif /* IFX_CAT1_WDT_IS_IRQ_EN */
uint32_t timeout;
bool timeout_installed;
};
struct ifx_cat1_wdt_data wdt_data;
#ifdef IFX_CAT1_WDT_IS_IRQ_EN
static void ifx_cat1_wdt_isr_handler(const struct device *dev)
{
struct ifx_cat1_wdt_data *dev_data = dev->data;
if (dev_data->callback) {
dev_data->callback(dev, 0);
}
Cy_WDT_MaskInterrupt();
}
#endif /* IFX_CAT1_WDT_IS_IRQ_EN */
static int ifx_cat1_wdt_setup(const struct device *dev, uint8_t options)
{
cy_rslt_t result;
struct ifx_cat1_wdt_data *dev_data = dev->data;
/* Initialize the WDT */
result = cyhal_wdt_init(&dev_data->obj, dev_data->timeout);
if (result != CY_RSLT_SUCCESS) {
LOG_ERR("Initialization failure : 0x%x", result);
return -ENOMSG;
}
#ifdef IFX_CAT1_WDT_IS_IRQ_EN
if (dev_data->callback) {
Cy_WDT_UnmaskInterrupt();
irq_enable(DT_INST_IRQN(0));
}
#endif /* IFX_CAT1_WDT_IS_IRQ_EN */
return 0;
}
static int ifx_cat1_wdt_disable(const struct device *dev)
{
struct ifx_cat1_wdt_data *dev_data = dev->data;
#ifdef IFX_CAT1_WDT_IS_IRQ_EN
Cy_WDT_MaskInterrupt();
irq_disable(DT_INST_IRQN(0));
#endif /* IFX_CAT1_WDT_IS_IRQ_EN */
cyhal_wdt_free(&dev_data->obj);
return 0;
}
static int ifx_cat1_wdt_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
{
struct ifx_cat1_wdt_data *dev_data = dev->data;
if (dev_data->timeout_installed) {
LOG_ERR("No more timeouts can be installed");
return -ENOMEM;
}
if (cfg->flags) {
LOG_WRN("Watchdog behavior is not configurable.");
}
if (cfg->callback) {
#ifndef IFX_CAT1_WDT_IS_IRQ_EN
LOG_WRN("Interrupt is not configured, can't set a callback.");
#else
dev_data->callback = cfg->callback;
#endif /* IFX_CAT1_WDT_IS_IRQ_EN */
}
/* window watchdog not supported */
if (cfg->window.min != 0U || cfg->window.max == 0U) {
return -EINVAL;
}
dev_data->timeout = cfg->window.max;
return 0;
}
static int ifx_cat1_wdt_feed(const struct device *dev, int channel_id)
{
struct ifx_cat1_wdt_data *data = dev->data;
/* Only channel 0 is supported */
if (channel_id) {
return -EINVAL;
}
cyhal_wdt_kick(&data->obj);
return 0;
}
static int ifx_cat1_wdt_init(const struct device *dev)
{
#ifdef IFX_CAT1_WDT_IS_IRQ_EN
/* Connect WDT interrupt to ISR */
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), ifx_cat1_wdt_isr_handler,
DEVICE_DT_INST_GET(0), 0);
#endif /* IFX_CAT1_WDT_IS_IRQ_EN */
return 0;
}
static const struct wdt_driver_api ifx_cat1_wdt_api = {
.setup = ifx_cat1_wdt_setup,
.disable = ifx_cat1_wdt_disable,
.install_timeout = ifx_cat1_wdt_install_timeout,
.feed = ifx_cat1_wdt_feed,
};
DEVICE_DT_INST_DEFINE(0, ifx_cat1_wdt_init, NULL, &wdt_data, NULL, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &ifx_cat1_wdt_api);