1 /*
2 * Copyright (c) 2020 Teslabs Engineering S.L.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT st_stm32_fmc_sdram
8
9 #include <zephyr/device.h>
10 #include <zephyr/kernel.h>
11 #include <soc.h>
12
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(memc_stm32_sdram, CONFIG_MEMC_LOG_LEVEL);
15
16 /** SDRAM controller register offset. */
17 #define SDRAM_OFFSET 0x140U
18
19 /** FMC SDRAM controller bank configuration fields. */
20 struct memc_stm32_sdram_bank_config {
21 FMC_SDRAM_InitTypeDef init;
22 FMC_SDRAM_TimingTypeDef timing;
23 };
24
25 /** FMC SDRAM controller configuration fields. */
26 struct memc_stm32_sdram_config {
27 FMC_SDRAM_TypeDef *sdram;
28 uint32_t power_up_delay;
29 uint8_t num_auto_refresh;
30 uint16_t mode_register;
31 uint16_t refresh_rate;
32 const struct memc_stm32_sdram_bank_config *banks;
33 size_t banks_len;
34 };
35
memc_stm32_sdram_init(const struct device * dev)36 static int memc_stm32_sdram_init(const struct device *dev)
37 {
38 const struct memc_stm32_sdram_config *config = dev->config;
39
40 SDRAM_HandleTypeDef sdram = { 0 };
41 FMC_SDRAM_CommandTypeDef sdram_cmd = { 0 };
42
43 sdram.Instance = config->sdram;
44
45 for (size_t i = 0U; i < config->banks_len; i++) {
46 sdram.State = HAL_SDRAM_STATE_RESET;
47 memcpy(&sdram.Init, &config->banks[i].init, sizeof(sdram.Init));
48
49 (void)HAL_SDRAM_Init(
50 &sdram,
51 (FMC_SDRAM_TimingTypeDef *)&config->banks[i].timing);
52 }
53
54 /* SDRAM initialization sequence */
55 if (config->banks_len == 2U) {
56 sdram_cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
57 } else if (config->banks[0].init.SDBank == FMC_SDRAM_BANK1) {
58 sdram_cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
59 } else {
60 sdram_cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
61 }
62
63 sdram_cmd.AutoRefreshNumber = config->num_auto_refresh;
64 sdram_cmd.ModeRegisterDefinition = config->mode_register;
65
66 /* enable clock */
67 sdram_cmd.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
68 (void)HAL_SDRAM_SendCommand(&sdram, &sdram_cmd, 0U);
69
70 k_usleep(config->power_up_delay);
71
72 /* pre-charge all */
73 sdram_cmd.CommandMode = FMC_SDRAM_CMD_PALL;
74 (void)HAL_SDRAM_SendCommand(&sdram, &sdram_cmd, 0U);
75
76 /* auto-refresh */
77 sdram_cmd.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
78 (void)HAL_SDRAM_SendCommand(&sdram, &sdram_cmd, 0U);
79
80 /* load mode */
81 sdram_cmd.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
82 (void)HAL_SDRAM_SendCommand(&sdram, &sdram_cmd, 0U);
83
84 /* program refresh count */
85 (void)HAL_SDRAM_ProgramRefreshRate(&sdram, config->refresh_rate);
86
87 return 0;
88 }
89
90 /** SDRAM bank/s configuration initialization macro. */
91 #define BANK_CONFIG(node_id) \
92 { .init = { \
93 .SDBank = DT_REG_ADDR(node_id), \
94 .ColumnBitsNumber = DT_PROP_BY_IDX(node_id, st_sdram_control, 0), \
95 .RowBitsNumber = DT_PROP_BY_IDX(node_id, st_sdram_control, 1), \
96 .MemoryDataWidth = DT_PROP_BY_IDX(node_id, st_sdram_control, 2), \
97 .InternalBankNumber = DT_PROP_BY_IDX(node_id, st_sdram_control, 3),\
98 .CASLatency = DT_PROP_BY_IDX(node_id, st_sdram_control, 4), \
99 .WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE, \
100 .SDClockPeriod = DT_PROP_BY_IDX(node_id, st_sdram_control, 5), \
101 .ReadBurst = DT_PROP_BY_IDX(node_id, st_sdram_control, 6), \
102 .ReadPipeDelay = DT_PROP_BY_IDX(node_id, st_sdram_control, 7), \
103 }, \
104 .timing = { \
105 .LoadToActiveDelay = DT_PROP_BY_IDX(node_id, st_sdram_timing, 0), \
106 .ExitSelfRefreshDelay = \
107 DT_PROP_BY_IDX(node_id, st_sdram_timing, 1), \
108 .SelfRefreshTime = DT_PROP_BY_IDX(node_id, st_sdram_timing, 2), \
109 .RowCycleDelay = DT_PROP_BY_IDX(node_id, st_sdram_timing, 3), \
110 .WriteRecoveryTime = DT_PROP_BY_IDX(node_id, st_sdram_timing, 4), \
111 .RPDelay = DT_PROP_BY_IDX(node_id, st_sdram_timing, 5), \
112 .RCDDelay = DT_PROP_BY_IDX(node_id, st_sdram_timing, 6), \
113 } \
114 },
115
116 /** SDRAM bank/s configuration. */
117 static const struct memc_stm32_sdram_bank_config bank_config[] = {
118 DT_INST_FOREACH_CHILD(0, BANK_CONFIG)
119 };
120
121 /** SDRAM configuration. */
122 static const struct memc_stm32_sdram_config config = {
123 .sdram = (FMC_SDRAM_TypeDef *)(DT_REG_ADDR(DT_INST_PARENT(0)) +
124 SDRAM_OFFSET),
125 .power_up_delay = DT_INST_PROP(0, power_up_delay),
126 .num_auto_refresh = DT_INST_PROP(0, num_auto_refresh),
127 .mode_register = DT_INST_PROP(0, mode_register),
128 .refresh_rate = DT_INST_PROP(0, refresh_rate),
129 .banks = bank_config,
130 .banks_len = ARRAY_SIZE(bank_config),
131 };
132
133 DEVICE_DT_INST_DEFINE(0, memc_stm32_sdram_init, NULL,
134 NULL, &config, POST_KERNEL, CONFIG_MEMC_INIT_PRIORITY, NULL);
135