/* * SPDX-License-Identifier: Apache-2.0 * * Copyright (C) 2024, Joakim Andersson */ #include #include #include #include #include #include "clock_stm32_ll_common.h" #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_clock_mco) #define DT_DRV_COMPAT st_stm32_clock_mco #define HAS_PRESCALER 1 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_clock_mco) #define DT_DRV_COMPAT st_stm32f1_clock_mco #endif struct stm32_mco_config { const struct pinctrl_dev_config *pcfg; #if defined(HAS_PRESCALER) uint32_t prescaler; #endif /* clock subsystem driving this peripheral */ const struct stm32_pclken pclken[1]; }; static int stm32_mco_init(const struct device *dev) { const struct stm32_mco_config *config = dev->config; const struct stm32_pclken *pclken = &config->pclken[0]; int err; err = enabled_clock(pclken->bus); if (err < 0) { /* Attempt to configure a src clock not available or not valid */ return err; } /* MCO source */ sys_clear_bits( DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_MCO_CFGR_REG_GET(pclken->enr), STM32_MCO_CFGR_MASK_GET(pclken->enr) << STM32_MCO_CFGR_SHIFT_GET(pclken->enr)); sys_set_bits( DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_MCO_CFGR_REG_GET(pclken->enr), STM32_MCO_CFGR_VAL_GET(pclken->enr) << STM32_MCO_CFGR_SHIFT_GET(pclken->enr)); #if defined(HAS_PRESCALER) /* MCO prescaler */ sys_clear_bits( DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_MCO_CFGR_REG_GET(config->prescaler), STM32_MCO_CFGR_MASK_GET(config->prescaler) << STM32_MCO_CFGR_SHIFT_GET(config->prescaler)); sys_set_bits( DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_MCO_CFGR_REG_GET(config->prescaler), STM32_MCO_CFGR_VAL_GET(config->prescaler) << STM32_MCO_CFGR_SHIFT_GET(config->prescaler)); #endif return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); } #define STM32_MCO_INIT(inst) \ \ PINCTRL_DT_INST_DEFINE(inst); \ \ const static struct stm32_mco_config stm32_mco_config_##inst = { \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .pclken = STM32_DT_INST_CLOCKS(inst), \ IF_ENABLED(HAS_PRESCALER, \ (.prescaler = DT_PROP(DT_DRV_INST(inst), prescaler),)) \ }; \ \ DEVICE_DT_INST_DEFINE(inst, stm32_mco_init, NULL, \ NULL, \ &stm32_mco_config_##inst, \ PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ NULL); DT_INST_FOREACH_STATUS_OKAY(STM32_MCO_INIT);