blob: 6b98095d600f95f1da6a59d6e3e9cbffbccb13f7 [file] [log] [blame]
Nicolas Le Bayon620ce332021-03-02 11:19:36 +01001/*
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 ******************************************************************************/
20uint32_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 ******************************************************************************/
43uint32_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 ******************************************************************************/
67uint32_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 ******************************************************************************/
127uint32_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}