[PATCH 1/1] am65x_gp_evm: Support for ECC DDR with DMA priming
Ben Roytburd
BRoytburd at relativityspace.com
Sat May 27 00:39:14 CEST 2023
>From e019ed98623c8c8388bef3082002d27d5ec9de40 Mon Sep 17 00:00:00 2001
From: broytburd <broytburd at relativityspace.com>
Date: Fri, 26 May 2023 09:14:14 -0700
Subject: [PATCH 1/1] am65x_gp_evm: Support for ECC DDR with DMA priming
Add support for configuring DDR4 memory on AM65x_GP_EVM SR1.0 with
ECC. Add register writes and memory priming function for
DDR initialization. Priming done using dma_memcpy from MSMC SRAM, bugfix
required for k3 udma driver to prevent dereferencing a null pointer
within unprimed DDR space.
Signed-off-by: broytburd <broytburd at relativityspace.com>
Cc: Tom Rini <trini at konsulko.com>
---
arch/arm/dts/k3-am654-base-board.dts | 5 +-
drivers/dma/ti/k3-udma.c | 9 +++-
drivers/ram/k3-am654-ddrss.c | 74 +++++++++++++++++++++++++++-
3 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts
index cfbcebfa37..bd54c84359 100644
--- a/arch/arm/dts/k3-am654-base-board.dts
+++ b/arch/arm/dts/k3-am654-base-board.dts
@@ -20,9 +20,8 @@
memory at 80000000 {
device_type = "memory";
- /* 4G RAM */
- reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
- <0x00000008 0x80000000 0x00000000 0x80000000>;
+ /* 2G RAM */
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
};
reserved-memory {
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 05c3a4311c..461162ab6c 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -1044,8 +1044,8 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc)
static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
- int fd_ring = k3_nav_ringacc_get_ring_id(uc->rflow->fd_ring);
- int rx_ring = k3_nav_ringacc_get_ring_id(uc->rflow->r_ring);
+ int fd_ring = 0;
+ int rx_ring = 0;
int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
struct ti_sci_msg_rm_udmap_rx_ch_cfg req = { 0 };
struct ti_sci_msg_rm_udmap_flow_cfg flow_req = { 0 };
@@ -1053,6 +1053,11 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
u32 mode;
int ret;
+ if (!uc->rflow) {
+ fd_ring = k3_nav_ringacc_get_ring_id(uc->rflow->fd_ring);
+ rx_ring = k3_nav_ringacc_get_ring_id(uc->rflow->r_ring);
+ }
+
if (uc->config.pkt_mode)
mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR;
else
diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c
index b8338f84a3..6f28cb856f 100644
--- a/drivers/ram/k3-am654-ddrss.c
+++ b/drivers/ram/k3-am654-ddrss.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <dma.h>
#include <log.h>
#include <ram.h>
#include <asm/io.h>
@@ -24,7 +25,20 @@ u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
#define LDELAY 10000
/* DDRSS PHY configuration register fixed values */
-#define DDRSS_DDRPHY_RANKIDR_RANK0 0
+#define DDRSS_DDRPHY_RANKIDR_RANK0 0x00000000
+#define DDRSS_DDRPHY_RANKIDR_RANK1 0x00010001
+
+/* Amount of DDR we wish to prime */
+#define DATA_BYTES 0x80000000
+
+/* Amount of MSMC memory we will use to prime */
+#define MSMC_BYTES 0x20000000
+
+/* Base address of DDR */
+static u32 *ddr_ptr = (uint32_t *)0x80000000;
+
+/* Base address of MSMC */
+static u32 *msmc_ptr = (uint32_t *)0x60000000;
/**
* struct am654_ddrss_desc - Description of ddrss integration.
@@ -49,6 +63,15 @@ struct am654_ddrss_desc {
struct ddrss_params params;
};
+/**
+ * am654_prime_ecc(struct am654_ddrss_desc *ddrss) - Prime ECC
+ *
+ * Write a specified pattern to our entire DDR so that ECC timing
+ * parameters can be calibrated
+ *
+ */
+static int am654_prime_ecc(struct am654_ddrss_desc *ddrss);
+
static inline u32 ddrss_readl(void __iomem *addr, unsigned int offset)
{
return readl(addr + offset);
@@ -172,6 +195,11 @@ static void am654_ddrss_ctrl_configuration(struct am654_ddrss_desc *ddrss)
ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP10, map->ddrctl_addrmap10);
ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP11, map->ddrctl_addrmap11);
+ ddrss_ctl_writel(DDRSS_DDRCTL_DQMAP0, map->ddrctl_dqmap0);
+ ddrss_ctl_writel(DDRSS_DDRCTL_DQMAP1, map->ddrctl_dqmap1);
+ ddrss_ctl_writel(DDRSS_DDRCTL_DQMAP4, map->ddrctl_dqmap4);
+ ddrss_ctl_writel(DDRSS_DDRCTL_DQMAP5, map->ddrctl_dqmap5);
+
ddrss_ctl_writel(DDRSS_DDRCTL_ODTCFG, reg->ddrctl_odtcfg);
ddrss_ctl_writel(DDRSS_DDRCTL_ODTMAP, reg->ddrctl_odtmap);
@@ -287,12 +315,14 @@ static void am654_ddrss_phy_configuration(struct am654_ddrss_desc *ddrss)
ddrss_phy_writel(DDRSS_DDRPHY_DX1GCR4, cfg->ddrphy_dx1gcr4);
ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR4, cfg->ddrphy_dx2gcr4);
ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR4, cfg->ddrphy_dx3gcr4);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR4, cfg->ddrphy_dx4gcr4);
ddrss_phy_writel(DDRSS_DDRPHY_PGCR5, cfg->ddrphy_pgcr5);
ddrss_phy_writel(DDRSS_DDRPHY_DX0GCR5, cfg->ddrphy_dx0gcr5);
ddrss_phy_writel(DDRSS_DDRPHY_DX1GCR5, cfg->ddrphy_dx1gcr5);
ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR5, cfg->ddrphy_dx2gcr5);
ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR5, cfg->ddrphy_dx3gcr5);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR5, cfg->ddrphy_dx4gcr5);
ddrss_phy_writel(DDRSS_DDRPHY_RANKIDR, DDRSS_DDRPHY_RANKIDR_RANK0);
@@ -300,6 +330,16 @@ static void am654_ddrss_phy_configuration(struct am654_ddrss_desc *ddrss)
ddrss_phy_writel(DDRSS_DDRPHY_DX1GTR0, cfg->ddrphy_dx1gtr0);
ddrss_phy_writel(DDRSS_DDRPHY_DX2GTR0, cfg->ddrphy_dx2gtr0);
ddrss_phy_writel(DDRSS_DDRPHY_DX3GTR0, cfg->ddrphy_dx3gtr0);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX4GTR0, cfg->ddrphy_dx4gtr0);
+ ddrss_phy_writel(DDRSS_DDRPHY_ODTCR, cfg->ddrphy_odtcr);
+
+ ddrss_phy_writel(DDRSS_DDRPHY_RANKIDR, DDRSS_DDRPHY_RANKIDR_RANK1);
+
+ ddrss_phy_writel(DDRSS_DDRPHY_DX0GTR0, cfg->ddrphy_dx0gtr0);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX1GTR0, cfg->ddrphy_dx1gtr0);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX2GTR0, cfg->ddrphy_dx2gtr0);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX3GTR0, cfg->ddrphy_dx3gtr0);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX4GTR0, cfg->ddrphy_dx4gtr0);
ddrss_phy_writel(DDRSS_DDRPHY_ODTCR, cfg->ddrphy_odtcr);
ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0IOCR, cfg->ddrphy_dx8sl0iocr);
@@ -543,13 +583,14 @@ int disable_dqs_pd(struct am654_ddrss_desc *ddrss)
int cleanup_training(struct am654_ddrss_desc *ddrss)
{
u32 val;
- u32 dgsl0, dgsl1, dgsl2, dgsl3, rddly, rd2wr_wr2rd;
+ u32 dgsl0, dgsl1, dgsl2, dgsl3, dgsl4, rddly, rd2wr_wr2rd;
ddrss_phy_writel(DDRSS_DDRPHY_RANKIDR, 0x00000000);
dgsl0 = (ddrss_phy_readl(DDRSS_DDRPHY_DX0GTR0) & 0x1F) >> 2;
dgsl1 = (ddrss_phy_readl(DDRSS_DDRPHY_DX1GTR0) & 0x1F) >> 2;
dgsl2 = (ddrss_phy_readl(DDRSS_DDRPHY_DX2GTR0) & 0x1F) >> 2;
dgsl3 = (ddrss_phy_readl(DDRSS_DDRPHY_DX3GTR0) & 0x1F) >> 2;
+ dgsl4 = (ddrss_phy_readl(DDRSS_DDRPHY_DX4GTR0) & 0x1F) >> 2;
rddly = dgsl0;
if (dgsl1 < rddly)
@@ -558,6 +599,8 @@ int cleanup_training(struct am654_ddrss_desc *ddrss)
rddly = dgsl2;
if (dgsl3 < rddly)
rddly = dgsl3;
+ if (dgsl4 < rddly)
+ rddly = dgsl4;
rddly += 5;
@@ -578,6 +621,10 @@ int cleanup_training(struct am654_ddrss_desc *ddrss)
val |= (rddly << 20);
ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR0, val);
+ val = (ddrss_phy_readl(DDRSS_DDRPHY_DX4GCR0) & ~0xF00000);
+ val |= (rddly << 20);
+ ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR0, val);
+
/*
* Add system latency derived from training back into rd2wr and wr2rd
* rd2wr = RL + BL/2 + 1 + WR_PREAMBLE - WL + max(DXnGTR0.DGSL) / 2
@@ -591,6 +638,7 @@ int cleanup_training(struct am654_ddrss_desc *ddrss)
dgsl1 = (ddrss_phy_readl(DDRSS_DDRPHY_DX1GTR0) & 0x1F);
dgsl2 = (ddrss_phy_readl(DDRSS_DDRPHY_DX2GTR0) & 0x1F);
dgsl3 = (ddrss_phy_readl(DDRSS_DDRPHY_DX3GTR0) & 0x1F);
+ dgsl4 = (ddrss_phy_readl(DDRSS_DDRPHY_DX4GTR0) & 0x1F);
/* Find maximum value across all bytes */
rd2wr_wr2rd = dgsl0;
@@ -600,6 +648,8 @@ int cleanup_training(struct am654_ddrss_desc *ddrss)
rd2wr_wr2rd = dgsl2;
if (dgsl3 > rd2wr_wr2rd)
rd2wr_wr2rd = dgsl3;
+ if (dgsl4 > rd2wr_wr2rd)
+ rd2wr_wr2rd = dgsl4;
rd2wr_wr2rd >>= 1;
@@ -1071,6 +1121,10 @@ static int am654_ddrss_probe(struct udevice *dev)
ret = am654_ddrss_init(ddrss);
+ // Only prime ECC if it is enabled
+ if (ddrss_ctl_readl(DDRSS_DDRCTL_ECCCFG0) & 0x4)
+ ret = am654_prime_ecc(ddrss);
+
return ret;
}
@@ -1096,3 +1150,19 @@ U_BOOT_DRIVER(am654_ddrss) = {
.probe = am654_ddrss_probe,
.priv_auto = sizeof(struct am654_ddrss_desc),
};
+
+static int am654_prime_ecc(struct am654_ddrss_desc *ddrss)
+{
+ int ret;
+
+ // Use MSMC memory to prime DDR memory
+ for (int i = 0; i < (DATA_BYTES / MSMC_BYTES); i++) {
+ ret = dma_memcpy(ddr_ptr + ((MSMC_BYTES / 4) * i), msmc_ptr, MSMC_BYTES);
+ if (ret) {
+ dev_err(ddrss->dev, "DDR prime DMA Memcpy failed %d\n", ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
--
2.25.1
More information about the U-Boot
mailing list