1 /*
2  * Copyright (c) 2020 - 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <nrf_802154_config.h>
8 #include <platform/nrf_802154_clock.h>
9 
10 #include <stddef.h>
11 
12 #include <compiler_abstraction.h>
13 #include <zephyr/kernel.h>
14 #if defined(CONFIG_CLOCK_CONTROL_NRF)
15 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
16 #include <zephyr/drivers/clock_control.h>
17 #elif !defined(NRF54H_SERIES)
18 #error No implementation to start or stop HFCLK due to missing clock_control.
19 #endif
20 
21 static bool hfclk_is_running;
22 
nrf_802154_clock_init(void)23 void nrf_802154_clock_init(void)
24 {
25 	/* Intentionally empty. */
26 }
27 
nrf_802154_clock_deinit(void)28 void nrf_802154_clock_deinit(void)
29 {
30 	/* Intentionally empty. */
31 }
32 
nrf_802154_clock_hfclk_is_running(void)33 bool nrf_802154_clock_hfclk_is_running(void)
34 {
35 	return hfclk_is_running;
36 }
37 
38 #if defined(CONFIG_CLOCK_CONTROL_NRF)
39 
40 static struct onoff_client hfclk_cli;
41 
hfclk_on_callback(struct onoff_manager * mgr,struct onoff_client * cli,uint32_t state,int res)42 static void hfclk_on_callback(struct onoff_manager *mgr,
43 			      struct onoff_client  *cli,
44 			      uint32_t state,
45 			      int res)
46 {
47 	hfclk_is_running = true;
48 	nrf_802154_clock_hfclk_ready();
49 }
50 
nrf_802154_clock_hfclk_start(void)51 void nrf_802154_clock_hfclk_start(void)
52 {
53 	int ret;
54 	struct onoff_manager *mgr =
55 		z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
56 
57 	__ASSERT_NO_MSG(mgr != NULL);
58 
59 	sys_notify_init_callback(&hfclk_cli.notify, hfclk_on_callback);
60 
61 	ret = onoff_request(mgr, &hfclk_cli);
62 	__ASSERT_NO_MSG(ret >= 0);
63 }
64 
nrf_802154_clock_hfclk_stop(void)65 void nrf_802154_clock_hfclk_stop(void)
66 {
67 	int ret;
68 	struct onoff_manager *mgr =
69 		z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
70 
71 	__ASSERT_NO_MSG(mgr != NULL);
72 
73 	ret = onoff_cancel_or_release(mgr, &hfclk_cli);
74 	__ASSERT_NO_MSG(ret >= 0);
75 	hfclk_is_running = false;
76 }
77 
78 #elif defined(NRF54H_SERIES)
79 
80 #define NRF_LRCCONF_RADIO_PD NRF_LRCCONF010
81 /* HF clock time to ramp-up. */
82 #define MAX_HFXO_RAMP_UP_TIME_US 550
83 
hfclk_started_timer_handler(struct k_timer * dummy)84 static void hfclk_started_timer_handler(struct k_timer *dummy)
85 {
86 	hfclk_is_running = true;
87 	nrf_802154_clock_hfclk_ready();
88 }
89 
90 K_TIMER_DEFINE(hfclk_started_timer, hfclk_started_timer_handler, NULL);
91 
nrf_802154_clock_hfclk_start(void)92 void nrf_802154_clock_hfclk_start(void)
93 {
94 	/* Use register directly, there is no support for that task in nrf_lrcconf_task_trigger.
95 	 * This code might cause troubles if there are other HFXO users in this CPU.
96 	 */
97 	NRF_LRCCONF_RADIO_PD->EVENTS_HFXOSTARTED = 0x0;
98 	NRF_LRCCONF_RADIO_PD->TASKS_REQHFXO = 0x1;
99 
100 	k_timer_start(&hfclk_started_timer, K_USEC(MAX_HFXO_RAMP_UP_TIME_US), K_NO_WAIT);
101 }
102 
nrf_802154_clock_hfclk_stop(void)103 void nrf_802154_clock_hfclk_stop(void)
104 {
105 	/* Use register directly, there is no support for that task in nrf_lrcconf_task_trigger.
106 	 * This code might cause troubles if there are other HFXO users in this CPU.
107 	 */
108 	NRF_LRCCONF_RADIO_PD->TASKS_STOPREQHFXO = 0x1;
109 	NRF_LRCCONF_RADIO_PD->EVENTS_HFXOSTARTED = 0x0;
110 
111 	hfclk_is_running = false;
112 }
113 
114 #endif
115