stm32mp_ddr_test.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (C) 2022-2024, STMicroelectronics - All Rights Reserved
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <common/debug.h>
  7. #include <drivers/st/stm32mp_ddr_test.h>
  8. #include <lib/mmio.h>
  9. #include <platform_def.h>
  10. #ifdef __aarch64__
  11. #define DDR_PATTERN 0xAAAAAAAAAAAAAAAAUL
  12. #define DDR_ANTIPATTERN 0x5555555555555555UL
  13. #else /* !__aarch64__ */
  14. #define DDR_PATTERN 0xAAAAAAAAU
  15. #define DDR_ANTIPATTERN 0x55555555U
  16. #endif /* __aarch64__ */
  17. static void mmio_write_pattern(uintptr_t addr, u_register_t value)
  18. {
  19. #ifdef __aarch64__
  20. mmio_write_64(addr, (uint64_t)value);
  21. #else /* !__aarch64__ */
  22. mmio_write_32(addr, (uint32_t)value);
  23. #endif /* __aarch64__ */
  24. }
  25. static u_register_t mmio_read_pattern(uintptr_t addr)
  26. {
  27. #ifdef __aarch64__
  28. return (u_register_t)mmio_read_64(addr);
  29. #else /* !__aarch64__ */
  30. return (u_register_t)mmio_read_32(addr);
  31. #endif /* __aarch64__ */
  32. }
  33. /*******************************************************************************
  34. * This function tests a simple read/write access to the DDR.
  35. * Note that the previous content is restored after test.
  36. * Returns 0 if success, and address value else.
  37. ******************************************************************************/
  38. uintptr_t stm32mp_ddr_test_rw_access(void)
  39. {
  40. u_register_t saved_value = mmio_read_pattern(STM32MP_DDR_BASE);
  41. mmio_write_pattern(STM32MP_DDR_BASE, DDR_PATTERN);
  42. if (mmio_read_pattern(STM32MP_DDR_BASE) != DDR_PATTERN) {
  43. return STM32MP_DDR_BASE;
  44. }
  45. mmio_write_pattern(STM32MP_DDR_BASE, saved_value);
  46. return 0UL;
  47. }
  48. /*******************************************************************************
  49. * This function tests the DDR data bus wiring.
  50. * This is inspired from the Data Bus Test algorithm written by Michael Barr
  51. * in "Programming Embedded Systems in C and C++" book.
  52. * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
  53. * File: memtest.c - This source code belongs to Public Domain.
  54. * Returns 0 if success, and address value else.
  55. ******************************************************************************/
  56. uintptr_t stm32mp_ddr_test_data_bus(void)
  57. {
  58. u_register_t pattern;
  59. for (pattern = 1U; pattern != 0U; pattern <<= 1U) {
  60. mmio_write_pattern(STM32MP_DDR_BASE, pattern);
  61. if (mmio_read_pattern(STM32MP_DDR_BASE) != pattern) {
  62. return STM32MP_DDR_BASE;
  63. }
  64. }
  65. return 0UL;
  66. }
  67. /*******************************************************************************
  68. * This function tests the DDR address bus wiring.
  69. * This is inspired from the Data Bus Test algorithm written by Michael Barr
  70. * in "Programming Embedded Systems in C and C++" book.
  71. * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
  72. * File: memtest.c - This source code belongs to Public Domain.
  73. * size: size in bytes of the DDR memory device.
  74. * Returns 0 if success, and address value else.
  75. ******************************************************************************/
  76. uintptr_t stm32mp_ddr_test_addr_bus(size_t size)
  77. {
  78. size_t addressmask = size - 1U;
  79. size_t offset;
  80. size_t testoffset = 0U;
  81. /* Write the default pattern at each of the power-of-two offsets. */
  82. for (offset = sizeof(u_register_t); (offset & addressmask) != 0U;
  83. offset <<= 1U) {
  84. mmio_write_pattern(STM32MP_DDR_BASE + offset, DDR_PATTERN);
  85. }
  86. /* Check for address bits stuck high. */
  87. mmio_write_pattern(STM32MP_DDR_BASE + testoffset, DDR_ANTIPATTERN);
  88. for (offset = sizeof(u_register_t); (offset & addressmask) != 0U;
  89. offset <<= 1U) {
  90. if (mmio_read_pattern(STM32MP_DDR_BASE + offset) != DDR_PATTERN) {
  91. return STM32MP_DDR_BASE + offset;
  92. }
  93. }
  94. mmio_write_pattern(STM32MP_DDR_BASE + testoffset, DDR_PATTERN);
  95. /* Check for address bits stuck low or shorted. */
  96. for (testoffset = sizeof(u_register_t); (testoffset & addressmask) != 0U;
  97. testoffset <<= 1U) {
  98. mmio_write_pattern(STM32MP_DDR_BASE + testoffset, DDR_ANTIPATTERN);
  99. if (mmio_read_pattern(STM32MP_DDR_BASE) != DDR_PATTERN) {
  100. return STM32MP_DDR_BASE;
  101. }
  102. for (offset = sizeof(u_register_t); (offset & addressmask) != 0U;
  103. offset <<= 1U) {
  104. if ((mmio_read_pattern(STM32MP_DDR_BASE + offset) != DDR_PATTERN) &&
  105. (offset != testoffset)) {
  106. return STM32MP_DDR_BASE + offset;
  107. }
  108. }
  109. mmio_write_pattern(STM32MP_DDR_BASE + testoffset, DDR_PATTERN);
  110. }
  111. return 0UL;
  112. }
  113. /*******************************************************************************
  114. * This function checks the DDR size. It has to be run with Data Cache off.
  115. * This test is run before data have been put in DDR, and is only done for
  116. * cold boot. The DDR data can then be overwritten, and it is not useful to
  117. * restore its content.
  118. * Returns DDR computed size.
  119. ******************************************************************************/
  120. size_t stm32mp_ddr_check_size(void)
  121. {
  122. size_t offset = sizeof(u_register_t);
  123. mmio_write_pattern(STM32MP_DDR_BASE, DDR_PATTERN);
  124. while (offset < STM32MP_DDR_MAX_SIZE) {
  125. mmio_write_pattern(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN);
  126. dsb();
  127. if (mmio_read_pattern(STM32MP_DDR_BASE) != DDR_PATTERN) {
  128. break;
  129. }
  130. offset <<= 1U;
  131. }
  132. return offset;
  133. }