1
1
/*
2
- * Copyright (c) 2024 Nordic Semiconductor ASA
2
+ * Copyright (c) 2025 Nordic Semiconductor ASA
3
3
* SPDX-License-Identifier: Apache-2.0
4
4
*/
5
5
9
9
#include <stdint.h>
10
10
11
11
#include <zephyr/arch/cpu.h>
12
- #include <zephyr/device.h>
13
12
#include <zephyr/devicetree.h>
14
- #include <zephyr/drivers/clock_control.h>
15
- #include <zephyr/kernel.h>
13
+ #include <zephyr/drivers/clock_control/nrf_clock_control.h>
16
14
#include <zephyr/sys/util.h>
17
15
#include <zephyr/toolchain.h>
16
+ #include <zephyr/dt-bindings/clock/nrf-auxpll.h>
17
+ #include "clock_control_nrf2_common.h"
18
18
19
19
#include <hal/nrf_auxpll.h>
20
20
21
- /* maximum lock time in ms, >10x time observed experimentally */
22
- #define AUXPLL_LOCK_TIME_MAX_MS 20
23
- /* lock wait step in ms*/
24
- #define AUXPLL_LOCK_WAIT_STEP_MS 1
21
+
22
+ /* Check dt-bindings match MDK frequency division definitions*/
23
+ BUILD_ASSERT (NRF_AUXPLL_FREQ_DIV_MIN == NRF_AUXPLL_FREQUENCY_DIV_MIN ,
24
+ "Different AUXPLL_FREQ_DIV_MIN definition in MDK and devicetree binding" );
25
+ BUILD_ASSERT (NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 == NRF_AUXPLL_FREQUENCY_AUDIO_44K1 ,
26
+ "Different AUXPLL_FREQ_DIV_AUDIO_44K1 definition in MDK and devicetree binding" );
27
+ BUILD_ASSERT (NRF_AUXPLL_FREQ_DIV_USB24M == NRF_AUXPLL_FREQUENCY_USB_24M ,
28
+ "Different AUXPLL_FREQ_DIV_USB24M definition in MDK and devicetree binding" );
29
+ BUILD_ASSERT (NRF_AUXPLL_FREQ_DIV_AUDIO_48K == NRF_AUXPLL_FREQUENCY_AUDIO_48K ,
30
+ "Different AUXPLL_FREQ_DIV_AUDIO_48K definition in MDK and devicetree binding" );
31
+ BUILD_ASSERT (NRF_AUXPLL_FREQ_DIV_MAX == NRF_AUXPLL_FREQUENCY_DIV_MAX ,
32
+ "Different AUXPLL_FREQ_DIV_MAX definition in MDK and devicetree binding" );
33
+
34
+ /* maximum lock time in us, >10x time observed experimentally */
35
+ #define AUXPLL_LOCK_TIME_MAX_US 20000
36
+ /* lock wait step in us*/
37
+ #define AUXPLL_LOCK_WAIT_STEP_US 1000
38
+
39
+ struct dev_data_auxpll {
40
+ struct onoff_manager mgr ;
41
+ onoff_notify_fn notify ;
42
+ const struct device * dev ;
43
+ };
25
44
26
45
struct clock_control_nrf_auxpll_config {
27
46
NRF_AUXPLL_Type * auxpll ;
28
47
uint32_t ref_clk_hz ;
29
48
uint32_t ficr_ctune ;
30
49
nrf_auxpll_config_t cfg ;
31
- uint16_t frequency ;
50
+ nrf_auxpll_freq_div_ratio_t frequency ;
32
51
nrf_auxpll_ctrl_outsel_t out_div ;
33
52
};
34
53
35
- static int clock_control_nrf_auxpll_on (const struct device * dev , clock_control_subsys_t sys )
54
+ static int clock_control_nrf_auxpll_on (struct dev_data_auxpll * dev_data )
36
55
{
37
- const struct clock_control_nrf_auxpll_config * config = dev -> config ;
56
+ const struct clock_control_nrf_auxpll_config * config = dev_data -> dev -> config ;
38
57
bool locked ;
39
- unsigned int wait = 0U ;
40
-
41
- ARG_UNUSED (sys );
42
58
43
59
nrf_auxpll_task_trigger (config -> auxpll , NRF_AUXPLL_TASK_START );
44
60
45
- do {
46
- locked = nrf_auxpll_mode_locked_check (config -> auxpll );
47
- if (!locked ) {
48
- k_msleep (AUXPLL_LOCK_WAIT_STEP_MS );
49
- wait += AUXPLL_LOCK_WAIT_STEP_MS ;
50
- }
51
- } while (wait < AUXPLL_LOCK_TIME_MAX_MS && !locked );
61
+ NRFX_WAIT_FOR (nrf_auxpll_mode_locked_check (config -> auxpll ),
62
+ AUXPLL_LOCK_TIME_MAX_US / AUXPLL_LOCK_WAIT_STEP_US ,
63
+ AUXPLL_LOCK_WAIT_STEP_US , locked );
52
64
53
65
return locked ? 0 : - ETIMEDOUT ;
54
66
}
55
67
56
- static int clock_control_nrf_auxpll_off (const struct device * dev , clock_control_subsys_t sys )
68
+ static int clock_control_nrf_auxpll_off (struct dev_data_auxpll * dev_data )
57
69
{
58
- const struct clock_control_nrf_auxpll_config * config = dev -> config ;
59
-
60
- ARG_UNUSED (sys );
70
+ const struct clock_control_nrf_auxpll_config * config = dev_data -> dev -> config ;
61
71
62
72
nrf_auxpll_task_trigger (config -> auxpll , NRF_AUXPLL_TASK_STOP );
63
73
@@ -67,6 +77,58 @@ static int clock_control_nrf_auxpll_off(const struct device *dev, clock_control_
67
77
return 0 ;
68
78
}
69
79
80
+ static void onoff_start_auxpll (struct onoff_manager * mgr , onoff_notify_fn notify )
81
+ {
82
+ struct dev_data_auxpll * dev_data =
83
+ CONTAINER_OF (mgr , struct dev_data_auxpll , mgr );
84
+
85
+ int ret = clock_control_nrf_auxpll_on (dev_data );
86
+
87
+ notify (& dev_data -> mgr , ret );
88
+
89
+ }
90
+
91
+ static void onoff_stop_auxpll (struct onoff_manager * mgr , onoff_notify_fn notify )
92
+ {
93
+ struct dev_data_auxpll * dev_data =
94
+ CONTAINER_OF (mgr , struct dev_data_auxpll , mgr );
95
+
96
+ clock_control_nrf_auxpll_off (dev_data );
97
+ notify (mgr , 0 );
98
+ }
99
+
100
+ static int api_request_auxpll (const struct device * dev ,
101
+ const struct nrf_clock_spec * spec ,
102
+ struct onoff_client * cli )
103
+ {
104
+ struct dev_data_auxpll * dev_data = dev -> data ;
105
+
106
+ ARG_UNUSED (spec );
107
+
108
+ return onoff_request (& dev_data -> mgr , cli );
109
+ }
110
+
111
+ static int api_release_auxpll (const struct device * dev ,
112
+ const struct nrf_clock_spec * spec )
113
+ {
114
+ struct dev_data_auxpll * dev_data = dev -> data ;
115
+
116
+ ARG_UNUSED (spec );
117
+
118
+ return onoff_release (& dev_data -> mgr );
119
+ }
120
+
121
+ static int api_cancel_or_release_auxpll (const struct device * dev ,
122
+ const struct nrf_clock_spec * spec ,
123
+ struct onoff_client * cli )
124
+ {
125
+ struct dev_data_auxpll * dev_data = dev -> data ;
126
+
127
+ ARG_UNUSED (spec );
128
+
129
+ return onoff_cancel_or_release (& dev_data -> mgr , cli );
130
+ }
131
+
70
132
static int clock_control_nrf_auxpll_get_rate (const struct device * dev , clock_control_subsys_t sys ,
71
133
uint32_t * rate )
72
134
{
@@ -99,16 +161,21 @@ static enum clock_control_status clock_control_nrf_auxpll_get_status(const struc
99
161
return CLOCK_CONTROL_STATUS_OFF ;
100
162
}
101
163
102
- static DEVICE_API (clock_control , clock_control_nrf_auxpll_api ) = {
103
- .on = clock_control_nrf_auxpll_on ,
104
- .off = clock_control_nrf_auxpll_off ,
105
- .get_rate = clock_control_nrf_auxpll_get_rate ,
106
- .get_status = clock_control_nrf_auxpll_get_status ,
164
+ static const struct onoff_transitions transitions = {
165
+ .start = onoff_start_auxpll ,
166
+ .stop = onoff_stop_auxpll
107
167
};
108
168
109
169
static int clock_control_nrf_auxpll_init (const struct device * dev )
110
170
{
171
+ struct dev_data_auxpll * dev_data = dev -> data ;
111
172
const struct clock_control_nrf_auxpll_config * config = dev -> config ;
173
+ int rc ;
174
+
175
+ rc = onoff_manager_init (& dev_data -> mgr , & transitions );
176
+ if (rc < 0 ) {
177
+ return rc ;
178
+ }
112
179
113
180
nrf_auxpll_ctrl_frequency_set (config -> auxpll , config -> frequency );
114
181
@@ -123,7 +190,31 @@ static int clock_control_nrf_auxpll_init(const struct device *dev)
123
190
return 0 ;
124
191
}
125
192
193
+ static DEVICE_API (nrf_clock_control , drv_api_auxpll ) = {
194
+ .std_api = {
195
+ .on = api_nosys_on_off ,
196
+ .off = api_nosys_on_off ,
197
+ .get_rate = clock_control_nrf_auxpll_get_rate ,
198
+ .get_status = clock_control_nrf_auxpll_get_status ,
199
+ },
200
+ .request = api_request_auxpll ,
201
+ .release = api_release_auxpll ,
202
+ .cancel_or_release = api_cancel_or_release_auxpll ,
203
+ };
204
+
126
205
#define CLOCK_CONTROL_NRF_AUXPLL_DEFINE (n ) \
206
+ BUILD_ASSERT( \
207
+ DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_DIV_MIN || \
208
+ DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_AUDIO_44K1 || \
209
+ DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_USB_24M || \
210
+ DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_AUDIO_48K || \
211
+ DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_DIV_MAX, \
212
+ "Invalid nordic,frequency value in DeviceTree for AUXPLL instance " #n); \
213
+ BUILD_ASSERT(DT_INST_PROP(n, nordic_out_div) > 0, \
214
+ "nordic,out_div must be greater than 0 for AUXPLL instance " #n); \
215
+ static struct dev_data_auxpll data_auxpll##n = { \
216
+ .dev = DEVICE_DT_INST_GET(n), \
217
+ }; \
127
218
static const struct clock_control_nrf_auxpll_config config##n = { \
128
219
.auxpll = (NRF_AUXPLL_Type *)DT_INST_REG_ADDR(n), \
129
220
.ref_clk_hz = DT_PROP(DT_INST_CLOCKS_CTLR(n), clock_frequency), \
@@ -140,9 +231,9 @@ static int clock_control_nrf_auxpll_init(const struct device *dev)
140
231
.frequency = DT_INST_PROP(n, nordic_frequency), \
141
232
.out_div = DT_INST_PROP(n, nordic_out_div), \
142
233
}; \
143
- \
144
- DEVICE_DT_INST_DEFINE(n, clock_control_nrf_auxpll_init, NULL, NULL , &config##n, \
234
+ \
235
+ DEVICE_DT_INST_DEFINE(n, clock_control_nrf_auxpll_init, NULL, &data_auxpll##n , &config##n, \
145
236
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \
146
- &clock_control_nrf_auxpll_api );
237
+ &drv_api_auxpll );
147
238
148
239
DT_INST_FOREACH_STATUS_OKAY (CLOCK_CONTROL_NRF_AUXPLL_DEFINE )
0 commit comments