Skip to content

Commit c976ada

Browse files
committed
[nrf fromlist] drivers: clock_control: nrf54h-lfclk: use values from BICR
The real, applicable and trusted values are the ones flashed into BICR. So, drop DT properties that replicate BICR and use runtime reads to BICR instead. Upstream PR #: 81122 Signed-off-by: Gerard Marull-Paretas <[email protected]> (cherry picked from commit 1b3500e022d28d78934570b2e3112badf65b6d23)
1 parent ba384d8 commit c976ada

File tree

3 files changed

+64
-67
lines changed

3 files changed

+64
-67
lines changed

boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-common.dtsi

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,4 @@
1515

1616
&lfxo {
1717
status = "okay";
18-
accuracy-ppm = <20>;
19-
startup-time-us = <600000>;
20-
mode = "crystal";
2118
};

drivers/clock_control/clock_control_nrf2_lfclk.c

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
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);
1617
BUILD_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

9357
struct 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

9864
struct 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,
227193
static 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,

dts/bindings/clock/nordic,nrf54h-lfxo.yaml

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,3 @@ include: fixed-clock.yaml
1010
properties:
1111
clock-frequency:
1212
const: 32768
13-
14-
accuracy-ppm:
15-
type: int
16-
description: Clock accuracy in parts per million
17-
required: true
18-
19-
startup-time-us:
20-
type: int
21-
description: Clock startup time in micro seconds
22-
required: true
23-
24-
mode:
25-
type: string
26-
description: LFXO operational mode
27-
required: true
28-
enum:
29-
- "crystal"
30-
- "external-sine"
31-
- "external-square"

0 commit comments

Comments
 (0)