LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
emc_001.c
Go to the documentation of this file.
1 /*
2  * @brief EMC Registers and control functions
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "emc_001.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
38 /*****************************************************************************
39  * Public types/enumerations/variables
40  ****************************************************************************/
41 
42 /*****************************************************************************
43  * Private functions
44  ****************************************************************************/
45 
46 /* DIV function with result rounded up */
47 #define EMC_DIV_ROUND_UP(x, y) ((x + y - 1) / y)
48 
49 #ifndef EMC_SUPPORT_ONLY_PL172
50 /* Get ARM External Memory Controller Version */
51 static uint32_t EMC_GetARMPeripheralID(IP_EMC_001_Type *pEMC)
52 {
53  uint32_t *RegAdd;
54  RegAdd = (uint32_t *) ((uint32_t) pEMC + 0xFE0);
55  return (RegAdd[0] & 0xFF) | ((RegAdd[1] & 0xFF) << 8) |
56  ((RegAdd[2] & 0xFF) << 16) | (RegAdd[3] << 24);
57 }
58 
59 #endif
60 
61 /* Calculate Clock Count from Timing Unit(nanoseconds) */
62 static uint32_t EMC_TimingParamConvert(uint32_t EMC_Clock, int32_t input_ns, uint32_t adjust)
63 {
64  uint32_t temp;
65  if (input_ns < 0) {
66  return (-input_ns) >> 8;
67  }
68  temp = EMC_Clock / 1000000; /* MHz calculation */
69  temp = temp * input_ns / 1000;
70 
71  /* round up */
72  temp += 0xFF;
73 
74  /* convert to simple integer number format */
75  temp >>= 8;
76  if (temp > adjust) {
77  return temp - adjust;
78  }
79 
80  return 0;
81 }
82 
83 /* Get Dynamic Memory Device Colum len */
84 static uint32_t EMC_GetColsLen(uint32_t DynConfig)
85 {
86  uint32_t DevBusWidth;
87  DevBusWidth = (DynConfig >> EMC_DYN_CONFIG_DEV_BUS_BIT) & 0x03;
88  if (DevBusWidth == 2) {
89  return 8;
90  }
91  else if (DevBusWidth == 1) {
92  return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 8;
93  }
94  else if (DevBusWidth == 0) {
95  return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 9;
96  }
97 
98  return 0;
99 }
100 
101 /*****************************************************************************
102  * Public functions
103  ****************************************************************************/
104 
105 /* Initializes the Dynamic Controller according to the specified parameters
106  in the IP_EMC_DYN_CONFIG_Type */
108 {
109  uint32_t ChipSelect, tmpclk;
110  int i;
111 
112  for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
113  IP_EMC_001_Type *EMC_Reg_add = (IP_EMC_001_Type *) ((uint32_t) pEMC + (ChipSelect << 5));
114 
115  EMC_Reg_add->DYNAMICRASCAS0 = Dynamic_Config->DevConfig[ChipSelect].RAS |
116  ((Dynamic_Config->DevConfig[ChipSelect].ModeRegister <<
117  (8 - EMC_DYN_MODE_CAS_BIT)) & 0xF00);
118  EMC_Reg_add->DYNAMICCONFIG0 = Dynamic_Config->DevConfig[ChipSelect].DynConfig;
119  }
120  pEMC->DYNAMICREADCONFIG = Dynamic_Config->ReadConfig; /* Read strategy */
121 
122  pEMC->DYNAMICRP = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRP, 1);
123  pEMC->DYNAMICRAS = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRAS, 1);
124  pEMC->DYNAMICSREX = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tSREX, 1);
125  pEMC->DYNAMICAPR = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tAPR, 1);
126  pEMC->DYNAMICDAL = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tDAL, 0);
127  pEMC->DYNAMICWR = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tWR, 1);
128  pEMC->DYNAMICRC = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRC, 1);
129  pEMC->DYNAMICRFC = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRFC, 1);
130  pEMC->DYNAMICXSR = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tXSR, 1);
131  pEMC->DYNAMICRRD = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRRD, 1);
132  pEMC->DYNAMICMRD = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tMRD, 1);
133 
134  /* TIM_Waitus(100); */
135  /*TODO: if Timer driver is ready, it should replace below "for" delay technic */
136  for (i = 0; i < 1000; i++) { /* wait 100us */
137  }
138  pEMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
139 
140  /* TIM_Waitus(200); */ /* wait 200us */
141  /*TODO: if Timer driver is ready, it should replace below "for" delay technic */
142  for (i = 0; i < 1000; i++) {}
143  pEMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
144 
145  pEMC->DYNAMICREFRESH = 2; /* ( 2 * 16 ) -> 32 clock cycles */
146 
147  /* TIM_Waitus(200); */ /* wait 200us */
148  for (i = 0; i < 80; i++) {}
149 
150  tmpclk = EMC_DIV_ROUND_UP(EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->RefreshPeriod, 0), 16);
151  pEMC->DYNAMICREFRESH = tmpclk;
152 
153  pEMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */
154 
155  for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
156  /*uint32_t burst_length;*/
157  uint32_t DynAddr;
158  uint8_t Col_len;
159 
160  Col_len = EMC_GetColsLen(Dynamic_Config->DevConfig[ChipSelect].DynConfig);
161  /* get bus wide: if 32bit, len is 4 else if 16bit len is 2 */
162  /* burst_length = 1 << ((((Dynamic_Config->DynConfig[ChipSelect] >> 14) & 1)^1) +1); */
163  if (Dynamic_Config->DevConfig[ChipSelect].DynConfig & (1 << EMC_DYN_CONFIG_DATA_BUS_WIDTH_BIT)) {
164  /*32bit bus */
165  /*burst_length = 2;*/
166  Col_len += 2;
167  }
168  else {
169  /*burst_length = 4;*/
170  Col_len += 1;
171  }
172  DynAddr = Dynamic_Config->DevConfig[ChipSelect].BaseAddr;
173 
174  if (DynAddr != 0) {
175  uint32_t temp;
176  uint32_t ModeRegister;
177  ModeRegister = Dynamic_Config->DevConfig[ChipSelect].ModeRegister;
178  temp = *((volatile uint32_t *) (DynAddr | (ModeRegister << Col_len)));
179  temp = temp;
180  }
181  }
182  pEMC->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
183 
184  /* enable buffers */
185  pEMC->DYNAMICCONFIG0 |= 1 << 19;
186  pEMC->DYNAMICCONFIG1 |= 1 << 19;
187  pEMC->DYNAMICCONFIG2 |= 1 << 19;
188  pEMC->DYNAMICCONFIG3 |= 1 << 19;
189 }
190 
191 /* Set Deep Sleep Mode for Dynamic Memory Controller */
193 {
194  if (Enable) {
196  }
197  else {
199  }
200 }
201 
202 /* Enable Dynamic Memory Controller */
203 void IP_EMC_Dynamic_Enable(IP_EMC_001_Type *pEMC, uint8_t Enable)
204 {
205  if (Enable) {
207  }
208  else {
210  }
211 }
212 
213 /* Initializes the Static Controller according to the specified parameters
214  * in the IP_EMC_STATIC_CONFIG_Type
215  */
217 {
218  IP_EMC_001_Type *EMC_Reg_add = (IP_EMC_001_Type *) ((uint32_t) pEMC + ((Static_Config->ChipSelect) << 5));
219  EMC_Reg_add->STATICCONFIG0 = Static_Config->Config;
220  EMC_Reg_add->STATICWAITWEN0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitWen, 1);
221  EMC_Reg_add->STATICWAITOEN0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitOen, 0);
222  EMC_Reg_add->STATICWAITRD0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitRd, 1);
223  EMC_Reg_add->STATICWAITPAG0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitPage, 1);
224  EMC_Reg_add->STATICWAITWR0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitWr, 2);
225  EMC_Reg_add->STATICWAITTURN0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitTurn, 1);
226 }
227 
228 /* Mirror CS1 to CS0 and DYCS0 */
230 {
231  if (Enable) {
232  pEMC->CONTROL |= 1 << 1;
233  }
234  else {
235  pEMC->CONTROL &= ~(1 << 1);
236  }
237 }
238 
239 /* Enable EMC */
241 {
242  if (Enable) {
243  pEMC->CONTROL |= 1;
244  }
245  else {
246  pEMC->CONTROL &= ~(1);
247  }
248 }
249 
250 /* Set EMC LowPower Mode */
252 {
253  if (Enable) {
254  pEMC->CONTROL |= 1 << 2;
255  }
256  else {
257  pEMC->CONTROL &= ~(1 << 2);
258  }
259 }
260 
261 /* Initialize EMC */
262 void IP_EMC_Init(IP_EMC_001_Type *pEMC, uint32_t Enable, uint32_t ClockRatio, uint32_t EndianMode)
263 {
264  pEMC->CONFIG = (EndianMode ? 1 : 0) | ((ClockRatio ? 1 : 0) << 8);
265 
266  /* Enable EMC 001 Normal Memory Map, No low power mode */
267  pEMC->CONTROL = (Enable ? 1 : 0);
268 }
269 
270 /* Set Static Memory Extended Wait in Clock */
272 {
273  pEMC->STATICEXTENDEDWAIT = Wait16Clks;
274 }