drivers: clock_control: smartbond: Add calibration

RCX and RC32K oscillators are not precisely trimmed.
This code allows to measure actual frequency of those two
oscillators.

Device tree binding were extended to specify calibration
interval. This interval (in seconds) is used to periodically
call work that will perform oscillator frequency measurement.

For XTAL32K settle time can be provided in device tree.
After this time (depending on actual oscillator used)
XTAL32K is assumed to be stable and low power clock driven by
XTAL32K is considered OK for precise usage in bluetooth.

Signed-off-by: Jerzy Kasenberg <jerzy.kasenberg@codecoup.pl>
This commit is contained in:
Jerzy Kasenberg 2023-04-19 15:21:54 +02:00 committed by Carles Cufí
parent d5edbba89f
commit 7a9744e169
2 changed files with 358 additions and 64 deletions

View file

@ -8,6 +8,7 @@
#include <soc.h>
#include <zephyr/sys/onoff.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/smartbond_clock_control.h>
#include <zephyr/logging/log.h>
#include <da1469x_clock.h>
@ -15,31 +16,125 @@ LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
#define DT_DRV_COMPAT smartbond_clock
struct lpc_clock_state {
uint8_t rcx_started : 1;
uint8_t rcx_ready : 1;
uint8_t rc32k_started : 1;
uint8_t rc32k_ready : 1;
uint8_t xtal32k_started : 1;
uint8_t xtal32k_ready : 1;
uint32_t rcx_freq;
uint32_t rc32k_freq;
} lpc_clock_state = {
.rcx_freq = DT_PROP(DT_NODELABEL(rcx), clock_frequency),
.rc32k_freq = DT_PROP(DT_NODELABEL(rc32k), clock_frequency),
};
#define CALIBRATION_INTERVAL (DT_NODE_HAS_STATUS(DT_NODELABEL(rcx), okay) ? \
DT_PROP(DT_NODELABEL(rcx), calibration_interval) : \
DT_PROP(DT_NODELABEL(rc32k), calibration_interval))
static void calibration_work_cb(struct k_work *work);
static void xtal32k_settle_work_cb(struct k_work *work);
static K_WORK_DELAYABLE_DEFINE(calibration_work, calibration_work_cb);
static K_WORK_DELAYABLE_DEFINE(xtal32k_settle_work, xtal32k_settle_work_cb);
static void calibration_work_cb(struct k_work *work)
{
if (lpc_clock_state.rcx_started) {
da1469x_clock_lp_rcx_calibrate();
lpc_clock_state.rcx_ready = true;
lpc_clock_state.rcx_freq = da1469x_clock_lp_rcx_freq_get();
k_work_schedule(&calibration_work,
K_MSEC(1000 * CALIBRATION_INTERVAL));
LOG_DBG("RCX calibration done, RCX freq: %d",
(int)lpc_clock_state.rcx_freq);
} else if (lpc_clock_state.rc32k_started) {
da1469x_clock_lp_rc32k_calibrate();
lpc_clock_state.rc32k_ready = true;
lpc_clock_state.rc32k_freq = da1469x_clock_lp_rc32k_freq_get();
k_work_schedule(&calibration_work,
K_MSEC(1000 * CALIBRATION_INTERVAL));
LOG_DBG("RC32K calibration done, RC32K freq: %d",
(int)lpc_clock_state.rc32k_freq);
}
}
static void xtal32k_settle_work_cb(struct k_work *work)
{
if (lpc_clock_state.xtal32k_started && !lpc_clock_state.xtal32k_ready) {
LOG_DBG("XTAL32K settled.");
lpc_clock_state.xtal32k_ready = true;
}
}
static void smartbond_start_rc32k(void)
{
if ((CRG_TOP->CLK_RC32K_REG & CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk) == 0) {
CRG_TOP->CLK_RC32K_REG |= CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk;
lpc_clock_state.rc32k_started = true;
}
if (!lpc_clock_state.rc32k_ready && (CALIBRATION_INTERVAL > 0)) {
if (!k_work_is_pending(&calibration_work.work)) {
k_work_schedule(&calibration_work,
K_MSEC(1000 * CALIBRATION_INTERVAL));
}
}
}
static void smartbond_start_rcx(void)
{
if (!lpc_clock_state.rcx_started) {
lpc_clock_state.rcx_ready = false;
da1469x_clock_lp_rcx_enable();
lpc_clock_state.rcx_started = true;
}
if (!lpc_clock_state.rcx_ready && (CALIBRATION_INTERVAL > 0)) {
if (!k_work_is_pending(&calibration_work.work)) {
k_work_schedule(&calibration_work,
K_MSEC(1000 * CALIBRATION_INTERVAL));
}
}
}
static void smartbond_start_xtal32k(void)
{
if (!lpc_clock_state.xtal32k_started) {
lpc_clock_state.xtal32k_ready = false;
da1469x_clock_lp_xtal32k_enable();
lpc_clock_state.xtal32k_started = true;
k_work_schedule(&xtal32k_settle_work,
K_MSEC(DT_PROP(DT_NODELABEL(xtal32k),
settle_time)));
}
}
static inline int smartbond_clock_control_on(const struct device *dev,
clock_control_subsys_t sub_system)
{
const uint32_t *clk = (const uint32_t *)(sub_system);
enum smartbond_clock clk = (enum smartbond_clock)(sub_system);
ARG_UNUSED(dev);
switch (*clk) {
case DT_DEP_ORD(DT_NODELABEL(rc32k)):
CRG_TOP->CLK_RC32K_REG |= CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk;
switch (clk) {
case SMARTBOND_CLK_RC32K:
smartbond_start_rc32k();
break;
case DT_DEP_ORD(DT_NODELABEL(rcx)):
da1469x_clock_lp_rcx_enable();
case SMARTBOND_CLK_RCX:
smartbond_start_rcx();
break;
case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
da1469x_clock_lp_xtal32k_enable();
case SMARTBOND_CLK_XTAL32K:
smartbond_start_xtal32k();
break;
case DT_DEP_ORD(DT_NODELABEL(rc32m)):
case SMARTBOND_CLK_RC32M:
CRG_TOP->CLK_RC32M_REG |= CRG_TOP_CLK_RC32M_REG_RC32M_ENABLE_Msk;
break;
case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
case SMARTBOND_CLK_XTAL32M:
da1469x_clock_sys_xtal32m_init();
da1469x_clock_sys_xtal32m_enable();
break;
case DT_DEP_ORD(DT_NODELABEL(pll)):
case SMARTBOND_CLK_PLL96M:
if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_PLL96M_Msk) == 0) {
if ((CRG_TOP->CLK_CTRL_REG &
CRG_TOP_CLK_CTRL_REG_RUNNING_AT_XTAL32M_Msk) == 0) {
@ -60,40 +155,46 @@ static inline int smartbond_clock_control_on(const struct device *dev,
static inline int smartbond_clock_control_off(const struct device *dev,
clock_control_subsys_t sub_system)
{
const uint32_t *clk = (const uint32_t *)(sub_system);
enum smartbond_clock clk = (enum smartbond_clock)(sub_system);
ARG_UNUSED(dev);
switch (*clk) {
case DT_DEP_ORD(DT_NODELABEL(rc32k)):
switch (clk) {
case SMARTBOND_CLK_RC32K:
if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) != 0) {
CRG_TOP->CLK_RC32K_REG &= ~CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk;
lpc_clock_state.rc32k_ready = false;
lpc_clock_state.rc32k_started = false;
}
break;
case DT_DEP_ORD(DT_NODELABEL(rcx)):
case SMARTBOND_CLK_RCX:
if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) != 1) {
CRG_TOP->CLK_RCX_REG &= ~CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk;
lpc_clock_state.rcx_ready = false;
lpc_clock_state.rcx_started = false;
}
break;
case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
case SMARTBOND_CLK_XTAL32K:
if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) > 1) {
CRG_TOP->CLK_XTAL32K_REG &= ~CRG_TOP_CLK_XTAL32K_REG_XTAL32K_ENABLE_Msk;
lpc_clock_state.xtal32k_ready = false;
lpc_clock_state.xtal32k_started = false;
}
break;
case DT_DEP_ORD(DT_NODELABEL(rc32m)):
case SMARTBOND_CLK_RC32M:
/* Disable rc32m only if not used as system clock */
if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_RC32M_Msk) == 0) {
da1469x_clock_sys_rc32m_disable();
}
break;
case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
case SMARTBOND_CLK_XTAL32M:
da1469x_clock_sys_xtal32m_init();
da1469x_clock_sys_xtal32m_enable();
break;
case DT_DEP_ORD(DT_NODELABEL(pll)):
case SMARTBOND_CLK_PLL96M:
da1469x_clock_sys_pll_disable();
break;
default:
@ -103,29 +204,54 @@ static inline int smartbond_clock_control_off(const struct device *dev,
return 0;
}
static int smartbond_clock_control_get_rate(const struct device *dev,
clock_control_subsys_t sub_system,
uint32_t *rate)
static enum smartbond_clock smartbond_source_clock(enum smartbond_clock clk)
{
const uint32_t *clk = (const uint32_t *)(sub_system);
static const enum smartbond_clock lp_clk_src[] = {
SMARTBOND_CLK_RC32K,
SMARTBOND_CLK_RCX,
SMARTBOND_CLK_XTAL32K,
SMARTBOND_CLK_XTAL32K,
};
static const enum smartbond_clock sys_clk_src[] = {
SMARTBOND_CLK_XTAL32M,
SMARTBOND_CLK_RC32M,
SMARTBOND_CLK_LP_CLK,
SMARTBOND_CLK_PLL96M,
};
switch (*clk) {
case DT_DEP_ORD(DT_NODELABEL(rc32k)):
*rate = da1469x_clock_lp_rc32m_freq_get();
if (clk == SMARTBOND_CLK_SYS_CLK) {
clk = sys_clk_src[CRG_TOP->CLK_CTRL_REG &
CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk];
}
/* System clock can be low power clock, so next check is not in else */
if (clk == SMARTBOND_CLK_LP_CLK) {
clk = lp_clk_src[(CRG_TOP->CLK_CTRL_REG &
CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >>
CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos];
}
return clk;
}
static int smartbond_clock_get_rate(enum smartbond_clock clk, uint32_t *rate)
{
clk = smartbond_source_clock(clk);
switch (clk) {
case SMARTBOND_CLK_RC32K:
*rate = lpc_clock_state.rc32k_freq;
break;
case DT_DEP_ORD(DT_NODELABEL(rcx)):
*rate = da1469x_clock_lp_rcx_freq_get();
case SMARTBOND_CLK_RCX:
*rate = lpc_clock_state.rcx_freq;
break;
case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
case SMARTBOND_CLK_XTAL32K:
*rate = DT_PROP(DT_NODELABEL(xtal32k), clock_frequency);
break;
case DT_DEP_ORD(DT_NODELABEL(rc32m)):
case SMARTBOND_CLK_RC32M:
*rate = DT_PROP(DT_NODELABEL(rc32m), clock_frequency);
break;
case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
case SMARTBOND_CLK_XTAL32M:
*rate = DT_PROP(DT_NODELABEL(xtal32m), clock_frequency);
break;
case DT_DEP_ORD(DT_NODELABEL(pll)):
case SMARTBOND_CLK_PLL96M:
*rate = DT_PROP(DT_NODELABEL(pll), clock_frequency);
break;
default:
@ -134,16 +260,146 @@ static int smartbond_clock_control_get_rate(const struct device *dev,
return 0;
}
static int smartbond_clock_control_get_rate(const struct device *dev,
clock_control_subsys_t sub_system,
uint32_t *rate)
{
ARG_UNUSED(dev);
return smartbond_clock_get_rate((enum smartbond_clock)(sub_system), rate);
}
static enum smartbond_clock smartbond_dt_ord_to_clock(uint32_t dt_ord)
{
switch (dt_ord) {
case DT_DEP_ORD(DT_NODELABEL(rc32k)):
return SMARTBOND_CLK_RC32K;
case DT_DEP_ORD(DT_NODELABEL(rcx)):
return SMARTBOND_CLK_RCX;
case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
return SMARTBOND_CLK_XTAL32K;
case DT_DEP_ORD(DT_NODELABEL(rc32m)):
return SMARTBOND_CLK_RC32M;
case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
return SMARTBOND_CLK_XTAL32M;
case DT_DEP_ORD(DT_NODELABEL(pll)):
return SMARTBOND_CLK_PLL96M;
default:
return SMARTBOND_CLK_NONE;
}
}
static void smartbond_clock_control_on_by_ord(const struct device *dev,
uint32_t clock_id)
{
smartbond_clock_control_on(dev, &clock_id);
enum smartbond_clock clk = smartbond_dt_ord_to_clock(clock_id);
smartbond_clock_control_on(dev, (clock_control_subsys_rate_t)clk);
}
static void smartbond_clock_control_off_by_ord(const struct device *dev,
uint32_t clock_id)
{
smartbond_clock_control_off(dev, &clock_id);
enum smartbond_clock clk = smartbond_dt_ord_to_clock(clock_id);
smartbond_clock_control_off(dev, (clock_control_subsys_rate_t)clk);
}
static void
qspi_set_read_pipe_delay(uint8_t delay)
{
QSPIC->QSPIC_CTRLMODE_REG =
(QSPIC->QSPIC_CTRLMODE_REG & ~QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Msk) |
(delay << QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Pos) |
QSPIC_QSPIC_CTRLMODE_REG_QSPIC_RPIPE_EN_Msk;
}
static void
qspi_set_cs_delay(uint32_t sys_clock_freq, uint32_t read_delay_ns, uint32_t erase_delay_ns)
{
sys_clock_freq /= 100000;
uint32_t read_delay_cyc = ((read_delay_ns * sys_clock_freq) + 9999) / 10000;
uint32_t erase_delay_cyc = ((erase_delay_ns * sys_clock_freq) + 9999) / 10000;
QSPIC->QSPIC_BURSTCMDB_REG =
(QSPIC->QSPIC_BURSTCMDB_REG & ~QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Msk) |
read_delay_cyc << QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Pos;
QSPIC->QSPIC_ERASECMDB_REG =
(QSPIC->QSPIC_ERASECMDB_REG & ~QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Msk) |
(erase_delay_cyc << QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Pos);
}
int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk)
{
int rc = 0;
uint32_t clk_sel = 0;
uint32_t clk_sel_msk = CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk;
switch (lp_clk) {
case SMARTBOND_CLK_RC32K:
clk_sel = 0;
break;
case SMARTBOND_CLK_RCX:
clk_sel = 1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos;
break;
case SMARTBOND_CLK_XTAL32K:
clk_sel = 2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos;
break;
default:
rc = -EINVAL;
}
if (rc == 0) {
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel;
}
return rc;
}
int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk)
{
uint32_t sys_clock_freq;
uint32_t clk_sel;
uint32_t clk_sel_msk = CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk;
int res;
res = smartbond_clock_get_rate(sys_clk, &sys_clock_freq);
if (res != 0) {
return -EINVAL;
}
/* When PLL is selected as system clock qspi read pipe delay must be set to 7 */
if (sys_clock_freq > 32000000) {
qspi_set_read_pipe_delay(7);
qspi_set_cs_delay(SystemCoreClock,
DT_PROP(DT_NODELABEL(flash_controller),
read_cs_idle_delay),
DT_PROP(DT_NODELABEL(flash_controller),
erase_cs_idle_delay));
}
if (sys_clk == SMARTBOND_CLK_RC32M) {
clk_sel = 1 << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos;
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel;
SystemCoreClock = sys_clock_freq;
} else if (sys_clk == SMARTBOND_CLK_PLL96M) {
da1469x_clock_pll_wait_to_lock();
da1469x_clock_sys_pll_switch();
} else if (sys_clk == SMARTBOND_CLK_XTAL32M) {
da1469x_clock_sys_xtal32m_switch_safe();
}
/* When switching back from PLL to 32MHz read pipe delay may be set to 2 */
if (SystemCoreClock <= 32000000) {
qspi_set_read_pipe_delay(2);
qspi_set_cs_delay(SystemCoreClock,
DT_PROP(DT_NODELABEL(flash_controller),
read_cs_idle_delay),
DT_PROP(DT_NODELABEL(flash_controller),
erase_cs_idle_delay));
}
return 0;
}
/**
@ -158,9 +414,11 @@ static void smartbond_clock_control_off_by_ord(const struct device *dev,
*/
int smartbond_clocks_init(const struct device *dev)
{
uint32_t clk_id;
enum smartbond_clock lp_clk;
enum smartbond_clock sys_clk;
ARG_UNUSED(dev);
uint32_t clk_ctrl;
uint32_t sys_clk_id;
#define ENABLE_OSC(clock) smartbond_clock_control_on_by_ord(dev, DT_DEP_ORD(clock))
#define DISABLE_OSC(clock) if (DT_NODE_HAS_STATUS(clock, disabled)) { \
@ -170,9 +428,6 @@ int smartbond_clocks_init(const struct device *dev)
/* Enable all oscillators with status "okay" */
DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(crg, osc), ENABLE_OSC, (;));
clk_ctrl = CRG_TOP->CLK_CTRL_REG &
~(CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk | CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk);
/* Make sure that selected sysclock is enabled */
BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_PROP(DT_NODELABEL(sys_clk), clock_src), okay),
"Clock selected as system clock no enabled in DT");
@ -182,32 +437,15 @@ int smartbond_clocks_init(const struct device *dev)
DT_NODE_HAS_STATUS(DT_NODELABEL(xtal32m), okay),
"PLL enabled in DT but XTAL32M is disabled");
sys_clk_id = DT_DEP_ORD(DT_NODELABEL(sys_clk));
smartbond_clock_control_on(dev, &sys_clk_id);
if (DT_SAME_NODE(DT_PROP(DT_NODELABEL(lp_clk), clock_src),
DT_NODELABEL(rc32k))) {
} else if (DT_SAME_NODE(DT_PROP(DT_NODELABEL(lp_clk), clock_src),
DT_NODELABEL(rcx))) {
clk_ctrl |= 1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos;
} else if (DT_SAME_NODE(DT_PROP(DT_NODELABEL(lp_clk), clock_src),
DT_NODELABEL(xtal32k))) {
clk_ctrl |= 2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos;
}
clk_id = DT_DEP_ORD(DT_PROP(DT_NODELABEL(lp_clk), clock_src));
lp_clk = smartbond_dt_ord_to_clock(clk_id);
z_smartbond_select_lp_clk(lp_clk);
if (DT_SAME_NODE(DT_PROP(DT_NODELABEL(sys_clk), clock_src),
DT_NODELABEL(rc32m))) {
clk_ctrl |= 1 << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos;
SystemCoreClock = DT_PROP(DT_NODELABEL(rc32m), clock_frequency);
} else if (DT_SAME_NODE(DT_PROP(DT_NODELABEL(sys_clk), clock_src),
DT_NODELABEL(pll))) {
da1469x_clock_pll_wait_to_lock();
SystemCoreClock = DT_PROP(DT_NODELABEL(pll), clock_frequency);
clk_ctrl |= 3 << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos;
} else if (DT_SAME_NODE(DT_PROP(DT_NODELABEL(sys_clk), clock_src),
DT_NODELABEL(xtal32m))) {
da1469x_clock_sys_xtal32m_switch_safe();
}
CRG_TOP->CLK_CTRL_REG = clk_ctrl;
clk_id = DT_DEP_ORD(DT_PROP(DT_NODELABEL(sys_clk), clock_src));
sys_clk = smartbond_dt_ord_to_clock(clk_id);
smartbond_clock_control_on(dev,
(clock_control_subsys_rate_t)smartbond_source_clock(sys_clk));
z_smartbond_select_sys_clk(sys_clk);
/* Disable unwanted oscillators */
DT_FOREACH_CHILD_SEP(DT_PATH(crg, osc), DISABLE_OSC, (;));

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2023 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_SMARTBOND_CLOCK_CONTROL_H_
#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_SMARTBOND_CLOCK_CONTROL_H_
#include <zephyr/device.h>
#include <zephyr/drivers/clock_control.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Smartbond clocks
*
* Enum oscillators and clocks.
*/
enum smartbond_clock {
/* Not a clock, used for error case only */
SMARTBOND_CLK_NONE,
SMARTBOND_CLK_RC32K,
SMARTBOND_CLK_RCX,
SMARTBOND_CLK_XTAL32K,
SMARTBOND_CLK_RC32M,
SMARTBOND_CLK_XTAL32M,
SMARTBOND_CLK_PLL96M,
SMARTBOND_CLK_DIVN_32M,
SMARTBOND_CLK_HCLK,
SMARTBOND_CLK_LP_CLK,
SMARTBOND_CLK_SYS_CLK,
};
/** @brief Selects system clock
*
* @param sys_clk system clock to switch to.
*
* @return 0 on success
*/
int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk);
/** @brief Selects low power clock
*
* @param lp_clk low power clock to switch to.
*
* @return 0 on success
*/
int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_SMARTBOND_CLOCK_CONTROL_H_ */