/* * Copyright 2025 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #define DT_DRV_COMPAT st_stm32n6_ramcfg /* Read-only driver configuration */ struct axisram_stm32_cfg { /* RAMCFG instance. */ RAMCFG_TypeDef *base; /* SRAM Clock configuration. */ struct stm32_pclken pclken_axisram; /* RAMCFG Clock configuration. */ struct stm32_pclken pclken_ramcfg; }; static int axisram_stm32_init(const struct device *dev) { const struct axisram_stm32_cfg *cfg = dev->config; RAMCFG_HandleTypeDef ramcfg = {0}; /* enable clock for subsystem */ const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); if (!device_is_ready(clk)) { return -ENODEV; } if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken_ramcfg) != 0) { return -EIO; } if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken_axisram) != 0) { return -EIO; } ramcfg.Instance = cfg->base; HAL_RAMCFG_EnableAXISRAM(&ramcfg); return 0; } /** * On other series which have no RAMCFG, whether RAMs are enabled * or not can be controlled by changing their "status" in Device Tree. * To match this behavior on N6, we check manually during instantation * of RAMCFG nodes whether they have an enabled child (= RAM node) and * perform our own instantiation only if so thanks to COND_CODE. */ #define STM32N6_AXISRAM_INIT(idx) \ \ COND_CODE_0(DT_INST_CHILD_NUM_STATUS_OKAY(idx), (), ( \ \ static const struct axisram_stm32_cfg axisram_stm32_cfg_##idx = { \ .base = (RAMCFG_TypeDef *)DT_INST_REG_ADDR(idx), \ .pclken_axisram = { \ .enr = DT_INST_CLOCKS_CELL_BY_NAME(idx, axisram, bits), \ .bus = DT_INST_CLOCKS_CELL_BY_NAME(idx, axisram, bus), \ }, \ .pclken_ramcfg = { \ .enr = DT_INST_CLOCKS_CELL_BY_NAME(idx, ramcfg, bits), \ .bus = DT_INST_CLOCKS_CELL_BY_NAME(idx, ramcfg, bus), \ }, \ }; \ \ DEVICE_DT_INST_DEFINE(idx, &axisram_stm32_init, NULL, \ NULL, &axisram_stm32_cfg_##idx, \ PRE_KERNEL_2, 0, NULL);)) DT_INST_FOREACH_STATUS_OKAY(STM32N6_AXISRAM_INIT)