Skip to content

Commit b20a233

Browse files
bjarki-andreasenkartben
authored andcommitted
drivers: clock_control: nrf2_lfclk: impl resolve and startup_time
Implement nrf_clock_control_resolve() and nrf_clock_control_get_startup_time_us() APIs. Signed-off-by: Bjarki Arge Andreasen <[email protected]>
1 parent 54d86e8 commit b20a233

File tree

4 files changed

+146
-21
lines changed

4 files changed

+146
-21
lines changed

drivers/clock_control/clock_control_nrf2_lfclk.c

Lines changed: 132 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
2222
#define LFCLK_LFLPRC_ACCURACY DT_INST_PROP(0, lflprc_accuracy_ppm)
2323
#define LFCLK_LFRC_ACCURACY DT_INST_PROP(0, lfrc_accuracy_ppm)
2424
#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)
2527

2628
#define LFCLK_MAX_OPTS 5
2729
#define LFCLK_DEF_OPTS 3
@@ -59,6 +61,8 @@ struct lfclk_dev_data {
5961
struct k_timer timer;
6062
uint16_t max_accuracy;
6163
uint8_t clock_options_cnt;
64+
uint32_t hfxo_startup_time_us;
65+
uint32_t lfxo_startup_time_us;
6266
};
6367

6468
struct lfclk_dev_config {
@@ -105,45 +109,108 @@ static void lfclk_work_handler(struct k_work *work)
105109
}
106110
}
107111

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)
110114
{
111115
struct lfclk_dev_data *dev_data = dev->data;
112116
const struct lfclk_dev_config *dev_config = dev->config;
113-
uint16_t accuracy;
117+
uint16_t req_accuracy;
114118

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) {
120120
LOG_ERR("invalid frequency");
121-
return NULL;
121+
return -EINVAL;
122122
}
123123

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;
127127

128128
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) {
132132
continue;
133133
}
134134

135-
return &dev_data->clk_cfg.onoff[i].mgr;
135+
return i;
136136
}
137137

138138
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);
140207
}
141208

142209
static int api_request_lfclk(const struct device *dev,
143210
const struct nrf_clock_spec *spec,
144211
struct onoff_client *cli)
145212
{
146-
struct onoff_manager *mgr = lfclk_find_mgr(dev, spec);
213+
struct onoff_manager *mgr = lfclk_find_mgr_by_spec(dev, spec);
147214

148215
if (mgr) {
149216
return clock_config_request(mgr, cli);
@@ -155,7 +222,7 @@ static int api_request_lfclk(const struct device *dev,
155222
static int api_release_lfclk(const struct device *dev,
156223
const struct nrf_clock_spec *spec)
157224
{
158-
struct onoff_manager *mgr = lfclk_find_mgr(dev, spec);
225+
struct onoff_manager *mgr = lfclk_find_mgr_by_spec(dev, spec);
159226

160227
if (mgr) {
161228
return onoff_release(mgr);
@@ -168,7 +235,7 @@ static int api_cancel_or_release_lfclk(const struct device *dev,
168235
const struct nrf_clock_spec *spec,
169236
struct onoff_client *cli)
170237
{
171-
struct onoff_manager *mgr = lfclk_find_mgr(dev, spec);
238+
struct onoff_manager *mgr = lfclk_find_mgr_by_spec(dev, spec);
172239

173240
if (mgr) {
174241
return onoff_cancel_or_release(mgr, cli);
@@ -177,6 +244,36 @@ static int api_cancel_or_release_lfclk(const struct device *dev,
177244
return -EINVAL;
178245
}
179246

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+
180277
static int api_get_rate_lfclk(const struct device *dev,
181278
clock_control_subsys_t sys,
182279
uint32_t *rate)
@@ -251,6 +348,19 @@ static int lfclk_init(const struct device *dev)
251348
LOG_ERR("Unexpected LFOSC mode");
252349
return -EINVAL;
253350
}
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;
254364
}
255365

256366
k_timer_init(&dev_data->timer, lfclk_update_timeout_handler, NULL);
@@ -269,6 +379,8 @@ static DEVICE_API(nrf_clock_control, lfclk_drv_api) = {
269379
.request = api_request_lfclk,
270380
.release = api_release_lfclk,
271381
.cancel_or_release = api_cancel_or_release_lfclk,
382+
.resolve = api_resolve,
383+
.get_startup_time = api_get_startup_time,
272384
};
273385

274386
static struct lfclk_dev_data lfclk_data;

dts/bindings/clock/nordic,nrf-fll16m.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ properties:
3232

3333
open-loop-accuracy-ppm:
3434
type: int
35-
description: Clock accuracy in parts per million if open-loop clock source is used.
35+
description: Clock accuracy in parts per million
36+
required: true

dts/bindings/clock/nordic,nrf-lfclk.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ description: |
2121
lfclk {
2222
lfrc-accuracy-ppm = <500>;
2323
lflprc-accuracy-ppm = <1000>;
24+
lfrc-startup-time-us = <400>;
25+
lflprc-startup-time-us = <400>;
2426
clocks = <&hfxo>, <&lfxo>;
2527
clock-names = "hfxo", "lfxo";
2628
};
@@ -40,3 +42,11 @@ properties:
4042
lflprc-accuracy-ppm:
4143
type: int
4244
description: Clock accuracy in parts per million if LFLPRC clock source is used.
45+
46+
lfrc-startup-time-us:
47+
type: int
48+
description: Clock startup time in microseconds if LFRC clock source is used.
49+
50+
lflprc-startup-time-us:
51+
type: int
52+
description: Clock startup time in microseconds if LFLPRC clock source is used.

dts/vendor/nordic/nrf54h20.dtsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@
199199
status = "okay";
200200
lfrc-accuracy-ppm = <500>;
201201
lflprc-accuracy-ppm = <1000>;
202+
lfrc-startup-time-us = <200>; /* To be measured */
203+
lflprc-startup-time-us = <200>; /* To be measured */
202204
clocks = <&hfxo>, <&lfxo>;
203205
clock-names = "hfxo", "lfxo";
204206
};

0 commit comments

Comments
 (0)