From af6a9024fb79f418cc4b0736b2a79d87164830fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2024 16:41:01 +0100 Subject: [PATCH] drivers: clock: siwx917: Add dumb clock driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver is mostly the initial seed for further implementation of a real clock driver. Currently, sinc ethe driver do not enable the clock sources, this driver still contains the series of #ifdef to enable the clocks. It also doesn't allow the user to choose the clock source for the various peripherals. The driver hardcodes some sane values. Signed-off-by: Jérôme Pouiller --- .../siwx917_rb4338a/siwx917_rb4338a_defconfig | 1 + drivers/CMakeLists.txt | 1 + drivers/clock_control/CMakeLists.txt | 5 + drivers/clock_control/Kconfig | 8 + drivers/clock_control/Kconfig.siwx917 | 15 ++ .../clock_control_silabs_siwx917.c | 205 ++++++++++++++++++ dts/arm/silabs/siwg917.dtsi | 22 +- dts/bindings/clock/silabs,siwx917-clock.yaml | 18 ++ .../dt-bindings/clock/silabs/siwx917-clock.h | 16 ++ soc/silabs/silabs_siwx917/siwg917/soc.c | 42 ---- 10 files changed, 288 insertions(+), 45 deletions(-) create mode 100644 drivers/clock_control/CMakeLists.txt create mode 100644 drivers/clock_control/Kconfig create mode 100644 drivers/clock_control/Kconfig.siwx917 create mode 100644 drivers/clock_control/clock_control_silabs_siwx917.c create mode 100644 dts/bindings/clock/silabs,siwx917-clock.yaml create mode 100644 include/zephyr/dt-bindings/clock/silabs/siwx917-clock.h diff --git a/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a_defconfig b/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a_defconfig index b008914..64142ee 100644 --- a/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a_defconfig +++ b/boards/silabs/radio_boards/siwx917_rb4338a/siwx917_rb4338a_defconfig @@ -6,5 +6,6 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_PINCTRL=y +CONFIG_CLOCK_CONTROL=y CONFIG_SIWX917_FLASH_MODE_COMMON=y CONFIG_USE_DT_CODE_PARTITION=y diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 5cbf42f..b239ee4 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 add_subdirectory(bluetooth) +add_subdirectory(clock_control) add_subdirectory(entropy) add_subdirectory(flash) add_subdirectory(gpio) diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt new file mode 100644 index 0000000..bd35fb6 --- /dev/null +++ b/drivers/clock_control/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_amend() +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SILABS_SIWX917 clock_control_silabs_siwx917.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig new file mode 100644 index 0000000..5aa3133 --- /dev/null +++ b/drivers/clock_control/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +if CLOCK_CONTROL + +rsource "Kconfig.siwx917" + +endif diff --git a/drivers/clock_control/Kconfig.siwx917 b/drivers/clock_control/Kconfig.siwx917 new file mode 100644 index 0000000..7512f69 --- /dev/null +++ b/drivers/clock_control/Kconfig.siwx917 @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_SILABS_SIWX917 + bool "SiWx917 clock control driver" + default y + depends on DT_HAS_SILABS_SIWX917_CLOCK_ENABLED + help + Enable clock management on Silicon Labs SiWx917 chips. This driver + includes support for HP (High Performace), ULP (Ultra Low Power), and + ULP VBAT locks. + + The original hardware allow to customize the various clocks offered for + every devices. This driver does not provide such customizations. It + just hardcodes sane default parameters for every devices. diff --git a/drivers/clock_control/clock_control_silabs_siwx917.c b/drivers/clock_control/clock_control_silabs_siwx917.c new file mode 100644 index 0000000..08577d1 --- /dev/null +++ b/drivers/clock_control/clock_control_silabs_siwx917.c @@ -0,0 +1,205 @@ +/* Copyright (c) 2024 Silicon Laboratories Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Poor man driver for 917 clocks. 917 includes High Performace (HP) clock + * (@46000000), Ultra Lower Power (ULP) clock (@24041400) and ULP VBAT (@24048000) + * + */ +#include +#include +#include + +#include "rsi_power_save.h" +#include "rsi_rom_ulpss_clk.h" +#include "rsi_rom_clks.h" +#include "sl_si91x_clock_manager.h" + +#define DT_DRV_COMPAT silabs_siwx917_clock + +LOG_MODULE_REGISTER(siwx917_clock, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +struct siwx917_clock_data { + uint32_t enable; +}; + +static int siwx917_clock_on(const struct device *dev, clock_control_subsys_t sys) +{ + struct siwx917_clock_data *data = dev->data; + uintptr_t clockid = (uintptr_t)sys; + + switch (clockid) { + case SIWX917_CLK_ULP_UART: + RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_UART); + RSI_ULPSS_UlpUartClkConfig(ULPCLK, ENABLE_STATIC_CLK, + false, ULP_UART_ULP_32MHZ_RC_CLK, 1); + break; + case SIWX917_CLK_ULP_I2C: + RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_I2C); + RSI_ULPSS_PeripheralEnable(ULPCLK, ULP_I2C_CLK, ENABLE_STATIC_CLK); + break; + case SIWX917_CLK_ULP_DMA: + RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_UDMA); + RSI_ULPSS_PeripheralEnable(ULPCLK, ULP_UDMA_CLK, ENABLE_STATIC_CLK); + break; + case SIWX917_CLK_UART1: + RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); + /* RSI_CLK_UsartClkConfig() calls RSI_CLK_PeripheralClkEnable(); */ + RSI_CLK_UsartClkConfig(M4CLK, ENABLE_STATIC_CLK, 0, USART1, 0, 1); + break; + case SIWX917_CLK_UART2: + RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); + /* RSI_CLK_UsartClkConfig() calls RSI_CLK_PeripheralClkEnable(); */ + RSI_CLK_UsartClkConfig(M4CLK, ENABLE_STATIC_CLK, 0, USART2, 0, 1); + break; + case SIWX917_CLK_I2C0: + RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); + RSI_CLK_I2CClkConfig(M4CLK, true, 0); + break; + case SIWX917_CLK_I2C1: + RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); + RSI_CLK_I2CClkConfig(M4CLK, true, 1); + break; + case SIWX917_CLK_DMA0: + RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); + RSI_CLK_PeripheralClkEnable(M4CLK, UDMA_CLK, ENABLE_STATIC_CLK); + break; + default: + return -EINVAL; + } + data->enable |= BIT(clockid); + + return 0; +} + +static int siwx917_clock_off(const struct device *dev, clock_control_subsys_t sys) +{ + struct siwx917_clock_data *data = dev->data; + uintptr_t clockid = (uintptr_t)sys; + + switch (clockid) { + case SIWX917_CLK_ULP_I2C: + RSI_ULPSS_PeripheralDisable(ULPCLK, ULP_I2C_CLK); + break; + case SIWX917_CLK_ULP_DMA: + RSI_ULPSS_PeripheralDisable(ULPCLK, ULP_UDMA_CLK); + break; + case SIWX917_CLK_UART1: + RSI_CLK_PeripheralClkDisable(M4CLK, USART1_CLK); + break; + case SIWX917_CLK_UART2: + RSI_CLK_PeripheralClkDisable(M4CLK, USART2_CLK); + break; + case SIWX917_CLK_DMA0: + RSI_CLK_PeripheralClkDisable(M4CLK, UDMA_CLK); + break; + case SIWX917_CLK_ULP_UART: + case SIWX917_CLK_I2C0: + case SIWX917_CLK_I2C1: + /* Not supported */ + return 0; + default: + return -EINVAL; + } + + data->enable &= ~BIT(clockid); + return 0; +} + +static int siwx917_clock_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + uintptr_t clockid = (uintptr_t)sys; + + switch (clockid) { + case SIWX917_CLK_ULP_UART: + *rate = 32000000; + return 0; + case SIWX917_CLK_UART1: + *rate = 25000000; + return 0; + case SIWX917_CLK_UART2: + *rate = 20000000; + return 0; + default: + /* For now, no other driver need clock rate */ + return -EINVAL; + } +} + +static enum clock_control_status siwx917_clock_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + struct siwx917_clock_data *data = dev->data; + uintptr_t clockid = (uintptr_t)sys; + + if (data->enable & BIT(clockid)) { + return CLOCK_CONTROL_STATUS_ON; + } else { + return CLOCK_CONTROL_STATUS_OFF; + } +} + +static int siwx917_clock_init(const struct device *dev) +{ + SystemCoreClockUpdate(); + + /* Use SoC PLL at configured frequency as core clock */ + sl_si91x_clock_manager_m4_set_core_clk(M4_SOCPLLCLK, CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + + /* Use interface PLL at configured frequency as peripheral clock */ + sl_si91x_clock_manager_set_pll_freq(INFT_PLL, CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + PLL_REF_CLK_VAL_XTAL); + + /* FIXME: Currently the clock consumer use clocks without power on them. + * This should be fixed in drivers. Meanwhile, get the list of required + * clocks using DT labels. + */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(ulpuart), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_ULP_UART); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(ulpi2c), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_ULP_I2C); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(ulpdma), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_ULP_DMA); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_UART1); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_UART2); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c0), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_I2C0); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_I2C1); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(udma0), okay) + siwx917_clock_on(dev, (clock_control_subsys_t)SIWX917_CLK_DMA0); +#endif + + return 0; +} + +static const struct clock_control_driver_api siwx917_clock_api = { + .on = siwx917_clock_on, + .off = siwx917_clock_off, + .get_rate = siwx917_clock_get_rate, + .get_status = siwx917_clock_get_status, +}; + +#define SIWX917_CLOCK_INIT(p) \ + static struct siwx917_clock_data siwx917_clock_data_##p; \ + DEVICE_DT_INST_DEFINE(p, siwx917_clock_init, NULL, &siwx917_clock_data_##p, NULL, \ + PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ + &siwx917_clock_api); + +DT_INST_FOREACH_STATUS_OKAY(SIWX917_CLOCK_INIT) diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi index e4e4cfb..3e202a2 100644 --- a/dts/arm/silabs/siwg917.dtsi +++ b/dts/arm/silabs/siwg917.dtsi @@ -7,6 +7,7 @@ #include #include #include +#include / { chosen { @@ -41,6 +42,16 @@ }; soc { + clock0: clock@46000000 { + compatible = "silabs,siwx917-clock"; + reg = <0x46000000 0x100>, + <0x46000800 0x100>, + <0x24041400 0x100>, + <0x24048000 0x200>; + #clock-cells = <1>; + status = "okay"; + }; + pinctrl0: pinctrl@46130000 { compatible = "silabs,siwx917-pinctrl"; reg = <0x46130000 0x1000>; @@ -64,7 +75,7 @@ reg = <0x24041800 0x1000>; interrupts = <12 0>; reg-shift = <2>; - clock-frequency = <32000000>; + clocks = <&clock0 SIWX917_CLK_ULP_UART>; current-speed = <115200>; status = "disabled"; }; @@ -74,7 +85,7 @@ reg = <0x44000000 0x1000>; interrupts = <38 0>; reg-shift = <2>; - clock-frequency = <25000000>; + clocks = <&clock0 SIWX917_CLK_UART1>; current-speed = <115200>; status = "disabled"; }; @@ -84,7 +95,7 @@ reg = <0x45020000 0x1000>; interrupts = <39 0>; reg-shift = <2>; - clock-frequency = <20000000>; + clocks = <&clock0 SIWX917_CLK_UART2>; current-speed = <115200>; status = "disabled"; }; @@ -194,6 +205,7 @@ reg = <0x44010000 0x100>; interrupts = <42 0>; interrupt-names = "i2c0"; + clocks = <&clock0 SIWX917_CLK_I2C0>; status = "disabled"; }; @@ -204,6 +216,7 @@ reg = <0x47040000 0x100>; interrupts = <61 0>; interrupt-names = "i2c1"; + clocks = <&clock0 SIWX917_CLK_I2C1>; status = "disabled"; }; @@ -214,6 +227,7 @@ reg = <0x24040000 0x100>; interrupts = <13 0>; interrupt-names = "i2c2"; + clocks = <&clock0 SIWX917_CLK_ULP_I2C>; status = "disabled"; }; @@ -229,6 +243,7 @@ reg = <0x44030000 0x82C>; interrupts = <33 0>; interrupt-names = "dma0"; + clocks = <&clock0 SIWX917_CLK_DMA0>; silabs,sram-desc-addr = <0x2fc00>; #dma-cells = < 1>; dma-channels = <32>; @@ -242,6 +257,7 @@ reg = <0x24078000 0x82C>; interrupts = <10 0>; interrupt-names = "ulpdma"; + clocks = <&clock0 SIWX917_CLK_ULP_DMA>; silabs,sram-desc-addr = <0x24061c00>; #dma-cells = < 1>; dma-channels = <12>; diff --git a/dts/bindings/clock/silabs,siwx917-clock.yaml b/dts/bindings/clock/silabs,siwx917-clock.yaml new file mode 100644 index 0000000..12f7074 --- /dev/null +++ b/dts/bindings/clock/silabs,siwx917-clock.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Clocks embedded on Silabs SiWx917 chips + +compatible: "silabs,siwx917-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 1 + +clock-cells: + - clkid diff --git a/include/zephyr/dt-bindings/clock/silabs/siwx917-clock.h b/include/zephyr/dt-bindings/clock/silabs/siwx917-clock.h new file mode 100644 index 0000000..97fdb9c --- /dev/null +++ b/include/zephyr/dt-bindings/clock/silabs/siwx917-clock.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2024 Silicon Laboratories Inc. + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_SILABS_SIWX917_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_SILABS_SIWX917_CLOCK_H_ + +#define SIWX917_CLK_ULP_UART 0 +#define SIWX917_CLK_ULP_I2C 1 +#define SIWX917_CLK_ULP_DMA 2 +#define SIWX917_CLK_UART1 3 +#define SIWX917_CLK_UART2 4 +#define SIWX917_CLK_I2C0 5 +#define SIWX917_CLK_I2C1 6 +#define SIWX917_CLK_DMA0 7 + +#endif diff --git a/soc/silabs/silabs_siwx917/siwg917/soc.c b/soc/silabs/silabs_siwx917/siwg917/soc.c index 304d67f..6f3586f 100644 --- a/soc/silabs/silabs_siwx917/siwg917/soc.c +++ b/soc/silabs/silabs_siwx917/siwg917/soc.c @@ -15,48 +15,6 @@ int silabs_siwx917_init(void) { SystemInit(); - SystemCoreClockUpdate(); - - /* Use SoC PLL at configured frequency as core clock */ - sl_si91x_clock_manager_m4_set_core_clk(M4_SOCPLLCLK, - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); - - /* Use interface PLL at configured frequency as peripheral clock */ - sl_si91x_clock_manager_set_pll_freq(INFT_PLL, - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, - PLL_REF_CLK_VAL_XTAL); - - /* FIXME: do not hardcode UART instances */ -#if DT_NODE_HAS_STATUS(DT_NODELABEL(ulpuart), okay) - RSI_ULPSS_UlpUartClkConfig(ULPCLK, ENABLE_STATIC_CLK, 0, ULP_UART_ULP_32MHZ_RC_CLK, 1); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay) - RSI_CLK_UsartClkConfig(M4CLK, ENABLE_STATIC_CLK, 0, USART1, 0, 1); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay) - RSI_CLK_UsartClkConfig(M4CLK, ENABLE_STATIC_CLK, 0, USART2, 0, 1); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c0), okay) - RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); - RSI_CLK_I2CClkConfig(M4CLK, true, 0); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) - RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); - RSI_CLK_I2CClkConfig(M4CLK, true, 1); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(ulpi2c), okay) - RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_I2C); - RSI_ULPSS_PeripheralEnable(ULPCLK, ULP_I2C_CLK, ENABLE_STATIC_CLK); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(dma0), okay) - RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI); - RSI_CLK_PeripheralClkEnable(M4CLK, UDMA_CLK, ENABLE_STATIC_CLK); -#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(ulpdma), okay) - RSI_PS_UlpssPeriPowerUp(ULPSS_PWRGATE_ULP_UDMA); - RSI_ULPSS_PeripheralEnable(ULPCLK, ULP_UDMA_CLK, ENABLE_STATIC_CLK); -#endif - return 0; } SYS_INIT(silabs_siwx917_init, PRE_KERNEL_1, 0);