]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_MPU_LPC54018_MCUXpresso/NXP_Code/drivers/fsl_emc.c
Add MPU demo project for LPC54018 board.
[freertos] / FreeRTOS / Demo / CORTEX_MPU_LPC54018_MCUXpresso / NXP_Code / drivers / fsl_emc.c
1 /*\r
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.\r
3  * Copyright 2016-2019 NXP\r
4  * All rights reserved.\r
5  *\r
6  * SPDX-License-Identifier: BSD-3-Clause\r
7  */\r
8 \r
9 #include "fsl_emc.h"\r
10 \r
11 /*******************************************************************************\r
12  * Definitions\r
13  ******************************************************************************/\r
14 \r
15 /* Component ID definition, used by tools. */\r
16 #ifndef FSL_COMPONENT_ID\r
17 #define FSL_COMPONENT_ID "platform.drivers.emc"\r
18 #endif\r
19 \r
20 /*! @brief Define macros for EMC driver. */\r
21 #define EMC_REFRESH_CLOCK_PARAM (16U)\r
22 #define EMC_SDRAM_WAIT_CYCLES (2000U)\r
23 #define EMC_DYNCTL_COLUMNBASE_OFFSET (0U)\r
24 #define EMC_DYNCTL_COLUMNBASE_MASK (0x3U)\r
25 #define EMC_DYNCTL_COLUMNPLUS_OFFSET (3U)\r
26 #define EMC_DYNCTL_COLUMNPLUS_MASK (0x18U)\r
27 #define EMC_DYNCTL_BUSWIDTH_MASK (0x80U)\r
28 #define EMC_DYNCTL_BUSADDRMAP_MASK (0x20U)\r
29 #define EMC_DYNCTL_DEVBANKS_BITS_MASK (0x1cU)\r
30 #define EMC_SDRAM_BANKCS_BA0_MASK (uint32_t)(0x2000)\r
31 #define EMC_SDRAM_BANKCS_BA1_MASK (uint32_t)(0x4000)\r
32 #define EMC_SDRAM_BANKCS_BA_MASK (EMC_SDRAM_BANKCS_BA0_MASK | EMC_SDRAM_BANKCS_BA1_MASK)\r
33 #define EMC_DIV_ROUND_UP(n, m) (((n) + (m)-1U) / (m))\r
34 \r
35 /*******************************************************************************\r
36  * Prototypes\r
37  ******************************************************************************/\r
38 /*!\r
39  * @brief Get instance number for EMC module.\r
40  *\r
41  * @param base EMC peripheral base address\r
42  */\r
43 static uint32_t EMC_GetInstance(EMC_Type *base);\r
44 \r
45 /*!\r
46  * @brief Get the clock cycles of EMC clock.\r
47  * The function is used to calculate the multiple of the\r
48  * 16 EMCCLKs between the timer_Ns period.\r
49  *\r
50  * @param base EMC peripheral base address\r
51  * @param timer_Ns The timer/period in unit of nanosecond\r
52  * @param plus The plus added to the register settings to reach the calculated cycles.\r
53  * @return The calculated cycles.\r
54  */\r
55 static uint32_t EMC_CalculateTimerCycles(EMC_Type *base, uint32_t timer_Ns, uint32_t plus);\r
56 \r
57 /*!\r
58  * @brief Get the shift value to shift the mode register content by.\r
59  *\r
60  * @param addrMap EMC address map for the dynamic memory configuration.\r
61  *                It is the bit 14 ~ bit 7 of the EMC_DYNAMICCONFIG.\r
62  * @return The offset value to shift the mode register content by.\r
63  */\r
64 static uint32_t EMC_ModeOffset(uint32_t addrMap);\r
65 \r
66 /*******************************************************************************\r
67  * Variables\r
68  ******************************************************************************/\r
69 \r
70 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)\r
71 /*! @brief Pointers to EMC clocks for each instance. */\r
72 static const clock_ip_name_t s_EMCClock[FSL_FEATURE_SOC_EMC_COUNT] = EMC_CLOCKS;\r
73 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */\r
74 \r
75 #if !(defined(FSL_FEATURE_EMC_HAS_NO_RESET) && FSL_FEATURE_EMC_HAS_NO_RESET)\r
76 /*! @brief Pointers to EMC resets for each instance. */\r
77 static const reset_ip_name_t s_emcResets[] = EMC_RSTS;\r
78 #endif\r
79 \r
80 /*! @brief Pointers to EMC bases for each instance. */\r
81 static const EMC_Type *const s_EMCBases[] = EMC_BASE_PTRS;\r
82 \r
83 /*! @brief Define the start address for each chip controlled by EMC. */\r
84 static const uint32_t s_EMCDYCSBases[] = EMC_DYCS_ADDRESS;\r
85 /*******************************************************************************\r
86  * Code\r
87  ******************************************************************************/\r
88 \r
89 static uint32_t EMC_GetInstance(EMC_Type *base)\r
90 {\r
91     uint32_t instance;\r
92 \r
93     /* Find the instance index from base address mappings. */\r
94     for (instance = 0; instance < ARRAY_SIZE(s_EMCBases); instance++)\r
95     {\r
96         if (s_EMCBases[instance] == base)\r
97         {\r
98             break;\r
99         }\r
100     }\r
101 \r
102     assert(instance < ARRAY_SIZE(s_EMCBases));\r
103 \r
104     return instance;\r
105 }\r
106 \r
107 static uint32_t EMC_CalculateTimerCycles(EMC_Type *base, uint32_t timer_Ns, uint32_t plus)\r
108 {\r
109     uint32_t cycles;\r
110 \r
111     cycles = CLOCK_GetEmcClkFreq() / EMC_HZ_ONEMHZ * timer_Ns;\r
112     cycles = EMC_DIV_ROUND_UP(cycles, EMC_MILLISECS_ONESEC); /* Round up. */\r
113 \r
114     /* Decrese according to the plus. */\r
115     if (cycles >= plus)\r
116     {\r
117         cycles = cycles - plus;\r
118     }\r
119     else\r
120     {\r
121         cycles = 0;\r
122     }\r
123 \r
124     return cycles;\r
125 }\r
126 \r
127 static uint32_t EMC_ModeOffset(uint32_t addrMap)\r
128 {\r
129     uint8_t offset     = 0;\r
130     uint32_t columbase = addrMap & EMC_DYNCTL_COLUMNBASE_MASK;\r
131 \r
132     /* First calculate the column length. */\r
133     if (columbase == 2U)\r
134     {\r
135         offset = 8;\r
136     }\r
137     else\r
138     {\r
139         if (0U == columbase)\r
140         {\r
141             offset = 9;\r
142         }\r
143         else\r
144         {\r
145             offset = 8;\r
146         }\r
147 \r
148         /* Add column length increase check. */\r
149         offset += (uint8_t)((addrMap & EMC_DYNCTL_COLUMNPLUS_MASK) >> EMC_DYNCTL_COLUMNPLUS_OFFSET);\r
150     }\r
151 \r
152     /* Add Buswidth/16. */\r
153     if (0U != (addrMap & EMC_DYNCTL_BUSWIDTH_MASK))\r
154     {\r
155         offset += 2U;\r
156     }\r
157     else\r
158     {\r
159         offset += 1U;\r
160     }\r
161 \r
162     /* Add bank select bit if the sdram address map mode is RBC(row-bank-column) mode. */\r
163     if (0U == (addrMap & EMC_DYNCTL_BUSADDRMAP_MASK))\r
164     {\r
165         if (0U == (addrMap & EMC_DYNCTL_DEVBANKS_BITS_MASK))\r
166         {\r
167             offset += 1U;\r
168         }\r
169         else\r
170         {\r
171             offset += 2U;\r
172         }\r
173     }\r
174 \r
175     return offset;\r
176 }\r
177 \r
178 /*!\r
179  * brief Initializes the basic for EMC.\r
180  * This function ungates the EMC clock, initializes the emc system configure\r
181  * and enable the EMC module. This function must be called in the first step to initialize\r
182  * the external memory.\r
183  *\r
184  * param base EMC peripheral base address.\r
185  * param config The EMC basic configuration.\r
186  */\r
187 void EMC_Init(EMC_Type *base, emc_basic_config_t *config)\r
188 {\r
189 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)\r
190     /* Enable the clock. */\r
191     CLOCK_EnableClock((s_EMCClock[EMC_GetInstance(base)]));\r
192 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */\r
193 \r
194 #if !(defined(FSL_FEATURE_EMC_HAS_NO_RESET) && FSL_FEATURE_EMC_HAS_NO_RESET)\r
195     /* Reset the EMC module */\r
196     RESET_PeripheralReset(s_emcResets[EMC_GetInstance(base)]);\r
197 #endif\r
198 \r
199     /* Reset the EMC. */\r
200     SYSCON->PRESETCTRL[2] |= SYSCON_PRESETCTRL_EMC_RESET_MASK;\r
201     SYSCON->PRESETCTRL[2] &= ~SYSCON_PRESETCTRL_EMC_RESET_MASK;\r
202 \r
203     /* Set the EMC sytem configure. */\r
204     SYSCON->EMCCLKDIV = SYSCON_EMCCLKDIV_DIV(config->emcClkDiv);\r
205 \r
206     SYSCON->EMCSYSCTRL = SYSCON_EMCSYSCTRL_EMCFBCLKINSEL(config->fbClkSrc);\r
207 \r
208     /* Set the endian mode. */\r
209     base->CONFIG = (uint32_t)config->endian;\r
210     /* Enable the EMC module with normal memory map mode and normal work mode. */\r
211     base->CONTROL = EMC_CONTROL_E_MASK;\r
212 }\r
213 \r
214 /*!\r
215  * brief Initializes the dynamic memory controller.\r
216  * This function initializes the dynamic memory controller in external memory controller.\r
217  * This function must be called after EMC_Init and before accessing the external dynamic memory.\r
218  *\r
219  * param base EMC peripheral base address.\r
220  * param timing The timing and latency for dynamica memory controller setting. It shall\r
221  *        be used for all dynamica memory chips, threfore the worst timing value for all\r
222  *        used chips must be given.\r
223  * param configure The EMC dynamic memory controller chip independent configuration pointer.\r
224  *       This configuration pointer is actually pointer to a configration array. the array number\r
225  *       depends on the "totalChips".\r
226  * param totalChips The total dynamic memory chip numbers been used or the length of the\r
227  *        "emc_dynamic_chip_config_t" type memory.\r
228  */\r
229 void EMC_DynamicMemInit(EMC_Type *base,\r
230                         emc_dynamic_timing_config_t *timing,\r
231                         emc_dynamic_chip_config_t *config,\r
232                         uint32_t totalChips)\r
233 {\r
234     assert(NULL != config);\r
235     assert(NULL != timing);\r
236     assert(totalChips <= EMC_DYNAMIC_MEMDEV_NUM);\r
237 \r
238     uint32_t count;\r
239     uint32_t casLatency;\r
240     uint32_t addr;\r
241     uint32_t offset;\r
242     uint32_t data;\r
243     emc_dynamic_chip_config_t *dynamicConfig = config;\r
244 \r
245     /* Setting for dynamic memory controller chip independent configuration. */\r
246     for (count = 0; (count < totalChips); count++)\r
247     {\r
248         if (NULL == dynamicConfig)\r
249         {\r
250             break;\r
251         }\r
252         else\r
253         {\r
254             base->DYNAMIC[dynamicConfig->chipIndex].DYNAMICCONFIG =\r
255                 EMC_DYNAMIC_DYNAMICCONFIG_MD(dynamicConfig->dynamicDevice) | EMC_ADDRMAP(dynamicConfig->devAddrMap);\r
256             /* Abstract CAS latency from the sdram mode reigster setting values. */\r
257             casLatency = ((uint32_t)dynamicConfig->sdramModeReg & EMC_SDRAM_MODE_CL_MASK) >> EMC_SDRAM_MODE_CL_SHIFT;\r
258             base->DYNAMIC[dynamicConfig->chipIndex].DYNAMICRASCAS =\r
259                 EMC_DYNAMIC_DYNAMICRASCAS_RAS(dynamicConfig->rAS_Nclk) | EMC_DYNAMIC_DYNAMICRASCAS_CAS(casLatency);\r
260 \r
261             dynamicConfig++;\r
262         }\r
263     }\r
264 \r
265     /* Configure the Dynamic Memory controller timing/latency for all chips. */\r
266     base->DYNAMICREADCONFIG = EMC_DYNAMICREADCONFIG_RD(timing->readConfig);\r
267     base->DYNAMICRP         = EMC_CalculateTimerCycles(base, timing->tRp_Ns, 1) & EMC_DYNAMICRP_TRP_MASK;\r
268     base->DYNAMICRAS        = EMC_CalculateTimerCycles(base, timing->tRas_Ns, 1) & EMC_DYNAMICRAS_TRAS_MASK;\r
269     base->DYNAMICSREX       = EMC_CalculateTimerCycles(base, timing->tSrex_Ns, 1) & EMC_DYNAMICSREX_TSREX_MASK;\r
270     base->DYNAMICAPR        = EMC_CalculateTimerCycles(base, timing->tApr_Ns, 1) & EMC_DYNAMICAPR_TAPR_MASK;\r
271     base->DYNAMICDAL        = EMC_CalculateTimerCycles(base, timing->tDal_Ns, 0) & EMC_DYNAMICDAL_TDAL_MASK;\r
272     base->DYNAMICWR         = EMC_CalculateTimerCycles(base, timing->tWr_Ns, 1) & EMC_DYNAMICWR_TWR_MASK;\r
273     base->DYNAMICRC         = EMC_CalculateTimerCycles(base, timing->tRc_Ns, 1) & EMC_DYNAMICRC_TRC_MASK;\r
274     base->DYNAMICRFC        = EMC_CalculateTimerCycles(base, timing->tRfc_Ns, 1) & EMC_DYNAMICRFC_TRFC_MASK;\r
275     base->DYNAMICXSR        = EMC_CalculateTimerCycles(base, timing->tXsr_Ns, 1) & EMC_DYNAMICXSR_TXSR_MASK;\r
276     base->DYNAMICRRD        = EMC_CalculateTimerCycles(base, timing->tRrd_Ns, 1) & EMC_DYNAMICRRD_TRRD_MASK;\r
277     base->DYNAMICMRD        = EMC_DYNAMICMRD_TMRD((timing->tMrd_Nclk > 0U) ? timing->tMrd_Nclk - 1UL : 0UL);\r
278 \r
279     SDK_DelayAtLeastUs(EMC_SDRAM_NOP_DELAY_US, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
280     /* Step 2. issue nop command. */\r
281     base->DYNAMICCONTROL = 0x00000183;\r
282 \r
283     SDK_DelayAtLeastUs(EMC_SDRAM_PRECHARGE_DELAY_US, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
284     /* Step 3. issue precharge all command. */\r
285     base->DYNAMICCONTROL = 0x00000103;\r
286 \r
287     /* Step 4. issue two auto-refresh command. */\r
288     base->DYNAMICREFRESH = 2;\r
289     SDK_DelayAtLeastUs(EMC_SDRAM_AUTO_REFRESH_DELAY_US, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);\r
290 \r
291     base->DYNAMICREFRESH = EMC_CalculateTimerCycles(base, timing->refreshPeriod_Nanosec, 0) / EMC_REFRESH_CLOCK_PARAM;\r
292 \r
293     /* Step 5. issue a mode command and set the mode value. */\r
294     base->DYNAMICCONTROL = 0x00000083;\r
295 \r
296     /* Calculate the mode settings here and to reach the 8 auto-refresh time requirement. */\r
297     dynamicConfig = config;\r
298     for (count = 0; (count < totalChips); count++)\r
299     {\r
300         if (NULL == dynamicConfig)\r
301         {\r
302             break;\r
303         }\r
304         else\r
305         {\r
306             /* Get the shift value first. */\r
307             offset = EMC_ModeOffset(dynamicConfig->devAddrMap);\r
308             addr   = (s_EMCDYCSBases[dynamicConfig->chipIndex] |\r
309                     ((uint32_t)(dynamicConfig->sdramModeReg & ~EMC_SDRAM_BANKCS_BA_MASK) << offset));\r
310             /* Set the right mode setting value. */\r
311             data = *(volatile uint32_t *)addr;\r
312             data = data;\r
313             dynamicConfig++;\r
314         }\r
315     }\r
316 \r
317     if (kEMC_Sdram != config->dynamicDevice)\r
318     {\r
319         /* Add extended mode register if the low-power sdram is used. */\r
320         base->DYNAMICCONTROL = 0x00000083;\r
321         /* Calculate the mode settings for extended mode register. */\r
322         dynamicConfig = config;\r
323         for (count = 0; (count < totalChips); count++)\r
324         {\r
325             if (NULL == dynamicConfig)\r
326             {\r
327                 break;\r
328             }\r
329             else\r
330             {\r
331                 /* Get the shift value first. */\r
332                 offset = EMC_ModeOffset(dynamicConfig->devAddrMap);\r
333                 addr   = (s_EMCDYCSBases[dynamicConfig->chipIndex] |\r
334                         (((uint32_t)(dynamicConfig->sdramExtModeReg & ~EMC_SDRAM_BANKCS_BA_MASK) |\r
335                           EMC_SDRAM_BANKCS_BA1_MASK)\r
336                          << offset));\r
337                 /* Set the right mode setting value. */\r
338                 data = *(volatile uint32_t *)addr;\r
339                 data = data;\r
340                 dynamicConfig++;\r
341             }\r
342         }\r
343     }\r
344 \r
345     /* Step 6. issue normal operation command. */\r
346     base->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */\r
347 \r
348     /* The buffer shall be disabled when do the sdram initialization and\r
349      * enabled after the initialization during normal opeation.\r
350      */\r
351     dynamicConfig = config;\r
352     for (count = 0; (count < totalChips); count++)\r
353     {\r
354         if (NULL == dynamicConfig)\r
355         {\r
356             break;\r
357         }\r
358         else\r
359         {\r
360             base->DYNAMIC[dynamicConfig->chipIndex].DYNAMICCONFIG |= EMC_DYNAMIC_DYNAMICCONFIG_B_MASK;\r
361             dynamicConfig++;\r
362         }\r
363     }\r
364 }\r
365 \r
366 /*!\r
367  * brief Initializes the static memory controller.\r
368  * This function initializes the static memory controller in external memory controller.\r
369  * This function must be called after EMC_Init and before accessing the external static memory.\r
370  *\r
371  * param base EMC peripheral base address.\r
372  * param extWait_Ns The extended wait timeout or the read/write transfer time.\r
373  *        This is common for all static memory chips and set with NULL if not required.\r
374  * param configure The EMC static memory controller chip independent configuration pointer.\r
375  *       This configuration pointer is actually pointer to a configration array. the array number\r
376  *       depends on the "totalChips".\r
377  * param totalChips The total static memory chip numbers been used or the length of the\r
378  *        "emc_static_chip_config_t" type memory.\r
379  */\r
380 void EMC_StaticMemInit(EMC_Type *base, uint32_t *extWait_Ns, emc_static_chip_config_t *config, uint32_t totalChips)\r
381 {\r
382     assert(NULL != config);\r
383 \r
384     uint32_t count;\r
385     emc_static_chip_config_t *staticConfig = config;\r
386 \r
387     /* Initialize extended wait. */\r
388     if (NULL != extWait_Ns)\r
389     {\r
390         for (count = 0; (count < totalChips) && (staticConfig != NULL); count++)\r
391         {\r
392             assert(0U != (staticConfig->specailConfig & (uint32_t)kEMC_AsynchronosPageEnable));\r
393         }\r
394 \r
395         base->STATICEXTENDEDWAIT = EMC_CalculateTimerCycles(base, *extWait_Ns, 1);\r
396         staticConfig++;\r
397     }\r
398 \r
399     /* Initialize the static memory chip specific configure. */\r
400     staticConfig = config;\r
401     for (count = 0; (count < totalChips); count++)\r
402     {\r
403         if (NULL == staticConfig)\r
404         {\r
405             break;\r
406         }\r
407         else\r
408         {\r
409             base->STATIC[staticConfig->chipIndex].STATICCONFIG =\r
410                 (staticConfig->specailConfig | (uint32_t)staticConfig->memWidth);\r
411             base->STATIC[staticConfig->chipIndex].STATICWAITWEN =\r
412                 EMC_CalculateTimerCycles(base, staticConfig->tWaitWriteEn_Ns, 1);\r
413             base->STATIC[staticConfig->chipIndex].STATICWAITOEN =\r
414                 EMC_CalculateTimerCycles(base, staticConfig->tWaitOutEn_Ns, 0);\r
415             base->STATIC[staticConfig->chipIndex].STATICWAITRD =\r
416                 EMC_CalculateTimerCycles(base, staticConfig->tWaitReadNoPage_Ns, 1);\r
417             base->STATIC[staticConfig->chipIndex].STATICWAITPAGE =\r
418                 EMC_CalculateTimerCycles(base, staticConfig->tWaitReadPage_Ns, 1);\r
419             base->STATIC[staticConfig->chipIndex].STATICWAITWR =\r
420                 EMC_CalculateTimerCycles(base, staticConfig->tWaitWrite_Ns, 2);\r
421             base->STATIC[staticConfig->chipIndex].STATICWAITTURN =\r
422                 EMC_CalculateTimerCycles(base, staticConfig->tWaitTurn_Ns, 1);\r
423 \r
424             staticConfig++;\r
425         }\r
426     }\r
427 }\r
428 \r
429 /*!\r
430  * brief Deinitializes the EMC module and gates the clock.\r
431  * This function gates the EMC controller clock. As a result, the EMC\r
432  * module doesn't work after calling this function.\r
433  *\r
434  * param base EMC peripheral base address.\r
435  */\r
436 void EMC_Deinit(EMC_Type *base)\r
437 {\r
438     /* Deinit the EMC. */\r
439     base->CONTROL &= ~EMC_CONTROL_E_MASK;\r
440 \r
441 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)\r
442     /* Disable the clock. */\r
443     CLOCK_DisableClock(s_EMCClock[EMC_GetInstance(base)]);\r
444 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */\r
445 }\r