emc_001.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. #include "emc_001.h"
  32. /*****************************************************************************
  33. * Private types/enumerations/variables
  34. ****************************************************************************/
  35. /*****************************************************************************
  36. * Public types/enumerations/variables
  37. ****************************************************************************/
  38. /*****************************************************************************
  39. * Private functions
  40. ****************************************************************************/
  41. /* DIV function with result rounded up */
  42. #define EMC_DIV_ROUND_UP(x, y) ((x + y - 1) / y)
  43. #ifndef EMC_SUPPORT_ONLY_PL172
  44. /* Get ARM External Memory Controller Version */
  45. static uint32_t EMC_GetARMPeripheralID(IP_EMC_001_Type *pEMC)
  46. {
  47. uint32_t *RegAdd;
  48. RegAdd = (uint32_t *) ((uint32_t) pEMC + 0xFE0);
  49. return (RegAdd[0] & 0xFF) | ((RegAdd[1] & 0xFF) << 8) |
  50. ((RegAdd[2] & 0xFF) << 16) | (RegAdd[3] << 24);
  51. }
  52. #endif
  53. /* Calculate Clock Count from Timing Unit(nanoseconds) */
  54. static uint32_t EMC_TimingParamConvert(uint32_t EMC_Clock, int32_t input_ns, uint32_t adjust)
  55. {
  56. uint32_t temp;
  57. if (input_ns < 0) {
  58. return (-input_ns) >> 8;
  59. }
  60. temp = EMC_Clock / 1000000; /* MHz calculation */
  61. temp = temp * input_ns / 1000;
  62. /* round up */
  63. temp += 0xFF;
  64. /* convert to simple integer number format */
  65. temp >>= 8;
  66. if (temp > adjust) {
  67. return temp - adjust;
  68. }
  69. return 0;
  70. }
  71. /* Get Dynamic Memory Device Colum len */
  72. static uint32_t EMC_GetColsLen(uint32_t DynConfig)
  73. {
  74. uint32_t DevBusWidth;
  75. DevBusWidth = (DynConfig >> EMC_DYN_CONFIG_DEV_BUS_BIT) & 0x03;
  76. if (DevBusWidth == 2) {
  77. return 8;
  78. }
  79. else if (DevBusWidth == 1) {
  80. return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 8;
  81. }
  82. else if (DevBusWidth == 0) {
  83. return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 9;
  84. }
  85. return 0;
  86. }
  87. /*****************************************************************************
  88. * Public functions
  89. ****************************************************************************/
  90. /* Initializes the Dynamic Controller according to the specified parameters
  91. in the IP_EMC_DYN_CONFIG_Type */
  92. void IP_EMC_Dynamic_Init(IP_EMC_001_Type *pEMC, IP_EMC_DYN_CONFIG_Type *Dynamic_Config, uint32_t EMC_Clock)
  93. {
  94. uint32_t ChipSelect, tmpclk;
  95. int i;
  96. for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
  97. IP_EMC_001_Type *EMC_Reg_add = (IP_EMC_001_Type *) ((uint32_t) pEMC + (ChipSelect << 5));
  98. EMC_Reg_add->DYNAMICRASCAS0 = Dynamic_Config->DevConfig[ChipSelect].RAS |
  99. ((Dynamic_Config->DevConfig[ChipSelect].ModeRegister <<
  100. (8 - EMC_DYN_MODE_CAS_BIT)) & 0xF00);
  101. EMC_Reg_add->DYNAMICCONFIG0 = Dynamic_Config->DevConfig[ChipSelect].DynConfig;
  102. }
  103. pEMC->DYNAMICREADCONFIG = Dynamic_Config->ReadConfig; /* Read strategy */
  104. pEMC->DYNAMICRP = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRP, 1);
  105. pEMC->DYNAMICRAS = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRAS, 1);
  106. pEMC->DYNAMICSREX = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tSREX, 1);
  107. pEMC->DYNAMICAPR = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tAPR, 1);
  108. pEMC->DYNAMICDAL = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tDAL, 0);
  109. pEMC->DYNAMICWR = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tWR, 1);
  110. pEMC->DYNAMICRC = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRC, 1);
  111. pEMC->DYNAMICRFC = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRFC, 1);
  112. pEMC->DYNAMICXSR = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tXSR, 1);
  113. pEMC->DYNAMICRRD = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tRRD, 1);
  114. pEMC->DYNAMICMRD = EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->tMRD, 1);
  115. /* TIM_Waitus(100); */
  116. /*TODO: if Timer driver is ready, it should replace below "for" delay technic */
  117. for (i = 0; i < 1000; i++) { /* wait 100us */
  118. }
  119. pEMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
  120. /* TIM_Waitus(200); */ /* wait 200us */
  121. /*TODO: if Timer driver is ready, it should replace below "for" delay technic */
  122. for (i = 0; i < 1000; i++) {}
  123. pEMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
  124. pEMC->DYNAMICREFRESH = 2; /* ( 2 * 16 ) -> 32 clock cycles */
  125. /* TIM_Waitus(200); */ /* wait 200us */
  126. for (i = 0; i < 80; i++) {}
  127. tmpclk = EMC_DIV_ROUND_UP(EMC_TimingParamConvert(EMC_Clock, Dynamic_Config->RefreshPeriod, 0), 16);
  128. pEMC->DYNAMICREFRESH = tmpclk;
  129. pEMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */
  130. for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
  131. /*uint32_t burst_length;*/
  132. uint32_t DynAddr;
  133. uint8_t Col_len;
  134. Col_len = EMC_GetColsLen(Dynamic_Config->DevConfig[ChipSelect].DynConfig);
  135. /* get bus wide: if 32bit, len is 4 else if 16bit len is 2 */
  136. /* burst_length = 1 << ((((Dynamic_Config->DynConfig[ChipSelect] >> 14) & 1)^1) +1); */
  137. if (Dynamic_Config->DevConfig[ChipSelect].DynConfig & (1 << EMC_DYN_CONFIG_DATA_BUS_WIDTH_BIT)) {
  138. /*32bit bus */
  139. /*burst_length = 2;*/
  140. Col_len += 2;
  141. }
  142. else {
  143. /*burst_length = 4;*/
  144. Col_len += 1;
  145. }
  146. DynAddr = Dynamic_Config->DevConfig[ChipSelect].BaseAddr;
  147. if (DynAddr != 0) {
  148. uint32_t temp;
  149. uint32_t ModeRegister;
  150. ModeRegister = Dynamic_Config->DevConfig[ChipSelect].ModeRegister;
  151. temp = *((volatile uint32_t *) (DynAddr | (ModeRegister << Col_len)));
  152. temp = temp;
  153. }
  154. }
  155. pEMC->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
  156. /* enable buffers */
  157. pEMC->DYNAMICCONFIG0 |= 1 << 19;
  158. pEMC->DYNAMICCONFIG1 |= 1 << 19;
  159. pEMC->DYNAMICCONFIG2 |= 1 << 19;
  160. pEMC->DYNAMICCONFIG3 |= 1 << 19;
  161. }
  162. /* Set Deep Sleep Mode for Dynamic Memory Controller */
  163. void IP_EMC_Dynamic_DeepSleepMode(IP_EMC_001_Type *pEMC, uint32_t Enable)
  164. {
  165. if (Enable) {
  166. pEMC->DYNAMICCONTROL |= 1 << EMC_DYN_CONTROL_DEEPSLEEP_BIT;
  167. }
  168. else {
  169. pEMC->DYNAMICCONTROL &= ~(1 << EMC_DYN_CONTROL_DEEPSLEEP_BIT);
  170. }
  171. }
  172. /* Enable Dynamic Memory Controller */
  173. void IP_EMC_Dynamic_Enable(IP_EMC_001_Type *pEMC, uint8_t Enable)
  174. {
  175. if (Enable) {
  176. pEMC->DYNAMICCONTROL |= EMC_DYN_CONTROL_ENABLE;
  177. }
  178. else {
  179. pEMC->DYNAMICCONTROL &= ~EMC_DYN_CONTROL_ENABLE;
  180. }
  181. }
  182. /* Initializes the Static Controller according to the specified parameters
  183. * in the IP_EMC_STATIC_CONFIG_Type
  184. */
  185. void IP_EMC_Static_Init(IP_EMC_001_Type *pEMC, IP_EMC_STATIC_CONFIG_Type *Static_Config, uint32_t EMC_Clock)
  186. {
  187. IP_EMC_001_Type *EMC_Reg_add = (IP_EMC_001_Type *) ((uint32_t) pEMC + ((Static_Config->ChipSelect) << 5));
  188. EMC_Reg_add->STATICCONFIG0 = Static_Config->Config;
  189. EMC_Reg_add->STATICWAITWEN0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitWen, 1);
  190. EMC_Reg_add->STATICWAITOEN0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitOen, 0);
  191. EMC_Reg_add->STATICWAITRD0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitRd, 1);
  192. EMC_Reg_add->STATICWAITPAG0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitPage, 1);
  193. EMC_Reg_add->STATICWAITWR0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitWr, 2);
  194. EMC_Reg_add->STATICWAITTURN0 = EMC_TimingParamConvert(EMC_Clock, Static_Config->WaitTurn, 1);
  195. }
  196. /* Mirror CS1 to CS0 and DYCS0 */
  197. void IP_EMC_Mirror(IP_EMC_001_Type *pEMC, uint32_t Enable)
  198. {
  199. if (Enable) {
  200. pEMC->CONTROL |= 1 << 1;
  201. }
  202. else {
  203. pEMC->CONTROL &= ~(1 << 1);
  204. }
  205. }
  206. /* Enable EMC */
  207. void IP_EMC_Enable(IP_EMC_001_Type *pEMC, uint32_t Enable)
  208. {
  209. if (Enable) {
  210. pEMC->CONTROL |= 1;
  211. }
  212. else {
  213. pEMC->CONTROL &= ~(1);
  214. }
  215. }
  216. /* Set EMC LowPower Mode */
  217. void IP_EMC_LowPowerMode(IP_EMC_001_Type *pEMC, uint32_t Enable)
  218. {
  219. if (Enable) {
  220. pEMC->CONTROL |= 1 << 2;
  221. }
  222. else {
  223. pEMC->CONTROL &= ~(1 << 2);
  224. }
  225. }
  226. /* Initialize EMC */
  227. void IP_EMC_Init(IP_EMC_001_Type *pEMC, uint32_t Enable, uint32_t ClockRatio, uint32_t EndianMode)
  228. {
  229. pEMC->CONFIG = (EndianMode ? 1 : 0) | ((ClockRatio ? 1 : 0) << 8);
  230. /* Enable EMC 001 Normal Memory Map, No low power mode */
  231. pEMC->CONTROL = (Enable ? 1 : 0);
  232. }
  233. /* Set Static Memory Extended Wait in Clock */
  234. void IP_EMC_SetStaticExtendedWait(IP_EMC_001_Type *pEMC, uint32_t Wait16Clks)
  235. {
  236. pEMC->STATICEXTENDEDWAIT = Wait16Clks;
  237. }