Re: [PATCH v4 05/10] ram: cadence: add driver for Cadence EDAC

2023-04-17 Thread Ralph Siemsen

On Mon, Apr 17, 2023 at 07:32:30PM +0200, Marek Vasut wrote:

On 3/8/23 21:26, Ralph Siemsen wrote:

[...]


+#define FUNCCTRL   0x00
+#define  FUNCCTRL_MASKSDLOFS   (0x18 << 16)
+#define  FUNCCTRL_DVDDQ_1_5V   (1 << 8)
+#define  FUNCCTRL_RESET_N  (1 << 0)
+#define DLLCTRL0x04
+#define  DLLCTRL_ASDLLOCK  (1 << 26)
+#define  DLLCTRL_MFSL_500MHz   (2 << 1)
+#define  DLLCTRL_MDLLSTBY  (1 << 0)


Use BIT() macro where applicable.


Will do.


+   /* DDR PHY setup */
+   phy_writel(DLLCTRL_MFSL_500MHz | DLLCTRL_MDLLSTBY, DLLCTRL);
+   phy_writel(0x0182, ZQCALCTRL);
+   if (ddr_type == RZN1_DDR3_DUAL_BANK)
+   phy_writel(0xAB330031, ZQODTCTRL);
+   else if (ddr_type == RZN1_DDR3_SINGLE_BANK)
+   phy_writel(0xAB320051, ZQODTCTRL);
+   else /* DDR2 */
+   phy_writel(0xAB330071, ZQODTCTRL);
+   phy_writel(0xB545B544, RDCTRL);
+   phy_writel(0x00B0, RDTMG);
+   phy_writel(0x020A0806, OUTCTRL);
+   if (ddr_type == RZN1_DDR3_DUAL_BANK)
+   phy_writel(0x80005556, WLCTRL1);
+   else
+   phy_writel(0x80005C5D, WLCTRL1);
+   phy_writel(0x0101, FIFOINIT);
+   phy_writel(0x4545, DQCALOFS1);


Is there any macro which defines those magic bits in magic numbers ?
If so, please use them.


This init sequence came from the u-boot 2017 repo published by Renesas. 
There do not appear to be any macros to help with all these magic 
numbers.



+   /* DDR Controller is always in ASYNC mode */
+   cdns_ddr_ctrl_init((void *)RZN1_DDR_BASE, 1,
+  ddr_00_87_async, ddr_350_374_async,
+  ddr_start_addr, CFG_SYS_SDRAM_SIZE,
+  priv->enable_ecc, priv->enable_8bit);
+
+   rzn1_ddr3_single_bank((void *)RZN1_DDR_BASE);


Can you obtain the DRAM base from DT ?


I'll check if it is possible.


+   priv->syscon = syscon_regmap_lookup_by_phandle(dev, "syscon");
+   if (IS_ERR(priv->syscon)) {
+   dev_err(dev, "No syscon node found\n");
+   //return PTR_ERR(priv->syscon);


This shouldn't be commented out, right ?


Does indeed look like an oversight. I'll fix it up, thanks for spotting!

Ralph


Re: [PATCH v4 05/10] ram: cadence: add driver for Cadence EDAC

2023-04-17 Thread Marek Vasut

On 3/8/23 21:26, Ralph Siemsen wrote:

[...]


+#define FUNCCTRL   0x00
+#define  FUNCCTRL_MASKSDLOFS   (0x18 << 16)
+#define  FUNCCTRL_DVDDQ_1_5V   (1 << 8)
+#define  FUNCCTRL_RESET_N  (1 << 0)
+#define DLLCTRL0x04
+#define  DLLCTRL_ASDLLOCK  (1 << 26)
+#define  DLLCTRL_MFSL_500MHz   (2 << 1)
+#define  DLLCTRL_MDLLSTBY  (1 << 0)


Use BIT() macro where applicable.


+#define ZQCALCTRL  0x08
+#define  ZQCALCTRL_ZQCALEND(1 << 30)
+#define  ZQCALCTRL_ZQCALRSTB   (1 << 0)
+#define ZQODTCTRL  0x0c
+#define RDCTRL 0x10
+#define RDTMG  0x14
+#define FIFOINIT   0x18
+#define  FIFOINIT_RDPTINITEXE  (1 << 8)
+#define  FIFOINIT_WRPTINITEXE  (1 << 0)
+#define OUTCTRL0x1c
+#define  OUTCTRL_ADCMDOE   (1 << 0)
+#define WLCTRL10x40
+#define  WLCTRL1_WLSTR (1 << 24)
+#define DQCALOFS1  0xe8
+
+/* DDR PHY setup */
+void ddr_phy_init(struct cadence_ddr_info *priv, int ddr_type)
+{
+   u32 val;
+
+   /* Disable DDR Controller clock and FlexWAY connection */
+   clk_disable(&priv->hclk_ddrc);
+   clk_disable(&priv->clk_ddrc);
+
+   clk_rzn1_reset_state(&priv->hclk_ddrc, 0);
+   clk_rzn1_reset_state(&priv->clk_ddrc, 0);
+
+   /* Enable DDR Controller clock and FlexWAY connection */
+   clk_enable(&priv->clk_ddrc);
+   clk_enable(&priv->hclk_ddrc);
+
+   /* DDR PHY Soft reset assert */
+   ddrc_writel(FUNCCTRL_MASKSDLOFS | FUNCCTRL_DVDDQ_1_5V, FUNCCTRL);
+
+   clk_rzn1_reset_state(&priv->hclk_ddrc, 1);
+   clk_rzn1_reset_state(&priv->clk_ddrc, 1);
+
+   /* DDR PHY setup */
+   phy_writel(DLLCTRL_MFSL_500MHz | DLLCTRL_MDLLSTBY, DLLCTRL);
+   phy_writel(0x0182, ZQCALCTRL);
+   if (ddr_type == RZN1_DDR3_DUAL_BANK)
+   phy_writel(0xAB330031, ZQODTCTRL);
+   else if (ddr_type == RZN1_DDR3_SINGLE_BANK)
+   phy_writel(0xAB320051, ZQODTCTRL);
+   else /* DDR2 */
+   phy_writel(0xAB330071, ZQODTCTRL);
+   phy_writel(0xB545B544, RDCTRL);
+   phy_writel(0x00B0, RDTMG);
+   phy_writel(0x020A0806, OUTCTRL);
+   if (ddr_type == RZN1_DDR3_DUAL_BANK)
+   phy_writel(0x80005556, WLCTRL1);
+   else
+   phy_writel(0x80005C5D, WLCTRL1);
+   phy_writel(0x0101, FIFOINIT);
+   phy_writel(0x4545, DQCALOFS1);


Is there any macro which defines those magic bits in magic numbers ?
If so, please use them.


+   /* Step 9 MDLL reset release */
+   val = phy_readl(DLLCTRL);
+   val &= ~DLLCTRL_MDLLSTBY;
+   phy_writel(val, DLLCTRL);
+
+   /* Step 12 Soft reset release */
+   val = phy_readl(FUNCCTRL);
+   val |= FUNCCTRL_RESET_N;
+   phy_writel(val, FUNCCTRL);
+
+   /* Step 13 FIFO pointer initialize */
+   phy_writel(FIFOINIT_RDPTINITEXE | FIFOINIT_WRPTINITEXE, FIFOINIT);
+
+   /* Step 14 Execute ZQ Calibration */
+   val = phy_readl(ZQCALCTRL);
+   val |= ZQCALCTRL_ZQCALRSTB;
+   phy_writel(val, ZQCALCTRL);
+
+   /* Step 15 Wait for 200us or more, or wait for DFIINITCOMPLETE to be 
"1" */
+   while (!(phy_readl(DLLCTRL) & DLLCTRL_ASDLLOCK))
+   ;
+   while (!(phy_readl(ZQCALCTRL) & ZQCALCTRL_ZQCALEND))
+   ;
+
+   /* Step 16 Enable Address and Command output */
+   val = phy_readl(OUTCTRL);
+   val |= OUTCTRL_ADCMDOE;
+   phy_writel(val, OUTCTRL);
+
+   /* Step 17 Wait for 200us or more(from MRESETB=0) */
+   udelay(200);
+}


[...]


+int rzn1_dram_init(struct cadence_ddr_info *priv)
+{
+   u32 version;
+   u32 ddr_start_addr = 0;
+
+   ddr_phy_init(priv, RZN1_DDR3_SINGLE_BANK);
+
+   /*
+* Override DDR PHY Interface (DFI) related settings
+* DFI is the internal interface between the DDR controller and the DDR 
PHY.
+* These settings are specific to the board and can't be known by the 
settings
+* provided for each DDR model within the generated include.
+*/
+   ddr_350_374_async[351 - 350] = 0x001e;
+   ddr_350_374_async[352 - 350] = 0x1e68;
+   ddr_350_374_async[353 - 350] = 0x0220;
+   ddr_350_374_async[354 - 350] = 0x02000200;
+   ddr_350_374_async[355 - 350] = 0x0c30;
+   ddr_350_374_async[356 - 350] = 0x9808;
+   ddr_350_374_async[357 - 350] = 0x020a0706;
+   ddr_350_374_async[372 - 350] = 0x0100;
+
+   /*
+* On ES1.0 devices, the DDR start address that the DDR Controller sees
+* is the physical address of the DDR. However, later devices changed it
+* to be 0 in order to fix an issue with DDR out-of-range detection.
+*/
+#define RZN1_SYSCTRL_REG_VERSION 412
+   regmap_read(priv->syscon, RZN1_SYSCTRL_REG_VERSION, &version);
+   if (version == 0x10)
+   ddr_start_addr = RZN1_V_DDR_BASE;
+
+   /* DDR Controller is always in ASYNC mode */
+   cdns_ddr_ctrl_init((void *)RZN1_DDR_B

[PATCH v4 05/10] ram: cadence: add driver for Cadence EDAC

2023-03-08 Thread Ralph Siemsen
Driver for Cadence EDAC DDR controller, as found in the Renesas RZ/N1.

Signed-off-by: Ralph Siemsen 
---

(no changes since v3)

Changes in v3:
- assorted small cleanups
- support version 1.0 silicon (previously #if 0...)

 drivers/ram/Kconfig |   1 +
 drivers/ram/Makefile|   2 +
 drivers/ram/cadence/Kconfig |  12 +
 drivers/ram/cadence/Makefile|   1 +
 drivers/ram/cadence/ddr_async.c | 311 
 drivers/ram/cadence/ddr_ctrl.c  | 414 
 drivers/ram/cadence/ddr_ctrl.h  | 175 ++
 7 files changed, 916 insertions(+)
 create mode 100644 drivers/ram/cadence/Kconfig
 create mode 100644 drivers/ram/cadence/Makefile
 create mode 100644 drivers/ram/cadence/ddr_async.c
 create mode 100644 drivers/ram/cadence/ddr_ctrl.c
 create mode 100644 drivers/ram/cadence/ddr_ctrl.h

diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index e085119963..2b6d8f1c7b 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -108,6 +108,7 @@ config IMXRT_SDRAM
  This driver is for the sdram memory interface with the SEMC.
 
 source "drivers/ram/aspeed/Kconfig"
+source "drivers/ram/cadence/Kconfig"
 source "drivers/ram/rockchip/Kconfig"
 source "drivers/ram/sifive/Kconfig"
 source "drivers/ram/stm32mp1/Kconfig"
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 83948e2c43..e2d5e730d1 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -22,3 +22,5 @@ obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o
 obj-$(CONFIG_RAM_SIFIVE) += sifive/
 
 obj-$(CONFIG_ARCH_OCTEON) += octeon/
+
+obj-$(CONFIG_CADENCE_DDR_CTRL) += cadence/
diff --git a/drivers/ram/cadence/Kconfig b/drivers/ram/cadence/Kconfig
new file mode 100644
index 00..2d5469cb8e
--- /dev/null
+++ b/drivers/ram/cadence/Kconfig
@@ -0,0 +1,12 @@
+if RAM || SPL_RAM
+
+config CADENCE_DDR_CTRL
+   bool "Enable Cadence DDR controller"
+   depends on DM
+   help
+ Enable support for Cadence DDR controller, as found on
+ the Renesas RZ/N1 SoC. This controller has a large number
+ of registers which need to be programmed, mostly using values
+ obtained from Denali SOMA files via a TCL script.
+
+endif
diff --git a/drivers/ram/cadence/Makefile b/drivers/ram/cadence/Makefile
new file mode 100644
index 00..16c7fe8488
--- /dev/null
+++ b/drivers/ram/cadence/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CADENCE_DDR_CTRL) += ddr_async.o ddr_ctrl.o
diff --git a/drivers/ram/cadence/ddr_async.c b/drivers/ram/cadence/ddr_async.c
new file mode 100644
index 00..444eeb8ac7
--- /dev/null
+++ b/drivers/ram/cadence/ddr_async.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * RZ/N1 DDR Controller initialisation
+ *
+ * The DDR Controller register values for a specific DDR device, mode and
+ * frequency are generated using a Cadence tool.
+ *
+ * Copyright (C) 2015 Renesas Electronics Europe Ltd
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "ddr_ctrl.h"
+
+void clk_rzn1_reset_state(struct clk *clk, int on);
+
+extern u32 ddr_00_87_async[];
+extern u32 ddr_350_374_async[];
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct cadence_ddr_info {
+   struct udevice *dev;
+   void __iomem *ddrc;
+   void __iomem *phy;
+   struct clk clk_ddrc;
+   struct clk hclk_ddrc;
+   struct regmap *syscon;
+   bool enable_ecc;
+   bool enable_8bit;
+};
+
+static inline u32 cadence_readl(void __iomem *addr, unsigned int offset)
+{
+   return readl(addr + offset);
+}
+
+static inline void cadence_writel(void __iomem *addr, unsigned int offset,
+ u32 data)
+{
+   debug("%s: addr = 0x%p, value = 0x%08x\n", __func__, addr + offset, 
data);
+   writel(data, addr + offset);
+}
+
+#define ddrc_readl(off)cadence_readl(priv->ddrc, off)
+#define ddrc_writel(val, off)  cadence_writel(priv->ddrc, off, val)
+
+#define phy_readl(off) cadence_readl(priv->phy, off)
+#define phy_writel(val, off)   cadence_writel(priv->phy, off, val)
+
+#define RZN1_DDR3_SINGLE_BANK 3
+#define RZN1_DDR3_DUAL_BANK 32
+
+#define FUNCCTRL   0x00
+#define  FUNCCTRL_MASKSDLOFS   (0x18 << 16)
+#define  FUNCCTRL_DVDDQ_1_5V   (1 << 8)
+#define  FUNCCTRL_RESET_N  (1 << 0)
+#define DLLCTRL0x04
+#define  DLLCTRL_ASDLLOCK  (1 << 26)
+#define  DLLCTRL_MFSL_500MHz   (2 << 1)
+#define  DLLCTRL_MDLLSTBY  (1 << 0)
+#define ZQCALCTRL  0x08
+#define  ZQCALCTRL_ZQCALEND(1 << 30)
+#define  ZQCALCTRL_ZQCALRSTB   (1 << 0)
+#define ZQODTCTRL  0x0c
+#define RDCTRL 0x10
+#define RDTMG  0x14
+#define FIFOINIT   0x18
+#define  FIFOINIT_RDPTINITEXE  (1 << 8)
+#define  FIFOINIT_WRPTINITEXE  (1 << 0)
+#define OUTCTRL0x1c
+#define  OUTCTRL_ADCMDOE   (1 << 0)
+#define WLCTRL10x40
+#define  WLCTRL1_WLSTR (1 << 24)
+#define DQCALOFS1  0x