From aca4b075f157b97137e6b4b5375c00a048a9509a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Boutreux?= Date: Mon, 1 Apr 2019 13:24:18 +0200 Subject: [PATCH] clock_control: Add stm32mp157c_dk2 board support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for stm32mp1x RCC with Zephyr clock_control driver Signed-off-by: Yaƫl Boutreux Signed-off-by: Arnaud Pouliquen Signed-off-by: Alexandre Torgue --- .../stm32mp157c_dk2/stm32mp157c_dk2_defconfig | 2 +- drivers/clock_control/CMakeLists.txt | 5 +- drivers/clock_control/Kconfig.stm32 | 1 + drivers/clock_control/clock_stm32_ll_mp1x.c | 416 ++++++++++++++++++ include/dt-bindings/clock/stm32_clock.h | 10 +- soc/arm/st_stm32/stm32mp1/Kconfig.series | 1 + soc/arm/st_stm32/stm32mp1/soc.h | 7 + 7 files changed, 439 insertions(+), 3 deletions(-) create mode 100644 drivers/clock_control/clock_stm32_ll_mp1x.c diff --git a/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2_defconfig b/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2_defconfig index 19fd10e70ff..5b498e3c74d 100644 --- a/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2_defconfig +++ b/boards/arm/stm32mp157c_dk2/stm32mp157c_dk2_defconfig @@ -7,7 +7,7 @@ CONFIG_CORTEX_M_SYSTICK=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=209000000 # clock configuration -CONFIG_CLOCK_CONTROL=n +CONFIG_CLOCK_CONTROL=y #remote proc console CONFIG_CONSOLE=y diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index f0da69568d8..6ce011d15f4 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -8,8 +8,10 @@ zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_QUARK_SE quark_se_clock_con zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_control_rv32m1_pcc.c) if(CONFIG_CLOCK_CONTROL_STM32_CUBE) +if(CONFIG_SOC_SERIES_STM32MP1X) + zephyr_sources(clock_stm32_ll_mp1x.c) +else() zephyr_sources(clock_stm32_ll_common.c) - zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F0X clock_stm32f0x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F1X clock_stm32f1x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F2X clock_stm32f2x.c) @@ -21,3 +23,4 @@ if(CONFIG_CLOCK_CONTROL_STM32_CUBE) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32L4X clock_stm32l4x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32WBX clock_stm32wbx.c) endif() +endif() diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 9b44de15bc7..0aebee40241 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -11,6 +11,7 @@ if SOC_FAMILY_STM32 menuconfig CLOCK_CONTROL_STM32_CUBE bool "STM32 Reset & Clock Control" select USE_STM32_LL_UTILS + select USE_STM32_LL_RCC if SOC_SERIES_STM32MP1X help Enable driver for Reset & Clock Control subsystem found in STM32 family of MCUs diff --git a/drivers/clock_control/clock_stm32_ll_mp1x.c b/drivers/clock_control/clock_stm32_ll_mp1x.c new file mode 100644 index 00000000000..e2365386bed --- /dev/null +++ b/drivers/clock_control/clock_stm32_ll_mp1x.c @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/** + * @brief fill in AHB/APB buses configuration structure + */ +static inline int stm32_clock_control_on(struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(dev); + + switch (pclken->bus) { + case STM32_CLOCK_BUS_APB1: + LL_APB1_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB2: + LL_APB2_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB3: + LL_APB3_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB4: + LL_APB4_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB5: + LL_APB5_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB2: + LL_AHB2_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB3: + LL_AHB3_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB4: + LL_AHB4_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB5: + LL_AHB5_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB6: + LL_AHB6_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AXI: + LL_AXI_GRP1_EnableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_MLAHB: + LL_MLAHB_GRP1_EnableClock(pclken->enr); + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static inline int stm32_clock_control_off(struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(dev); + + switch (pclken->bus) { + case STM32_CLOCK_BUS_APB1: + LL_APB1_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB2: + LL_APB2_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB3: + LL_APB3_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB4: + LL_APB4_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_APB5: + LL_APB5_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB2: + LL_AHB2_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB3: + LL_AHB3_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB4: + LL_AHB4_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB5: + LL_AHB5_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AHB6: + LL_AHB6_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_AXI: + LL_AXI_GRP1_DisableClock(pclken->enr); + break; + case STM32_CLOCK_BUS_MLAHB: + LL_MLAHB_GRP1_DisableClock(pclken->enr); + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int stm32_clock_control_get_subsys_rate(struct device *clock, + clock_control_subsys_t sub_system, + u32_t *rate) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(clock); + + switch (pclken->bus) { + case STM32_CLOCK_BUS_APB1: + switch (pclken->enr) { + case LL_APB1_GRP1_PERIPH_TIM2: + case LL_APB1_GRP1_PERIPH_TIM3: + case LL_APB1_GRP1_PERIPH_TIM4: + case LL_APB1_GRP1_PERIPH_TIM5: + case LL_APB1_GRP1_PERIPH_TIM6: + case LL_APB1_GRP1_PERIPH_TIM7: + case LL_APB1_GRP1_PERIPH_TIM12: + case LL_APB1_GRP1_PERIPH_TIM13: + case LL_APB1_GRP1_PERIPH_TIM14: + *rate = LL_RCC_GetTIMGClockFreq(LL_RCC_TIMG1PRES); + break; + case LL_APB1_GRP1_PERIPH_LPTIM1: + *rate = LL_RCC_GetLPTIMClockFreq( + LL_RCC_LPTIM1_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_SPI2: + case LL_APB1_GRP1_PERIPH_SPI3: + *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI23_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_USART2: + case LL_APB1_GRP1_PERIPH_UART4: + *rate = LL_RCC_GetUARTClockFreq( + LL_RCC_UART24_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_USART3: + case LL_APB1_GRP1_PERIPH_UART5: + *rate = LL_RCC_GetUARTClockFreq( + LL_RCC_UART35_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_UART7: + case LL_APB1_GRP1_PERIPH_UART8: + *rate = LL_RCC_GetUARTClockFreq( + LL_RCC_UART78_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_I2C1: + case LL_APB1_GRP1_PERIPH_I2C2: + *rate = LL_RCC_GetI2CClockFreq(LL_RCC_I2C12_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_I2C3: + case LL_APB1_GRP1_PERIPH_I2C5: + *rate = LL_RCC_GetI2CClockFreq(LL_RCC_I2C35_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_SPDIF: + *rate = LL_RCC_GetSPDIFRXClockFreq( + LL_RCC_SPDIFRX_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_CEC: + *rate = LL_RCC_GetCECClockFreq(LL_RCC_CEC_CLKSOURCE); + break; + case LL_APB1_GRP1_PERIPH_WWDG1: + case LL_APB1_GRP1_PERIPH_DAC12: + case LL_APB1_GRP1_PERIPH_MDIOS: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_APB2: + switch (pclken->enr) { + case LL_APB2_GRP1_PERIPH_TIM1: + case LL_APB2_GRP1_PERIPH_TIM8: + case LL_APB2_GRP1_PERIPH_TIM15: + case LL_APB2_GRP1_PERIPH_TIM16: + case LL_APB2_GRP1_PERIPH_TIM17: + *rate = LL_RCC_GetTIMGClockFreq(LL_RCC_TIMG2PRES); + break; + case LL_APB2_GRP1_PERIPH_SPI1: + *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI1_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_SPI4: + case LL_APB2_GRP1_PERIPH_SPI5: + *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI45_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_USART6: + *rate = LL_RCC_GetUARTClockFreq( + LL_RCC_USART6_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_SAI1: + *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI1_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_SAI2: + *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI2_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_SAI3: + *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI3_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_DFSDM1: + *rate = LL_RCC_GetDFSDMClockFreq( + LL_RCC_DFSDM_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_FDCAN: + *rate = LL_RCC_GetFDCANClockFreq( + LL_RCC_FDCAN_CLKSOURCE); + break; + case LL_APB2_GRP1_PERIPH_ADFSDM1: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_APB3: + switch (pclken->enr) { + case LL_APB3_GRP1_PERIPH_LPTIM2: + case LL_APB3_GRP1_PERIPH_LPTIM3: + *rate = LL_RCC_GetLPTIMClockFreq( + LL_RCC_LPTIM23_CLKSOURCE); + break; + case LL_APB3_GRP1_PERIPH_LPTIM4: + case LL_APB3_GRP1_PERIPH_LPTIM5: + *rate = LL_RCC_GetLPTIMClockFreq( + LL_RCC_LPTIM45_CLKSOURCE); + break; + case LL_APB3_GRP1_PERIPH_SAI4: + *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI4_CLKSOURCE); + break; + case LL_APB3_GRP1_PERIPH_SYSCFG: + case LL_APB3_GRP1_PERIPH_VREF: + case LL_APB3_GRP1_PERIPH_TMPSENS: + case LL_APB3_GRP1_PERIPH_PMBCTRL: + case LL_APB3_GRP1_PERIPH_HDP: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_APB4: + switch (pclken->enr) { + case LL_APB4_GRP1_PERIPH_LTDC: + *rate = LL_RCC_GetLTDCClockFreq(); + break; + case LL_APB4_GRP1_PERIPH_DSI: + *rate = LL_RCC_GetDSIClockFreq(LL_RCC_DSI_CLKSOURCE); + break; + case LL_APB4_GRP1_PERIPH_USBPHY: + *rate = LL_RCC_GetUSBPHYClockFreq( + LL_RCC_USBPHY_CLKSOURCE); + break; + case LL_APB4_GRP1_PERIPH_DDRPERFM: + case LL_APB4_GRP1_PERIPH_STGENRO: + case LL_APB4_GRP1_PERIPH_STGENROSTP: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_APB5: + switch (pclken->enr) { + case LL_APB5_GRP1_PERIPH_SPI6: + *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI6_CLKSOURCE); + break; + case LL_APB5_GRP1_PERIPH_I2C4: + case LL_APB5_GRP1_PERIPH_I2C6: + *rate = LL_RCC_GetI2CClockFreq(LL_RCC_I2C46_CLKSOURCE); + case LL_APB5_GRP1_PERIPH_USART1: + *rate = LL_RCC_GetUARTClockFreq( + LL_RCC_USART1_CLKSOURCE); + break; + case LL_APB5_GRP1_PERIPH_STGEN: + case LL_APB5_GRP1_PERIPH_STGENSTP: + *rate = LL_RCC_GetSTGENClockFreq( + LL_RCC_STGEN_CLKSOURCE); + break; + case LL_APB5_GRP1_PERIPH_RTCAPB: + *rate = LL_RCC_GetRTCClockFreq(); + break; + case LL_APB5_GRP1_PERIPH_TZC1: + case LL_APB5_GRP1_PERIPH_TZC2: + case LL_APB5_GRP1_PERIPH_TZPC: + case LL_APB5_GRP1_PERIPH_BSEC: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_AHB2: + switch (pclken->enr) { + case LL_AHB2_GRP1_PERIPH_ADC12: + *rate = LL_RCC_GetADCClockFreq(LL_RCC_ADC_CLKSOURCE); + break; + case LL_AHB2_GRP1_PERIPH_USBO: + *rate = LL_RCC_GetUSBOClockFreq(LL_RCC_USBO_CLKSOURCE); + break; + case LL_AHB2_GRP1_PERIPH_SDMMC3: + *rate = LL_RCC_GetSDMMCClockFreq( + LL_RCC_SDMMC3_CLKSOURCE); + break; + case LL_AHB2_GRP1_PERIPH_DMA1: + case LL_AHB2_GRP1_PERIPH_DMA2: + case LL_AHB2_GRP1_PERIPH_DMAMUX: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_AHB3: + switch (pclken->enr) { + case LL_AHB3_GRP1_PERIPH_RNG2: + *rate = LL_RCC_GetRNGClockFreq(LL_RCC_RNG2_CLKSOURCE); + break; + case LL_AHB3_GRP1_PERIPH_DCMI: + case LL_AHB3_GRP1_PERIPH_CRYP2: + case LL_AHB3_GRP1_PERIPH_HASH2: + case LL_AHB3_GRP1_PERIPH_CRC2: + case LL_AHB3_GRP1_PERIPH_HSEM: + case LL_AHB3_GRP1_PERIPH_IPCC: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_AHB4: + return -ENOTSUP; + case STM32_CLOCK_BUS_AHB5: + switch (pclken->enr) { + case LL_AHB5_GRP1_PERIPH_RNG1: + *rate = LL_RCC_GetRNGClockFreq(LL_RCC_RNG1_CLKSOURCE); + break; + case LL_AHB5_GRP1_PERIPH_GPIOZ: + case LL_AHB5_GRP1_PERIPH_CRYP1: + case LL_AHB5_GRP1_PERIPH_HASH1: + case LL_AHB5_GRP1_PERIPH_BKPSRAM: + case LL_AHB5_GRP1_PERIPH_AXIMC: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_AHB6: + switch (pclken->enr) { + case LL_AHB6_GRP1_PERIPH_ETH1CK: + case LL_AHB6_GRP1_PERIPH_ETH1TX: + case LL_AHB6_GRP1_PERIPH_ETH1RX: + case LL_AHB6_GRP1_PERIPH_ETH1MAC: + case LL_AHB6_GRP1_PERIPH_ETH1STP: + *rate = LL_RCC_GetETHClockFreq(LL_RCC_ETH_CLKSOURCE); + break; + case LL_AHB6_GRP1_PERIPH_FMC: + *rate = LL_RCC_GetFMCClockFreq(LL_RCC_FMC_CLKSOURCE); + break; + case LL_AHB6_GRP1_PERIPH_QSPI: + *rate = LL_RCC_GetQSPIClockFreq(LL_RCC_QSPI_CLKSOURCE); + break; + case LL_AHB6_GRP1_PERIPH_SDMMC1: + case LL_AHB6_GRP1_PERIPH_SDMMC2: + *rate = LL_RCC_GetSDMMCClockFreq( + LL_RCC_SDMMC12_CLKSOURCE); + break; + case LL_AHB6_GRP1_PERIPH_MDMA: + case LL_AHB6_GRP1_PERIPH_GPU: + case LL_AHB6_GRP1_PERIPH_CRC1: + case LL_AHB6_GRP1_PERIPH_USBH: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_AXI: + switch (pclken->enr) { + case LL_AXI_GRP1_PERIPH_SYSRAMEN: + default: + return -ENOTSUP; + } + break; + case STM32_CLOCK_BUS_MLAHB: + switch (pclken->enr) { + case LL_MLAHB_GRP1_PERIPH_RETRAMEN: + default: + return -ENOTSUP; + } + break; + default: + return -ENOTSUP; + } + return 0; +} + +static struct clock_control_driver_api stm32_clock_control_api = { + .on = stm32_clock_control_on, + .off = stm32_clock_control_off, + .get_rate = stm32_clock_control_get_subsys_rate, +}; + +static int stm32_clock_control_init(struct device *dev) +{ + ARG_UNUSED(dev); + return 0; +} + +/** + * @brief RCC device, note that priority is intentionally set to 1 so + * that the device init runs just after SOC init + */ +DEVICE_AND_API_INIT(rcc_stm32, STM32_CLOCK_CONTROL_NAME, + &stm32_clock_control_init, + NULL, NULL, + PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_STM32_DEVICE_INIT_PRIORITY, + &stm32_clock_control_api); diff --git a/include/dt-bindings/clock/stm32_clock.h b/include/dt-bindings/clock/stm32_clock.h index 9e187783682..a669f49b92c 100644 --- a/include/dt-bindings/clock/stm32_clock.h +++ b/include/dt-bindings/clock/stm32_clock.h @@ -13,6 +13,14 @@ #define STM32_CLOCK_BUS_APB2 3 #define STM32_CLOCK_BUS_APB1_2 4 #define STM32_CLOCK_BUS_IOP 5 - +#define STM32_CLOCK_BUS_AHB3 6 +#define STM32_CLOCK_BUS_AHB4 7 +#define STM32_CLOCK_BUS_AHB5 8 +#define STM32_CLOCK_BUS_AHB6 9 +#define STM32_CLOCK_BUS_APB3 10 +#define STM32_CLOCK_BUS_APB4 11 +#define STM32_CLOCK_BUS_APB5 12 +#define STM32_CLOCK_BUS_AXI 13 +#define STM32_CLOCK_BUS_MLAHB 14 #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32_CLOCK_H_ */ diff --git a/soc/arm/st_stm32/stm32mp1/Kconfig.series b/soc/arm/st_stm32/stm32mp1/Kconfig.series index 53f252cb705..5678c0b284f 100644 --- a/soc/arm/st_stm32/stm32mp1/Kconfig.series +++ b/soc/arm/st_stm32/stm32mp1/Kconfig.series @@ -11,5 +11,6 @@ config SOC_SERIES_STM32MP1X select SOC_FAMILY_STM32 select HAS_STM32CUBE select CPU_HAS_ARM_MPU + select CLOCK_CONTROL_STM32_CUBE if CLOCK_CONTROL help Enable support for STM32MP1 MPU series diff --git a/soc/arm/st_stm32/stm32mp1/soc.h b/soc/arm/st_stm32/stm32mp1/soc.h index 6e38119b9ec..f605b84b6b9 100644 --- a/soc/arm/st_stm32/stm32mp1/soc.h +++ b/soc/arm/st_stm32/stm32mp1/soc.h @@ -31,6 +31,13 @@ #include #endif +#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE +#include +#include +#include +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32MP1SOC_H_ */