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