2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
\r
3 * Copyright 2016-2019 NXP
\r
4 * All rights reserved.
\r
6 * SPDX-License-Identifier: BSD-3-Clause
\r
11 /*******************************************************************************
\r
13 ******************************************************************************/
\r
15 /* Component ID definition, used by tools. */
\r
16 #ifndef FSL_COMPONENT_ID
\r
17 #define FSL_COMPONENT_ID "platform.drivers.emc"
\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
35 /*******************************************************************************
\r
37 ******************************************************************************/
\r
39 * @brief Get instance number for EMC module.
\r
41 * @param base EMC peripheral base address
\r
43 static uint32_t EMC_GetInstance(EMC_Type *base);
\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
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
55 static uint32_t EMC_CalculateTimerCycles(EMC_Type *base, uint32_t timer_Ns, uint32_t plus);
\r
58 * @brief Get the shift value to shift the mode register content by.
\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
64 static uint32_t EMC_ModeOffset(uint32_t addrMap);
\r
66 /*******************************************************************************
\r
68 ******************************************************************************/
\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
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
80 /*! @brief Pointers to EMC bases for each instance. */
\r
81 static const EMC_Type *const s_EMCBases[] = EMC_BASE_PTRS;
\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
87 ******************************************************************************/
\r
89 static uint32_t EMC_GetInstance(EMC_Type *base)
\r
93 /* Find the instance index from base address mappings. */
\r
94 for (instance = 0; instance < ARRAY_SIZE(s_EMCBases); instance++)
\r
96 if (s_EMCBases[instance] == base)
\r
102 assert(instance < ARRAY_SIZE(s_EMCBases));
\r
107 static uint32_t EMC_CalculateTimerCycles(EMC_Type *base, uint32_t timer_Ns, uint32_t plus)
\r
111 cycles = CLOCK_GetEmcClkFreq() / EMC_HZ_ONEMHZ * timer_Ns;
\r
112 cycles = EMC_DIV_ROUND_UP(cycles, EMC_MILLISECS_ONESEC); /* Round up. */
\r
114 /* Decrese according to the plus. */
\r
115 if (cycles >= plus)
\r
117 cycles = cycles - plus;
\r
127 static uint32_t EMC_ModeOffset(uint32_t addrMap)
\r
129 uint8_t offset = 0;
\r
130 uint32_t columbase = addrMap & EMC_DYNCTL_COLUMNBASE_MASK;
\r
132 /* First calculate the column length. */
\r
133 if (columbase == 2U)
\r
139 if (0U == columbase)
\r
148 /* Add column length increase check. */
\r
149 offset += (uint8_t)((addrMap & EMC_DYNCTL_COLUMNPLUS_MASK) >> EMC_DYNCTL_COLUMNPLUS_OFFSET);
\r
152 /* Add Buswidth/16. */
\r
153 if (0U != (addrMap & EMC_DYNCTL_BUSWIDTH_MASK))
\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
165 if (0U == (addrMap & EMC_DYNCTL_DEVBANKS_BITS_MASK))
\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
184 * param base EMC peripheral base address.
\r
185 * param config The EMC basic configuration.
\r
187 void EMC_Init(EMC_Type *base, emc_basic_config_t *config)
\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
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
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
203 /* Set the EMC sytem configure. */
\r
204 SYSCON->EMCCLKDIV = SYSCON_EMCCLKDIV_DIV(config->emcClkDiv);
\r
206 SYSCON->EMCSYSCTRL = SYSCON_EMCSYSCTRL_EMCFBCLKINSEL(config->fbClkSrc);
\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
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
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
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
234 assert(NULL != config);
\r
235 assert(NULL != timing);
\r
236 assert(totalChips <= EMC_DYNAMIC_MEMDEV_NUM);
\r
239 uint32_t casLatency;
\r
243 emc_dynamic_chip_config_t *dynamicConfig = config;
\r
245 /* Setting for dynamic memory controller chip independent configuration. */
\r
246 for (count = 0; (count < totalChips); count++)
\r
248 if (NULL == dynamicConfig)
\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
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
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
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
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
291 base->DYNAMICREFRESH = EMC_CalculateTimerCycles(base, timing->refreshPeriod_Nanosec, 0) / EMC_REFRESH_CLOCK_PARAM;
\r
293 /* Step 5. issue a mode command and set the mode value. */
\r
294 base->DYNAMICCONTROL = 0x00000083;
\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
300 if (NULL == dynamicConfig)
\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
317 if (kEMC_Sdram != config->dynamicDevice)
\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
325 if (NULL == dynamicConfig)
\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
337 /* Set the right mode setting value. */
\r
338 data = *(volatile uint32_t *)addr;
\r
345 /* Step 6. issue normal operation command. */
\r
346 base->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
\r
348 /* The buffer shall be disabled when do the sdram initialization and
\r
349 * enabled after the initialization during normal opeation.
\r
351 dynamicConfig = config;
\r
352 for (count = 0; (count < totalChips); count++)
\r
354 if (NULL == dynamicConfig)
\r
360 base->DYNAMIC[dynamicConfig->chipIndex].DYNAMICCONFIG |= EMC_DYNAMIC_DYNAMICCONFIG_B_MASK;
\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
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
380 void EMC_StaticMemInit(EMC_Type *base, uint32_t *extWait_Ns, emc_static_chip_config_t *config, uint32_t totalChips)
\r
382 assert(NULL != config);
\r
385 emc_static_chip_config_t *staticConfig = config;
\r
387 /* Initialize extended wait. */
\r
388 if (NULL != extWait_Ns)
\r
390 for (count = 0; (count < totalChips) && (staticConfig != NULL); count++)
\r
392 assert(0U != (staticConfig->specailConfig & (uint32_t)kEMC_AsynchronosPageEnable));
\r
395 base->STATICEXTENDEDWAIT = EMC_CalculateTimerCycles(base, *extWait_Ns, 1);
\r
399 /* Initialize the static memory chip specific configure. */
\r
400 staticConfig = config;
\r
401 for (count = 0; (count < totalChips); count++)
\r
403 if (NULL == staticConfig)
\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
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
434 * param base EMC peripheral base address.
\r
436 void EMC_Deinit(EMC_Type *base)
\r
438 /* Deinit the EMC. */
\r
439 base->CONTROL &= ~EMC_CONTROL_E_MASK;
\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