@@ -34,6 +34,7 @@ BUILD_ASSERT(FLL16M_MODE_CLOSED_LOOP == NRF_LRCCONF_CLK_SRC_CLOSED_LOOP);
3434#define FLL16M_HFXO_ACCURACY DT_PROP(FLL16M_HFXO_NODE, accuracy_ppm)
3535#define FLL16M_OPEN_LOOP_ACCURACY DT_INST_PROP(0, open_loop_accuracy_ppm)
3636#define FLL16M_MAX_ACCURACY FLL16M_HFXO_ACCURACY
37+ #define FLL16M_OPEN_LOOP_STARTUP_TIME_US DT_INST_PROP(0, open_loop_startup_time_us)
3738
3839#define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr))
3940
@@ -57,6 +58,7 @@ struct fll16m_dev_data {
5758 STRUCT_CLOCK_CONFIG (fll16m , ARRAY_SIZE (clock_options )) clk_cfg ;
5859 struct onoff_client hfxo_cli ;
5960 sys_snode_t fll16m_node ;
61+ uint32_t bypass_startup_time_us ;
6062};
6163
6264struct fll16m_dev_config {
@@ -133,49 +135,98 @@ static void fll16m_work_handler(struct k_work *work)
133135 }
134136}
135137
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 )
138140{
139- struct fll16m_dev_data * dev_data = dev -> data ;
140141 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 ;
146143
147- if (spec -> frequency > dev_config -> fixed_frequency ) {
144+ if (req_spec -> frequency > dev_config -> fixed_frequency ) {
148145 LOG_ERR ("invalid frequency" );
149- return NULL ;
146+ return - EINVAL ;
150147 }
151148
152- if (spec -> precision ) {
149+ if (req_spec -> precision ) {
153150 LOG_ERR ("invalid precision" );
154- return NULL ;
151+ return - EINVAL ;
155152 }
156153
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 ;
160157
161158 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 ) {
164161 continue ;
165162 }
166163
167- return & dev_data -> clk_cfg . onoff [ i ]. mgr ;
164+ return i ;
168165 }
169166
170167 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 );
172223}
173224
174225static int api_request_fll16m (const struct device * dev ,
175226 const struct nrf_clock_spec * spec ,
176227 struct onoff_client * cli )
177228{
178- struct onoff_manager * mgr = fll16m_find_mgr (dev , spec );
229+ struct onoff_manager * mgr = fll16m_find_mgr_by_spec (dev , spec );
179230
180231 if (mgr ) {
181232 return clock_config_request (mgr , cli );
@@ -187,7 +238,7 @@ static int api_request_fll16m(const struct device *dev,
187238static int api_release_fll16m (const struct device * dev ,
188239 const struct nrf_clock_spec * spec )
189240{
190- struct onoff_manager * mgr = fll16m_find_mgr (dev , spec );
241+ struct onoff_manager * mgr = fll16m_find_mgr_by_spec (dev , spec );
191242
192243 if (mgr ) {
193244 return onoff_release (mgr );
@@ -200,7 +251,7 @@ static int api_cancel_or_release_fll16m(const struct device *dev,
200251 const struct nrf_clock_spec * spec ,
201252 struct onoff_client * cli )
202253{
203- struct onoff_manager * mgr = fll16m_find_mgr (dev , spec );
254+ struct onoff_manager * mgr = fll16m_find_mgr_by_spec (dev , spec );
204255
205256 if (mgr ) {
206257 return onoff_cancel_or_release (mgr , cli );
@@ -222,10 +273,45 @@ static int api_get_rate_fll16m(const struct device *dev,
222273 return 0 ;
223274}
224275
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+
225305static int fll16m_init (const struct device * dev )
226306{
227307 struct fll16m_dev_data * dev_data = dev -> data ;
228308
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+
229315 return clock_config_init (& dev_data -> clk_cfg ,
230316 ARRAY_SIZE (dev_data -> clk_cfg .onoff ),
231317 fll16m_work_handler );
@@ -240,6 +326,8 @@ static DEVICE_API(nrf_clock_control, fll16m_drv_api) = {
240326 .request = api_request_fll16m ,
241327 .release = api_release_fll16m ,
242328 .cancel_or_release = api_cancel_or_release_fll16m ,
329+ .resolve = api_resolve ,
330+ .get_startup_time = api_get_startup_time ,
243331};
244332
245333static struct fll16m_dev_data fll16m_data ;
0 commit comments