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