memconf.c 3.0 KB

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