88#include "clock_control_nrf2_common.h"
99#include <zephyr/devicetree.h>
1010#include <zephyr/drivers/clock_control/nrf_clock_control.h>
11+ #include <hal/nrf_bicr.h>
1112#include <nrfs_clock.h>
1213
1314#include <zephyr/logging/log.h>
@@ -16,30 +17,25 @@ LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
1617BUILD_ASSERT (DT_NUM_INST_STATUS_OKAY (DT_DRV_COMPAT ) == 1 ,
1718 "multiple instances not supported" );
1819
19- #define LFCLK_LFXO_NODE DT_INST_PHANDLE_BY_NAME(0, clocks, lfxo)
2020#define LFCLK_HFXO_NODE DT_INST_PHANDLE_BY_NAME(0, clocks, hfxo)
2121
22- #define LFCLK_HAS_LFXO DT_NODE_HAS_STATUS_OKAY(LFCLK_LFXO_NODE)
23-
2422#define LFCLK_LFLPRC_ACCURACY DT_INST_PROP(0, lflprc_accuracy_ppm)
2523#define LFCLK_LFRC_ACCURACY DT_INST_PROP(0, lfrc_accuracy_ppm)
26- #define LFCLK_LFXO_ACCURACY DT_PROP(LFCLK_LFXO_NODE, accuracy_ppm)
2724#define LFCLK_HFXO_ACCURACY DT_PROP(LFCLK_HFXO_NODE, accuracy_ppm)
2825
29- #if LFCLK_HAS_LFXO
30- #define LFCLK_MAX_ACCURACY LFCLK_LFXO_ACCURACY
31- #else
32- #define LFCLK_MAX_ACCURACY LFCLK_HFXO_ACCURACY
33- #endif
26+ #define LFCLK_MAX_OPTS 5
27+ #define LFCLK_DEF_OPTS 3
3428
3529#define NRFS_CLOCK_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF2_NRFS_CLOCK_TIMEOUT_MS)
3630
31+ #define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr))
32+
3733/* Clock options sorted from lowest to highest accuracy/precision */
38- static const struct clock_options {
34+ static struct clock_options {
3935 uint16_t accuracy : 15 ;
4036 uint16_t precision : 1 ;
4137 nrfs_clock_src_t src ;
42- } clock_options [] = {
38+ } clock_options [LFCLK_MAX_OPTS ] = {
4339 {
4440 .accuracy = LFCLK_LFLPRC_ACCURACY ,
4541 .precision = 0 ,
@@ -56,43 +52,13 @@ static const struct clock_options {
5652 .precision = 1 ,
5753 .src = NRFS_CLOCK_SRC_LFCLK_SYNTH ,
5854 },
59- #if LFCLK_HAS_LFXO
60- #if DT_ENUM_HAS_VALUE (LFCLK_LFXO_NODE , mode , crystal )
61- {
62- .accuracy = LFCLK_LFXO_ACCURACY ,
63- .src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE ,
64- },
65- {
66- .accuracy = LFCLK_LFXO_ACCURACY ,
67- .precision = 1 ,
68- .src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP ,
69- },
70- #elif DT_ENUM_HAS_VALUE (LFCLK_LFXO_NODE , mode , external_sine )
71- {
72- .accuracy = LFCLK_LFXO_ACCURACY ,
73- .precision = 0 ,
74- .src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE ,
75- },
76- {
77- .accuracy = LFCLK_LFXO_ACCURACY ,
78- .precision = 1 ,
79- .src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP ,
80- },
81- #elif DT_ENUM_HAS_VALUE (LFCLK_LFXO_NODE , mode , external_square )
82- {
83- .accuracy = LFCLK_LFXO_ACCURACY ,
84- .precision = 0 ,
85- .src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE ,
86- },
87- #else
88- #error "unsupported LFXO mode"
89- #endif
90- #endif
9155};
9256
9357struct lfclk_dev_data {
9458 STRUCT_CLOCK_CONFIG (lfclk , ARRAY_SIZE (clock_options )) clk_cfg ;
9559 struct k_timer timer ;
60+ uint16_t max_accuracy ;
61+ uint8_t clock_options_cnt ;
9662};
9763
9864struct lfclk_dev_config {
@@ -156,10 +122,10 @@ static struct onoff_manager *lfclk_find_mgr(const struct device *dev,
156122 }
157123
158124 accuracy = spec -> accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX
159- ? LFCLK_MAX_ACCURACY
125+ ? dev_data -> max_accuracy
160126 : spec -> accuracy ;
161127
162- for (int i = 0 ; i < ARRAY_SIZE ( clock_options ) ; ++ i ) {
128+ for (int i = 0 ; i < dev_data -> clock_options_cnt ; ++ i ) {
163129 if ((accuracy &&
164130 accuracy < clock_options [i ].accuracy ) ||
165131 spec -> precision > clock_options [i ].precision ) {
@@ -227,13 +193,66 @@ static int api_get_rate_lfclk(const struct device *dev,
227193static int lfclk_init (const struct device * dev )
228194{
229195 struct lfclk_dev_data * dev_data = dev -> data ;
196+ nrf_bicr_lfosc_mode_t lfosc_mode ;
230197 nrfs_err_t res ;
231198
232199 res = nrfs_clock_init (clock_evt_handler );
233200 if (res != NRFS_SUCCESS ) {
234201 return - EIO ;
235202 }
236203
204+ dev_data -> clock_options_cnt = LFCLK_DEF_OPTS ;
205+
206+ lfosc_mode = nrf_bicr_lfosc_mode_get (BICR );
207+
208+ if (lfosc_mode == NRF_BICR_LFOSC_MODE_UNCONFIGURED ||
209+ lfosc_mode == NRF_BICR_LFOSC_MODE_DISABLED ) {
210+ dev_data -> max_accuracy = LFCLK_HFXO_ACCURACY ;
211+ } else {
212+ int ret ;
213+
214+ ret = lfosc_get_accuracy (& dev_data -> max_accuracy );
215+ if (ret < 0 ) {
216+ LOG_ERR ("LFOSC enabled with invalid accuracy" );
217+ return ret ;
218+ }
219+
220+ switch (lfosc_mode ) {
221+ case NRF_BICR_LFOSC_MODE_CRYSTAL :
222+ clock_options [LFCLK_MAX_OPTS - 2 ].accuracy = dev_data -> max_accuracy ;
223+ clock_options [LFCLK_MAX_OPTS - 2 ].precision = 0 ;
224+ clock_options [LFCLK_MAX_OPTS - 2 ].src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE ;
225+
226+ clock_options [LFCLK_MAX_OPTS - 1 ].accuracy = dev_data -> max_accuracy ;
227+ clock_options [LFCLK_MAX_OPTS - 1 ].precision = 1 ;
228+ clock_options [LFCLK_MAX_OPTS - 1 ].src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP ;
229+
230+ dev_data -> clock_options_cnt += 2 ;
231+ break ;
232+ case NRF_BICR_LFOSC_MODE_EXTSINE :
233+ clock_options [LFCLK_MAX_OPTS - 2 ].accuracy = dev_data -> max_accuracy ;
234+ clock_options [LFCLK_MAX_OPTS - 2 ].precision = 0 ;
235+ clock_options [LFCLK_MAX_OPTS - 2 ].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE ;
236+
237+ clock_options [LFCLK_MAX_OPTS - 1 ].accuracy = dev_data -> max_accuracy ;
238+ clock_options [LFCLK_MAX_OPTS - 1 ].precision = 1 ;
239+ clock_options [LFCLK_MAX_OPTS - 1 ].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP ;
240+
241+ dev_data -> clock_options_cnt += 2 ;
242+ break ;
243+ case NRF_BICR_LFOSC_MODE_EXTSQUARE :
244+ clock_options [LFCLK_MAX_OPTS - 2 ].accuracy = dev_data -> max_accuracy ;
245+ clock_options [LFCLK_MAX_OPTS - 2 ].precision = 0 ;
246+ clock_options [LFCLK_MAX_OPTS - 2 ].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE ;
247+
248+ dev_data -> clock_options_cnt += 1 ;
249+ break ;
250+ default :
251+ LOG_ERR ("Unexpected LFOSC mode" );
252+ return - EINVAL ;
253+ }
254+ }
255+
237256 k_timer_init (& dev_data -> timer , lfclk_update_timeout_handler , NULL );
238257
239258 return clock_config_init (& dev_data -> clk_cfg ,
0 commit comments