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