Skip to content

Commit 9983222

Browse files
bjarki-andreasenkartben
authored andcommitted
drivers: clock_control: nrf2_fll16m: 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 b20a233 commit 9983222

File tree

3 files changed

+117
-22
lines changed

3 files changed

+117
-22
lines changed

drivers/clock_control/clock_control_nrf2_fll16m.c

Lines changed: 110 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

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

174225
static 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,
187238
static 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+
225305
static 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

245333
static struct fll16m_dev_data fll16m_data;

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ description: |
1818
1919
fll16m {
2020
open-loop-accuracy-ppm = <20000>;
21+
open-loop-startup-time-us = <400>;
2122
clocks = <&hfxo>, <&lfxo>;
2223
clock-names = "hfxo", "lfxo";
2324
};
@@ -34,3 +35,8 @@ properties:
3435
type: int
3536
description: Clock accuracy in parts per million
3637
required: true
38+
39+
open-loop-startup-time-us:
40+
type: int
41+
description: Clock startup time if open-loop clock source is used.
42+
required: true

dts/vendor/nordic/nrf54h20.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@
177177
#clock-cells = <0>;
178178
clock-frequency = <DT_FREQ_M(16)>;
179179
open-loop-accuracy-ppm = <20000>;
180+
open-loop-startup-time-us = <200>; /* To be measured */
180181
clocks = <&hfxo>, <&lfxo>;
181182
clock-names = "hfxo", "lfxo";
182183
};

0 commit comments

Comments
 (0)