1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Note that the function prototypes are taken from the NRFx HAL
7  */
8 #include "hal/nrf_grtc.h"
9 #include "bs_tracing.h"
10 #include "NHW_GRTC.h"
11 
nrf_grtc_sys_counter_cc_set(NRF_GRTC_Type * p_reg,uint8_t cc_channel,uint64_t cc_value)12 void nrf_grtc_sys_counter_cc_set(NRF_GRTC_Type * p_reg,
13                                  uint8_t         cc_channel,
14                                  uint64_t        cc_value)
15 {
16 #if NRF_GRTC_HAS_EXTENDED
17     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT);
18 #else
19     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT &&
20                 cc_channel > NRF_GRTC_MAIN_CC_CHANNEL);
21 #endif
22     uint32_t cc_h = (uint32_t)(cc_value >> 32);
23     NRFX_ASSERT(cc_h <= NRF_GRTC_SYSCOUNTER_CCH_MASK);
24 
25     p_reg->CC[cc_channel].CCL = (uint32_t)cc_value;
26     nhw_GRTC_regw_sideeffects_CC_CCL(0, cc_channel);
27     p_reg->CC[cc_channel].CCH = cc_h & NRF_GRTC_SYSCOUNTER_CCH_MASK;
28     nhw_GRTC_regw_sideeffects_CC_CCH(0, cc_channel);
29 }
30 
nrf_grtc_sys_counter_cc_add_set(NRF_GRTC_Type * p_reg,uint8_t cc_channel,uint32_t value,nrf_grtc_cc_add_reference_t reference)31 void nrf_grtc_sys_counter_cc_add_set(NRF_GRTC_Type *             p_reg,
32                                      uint8_t                     cc_channel,
33                                      uint32_t                    value,
34                                      nrf_grtc_cc_add_reference_t reference)
35 {
36 #if NRF_GRTC_HAS_EXTENDED
37     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT);
38 #else
39     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT &&
40                 cc_channel > NRF_GRTC_MAIN_CC_CHANNEL);
41 #endif
42     NRFX_ASSERT(value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK);
43 
44     p_reg->CC[cc_channel].CCADD = ((uint32_t)reference << GRTC_CC_CCADD_REFERENCE_Pos) |
45                                (value & NRF_GRTC_SYSCOUNTER_CCADD_MASK);
46     nhw_GRTC_regw_sideeffects_CC_CCADD(0, cc_channel);
47 }
48 
nrf_grtc_int_enable(NRF_GRTC_Type * p_reg,uint32_t mask)49 void nrf_grtc_int_enable(NRF_GRTC_Type * p_reg, uint32_t mask)
50 {
51     p_reg->GRTC_INTENSET = mask;
52     nhw_GRTC_regw_sideeffects_INTENSET(0, GRTC_IRQ_GROUP);
53 }
54 
nrf_grtc_int_disable(NRF_GRTC_Type * p_reg,uint32_t mask)55 void nrf_grtc_int_disable(NRF_GRTC_Type * p_reg, uint32_t mask)
56 {
57     p_reg->GRTC_INTENCLR = mask;
58     nhw_GRTC_regw_sideeffects_INTENCLR(0, GRTC_IRQ_GROUP);
59 }
60 
61 #define INTENGRPOFFSET (offsetof(NRF_GRTC_Type, INTENSET1) - offsetof(NRF_GRTC_Type, INTENSET0))
62 
nrf_grtc_int_group_enable(NRF_GRTC_Type * p_reg,uint8_t group_idx,uint32_t mask)63 void nrf_grtc_int_group_enable(NRF_GRTC_Type * p_reg,
64                                uint8_t         group_idx,
65                                uint32_t        mask)
66 {
67   *(uint32_t*)((char*)p_reg->INTENSET0 + INTENGRPOFFSET*group_idx) = mask;
68   nhw_GRTC_regw_sideeffects_INTENSET(0, group_idx);
69 }
70 
nrf_grtc_int_group_disable(NRF_GRTC_Type * p_reg,uint8_t group_idx,uint32_t mask)71 void nrf_grtc_int_group_disable(NRF_GRTC_Type * p_reg,
72                                                   uint8_t         group_idx,
73                                                   uint32_t        mask)
74 {
75   *(uint32_t*)((char*)p_reg->INTENCLR0 + INTENGRPOFFSET*group_idx) = mask;
76   nhw_GRTC_regw_sideeffects_INTENCLR(0, group_idx);
77 }
78 
nrf_grtc_subscribe_set(NRF_GRTC_Type * p_reg,nrf_grtc_task_t task,uint8_t channel)79 void nrf_grtc_subscribe_set(NRF_GRTC_Type * p_reg,
80                            nrf_grtc_task_t task,
81                            uint8_t        channel)
82 {
83 #if NRF_GRTC_HAS_EXTENDED
84     NRFX_ASSERT((task != NRF_GRTC_TASK_START) &&
85                 (task != NRF_GRTC_TASK_CLEAR) &&
86                 (task != NRF_GRTC_TASK_STOP));
87 #endif
88 
89     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) =
90             ((uint32_t)channel | NRF_SUBSCRIBE_PUBLISH_ENABLE);
91 
92     int task_nbr = (task - NRF_GRTC_TASK_CAPTURE_0)/sizeof(uint32_t);
93 
94     nhw_GRTC_regw_sideeffects_SUBSCRIBE_CAPTURE(0, task_nbr);
95 }
96 
nrf_grtc_subscribe_clear(NRF_GRTC_Type * p_reg,nrf_grtc_task_t task)97 void nrf_grtc_subscribe_clear(NRF_GRTC_Type * p_reg,
98                              nrf_grtc_task_t task)
99 {
100 #if NRF_GRTC_HAS_EXTENDED
101     NRFX_ASSERT((task != NRF_GRTC_TASK_START) &&
102                 (task != NRF_GRTC_TASK_CLEAR) &&
103                 (task != NRF_GRTC_TASK_STOP));
104 #endif
105 
106     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) = 0;
107 
108     int task_nbr = (task - NRF_GRTC_TASK_CAPTURE_0)/sizeof(uint32_t);
109 
110     nhw_GRTC_regw_sideeffects_SUBSCRIBE_CAPTURE(0, task_nbr);
111 }
112 
nrf_grtc_event_clear(NRF_GRTC_Type * p_reg,nrf_grtc_event_t event)113 void nrf_grtc_event_clear(NRF_GRTC_Type * p_reg, nrf_grtc_event_t event)
114 {
115   *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
116 
117   nhw_GRTC_regw_sideeffects_EVENTS_all(0);
118 }
119 
120 
nrf_grtc_sys_counter_low_get(NRF_GRTC_Type const * p_reg)121 uint32_t nrf_grtc_sys_counter_low_get(NRF_GRTC_Type const * p_reg)
122 {
123     (void) p_reg;
124 #if NRF_GRTC_HAS_SYSCOUNTER_ARRAY
125     return nhw_GRTC_regr_sideeffects_SYSCOUNTERL(0, NRF_GRTC_DOMAIN_INDEX);
126 #else
127 #error "Not supported"
128 #endif // NRF_GRTC_HAS_SYSCOUNTER_ARRAY
129 
130 }
131 
nrf_grtc_sys_counter_high_get(NRF_GRTC_Type const * p_reg)132 uint32_t nrf_grtc_sys_counter_high_get(NRF_GRTC_Type const * p_reg)
133 {
134     (void) p_reg;
135 #if NRF_GRTC_HAS_SYSCOUNTER_ARRAY
136     return nhw_GRTC_regr_sideeffects_SYSCOUNTERH(0, NRF_GRTC_DOMAIN_INDEX);
137 #else
138 #error "Not supported"
139 #endif // NRF_GRTC_HAS_SYSCOUNTER_ARRAY
140 }
141 
nrf_grtc_sys_counter_get(NRF_GRTC_Type const * p_reg)142 uint64_t nrf_grtc_sys_counter_get(NRF_GRTC_Type const * p_reg)
143 {
144     nhw_GRTC_regr_sideeffects_SYSCOUNTERL(0, NRF_GRTC_DOMAIN_INDEX);
145     nhw_GRTC_regr_sideeffects_SYSCOUNTERH(0, NRF_GRTC_DOMAIN_INDEX);
146     return *((const uint64_t volatile *)&p_reg->GRTC_SYSCOUNTER.SYSCOUNTERL);
147 }
148 
nrf_grtc_sys_counter_overflow_check(NRF_GRTC_Type const * p_reg)149 bool nrf_grtc_sys_counter_overflow_check(NRF_GRTC_Type const * p_reg)
150 {
151     nhw_GRTC_regr_sideeffects_SYSCOUNTERH(0, NRF_GRTC_DOMAIN_INDEX);
152     return (p_reg->GRTC_SYSCOUNTER.SYSCOUNTERH &
153             GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Msk) ? true : false;
154 }
155 
nrf_grtc_sys_counter_indexed_get(NRF_GRTC_Type const * p_reg,uint8_t index)156 uint64_t nrf_grtc_sys_counter_indexed_get(NRF_GRTC_Type const * p_reg,
157                                           uint8_t               index)
158 {
159     nhw_GRTC_regr_sideeffects_SYSCOUNTERL(0, index);
160     nhw_GRTC_regr_sideeffects_SYSCOUNTERH(0, index);
161     return *((const uint64_t volatile *)&p_reg->SYSCOUNTER[index]);
162 }
163 
nrf_grtc_task_trigger(NRF_GRTC_Type * p_reg,nrf_grtc_task_t grtc_task)164 void nrf_grtc_task_trigger(NRF_GRTC_Type * p_reg, nrf_grtc_task_t grtc_task)
165 {
166     uint inst = 0;
167     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)grtc_task)) = 0x1UL;
168 
169     if ((grtc_task >= NRF_GRTC_TASK_CAPTURE_0) && (grtc_task < NRF_GRTC_TASK_START)) {
170       int task_nbr = (grtc_task - NRF_GRTC_TASK_CAPTURE_0)/sizeof(uint32_t);
171       nhw_GRTC_regw_sideeffects_TASKS_CAPTURE(inst, task_nbr);
172     } else if (grtc_task == NRF_GRTC_TASK_START) {
173       nhw_GRTC_regw_sideeffects_TASKS_START(inst);
174     } else if (grtc_task == NRF_GRTC_TASK_STOP) {
175       nhw_GRTC_regw_sideeffects_TASKS_STOP(inst);
176     } else if (grtc_task == NRF_GRTC_TASK_CLEAR) {
177       nhw_GRTC_regw_sideeffects_TASKS_CLEAR(inst);
178 #if NRF_GRTC_HAS_PWM
179     } else if (grtc_task == NRF_GRTC_TASK_PWM_START) {
180        nhw_GRTC_regw_sideeffects_TASKS_PWMSTART(inst);
181     } else if (grtc_task == NRF_GRTC_TASK_PWM_STOP) {
182        nhw_GRTC_regw_sideeffects_TASKS_PWMSTOP(inst);
183 #endif
184     } else {
185       bs_trace_error_time_line("GRTC task %i not known\n", grtc_task);
186     }
187 }
188 
nrf_grtc_sys_counter_compare_event_enable(NRF_GRTC_Type * p_reg,uint8_t cc_channel)189 void nrf_grtc_sys_counter_compare_event_enable(NRF_GRTC_Type * p_reg,
190                                                                  uint8_t         cc_channel)
191 {
192 
193 #if NRF_GRTC_HAS_EXTENDED
194     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT);
195 #else
196     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT &&
197                 cc_channel > NRF_GRTC_MAIN_CC_CHANNEL);
198 #endif
199     p_reg->CC[cc_channel].CCEN = GRTC_CC_CCEN_ACTIVE_Enable;
200     nhw_GRTC_regw_sideeffects_CC_CCEN(0, cc_channel);
201 }
202 
nrf_grtc_sys_counter_compare_event_disable(NRF_GRTC_Type * p_reg,uint8_t cc_channel)203 NRF_STATIC_INLINE void nrf_grtc_sys_counter_compare_event_disable(NRF_GRTC_Type * p_reg,
204                                                                   uint8_t         cc_channel)
205 {
206 #if NRF_GRTC_HAS_EXTENDED
207     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT);
208 #else
209     NRFX_ASSERT(cc_channel < NRF_GRTC_SYSCOUNTER_CC_COUNT &&
210                 cc_channel > NRF_GRTC_MAIN_CC_CHANNEL);
211 #endif
212     p_reg->CC[cc_channel].CCEN = GRTC_CC_CCEN_ACTIVE_Disable;
213     nhw_GRTC_regw_sideeffects_CC_CCEN(0, cc_channel);
214 }
215