| /* |
| * Copyright 2025 STMicroelectronics |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <errno.h> |
| |
| #include <zephyr/device.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/init.h> |
| #include <soc.h> |
| |
| #include <zephyr/drivers/clock_control/stm32_clock_control.h> |
| |
| #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) |