Intel® Quark™ Microcontroller Software Interface 1.4.0 Intel® Quark™ Microcontroller BSP

- Main Page
- Modules
- Data Structures
- Files

- File List

qm_wdt.c
1 /*
2 * {% copyright %}
3 */
4
5 #include "qm_wdt.h"
6 #include "clk.h"
7 #include "soc_watch.h"
8
9 static void (*callback[QM_WDT_NUM])(void *data);
10 static void *callback_data[QM_WDT_NUM];
11
12 #ifndef UNIT_TEST
13 qm_wdt_reg_t *qm_wdt[QM_WDT_NUM] = {((qm_wdt_reg_t *)QM_WDT_0_BASE),
14 #if (NUM_WDT_CONTROLLERS > 1)
15 ((qm_wdt_reg_t *)QM_WDT_1_BASE)
16 #endif /* NUM_WDT_CONTROLLERS >1 */
17 };
18 #endif /* UNIT_TEST */
19
20 QM_ISR_DECLARE(qm_wdt_0_isr)
21 {
22 if (callback[QM_WDT_0]) {
23 callback[QM_WDT_0](callback_data[QM_WDT_0]);
24 }
25
26 /* Clear the interrupt by reading. */
27 QM_WDT[QM_WDT_0]->wdt_eoi;
28 QM_ISR_EOI(QM_IRQ_WDT_0_INT_VECTOR);
29 }
30
31 #if (NUM_WDT_CONTROLLERS > 1)
32 QM_ISR_DECLARE(qm_wdt_1_isr)
33 {
34 if (NULL != callback[QM_WDT_1]) {
35 (callback[QM_WDT_1])(callback_data[QM_WDT_1]);
36 }
37
38 /* Clear the interrupt by reading. */
39 QM_WDT[QM_WDT_1]->wdt_eoi;
40 QM_ISR_EOI(QM_IRQ_WDT_1_INT_VECTOR);
41 }
42 #endif /* (NUM_WDT_CONTROLLERS > 1) */
43
44 int qm_wdt_start(const qm_wdt_t wdt)
45 {
46 QM_CHECK(wdt < QM_WDT_NUM, -EINVAL);
47
48 QM_WDT[wdt]->wdt_cr |= QM_WDT_CR_WDT_ENABLE;
49
50 #if (HAS_WDT_CLOCK_ENABLE)
51 clk_periph_enable(CLK_PERIPH_WDT_REGISTER | CLK_PERIPH_CLK);
52 QM_SCSS_PERIPHERAL->periph_cfg0 |= BIT(1);
53 #endif /* HAS_WDT_CLOCK_ENABLE */
54
55 qm_wdt_reload(wdt);
56
57 return 0;
58 }
59
60 int qm_wdt_set_config(const qm_wdt_t wdt, const qm_wdt_config_t *const cfg)
61 {
62 QM_CHECK(wdt < QM_WDT_NUM, -EINVAL);
63 QM_CHECK(cfg != NULL, -EINVAL);
64 QM_CHECK(cfg->timeout <= QM_WDT_TORR_TOP_MASK, -EINVAL);
65
66 qm_wdt_reload(wdt);
67
68 if (cfg->mode == QM_WDT_MODE_INTERRUPT_RESET) {
69 callback[wdt] = cfg->callback;
70 callback_data[wdt] = cfg->callback_data;
71 }
72
73 QM_WDT[wdt]->wdt_cr &= ~QM_WDT_CR_RMOD;
74 QM_WDT[wdt]->wdt_cr |= cfg->mode << QM_WDT_CR_RMOD_OFFSET;
75
76 /* If the SoC has the C2 Pause enable bit for LMT WDT. */
77 #if (HAS_WDT_PAUSE)
78 /* Make sure WDT0 is the one requested to be configured. */
79 QM_CHECK(QM_WDT_0 == wdt, -EINVAL);
80 (QM_SCU_AON_CRU_BLOCK)->wdt0_tclk_en &= ~C2_WDT_PAUSE_EN_MASK;
81 (QM_SCU_AON_CRU_BLOCK)->wdt0_tclk_en |= cfg->pause_en
82 << C2_WDT_PAUSE_EN_SHIFT;
83 #endif /* HAS_WDT_PAUSE */
84
85 /*
86 * Timeout range register. Select the timeout from the pre-defined
87 * tables. These tables can be found in the SoC databook or register
88 * file.
89 */
90 QM_WDT[wdt]->wdt_torr = cfg->timeout;
91
92 /* kick the WDT to load the Timeout Period(TOP) value */
93 qm_wdt_reload(wdt);
94
95 return 0;
96 }
97
98 int qm_wdt_reload(const qm_wdt_t wdt)
99 {
100 QM_CHECK(wdt < QM_WDT_NUM, -EINVAL);
101
102 /*
103 * This register is used to restart the WDT counter. As a safety feature
104 * to prevent accidental restarts the value 0x76 must be written.
105 * A restart also clears the WDT interrupt.
106 */
107 QM_WDT[wdt]->wdt_crr = QM_WDT_RELOAD_VALUE;
108
109 return 0;
110 }
111
112 #if (ENABLE_RESTORE_CONTEXT)
113 int qm_wdt_save_context(const qm_wdt_t wdt, qm_wdt_context_t *const ctx)
114 {
115 QM_CHECK(wdt < QM_WDT_NUM, -EINVAL);
116 QM_CHECK(ctx != NULL, -EINVAL);
117
118 ctx->wdt_torr = QM_WDT[wdt]->wdt_torr;
119 ctx->wdt_cr = QM_WDT[wdt]->wdt_cr;
120
121 return 0;
122 }
123
124 int qm_wdt_restore_context(const qm_wdt_t wdt,
125 const qm_wdt_context_t *const ctx)
126 {
127 QM_CHECK(wdt < QM_WDT_NUM, -EINVAL);
128 QM_CHECK(ctx != NULL, -EINVAL);
129
130 /*
131 * TOP_INIT field has to be written before Watchdog Timer is enabled.
132 */
133 QM_WDT[wdt]->wdt_torr = ctx->wdt_torr;
134 QM_WDT[wdt]->wdt_cr = ctx->wdt_cr;
135
136 /*
137 * Reload the wdt value to avoid interrupts to fire on wake up.
138 */
139 QM_WDT[wdt]->wdt_crr = QM_WDT_RELOAD_VALUE;
140
141 return 0;
142 }
143 #else
144 int qm_wdt_save_context(const qm_wdt_t wdt, qm_wdt_context_t *const ctx)
145 {
146 (void)wdt;
147 (void)ctx;
148
149 return 0;
150 }
151
152 int qm_wdt_restore_context(const qm_wdt_t wdt,
153 const qm_wdt_context_t *const ctx)
154 {
155 (void)wdt;
156 (void)ctx;
157
158 return 0;
159 }
160 #endif /* ENABLE_RESTORE_CONTEXT */
QM_WDT_MODE_INTERRUPT_RESET
Watchdog Interrupt Reset Response Mode.
Definition: qm_wdt.h:33
qm_wdt_config_t::mode
qm_wdt_mode_t mode
Watchdog response mode.
Definition: qm_wdt.h:48
qm_wdt_config_t::pause_en
bool pause_en
Pause enable in LMT power state C2 and C2 Plus.
Definition: qm_wdt.h:60
qm_wdt_config_t
QM WDT configuration type.
Definition: qm_wdt.h:39
clk_periph_enable
int clk_periph_enable(const clk_periph_t clocks)
Enable clocks for peripherals / registers.
Definition: clk.c:319
qm_wdt_config_t::timeout
uint32_t timeout
Index for the WDT timeout table.
Definition: qm_wdt.h:47
qm_wdt_config_t::callback
void(* callback)(void *data)
User callback.
Definition: qm_wdt.h:68
CLK_PERIPH_CLK
Peripheral Clock Enable.
Definition: qm_soc_regs.h:1370
qm_wdt_restore_context
int qm_wdt_restore_context(const qm_wdt_t wdt, const qm_wdt_context_t *const ctx)
Restore watchdog context.
Definition: qm_wdt.c:124
CLK_PERIPH_WDT_REGISTER
Watchdog Clock Enable.
Definition: qm_soc_regs.h:1376
qm_wdt_reload
int qm_wdt_reload(const qm_wdt_t wdt)
Reload the WDT counter.
Definition: qm_wdt.c:98
qm_wdt_save_context
int qm_wdt_save_context(const qm_wdt_t wdt, qm_wdt_context_t *const ctx)
Save watchdog context.
Definition: qm_wdt.c:113
QM_ISR_DECLARE
QM_ISR_DECLARE(qm_wdt_0_isr)
ISR for WDT 0 interrupt.
Definition: qm_wdt.c:20
qm_wdt_set_config
int qm_wdt_set_config(const qm_wdt_t wdt, const qm_wdt_config_t *const cfg)
Set configuration of WDT module.
Definition: qm_wdt.c:60
qm_wdt_t
qm_wdt_t
Number of WDT controllers.
Definition: qm_soc_regs.h:467
qm_wdt_start
int qm_wdt_start(const qm_wdt_t wdt)
Start WDT.
Definition: qm_wdt.c:44
qm_wdt_reg_t
Watchdog timer register map.
Definition: qm_soc_regs.h:470
qm_wdt_config_t::callback_data
void * callback_data
Callback user data.
Definition: qm_wdt.h:69