dram_win.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * Copyright (C) 2018-2021 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <string.h>
  8. #include <lib/mmio.h>
  9. #include <dram_win.h>
  10. #include <marvell_plat_priv.h>
  11. #include <mvebu.h>
  12. #include <plat_marvell.h>
  13. /* Armada 3700 has 5 configurable windows */
  14. #define MV_CPU_WIN_NUM 5
  15. #define CPU_WIN_DISABLED 0
  16. #define CPU_WIN_ENABLED 1
  17. /*
  18. * There are 2 different cpu decode window configuration cases:
  19. * - DRAM size is not over 2GB;
  20. * - DRAM size is 4GB.
  21. */
  22. enum cpu_win_config_num {
  23. CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB = 0,
  24. CPU_WIN_CONFIG_DRAM_4GB,
  25. CPU_WIN_CONFIG_MAX
  26. };
  27. enum cpu_win_target {
  28. CPU_WIN_TARGET_DRAM = 0,
  29. CPU_WIN_TARGET_INTERNAL_REG,
  30. CPU_WIN_TARGET_PCIE,
  31. CPU_WIN_TARGET_PCIE_OVER_MCI,
  32. CPU_WIN_TARGET_BOOT_ROM,
  33. CPU_WIN_TARGET_MCI_EXTERNAL,
  34. CPU_WIN_TARGET_RWTM_RAM = 7,
  35. CPU_WIN_TARGET_CCI400_REG
  36. };
  37. struct cpu_win_configuration {
  38. uint32_t enabled;
  39. enum cpu_win_target target;
  40. uint64_t base_addr;
  41. uint64_t size;
  42. uint64_t remap_addr;
  43. };
  44. struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = {
  45. /*
  46. * When total dram size is not over 2GB:
  47. * DDR window 0 is configured in tim header, its size may be not 512MB,
  48. * but the actual dram size, no need to configure it again;
  49. * other cpu windows are kept as default.
  50. */
  51. {
  52. /* enabled
  53. * target
  54. * base
  55. * size
  56. * remap
  57. */
  58. {CPU_WIN_ENABLED,
  59. CPU_WIN_TARGET_DRAM,
  60. 0x0,
  61. 0x08000000,
  62. 0x0},
  63. {CPU_WIN_ENABLED,
  64. CPU_WIN_TARGET_MCI_EXTERNAL,
  65. 0xe0000000,
  66. 0x08000000,
  67. 0xe0000000},
  68. {CPU_WIN_ENABLED,
  69. CPU_WIN_TARGET_PCIE,
  70. 0xe8000000,
  71. 0x08000000,
  72. 0xe8000000},
  73. {CPU_WIN_ENABLED,
  74. CPU_WIN_TARGET_RWTM_RAM,
  75. 0xf0000000,
  76. 0x00020000,
  77. 0x1fff0000},
  78. {CPU_WIN_ENABLED,
  79. CPU_WIN_TARGET_PCIE_OVER_MCI,
  80. 0x80000000,
  81. 0x10000000,
  82. 0x80000000},
  83. },
  84. /*
  85. * If total DRAM size is more than 2GB, now there is only one case:
  86. * 4GB of DRAM; to better utilize address space (for maximization of
  87. * DRAM usage), we will use the configuration of CPU windows below:
  88. * - Internal Regs and Boot ROM windows are kept as default;
  89. * - CCI-400 is moved from its default address to another address
  90. * (this is actually done even if DRAM size is not more than 2 GB,
  91. * because the firmware is compiled with that address as a
  92. * constant);
  93. * - PCIe window is moved to another address;
  94. * - Use 4 CPU decode windows for DRAM, which cover 3.75GB DRAM;
  95. * DDR window 0 is configured in tim header with 2G B size, no need
  96. * to configure it again here;
  97. *
  98. * 0xFFFFFFFF ---> +-----------------------+
  99. * | Boot ROM | 1 MB
  100. * | AP Boot ROM - 16 KB: |
  101. * | 0xFFFF0000-0xFFFF4000 |
  102. * 0xFFF00000 ---> +-----------------------+
  103. * : :
  104. * 0xFE010000 ---> +-----------------------+
  105. * | CCI Regs | 64 KB
  106. * 0xFE000000 ---> +-----------------------+
  107. * : :
  108. * 0xFA000000 ---> +-----------------------+
  109. * | PCIE | 128 MB
  110. * 0xF2000000 ---> +-----------------------+
  111. * | DDR window 3 | 512 MB
  112. * 0xD2000000 ---> +-----------------------+
  113. * | Internal Regs | 32 MB
  114. * 0xD0000000 ---> |-----------------------|
  115. * | DDR window 2 | 256 MB
  116. * 0xC0000000 ---> |-----------------------|
  117. * | |
  118. * | DDR window 1 | 1 GB
  119. * | |
  120. * 0x80000000 ---> |-----------------------|
  121. * | |
  122. * | |
  123. * | DDR window 0 | 2 GB
  124. * | |
  125. * | |
  126. * 0x00000000 ---> +-----------------------+
  127. */
  128. {
  129. /* win_id
  130. * target
  131. * base
  132. * size
  133. * remap
  134. */
  135. {CPU_WIN_ENABLED,
  136. CPU_WIN_TARGET_DRAM,
  137. 0x0,
  138. 0x80000000,
  139. 0x0},
  140. {CPU_WIN_ENABLED,
  141. CPU_WIN_TARGET_DRAM,
  142. 0x80000000,
  143. 0x40000000,
  144. 0x80000000},
  145. {CPU_WIN_ENABLED,
  146. CPU_WIN_TARGET_DRAM,
  147. 0xc0000000,
  148. 0x10000000,
  149. 0xc0000000},
  150. {CPU_WIN_ENABLED,
  151. CPU_WIN_TARGET_DRAM,
  152. 0xd2000000,
  153. 0x20000000,
  154. 0xd2000000},
  155. {CPU_WIN_ENABLED,
  156. CPU_WIN_TARGET_PCIE,
  157. 0xf2000000,
  158. 0x08000000,
  159. 0xf2000000},
  160. },
  161. };
  162. /*
  163. * dram_win_map_build
  164. *
  165. * This function builds cpu dram windows mapping
  166. * which includes base address and window size by
  167. * reading cpu dram decode windows registers.
  168. *
  169. * @input: N/A
  170. *
  171. * @output:
  172. * - win_map: cpu dram windows mapping
  173. *
  174. * @return: N/A
  175. */
  176. void dram_win_map_build(struct dram_win_map *win_map)
  177. {
  178. int32_t win_id;
  179. struct dram_win *win;
  180. uint32_t base_reg, ctrl_reg, size_reg, enabled, target;
  181. memset(win_map, 0, sizeof(struct dram_win_map));
  182. for (win_id = 0; win_id < DRAM_WIN_MAP_NUM_MAX; win_id++) {
  183. ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
  184. target = (ctrl_reg & CPU_DEC_CR_WIN_TARGET_MASK) >>
  185. CPU_DEC_CR_WIN_TARGET_OFFS;
  186. enabled = ctrl_reg & CPU_DEC_CR_WIN_ENABLE;
  187. /* Ignore invalid and non-dram windows*/
  188. if ((enabled == 0) || (target != DRAM_CPU_DEC_TARGET_NUM))
  189. continue;
  190. win = win_map->dram_windows + win_map->dram_win_num;
  191. base_reg = mmio_read_32(CPU_DEC_WIN_BASE_REG(win_id));
  192. size_reg = mmio_read_32(CPU_DEC_WIN_SIZE_REG(win_id));
  193. /* Base reg [15:0] corresponds to transaction address [39:16] */
  194. win->base_addr = (base_reg & CPU_DEC_BR_BASE_MASK) >>
  195. CPU_DEC_BR_BASE_OFFS;
  196. win->base_addr *= CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
  197. /*
  198. * Size reg [15:0] is programmed from LSB to MSB as a sequence
  199. * of 1s followed by a sequence of 0s and the number of 1s
  200. * specifies the size of the window in 64 KB granularity,
  201. * for example, a value of 00FFh specifies 256 x 64 KB = 16 MB
  202. */
  203. win->win_size = (size_reg & CPU_DEC_CR_WIN_SIZE_MASK) >>
  204. CPU_DEC_CR_WIN_SIZE_OFFS;
  205. win->win_size = (win->win_size + 1) *
  206. CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
  207. win_map->dram_win_num++;
  208. }
  209. }
  210. static void cpu_win_set(uint32_t win_id, struct cpu_win_configuration *win_cfg)
  211. {
  212. uint32_t base_reg, ctrl_reg, size_reg, remap_reg;
  213. /* Disable window */
  214. ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
  215. ctrl_reg &= ~CPU_DEC_CR_WIN_ENABLE;
  216. mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
  217. /* For an disabled window, only disable it. */
  218. if (!win_cfg->enabled)
  219. return;
  220. /* Set Base Register */
  221. base_reg = (uint32_t)(win_cfg->base_addr /
  222. CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
  223. base_reg <<= CPU_DEC_BR_BASE_OFFS;
  224. base_reg &= CPU_DEC_BR_BASE_MASK;
  225. mmio_write_32(CPU_DEC_WIN_BASE_REG(win_id), base_reg);
  226. /* Set Remap Register with the same value
  227. * as the <Base> field in Base Register
  228. */
  229. remap_reg = (uint32_t)(win_cfg->remap_addr /
  230. CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
  231. remap_reg <<= CPU_DEC_RLR_REMAP_LOW_OFFS;
  232. remap_reg &= CPU_DEC_RLR_REMAP_LOW_MASK;
  233. mmio_write_32(CPU_DEC_REMAP_LOW_REG(win_id), remap_reg);
  234. /* Set Size Register */
  235. size_reg = (win_cfg->size / CPU_DEC_CR_WIN_SIZE_ALIGNMENT) - 1;
  236. size_reg <<= CPU_DEC_CR_WIN_SIZE_OFFS;
  237. size_reg &= CPU_DEC_CR_WIN_SIZE_MASK;
  238. mmio_write_32(CPU_DEC_WIN_SIZE_REG(win_id), size_reg);
  239. /* Set Control Register - set target id and enable window */
  240. ctrl_reg &= ~CPU_DEC_CR_WIN_TARGET_MASK;
  241. ctrl_reg |= (win_cfg->target << CPU_DEC_CR_WIN_TARGET_OFFS);
  242. ctrl_reg |= CPU_DEC_CR_WIN_ENABLE;
  243. mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
  244. }
  245. void cpu_wins_init(void)
  246. {
  247. uint32_t cfg_idx, win_id;
  248. if (mvebu_get_dram_size(MVEBU_REGS_BASE) <= _2GB_)
  249. cfg_idx = CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB;
  250. else
  251. cfg_idx = CPU_WIN_CONFIG_DRAM_4GB;
  252. /* Window 0 is configured always for DRAM in tim header
  253. * already, no need to configure it again here
  254. */
  255. for (win_id = 1; win_id < MV_CPU_WIN_NUM; win_id++)
  256. cpu_win_set(win_id, &mv_cpu_wins[cfg_idx][win_id]);
  257. }