@@ -22,6 +22,8 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
22
22
#define LFCLK_LFLPRC_ACCURACY DT_INST_PROP(0, lflprc_accuracy_ppm)
23
23
#define LFCLK_LFRC_ACCURACY DT_INST_PROP(0, lfrc_accuracy_ppm)
24
24
#define LFCLK_HFXO_ACCURACY DT_PROP(LFCLK_HFXO_NODE, accuracy_ppm)
25
+ #define LFCLK_LFLPRC_STARTUP_TIME_US DT_INST_PROP(0, lflprc_startup_time_us)
26
+ #define LFCLK_LFRC_STARTUP_TIME_US DT_INST_PROP(0, lfrc_startup_time_us)
25
27
26
28
#define LFCLK_MAX_OPTS 5
27
29
#define LFCLK_DEF_OPTS 3
@@ -59,6 +61,8 @@ struct lfclk_dev_data {
59
61
struct k_timer timer ;
60
62
uint16_t max_accuracy ;
61
63
uint8_t clock_options_cnt ;
64
+ uint32_t hfxo_startup_time_us ;
65
+ uint32_t lfxo_startup_time_us ;
62
66
};
63
67
64
68
struct lfclk_dev_config {
@@ -105,45 +109,108 @@ static void lfclk_work_handler(struct k_work *work)
105
109
}
106
110
}
107
111
108
- static struct onoff_manager * lfclk_find_mgr (const struct device * dev ,
109
- const struct nrf_clock_spec * spec )
112
+ static int lfclk_resolve_spec_to_idx (const struct device * dev ,
113
+ const struct nrf_clock_spec * req_spec )
110
114
{
111
115
struct lfclk_dev_data * dev_data = dev -> data ;
112
116
const struct lfclk_dev_config * dev_config = dev -> config ;
113
- uint16_t accuracy ;
117
+ uint16_t req_accuracy ;
114
118
115
- if (!spec ) {
116
- return & dev_data -> clk_cfg .onoff [0 ].mgr ;
117
- }
118
-
119
- if (spec -> frequency > dev_config -> fixed_frequency ) {
119
+ if (req_spec -> frequency > dev_config -> fixed_frequency ) {
120
120
LOG_ERR ("invalid frequency" );
121
- return NULL ;
121
+ return - EINVAL ;
122
122
}
123
123
124
- accuracy = spec -> accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX
125
- ? dev_data -> max_accuracy
126
- : spec -> accuracy ;
124
+ req_accuracy = req_spec -> accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX
125
+ ? dev_data -> max_accuracy
126
+ : req_spec -> accuracy ;
127
127
128
128
for (int i = 0 ; i < dev_data -> clock_options_cnt ; ++ i ) {
129
- if ((accuracy &&
130
- accuracy < clock_options [i ].accuracy ) ||
131
- spec -> precision > clock_options [i ].precision ) {
129
+ if ((req_accuracy &&
130
+ req_accuracy < clock_options [i ].accuracy ) ||
131
+ req_spec -> precision > clock_options [i ].precision ) {
132
132
continue ;
133
133
}
134
134
135
- return & dev_data -> clk_cfg . onoff [ i ]. mgr ;
135
+ return i ;
136
136
}
137
137
138
138
LOG_ERR ("invalid accuracy or precision" );
139
- return NULL ;
139
+ return - EINVAL ;
140
+ }
141
+
142
+ static void lfclk_get_spec_by_idx (const struct device * dev ,
143
+ uint8_t idx ,
144
+ struct nrf_clock_spec * spec )
145
+ {
146
+ const struct lfclk_dev_config * dev_config = dev -> config ;
147
+
148
+ spec -> frequency = dev_config -> fixed_frequency ;
149
+ spec -> accuracy = clock_options [idx ].accuracy ;
150
+ spec -> precision = clock_options [idx ].precision ;
151
+ }
152
+
153
+ static struct onoff_manager * lfclk_get_mgr_by_idx (const struct device * dev , uint8_t idx )
154
+ {
155
+ struct lfclk_dev_data * dev_data = dev -> data ;
156
+
157
+ return & dev_data -> clk_cfg .onoff [idx ].mgr ;
158
+ }
159
+
160
+ static int lfclk_get_startup_time_by_idx (const struct device * dev ,
161
+ uint8_t idx ,
162
+ uint32_t * startup_time_us )
163
+ {
164
+ struct lfclk_dev_data * dev_data = dev -> data ;
165
+ nrfs_clock_src_t src = clock_options [idx ].src ;
166
+
167
+ switch (src ) {
168
+ case NRFS_CLOCK_SRC_LFCLK_LFLPRC :
169
+ * startup_time_us = LFCLK_LFLPRC_STARTUP_TIME_US ;
170
+ return 0 ;
171
+
172
+ case NRFS_CLOCK_SRC_LFCLK_LFRC :
173
+ * startup_time_us = LFCLK_LFRC_STARTUP_TIME_US ;
174
+ return 0 ;
175
+
176
+ case NRFS_CLOCK_SRC_LFCLK_XO_PIXO :
177
+ case NRFS_CLOCK_SRC_LFCLK_XO_PIERCE :
178
+ case NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE :
179
+ case NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE :
180
+ case NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP :
181
+ case NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP :
182
+ * startup_time_us = dev_data -> lfxo_startup_time_us ;
183
+ return 0 ;
184
+
185
+ case NRFS_CLOCK_SRC_LFCLK_SYNTH :
186
+ * startup_time_us = dev_data -> hfxo_startup_time_us ;
187
+ return 0 ;
188
+
189
+ default :
190
+ break ;
191
+ }
192
+
193
+ return - EINVAL ;
194
+ }
195
+
196
+ static struct onoff_manager * lfclk_find_mgr_by_spec (const struct device * dev ,
197
+ const struct nrf_clock_spec * spec )
198
+ {
199
+ int idx ;
200
+
201
+ if (!spec ) {
202
+ return lfclk_get_mgr_by_idx (dev , 0 );
203
+ }
204
+
205
+ idx = lfclk_resolve_spec_to_idx (dev , spec );
206
+ return idx < 0 ? NULL : lfclk_get_mgr_by_idx (dev , idx );
140
207
}
141
208
142
209
static int api_request_lfclk (const struct device * dev ,
143
210
const struct nrf_clock_spec * spec ,
144
211
struct onoff_client * cli )
145
212
{
146
- struct onoff_manager * mgr = lfclk_find_mgr (dev , spec );
213
+ struct onoff_manager * mgr = lfclk_find_mgr_by_spec (dev , spec );
147
214
148
215
if (mgr ) {
149
216
return clock_config_request (mgr , cli );
@@ -155,7 +222,7 @@ static int api_request_lfclk(const struct device *dev,
155
222
static int api_release_lfclk (const struct device * dev ,
156
223
const struct nrf_clock_spec * spec )
157
224
{
158
- struct onoff_manager * mgr = lfclk_find_mgr (dev , spec );
225
+ struct onoff_manager * mgr = lfclk_find_mgr_by_spec (dev , spec );
159
226
160
227
if (mgr ) {
161
228
return onoff_release (mgr );
@@ -168,7 +235,7 @@ static int api_cancel_or_release_lfclk(const struct device *dev,
168
235
const struct nrf_clock_spec * spec ,
169
236
struct onoff_client * cli )
170
237
{
171
- struct onoff_manager * mgr = lfclk_find_mgr (dev , spec );
238
+ struct onoff_manager * mgr = lfclk_find_mgr_by_spec (dev , spec );
172
239
173
240
if (mgr ) {
174
241
return onoff_cancel_or_release (mgr , cli );
@@ -177,6 +244,36 @@ static int api_cancel_or_release_lfclk(const struct device *dev,
177
244
return - EINVAL ;
178
245
}
179
246
247
+
248
+ static int api_resolve (const struct device * dev ,
249
+ const struct nrf_clock_spec * req_spec ,
250
+ struct nrf_clock_spec * res_spec )
251
+ {
252
+ int idx ;
253
+
254
+ idx = lfclk_resolve_spec_to_idx (dev , req_spec );
255
+ if (idx < 0 ) {
256
+ return - EINVAL ;
257
+ }
258
+
259
+ lfclk_get_spec_by_idx (dev , idx , res_spec );
260
+ return 0 ;
261
+ }
262
+
263
+ static int api_get_startup_time (const struct device * dev ,
264
+ const struct nrf_clock_spec * spec ,
265
+ uint32_t * startup_time_us )
266
+ {
267
+ int idx ;
268
+
269
+ idx = lfclk_resolve_spec_to_idx (dev , spec );
270
+ if (idx < 0 ) {
271
+ return - EINVAL ;
272
+ }
273
+
274
+ return lfclk_get_startup_time_by_idx (dev , idx , startup_time_us );
275
+ }
276
+
180
277
static int api_get_rate_lfclk (const struct device * dev ,
181
278
clock_control_subsys_t sys ,
182
279
uint32_t * rate )
@@ -251,6 +348,19 @@ static int lfclk_init(const struct device *dev)
251
348
LOG_ERR ("Unexpected LFOSC mode" );
252
349
return - EINVAL ;
253
350
}
351
+
352
+ dev_data -> lfxo_startup_time_us = nrf_bicr_lfosc_startup_time_ms_get (BICR )
353
+ * USEC_PER_MSEC ;
354
+ if (dev_data -> lfxo_startup_time_us == NRF_BICR_LFOSC_STARTUP_TIME_UNCONFIGURED ) {
355
+ LOG_ERR ("BICR LFXO startup time invalid" );
356
+ return - ENODEV ;
357
+ }
358
+ }
359
+
360
+ dev_data -> hfxo_startup_time_us = nrf_bicr_hfxo_startup_time_us_get (BICR );
361
+ if (dev_data -> hfxo_startup_time_us == NRF_BICR_HFXO_STARTUP_TIME_UNCONFIGURED ) {
362
+ LOG_ERR ("BICR HFXO startup time invalid" );
363
+ return - ENODEV ;
254
364
}
255
365
256
366
k_timer_init (& dev_data -> timer , lfclk_update_timeout_handler , NULL );
@@ -269,6 +379,8 @@ static DEVICE_API(nrf_clock_control, lfclk_drv_api) = {
269
379
.request = api_request_lfclk ,
270
380
.release = api_release_lfclk ,
271
381
.cancel_or_release = api_cancel_or_release_lfclk ,
382
+ .resolve = api_resolve ,
383
+ .get_startup_time = api_get_startup_time ,
272
384
};
273
385
274
386
static struct lfclk_dev_data lfclk_data ;
0 commit comments