1 /*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 /*
9 * COPYRIGHT(c) 2015 STMicroelectronics
10 *
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * 3. Neither the name of STMicroelectronics nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 ******************************************************************************
34 */
35
36 #include <lk/err.h>
37 #include <lk/debug.h>
38 #include <lk/trace.h>
39 #include <target.h>
40 #include <lk/compiler.h>
41 #include <dev/gpio.h>
42 #include <platform/stm32.h>
43 #include <platform/sdram.h>
44
45 /*
46 * sdram initialization sequence, taken from
47 * STM32Cube_FW_F7_V1.1.0/Drivers/BSP
48 */
49
50 /**
51 * @brief SDRAM status structure definition
52 */
53 #define SDRAM_OK ((uint8_t)0x00)
54 #define SDRAM_ERROR ((uint8_t)0x01)
55
56 /* SDRAM refresh counter (100Mhz SD clock) */
57 #define REFRESH_COUNT ((uint32_t)0x0603)
58
59 #define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
60
61 /* DMA definitions for SDRAM DMA transfer */
62 #define __DMAx_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE
63 #define __DMAx_CLK_DISABLE __HAL_RCC_DMA2_CLK_DISABLE
64 #define SDRAM_DMAx_CHANNEL DMA_CHANNEL_0
65 #define SDRAM_DMAx_STREAM DMA2_Stream0
66 #define SDRAM_DMAx_IRQn DMA2_Stream0_IRQn
67 #define SDRAM_DMAx_IRQHandler DMA2_Stream0_IRQHandler
68
69 /**
70 * @brief FMC SDRAM Mode definition register defines
71 */
72 #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
73 #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
74 #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
75 #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
76 #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
77 #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
78 #define SDRAM_MODEREG_CAS_LATENCY_1 ((uint16_t)0x0010)
79 #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
80 #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
81 #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
82 #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
83 #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
84
85 static SDRAM_HandleTypeDef sdramHandle;
86
87 /**
88 * @brief Programs the SDRAM device.
89 * @param RefreshCount: SDRAM refresh counter value
90 * @retval None
91 */
BSP_SDRAM_Initialization_sequence(uint32_t RefreshCount,uint32_t CasLatency)92 static void BSP_SDRAM_Initialization_sequence(uint32_t RefreshCount,
93 uint32_t CasLatency) {
94 __IO uint32_t tmpmrd = 0;
95 FMC_SDRAM_CommandTypeDef Command;
96
97 /* Step 1: Configure a clock configuration enable command */
98 Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
99 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
100 Command.AutoRefreshNumber = 1;
101 Command.ModeRegisterDefinition = 0;
102
103 /* Send the command */
104 HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
105
106 /* Step 2: Insert 100 us minimum delay */
107 spin(1000);
108
109 /* Step 3: Configure a PALL (precharge all) command */
110 Command.CommandMode = FMC_SDRAM_CMD_PALL;
111 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
112 Command.AutoRefreshNumber = 1;
113 Command.ModeRegisterDefinition = 0;
114
115 /* Send the command */
116 HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
117
118 /* Step 4: Configure an Auto Refresh command */
119 Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
120 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
121 Command.AutoRefreshNumber = 8;
122 Command.ModeRegisterDefinition = 0;
123
124 /* Send the command */
125 HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
126
127 /* Step 5: Program the external memory mode register */
128 tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |\
129 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |\
130 SDRAM_MODEREG_OPERATING_MODE_STANDARD |\
131 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
132
133 tmpmrd |= CasLatency;
134
135 Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
136 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
137 Command.AutoRefreshNumber = 1;
138 Command.ModeRegisterDefinition = tmpmrd;
139
140 /* Send the command */
141 HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
142
143 /* Step 6: Set the refresh rate counter */
144 /* Set the device refresh rate */
145 HAL_SDRAM_ProgramRefreshRate(&sdramHandle, RefreshCount);
146 }
147
GetMemoryWidth(sdram_config_t * config)148 static uint32_t GetMemoryWidth(sdram_config_t *config) {
149 switch (config->bus_width) {
150 case SDRAM_BUS_WIDTH_8 :
151 return FMC_SDRAM_MEM_BUS_WIDTH_8;
152 case SDRAM_BUS_WIDTH_16 :
153 return FMC_SDRAM_MEM_BUS_WIDTH_16;
154 case SDRAM_BUS_WIDTH_32 :
155 return FMC_SDRAM_MEM_BUS_WIDTH_32;
156 }
157 return 0;
158 }
159
GetColumnBitsNumber(sdram_config_t * config)160 static uint32_t GetColumnBitsNumber(sdram_config_t *config) {
161 switch (config->col_bits_num) {
162 case SDRAM_COLUMN_BITS_8 :
163 return FMC_SDRAM_COLUMN_BITS_NUM_8;
164 case SDRAM_COLUMN_BITS_9 :
165 return FMC_SDRAM_COLUMN_BITS_NUM_9;
166 case SDRAM_COLUMN_BITS_10 :
167 return FMC_SDRAM_COLUMN_BITS_NUM_10;
168 case SDRAM_COLUMN_BITS_11 :
169 return FMC_SDRAM_COLUMN_BITS_NUM_11;
170 }
171 return 0;
172 }
173
GetCasLatencyFMC(sdram_config_t * config)174 static uint32_t GetCasLatencyFMC(sdram_config_t *config) {
175 switch (config->cas_latency) {
176 case SDRAM_CAS_LATENCY_1 :
177 return FMC_SDRAM_CAS_LATENCY_1;
178 case SDRAM_CAS_LATENCY_2 :
179 return FMC_SDRAM_CAS_LATENCY_2;
180 case SDRAM_CAS_LATENCY_3 :
181 return FMC_SDRAM_CAS_LATENCY_3;
182 }
183 return 0;
184 }
185
GetCasLatencyModeReg(sdram_config_t * config)186 static uint32_t GetCasLatencyModeReg(sdram_config_t *config) {
187 switch (config->cas_latency) {
188 case SDRAM_CAS_LATENCY_1 :
189 return SDRAM_MODEREG_CAS_LATENCY_1;
190 case SDRAM_CAS_LATENCY_2 :
191 return SDRAM_MODEREG_CAS_LATENCY_2;
192 case SDRAM_CAS_LATENCY_3 :
193 return SDRAM_MODEREG_CAS_LATENCY_3;
194 }
195 return 0;
196 }
197
198 /**
199 * @brief Initializes the SDRAM device.
200 * @retval SDRAM status
201 */
stm32_sdram_init(sdram_config_t * config)202 uint8_t stm32_sdram_init(sdram_config_t *config) {
203 static uint8_t sdramstatus = SDRAM_ERROR;
204 static DMA_HandleTypeDef dma_handle;
205
206 /* SDRAM device configuration */
207 sdramHandle.Instance = FMC_SDRAM_DEVICE;
208
209 /* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
210 FMC_SDRAM_TimingTypeDef Timing;
211 Timing.LoadToActiveDelay = 2;
212 Timing.ExitSelfRefreshDelay = 7;
213 Timing.SelfRefreshTime = 4;
214 Timing.RowCycleDelay = 7;
215 Timing.WriteRecoveryTime = 2;
216 Timing.RPDelay = 2;
217 Timing.RCDDelay = 2;
218
219 sdramHandle.Init.SDBank = FMC_SDRAM_BANK1;
220 sdramHandle.Init.ColumnBitsNumber = GetColumnBitsNumber(config);
221 sdramHandle.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
222 sdramHandle.Init.MemoryDataWidth = GetMemoryWidth(config);
223 sdramHandle.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
224 sdramHandle.Init.CASLatency = GetCasLatencyFMC(config);
225 sdramHandle.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
226 sdramHandle.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
227 sdramHandle.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
228 sdramHandle.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
229
230 /* Enable FMC clock */
231 __HAL_RCC_FMC_CLK_ENABLE();
232
233 /* Enable chosen DMAx clock */
234 __DMAx_CLK_ENABLE();
235
236 /* SDRAM GPIO initialization */
237 stm_sdram_GPIO_init();
238
239 /* Configure common DMA parameters */
240 dma_handle.Init.Channel = SDRAM_DMAx_CHANNEL;
241 dma_handle.Init.Direction = DMA_MEMORY_TO_MEMORY;
242 dma_handle.Init.PeriphInc = DMA_PINC_ENABLE;
243 dma_handle.Init.MemInc = DMA_MINC_ENABLE;
244 dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
245 dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
246 dma_handle.Init.Mode = DMA_NORMAL;
247 dma_handle.Init.Priority = DMA_PRIORITY_HIGH;
248 dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
249 dma_handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
250 dma_handle.Init.MemBurst = DMA_MBURST_SINGLE;
251 dma_handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
252
253 dma_handle.Instance = SDRAM_DMAx_STREAM;
254
255 /* Associate the DMA handle */
256 __HAL_LINKDMA(&sdramHandle, hdma, dma_handle);
257
258 /* Deinitialize the stream for new transfer */
259 HAL_DMA_DeInit(&dma_handle);
260
261 /* Configure the DMA stream */
262 HAL_DMA_Init(&dma_handle);
263
264 #if 0
265 /* NVIC configuration for DMA transfer complete interrupt */
266 HAL_NVIC_SetPriority(SDRAM_DMAx_IRQn, 5, 0);
267 HAL_NVIC_EnableIRQ(SDRAM_DMAx_IRQn);
268 #endif
269
270 if (HAL_SDRAM_Init(&sdramHandle, &Timing) != HAL_OK) {
271 sdramstatus = SDRAM_ERROR;
272 } else {
273 sdramstatus = SDRAM_OK;
274 }
275
276 /* SDRAM initialization sequence */
277 BSP_SDRAM_Initialization_sequence(REFRESH_COUNT,
278 GetCasLatencyModeReg(config));
279
280 return sdramstatus;
281 }
282
283
284