Contiki-NG
Loading...
Searching...
No Matches
nrf_802154_platform_clock.c
1/*
2 * Copyright (c) 2026, RISE Research Institutes of Sweden AB
3 * All rights reserved.
4 *
5 * Author: Joakim Eriksson <joakim.eriksson@ri.se>
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * Clock Abstraction Layer for nrf_802154 on nRF54L15.
10 *
11 * On nRF54L15 the HFXO is started via TASKS_XOSTART (not TASKS_HFCLKSTART
12 * as on nRF52). The PLL must also be started explicitly after the HFXO
13 * (MLTPAN-20 workaround) for the radio to function correctly.
14 * LFCLK is controlled through the CLOCK peripheral as usual.
15 */
16
17#include "platform/nrf_802154_clock.h"
18#include "nrf.h"
19#include <stdbool.h>
20
21static volatile bool hfclk_running;
22static volatile bool lfclk_running;
23/*---------------------------------------------------------------------------*/
24static void
25set_constant_latency(bool enable)
26{
27#if defined(POWER_TASKS_CONSTLAT_TASKS_CONSTLAT_Msk) && defined(POWER_TASKS_LOWPWR_TASKS_LOWPWR_Msk)
28 if(enable) {
29 NRF_POWER->TASKS_CONSTLAT = POWER_TASKS_CONSTLAT_TASKS_CONSTLAT_Trigger;
30 } else {
31 NRF_POWER->TASKS_LOWPWR = POWER_TASKS_LOWPWR_TASKS_LOWPWR_Trigger;
32 }
33#else
34 (void)enable;
35#endif
36}
37/*---------------------------------------------------------------------------*/
38void
39nrf_802154_clock_init(void)
40{
41 lfclk_running = true; /* LFCLK already started by clock-arch.c */
42 set_constant_latency(false);
43
44 /* Pre-start HFXO + PLL while interrupts are still enabled, so the
45 * GRTC clock tick ISR keeps running during the busy-wait. */
46 NRF_CLOCK->EVENTS_XOSTARTED = 0;
47 NRF_CLOCK->TASKS_XOSTART = 1;
48 while(NRF_CLOCK->EVENTS_XOSTARTED == 0) {
49 }
50 NRF_CLOCK->EVENTS_XOSTARTED = 0;
51
52 NRF_CLOCK->EVENTS_PLLSTARTED = 0;
53 NRF_CLOCK->TASKS_PLLSTART = 1;
54 while(NRF_CLOCK->EVENTS_PLLSTARTED == 0) {
55 }
56 NRF_CLOCK->EVENTS_PLLSTARTED = 0;
57
58 hfclk_running = true;
59}
60/*---------------------------------------------------------------------------*/
61void
62nrf_802154_clock_deinit(void)
63{
64 /* Nothing to do. */
65}
66/*---------------------------------------------------------------------------*/
67void
68nrf_802154_clock_hfclk_start(void)
69{
70 /*
71 * HFXO+PLL are pre-started in nrf_802154_clock_init() so this is always
72 * a fast path. The radio library calls this from a critical section
73 * (interrupts disabled), so we must not busy-wait here.
74 */
75 if(!hfclk_running) {
76 /* Emergency start — should not happen if init was called. */
77 NRF_CLOCK->EVENTS_XOSTARTED = 0;
78 NRF_CLOCK->TASKS_XOSTART = 1;
79 while(NRF_CLOCK->EVENTS_XOSTARTED == 0) {
80 }
81 NRF_CLOCK->EVENTS_XOSTARTED = 0;
82
83 NRF_CLOCK->EVENTS_PLLSTARTED = 0;
84 NRF_CLOCK->TASKS_PLLSTART = 1;
85 while(NRF_CLOCK->EVENTS_PLLSTARTED == 0) {
86 }
87 NRF_CLOCK->EVENTS_PLLSTARTED = 0;
88
89 hfclk_running = true;
90 }
91 set_constant_latency(true);
92 nrf_802154_clock_hfclk_ready();
93}
94/*---------------------------------------------------------------------------*/
95void
96nrf_802154_clock_hfclk_stop(void)
97{
98 /* Keep HFXO+PLL always running — stopping them on nRF54L15 can disrupt
99 * the GRTC syscounter that Contiki-NG uses for clock ticks. */
100 set_constant_latency(false);
101}
102/*---------------------------------------------------------------------------*/
103bool
104nrf_802154_clock_hfclk_is_running(void)
105{
106 return hfclk_running;
107}
108/*---------------------------------------------------------------------------*/
109void
110nrf_802154_clock_lfclk_start(void)
111{
112 /* LFCLK is already started by clock-arch.c via nrfx_clock_lfclk_start().
113 * Do NOT touch the CLOCK peripheral registers again — on nRF54L15 this
114 * can interfere with the GRTC syscounter. */
115 lfclk_running = true;
116 nrf_802154_clock_lfclk_ready();
117}
118/*---------------------------------------------------------------------------*/
119void
120nrf_802154_clock_lfclk_stop(void)
121{
122 /* Never stop LFCLK — GRTC depends on it. */
123}
124/*---------------------------------------------------------------------------*/
125bool
126nrf_802154_clock_lfclk_is_running(void)
127{
128 return lfclk_running;
129}
130/*---------------------------------------------------------------------------*/