summaryrefslogtreecommitdiff
path: root/drivers/st/ddr
diff options
context:
space:
mode:
authorNicolas Le Bayon <nicolas.le.bayon@foss.st.com>2021-03-02 11:19:36 +0100
committerYann Gautier <yann.gautier@st.com>2022-01-05 11:47:46 +0100
commit63d215984691e8b2de46e7b725ca2abf7f8ae304 (patch)
treed9408971155a6f0b1136056dd977bf32b248efac /drivers/st/ddr
parent06e55dc8424277f7d6325949c4cd6ebe7fabb173 (diff)
downloadarm-trusted-firmware-63d215984691e8b2de46e7b725ca2abf7f8ae304.tar.gz
refactor(st-ddr): move basic tests in a dedicated file
These basic tests are generic and should be used independently of the driver, depending on the plaftorm characteristics. Change-Id: I38161b659ef2a23fd30a56e1c9b1bd98461a2fe4 Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@foss.st.com>
Diffstat (limited to 'drivers/st/ddr')
-rw-r--r--drivers/st/ddr/stm32mp1_ram.c123
-rw-r--r--drivers/st/ddr/stm32mp_ddr_test.c147
2 files changed, 151 insertions, 119 deletions
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index 78a89f373..b510c8fa2 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -14,15 +14,13 @@
#include <drivers/st/stm32mp1_ddr_helpers.h>
#include <drivers/st/stm32mp1_ram.h>
#include <drivers/st/stm32mp_ddr.h>
+#include <drivers/st/stm32mp_ddr_test.h>
#include <drivers/st/stm32mp_ram.h>
#include <lib/mmio.h>
#include <libfdt.h>
#include <platform_def.h>
-#define DDR_PATTERN 0xAAAAAAAAU
-#define DDR_ANTIPATTERN 0x55555555U
-
static struct stm32mp_ddr_priv ddr_priv_data;
int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed)
@@ -52,119 +50,6 @@ int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed)
return 0;
}
-/*******************************************************************************
- * This function tests the DDR data bus wiring.
- * This is inspired from the Data Bus Test algorithm written by Michael Barr
- * in "Programming Embedded Systems in C and C++" book.
- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
- * File: memtest.c - This source code belongs to Public Domain.
- * Returns 0 if success, and address value else.
- ******************************************************************************/
-static uint32_t ddr_test_data_bus(void)
-{
- uint32_t pattern;
-
- for (pattern = 1U; pattern != 0U; pattern <<= 1) {
- mmio_write_32(STM32MP_DDR_BASE, pattern);
-
- if (mmio_read_32(STM32MP_DDR_BASE) != pattern) {
- return (uint32_t)STM32MP_DDR_BASE;
- }
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function tests the DDR address bus wiring.
- * This is inspired from the Data Bus Test algorithm written by Michael Barr
- * in "Programming Embedded Systems in C and C++" book.
- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
- * File: memtest.c - This source code belongs to Public Domain.
- * Returns 0 if success, and address value else.
- ******************************************************************************/
-static uint32_t ddr_test_addr_bus(void)
-{
- uint64_t addressmask = (ddr_priv_data.info.size - 1U);
- uint64_t offset;
- uint64_t testoffset = 0;
-
- /* Write the default pattern at each of the power-of-two offsets. */
- for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
- offset <<= 1) {
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset,
- DDR_PATTERN);
- }
-
- /* Check for address bits stuck high. */
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
- DDR_ANTIPATTERN);
-
- for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
- offset <<= 1) {
- if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) !=
- DDR_PATTERN) {
- return (uint32_t)(STM32MP_DDR_BASE + offset);
- }
- }
-
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
-
- /* Check for address bits stuck low or shorted. */
- for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U;
- testoffset <<= 1) {
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
- DDR_ANTIPATTERN);
-
- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
- return STM32MP_DDR_BASE;
- }
-
- for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
- offset <<= 1) {
- if ((mmio_read_32(STM32MP_DDR_BASE +
- (uint32_t)offset) != DDR_PATTERN) &&
- (offset != testoffset)) {
- return (uint32_t)(STM32MP_DDR_BASE + offset);
- }
- }
-
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
- DDR_PATTERN);
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function checks the DDR size. It has to be run with Data Cache off.
- * This test is run before data have been put in DDR, and is only done for
- * cold boot. The DDR data can then be overwritten, and it is not useful to
- * restore its content.
- * Returns DDR computed size.
- ******************************************************************************/
-static uint32_t ddr_check_size(void)
-{
- uint32_t offset = sizeof(uint32_t);
-
- mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
-
- while (offset < STM32MP_DDR_MAX_SIZE) {
- mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN);
- dsb();
-
- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
- break;
- }
-
- offset <<= 1;
- }
-
- INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U));
-
- return offset;
-}
-
static int stm32mp1_ddr_setup(void)
{
struct stm32mp_ddr_priv *priv = &ddr_priv_data;
@@ -220,21 +105,21 @@ static int stm32mp1_ddr_setup(void)
panic();
}
- uret = ddr_test_data_bus();
+ uret = stm32mp_ddr_test_data_bus();
if (uret != 0U) {
ERROR("DDR data bus test: can't access memory @ 0x%x\n",
uret);
panic();
}
- uret = ddr_test_addr_bus();
+ uret = stm32mp_ddr_test_addr_bus(config.info.size);
if (uret != 0U) {
ERROR("DDR addr bus test: can't access memory @ 0x%x\n",
uret);
panic();
}
- uret = ddr_check_size();
+ uret = stm32mp_ddr_check_size();
if (uret < config.info.size) {
ERROR("DDR size: 0x%x does not match DT config: 0x%x\n",
uret, config.info.size);
diff --git a/drivers/st/ddr/stm32mp_ddr_test.c b/drivers/st/ddr/stm32mp_ddr_test.c
new file mode 100644
index 000000000..6b98095d6
--- /dev/null
+++ b/drivers/st/ddr/stm32mp_ddr_test.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/st/stm32mp_ddr_test.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define DDR_PATTERN 0xAAAAAAAAU
+#define DDR_ANTIPATTERN 0x55555555U
+
+/*******************************************************************************
+ * This function tests a simple read/write access to the DDR.
+ * Note that the previous content is restored after test.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_test_rw_access(void)
+{
+ uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE);
+
+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ return (uint32_t)STM32MP_DDR_BASE;
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE, saved_value);
+
+ return 0U;
+}
+
+/*******************************************************************************
+ * This function tests the DDR data bus wiring.
+ * This is inspired from the Data Bus Test algorithm written by Michael Barr
+ * in "Programming Embedded Systems in C and C++" book.
+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
+ * File: memtest.c - This source code belongs to Public Domain.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_test_data_bus(void)
+{
+ uint32_t pattern;
+
+ for (pattern = 1U; pattern != 0U; pattern <<= 1U) {
+ mmio_write_32(STM32MP_DDR_BASE, pattern);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != pattern) {
+ return (uint32_t)STM32MP_DDR_BASE;
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function tests the DDR address bus wiring.
+ * This is inspired from the Data Bus Test algorithm written by Michael Barr
+ * in "Programming Embedded Systems in C and C++" book.
+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
+ * File: memtest.c - This source code belongs to Public Domain.
+ * size: size in bytes of the DDR memory device.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_test_addr_bus(uint64_t size)
+{
+ uint64_t addressmask = size - 1U;
+ uint64_t offset;
+ uint64_t testoffset = 0U;
+
+ /* Write the default pattern at each of the power-of-two offsets. */
+ for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+ offset <<= 1U) {
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset,
+ DDR_PATTERN);
+ }
+
+ /* Check for address bits stuck high. */
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
+ DDR_ANTIPATTERN);
+
+ for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+ offset <<= 1U) {
+ if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) !=
+ DDR_PATTERN) {
+ return (uint32_t)(STM32MP_DDR_BASE + offset);
+ }
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
+
+ /* Check for address bits stuck low or shorted. */
+ for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U;
+ testoffset <<= 1U) {
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
+ DDR_ANTIPATTERN);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ return STM32MP_DDR_BASE;
+ }
+
+ for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+ offset <<= 1) {
+ if ((mmio_read_32(STM32MP_DDR_BASE +
+ (uint32_t)offset) != DDR_PATTERN) &&
+ (offset != testoffset)) {
+ return (uint32_t)(STM32MP_DDR_BASE + offset);
+ }
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
+ DDR_PATTERN);
+ }
+
+ return 0U;
+}
+
+/*******************************************************************************
+ * This function checks the DDR size. It has to be run with Data Cache off.
+ * This test is run before data have been put in DDR, and is only done for
+ * cold boot. The DDR data can then be overwritten, and it is not useful to
+ * restore its content.
+ * Returns DDR computed size.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_check_size(void)
+{
+ uint32_t offset = sizeof(uint32_t);
+
+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
+
+ while (offset < STM32MP_DDR_MAX_SIZE) {
+ mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN);
+ dsb();
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ break;
+ }
+
+ offset <<= 1U;
+ }
+
+ INFO("Memory size = 0x%x (%u MB)\n", offset, offset / (1024U * 1024U));
+
+ return offset;
+}