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