drivers: clock_control: smartbond: initial support
This commit adds basic support for the clock controller used in SmartBond MCUs. Signed-off-by: Jerzy Kasenberg <jerzy.kasenberg@codecoup.pl>
This commit is contained in:
parent
5b4a83f9b9
commit
884d7ea706
|
@ -22,6 +22,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION nrf_clo
|
|||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_control_rv32m1_pcc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_INFINEON_CAT1 clock_control_ifx_cat1.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SAM clock_control_sam_pmc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SMARTBOND clock_control_smartbond.c)
|
||||
|
||||
|
||||
if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
|
||||
|
|
|
@ -70,4 +70,6 @@ source "drivers/clock_control/Kconfig.gd32"
|
|||
|
||||
source "drivers/clock_control/Kconfig.sam"
|
||||
|
||||
source "drivers/clock_control/Kconfig.smartbond"
|
||||
|
||||
endif # CLOCK_CONTROL
|
||||
|
|
10
drivers/clock_control/Kconfig.smartbond
Normal file
10
drivers/clock_control/Kconfig.smartbond
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Smartbond clock control driver config
|
||||
|
||||
# Copyright (c) 2022 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config CLOCK_CONTROL_SMARTBOND
|
||||
bool "Smartbond Clock Control"
|
||||
depends on SOC_FAMILY_SMARTBOND
|
||||
help
|
||||
Enable driver for Clock Control subsystem found in SmartBond
|
230
drivers/clock_control/clock_control_smartbond.c
Normal file
230
drivers/clock_control/clock_control_smartbond.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Renesas Electronics Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <soc.h>
|
||||
#include <zephyr/sys/onoff.h>
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <da1469x_clock.h>
|
||||
|
||||
LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
|
||||
|
||||
#define DT_DRV_COMPAT smartbond_clock
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(rcx)):
|
||||
da1469x_clock_lp_rcx_enable();
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
|
||||
da1469x_clock_lp_xtal32k_enable();
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(rc32m)):
|
||||
CRG_TOP->CLK_RC32M_REG |= CRG_TOP_CLK_RC32M_REG_RC32M_ENABLE_Msk;
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
|
||||
da1469x_clock_sys_xtal32m_init();
|
||||
da1469x_clock_sys_xtal32m_enable();
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(pll)):
|
||||
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) {
|
||||
da1469x_clock_sys_xtal32m_init();
|
||||
da1469x_clock_sys_xtal32m_enable();
|
||||
da1469x_clock_sys_xtal32m_wait_to_settle();
|
||||
}
|
||||
da1469x_clock_sys_pll_enable();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
switch (*clk) {
|
||||
case DT_DEP_ORD(DT_NODELABEL(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;
|
||||
}
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(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;
|
||||
}
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(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;
|
||||
}
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(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)):
|
||||
da1469x_clock_sys_xtal32m_init();
|
||||
da1469x_clock_sys_xtal32m_enable();
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(pll)):
|
||||
da1469x_clock_sys_pll_disable();
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smartbond_clock_control_get_rate(const struct device *dev,
|
||||
clock_control_subsys_t sub_system,
|
||||
uint32_t *rate)
|
||||
{
|
||||
const uint32_t *clk = (const uint32_t *)(sub_system);
|
||||
|
||||
switch (*clk) {
|
||||
case DT_DEP_ORD(DT_NODELABEL(rc32k)):
|
||||
*rate = da1469x_clock_lp_rc32m_freq_get();
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(rcx)):
|
||||
*rate = da1469x_clock_lp_rcx_freq_get();
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(xtal32k)):
|
||||
*rate = DT_PROP(DT_NODELABEL(xtal32k), clock_frequency);
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(rc32m)):
|
||||
*rate = DT_PROP(DT_NODELABEL(rc32m), clock_frequency);
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(xtal32m)):
|
||||
*rate = DT_PROP(DT_NODELABEL(xtal32m), clock_frequency);
|
||||
break;
|
||||
case DT_DEP_ORD(DT_NODELABEL(pll)):
|
||||
*rate = DT_PROP(DT_NODELABEL(pll), clock_frequency);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smartbond_clock_control_on_by_ord(const struct device *dev,
|
||||
uint32_t clock_id)
|
||||
{
|
||||
smartbond_clock_control_on(dev, &clock_id);
|
||||
}
|
||||
|
||||
static void smartbond_clock_control_off_by_ord(const struct device *dev,
|
||||
uint32_t clock_id)
|
||||
{
|
||||
smartbond_clock_control_off(dev, &clock_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize clocks for the Smartbond
|
||||
*
|
||||
* This routine is called to enable and configure the clocks and PLL
|
||||
* of the soc on the board.
|
||||
*
|
||||
* @param dev clocks device struct
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
int smartbond_clocks_init(const struct device *dev)
|
||||
{
|
||||
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)) { \
|
||||
smartbond_clock_control_off_by_ord(dev, DT_DEP_ORD(clock)); \
|
||||
}
|
||||
|
||||
/* 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");
|
||||
BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_PROP(DT_NODELABEL(lp_clk), clock_src), okay),
|
||||
"Clock selected as LP clock no enabled in DT");
|
||||
BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(pll), disabled) ||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* Disable unwanted oscillators */
|
||||
DT_FOREACH_CHILD_SEP(DT_PATH(crg, osc), DISABLE_OSC, (;));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_control_driver_api smartbond_clock_control_api = {
|
||||
.on = smartbond_clock_control_on,
|
||||
.off = smartbond_clock_control_off,
|
||||
.get_rate = smartbond_clock_control_get_rate,
|
||||
};
|
||||
|
||||
DEVICE_DT_DEFINE(DT_NODELABEL(osc),
|
||||
&smartbond_clocks_init,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
PRE_KERNEL_1,
|
||||
CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
|
||||
&smartbond_clock_control_api);
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <arm/armv8-m.dtsi>
|
||||
#include <mem.h>
|
||||
#include <freq.h>
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
|
@ -23,6 +24,63 @@
|
|||
};
|
||||
};
|
||||
|
||||
crg {
|
||||
osc: osc {
|
||||
rc32k: rc32k {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <DT_FREQ_K(32)>;
|
||||
#clock-cells = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
xtal32k: xtal32k {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <32768>;
|
||||
#clock-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
rcx: rcx {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <DT_FREQ_K(15)>;
|
||||
#clock-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
rc32m: rc32m {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <DT_FREQ_M(32)>;
|
||||
#clock-cells = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
xtal32m: xtal32m {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <DT_FREQ_M(32)>;
|
||||
#clock-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
pll: pll {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <DT_FREQ_M(96)>;
|
||||
#clock-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
divn_clk: divn_clk {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <DT_FREQ_M(32)>;
|
||||
#clock-cells = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
sys_clk: sys_clk {
|
||||
compatible = "renesas,smartbond-sys-clk";
|
||||
status = "okay";
|
||||
clock-src = <&rc32m>;
|
||||
status = "okay";
|
||||
};
|
||||
lp_clk: lp_clk {
|
||||
compatible = "renesas,smartbond-lp-clk";
|
||||
clock-src = <&rc32k>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
sram0: memory@20000000 {
|
||||
|
|
18
dts/bindings/clock/renesas,smartbond-lp-clock.yaml
Normal file
18
dts/bindings/clock/renesas,smartbond-lp-clock.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2022 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Smartbond low power clock
|
||||
|
||||
compatible: "renesas,smartbond-lp-clk"
|
||||
|
||||
include:
|
||||
- name: base.yaml
|
||||
property-allowlist:
|
||||
- status
|
||||
- compatible
|
||||
|
||||
properties:
|
||||
clock-src:
|
||||
type: phandle
|
||||
description: |
|
||||
Low power clock source.
|
18
dts/bindings/clock/renesas,smartbond-sys-clock.yaml
Normal file
18
dts/bindings/clock/renesas,smartbond-sys-clock.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2022 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Smartbond system clock
|
||||
|
||||
compatible: "renesas,smartbond-sys-clk"
|
||||
|
||||
include:
|
||||
- name: base.yaml
|
||||
property-allowlist:
|
||||
- status
|
||||
- compatible
|
||||
|
||||
properties:
|
||||
clock-src:
|
||||
type: phandle
|
||||
description: |
|
||||
System clock source.
|
|
@ -10,5 +10,7 @@ config SOC_SERIES_DA1469X
|
|||
select CPU_CORTEX_M_HAS_SYSTICK
|
||||
select SOC_FAMILY_SMARTBOND
|
||||
select HAS_SEGGER_RTT
|
||||
select CLOCK_CONTROL
|
||||
select CLOCK_CONTROL_SMARTBOND
|
||||
help
|
||||
Enable support for Renesas SmartBond(tm) DA1469x MCU series
|
||||
|
|
Loading…
Reference in a new issue