• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #include "hpm_wdg_drv.h"
8 
9 #define TICKS_1K (1024UL)
10 #define TICKS_1M (1024UL * TICKS_1K)
11 #define TICKS_1G (1024UL * TICKS_1M)
12 #define ONE_SECOND_TICKS_IN_NS (1000UL * 1000UL * 1000UL)
13 
14 typedef struct {
15     uint32_t top;
16     reset_interval_t interval;
17 } reset_interval_map_t;
18 
19 typedef struct {
20     uint32_t top;
21     interrupt_interval_t interval;
22 } interrupt_interval_map_t;
23 
24 static const reset_interval_map_t k_reset_interval_map[reset_interval_out_of_range + 1U] = {
25     {128UL, reset_interval_clock_period_mult_128},
26     {256UL, reset_interval_clock_period_mult_256},
27     {512UL, reset_interval_clock_period_mult_512},
28     {1UL * TICKS_1K, reset_interval_clock_period_mult_1k},
29     {2UL * TICKS_1K, reset_interval_clock_period_mult_2k},
30     {4UL * TICKS_1K, reset_interval_clock_period_mult_4k},
31     {8UL * TICKS_1K, reset_interval_clock_period_mult_8k},
32     {16UL * TICKS_1K, reset_interval_clock_period_mult_16k},
33     {0xFFFFFFFFUL, reset_interval_out_of_range},
34 };
35 
36 static const interrupt_interval_map_t k_interrupt_interval_map[interrupt_interval_out_of_range + 1U] = {
37     {64UL, interrupt_interval_clock_period_multi_64},
38     {256UL, interrupt_interval_clock_period_multi_256},
39     {1UL * TICKS_1K, interrupt_interval_clock_period_multi_1k},
40     {2UL * TICKS_1K, interrupt_interval_clock_period_multi_2k},
41     {4UL * TICKS_1K, interrupt_interval_clock_period_multi_4k},
42     {8UL * TICKS_1K, interrupt_interval_clock_period_multi_8k},
43     {16UL * TICKS_1K, interrupt_interval_clock_period_multi_16k},
44     {32UL * TICKS_1K, interrupt_interval_clock_period_multi_32k},
45     {128UL * TICKS_1K, interrupt_interval_clock_period_multi_128k},
46     {512UL * TICKS_1K, interrupt_interval_clock_period_multi_512k},
47     {2UL * TICKS_1M, interrupt_interval_clock_period_multi_2m},
48     {8UL * TICKS_1M, interrupt_interval_clock_period_multi_8m},
49     {32UL * TICKS_1M, interrupt_interval_clock_period_multi_32m},
50     {128UL * TICKS_1M, interrupt_interval_clock_period_multi_128m},
51     {512UL * TICKS_1M, interrupt_interval_clock_period_multi_512m},
52     {2UL * TICKS_1G, interrupt_interval_clock_period_multi_2g},
53     {0xFFFFFFFFUL, interrupt_interval_out_of_range}
54 
55 };
56 
57 /* See hpm_wdg_drv.h for more details */
wdg_init(WDG_Type * base,wdg_control_t * wdg_ctrl)58 hpm_stat_t wdg_init(WDG_Type *base, wdg_control_t *wdg_ctrl)
59 {
60     hpm_stat_t status = status_invalid_argument;
61     do {
62         HPM_BREAK_IF((base == NULL) || (wdg_ctrl == NULL));
63 
64         HPM_BREAK_IF((wdg_ctrl->reset_interval > reset_interval_max) ||
65             (wdg_ctrl->interrupt_interval > interrupt_interval_max) ||
66             (wdg_ctrl->clksrc > wdg_clksrc_pclk));
67 
68         uint32_t rst_time = (uint32_t) wdg_ctrl->reset_interval;
69         uint32_t int_time = (uint32_t) wdg_ctrl->interrupt_interval;
70         uint32_t reset_en = wdg_ctrl->reset_enable ? 1UL : 0UL;
71         uint32_t int_en = wdg_ctrl->interrupt_enable ? 1UL : 0UL;
72         uint32_t clk_src = (wdg_ctrl->clksrc == wdg_clksrc_pclk) ? 1UL : 0UL;
73         uint32_t wdg_en = wdg_ctrl->wdg_enable ? 1UL : 0UL;
74 
75         uint32_t wdg_ctrl = WDG_CTRL_RSTTIME_SET(rst_time)
76             | WDG_CTRL_INTTIME_SET(int_time)
77             | WDG_CTRL_CLKSEL_SET(clk_src)
78             | WDG_CTRL_RSTEN_SET(reset_en)
79             | WDG_CTRL_INTEN_SET(int_en)
80             | WDG_CTRL_EN_SET(wdg_en);
81 
82         wdg_write_enable(base);
83 
84         base->CTRL = wdg_ctrl;
85 
86         status = status_success;
87 
88     } while (false);
89 
90     return status;
91 }
92 
93 /* See hpm_wdg_drv.h for more details */
wdg_convert_reset_interval_from_us(const uint32_t src_freq,const uint32_t reset_us)94 reset_interval_t wdg_convert_reset_interval_from_us(const uint32_t src_freq, const uint32_t reset_us)
95 {
96     reset_interval_t reset_interval = reset_interval_out_of_range;
97 
98     uint32_t src_clk_one_tick_in_ns = ONE_SECOND_TICKS_IN_NS / src_freq;
99     if (src_clk_one_tick_in_ns < 1U) {
100         src_clk_one_tick_in_ns = 1U;
101     }
102 
103     uint32_t reset_interval_ticks = (reset_us * 1000UL) / src_clk_one_tick_in_ns;
104 
105     for (uint32_t i = 0; i < ARRAY_SIZE(k_reset_interval_map); i++) {
106         if (reset_interval_ticks <= k_reset_interval_map[i].top) {
107             reset_interval = k_reset_interval_map[i].interval;
108             break;
109         }
110     }
111 
112     return reset_interval;
113 }
114 
115 /* See hpm_wdg_drv.h for more details */
wdg_convert_interrupt_interval_from_us(const uint32_t src_freq,uint32_t interval_us)116 interrupt_interval_t wdg_convert_interrupt_interval_from_us(const uint32_t src_freq, uint32_t interval_us)
117 {
118     interrupt_interval_t interrupt_interval = interrupt_interval_out_of_range;
119 
120     uint32_t src_clk_one_tick_in_ns = ONE_SECOND_TICKS_IN_NS / src_freq;
121     if (src_clk_one_tick_in_ns < 1U) {
122         src_clk_one_tick_in_ns = 1U;
123     }
124 
125     uint32_t interrupt_interval_ticks = ((uint64_t) interval_us * 1000L) / src_clk_one_tick_in_ns;
126     for (uint32_t i = 0; i < ARRAY_SIZE(k_interrupt_interval_map); i++) {
127         if (interrupt_interval_ticks <= k_interrupt_interval_map[i].top) {
128             interrupt_interval = k_interrupt_interval_map[i].interval;
129             break;
130         }
131     }
132 
133     return interrupt_interval;
134 }
135 
wdg_convert_interrupt_interval_to_us(const uint32_t src_freq,interrupt_interval_t interval)136 uint64_t wdg_convert_interrupt_interval_to_us(const uint32_t src_freq, interrupt_interval_t interval)
137 {
138     uint64_t time_in_us = 0;
139     if ((src_freq != 0) && (interval < interrupt_interval_out_of_range)) {
140         uint32_t interrupt_interval_in_reg = (uint32_t) interval;
141 
142         double tick_in_ns = 1.0 * ONE_SECOND_TICKS_IN_NS / src_freq;
143         uint64_t
144             total_interval_in_ns = (uint64_t)(tick_in_ns * k_interrupt_interval_map[interrupt_interval_in_reg].top);
145 
146         time_in_us = total_interval_in_ns / 1000UL;
147     }
148 
149     return time_in_us;
150 }
151 
wdg_convert_reset_interval_to_us(const uint32_t src_freq,reset_interval_t interval)152 uint32_t wdg_convert_reset_interval_to_us(const uint32_t src_freq, reset_interval_t interval)
153 {
154     uint32_t time_in_us = 0;
155     if ((src_freq != 0) && (interval < reset_interval_out_of_range)) {
156         uint32_t reset_interval_in_reg = (uint32_t) interval;
157         double tick_in_ns = 1.0 * ONE_SECOND_TICKS_IN_NS / src_freq;
158         uint64_t total_interval_in_ns = (uint64_t)(tick_in_ns * k_reset_interval_map[reset_interval_in_reg].top);
159 
160         time_in_us = (uint32_t)(total_interval_in_ns / 1000UL);
161     }
162 
163     return time_in_us;
164 }
165 
wdg_get_interrupt_interval_in_us(WDG_Type * base,const uint32_t src_freq)166 uint64_t wdg_get_interrupt_interval_in_us(WDG_Type *base, const uint32_t src_freq)
167 {
168     uint64_t time_in_us = 0;
169     if ((base != NULL) && (src_freq != 0)) {
170         interrupt_interval_t interval = (interrupt_interval_t) WDG_CTRL_INTTIME_GET(base->CTRL);
171 
172         time_in_us = wdg_convert_interrupt_interval_to_us(src_freq, interval);
173     }
174 
175     return time_in_us;
176 }
177 
wdg_get_total_reset_interval_in_us(WDG_Type * base,const uint32_t src_freq)178 uint64_t wdg_get_total_reset_interval_in_us(WDG_Type *base, const uint32_t src_freq)
179 {
180     uint64_t time_in_us = 0;
181     if ((base != NULL) && (src_freq != 0)) {
182         reset_interval_t reset_interval = (reset_interval_t) WDG_CTRL_RSTTIME_GET(base->CTRL);
183         interrupt_interval_t interrupt_interval = (interrupt_interval_t) WDG_CTRL_INTTIME_GET(base->CTRL);
184         time_in_us = wdg_convert_reset_interval_to_us(src_freq, reset_interval) +
185             wdg_convert_interrupt_interval_to_us(src_freq, interrupt_interval);
186     }
187 
188     return time_in_us;
189 }
190