memconf.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2011-2015 Panasonic Corporation
  4. * Copyright (C) 2016 Socionext Inc.
  5. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  6. */
  7. #include <common.h>
  8. #include <linux/errno.h>
  9. #include <linux/io.h>
  10. #include <linux/sizes.h>
  11. #include "sg-regs.h"
  12. #include "init.h"
  13. static int __uniphier_memconf_init(const struct uniphier_board_data *bd,
  14. int have_ch2)
  15. {
  16. u32 val = 0;
  17. unsigned long size_per_word;
  18. /* set up ch0 */
  19. switch (bd->dram_ch[0].width) {
  20. case 16:
  21. val |= SG_MEMCONF_CH0_NUM_1;
  22. size_per_word = bd->dram_ch[0].size;
  23. break;
  24. case 32:
  25. val |= SG_MEMCONF_CH0_NUM_2;
  26. size_per_word = bd->dram_ch[0].size >> 1;
  27. break;
  28. default:
  29. pr_err("error: unsupported DRAM ch0 width\n");
  30. return -EINVAL;
  31. }
  32. switch (size_per_word) {
  33. case SZ_64M:
  34. val |= SG_MEMCONF_CH0_SZ_64M;
  35. break;
  36. case SZ_128M:
  37. val |= SG_MEMCONF_CH0_SZ_128M;
  38. break;
  39. case SZ_256M:
  40. val |= SG_MEMCONF_CH0_SZ_256M;
  41. break;
  42. case SZ_512M:
  43. val |= SG_MEMCONF_CH0_SZ_512M;
  44. break;
  45. case SZ_1G:
  46. val |= SG_MEMCONF_CH0_SZ_1G;
  47. break;
  48. default:
  49. pr_err("error: unsupported DRAM ch0 size\n");
  50. return -EINVAL;
  51. }
  52. /* set up ch1 */
  53. switch (bd->dram_ch[1].width) {
  54. case 16:
  55. val |= SG_MEMCONF_CH1_NUM_1;
  56. size_per_word = bd->dram_ch[1].size;
  57. break;
  58. case 32:
  59. val |= SG_MEMCONF_CH1_NUM_2;
  60. size_per_word = bd->dram_ch[1].size >> 1;
  61. break;
  62. default:
  63. pr_err("error: unsupported DRAM ch1 width\n");
  64. return -EINVAL;
  65. }
  66. switch (size_per_word) {
  67. case SZ_64M:
  68. val |= SG_MEMCONF_CH1_SZ_64M;
  69. break;
  70. case SZ_128M:
  71. val |= SG_MEMCONF_CH1_SZ_128M;
  72. break;
  73. case SZ_256M:
  74. val |= SG_MEMCONF_CH1_SZ_256M;
  75. break;
  76. case SZ_512M:
  77. val |= SG_MEMCONF_CH1_SZ_512M;
  78. break;
  79. case SZ_1G:
  80. val |= SG_MEMCONF_CH1_SZ_1G;
  81. break;
  82. default:
  83. pr_err("error: unsupported DRAM ch1 size\n");
  84. return -EINVAL;
  85. }
  86. /* is sparse mem? */
  87. if (bd->flags & UNIPHIER_BD_DRAM_SPARSE)
  88. val |= SG_MEMCONF_SPARSEMEM;
  89. if (!have_ch2)
  90. goto out;
  91. if (!bd->dram_ch[2].size) {
  92. val |= SG_MEMCONF_CH2_DISABLE;
  93. goto out;
  94. }
  95. /* set up ch2 */
  96. switch (bd->dram_ch[2].width) {
  97. case 16:
  98. val |= SG_MEMCONF_CH2_NUM_1;
  99. size_per_word = bd->dram_ch[2].size;
  100. break;
  101. case 32:
  102. val |= SG_MEMCONF_CH2_NUM_2;
  103. size_per_word = bd->dram_ch[2].size >> 1;
  104. break;
  105. default:
  106. pr_err("error: unsupported DRAM ch2 width\n");
  107. return -EINVAL;
  108. }
  109. switch (size_per_word) {
  110. case SZ_64M:
  111. val |= SG_MEMCONF_CH2_SZ_64M;
  112. break;
  113. case SZ_128M:
  114. val |= SG_MEMCONF_CH2_SZ_128M;
  115. break;
  116. case SZ_256M:
  117. val |= SG_MEMCONF_CH2_SZ_256M;
  118. break;
  119. case SZ_512M:
  120. val |= SG_MEMCONF_CH2_SZ_512M;
  121. break;
  122. case SZ_1G:
  123. val |= SG_MEMCONF_CH2_SZ_1G;
  124. break;
  125. default:
  126. pr_err("error: unsupported DRAM ch2 size\n");
  127. return -EINVAL;
  128. }
  129. out:
  130. writel(val, SG_MEMCONF);
  131. return 0;
  132. }
  133. int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd)
  134. {
  135. return __uniphier_memconf_init(bd, 0);
  136. }
  137. int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd)
  138. {
  139. return __uniphier_memconf_init(bd, 1);
  140. }