11/*
2- * Copyright (c) 2024 Nordic Semiconductor ASA
2+ * Copyright (c) 2025 Nordic Semiconductor ASA
33 * SPDX-License-Identifier: Apache-2.0
44 */
55
99#include <stdint.h>
1010
1111#include <zephyr/arch/cpu.h>
12- #include <zephyr/device.h>
1312#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>
1614#include <zephyr/sys/util.h>
1715#include <zephyr/toolchain.h>
16+ #include <zephyr/dt-bindings/clock/nrf-auxpll.h>
17+ #include "clock_control_nrf2_common.h"
1818
1919#include <hal/nrf_auxpll.h>
2020
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+ };
2544
2645struct clock_control_nrf_auxpll_config {
2746 NRF_AUXPLL_Type * auxpll ;
2847 uint32_t ref_clk_hz ;
2948 uint32_t ficr_ctune ;
3049 nrf_auxpll_config_t cfg ;
31- uint16_t frequency ;
50+ nrf_auxpll_freq_div_ratio_t frequency ;
3251 nrf_auxpll_ctrl_outsel_t out_div ;
3352};
3453
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 )
3655{
37- const struct clock_control_nrf_auxpll_config * config = dev -> config ;
56+ const struct clock_control_nrf_auxpll_config * config = dev_data -> dev -> config ;
3857 bool locked ;
39- unsigned int wait = 0U ;
40-
41- ARG_UNUSED (sys );
4258
4359 nrf_auxpll_task_trigger (config -> auxpll , NRF_AUXPLL_TASK_START );
4460
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 );
5264
5365 return locked ? 0 : - ETIMEDOUT ;
5466}
5567
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 )
5769{
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 ;
6171
6272 nrf_auxpll_task_trigger (config -> auxpll , NRF_AUXPLL_TASK_STOP );
6373
@@ -67,6 +77,58 @@ static int clock_control_nrf_auxpll_off(const struct device *dev, clock_control_
6777 return 0 ;
6878}
6979
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+
70132static int clock_control_nrf_auxpll_get_rate (const struct device * dev , clock_control_subsys_t sys ,
71133 uint32_t * rate )
72134{
@@ -99,16 +161,21 @@ static enum clock_control_status clock_control_nrf_auxpll_get_status(const struc
99161 return CLOCK_CONTROL_STATUS_OFF ;
100162}
101163
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
107167};
108168
109169static int clock_control_nrf_auxpll_init (const struct device * dev )
110170{
171+ struct dev_data_auxpll * dev_data = dev -> data ;
111172 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+ }
112179
113180 nrf_auxpll_ctrl_frequency_set (config -> auxpll , config -> frequency );
114181
@@ -123,7 +190,31 @@ static int clock_control_nrf_auxpll_init(const struct device *dev)
123190 return 0 ;
124191}
125192
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+
126205#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+ }; \
127218 static const struct clock_control_nrf_auxpll_config config##n = { \
128219 .auxpll = (NRF_AUXPLL_Type *)DT_INST_REG_ADDR(n), \
129220 .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)
140231 .frequency = DT_INST_PROP(n, nordic_frequency), \
141232 .out_div = DT_INST_PROP(n, nordic_out_div), \
142233 }; \
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, \
145236 PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \
146- &clock_control_nrf_auxpll_api );
237+ &drv_api_auxpll );
147238
148239DT_INST_FOREACH_STATUS_OKAY (CLOCK_CONTROL_NRF_AUXPLL_DEFINE )
0 commit comments