@@ -34,6 +34,7 @@ BUILD_ASSERT(FLL16M_MODE_CLOSED_LOOP == NRF_LRCCONF_CLK_SRC_CLOSED_LOOP);
34
34
#define FLL16M_HFXO_ACCURACY DT_PROP(FLL16M_HFXO_NODE, accuracy_ppm)
35
35
#define FLL16M_OPEN_LOOP_ACCURACY DT_INST_PROP(0, open_loop_accuracy_ppm)
36
36
#define FLL16M_MAX_ACCURACY FLL16M_HFXO_ACCURACY
37
+ #define FLL16M_OPEN_LOOP_STARTUP_TIME_US DT_INST_PROP(0, open_loop_startup_time_us)
37
38
38
39
#define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr))
39
40
@@ -57,6 +58,7 @@ struct fll16m_dev_data {
57
58
STRUCT_CLOCK_CONFIG (fll16m , ARRAY_SIZE (clock_options )) clk_cfg ;
58
59
struct onoff_client hfxo_cli ;
59
60
sys_snode_t fll16m_node ;
61
+ uint32_t bypass_startup_time_us ;
60
62
};
61
63
62
64
struct fll16m_dev_config {
@@ -133,49 +135,98 @@ static void fll16m_work_handler(struct k_work *work)
133
135
}
134
136
}
135
137
136
- static struct onoff_manager * fll16m_find_mgr (const struct device * dev ,
137
- const struct nrf_clock_spec * spec )
138
+ static int fll16m_resolve_spec_to_idx (const struct device * dev ,
139
+ const struct nrf_clock_spec * req_spec )
138
140
{
139
- struct fll16m_dev_data * dev_data = dev -> data ;
140
141
const struct fll16m_dev_config * dev_config = dev -> config ;
141
- uint16_t accuracy ;
142
-
143
- if (!spec ) {
144
- return & dev_data -> clk_cfg .onoff [0 ].mgr ;
145
- }
142
+ uint16_t req_accuracy ;
146
143
147
- if (spec -> frequency > dev_config -> fixed_frequency ) {
144
+ if (req_spec -> frequency > dev_config -> fixed_frequency ) {
148
145
LOG_ERR ("invalid frequency" );
149
- return NULL ;
146
+ return - EINVAL ;
150
147
}
151
148
152
- if (spec -> precision ) {
149
+ if (req_spec -> precision ) {
153
150
LOG_ERR ("invalid precision" );
154
- return NULL ;
151
+ return - EINVAL ;
155
152
}
156
153
157
- accuracy = spec -> accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX
158
- ? FLL16M_MAX_ACCURACY
159
- : spec -> accuracy ;
154
+ req_accuracy = req_spec -> accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX
155
+ ? FLL16M_MAX_ACCURACY
156
+ : req_spec -> accuracy ;
160
157
161
158
for (int i = 0 ; i < ARRAY_SIZE (clock_options ); ++ i ) {
162
- if (accuracy &&
163
- accuracy < clock_options [i ].accuracy ) {
159
+ if (req_accuracy &&
160
+ req_accuracy < clock_options [i ].accuracy ) {
164
161
continue ;
165
162
}
166
163
167
- return & dev_data -> clk_cfg . onoff [ i ]. mgr ;
164
+ return i ;
168
165
}
169
166
170
167
LOG_ERR ("invalid accuracy" );
171
- return NULL ;
168
+ return - EINVAL ;
169
+ }
170
+
171
+ static void fll16m_get_spec_by_idx (const struct device * dev ,
172
+ uint8_t idx ,
173
+ struct nrf_clock_spec * spec )
174
+ {
175
+ const struct fll16m_dev_config * dev_config = dev -> config ;
176
+
177
+ spec -> frequency = dev_config -> fixed_frequency ;
178
+ spec -> accuracy = clock_options [idx ].accuracy ;
179
+ spec -> precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT ;
180
+ }
181
+
182
+ static int fll16m_get_startup_time_by_idx (const struct device * dev ,
183
+ uint8_t idx ,
184
+ uint32_t * startup_time_us )
185
+ {
186
+ const struct fll16m_dev_data * dev_data = dev -> data ;
187
+ uint8_t mode = clock_options [idx ].mode ;
188
+
189
+ switch (mode ) {
190
+ case FLL16M_MODE_OPEN_LOOP :
191
+ * startup_time_us = FLL16M_OPEN_LOOP_STARTUP_TIME_US ;
192
+ return 0 ;
193
+
194
+ case FLL16M_MODE_BYPASS :
195
+ * startup_time_us = dev_data -> bypass_startup_time_us ;
196
+ return 0 ;
197
+
198
+ default :
199
+ break ;
200
+ }
201
+
202
+ return - EINVAL ;
203
+ }
204
+
205
+ static struct onoff_manager * fll16m_get_mgr_by_idx (const struct device * dev , uint8_t idx )
206
+ {
207
+ struct fll16m_dev_data * dev_data = dev -> data ;
208
+
209
+ return & dev_data -> clk_cfg .onoff [idx ].mgr ;
210
+ }
211
+
212
+ static struct onoff_manager * fll16m_find_mgr_by_spec (const struct device * dev ,
213
+ const struct nrf_clock_spec * spec )
214
+ {
215
+ int idx ;
216
+
217
+ if (!spec ) {
218
+ return fll16m_get_mgr_by_idx (dev , 0 );
219
+ }
220
+
221
+ idx = fll16m_resolve_spec_to_idx (dev , spec );
222
+ return idx < 0 ? NULL : fll16m_get_mgr_by_idx (dev , idx );
172
223
}
173
224
174
225
static int api_request_fll16m (const struct device * dev ,
175
226
const struct nrf_clock_spec * spec ,
176
227
struct onoff_client * cli )
177
228
{
178
- struct onoff_manager * mgr = fll16m_find_mgr (dev , spec );
229
+ struct onoff_manager * mgr = fll16m_find_mgr_by_spec (dev , spec );
179
230
180
231
if (mgr ) {
181
232
return clock_config_request (mgr , cli );
@@ -187,7 +238,7 @@ static int api_request_fll16m(const struct device *dev,
187
238
static int api_release_fll16m (const struct device * dev ,
188
239
const struct nrf_clock_spec * spec )
189
240
{
190
- struct onoff_manager * mgr = fll16m_find_mgr (dev , spec );
241
+ struct onoff_manager * mgr = fll16m_find_mgr_by_spec (dev , spec );
191
242
192
243
if (mgr ) {
193
244
return onoff_release (mgr );
@@ -200,7 +251,7 @@ static int api_cancel_or_release_fll16m(const struct device *dev,
200
251
const struct nrf_clock_spec * spec ,
201
252
struct onoff_client * cli )
202
253
{
203
- struct onoff_manager * mgr = fll16m_find_mgr (dev , spec );
254
+ struct onoff_manager * mgr = fll16m_find_mgr_by_spec (dev , spec );
204
255
205
256
if (mgr ) {
206
257
return onoff_cancel_or_release (mgr , cli );
@@ -222,10 +273,45 @@ static int api_get_rate_fll16m(const struct device *dev,
222
273
return 0 ;
223
274
}
224
275
276
+ static int api_resolve (const struct device * dev ,
277
+ const struct nrf_clock_spec * req_spec ,
278
+ struct nrf_clock_spec * res_spec )
279
+ {
280
+ int idx ;
281
+
282
+ idx = fll16m_resolve_spec_to_idx (dev , req_spec );
283
+ if (idx < 0 ) {
284
+ return - EINVAL ;
285
+ }
286
+
287
+ fll16m_get_spec_by_idx (dev , idx , res_spec );
288
+ return 0 ;
289
+ }
290
+
291
+ static int api_get_startup_time (const struct device * dev ,
292
+ const struct nrf_clock_spec * spec ,
293
+ uint32_t * startup_time_us )
294
+ {
295
+ int idx ;
296
+
297
+ idx = fll16m_resolve_spec_to_idx (dev , spec );
298
+ if (idx < 0 ) {
299
+ return - EINVAL ;
300
+ }
301
+
302
+ return fll16m_get_startup_time_by_idx (dev , idx , startup_time_us );
303
+ }
304
+
225
305
static int fll16m_init (const struct device * dev )
226
306
{
227
307
struct fll16m_dev_data * dev_data = dev -> data ;
228
308
309
+ dev_data -> bypass_startup_time_us = nrf_bicr_hfxo_startup_time_us_get (BICR );
310
+ if (dev_data -> bypass_startup_time_us == NRF_BICR_HFXO_STARTUP_TIME_UNCONFIGURED ) {
311
+ LOG_ERR ("BICR HFXO startup time invalid" );
312
+ return - ENODEV ;
313
+ }
314
+
229
315
return clock_config_init (& dev_data -> clk_cfg ,
230
316
ARRAY_SIZE (dev_data -> clk_cfg .onoff ),
231
317
fll16m_work_handler );
@@ -240,6 +326,8 @@ static DEVICE_API(nrf_clock_control, fll16m_drv_api) = {
240
326
.request = api_request_fll16m ,
241
327
.release = api_release_fll16m ,
242
328
.cancel_or_release = api_cancel_or_release_fll16m ,
329
+ .resolve = api_resolve ,
330
+ .get_startup_time = api_get_startup_time ,
243
331
};
244
332
245
333
static struct fll16m_dev_data fll16m_data ;
0 commit comments