marvell_ddr_info.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Copyright (C) 2018 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <platform_def.h>
  8. #include <common/debug.h>
  9. #include <lib/mmio.h>
  10. #include <ddr_info.h>
  11. #define DRAM_CH0_MMAP_LOW_REG(iface, cs, base) \
  12. (base + DRAM_CH0_MMAP_LOW_OFFSET + (iface) * 0x10000 + (cs) * 0x8)
  13. #define DRAM_CH0_MMAP_HIGH_REG(iface, cs, base) \
  14. (DRAM_CH0_MMAP_LOW_REG(iface, cs, base) + 4)
  15. #define DRAM_CS_VALID_ENABLED_MASK 0x1
  16. #define DRAM_AREA_LENGTH_OFFS 16
  17. #define DRAM_AREA_LENGTH_MASK (0x1f << DRAM_AREA_LENGTH_OFFS)
  18. #define DRAM_START_ADDRESS_L_OFFS 23
  19. #define DRAM_START_ADDRESS_L_MASK \
  20. (0x1ff << DRAM_START_ADDRESS_L_OFFS)
  21. #define DRAM_START_ADDR_HTOL_OFFS 32
  22. #define DRAM_MAX_CS_NUM 2
  23. #define DRAM_CS_ENABLED(iface, cs, base) \
  24. (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \
  25. DRAM_CS_VALID_ENABLED_MASK)
  26. #define GET_DRAM_REGION_SIZE_CODE(iface, cs, base) \
  27. (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \
  28. DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS
  29. /* Mapping between DDR area length and real DDR size is specific and looks like
  30. * below:
  31. * 0 => 384 MB
  32. * 1 => 768 MB
  33. * 2 => 1536 MB
  34. * 3 => 3 GB
  35. * 4 => 6 GB
  36. *
  37. * 7 => 8 MB
  38. * 8 => 16 MB
  39. * 9 => 32 MB
  40. * 10 => 64 MB
  41. * 11 => 128 MB
  42. * 12 => 256 MB
  43. * 13 => 512 MB
  44. * 14 => 1 GB
  45. * 15 => 2 GB
  46. * 16 => 4 GB
  47. * 17 => 8 GB
  48. * 18 => 16 GB
  49. * 19 => 32 GB
  50. * 20 => 64 GB
  51. * 21 => 128 GB
  52. * 22 => 256 GB
  53. * 23 => 512 GB
  54. * 24 => 1 TB
  55. * 25 => 2 TB
  56. * 26 => 4 TB
  57. *
  58. * to calculate real size we need to use two different formulas:
  59. * -- GET_DRAM_REGION_SIZE_ODD for values 0-4 (DRAM_REGION_SIZE_ODD)
  60. * -- GET_DRAM_REGION_SIZE_EVEN for values 7-26 (DRAM_REGION_SIZE_EVEN)
  61. * using mentioned formulas we cover whole mapping between "Area length" value
  62. * and real size (see above mapping).
  63. */
  64. #define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26))
  65. #define GET_DRAM_REGION_SIZE_EVEN(C) ((uint64_t)1 << ((C) + 16))
  66. #define DRAM_REGION_SIZE_ODD(C) ((C) <= 4)
  67. #define GET_DRAM_REGION_SIZE_ODD(C) ((uint64_t)0x18000000 << (C))
  68. uint64_t mvebu_get_dram_size(uint64_t ap_base_addr)
  69. {
  70. uint64_t mem_size = 0;
  71. uint8_t region_code;
  72. uint8_t cs, iface;
  73. for (iface = 0; iface < DRAM_MAX_IFACE; iface++) {
  74. for (cs = 0; cs < DRAM_MAX_CS_NUM; cs++) {
  75. /* Exit loop on first disabled DRAM CS */
  76. if (!DRAM_CS_ENABLED(iface, cs, ap_base_addr))
  77. break;
  78. /* Decode area length for current CS
  79. * from register value
  80. */
  81. region_code =
  82. GET_DRAM_REGION_SIZE_CODE(iface, cs,
  83. ap_base_addr);
  84. if (DRAM_REGION_SIZE_EVEN(region_code)) {
  85. mem_size +=
  86. GET_DRAM_REGION_SIZE_EVEN(region_code);
  87. } else if (DRAM_REGION_SIZE_ODD(region_code)) {
  88. mem_size +=
  89. GET_DRAM_REGION_SIZE_ODD(region_code);
  90. } else {
  91. WARN("%s: Invalid mem region (0x%x) CS#%d\n",
  92. __func__, region_code, cs);
  93. return 0;
  94. }
  95. }
  96. }
  97. return mem_size;
  98. }