/* * Copyright (c) 2020 Teslabs Engineering S.L. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include LOG_MODULE_REGISTER(memc_stm32, CONFIG_MEMC_LOG_LEVEL); #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_fmc) #define DT_DRV_COMPAT st_stm32_fmc #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_fmc) #define DT_DRV_COMPAT st_stm32h7_fmc #else #error "No compatible FMC devicetree node found" #endif /* This symbol takes the value 1 if one of the device instances */ /* is configured in dts with a domain clock */ #if STM32_DT_INST_DEV_DOMAIN_CLOCK_SUPPORT #define STM32_FMC_DOMAIN_CLOCK_SUPPORT 1 #else #define STM32_FMC_DOMAIN_CLOCK_SUPPORT 0 #endif struct memc_stm32_config { uint32_t fmc; const struct stm32_pclken *pclken; size_t pclk_len; const struct pinctrl_dev_config *pcfg; }; static int memc_stm32_init(const struct device *dev) { const struct memc_stm32_config *config = dev->config; int r; const struct device *clk; /* configure pinmux */ r = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); if (r < 0) { LOG_ERR("FMC pinctrl setup failed (%d)", r); return r; } /* enable FMC peripheral clock */ clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); if (!device_is_ready(clk)) { LOG_ERR("clock control device not ready"); return -ENODEV; } r = clock_control_on(clk, (clock_control_subsys_t)&config->pclken[0]); if (r < 0) { LOG_ERR("Could not initialize FMC clock (%d)", r); return r; } if (IS_ENABLED(STM32_FMC_DOMAIN_CLOCK_SUPPORT) && (config->pclk_len > 1)) { /* Enable FMC clock source */ r = clock_control_configure(clk, (clock_control_subsys_t)&config->pclken[1], NULL); if (r < 0) { LOG_ERR("Could not select FMC clock (%d)", r); return r; } } #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_fmc) #if (DT_ENUM_IDX(DT_DRV_INST(0), st_mem_swap) == 1) /* sdram-sram */ MODIFY_REG(FMC_Bank1_R->BTCR[0], FMC_BCR1_BMAP, FMC_BCR1_BMAP_0); #elif (DT_ENUM_IDX(DT_DRV_INST(0), st_mem_swap) == 2) /* sdramb2 */ MODIFY_REG(FMC_Bank1_R->BTCR[0], FMC_BCR1_BMAP, FMC_BCR1_BMAP_1); #endif #endif return 0; } PINCTRL_DT_INST_DEFINE(0); static const struct stm32_pclken pclken[] = STM32_DT_INST_CLOCKS(0); static const struct memc_stm32_config config = { .fmc = DT_INST_REG_ADDR(0), .pclken = pclken, .pclk_len = DT_INST_NUM_CLOCKS(0), .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), }; DEVICE_DT_INST_DEFINE(0, memc_stm32_init, NULL, NULL, &config, POST_KERNEL, CONFIG_MEMC_INIT_PRIORITY, NULL);