dram_init.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2012-2015 Panasonic Corporation
  4. * Copyright (C) 2015-2017 Socionext Inc.
  5. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  6. */
  7. #include <init.h>
  8. #include <linux/errno.h>
  9. #include <linux/io.h>
  10. #include <linux/kernel.h>
  11. #include <linux/printk.h>
  12. #include <linux/sizes.h>
  13. #include <asm/global_data.h>
  14. #include <asm/u-boot.h>
  15. #include "init.h"
  16. #include "sg-regs.h"
  17. #include "soc-info.h"
  18. DECLARE_GLOBAL_DATA_PTR;
  19. struct uniphier_dram_map {
  20. unsigned long base;
  21. unsigned long size;
  22. };
  23. static int uniphier_memconf_decode(struct uniphier_dram_map *dram_map,
  24. unsigned long sparse_ch1_base, bool have_ch2)
  25. {
  26. unsigned long size;
  27. u32 val;
  28. val = readl(sg_base + SG_MEMCONF);
  29. /* set up ch0 */
  30. dram_map[0].base = 0x80000000;
  31. switch (val & SG_MEMCONF_CH0_SZ_MASK) {
  32. case SG_MEMCONF_CH0_SZ_64M:
  33. size = SZ_64M;
  34. break;
  35. case SG_MEMCONF_CH0_SZ_128M:
  36. size = SZ_128M;
  37. break;
  38. case SG_MEMCONF_CH0_SZ_256M:
  39. size = SZ_256M;
  40. break;
  41. case SG_MEMCONF_CH0_SZ_512M:
  42. size = SZ_512M;
  43. break;
  44. case SG_MEMCONF_CH0_SZ_1G:
  45. size = SZ_1G;
  46. break;
  47. default:
  48. pr_err("error: invalid value is set to MEMCONF ch0 size\n");
  49. return -EINVAL;
  50. }
  51. if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2)
  52. size *= 2;
  53. dram_map[0].size = size;
  54. /* set up ch1 */
  55. dram_map[1].base = dram_map[0].base + size;
  56. if (val & SG_MEMCONF_SPARSEMEM) {
  57. if (dram_map[1].base > sparse_ch1_base) {
  58. pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n");
  59. pr_warn("Only ch0 is available\n");
  60. dram_map[1].base = 0;
  61. return 0;
  62. }
  63. dram_map[1].base = sparse_ch1_base;
  64. }
  65. switch (val & SG_MEMCONF_CH1_SZ_MASK) {
  66. case SG_MEMCONF_CH1_SZ_64M:
  67. size = SZ_64M;
  68. break;
  69. case SG_MEMCONF_CH1_SZ_128M:
  70. size = SZ_128M;
  71. break;
  72. case SG_MEMCONF_CH1_SZ_256M:
  73. size = SZ_256M;
  74. break;
  75. case SG_MEMCONF_CH1_SZ_512M:
  76. size = SZ_512M;
  77. break;
  78. case SG_MEMCONF_CH1_SZ_1G:
  79. size = SZ_1G;
  80. break;
  81. default:
  82. pr_err("error: invalid value is set to MEMCONF ch1 size\n");
  83. return -EINVAL;
  84. }
  85. if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2)
  86. size *= 2;
  87. dram_map[1].size = size;
  88. if (!have_ch2 || val & SG_MEMCONF_CH2_DISABLE)
  89. return 0;
  90. /* set up ch2 */
  91. dram_map[2].base = dram_map[1].base + size;
  92. switch (val & SG_MEMCONF_CH2_SZ_MASK) {
  93. case SG_MEMCONF_CH2_SZ_64M:
  94. size = SZ_64M;
  95. break;
  96. case SG_MEMCONF_CH2_SZ_128M:
  97. size = SZ_128M;
  98. break;
  99. case SG_MEMCONF_CH2_SZ_256M:
  100. size = SZ_256M;
  101. break;
  102. case SG_MEMCONF_CH2_SZ_512M:
  103. size = SZ_512M;
  104. break;
  105. case SG_MEMCONF_CH2_SZ_1G:
  106. size = SZ_1G;
  107. break;
  108. default:
  109. pr_err("error: invalid value is set to MEMCONF ch2 size\n");
  110. return -EINVAL;
  111. }
  112. if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2)
  113. size *= 2;
  114. dram_map[2].size = size;
  115. return 0;
  116. }
  117. static int uniphier_ld4_dram_map_get(struct uniphier_dram_map dram_map[])
  118. {
  119. return uniphier_memconf_decode(dram_map, 0xc0000000, false);
  120. }
  121. static int uniphier_pro4_dram_map_get(struct uniphier_dram_map dram_map[])
  122. {
  123. return uniphier_memconf_decode(dram_map, 0xa0000000, false);
  124. }
  125. static int uniphier_pxs2_dram_map_get(struct uniphier_dram_map dram_map[])
  126. {
  127. return uniphier_memconf_decode(dram_map, 0xc0000000, true);
  128. }
  129. struct uniphier_dram_init_data {
  130. unsigned int soc_id;
  131. int (*dram_map_get)(struct uniphier_dram_map dram_map[]);
  132. };
  133. static const struct uniphier_dram_init_data uniphier_dram_init_data[] = {
  134. {
  135. .soc_id = UNIPHIER_LD4_ID,
  136. .dram_map_get = uniphier_ld4_dram_map_get,
  137. },
  138. {
  139. .soc_id = UNIPHIER_PRO4_ID,
  140. .dram_map_get = uniphier_pro4_dram_map_get,
  141. },
  142. {
  143. .soc_id = UNIPHIER_SLD8_ID,
  144. .dram_map_get = uniphier_ld4_dram_map_get,
  145. },
  146. {
  147. .soc_id = UNIPHIER_PRO5_ID,
  148. .dram_map_get = uniphier_ld4_dram_map_get,
  149. },
  150. {
  151. .soc_id = UNIPHIER_PXS2_ID,
  152. .dram_map_get = uniphier_pxs2_dram_map_get,
  153. },
  154. {
  155. .soc_id = UNIPHIER_LD6B_ID,
  156. .dram_map_get = uniphier_pxs2_dram_map_get,
  157. },
  158. {
  159. .soc_id = UNIPHIER_LD11_ID,
  160. .dram_map_get = uniphier_ld4_dram_map_get,
  161. },
  162. {
  163. .soc_id = UNIPHIER_LD20_ID,
  164. .dram_map_get = uniphier_pxs2_dram_map_get,
  165. },
  166. {
  167. .soc_id = UNIPHIER_PXS3_ID,
  168. .dram_map_get = uniphier_pxs2_dram_map_get,
  169. },
  170. };
  171. UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_dram_init_data,
  172. uniphier_dram_init_data)
  173. static int uniphier_dram_map_get(struct uniphier_dram_map *dram_map)
  174. {
  175. const struct uniphier_dram_init_data *data;
  176. data = uniphier_get_dram_init_data();
  177. if (!data) {
  178. pr_err("unsupported SoC\n");
  179. return -ENOTSUPP;
  180. }
  181. return data->dram_map_get(dram_map);
  182. }
  183. int dram_init(void)
  184. {
  185. struct uniphier_dram_map dram_map[3] = {};
  186. bool valid_bank_found = false;
  187. unsigned long prev_top;
  188. int ret, i;
  189. gd->ram_size = 0;
  190. ret = uniphier_dram_map_get(dram_map);
  191. if (ret)
  192. return ret;
  193. for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
  194. unsigned long max_size;
  195. if (!dram_map[i].size)
  196. continue;
  197. /*
  198. * U-Boot relocates itself to the tail of the memory region,
  199. * but it does not expect sparse memory. We use the first
  200. * contiguous chunk here.
  201. */
  202. if (valid_bank_found && prev_top < dram_map[i].base)
  203. break;
  204. /*
  205. * Do not use memory that exceeds 32bit address range. U-Boot
  206. * relocates itself to the end of the effectively available RAM.
  207. * This could be a problem for DMA engines that do not support
  208. * 64bit address (SDMA of SDHCI, UniPhier AV-ether, etc.)
  209. */
  210. if (dram_map[i].base >= 1ULL << 32)
  211. break;
  212. max_size = (1ULL << 32) - dram_map[i].base;
  213. gd->ram_size = min(dram_map[i].size, max_size);
  214. if (!valid_bank_found)
  215. gd->ram_base = dram_map[i].base;
  216. prev_top = dram_map[i].base + dram_map[i].size;
  217. valid_bank_found = true;
  218. }
  219. /*
  220. * LD20 uses the last 64 byte for each channel for dynamic
  221. * DDR PHY training
  222. */
  223. if (uniphier_get_soc_id() == UNIPHIER_LD20_ID)
  224. gd->ram_size -= 64;
  225. return 0;
  226. }
  227. int dram_init_banksize(void)
  228. {
  229. struct uniphier_dram_map dram_map[3] = {};
  230. unsigned long base, top;
  231. bool valid_bank_found = false;
  232. int ret, i;
  233. ret = uniphier_dram_map_get(dram_map);
  234. if (ret)
  235. return ret;
  236. for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
  237. if (i < ARRAY_SIZE(gd->bd->bi_dram)) {
  238. gd->bd->bi_dram[i].start = dram_map[i].base;
  239. gd->bd->bi_dram[i].size = dram_map[i].size;
  240. }
  241. if (!dram_map[i].size)
  242. continue;
  243. if (!valid_bank_found)
  244. base = dram_map[i].base;
  245. top = dram_map[i].base + dram_map[i].size;
  246. valid_bank_found = true;
  247. }
  248. if (!valid_bank_found)
  249. return -EINVAL;
  250. /* map all the DRAM regions */
  251. uniphier_mem_map_init(base, top - base);
  252. return 0;
  253. }