From 0ab319927df6efdf8033843c550df37ee5f9381f Mon Sep 17 00:00:00 2001
From: Michal Gorecki <michal.gorecki@codecoup.pl>
Date: Thu, 11 May 2023 14:39:18 +0200
Subject: [PATCH 1/4] mcu/nrf5340_net: Add API to switch lpclk in the runtime

---
 .../include/mcu/nrf5340_net_clock.h           | 14 +++++
 .../nrf5340_net/src/nrf5340_net_clock.c       | 55 +++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h b/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h
index a87e41e462..ec73db6914 100644
--- a/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h
+++ b/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h
@@ -43,6 +43,20 @@ int nrf5340_net_clock_hfxo_request(void);
  */
 int nrf5340_net_clock_hfxo_release(void);
 
+/**
+ * Request low frequency clock source change.
+ *
+ * @param  clksrc Value to determine requested clock source
+ *                This parameter can be one of the following values:
+ *                @arg CLOCK_LFCLKSTAT_SRC_LFRC - 32.768 kHz RC oscillator
+ *                @arg CLOCK_LFCLKSTAT_SRC_LFXO - 32.768 kHz crystal oscillator
+ *                @arg CLOCK_LFCLKSTAT_SRC_LFSYNT - 32.768 kHz synthesized from HFCLK
+ *
+ * @return int 0: clock source was already as requested. 1: clock source
+ *         changed.
+ */
+int nrf5340_net_set_lf_clock_source(uint32_t clksrc);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c b/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c
index 8a67ec1add..74c97c1f44 100644
--- a/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c
+++ b/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c
@@ -75,3 +75,58 @@ nrf5340_net_clock_hfxo_release(void)
 
     return stopped;
 }
+
+/**
+ * Request low frequency clock source change.
+ *
+ * @return int 0: clock source was already as requested. 1: clock source
+ *         changed.
+ */
+int
+nrf5340_net_set_lf_clock_source(uint32_t clksrc)
+{
+    uint32_t regmsk;
+    uint32_t regval;
+
+    regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk;
+    regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos;
+
+    regval |= clksrc << CLOCK_LFCLKSTAT_SRC_Pos;
+
+    /* Check if this clock source isn't already running */
+    if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) == regval) {
+        return 0;
+    }
+
+    /*
+     * Request HFXO if LFSYNTH is going to be set as source. If LFSYNTH is going to be
+     * replaced with other source, release HFXO.
+     */
+    if (clksrc == CLOCK_LFCLKSTAT_SRC_LFSYNT) {
+        if ((NRF_CLOCK_NS->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) !=
+            (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) {
+            NRF_CLOCK_NS->EVENTS_HFCLKSTARTED = 0;
+            nrf5340_net_clock_hfxo_request();
+            while (!NRF_CLOCK_NS->EVENTS_HFCLKSTARTED) {
+            }
+        } else {
+            nrf5340_net_clock_hfxo_request();
+        }
+    } else if (NRF_CLOCK_NS->LFCLKSRC == CLOCK_LFCLKSTAT_SRC_LFSYNT) {
+        nrf5340_net_clock_hfxo_release();
+    }
+
+    NRF_CLOCK_NS->LFCLKSRC = clksrc;
+    NRF_CLOCK_NS->TASKS_LFCLKSTART = 1;
+
+    /* Wait here till started! */
+    while (1) {
+        if (NRF_CLOCK_NS->EVENTS_LFCLKSTARTED) {
+            if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) == regval) {
+                break;
+            }
+        }
+    }
+
+    return 1;
+}

From f9a2fbfaea6db9fa3e4f0071893857f8bee1f929 Mon Sep 17 00:00:00 2001
From: Michal Gorecki <michal.gorecki@codecoup.pl>
Date: Thu, 11 May 2023 15:05:29 +0200
Subject: [PATCH 2/4] mcu/nrf5340_net: Use Low Frequency Clock source setting
 API in startup

Code from function hal_system_clock_start was moved into new API,
so now we can call that API with proper argument to avoid code
repetition.
---
 hw/mcu/nordic/nrf5340_net/src/hal_system.c | 47 ++--------------------
 1 file changed, 3 insertions(+), 44 deletions(-)

diff --git a/hw/mcu/nordic/nrf5340_net/src/hal_system.c b/hw/mcu/nordic/nrf5340_net/src/hal_system.c
index d7d1f3cb51..947d60fb67 100644
--- a/hw/mcu/nordic/nrf5340_net/src/hal_system.c
+++ b/hw/mcu/nordic/nrf5340_net/src/hal_system.c
@@ -70,57 +70,16 @@ void
 hal_system_clock_start(void)
 {
 #if MYNEWT_VAL(MCU_LFCLK_SOURCE)
-    uint32_t regmsk;
-    uint32_t regval;
-    uint32_t clksrc;
-
-    regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk;
-    regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos;
 
 #if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFXO)
-    regval |= CLOCK_LFCLKSTAT_SRC_LFXO << CLOCK_LFCLKSTAT_SRC_Pos;
-    clksrc = CLOCK_LFCLKSTAT_SRC_LFXO;
+    nrf5340_net_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFXO);
 #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH)
-    regval |= CLOCK_LFCLKSTAT_SRC_LFSYNT << CLOCK_LFCLKSTAT_SRC_Pos;
-    clksrc = CLOCK_LFCLKSTAT_SRC_LFSYNT;
+    nrf5340_net_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFSYNT);
 #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFRC)
-    regval |= CLOCK_LFCLKSTAT_SRC_LFRC << CLOCK_LFCLKSTAT_SRC_Pos;
-    clksrc = CLOCK_LFCLKSTAT_SRC_LFRC;
+    nrf5340_net_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFRC);
 #else
     #error Unknown LFCLK source selected
 #endif
 
-#if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH)
-    /* Must turn on HFLCK for synthesized 32768 crystal */
-    if ((NRF_CLOCK_NS->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) !=
-        (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) {
-        NRF_CLOCK_NS->EVENTS_HFCLKSTARTED = 0;
-        nrf5340_net_clock_hfxo_request();
-        while (1) {
-            if ((NRF_CLOCK_NS->EVENTS_HFCLKSTARTED) != 0) {
-                break;
-            }
-        }
-    } else {
-        nrf5340_net_clock_hfxo_request();
-    }
-#endif
-
-    /* Check if this clock source is already running */
-    if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) != regval) {
-        NRF_CLOCK_NS->TASKS_LFCLKSTOP = 1;
-        NRF_CLOCK_NS->EVENTS_LFCLKSTARTED = 0;
-        NRF_CLOCK_NS->LFCLKSRC = clksrc;
-        NRF_CLOCK_NS->TASKS_LFCLKSTART = 1;
-
-        /* Wait here till started! */
-        while (1) {
-            if (NRF_CLOCK_NS->EVENTS_LFCLKSTARTED) {
-                if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) == regval) {
-                    break;
-                }
-            }
-        }
-    }
 #endif
 }

From 942adc6bf50de082cd985dd76640c9109a7ea65b Mon Sep 17 00:00:00 2001
From: Michal Gorecki <michal.gorecki@codecoup.pl>
Date: Thu, 11 May 2023 16:20:27 +0200
Subject: [PATCH 3/4] mcu/nrf5340: Add API to switch lpclk in the runtime

---
 .../nrf5340/include/mcu/nrf5340_clock.h       | 14 ++++++
 hw/mcu/nordic/nrf5340/src/nrf5340_clock.c     | 49 +++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h b/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h
index 0a69dbaee9..9c623a9723 100644
--- a/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h
+++ b/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h
@@ -43,6 +43,20 @@ int nrf5340_clock_hfxo_request(void);
  */
 int nrf5340_clock_hfxo_release(void);
 
+/**
+ * Request low frequency clock source change.
+ *
+ * @param  clksrc Value to determine requested clock source
+ *                This parameter can be one of the following values:
+ *                @arg CLOCK_LFCLKSTAT_SRC_LFRC - 32.768 kHz RC oscillator
+ *                @arg CLOCK_LFCLKSTAT_SRC_LFXO - 32.768 kHz crystal oscillator
+ *                @arg CLOCK_LFCLKSTAT_SRC_LFSYNT - 32.768 kHz synthesized from HFCLK
+ *
+ * @return int 0: clock source was already as requested. 1: clock source
+ *         changed.
+ */
+int nrf5340_set_lf_clock_source(uint32_t clksrc);
+
 /**
  * Request HFCLK192M clock be turned on. Note that each request must have a
  * corresponding release.
diff --git a/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c b/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c
index 77b7f0bee3..6ad8b67221 100644
--- a/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c
+++ b/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c
@@ -100,3 +100,52 @@ nrf5340_clock_hfclk192m_release(void)
 
     return stopped;
 }
+
+int
+nrf5340_set_lf_clock_source(uint32_t clksrc)
+{
+    uint32_t regmsk;
+    uint32_t regval;
+
+    regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk;
+    regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos;
+
+    regval |= clksrc << CLOCK_LFCLKSTAT_SRC_Pos;
+
+    /* Check if this clock source isn't already running */
+    if ((NRF_CLOCK->LFCLKSTAT & regmsk) == regval) {
+        return 0;
+    }
+
+    /*
+     * Request HFXO if LFSYNTH is going to be set as source. If LFSYNTH is going to be
+     * replaced with other source, release HFXO.
+     */
+    if (clksrc == CLOCK_LFCLKSTAT_SRC_LFSYNT) {
+        if ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) !=
+            (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) {
+            NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+            nrf5340_clock_hfxo_request();
+            while (!NRF_CLOCK->EVENTS_HFCLKSTARTED) {
+            }
+        } else {
+            nrf5340_clock_hfxo_request();
+        }
+    } else if (NRF_CLOCK->LFCLKSRC == CLOCK_LFCLKSTAT_SRC_LFSYNT) {
+        nrf5340_clock_hfxo_release();
+    }
+
+    NRF_CLOCK->LFCLKSRC = clksrc;
+    NRF_CLOCK->TASKS_LFCLKSTART = 1;
+
+    /* Wait here till started! */
+    while (1) {
+        if (NRF_CLOCK->EVENTS_LFCLKSTARTED) {
+            if ((NRF_CLOCK->LFCLKSTAT & regmsk) == regval) {
+                break;
+            }
+        }
+    }
+
+    return 1;
+}
\ No newline at end of file

From 71d8fad72a30c13293946009ef5cd6ae26865d37 Mon Sep 17 00:00:00 2001
From: Michal Gorecki <michal.gorecki@codecoup.pl>
Date: Thu, 11 May 2023 16:22:37 +0200
Subject: [PATCH 4/4] mcu/nrf5340: Use Low Frequency Clock source setting API
 in startup

Code from function hal_system_clock_start was moved into new API,
so now we can call that API with proper argument to avoid code
repetition.
---
 hw/mcu/nordic/nrf5340/src/hal_system.c | 47 ++------------------------
 1 file changed, 3 insertions(+), 44 deletions(-)

diff --git a/hw/mcu/nordic/nrf5340/src/hal_system.c b/hw/mcu/nordic/nrf5340/src/hal_system.c
index 36868c0f90..8f641b7a0f 100644
--- a/hw/mcu/nordic/nrf5340/src/hal_system.c
+++ b/hw/mcu/nordic/nrf5340/src/hal_system.c
@@ -84,12 +84,6 @@ void
 hal_system_clock_start(void)
 {
 #if MYNEWT_VAL(MCU_LFCLK_SOURCE)
-    uint32_t regmsk;
-    uint32_t regval;
-    uint32_t clksrc;
-
-    regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk;
-    regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos;
 
 #if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFXO)
 
@@ -107,50 +101,15 @@ hal_system_clock_start(void)
     NRF_P0->PIN_CNF[0] = GPIO_PIN_CNF_MCUSEL_Peripheral << GPIO_PIN_CNF_MCUSEL_Pos;
     NRF_P0->PIN_CNF[1] = GPIO_PIN_CNF_MCUSEL_Peripheral << GPIO_PIN_CNF_MCUSEL_Pos;
 #endif
-    regval |= CLOCK_LFCLKSTAT_SRC_LFXO << CLOCK_LFCLKSTAT_SRC_Pos;
-    clksrc = CLOCK_LFCLKSTAT_SRC_LFXO;
+    nrf5340_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFXO);
 #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH)
-    regval |= CLOCK_LFCLKSTAT_SRC_LFSYNT << CLOCK_LFCLKSTAT_SRC_Pos;
-    clksrc = CLOCK_LFCLKSTAT_SRC_LFSYNT;
+    nrf5340_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFSYNT);
 #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFRC)
-    regval |= CLOCK_LFCLKSTAT_SRC_LFRC << CLOCK_LFCLKSTAT_SRC_Pos;
-    clksrc = CLOCK_LFCLKSTAT_SRC_LFRC;
+    nrf5340_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFRC);
 #else
     #error Unknown LFCLK source selected
 #endif
 
-#if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH)
-    /* Must turn on HFLCK for synthesized 32768 crystal */
-    if ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) !=
-        (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) {
-        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
-        nrf5340_clock_hfxo_request();
-        while (1) {
-            if ((NRF_CLOCK->EVENTS_HFCLKSTARTED) != 0) {
-                break;
-            }
-        }
-    } else {
-        nrf5340_clock_hfxo_request();
-    }
-#endif
-
-    /* Check if this clock source is already running */
-    if ((NRF_CLOCK->LFCLKSTAT & regmsk) != regval) {
-        NRF_CLOCK->TASKS_LFCLKSTOP = 1;
-        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
-        NRF_CLOCK->LFCLKSRC = clksrc;
-        NRF_CLOCK->TASKS_LFCLKSTART = 1;
-
-        /* Wait here till started! */
-        while (1) {
-            if (NRF_CLOCK->EVENTS_LFCLKSTARTED) {
-                if ((NRF_CLOCK->LFCLKSTAT & regmsk) == regval) {
-                    break;
-                }
-            }
-        }
-    }
 #endif
     if (MYNEWT_VAL(MCU_HFCLCK192_DIV) == 1) {
         NRF_CLOCK->HFCLK192MCTRL = 0;