1 /*
2  * Copyright (c) 2016-2018 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdint.h>
9 #include <stdbool.h>
10 
11 #include <zephyr/sys/util.h>
12 
13 #include "hal/cntr.h"
14 
15 #include "util/memq.h"
16 #include "util/mayfly.h"
17 
18 #include "ticker/ticker.h"
19 
20 #include "ll_sw/lll.h"
21 
22 #include "hal/debug.h"
23 
24 #define TICKER_MAYFLY_CALL_ID_ISR     TICKER_USER_ID_LLL
25 #define TICKER_MAYFLY_CALL_ID_TRIGGER TICKER_USER_ID_ULL_HIGH
26 #define TICKER_MAYFLY_CALL_ID_WORKER  TICKER_USER_ID_ULL_HIGH
27 #define TICKER_MAYFLY_CALL_ID_JOB     TICKER_USER_ID_ULL_LOW
28 #define TICKER_MAYFLY_CALL_ID_PROGRAM TICKER_USER_ID_THREAD
29 
30 static uint8_t const caller_id_lut[] = {
31 	TICKER_CALL_ID_ISR,
32 	TICKER_CALL_ID_WORKER,
33 	TICKER_CALL_ID_JOB,
34 	TICKER_CALL_ID_PROGRAM
35 };
36 
hal_ticker_instance0_caller_id_get(uint8_t user_id)37 uint8_t hal_ticker_instance0_caller_id_get(uint8_t user_id)
38 {
39 	uint8_t caller_id;
40 
41 	LL_ASSERT(user_id < sizeof(caller_id_lut));
42 
43 	caller_id = caller_id_lut[user_id];
44 	LL_ASSERT(caller_id != TICKER_CALL_ID_NONE);
45 
46 	return caller_id;
47 }
48 
hal_ticker_instance0_sched(uint8_t caller_id,uint8_t callee_id,uint8_t chain,void * instance)49 void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
50 				void *instance)
51 {
52 	/* return value not checked as we allow multiple calls to schedule
53 	 * before being actually needing the work to complete before new
54 	 * schedule.
55 	 */
56 	switch (caller_id) {
57 	case TICKER_CALL_ID_ISR:
58 		switch (callee_id) {
59 		case TICKER_CALL_ID_JOB:
60 		{
61 			static memq_link_t link;
62 			static struct mayfly m = {0, 0, &link, NULL,
63 						  ticker_job};
64 
65 			m.param = instance;
66 
67 			/* TODO: scheduler lock, if preemptive threads used */
68 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_ISR,
69 				       TICKER_MAYFLY_CALL_ID_JOB,
70 				       chain,
71 				       &m);
72 		}
73 		break;
74 
75 		default:
76 			LL_ASSERT(0);
77 			break;
78 		}
79 		break;
80 
81 	case TICKER_CALL_ID_TRIGGER:
82 		switch (callee_id) {
83 		case TICKER_CALL_ID_WORKER:
84 		{
85 			static memq_link_t link;
86 			static struct mayfly m = {0, 0, &link, NULL,
87 						  ticker_worker};
88 
89 			m.param = instance;
90 
91 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
92 				       TICKER_MAYFLY_CALL_ID_WORKER,
93 				       chain,
94 				       &m);
95 		}
96 		break;
97 
98 		default:
99 			LL_ASSERT(0);
100 			break;
101 		}
102 		break;
103 
104 	case TICKER_CALL_ID_WORKER:
105 		switch (callee_id) {
106 		case TICKER_CALL_ID_JOB:
107 		{
108 			static memq_link_t link;
109 			static struct mayfly m = {0, 0, &link, NULL,
110 						  ticker_job};
111 
112 			m.param = instance;
113 
114 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER,
115 				       TICKER_MAYFLY_CALL_ID_JOB,
116 				       chain,
117 				       &m);
118 		}
119 		break;
120 
121 		default:
122 			LL_ASSERT(0);
123 			break;
124 		}
125 		break;
126 
127 	case TICKER_CALL_ID_JOB:
128 		switch (callee_id) {
129 		case TICKER_CALL_ID_WORKER:
130 		{
131 			static memq_link_t link;
132 			static struct mayfly m = {0, 0, &link, NULL,
133 						  ticker_worker};
134 
135 			m.param = instance;
136 
137 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
138 				       TICKER_MAYFLY_CALL_ID_WORKER,
139 				       chain,
140 				       &m);
141 		}
142 		break;
143 
144 		case TICKER_CALL_ID_JOB:
145 		{
146 			static memq_link_t link;
147 			static struct mayfly m = {0, 0, &link, NULL,
148 						  ticker_job};
149 
150 			m.param = instance;
151 
152 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
153 				       TICKER_MAYFLY_CALL_ID_JOB,
154 				       chain,
155 				       &m);
156 		}
157 		break;
158 
159 		default:
160 			LL_ASSERT(0);
161 			break;
162 		}
163 		break;
164 
165 	case TICKER_CALL_ID_PROGRAM:
166 		switch (callee_id) {
167 		case TICKER_CALL_ID_JOB:
168 		{
169 			static memq_link_t link;
170 			static struct mayfly m = {0, 0, &link, NULL,
171 						  ticker_job};
172 
173 			m.param = instance;
174 
175 			/* TODO: scheduler lock, if preemptive threads used */
176 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM,
177 				       TICKER_MAYFLY_CALL_ID_JOB,
178 				       chain,
179 				       &m);
180 		}
181 		break;
182 
183 		default:
184 			LL_ASSERT(0);
185 			break;
186 		}
187 		break;
188 
189 	default:
190 		LL_ASSERT(0);
191 		break;
192 	}
193 }
194 
hal_ticker_instance0_trigger_set(uint32_t value)195 void hal_ticker_instance0_trigger_set(uint32_t value)
196 {
197 #if defined(CONFIG_BT_CTLR_NRF_GRTC)
198 	cntr_cmp_set(HAL_CNTR_GRTC_CC_IDX_TICKER, value);
199 #else /* !CONFIG_BT_CTLR_NRF_GRTC */
200 	cntr_cmp_set(0U, value);
201 #endif /* !CONFIG_BT_CTLR_NRF_GRTC */
202 }
203